java/com/facebook/soloader/NativeLibrary.java (57 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.util.Log; import java.util.List; import javax.annotation.Nullable; /** * This is the base class for all the classes representing certain native library. For loading * native libraries we should always inherit from this class and provide relevant information * (libraries to load, code to test native call, dependencies?). * * <p>This instances should be singletons provided by DI. * * <p>This is a basic template but could be improved if we find the need. */ public abstract class NativeLibrary { private static final String TAG = NativeLibrary.class.getName(); private final Object mLock; private @Nullable List<String> mLibraryNames; private Boolean mLoadLibraries; private boolean mLibrariesLoaded; private volatile @Nullable UnsatisfiedLinkError mLinkError; protected NativeLibrary(List<String> libraryNames) { mLock = new Object(); mLoadLibraries = true; mLibrariesLoaded = false; mLinkError = null; mLibraryNames = libraryNames; } /** * safe loading of native libs * * @return true if native libs loaded properly, false otherwise */ @Nullable public boolean loadLibraries() { synchronized (mLock) { if (mLoadLibraries == false) { return mLibrariesLoaded; } try { if (mLibraryNames != null) { for (String name : mLibraryNames) { SoLoader.loadLibrary(name); } } initialNativeCheck(); mLibrariesLoaded = true; mLibraryNames = null; } catch (UnsatisfiedLinkError error) { Log.e(TAG, "Failed to load native lib (initial check): ", error); mLinkError = error; mLibrariesLoaded = false; } catch (Throwable other) { Log.e(TAG, "Failed to load native lib (other error): ", other); mLinkError = new UnsatisfiedLinkError("Failed loading libraries"); mLinkError.initCause(other); mLibrariesLoaded = false; } mLoadLibraries = false; return mLibrariesLoaded; } } /** * loads libraries (if not loaded yet), throws on failure * * @throws UnsatisfiedLinkError */ public void ensureLoaded() throws UnsatisfiedLinkError { if (!loadLibraries()) { throw mLinkError; } } /** * Override this method to make some concrete (quick and harmless) native call. This avoids * lazy-loading some phones (LG) use when we call loadLibrary. If there's a problem we'll face an * UnsupportedLinkError when first using the feature instead of here. This check force a check * right when intended. This way clients of this library can know if it's loaded for sure or not. * * @throws UnsatisfiedLinkError if there was an error loading native library */ protected void initialNativeCheck() throws UnsatisfiedLinkError {} public @Nullable UnsatisfiedLinkError getError() { return mLinkError; } }