Loading config/hiddenapi-light-greylist.txt +0 −16 Original line number Diff line number Diff line Loading @@ -220,28 +220,13 @@ Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;IZ)Landroid/conte Landroid/content/pm/UserInfo;->id:I Landroid/content/pm/UserInfo;->isPrimary()Z Landroid/content/res/AssetManager;->addAssetPath(Ljava/lang/String;)I Landroid/content/res/AssetManager;->addAssetPaths([Ljava/lang/String;)[I Landroid/content/res/AssetManager;->applyStyle(JIIJ[IIJJ)V Landroid/content/res/AssetManager;->getArraySize(I)I Landroid/content/res/AssetManager;->getAssignedPackageIdentifiers()Landroid/util/SparseArray; Landroid/content/res/AssetManager;->getCookieName(I)Ljava/lang/String; Landroid/content/res/AssetManager;->getResourceBagText(II)Ljava/lang/CharSequence; Landroid/content/res/AssetManager;->loadResourceBagValue(IILandroid/util/TypedValue;Z)I Landroid/content/res/AssetManager;->loadResourceValue(ISLandroid/util/TypedValue;Z)I Landroid/content/res/AssetManager;->loadThemeAttributeValue(JILandroid/util/TypedValue;Z)I Landroid/content/res/AssetManager;->mObject:J Landroid/content/res/AssetManager;->openNonAssetFdNative(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor; Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;I)Ljava/io/InputStream; Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;)Ljava/io/InputStream; Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;I)Ljava/io/InputStream; Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;)Ljava/io/InputStream; Landroid/content/res/AssetManager;->openNonAssetNative(ILjava/lang/String;I)J Landroid/content/res/AssetManager;->openXmlAssetNative(ILjava/lang/String;)J Landroid/content/res/AssetManager;->resolveAttrs(JII[I[I[I[I)Z Landroid/content/res/AssetManager;->retrieveArray(I[I)I Landroid/content/res/AssetManager;->retrieveAttributes(J[I[I[I)Z Landroid/content/res/AssetManager;->STYLE_NUM_ENTRIES:I Landroid/content/res/AssetManager;->STYLE_RESOURCE_ID:I Landroid/content/res/DrawableCache;->getInstance(JLandroid/content/res/Resources;Landroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable; Landroid/content/res/Resources;->getCompatibilityInfo()Landroid/content/res/CompatibilityInfo; Landroid/content/res/ResourcesImpl;->mAccessLock:Ljava/lang/Object; Loading Loading @@ -271,7 +256,6 @@ Landroid/content/res/TypedArray;->mResources:Landroid/content/res/Resources; Landroid/content/res/TypedArray;->mTheme:Landroid/content/res/Resources$Theme; Landroid/content/res/TypedArray;->mValue:Landroid/util/TypedValue; Landroid/content/res/TypedArray;->mXml:Landroid/content/res/XmlBlock$Parser; Landroid/content/res/XmlBlock;->close()V Landroid/content/res/XmlBlock;->newParser()Landroid/content/res/XmlResourceParser; Landroid/content/res/XmlBlock$Parser;->mParseState:J Landroid/content/SyncStatusInfo;->lastSuccessTime:J Loading core/java/android/content/pm/PackageParser.java +9 −10 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import android.content.pm.PackageParserCacheHelper.WriteHelper; import android.content.pm.split.DefaultSplitAssetLoader; import android.content.pm.split.SplitAssetDependencyLoader; import android.content.pm.split.SplitAssetLoader; import android.content.res.ApkAssets; import android.content.res.AssetManager; import android.content.res.Configuration; import android.content.res.Resources; Loading Loading @@ -1596,21 +1597,19 @@ public class PackageParser { int flags) throws PackageParserException { final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath(); AssetManager assets = null; ApkAssets apkAssets = null; XmlResourceParser parser = null; try { assets = newConfiguredAssetManager(); int cookie = fd != null ? assets.addAssetFd(fd, debugPathName) : assets.addAssetPath(apkPath); if (cookie == 0) { try { apkAssets = fd != null ? ApkAssets.loadFromFd(fd, debugPathName, false, false) : ApkAssets.loadFromPath(apkPath); } catch (IOException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "Failed to parse " + apkPath); } final DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME); final SigningDetails signingDetails; if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) { Loading @@ -1637,7 +1636,7 @@ public class PackageParser { "Failed to parse " + apkPath, e); } finally { IoUtils.closeQuietly(parser); IoUtils.closeQuietly(assets); IoUtils.closeQuietly(apkAssets); } } Loading core/java/android/content/res/ApkAssets.java 0 → 100644 +221 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * 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 android.content.res; import android.annotation.NonNull; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import java.io.FileDescriptor; import java.io.IOException; /** * The loaded, immutable, in-memory representation of an APK. * * The main implementation is native C++ and there is very little API surface exposed here. The APK * is mainly accessed via {@link AssetManager}. * * Since the ApkAssets instance is immutable, it can be reused and shared across AssetManagers, * making the creation of AssetManagers very cheap. * @hide */ public final class ApkAssets implements AutoCloseable { @GuardedBy("this") private long mNativePtr; @GuardedBy("this") private StringBlock mStringBlock; /** * Creates a new ApkAssets instance from the given path on disk. * * @param path The path to an APK on disk. * @return a new instance of ApkAssets. * @throws IOException if a disk I/O error or parsing error occurred. */ public static @NonNull ApkAssets loadFromPath(@NonNull String path) throws IOException { return new ApkAssets(path, false /*system*/, false /*forceSharedLib*/, false /*overlay*/); } /** * Creates a new ApkAssets instance from the given path on disk. * * @param path The path to an APK on disk. * @param system When true, the APK is loaded as a system APK (framework). * @return a new instance of ApkAssets. * @throws IOException if a disk I/O error or parsing error occurred. */ public static @NonNull ApkAssets loadFromPath(@NonNull String path, boolean system) throws IOException { return new ApkAssets(path, system, false /*forceSharedLib*/, false /*overlay*/); } /** * Creates a new ApkAssets instance from the given path on disk. * * @param path The path to an APK on disk. * @param system When true, the APK is loaded as a system APK (framework). * @param forceSharedLibrary When true, any packages within the APK with package ID 0x7f are * loaded as a shared library. * @return a new instance of ApkAssets. * @throws IOException if a disk I/O error or parsing error occurred. */ public static @NonNull ApkAssets loadFromPath(@NonNull String path, boolean system, boolean forceSharedLibrary) throws IOException { return new ApkAssets(path, system, forceSharedLibrary, false /*overlay*/); } /** * Creates a new ApkAssets instance from the given file descriptor. Not for use by applications. * * Performs a dup of the underlying fd, so you must take care of still closing * the FileDescriptor yourself (and can do that whenever you want). * * @param fd The FileDescriptor of an open, readable APK. * @param friendlyName The friendly name used to identify this ApkAssets when logging. * @param system When true, the APK is loaded as a system APK (framework). * @param forceSharedLibrary When true, any packages within the APK with package ID 0x7f are * loaded as a shared library. * @return a new instance of ApkAssets. * @throws IOException if a disk I/O error or parsing error occurred. */ public static @NonNull ApkAssets loadFromFd(@NonNull FileDescriptor fd, @NonNull String friendlyName, boolean system, boolean forceSharedLibrary) throws IOException { return new ApkAssets(fd, friendlyName, system, forceSharedLibrary); } /** * Creates a new ApkAssets instance from the IDMAP at idmapPath. The overlay APK path * is encoded within the IDMAP. * * @param idmapPath Path to the IDMAP of an overlay APK. * @param system When true, the APK is loaded as a system APK (framework). * @return a new instance of ApkAssets. * @throws IOException if a disk I/O error or parsing error occurred. */ public static @NonNull ApkAssets loadOverlayFromPath(@NonNull String idmapPath, boolean system) throws IOException { return new ApkAssets(idmapPath, system, false /*forceSharedLibrary*/, true /*overlay*/); } private ApkAssets(@NonNull String path, boolean system, boolean forceSharedLib, boolean overlay) throws IOException { Preconditions.checkNotNull(path, "path"); mNativePtr = nativeLoad(path, system, forceSharedLib, overlay); mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/); } private ApkAssets(@NonNull FileDescriptor fd, @NonNull String friendlyName, boolean system, boolean forceSharedLib) throws IOException { Preconditions.checkNotNull(fd, "fd"); Preconditions.checkNotNull(friendlyName, "friendlyName"); mNativePtr = nativeLoadFromFd(fd, friendlyName, system, forceSharedLib); mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/); } @NonNull String getAssetPath() { synchronized (this) { ensureValidLocked(); return nativeGetAssetPath(mNativePtr); } } CharSequence getStringFromPool(int idx) { synchronized (this) { ensureValidLocked(); return mStringBlock.get(idx); } } /** * Retrieve a parser for a compiled XML file. This is associated with a single APK and * <em>NOT</em> a full AssetManager. This means that shared-library references will not be * dynamically assigned runtime package IDs. * * @param fileName The path to the file within the APK. * @return An XmlResourceParser. * @throws IOException if the file was not found or an error occurred retrieving it. */ public @NonNull XmlResourceParser openXml(@NonNull String fileName) throws IOException { Preconditions.checkNotNull(fileName, "fileName"); synchronized (this) { ensureValidLocked(); long nativeXmlPtr = nativeOpenXml(mNativePtr, fileName); try (XmlBlock block = new XmlBlock(null, nativeXmlPtr)) { XmlResourceParser parser = block.newParser(); // If nativeOpenXml doesn't throw, it will always return a valid native pointer, // which makes newParser always return non-null. But let's be paranoid. if (parser == null) { throw new AssertionError("block.newParser() returned a null parser"); } return parser; } } } /** * Returns false if the underlying APK was changed since this ApkAssets was loaded. */ public boolean isUpToDate() { synchronized (this) { ensureValidLocked(); return nativeIsUpToDate(mNativePtr); } } /** * Closes the ApkAssets and destroys the underlying native implementation. Further use of the * ApkAssets object will cause exceptions to be thrown. * * Calling close on an already closed ApkAssets does nothing. */ @Override public void close() { synchronized (this) { if (mNativePtr == 0) { return; } mStringBlock = null; nativeDestroy(mNativePtr); mNativePtr = 0; } } @Override protected void finalize() throws Throwable { if (mNativePtr != 0) { nativeDestroy(mNativePtr); } } private void ensureValidLocked() { if (mNativePtr == 0) { throw new RuntimeException("ApkAssets is closed"); } } private static native long nativeLoad( @NonNull String path, boolean system, boolean forceSharedLib, boolean overlay) throws IOException; private static native long nativeLoadFromFd(@NonNull FileDescriptor fd, @NonNull String friendlyName, boolean system, boolean forceSharedLib) throws IOException; private static native void nativeDestroy(long ptr); private static native @NonNull String nativeGetAssetPath(long ptr); private static native long nativeGetStringBlock(long ptr); private static native boolean nativeIsUpToDate(long ptr); private static native long nativeOpenXml(long ptr, @NonNull String fileName) throws IOException; } Loading
config/hiddenapi-light-greylist.txt +0 −16 Original line number Diff line number Diff line Loading @@ -220,28 +220,13 @@ Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;IZ)Landroid/conte Landroid/content/pm/UserInfo;->id:I Landroid/content/pm/UserInfo;->isPrimary()Z Landroid/content/res/AssetManager;->addAssetPath(Ljava/lang/String;)I Landroid/content/res/AssetManager;->addAssetPaths([Ljava/lang/String;)[I Landroid/content/res/AssetManager;->applyStyle(JIIJ[IIJJ)V Landroid/content/res/AssetManager;->getArraySize(I)I Landroid/content/res/AssetManager;->getAssignedPackageIdentifiers()Landroid/util/SparseArray; Landroid/content/res/AssetManager;->getCookieName(I)Ljava/lang/String; Landroid/content/res/AssetManager;->getResourceBagText(II)Ljava/lang/CharSequence; Landroid/content/res/AssetManager;->loadResourceBagValue(IILandroid/util/TypedValue;Z)I Landroid/content/res/AssetManager;->loadResourceValue(ISLandroid/util/TypedValue;Z)I Landroid/content/res/AssetManager;->loadThemeAttributeValue(JILandroid/util/TypedValue;Z)I Landroid/content/res/AssetManager;->mObject:J Landroid/content/res/AssetManager;->openNonAssetFdNative(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor; Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;I)Ljava/io/InputStream; Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;)Ljava/io/InputStream; Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;I)Ljava/io/InputStream; Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;)Ljava/io/InputStream; Landroid/content/res/AssetManager;->openNonAssetNative(ILjava/lang/String;I)J Landroid/content/res/AssetManager;->openXmlAssetNative(ILjava/lang/String;)J Landroid/content/res/AssetManager;->resolveAttrs(JII[I[I[I[I)Z Landroid/content/res/AssetManager;->retrieveArray(I[I)I Landroid/content/res/AssetManager;->retrieveAttributes(J[I[I[I)Z Landroid/content/res/AssetManager;->STYLE_NUM_ENTRIES:I Landroid/content/res/AssetManager;->STYLE_RESOURCE_ID:I Landroid/content/res/DrawableCache;->getInstance(JLandroid/content/res/Resources;Landroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable; Landroid/content/res/Resources;->getCompatibilityInfo()Landroid/content/res/CompatibilityInfo; Landroid/content/res/ResourcesImpl;->mAccessLock:Ljava/lang/Object; Loading Loading @@ -271,7 +256,6 @@ Landroid/content/res/TypedArray;->mResources:Landroid/content/res/Resources; Landroid/content/res/TypedArray;->mTheme:Landroid/content/res/Resources$Theme; Landroid/content/res/TypedArray;->mValue:Landroid/util/TypedValue; Landroid/content/res/TypedArray;->mXml:Landroid/content/res/XmlBlock$Parser; Landroid/content/res/XmlBlock;->close()V Landroid/content/res/XmlBlock;->newParser()Landroid/content/res/XmlResourceParser; Landroid/content/res/XmlBlock$Parser;->mParseState:J Landroid/content/SyncStatusInfo;->lastSuccessTime:J Loading
core/java/android/content/pm/PackageParser.java +9 −10 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import android.content.pm.PackageParserCacheHelper.WriteHelper; import android.content.pm.split.DefaultSplitAssetLoader; import android.content.pm.split.SplitAssetDependencyLoader; import android.content.pm.split.SplitAssetLoader; import android.content.res.ApkAssets; import android.content.res.AssetManager; import android.content.res.Configuration; import android.content.res.Resources; Loading Loading @@ -1596,21 +1597,19 @@ public class PackageParser { int flags) throws PackageParserException { final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath(); AssetManager assets = null; ApkAssets apkAssets = null; XmlResourceParser parser = null; try { assets = newConfiguredAssetManager(); int cookie = fd != null ? assets.addAssetFd(fd, debugPathName) : assets.addAssetPath(apkPath); if (cookie == 0) { try { apkAssets = fd != null ? ApkAssets.loadFromFd(fd, debugPathName, false, false) : ApkAssets.loadFromPath(apkPath); } catch (IOException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "Failed to parse " + apkPath); } final DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME); final SigningDetails signingDetails; if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) { Loading @@ -1637,7 +1636,7 @@ public class PackageParser { "Failed to parse " + apkPath, e); } finally { IoUtils.closeQuietly(parser); IoUtils.closeQuietly(assets); IoUtils.closeQuietly(apkAssets); } } Loading
core/java/android/content/res/ApkAssets.java 0 → 100644 +221 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * 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 android.content.res; import android.annotation.NonNull; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import java.io.FileDescriptor; import java.io.IOException; /** * The loaded, immutable, in-memory representation of an APK. * * The main implementation is native C++ and there is very little API surface exposed here. The APK * is mainly accessed via {@link AssetManager}. * * Since the ApkAssets instance is immutable, it can be reused and shared across AssetManagers, * making the creation of AssetManagers very cheap. * @hide */ public final class ApkAssets implements AutoCloseable { @GuardedBy("this") private long mNativePtr; @GuardedBy("this") private StringBlock mStringBlock; /** * Creates a new ApkAssets instance from the given path on disk. * * @param path The path to an APK on disk. * @return a new instance of ApkAssets. * @throws IOException if a disk I/O error or parsing error occurred. */ public static @NonNull ApkAssets loadFromPath(@NonNull String path) throws IOException { return new ApkAssets(path, false /*system*/, false /*forceSharedLib*/, false /*overlay*/); } /** * Creates a new ApkAssets instance from the given path on disk. * * @param path The path to an APK on disk. * @param system When true, the APK is loaded as a system APK (framework). * @return a new instance of ApkAssets. * @throws IOException if a disk I/O error or parsing error occurred. */ public static @NonNull ApkAssets loadFromPath(@NonNull String path, boolean system) throws IOException { return new ApkAssets(path, system, false /*forceSharedLib*/, false /*overlay*/); } /** * Creates a new ApkAssets instance from the given path on disk. * * @param path The path to an APK on disk. * @param system When true, the APK is loaded as a system APK (framework). * @param forceSharedLibrary When true, any packages within the APK with package ID 0x7f are * loaded as a shared library. * @return a new instance of ApkAssets. * @throws IOException if a disk I/O error or parsing error occurred. */ public static @NonNull ApkAssets loadFromPath(@NonNull String path, boolean system, boolean forceSharedLibrary) throws IOException { return new ApkAssets(path, system, forceSharedLibrary, false /*overlay*/); } /** * Creates a new ApkAssets instance from the given file descriptor. Not for use by applications. * * Performs a dup of the underlying fd, so you must take care of still closing * the FileDescriptor yourself (and can do that whenever you want). * * @param fd The FileDescriptor of an open, readable APK. * @param friendlyName The friendly name used to identify this ApkAssets when logging. * @param system When true, the APK is loaded as a system APK (framework). * @param forceSharedLibrary When true, any packages within the APK with package ID 0x7f are * loaded as a shared library. * @return a new instance of ApkAssets. * @throws IOException if a disk I/O error or parsing error occurred. */ public static @NonNull ApkAssets loadFromFd(@NonNull FileDescriptor fd, @NonNull String friendlyName, boolean system, boolean forceSharedLibrary) throws IOException { return new ApkAssets(fd, friendlyName, system, forceSharedLibrary); } /** * Creates a new ApkAssets instance from the IDMAP at idmapPath. The overlay APK path * is encoded within the IDMAP. * * @param idmapPath Path to the IDMAP of an overlay APK. * @param system When true, the APK is loaded as a system APK (framework). * @return a new instance of ApkAssets. * @throws IOException if a disk I/O error or parsing error occurred. */ public static @NonNull ApkAssets loadOverlayFromPath(@NonNull String idmapPath, boolean system) throws IOException { return new ApkAssets(idmapPath, system, false /*forceSharedLibrary*/, true /*overlay*/); } private ApkAssets(@NonNull String path, boolean system, boolean forceSharedLib, boolean overlay) throws IOException { Preconditions.checkNotNull(path, "path"); mNativePtr = nativeLoad(path, system, forceSharedLib, overlay); mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/); } private ApkAssets(@NonNull FileDescriptor fd, @NonNull String friendlyName, boolean system, boolean forceSharedLib) throws IOException { Preconditions.checkNotNull(fd, "fd"); Preconditions.checkNotNull(friendlyName, "friendlyName"); mNativePtr = nativeLoadFromFd(fd, friendlyName, system, forceSharedLib); mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/); } @NonNull String getAssetPath() { synchronized (this) { ensureValidLocked(); return nativeGetAssetPath(mNativePtr); } } CharSequence getStringFromPool(int idx) { synchronized (this) { ensureValidLocked(); return mStringBlock.get(idx); } } /** * Retrieve a parser for a compiled XML file. This is associated with a single APK and * <em>NOT</em> a full AssetManager. This means that shared-library references will not be * dynamically assigned runtime package IDs. * * @param fileName The path to the file within the APK. * @return An XmlResourceParser. * @throws IOException if the file was not found or an error occurred retrieving it. */ public @NonNull XmlResourceParser openXml(@NonNull String fileName) throws IOException { Preconditions.checkNotNull(fileName, "fileName"); synchronized (this) { ensureValidLocked(); long nativeXmlPtr = nativeOpenXml(mNativePtr, fileName); try (XmlBlock block = new XmlBlock(null, nativeXmlPtr)) { XmlResourceParser parser = block.newParser(); // If nativeOpenXml doesn't throw, it will always return a valid native pointer, // which makes newParser always return non-null. But let's be paranoid. if (parser == null) { throw new AssertionError("block.newParser() returned a null parser"); } return parser; } } } /** * Returns false if the underlying APK was changed since this ApkAssets was loaded. */ public boolean isUpToDate() { synchronized (this) { ensureValidLocked(); return nativeIsUpToDate(mNativePtr); } } /** * Closes the ApkAssets and destroys the underlying native implementation. Further use of the * ApkAssets object will cause exceptions to be thrown. * * Calling close on an already closed ApkAssets does nothing. */ @Override public void close() { synchronized (this) { if (mNativePtr == 0) { return; } mStringBlock = null; nativeDestroy(mNativePtr); mNativePtr = 0; } } @Override protected void finalize() throws Throwable { if (mNativePtr != 0) { nativeDestroy(mNativePtr); } } private void ensureValidLocked() { if (mNativePtr == 0) { throw new RuntimeException("ApkAssets is closed"); } } private static native long nativeLoad( @NonNull String path, boolean system, boolean forceSharedLib, boolean overlay) throws IOException; private static native long nativeLoadFromFd(@NonNull FileDescriptor fd, @NonNull String friendlyName, boolean system, boolean forceSharedLib) throws IOException; private static native void nativeDestroy(long ptr); private static native @NonNull String nativeGetAssetPath(long ptr); private static native long nativeGetStringBlock(long ptr); private static native boolean nativeIsUpToDate(long ptr); private static native long nativeOpenXml(long ptr, @NonNull String fileName) throws IOException; }