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

Commit f02954cc authored by Jeff Sharkey's avatar Jeff Sharkey Committed by android-build-merger
Browse files

Merge "Release AssetManagers when ejecting storage." into nyc-dev

am: 380f3b12

* commit '380f3b12':
  Release AssetManagers when ejecting storage.

Change-Id: I54282cfcf53279f87e66cc1263ae9663fe94bc04
parents 60585d12 380f3b12
Loading
Loading
Loading
Loading
+25 −3
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import android.content.res.ResourcesImpl;
import android.content.res.ResourcesKey;
import android.hardware.display.DisplayManagerGlobal;
import android.os.IBinder;
import android.os.LocaleList;
import android.os.Trace;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
@@ -38,13 +37,12 @@ import android.util.Pair;
import android.util.Slog;
import android.view.Display;
import android.view.DisplayAdjustments;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import java.util.WeakHashMap;
import java.util.function.Predicate;
@@ -120,6 +118,30 @@ public class ResourcesManager {
        }
    }

    /**
     * Invalidate and destroy any resources that reference content under the
     * given filesystem path. Typically used when unmounting a storage device to
     * try as hard as possible to release any open FDs.
     */
    public void invalidatePath(String path) {
        synchronized (this) {
            int count = 0;
            for (int i = 0; i < mResourceImpls.size();) {
                final ResourcesKey key = mResourceImpls.keyAt(i);
                if (key.isPathReferenced(path)) {
                    final ResourcesImpl res = mResourceImpls.removeAt(i).get();
                    if (res != null) {
                        res.flushLayoutCache();
                    }
                    count++;
                } else {
                    i++;
                }
            }
            Log.i(TAG, "Invalidated " + count + " asset managers that referenced " + path);
        }
    }

    public Configuration getConfiguration() {
        synchronized (this) {
            return mResConfiguration;
+20 −0
Original line number Diff line number Diff line
@@ -77,6 +77,26 @@ public final class ResourcesKey {
        return !Configuration.EMPTY.equals(mOverrideConfiguration);
    }

    public boolean isPathReferenced(String path) {
        if (mResDir != null && mResDir.startsWith(path)) {
            return true;
        } else {
            return anyStartsWith(mSplitResDirs, path) || anyStartsWith(mOverlayDirs, path)
                    || anyStartsWith(mLibDirs, path);
        }
    }

    private static boolean anyStartsWith(String[] list, String prefix) {
        if (list != null) {
            for (String s : list) {
                if (s != null && s.startsWith(prefix)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public int hashCode() {
        return mHash;
+40 −16
Original line number Diff line number Diff line
@@ -24,10 +24,12 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.SparseArray;

import java.util.HashMap;
import java.util.WeakHashMap;
import com.android.internal.annotations.GuardedBy;

import java.lang.ref.WeakReference;

/**
 * TODO: This should be better integrated into the system so it doesn't need
@@ -37,14 +39,15 @@ public final class AttributeCache {
    private static AttributeCache sInstance = null;

    private final Context mContext;
    private final WeakHashMap<String, Package> mPackages =
            new WeakHashMap<String, Package>();

    @GuardedBy("this")
    private final ArrayMap<String, WeakReference<Package>> mPackages = new ArrayMap<>();
    @GuardedBy("this")
    private final Configuration mConfiguration = new Configuration();

    public final static class Package {
        public final Context context;
        private final SparseArray<HashMap<int[], Entry>> mMap
                = new SparseArray<HashMap<int[], Entry>>();
        private final SparseArray<ArrayMap<int[], Entry>> mMap = new SparseArray<>();

        public Package(Context c) {
            context = c;
@@ -59,6 +62,12 @@ public final class AttributeCache {
            context = c;
            array = ta;
        }

        void recycle() {
            if (array != null) {
                array.recycle();
            }
        }
    }
    
    public static void init(Context context) {
@@ -77,7 +86,21 @@ public final class AttributeCache {

    public void removePackage(String packageName) {
        synchronized (this) {
            mPackages.remove(packageName);
            final WeakReference<Package> ref = mPackages.remove(packageName);
            final Package pkg = (ref != null) ? ref.get() : null;
            if (pkg != null) {
                if (pkg.mMap != null) {
                    for (int i = 0; i < pkg.mMap.size(); i++) {
                        final ArrayMap<int[], Entry> map = pkg.mMap.valueAt(i);
                        for (int j = 0; j < map.size(); j++) {
                            map.valueAt(j).recycle();
                        }
                    }
                }

                final Resources res = pkg.context.getResources();
                res.flushLayoutCache();
            }
        }
    }

@@ -97,8 +120,9 @@ public final class AttributeCache {
    
    public Entry get(String packageName, int resId, int[] styleable, int userId) {
        synchronized (this) {
            Package pkg = mPackages.get(packageName);
            HashMap<int[], Entry> map = null;
            WeakReference<Package> ref = mPackages.get(packageName);
            Package pkg = (ref != null) ? ref.get() : null;
            ArrayMap<int[], Entry> map = null;
            Entry ent = null;
            if (pkg != null) {
                map = pkg.mMap.get(resId);
@@ -120,11 +144,11 @@ public final class AttributeCache {
                    return null;
                }
                pkg = new Package(context);
                mPackages.put(packageName, pkg);
                mPackages.put(packageName, new WeakReference<>(pkg));
            }
            
            if (map == null) {
                map = new HashMap<int[], Entry>();
                map = new ArrayMap<>();
                pkg.mMap.put(resId, map);
            }
            
+16 −0
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.ResourcesManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.IDevicePolicyManager;
import android.app.admin.SecurityLog;
@@ -238,6 +239,7 @@ import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.AttributeCache;
import com.android.server.EventLogTags;
import com.android.server.FgThread;
import com.android.server.IntentResolver;
@@ -19133,6 +19135,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
                        Slog.w(TAG, "Failed to unload " + ps.codePath);
                    }
                }
                // Try very hard to release any references to this package
                // so we don't risk the system server being killed due to
                // open FDs
                AttributeCache.instance().removePackage(ps.name);
            }
            mSettings.writeLPr();
@@ -19141,6 +19148,15 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
        if (DEBUG_INSTALL) Slog.d(TAG, "Unloaded packages " + unloaded);
        sendResourcesChangedBroadcast(false, false, unloaded, null);
        // Try very hard to release any references to this path so we don't risk
        // the system server being killed due to open FDs
        ResourcesManager.getInstance().invalidatePath(vol.getPath().getAbsolutePath());
        for (int i = 0; i < 3; i++) {
            System.gc();
            System.runFinalization();
        }
    }
    /**