Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7d01dd7 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

Revert "Replace AssetManager with AssetManager2 implementation"

This reverts commit dcb3c655.

Bug:72511998
Change-Id: I665966ca109f66f85d8665db388c71ea2303c3b8
parent 646265cb
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -54,7 +54,6 @@ 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;
@@ -1595,19 +1594,21 @@ public class PackageParser {
            int flags) throws PackageParserException {
        final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();

        ApkAssets apkAssets = null;
        AssetManager assets = null;
        XmlResourceParser parser = null;
        try {
            try {
                apkAssets = fd != null
                        ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
                        : ApkAssets.loadFromPath(apkPath);
            } catch (IOException e) {
            assets = newConfiguredAssetManager();
            int cookie = fd != null
                    ? assets.addAssetFd(fd, debugPathName) : assets.addAssetPath(apkPath);
            if (cookie == 0) {
                throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
                        "Failed to parse " + apkPath);
            }

            parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
            final DisplayMetrics metrics = new DisplayMetrics();
            metrics.setToDefaults();

            parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);

            final SigningDetails signingDetails;
            if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
@@ -1634,7 +1635,7 @@ public class PackageParser {
                    "Failed to parse " + apkPath, e);
        } finally {
            IoUtils.closeQuietly(parser);
            IoUtils.closeQuietly(apkAssets);
            IoUtils.closeQuietly(assets);
        }
    }

+0 −221
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;
}
+501 −820

File changed.

Preview size limit exceeded, changes collapsed.

+5 −4
Original line number Diff line number Diff line
@@ -590,7 +590,7 @@ public class Resources {
     */
    @NonNull
    public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
        int[] res = mResourcesImpl.getAssets().getResourceIntArray(id);
        int[] res = mResourcesImpl.getAssets().getArrayIntResource(id);
        if (res != null) {
            return res;
        }
@@ -613,13 +613,13 @@ public class Resources {
    @NonNull
    public TypedArray obtainTypedArray(@ArrayRes int id) throws NotFoundException {
        final ResourcesImpl impl = mResourcesImpl;
        int len = impl.getAssets().getResourceArraySize(id);
        int len = impl.getAssets().getArraySize(id);
        if (len < 0) {
            throw new NotFoundException("Array resource ID #0x" + Integer.toHexString(id));
        }
        
        TypedArray array = TypedArray.obtain(this, len);
        array.mLength = impl.getAssets().getResourceArray(id, array.mData);
        array.mLength = impl.getAssets().retrieveArray(id, array.mData);
        array.mIndices[0] = 0;
        
        return array;
@@ -1789,7 +1789,8 @@ public class Resources {
        // out the attributes from the XML file (applying type information
        // contained in the resources and such).
        XmlBlock.Parser parser = (XmlBlock.Parser)set;
        mResourcesImpl.getAssets().retrieveAttributes(parser, attrs, array.mData, array.mIndices);
        mResourcesImpl.getAssets().retrieveAttributes(parser.mParseState, attrs,
                array.mData, array.mIndices);

        array.mXml = parser;

+13 −9
Original line number Diff line number Diff line
@@ -168,6 +168,7 @@ public class ResourcesImpl {
        mDisplayAdjustments = displayAdjustments;
        mConfiguration.setToDefaults();
        updateConfiguration(config, metrics, displayAdjustments.getCompatibilityInfo());
        mAssets.ensureStringBlocks();
    }

    public DisplayAdjustments getDisplayAdjustments() {
@@ -1273,7 +1274,8 @@ public class ResourcesImpl {

        void applyStyle(int resId, boolean force) {
            synchronized (mKey) {
                mAssets.applyStyleToTheme(mTheme, resId, force);
                AssetManager.applyThemeStyle(mTheme, resId, force);

                mThemeResId = resId;
                mKey.append(resId, force);
            }
@@ -1282,7 +1284,7 @@ public class ResourcesImpl {
        void setTo(ThemeImpl other) {
            synchronized (mKey) {
                synchronized (other.mKey) {
                    AssetManager.nativeThemeCopy(mTheme, other.mTheme);
                    AssetManager.copyTheme(mTheme, other.mTheme);

                    mThemeResId = other.mThemeResId;
                    mKey.setTo(other.getKey());
@@ -1305,10 +1307,12 @@ public class ResourcesImpl {
                // out the attributes from the XML file (applying type information
                // contained in the resources and such).
                final XmlBlock.Parser parser = (XmlBlock.Parser) set;
                mAssets.applyStyle(mTheme, defStyleAttr, defStyleRes, parser, attrs,
                        array.mDataAddress, array.mIndicesAddress);
                AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
                        parser != null ? parser.mParseState : 0,
                        attrs, attrs.length, array.mDataAddress, array.mIndicesAddress);
                array.mTheme = wrapper;
                array.mXml = parser;

                return array;
            }
        }
@@ -1325,7 +1329,7 @@ public class ResourcesImpl {
                }

                final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
                mAssets.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
                AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
                array.mTheme = wrapper;
                array.mXml = null;
                return array;
@@ -1345,14 +1349,14 @@ public class ResourcesImpl {
        @Config int getChangingConfigurations() {
            synchronized (mKey) {
                final @NativeConfig int nativeChangingConfig =
                        AssetManager.nativeThemeGetChangingConfigurations(mTheme);
                        AssetManager.getThemeChangingConfigurations(mTheme);
                return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
            }
        }

        public void dump(int priority, String tag, String prefix) {
            synchronized (mKey) {
                mAssets.dumpTheme(mTheme, priority, tag, prefix);
                AssetManager.dumpTheme(mTheme, priority, tag, prefix);
            }
        }

@@ -1381,13 +1385,13 @@ public class ResourcesImpl {
         */
        void rebase() {
            synchronized (mKey) {
                AssetManager.nativeThemeClear(mTheme);
                AssetManager.clearTheme(mTheme);

                // Reapply the same styles in the same order.
                for (int i = 0; i < mKey.mCount; i++) {
                    final int resId = mKey.mResId[i];
                    final boolean force = mKey.mForce[i];
                    mAssets.applyStyleToTheme(mTheme, resId, force);
                    AssetManager.applyThemeStyle(mTheme, resId, force);
                }
            }
        }
Loading