Skip to content

Commit

Permalink
Allow OSS libraries to provide an ExternalSoMapping during init. (#127)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #127

As of now, MergedSoMapping was stabbed to a static empty class, so it was not
possible for libraries or apps in OSS to provide an implementation for it.

I'm extending the SoLoader API to offer a `init` method which accepts a
new interface called `ExternalSoMapping` which is not static, and libraries can
implement.

Reviewed By: adicatana

Differential Revision: D60110088

fbshipit-source-id: 9e47328dc59f27177ab3a221bcbb497bcf2d642b
  • Loading branch information
cortinico authored and facebook-github-bot committed Aug 16, 2024
1 parent 3c73566 commit 88a8779
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 5 deletions.
32 changes: 32 additions & 0 deletions java/com/facebook/soloader/ExternalSoMapping.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.facebook.soloader;

import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;

/**
* Similar to {@link MergedSoMapping}, but this interface allows extrenal libraries and map to
* provide their own mapping from Open Source.
*/
@ThreadSafe
interface ExternalSoMapping {
@Nullable
String mapLibName(String preMergedLibName);

void invokeJniOnload(String preMergedLibName);
}
55 changes: 50 additions & 5 deletions java/com/facebook/soloader/SoLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,12 @@ interface AppType {

private static int sAppType = AppType.UNSET;

/**
* If provided during the init method, external libraries can provide their own implementation
* ExternalSoMapping. This is useful for apps that want to use SoMerging in OSS.
*/
@Nullable private static ExternalSoMapping externalSoMapping = null;

static {
boolean shouldSystrace = false;
try {
Expand Down Expand Up @@ -313,6 +319,31 @@ public static void init(Context context, boolean nativeExopackage) {
}
}

/**
* Initializes native code loading for this app; this class's other static facilities cannot be
* used until this {@link #init} is called. This method is idempotent: calls after the first are
* ignored.
*
* <p>This is used only by apps that use SoMerging in OSS, such as React Native apps.
*
* @param context application context
* @param flags Zero or more of the SOLOADER_* flags
* @param soFileLoader the custom {@link SoFileLoader}, you can implement your own loader
* @param externalSoMapping the custom {@link ExternalSoMapping} if the App is using SoMerging.
* @throws IOException IOException
*/
public static void init(
Context context,
int flags,
@Nullable SoFileLoader soFileLoader,
@Nullable ExternalSoMapping externalSoMapping)
throws IOException {
synchronized (SoLoader.class) {
SoLoader.externalSoMapping = externalSoMapping;
}
init(context, flags, soFileLoader);
}

/**
* Determine whether to enable soloader.
*
Expand Down Expand Up @@ -745,7 +776,12 @@ public static SoSource[] cloneSoSources() {
* @return the File object of the so file
*/
public static @Nullable File getSoFile(String shortName) {
String mergedLibName = MergedSoMapping.mapLibName(shortName);
String mergedLibName;
if (externalSoMapping != null) {
mergedLibName = externalSoMapping.mapLibName(shortName);
} else {
mergedLibName = MergedSoMapping.mapLibName(shortName);
}
String soName = mergedLibName != null ? mergedLibName : shortName;
String mappedName = System.mapLibraryName(soName);

Expand Down Expand Up @@ -808,7 +844,12 @@ public static boolean loadLibrary(String shortName, int loadFlags) throws Unsati
@SuppressLint({"CatchGeneralException", "EmptyCatchBlock"})
private static boolean loadLibraryOnAndroid(String shortName, int loadFlags) {
@Nullable Throwable failure = null;
String mergedLibName = MergedSoMapping.mapLibName(shortName);
String mergedLibName;
if (externalSoMapping != null) {
mergedLibName = externalSoMapping.mapLibName(shortName);
} else {
mergedLibName = MergedSoMapping.mapLibName(shortName);
}
String soName = mergedLibName != null ? mergedLibName : shortName;
ObserverHolder.onLoadLibraryStart(shortName, mergedLibName, loadFlags);
boolean wasLoaded = false;
Expand Down Expand Up @@ -1057,7 +1098,7 @@ private static boolean loadLibraryBySoNameImpl(
boolean wasAlreadyJniInvoked =
!TextUtils.isEmpty(shortName) && sLoadedAndJniInvoked.contains(shortName);
if (!wasAlreadyJniInvoked) {
if (SYSTRACE_LIBRARY_LOADING) {
if (SYSTRACE_LIBRARY_LOADING && externalSoMapping == null) {
Api18TraceUtils.beginTraceSection("MergedSoMapping.invokeJniOnload[", shortName, "]");
}
try {
Expand All @@ -1067,7 +1108,11 @@ private static boolean loadLibraryBySoNameImpl(
+ shortName
+ ", which was merged into "
+ soName);
MergedSoMapping.invokeJniOnload(shortName);
if (externalSoMapping != null) {
externalSoMapping.invokeJniOnload(shortName);
} else {
MergedSoMapping.invokeJniOnload(shortName);
}
sLoadedAndJniInvoked.add(shortName);
} catch (UnsatisfiedLinkError e) {
// If you are seeing this exception, first make sure your library sets
Expand Down Expand Up @@ -1095,7 +1140,7 @@ private static boolean loadLibraryBySoNameImpl(
+ "'. See comment for details.",
e);
} finally {
if (SYSTRACE_LIBRARY_LOADING) {
if (SYSTRACE_LIBRARY_LOADING && externalSoMapping == null) {
Api18TraceUtils.endSection();
}
}
Expand Down

0 comments on commit 88a8779

Please sign in to comment.