/*
 * Copyright (C) 2006 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.AnyRes;
import android.annotation.ArrayRes;
import android.annotation.AttrRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration.NativeConfig;
import android.content.res.loader.ResourcesLoader;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.om.OverlayConfig;

import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.ref.Reference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;

/**
 * Provides access to an application's raw asset files; see {@link Resources}
 * for the way most applications will want to retrieve their resource data.
 * This class presents a lower-level API that allows you to open and read raw
 * files that have been bundled with the application as a simple stream of
 * bytes.
 */
public final class AssetManager implements AutoCloseable {
    private static final String TAG = "AssetManager";
    private static final boolean DEBUG_REFS = false;

    private static final String FRAMEWORK_APK_PATH = "/system/framework/framework-res.apk";

    private static final Object sSync = new Object();

    private static final ApkAssets[] sEmptyApkAssets = new ApkAssets[0];

    // Not private for LayoutLib's BridgeAssetManager.
    @UnsupportedAppUsage
    @GuardedBy("sSync") static AssetManager sSystem = null;

    @GuardedBy("sSync") private static ApkAssets[] sSystemApkAssets = new ApkAssets[0];
    @GuardedBy("sSync") private static ArraySet<ApkAssets> sSystemApkAssetsSet;

    /**
     * Cookie value to use when the actual cookie is unknown. This value tells the system to search
     * all the ApkAssets for the asset.
     * @hide
     */
    public static final int COOKIE_UNKNOWN = -1;

    /**
     * Mode for {@link #open(String, int)}: no specific information about how
     * data will be accessed.
     */
    public static final int ACCESS_UNKNOWN = 0;
    /**
     * Mode for {@link #open(String, int)}: Read chunks, and seek forward and
     * backward.
     */
    public static final int ACCESS_RANDOM = 1;
    /**
     * Mode for {@link #open(String, int)}: Read sequentially, with an
     * occasional forward seek.
     */
    public static final int ACCESS_STREAMING = 2;
    /**
     * Mode for {@link #open(String, int)}: Attempt to load contents into
     * memory, for fast small reads.
     */
    public static final int ACCESS_BUFFER = 3;

    @GuardedBy("this") private final TypedValue mValue = new TypedValue();
    @GuardedBy("this") private final long[] mOffsets = new long[2];

    // Pointer to native implementation, stuffed inside a long.
    @UnsupportedAppUsage
    @GuardedBy("this") private long mObject;

    // The loaded asset paths.
    @GuardedBy("this") private ApkAssets[] mApkAssets;

    // Debug/reference counting implementation.
    @GuardedBy("this") private boolean mOpen = true;
    @GuardedBy("this") private int mNumRefs = 1;
    @GuardedBy("this") private HashMap<Long, RuntimeException> mRefStacks;

    private ResourcesLoader[] mLoaders;

    /**
     * A Builder class that helps create an AssetManager with only a single invocation of
     * {@link AssetManager#setApkAssets(ApkAssets[], boolean)}. Without using this builder,
     * AssetManager must ensure there are system ApkAssets loaded at all times, which when combined
     * with the user's call to add additional ApkAssets, results in multiple calls to
     * {@link AssetManager#setApkAssets(ApkAssets[], boolean)}.
     * @hide
     */
    public static class Builder {
        private ArrayList<ApkAssets> mUserApkAssets = new ArrayList<>();
        private ArrayList<ResourcesLoader> mLoaders = new ArrayList<>();

        public Builder addApkAssets(ApkAssets apkAssets) {
            mUserApkAssets.add(apkAssets);
            return this;
        }

        public Builder addLoader(ResourcesLoader loader) {
            mLoaders.add(loader);
            return this;
        }

        public AssetManager build() {
            // Retrieving the system ApkAssets forces their creation as well.
            final ApkAssets[] systemApkAssets = getSystem().getApkAssets();

            // Filter ApkAssets so that assets provided by multiple loaders are only included once
            // in the AssetManager assets. The last appearance of the ApkAssets dictates its load
            // order.
            final ArrayList<ApkAssets> loaderApkAssets = new ArrayList<>();
            final ArraySet<ApkAssets> uniqueLoaderApkAssets = new ArraySet<>();
            for (int i = mLoaders.size() - 1; i >= 0; i--) {
                final List<ApkAssets> currentLoaderApkAssets = mLoaders.get(i).getApkAssets();
                for (int j = currentLoaderApkAssets.size() - 1; j >= 0; j--) {
                    final ApkAssets apkAssets = currentLoaderApkAssets.get(j);
                    if (uniqueLoaderApkAssets.add(apkAssets)) {
                        loaderApkAssets.add(0, apkAssets);
                    }
                }
            }

            final int totalApkAssetCount = systemApkAssets.length + mUserApkAssets.size()
                    + loaderApkAssets.size();
            final ApkAssets[] apkAssets = new ApkAssets[totalApkAssetCount];

            System.arraycopy(systemApkAssets, 0, apkAssets, 0, systemApkAssets.length);

            // Append user ApkAssets after system ApkAssets.
            for (int i = 0, n = mUserApkAssets.size(); i < n; i++) {
                apkAssets[i + systemApkAssets.length] = mUserApkAssets.get(i);
            }

            // Append ApkAssets provided by loaders to the end.
            for (int i = 0, n = loaderApkAssets.size(); i < n; i++) {
                apkAssets[i + systemApkAssets.length  + mUserApkAssets.size()] =
                        loaderApkAssets.get(i);
            }

            // Calling this constructor prevents creation of system ApkAssets, which we took care
            // of in this Builder.
            final AssetManager assetManager = new AssetManager(false /*sentinel*/);
            assetManager.mApkAssets = apkAssets;
            AssetManager.nativeSetApkAssets(assetManager.mObject, apkAssets,
                    false /*invalidateCaches*/);
            assetManager.mLoaders = mLoaders.isEmpty() ? null
                    : mLoaders.toArray(new ResourcesLoader[0]);

            return assetManager;
        }
    }

    /**
     * Create a new AssetManager containing only the basic system assets.
     * Applications will not generally use this method, instead retrieving the
     * appropriate asset manager with {@link Resources#getAssets}.    Not for
     * use by applications.
     * @hide
     */
    @UnsupportedAppUsage
    public AssetManager() {
        final ApkAssets[] assets;
        synchronized (sSync) {
            createSystemAssetsInZygoteLocked(false, FRAMEWORK_APK_PATH);
            assets = sSystemApkAssets;
        }

        mObject = nativeCreate();
        if (DEBUG_REFS) {
            mNumRefs = 0;
            incRefsLocked(hashCode());
        }

        // Always set the framework resources.
        setApkAssets(assets, false /*invalidateCaches*/);
    }

    /**
     * Private constructor that doesn't call ensureSystemAssets.
     * Used for the creation of system assets.
     */
    @SuppressWarnings("unused")
    private AssetManager(boolean sentinel) {
        mObject = nativeCreate();
        if (DEBUG_REFS) {
            mNumRefs = 0;
            incRefsLocked(hashCode());
        }
    }

    /**
     * This must be called from Zygote so that system assets are shared by all applications.
     * @hide
     */
    @GuardedBy("sSync")
    @VisibleForTesting
    public static void createSystemAssetsInZygoteLocked(boolean reinitialize,
            String frameworkPath) {
        if (sSystem != null && !reinitialize) {
            return;
        }

        try {
            final ArrayList<ApkAssets> apkAssets = new ArrayList<>();
            apkAssets.add(ApkAssets.loadFromPath(frameworkPath, ApkAssets.PROPERTY_SYSTEM));

            final String[] systemIdmapPaths =
                    OverlayConfig.getZygoteInstance().createImmutableFrameworkIdmapsInZygote();
            for (String idmapPath : systemIdmapPaths) {
                apkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, ApkAssets.PROPERTY_SYSTEM));
            }

            sSystemApkAssetsSet = new ArraySet<>(apkAssets);
            sSystemApkAssets = apkAssets.toArray(new ApkAssets[apkAssets.size()]);
            if (sSystem == null) {
                sSystem = new AssetManager(true /*sentinel*/);
            }
            sSystem.setApkAssets(sSystemApkAssets, false /*invalidateCaches*/);
        } catch (IOException e) {
            throw new IllegalStateException("Failed to create system AssetManager", e);
        }
    }

    /**
     * Return a global shared asset manager that provides access to only
     * system assets (no application assets).
     * @hide
     */
    @UnsupportedAppUsage
    public static AssetManager getSystem() {
        synchronized (sSync) {
            createSystemAssetsInZygoteLocked(false, FRAMEWORK_APK_PATH);
            return sSystem;
        }
    }

    /**
     * Close this asset manager.
     */
    @Override
    public void close() {
        synchronized (this) {
            if (!mOpen) {
                return;
            }

            mOpen = false;
            decRefsLocked(hashCode());
        }
    }

    /**
     * Changes the asset paths in this AssetManager. This replaces the {@link #addAssetPath(String)}
     * family of methods.
     *
     * @param apkAssets The new set of paths.
     * @param invalidateCaches Whether to invalidate any caches. This should almost always be true.
     *                         Set this to false if you are appending new resources
     *                         (not new configurations).
     * @hide
     */
    public void setApkAssets(@NonNull ApkAssets[] apkAssets, boolean invalidateCaches) {
        Objects.requireNonNull(apkAssets, "apkAssets");

        ApkAssets[] newApkAssets = new ApkAssets[sSystemApkAssets.length + apkAssets.length];

        // Copy the system assets first.
        System.arraycopy(sSystemApkAssets, 0, newApkAssets, 0, sSystemApkAssets.length);

        // Copy the given ApkAssets if they are not already in the system list.
        int newLength = sSystemApkAssets.length;
        for (ApkAssets apkAsset : apkAssets) {
            if (!sSystemApkAssetsSet.contains(apkAsset)) {
                newApkAssets[newLength++] = apkAsset;
            }
        }

        // Truncate if necessary.
        if (newLength != newApkAssets.length) {
            newApkAssets = Arrays.copyOf(newApkAssets, newLength);
        }

        synchronized (this) {
            ensureOpenLocked();
            mApkAssets = newApkAssets;
            nativeSetApkAssets(mObject, mApkAssets, invalidateCaches);
            if (invalidateCaches) {
                // Invalidate all caches.
                invalidateCachesLocked(-1);
            }
        }
    }

    /**
     * Changes the {@link ResourcesLoader ResourcesLoaders} used in this AssetManager.
     * @hide
     */
    void setLoaders(@NonNull List<ResourcesLoader> newLoaders) {
        Objects.requireNonNull(newLoaders, "newLoaders");

        final ArrayList<ApkAssets> apkAssets = new ArrayList<>();
        for (int i = 0; i < mApkAssets.length; i++) {
            // Filter out the previous loader apk assets.
            if (!mApkAssets[i].isForLoader()) {
                apkAssets.add(mApkAssets[i]);
            }
        }

        if (!newLoaders.isEmpty()) {
            // Filter so that assets provided by multiple loaders are only included once
            // in the final assets list. The last appearance of the ApkAssets dictates its load
            // order.
            final int loaderStartIndex = apkAssets.size();
            final ArraySet<ApkAssets> uniqueLoaderApkAssets = new ArraySet<>();
            for (int i = newLoaders.size() - 1; i >= 0; i--) {
                final List<ApkAssets> currentLoaderApkAssets = newLoaders.get(i).getApkAssets();
                for (int j = currentLoaderApkAssets.size() - 1; j >= 0; j--) {
                    final ApkAssets loaderApkAssets = currentLoaderApkAssets.get(j);
                    if (uniqueLoaderApkAssets.add(loaderApkAssets)) {
                        apkAssets.add(loaderStartIndex, loaderApkAssets);
                    }
                }
            }
        }

        mLoaders = newLoaders.toArray(new ResourcesLoader[0]);
        setApkAssets(apkAssets.toArray(new ApkAssets[0]), true /* invalidate_caches */);
    }

    /**
     * Invalidates the caches in this AssetManager according to the bitmask `diff`.
     *
     * @param diff The bitmask of changes generated by {@link Configuration#diff(Configuration)}.
     * @see ActivityInfo.Config
     */
    private void invalidateCachesLocked(int diff) {
        // TODO(adamlesinski): Currently there are no caches to invalidate in Java code.
    }

    /**
     * Returns the set of ApkAssets loaded by this AssetManager. If the AssetManager is closed, this
     * returns a 0-length array.
     * @hide
     */
    @UnsupportedAppUsage
    public @NonNull ApkAssets[] getApkAssets() {
        synchronized (this) {
            if (mOpen) {
                return mApkAssets;
            }
        }
        return sEmptyApkAssets;
    }

    /** @hide */
    @TestApi
    public @NonNull String[] getApkPaths() {
        synchronized (this) {
            if (mOpen) {
                String[] paths = new String[mApkAssets.length];
                final int count = mApkAssets.length;
                for (int i = 0; i < count; i++) {
                    paths[i] = mApkAssets[i].getAssetPath();
                }
                return paths;
            }
        }
        return new String[0];
    }

    /**
     * Returns a cookie for use with the other APIs of AssetManager.
     * @return 0 if the path was not found, otherwise a positive integer cookie representing
     * this path in the AssetManager.
     * @hide
     */
    public int findCookieForPath(@NonNull String path) {
        Objects.requireNonNull(path, "path");
        synchronized (this) {
            ensureValidLocked();
            final int count = mApkAssets.length;
            for (int i = 0; i < count; i++) {
                if (path.equals(mApkAssets[i].getAssetPath())) {
                    return i + 1;
                }
            }
        }
        return 0;
    }

    /**
     * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
     * @hide
     */
    @Deprecated
    @UnsupportedAppUsage
    public int addAssetPath(String path) {
        return addAssetPathInternal(path, false /*overlay*/, false /*appAsLib*/);
    }

    /**
     * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
     * @hide
     */
    @Deprecated
    @UnsupportedAppUsage
    public int addAssetPathAsSharedLibrary(String path) {
        return addAssetPathInternal(path, false /*overlay*/, true /*appAsLib*/);
    }

    /**
     * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
     * @hide
     */
    @Deprecated
    @UnsupportedAppUsage
    public int addOverlayPath(String path) {
        return addAssetPathInternal(path, true /*overlay*/, false /*appAsLib*/);
    }

    private int addAssetPathInternal(String path, boolean overlay, boolean appAsLib) {
        Objects.requireNonNull(path, "path");
        synchronized (this) {
            ensureOpenLocked();
            final int count = mApkAssets.length;

            // See if we already have it loaded.
            for (int i = 0; i < count; i++) {
                if (mApkAssets[i].getAssetPath().equals(path)) {
                    return i + 1;
                }
            }

            final ApkAssets assets;
            try {
                if (overlay) {
                    // TODO(b/70343104): This hardcoded path will be removed once
                    // addAssetPathInternal is deleted.
                    final String idmapPath = "/data/resource-cache/"
                            + path.substring(1).replace('/', '@')
                            + "@idmap";
                    assets = ApkAssets.loadOverlayFromPath(idmapPath, 0 /* flags */);
                } else {
                    assets = ApkAssets.loadFromPath(path,
                            appAsLib ? ApkAssets.PROPERTY_DYNAMIC : 0);
                }
            } catch (IOException e) {
                return 0;
            }

            mApkAssets = Arrays.copyOf(mApkAssets, count + 1);
            mApkAssets[count] = assets;
            nativeSetApkAssets(mObject, mApkAssets, true);
            invalidateCachesLocked(-1);
            return count + 1;
        }
    }

    /** @hide */
    @NonNull
    public List<ResourcesLoader> getLoaders() {
        return mLoaders == null ? Collections.emptyList() : Arrays.asList(mLoaders);
    }

    /**
     * Ensures that the native implementation has not been destroyed.
     * The AssetManager may have been closed, but references to it still exist
     * and therefore the native implementation is not destroyed.
     */
    @GuardedBy("this")
    private void ensureValidLocked() {
        if (mObject == 0) {
            throw new RuntimeException("AssetManager has been destroyed");
        }
    }

    /**
     * Ensures that the AssetManager has not been explicitly closed. If this method passes,
     * then this implies that ensureValidLocked() also passes.
     */
    @GuardedBy("this")
    private void ensureOpenLocked() {
        // If mOpen is true, this implies that mObject != 0.
        if (!mOpen) {
            throw new RuntimeException("AssetManager has been closed");
        }
    }

    /**
     * Populates {@code outValue} with the data associated a particular
     * resource identifier for the current configuration.
     *
     * @param resId the resource identifier to load
     * @param densityDpi the density bucket for which to load the resource
     * @param outValue the typed value in which to put the data
     * @param resolveRefs {@code true} to resolve references, {@code false}
     *                    to leave them unresolved
     * @return {@code true} if the data was loaded into {@code outValue},
     *         {@code false} otherwise
     */
    @UnsupportedAppUsage
    boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
            boolean resolveRefs) {
        Objects.requireNonNull(outValue, "outValue");
        synchronized (this) {
            ensureValidLocked();
            final int cookie = nativeGetResourceValue(
                    mObject, resId, (short) densityDpi, outValue, resolveRefs);
            if (cookie <= 0) {
                return false;
            }

            // Convert the changing configurations flags populated by native code.
            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
                    outValue.changingConfigurations);

            if (outValue.type == TypedValue.TYPE_STRING) {
                if ((outValue.string = getPooledStringForCookie(cookie, outValue.data)) == null) {
                    return false;
                }
            }
            return true;
        }
    }

    /**
     * Retrieves the string value associated with a particular resource
     * identifier for the current configuration.
     *
     * @param resId the resource identifier to load
     * @return the string value, or {@code null}
     */
    @UnsupportedAppUsage
    @Nullable CharSequence getResourceText(@StringRes int resId) {
        synchronized (this) {
            final TypedValue outValue = mValue;
            if (getResourceValue(resId, 0, outValue, true)) {
                return outValue.coerceToString();
            }
            return null;
        }
    }

    /**
     * Retrieves the string value associated with a particular resource
     * identifier for the current configuration.
     *
     * @param resId the resource identifier to load
     * @param bagEntryId the index into the bag to load
     * @return the string value, or {@code null}
     */
    @UnsupportedAppUsage
    @Nullable CharSequence getResourceBagText(@StringRes int resId, int bagEntryId) {
        synchronized (this) {
            ensureValidLocked();
            final TypedValue outValue = mValue;
            final int cookie = nativeGetResourceBagValue(mObject, resId, bagEntryId, outValue);
            if (cookie <= 0) {
                return null;
            }

            // Convert the changing configurations flags populated by native code.
            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
                    outValue.changingConfigurations);

            if (outValue.type == TypedValue.TYPE_STRING) {
                return getPooledStringForCookie(cookie, outValue.data);
            }
            return outValue.coerceToString();
        }
    }

    int getResourceArraySize(@ArrayRes int resId) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetResourceArraySize(mObject, resId);
        }
    }

    /**
     * Populates `outData` with array elements of `resId`. `outData` is normally
     * used with
     * {@link TypedArray}.
     *
     * Each logical element in `outData` is {@link TypedArray#STYLE_NUM_ENTRIES}
     * long,
     * with the indices of the data representing the type, value, asset cookie,
     * resource ID,
     * configuration change mask, and density of the element.
     *
     * @param resId The resource ID of an array resource.
     * @param outData The array to populate with data.
     * @return The length of the array.
     *
     * @see TypedArray#STYLE_TYPE
     * @see TypedArray#STYLE_DATA
     * @see TypedArray#STYLE_ASSET_COOKIE
     * @see TypedArray#STYLE_RESOURCE_ID
     * @see TypedArray#STYLE_CHANGING_CONFIGURATIONS
     * @see TypedArray#STYLE_DENSITY
     */
    int getResourceArray(@ArrayRes int resId, @NonNull int[] outData) {
        Objects.requireNonNull(outData, "outData");
        synchronized (this) {
            ensureValidLocked();
            return nativeGetResourceArray(mObject, resId, outData);
        }
    }

    /**
     * Retrieves the string array associated with a particular resource
     * identifier for the current configuration.
     *
     * @param resId the resource identifier of the string array
     * @return the string array, or {@code null}
     */
    @Nullable String[] getResourceStringArray(@ArrayRes int resId) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetResourceStringArray(mObject, resId);
        }
    }

    /**
     * Retrieve the text array associated with a particular resource
     * identifier.
     *
     * @param resId the resource id of the string array
     */
    @Nullable CharSequence[] getResourceTextArray(@ArrayRes int resId) {
        synchronized (this) {
            ensureValidLocked();
            final int[] rawInfoArray = nativeGetResourceStringArrayInfo(mObject, resId);
            if (rawInfoArray == null) {
                return null;
            }

            final int rawInfoArrayLen = rawInfoArray.length;
            final int infoArrayLen = rawInfoArrayLen / 2;
            final CharSequence[] retArray = new CharSequence[infoArrayLen];
            for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) {
                int cookie = rawInfoArray[i];
                int index = rawInfoArray[i + 1];
                retArray[j] = (index >= 0 && cookie > 0)
                        ? getPooledStringForCookie(cookie, index) : null;
            }
            return retArray;
        }
    }

    @Nullable int[] getResourceIntArray(@ArrayRes int resId) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetResourceIntArray(mObject, resId);
        }
    }

    /**
     * Get the attributes for a style resource. These are the &lt;item&gt;
     * elements in
     * a &lt;style&gt; resource.
     * @param resId The resource ID of the style
     * @return An array of attribute IDs.
     */
    @AttrRes int[] getStyleAttributes(@StyleRes int resId) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetStyleAttributes(mObject, resId);
        }
    }

    /**
     * Populates {@code outValue} with the data associated with a particular
     * resource identifier for the current configuration. Resolves theme
     * attributes against the specified theme.
     *
     * @param theme the native pointer of the theme
     * @param resId the resource identifier to load
     * @param outValue the typed value in which to put the data
     * @param resolveRefs {@code true} to resolve references, {@code false}
     *                    to leave them unresolved
     * @return {@code true} if the data was loaded into {@code outValue},
     *         {@code false} otherwise
     */
    boolean getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue,
            boolean resolveRefs) {
        Objects.requireNonNull(outValue, "outValue");
        synchronized (this) {
            ensureValidLocked();
            final int cookie = nativeThemeGetAttributeValue(mObject, theme, resId, outValue,
                    resolveRefs);
            if (cookie <= 0) {
                return false;
            }

            // Convert the changing configurations flags populated by native code.
            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
                    outValue.changingConfigurations);

            if (outValue.type == TypedValue.TYPE_STRING) {
                if ((outValue.string = getPooledStringForCookie(cookie, outValue.data)) == null) {
                    return false;
                }
            }
            return true;
        }
    }

    void dumpTheme(long theme, int priority, String tag, String prefix) {
        synchronized (this) {
            ensureValidLocked();
            nativeThemeDump(mObject, theme, priority, tag, prefix);
        }
    }

    @UnsupportedAppUsage
    @Nullable String getResourceName(@AnyRes int resId) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetResourceName(mObject, resId);
        }
    }

    @UnsupportedAppUsage
    @Nullable String getResourcePackageName(@AnyRes int resId) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetResourcePackageName(mObject, resId);
        }
    }

    @UnsupportedAppUsage
    @Nullable String getResourceTypeName(@AnyRes int resId) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetResourceTypeName(mObject, resId);
        }
    }

    @UnsupportedAppUsage
    @Nullable String getResourceEntryName(@AnyRes int resId) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetResourceEntryName(mObject, resId);
        }
    }

    @UnsupportedAppUsage
    @AnyRes int getResourceIdentifier(@NonNull String name, @Nullable String defType,
            @Nullable String defPackage) {
        synchronized (this) {
            ensureValidLocked();
            // name is checked in JNI.
            return nativeGetResourceIdentifier(mObject, name, defType, defPackage);
        }
    }

    /**
     * To get the parent theme resource id according to the parameter theme resource id.
     * @param resId theme resource id.
     * @return the parent theme resource id.
     * @hide
     */
    @StyleRes
    int getParentThemeIdentifier(@StyleRes int resId) {
        synchronized (this) {
            ensureValidLocked();
            // name is checked in JNI.
            return nativeGetParentThemeIdentifier(mObject, resId);
        }
    }

    /**
     * Enable resource resolution logging to track the steps taken to resolve the last resource
     * entry retrieved. Stores the configuration and package names for each step.
     *
     * Default disabled.
     *
     * @param enabled Boolean indicating whether to enable or disable logging.
     *
     * @hide
     */
    @TestApi
    public void setResourceResolutionLoggingEnabled(boolean enabled) {
        synchronized (this) {
            ensureValidLocked();
            nativeSetResourceResolutionLoggingEnabled(mObject, enabled);
        }
    }

    /**
     * Retrieve the last resource resolution path logged.
     *
     * @return Formatted string containing last resource ID/name and steps taken to resolve final
     * entry, including configuration and package names.
     *
     * @hide
     */
    @TestApi
    public @Nullable String getLastResourceResolution() {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetLastResourceResolution(mObject);
        }
    }

    /**
     * Returns whether the {@code resources.arsc} of any loaded apk assets is allocated in RAM
     * (not mmapped).
     *
     * @hide
     */
    public boolean containsAllocatedTable() {
        synchronized (this) {
            ensureValidLocked();
            return nativeContainsAllocatedTable(mObject);
        }
    }

    @Nullable
    CharSequence getPooledStringForCookie(int cookie, int id) {
        // Cookies map to ApkAssets starting at 1.
        return getApkAssets()[cookie - 1].getStringFromPool(id);
    }

    /**
     * Open an asset using ACCESS_STREAMING mode.  This provides access to
     * files that have been bundled with an application as assets -- that is,
     * files placed in to the "assets" directory.
     * 
     * @param fileName The name of the asset to open.  This name can be hierarchical.
     * 
     * @see #open(String, int)
     * @see #list
     */
    public @NonNull InputStream open(@NonNull String fileName) throws IOException {
        return open(fileName, ACCESS_STREAMING);
    }

    /**
     * Open an asset using an explicit access mode, returning an InputStream to
     * read its contents.  This provides access to files that have been bundled
     * with an application as assets -- that is, files placed in to the
     * "assets" directory.
     * 
     * @param fileName The name of the asset to open.  This name can be hierarchical.
     * @param accessMode Desired access mode for retrieving the data.
     * 
     * @see #ACCESS_UNKNOWN
     * @see #ACCESS_STREAMING
     * @see #ACCESS_RANDOM
     * @see #ACCESS_BUFFER
     * @see #open(String)
     * @see #list
     */
    public @NonNull InputStream open(@NonNull String fileName, int accessMode) throws IOException {
        Objects.requireNonNull(fileName, "fileName");
        synchronized (this) {
            ensureOpenLocked();
            final long asset = nativeOpenAsset(mObject, fileName, accessMode);
            if (asset == 0) {
                throw new FileNotFoundException("Asset file: " + fileName);
            }
            final AssetInputStream assetInputStream = new AssetInputStream(asset);
            incRefsLocked(assetInputStream.hashCode());
            return assetInputStream;
        }
    }

    /**
     * Open an uncompressed asset by mmapping it and returning an {@link AssetFileDescriptor}.
     * This provides access to files that have been bundled with an application as assets -- that
     * is, files placed in to the "assets" directory.
     *
     * The asset must be uncompressed, or an exception will be thrown.
     *
     * @param fileName The name of the asset to open.  This name can be hierarchical.
     * @return An open AssetFileDescriptor.
     */
    public @NonNull AssetFileDescriptor openFd(@NonNull String fileName) throws IOException {
        Objects.requireNonNull(fileName, "fileName");
        synchronized (this) {
            ensureOpenLocked();
            final ParcelFileDescriptor pfd = nativeOpenAssetFd(mObject, fileName, mOffsets);
            if (pfd == null) {
                throw new FileNotFoundException("Asset file: " + fileName);
            }
            return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
        }
    }

    /**
     * Return a String array of all the assets at the given path.
     * 
     * @param path A relative path within the assets, i.e., "docs/home.html".
     * 
     * @return String[] Array of strings, one for each asset.  These file
     *         names are relative to 'path'.  You can open the file by
     *         concatenating 'path' and a name in the returned string (via
     *         File) and passing that to open().
     * 
     * @see #open
     */
    public @Nullable String[] list(@NonNull String path) throws IOException {
        Objects.requireNonNull(path, "path");
        synchronized (this) {
            ensureValidLocked();
            return nativeList(mObject, path);
        }
    }

    /**
     * Open a non-asset file as an asset using ACCESS_STREAMING mode.  This
     * provides direct access to all of the files included in an application
     * package (not only its assets).  Applications should not normally use
     * this.
     *
     * @param fileName Name of the asset to retrieve.
     *
     * @see #open(String)
     * @hide
     */
    @UnsupportedAppUsage
    public @NonNull InputStream openNonAsset(@NonNull String fileName) throws IOException {
        return openNonAsset(0, fileName, ACCESS_STREAMING);
    }

    /**
     * Open a non-asset file as an asset using a specific access mode.  This
     * provides direct access to all of the files included in an application
     * package (not only its assets).  Applications should not normally use
     * this.
     *
     * @param fileName Name of the asset to retrieve.
     * @param accessMode Desired access mode for retrieving the data.
     *
     * @see #ACCESS_UNKNOWN
     * @see #ACCESS_STREAMING
     * @see #ACCESS_RANDOM
     * @see #ACCESS_BUFFER
     * @see #open(String, int)
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public @NonNull InputStream openNonAsset(@NonNull String fileName, int accessMode)
            throws IOException {
        return openNonAsset(0, fileName, accessMode);
    }

    /**
     * Open a non-asset in a specified package.  Not for use by applications.
     *
     * @param cookie Identifier of the package to be opened.
     * @param fileName Name of the asset to retrieve.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName)
            throws IOException {
        return openNonAsset(cookie, fileName, ACCESS_STREAMING);
    }

    /**
     * Open a non-asset in a specified package.  Not for use by applications.
     *
     * @param cookie Identifier of the package to be opened.
     * @param fileName Name of the asset to retrieve.
     * @param accessMode Desired access mode for retrieving the data.
     * @hide
     */
    @UnsupportedAppUsage
    public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName, int accessMode)
            throws IOException {
        Objects.requireNonNull(fileName, "fileName");
        synchronized (this) {
            ensureOpenLocked();
            final long asset = nativeOpenNonAsset(mObject, cookie, fileName, accessMode);
            if (asset == 0) {
                throw new FileNotFoundException("Asset absolute file: " + fileName);
            }
            final AssetInputStream assetInputStream = new AssetInputStream(asset);
            incRefsLocked(assetInputStream.hashCode());
            return assetInputStream;
        }
    }

    /**
     * Open a non-asset as an asset by mmapping it and returning an {@link AssetFileDescriptor}.
     * This provides direct access to all of the files included in an application
     * package (not only its assets).  Applications should not normally use this.
     *
     * The asset must not be compressed, or an exception will be thrown.
     *
     * @param fileName Name of the asset to retrieve.
     */
    public @NonNull AssetFileDescriptor openNonAssetFd(@NonNull String fileName)
            throws IOException {
        return openNonAssetFd(0, fileName);
    }

    /**
     * Open a non-asset as an asset by mmapping it and returning an {@link AssetFileDescriptor}.
     * This provides direct access to all of the files included in an application
     * package (not only its assets).  Applications should not normally use this.
     *
     * The asset must not be compressed, or an exception will be thrown.
     *
     * @param cookie Identifier of the package to be opened.
     * @param fileName Name of the asset to retrieve.
     */
    public @NonNull AssetFileDescriptor openNonAssetFd(int cookie, @NonNull String fileName)
            throws IOException {
        Objects.requireNonNull(fileName, "fileName");
        synchronized (this) {
            ensureOpenLocked();
            final ParcelFileDescriptor pfd =
                    nativeOpenNonAssetFd(mObject, cookie, fileName, mOffsets);
            if (pfd == null) {
                throw new FileNotFoundException("Asset absolute file: " + fileName);
            }
            return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
        }
    }
    
    /**
     * Retrieve a parser for a compiled XML file.
     * 
     * @param fileName The name of the file to retrieve.
     */
    public @NonNull XmlResourceParser openXmlResourceParser(@NonNull String fileName)
            throws IOException {
        return openXmlResourceParser(0, fileName);
    }
    
    /**
     * Retrieve a parser for a compiled XML file.
     * 
     * @param cookie Identifier of the package to be opened.
     * @param fileName The name of the file to retrieve.
     */
    public @NonNull XmlResourceParser openXmlResourceParser(int cookie, @NonNull String fileName)
            throws IOException {
        try (XmlBlock block = openXmlBlockAsset(cookie, fileName)) {
            XmlResourceParser parser = block.newParser();
            // If openXmlBlockAsset doesn't throw, it will always return an XmlBlock object with
            // a valid native pointer, which makes newParser always return non-null. But let's
            // be careful.
            if (parser == null) {
                throw new AssertionError("block.newParser() returned a null parser");
            }
            return parser;
        }
    }

    /**
     * Retrieve a non-asset as a compiled XML file.  Not for use by applications.
     * 
     * @param fileName The name of the file to retrieve.
     * @hide
     */
    @NonNull XmlBlock openXmlBlockAsset(@NonNull String fileName) throws IOException {
        return openXmlBlockAsset(0, fileName);
    }

    /**
     * Retrieve a non-asset as a compiled XML file.  Not for use by
     * applications.
     * 
     * @param cookie Identifier of the package to be opened.
     * @param fileName Name of the asset to retrieve.
     * @hide
     */
    @NonNull XmlBlock openXmlBlockAsset(int cookie, @NonNull String fileName) throws IOException {
        Objects.requireNonNull(fileName, "fileName");
        synchronized (this) {
            ensureOpenLocked();

            final long xmlBlock = nativeOpenXmlAsset(mObject, cookie, fileName);
            if (xmlBlock == 0) {
                throw new FileNotFoundException("Asset XML file: " + fileName);
            }
            final XmlBlock block = new XmlBlock(this, xmlBlock);
            incRefsLocked(block.hashCode());
            return block;
        }
    }

    void xmlBlockGone(int id) {
        synchronized (this) {
            decRefsLocked(id);
        }
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    void applyStyle(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
            @Nullable XmlBlock.Parser parser, @NonNull int[] inAttrs, long outValuesAddress,
            long outIndicesAddress) {
        Objects.requireNonNull(inAttrs, "inAttrs");
        synchronized (this) {
            // Need to synchronize on AssetManager because we will be accessing
            // the native implementation of AssetManager.
            ensureValidLocked();
            nativeApplyStyle(mObject, themePtr, defStyleAttr, defStyleRes,
                    parser != null ? parser.mParseState : 0, inAttrs, outValuesAddress,
                    outIndicesAddress);
        }
    }

    int[] getAttributeResolutionStack(long themePtr, @AttrRes int defStyleAttr,
            @StyleRes int defStyleRes, @StyleRes int xmlStyle) {
        synchronized (this) {
            return nativeAttributeResolutionStack(
                    mObject, themePtr, xmlStyle, defStyleAttr, defStyleRes);
        }
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    boolean resolveAttrs(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
            @Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues,
            @NonNull int[] outIndices) {
        Objects.requireNonNull(inAttrs, "inAttrs");
        Objects.requireNonNull(outValues, "outValues");
        Objects.requireNonNull(outIndices, "outIndices");
        synchronized (this) {
            // Need to synchronize on AssetManager because we will be accessing
            // the native implementation of AssetManager.
            ensureValidLocked();
            return nativeResolveAttrs(mObject,
                    themePtr, defStyleAttr, defStyleRes, inValues, inAttrs, outValues, outIndices);
        }
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    boolean retrieveAttributes(@NonNull XmlBlock.Parser parser, @NonNull int[] inAttrs,
            @NonNull int[] outValues, @NonNull int[] outIndices) {
        Objects.requireNonNull(parser, "parser");
        Objects.requireNonNull(inAttrs, "inAttrs");
        Objects.requireNonNull(outValues, "outValues");
        Objects.requireNonNull(outIndices, "outIndices");
        synchronized (this) {
            // Need to synchronize on AssetManager because we will be accessing
            // the native implementation of AssetManager.
            ensureValidLocked();
            return nativeRetrieveAttributes(
                    mObject, parser.mParseState, inAttrs, outValues, outIndices);
        }
    }

    @UnsupportedAppUsage
    long createTheme() {
        synchronized (this) {
            ensureValidLocked();
            long themePtr = nativeThemeCreate(mObject);
            incRefsLocked(themePtr);
            return themePtr;
        }
    }

    void releaseTheme(long themePtr) {
        synchronized (this) {
            decRefsLocked(themePtr);
        }
    }

    static long getThemeFreeFunction() {
        return nativeGetThemeFreeFunction();
    }

    void applyStyleToTheme(long themePtr, @StyleRes int resId, boolean force) {
        synchronized (this) {
            // Need to synchronize on AssetManager because we will be accessing
            // the native implementation of AssetManager.
            ensureValidLocked();
            nativeThemeApplyStyle(mObject, themePtr, resId, force);
        }
    }

    AssetManager rebaseTheme(long themePtr, @NonNull AssetManager newAssetManager,
            @StyleRes int[] styleIds, @StyleRes boolean[] force, int count) {
        // Exchange ownership of the theme with the new asset manager.
        if (this != newAssetManager) {
            synchronized (this) {
                ensureValidLocked();
                decRefsLocked(themePtr);
            }
            synchronized (newAssetManager) {
                newAssetManager.ensureValidLocked();
                newAssetManager.incRefsLocked(themePtr);
            }
        }

        try {
            synchronized (newAssetManager) {
                newAssetManager.ensureValidLocked();
                nativeThemeRebase(newAssetManager.mObject, themePtr, styleIds, force, count);
            }
        } finally {
            Reference.reachabilityFence(newAssetManager);
        }
        return newAssetManager;
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    void setThemeTo(long dstThemePtr, @NonNull AssetManager srcAssetManager, long srcThemePtr) {
        synchronized (this) {
            ensureValidLocked();
            synchronized (srcAssetManager) {
                srcAssetManager.ensureValidLocked();
                nativeThemeCopy(mObject, dstThemePtr, srcAssetManager.mObject, srcThemePtr);
            }
        }
    }

    @Override
    protected void finalize() throws Throwable {
        if (DEBUG_REFS && mNumRefs != 0) {
            Log.w(TAG, "AssetManager " + this + " finalized with non-zero refs: " + mNumRefs);
            if (mRefStacks != null) {
                for (RuntimeException e : mRefStacks.values()) {
                    Log.w(TAG, "Reference from here", e);
                }
            }
        }

        synchronized (this) {
            if (mObject != 0) {
                nativeDestroy(mObject);
                mObject = 0;
            }
        }
    }

    /* No Locking is needed for AssetInputStream because an AssetInputStream is not-thread
    safe and it does not rely on AssetManager once it has been created. It completely owns the
    underlying Asset. */
    public final class AssetInputStream extends InputStream {
        private long mAssetNativePtr;
        private long mLength;
        private long mMarkPos;

        /**
         * @hide
         */
        @UnsupportedAppUsage
        public final int getAssetInt() {
            throw new UnsupportedOperationException();
        }

        /**
         * @hide
         */
        @UnsupportedAppUsage
        public final long getNativeAsset() {
            return mAssetNativePtr;
        }

        private AssetInputStream(long assetNativePtr) {
            mAssetNativePtr = assetNativePtr;
            mLength = nativeAssetGetLength(assetNativePtr);
        }

        @Override
        public final int read() throws IOException {
            ensureOpen();
            return nativeAssetReadChar(mAssetNativePtr);
        }

        @Override
        public final int read(@NonNull byte[] b) throws IOException {
            ensureOpen();
            Objects.requireNonNull(b, "b");
            return nativeAssetRead(mAssetNativePtr, b, 0, b.length);
        }

        @Override
        public final int read(@NonNull byte[] b, int off, int len) throws IOException {
            ensureOpen();
            Objects.requireNonNull(b, "b");
            return nativeAssetRead(mAssetNativePtr, b, off, len);
        }

        @Override
        public final long skip(long n) throws IOException {
            ensureOpen();
            long pos = nativeAssetSeek(mAssetNativePtr, 0, 0);
            if ((pos + n) > mLength) {
                n = mLength - pos;
            }
            if (n > 0) {
                nativeAssetSeek(mAssetNativePtr, n, 0);
            }
            return n;
        }

        @Override
        public final int available() throws IOException {
            ensureOpen();
            final long len = nativeAssetGetRemainingLength(mAssetNativePtr);
            return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) len;
        }

        @Override
        public final boolean markSupported() {
            return true;
        }

        @Override
        public final void mark(int readlimit) {
            ensureOpen();
            mMarkPos = nativeAssetSeek(mAssetNativePtr, 0, 0);
        }

        @Override
        public final void reset() throws IOException {
            ensureOpen();
            nativeAssetSeek(mAssetNativePtr, mMarkPos, -1);
        }

        @Override
        public final void close() throws IOException {
            if (mAssetNativePtr != 0) {
                nativeAssetDestroy(mAssetNativePtr);
                mAssetNativePtr = 0;

                synchronized (AssetManager.this) {
                    decRefsLocked(hashCode());
                }
            }
        }

        @Override
        protected void finalize() throws Throwable {
            close();
        }

        private void ensureOpen() {
            if (mAssetNativePtr == 0) {
                throw new IllegalStateException("AssetInputStream is closed");
            }
        }
    }

    /**
     * Determine whether the state in this asset manager is up-to-date with
     * the files on the filesystem.  If false is returned, you need to
     * instantiate a new AssetManager class to see the new data.
     * @hide
     */
    @UnsupportedAppUsage
    public boolean isUpToDate() {
        synchronized (this) {
            if (!mOpen) {
                return false;
            }

            for (ApkAssets apkAssets : mApkAssets) {
                if (!apkAssets.isUpToDate()) {
                    return false;
                }
            }

            return true;
        }
    }

    /**
     * Get the locales that this asset manager contains data for.
     *
     * <p>On SDK 21 (Android 5.0: Lollipop) and above, Locale strings are valid
     * <a href="https://tools.ietf.org/html/bcp47">BCP-47</a> language tags and can be
     * parsed using {@link Locale#forLanguageTag(String)}.
     *
     * <p>On SDK 20 (Android 4.4W: Kitkat for watches) and below, locale strings
     * are of the form {@code ll_CC} where {@code ll} is a two letter language code,
     * and {@code CC} is a two letter country code.
     */
    public String[] getLocales() {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetLocales(mObject, false /*excludeSystem*/);
        }
    }

    /**
     * Same as getLocales(), except that locales that are only provided by the system (i.e. those
     * present in framework-res.apk or its overlays) will not be listed.
     *
     * For example, if the "system" assets support English, French, and German, and the additional
     * assets support Cherokee and French, getLocales() would return
     * [Cherokee, English, French, German], while getNonSystemLocales() would return
     * [Cherokee, French].
     * @hide
     */
    public String[] getNonSystemLocales() {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetLocales(mObject, true /*excludeSystem*/);
        }
    }

    /**
     * @hide
     */
    Configuration[] getSizeConfigurations() {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetSizeConfigurations(mObject);
        }
    }

    /**
     * @hide
     */
    Configuration[] getSizeAndUiModeConfigurations() {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetSizeAndUiModeConfigurations(mObject);
        }
    }

    /**
     * Change the configuration used when retrieving resources.  Not for use by
     * applications.
     * @hide
     */
    @UnsupportedAppUsage
    public void setConfiguration(int mcc, int mnc, @Nullable String locale, int orientation,
            int touchscreen, int density, int keyboard, int keyboardHidden, int navigation,
            int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp,
            int screenHeightDp, int screenLayout, int uiMode, int colorMode, int majorVersion) {
        synchronized (this) {
            ensureValidLocked();
            nativeSetConfiguration(mObject, mcc, mnc, locale, orientation, touchscreen, density,
                    keyboard, keyboardHidden, navigation, screenWidth, screenHeight,
                    smallestScreenWidthDp, screenWidthDp, screenHeightDp, screenLayout, uiMode,
                    colorMode, majorVersion);
        }
    }

    /**
     * @hide
     */
    @UnsupportedAppUsage
    public SparseArray<String> getAssignedPackageIdentifiers() {
        return getAssignedPackageIdentifiers(true, true);
    }

    /**
     * @hide
     */
    public SparseArray<String> getAssignedPackageIdentifiers(boolean includeOverlays,
            boolean includeLoaders) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetAssignedPackageIdentifiers(mObject, includeOverlays, includeLoaders);
        }
    }

    /**
     * @hide
     */
    @GuardedBy("this")
    public @Nullable Map<String, String> getOverlayableMap(String packageName) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetOverlayableMap(mObject, packageName);
        }
    }

    /**
     * @hide
     */
    @TestApi
    @GuardedBy("this")
    public @Nullable String getOverlayablesToString(String packageName) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetOverlayablesToString(mObject, packageName);
        }
    }

    @GuardedBy("this")
    private void incRefsLocked(long id) {
        if (DEBUG_REFS) {
            if (mRefStacks == null) {
                mRefStacks = new HashMap<>();
            }
            RuntimeException ex = new RuntimeException();
            ex.fillInStackTrace();
            mRefStacks.put(id, ex);
        }
        mNumRefs++;
    }

    @GuardedBy("this")
    private void decRefsLocked(long id) {
        if (DEBUG_REFS && mRefStacks != null) {
            mRefStacks.remove(id);
        }
        mNumRefs--;
        if (mNumRefs == 0 && mObject != 0) {
            nativeDestroy(mObject);
            mObject = 0;
            mApkAssets = sEmptyApkAssets;
        }
    }

    synchronized void dump(PrintWriter pw, String prefix) {
        pw.println(prefix + "class=" + getClass());
        pw.println(prefix + "apkAssets=");
        for (int i = 0; i < mApkAssets.length; i++) {
            pw.println(prefix + i);
            mApkAssets[i].dump(pw, prefix + "  ");
        }
    }

    // AssetManager setup native methods.
    private static native long nativeCreate();
    private static native void nativeDestroy(long ptr);
    private static native void nativeSetApkAssets(long ptr, @NonNull ApkAssets[] apkAssets,
            boolean invalidateCaches);
    private static native void nativeSetConfiguration(long ptr, int mcc, int mnc,
            @Nullable String locale, int orientation, int touchscreen, int density, int keyboard,
            int keyboardHidden, int navigation, int screenWidth, int screenHeight,
            int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout,
            int uiMode, int colorMode, int majorVersion);
    private static native @NonNull SparseArray<String> nativeGetAssignedPackageIdentifiers(
            long ptr, boolean includeOverlays, boolean includeLoaders);

    // File native methods.
    private static native boolean nativeContainsAllocatedTable(long ptr);
    private static native @Nullable String[] nativeList(long ptr, @NonNull String path)
            throws IOException;
    private static native long nativeOpenAsset(long ptr, @NonNull String fileName, int accessMode);
    private static native @Nullable ParcelFileDescriptor nativeOpenAssetFd(long ptr,
            @NonNull String fileName, long[] outOffsets) throws IOException;
    private static native long nativeOpenNonAsset(long ptr, int cookie, @NonNull String fileName,
            int accessMode);
    private static native @Nullable ParcelFileDescriptor nativeOpenNonAssetFd(long ptr, int cookie,
            @NonNull String fileName, @NonNull long[] outOffsets) throws IOException;
    private static native long nativeOpenXmlAsset(long ptr, int cookie, @NonNull String fileName);
    private static native long nativeOpenXmlAssetFd(long ptr, int cookie,
            @NonNull FileDescriptor fileDescriptor);

    // Primitive resource native methods.
    private static native int nativeGetResourceValue(long ptr, @AnyRes int resId, short density,
            @NonNull TypedValue outValue, boolean resolveReferences);
    private static native int nativeGetResourceBagValue(long ptr, @AnyRes int resId, int bagEntryId,
            @NonNull TypedValue outValue);

    private static native @Nullable @AttrRes int[] nativeGetStyleAttributes(long ptr,
            @StyleRes int resId);
    private static native @Nullable String[] nativeGetResourceStringArray(long ptr,
            @ArrayRes int resId);
    private static native @Nullable int[] nativeGetResourceStringArrayInfo(long ptr,
            @ArrayRes int resId);
    private static native @Nullable int[] nativeGetResourceIntArray(long ptr, @ArrayRes int resId);
    private static native int nativeGetResourceArraySize(long ptr, @ArrayRes int resId);
    private static native int nativeGetResourceArray(long ptr, @ArrayRes int resId,
            @NonNull int[] outValues);

    // Resource name/ID native methods.
    private static native @AnyRes int nativeGetResourceIdentifier(long ptr, @NonNull String name,
            @Nullable String defType, @Nullable String defPackage);
    private static native @Nullable String nativeGetResourceName(long ptr, @AnyRes int resid);
    private static native @Nullable String nativeGetResourcePackageName(long ptr,
            @AnyRes int resid);
    private static native @Nullable String nativeGetResourceTypeName(long ptr, @AnyRes int resid);
    private static native @Nullable String nativeGetResourceEntryName(long ptr, @AnyRes int resid);
    private static native @Nullable String[] nativeGetLocales(long ptr, boolean excludeSystem);
    private static native @Nullable Configuration[] nativeGetSizeConfigurations(long ptr);
    private static native @Nullable Configuration[] nativeGetSizeAndUiModeConfigurations(long ptr);
    private static native void nativeSetResourceResolutionLoggingEnabled(long ptr, boolean enabled);
    private static native @Nullable String nativeGetLastResourceResolution(long ptr);

    // Style attribute retrieval native methods.
    private static native int[] nativeAttributeResolutionStack(long ptr, long themePtr,
            @StyleRes int xmlStyleRes, @AttrRes int defStyleAttr, @StyleRes int defStyleRes);
    private static native void nativeApplyStyle(long ptr, long themePtr, @AttrRes int defStyleAttr,
            @StyleRes int defStyleRes, long xmlParserPtr, @NonNull int[] inAttrs,
            long outValuesAddress, long outIndicesAddress);
    private static native boolean nativeResolveAttrs(long ptr, long themePtr,
            @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @Nullable int[] inValues,
            @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices);
    private static native boolean nativeRetrieveAttributes(long ptr, long xmlParserPtr,
            @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices);

    // Theme related native methods
    private static native long nativeThemeCreate(long ptr);
    private static native long nativeGetThemeFreeFunction();
    private static native void nativeThemeApplyStyle(long ptr, long themePtr, @StyleRes int resId,
            boolean force);
    private static native void nativeThemeRebase(long ptr, long themePtr, @NonNull int[] styleIds,
            @NonNull boolean[] force, int styleSize);
    private static native void nativeThemeCopy(long dstAssetManagerPtr, long dstThemePtr,
            long srcAssetManagerPtr, long srcThemePtr);
    private static native int nativeThemeGetAttributeValue(long ptr, long themePtr,
            @AttrRes int resId, @NonNull TypedValue outValue, boolean resolve);
    private static native void nativeThemeDump(long ptr, long themePtr, int priority, String tag,
            String prefix);
    static native @NativeConfig int nativeThemeGetChangingConfigurations(long themePtr);
    @StyleRes
    private static native int nativeGetParentThemeIdentifier(long ptr, @StyleRes int styleId);

    // AssetInputStream related native methods.
    private static native void nativeAssetDestroy(long assetPtr);
    private static native int nativeAssetReadChar(long assetPtr);
    private static native int nativeAssetRead(long assetPtr, byte[] b, int off, int len);
    private static native long nativeAssetSeek(long assetPtr, long offset, int whence);
    private static native long nativeAssetGetLength(long assetPtr);
    private static native long nativeAssetGetRemainingLength(long assetPtr);

    private static native @Nullable Map nativeGetOverlayableMap(long ptr,
            @NonNull String packageName);
    private static native @Nullable String nativeGetOverlayablesToString(long ptr,
            @NonNull String packageName);

    // Global debug native methods.
    /**
     * @hide
     */
    @UnsupportedAppUsage
    public static native int getGlobalAssetCount();

    /**
     * @hide
     */
    public static native String getAssetAllocations();

    /**
     * @hide
     */
    @UnsupportedAppUsage
    public static native int getGlobalAssetManagerCount();
}
