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

Commit 7a3d82a5 authored by Winson's avatar Winson Committed by Winson Chiu
Browse files

Close ApkAssets in PackageParser

Immediately closes ApkAssets to free up some memory during package
parsing/install process.

This is used instead of implementing AutoCloseable because of
complexities with AssetManager and tracking assets opened
outside of the ApkAssets.java class.

Explained more in b/72056911.

Test: manually booted emulator; closing ApkAssets is used at
boot in PackageParser#parseApkLiteInner
Test: adb install test.apk && sleep 5 && adb uninstall test.package
&& sleep 1 && (adb shell lsof | grep "test.package") prints no
system_server references

Bug: 130182148

Change-Id: Ia471d7065e65bd39b535309de6c6da7ec35bdf12
parent 329a9b0b
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -1580,8 +1580,8 @@ public class PackageParser {
        final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();

        XmlResourceParser parser = null;
        ApkAssets apkAssets = null;
        try {
            final ApkAssets apkAssets;
            try {
                apkAssets = fd != null
                        ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
@@ -1618,7 +1618,13 @@ public class PackageParser {
                    "Failed to parse " + apkPath, e);
        } finally {
            IoUtils.closeQuietly(parser);
            // TODO(b/72056911): Implement and call close() on ApkAssets.
            if (apkAssets != null) {
                try {
                    apkAssets.close();
                } catch (Throwable ignored) {
                }
            }
            // TODO(b/72056911): Implement AutoCloseable on ApkAssets.
        }
    }

+17 −2
Original line number Diff line number Diff line
@@ -36,7 +36,9 @@ import java.io.IOException;
 */
public final class ApkAssets {
    @GuardedBy("this") private final long mNativePtr;
    @GuardedBy("this") private StringBlock mStringBlock;
    @GuardedBy("this") private final StringBlock mStringBlock;

    @GuardedBy("this") private boolean mOpen = true;

    /**
     * Creates a new ApkAssets instance from the given path on disk.
@@ -180,8 +182,21 @@ public final class ApkAssets {

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

    /**
     * Closes this class and the contained {@link #mStringBlock}.
     */
    public void close() throws Throwable {
        synchronized (this) {
            if (mOpen) {
                mOpen = false;
                mStringBlock.close();
                nativeDestroy(mNativePtr);
            }
        }
    }

    private static native long nativeLoad(
            @NonNull String path, boolean system, boolean forceSharedLib, boolean overlay)
+42 −6
Original line number Diff line number Diff line
@@ -18,13 +18,34 @@ package android.content.res;

import android.annotation.UnsupportedAppUsage;
import android.graphics.Color;
import android.text.*;
import android.text.style.*;
import android.util.Log;
import android.util.SparseArray;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.text.Annotation;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannedString;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.BackgroundColorSpan;
import android.text.style.BulletSpan;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.LineHeightSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.TextAppearanceSpan;
import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;

import java.util.Arrays;

@@ -40,8 +61,12 @@ final class StringBlock {
    private final long mNative;
    private final boolean mUseSparse;
    private final boolean mOwnsNative;

    private CharSequence[] mStrings;
    private SparseArray<CharSequence> mSparseStrings;

    @GuardedBy("this") private boolean mOpen = true;

    StyleIDs mStyleIDs = null;

    public StringBlock(byte[] data, boolean useSparse) {
@@ -141,15 +166,26 @@ final class StringBlock {
        }
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            super.finalize();
        } finally {
            close();
        }
    }

    public void close() throws Throwable {
        synchronized (this) {
            if (mOpen) {
                mOpen = false;

                if (mOwnsNative) {
                    nativeDestroy(mNative);
                }
            }
        }
    }

    static final class StyleIDs {
        private int boldId = -1;