java/com/facebook/soloader/ApplicationSoSource.java (92 lines of code) (raw):

/* * 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 android.content.Context; import android.content.pm.PackageManager; import android.os.StrictMode; import android.util.Log; import java.io.File; import java.io.IOException; import java.util.Collection; import javax.annotation.Nullable; /** {@link SoSource} that wraps a DirectorySoSource for the application's nativeLibraryDir. */ public class ApplicationSoSource extends SoSource { private Context applicationContext; private int flags; private DirectorySoSource soSource; public ApplicationSoSource(Context context, int flags) { applicationContext = context.getApplicationContext(); if (applicationContext == null) { Log.w( SoLoader.TAG, "context.getApplicationContext returned null, holding reference to original context." + "ApplicationSoSource fallbacks to: " + context.getApplicationInfo().nativeLibraryDir); applicationContext = context; } this.flags = flags; soSource = new DirectorySoSource( new File(applicationContext.getApplicationInfo().nativeLibraryDir), flags); } /** * check to make sure there haven't been any changes to the nativeLibraryDir since the last check, * if there have been changes, update the context and soSource * * @return true if the nativeLibraryDir was updated */ public boolean checkAndMaybeUpdate() throws IOException { File nativeLibDir = soSource.soDirectory; Context updatedContext = getUpdatedContext(); File updatedNativeLibDir = getNativeLibDirFromContext(updatedContext); if (!nativeLibDir.equals(updatedNativeLibDir)) { Log.d( SoLoader.TAG, "Native library directory updated from " + nativeLibDir + " to " + updatedNativeLibDir); // update flags to resolve dependencies since the system does not properly resolve // dependencies when the location has moved flags |= DirectorySoSource.RESOLVE_DEPENDENCIES; soSource = new DirectorySoSource(updatedNativeLibDir, flags); soSource.prepare(flags); applicationContext = updatedContext; return true; } return false; } public Context getUpdatedContext() { try { return applicationContext.createPackageContext(applicationContext.getPackageName(), 0); } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException(e); } } public static File getNativeLibDirFromContext(Context context) { return new File(context.getApplicationInfo().nativeLibraryDir); } @Override public int loadLibrary(String soName, int loadFlags, StrictMode.ThreadPolicy threadPolicy) throws IOException { return soSource.loadLibrary(soName, loadFlags, threadPolicy); } @Override @Nullable public File getSoFileByName(String soName) throws IOException { return soSource.getSoFileByName(soName); } @Override @Nullable public String getLibraryPath(String soName) throws IOException { return soSource.getLibraryPath(soName); } @Nullable @Override public String[] getLibraryDependencies(String soName) throws IOException { return soSource.getLibraryDependencies(soName); } @Nullable @Override public File unpackLibrary(String soName) throws IOException { return soSource.unpackLibrary(soName); } @Override protected void prepare(int flags) throws IOException { soSource.prepare(flags); } @Override public void addToLdLibraryPath(Collection<String> paths) { soSource.addToLdLibraryPath(paths); } @Override public String toString() { return soSource.toString(); } }