From da0b92b1abdd642f642f641c1e636779f123d78d Mon Sep 17 00:00:00 2001 From: Yurii Zubrytskyi Date: Fri, 11 Nov 2022 15:41:23 -0800 Subject: [PATCH] Replace often searched ArrayList with ArraySet ArrayList.contains() is the top function in PackageManager's boot profile for IntenFilter.matchAction(). Replacing the arrays with ArraySets makes those completely disappear. Bug: 237583012 Test: build + boot Change-Id: I659f802be54c5a3f70fd23688bbff1fb5f44cb51 --- core/java/android/content/IntentFilter.java | 31 ++++++++++--------- .../com/android/server/pm/AppsFilterBase.java | 5 ++- .../com/android/server/pm/AppsFilterImpl.java | 28 +++++++++++------ .../android/server/pm/AppsFilterUtils.java | 12 +++---- 4 files changed, 43 insertions(+), 33 deletions(-) diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index b3435b1180c2d..8b6c4dd8497b1 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -28,6 +28,7 @@ import android.os.Parcelable; import android.os.PatternMatcher; import android.text.TextUtils; import android.util.AndroidException; +import android.util.ArraySet; import android.util.Log; import android.util.Printer; import android.util.proto.ProtoOutputStream; @@ -302,7 +303,7 @@ public class IntentFilter implements Parcelable { @UnsupportedAppUsage private int mOrder; @UnsupportedAppUsage - private final ArrayList mActions; + private final ArraySet mActions; private ArrayList mCategories = null; private ArrayList mDataSchemes = null; private ArrayList mDataSchemeSpecificParts = null; @@ -433,7 +434,7 @@ public class IntentFilter implements Parcelable { */ public IntentFilter() { mPriority = 0; - mActions = new ArrayList(); + mActions = new ArraySet<>(); } /** @@ -445,7 +446,7 @@ public class IntentFilter implements Parcelable { */ public IntentFilter(String action) { mPriority = 0; - mActions = new ArrayList(); + mActions = new ArraySet<>(); addAction(action); } @@ -468,7 +469,7 @@ public class IntentFilter implements Parcelable { public IntentFilter(String action, String dataType) throws MalformedMimeTypeException { mPriority = 0; - mActions = new ArrayList(); + mActions = new ArraySet<>(); addAction(action); addDataType(dataType); } @@ -481,7 +482,7 @@ public class IntentFilter implements Parcelable { public IntentFilter(IntentFilter o) { mPriority = o.mPriority; mOrder = o.mOrder; - mActions = new ArrayList(o.mActions); + mActions = new ArraySet<>(o.mActions); if (o.mCategories != null) { mCategories = new ArrayList(o.mCategories); } @@ -742,9 +743,7 @@ public class IntentFilter implements Parcelable { * @param action Name of the action to match, such as Intent.ACTION_VIEW. */ public final void addAction(String action) { - if (!mActions.contains(action)) { - mActions.add(action.intern()); - } + mActions.add(action.intern()); } /** @@ -758,7 +757,7 @@ public class IntentFilter implements Parcelable { * Return an action in the filter. */ public final String getAction(int index) { - return mActions.get(index); + return mActions.valueAt(index); } /** @@ -797,8 +796,11 @@ public class IntentFilter implements Parcelable { if (ignoreActions == null) { return !mActions.isEmpty(); } + if (mActions.size() > ignoreActions.size()) { + return true; // some actions are definitely not ignored + } for (int i = mActions.size() - 1; i >= 0; i--) { - if (!ignoreActions.contains(mActions.get(i))) { + if (!ignoreActions.contains(mActions.valueAt(i))) { return true; } } @@ -1918,7 +1920,7 @@ public class IntentFilter implements Parcelable { int N = countActions(); for (int i=0; i(); - source.readStringList(mActions); + List actions = new ArrayList<>(); + source.readStringList(actions); + mActions = new ArraySet<>(actions); if (source.readInt() != 0) { mCategories = new ArrayList(); source.readStringList(mCategories); diff --git a/services/core/java/com/android/server/pm/AppsFilterBase.java b/services/core/java/com/android/server/pm/AppsFilterBase.java index 3b676c65db753..b4792c65bce54 100644 --- a/services/core/java/com/android/server/pm/AppsFilterBase.java +++ b/services/core/java/com/android/server/pm/AppsFilterBase.java @@ -44,7 +44,6 @@ import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.snapshot.PackageDataSnapshot; import com.android.server.utils.SnapshotCache; import com.android.server.utils.Watched; -import com.android.server.utils.WatchedArrayList; import com.android.server.utils.WatchedArrayMap; import com.android.server.utils.WatchedArraySet; import com.android.server.utils.WatchedSparseBooleanMatrix; @@ -179,9 +178,9 @@ public abstract class AppsFilterBase implements AppsFilterSnapshot { @NonNull @Watched - protected WatchedArrayList mProtectedBroadcasts; + protected WatchedArraySet mProtectedBroadcasts; @NonNull - protected SnapshotCache> mProtectedBroadcastsSnapshot; + protected SnapshotCache> mProtectedBroadcastsSnapshot; /** * This structure maps uid -> uid and indicates whether access from the first should be diff --git a/services/core/java/com/android/server/pm/AppsFilterImpl.java b/services/core/java/com/android/server/pm/AppsFilterImpl.java index 2e67bf2fcdf73..c97711b3aa806 100644 --- a/services/core/java/com/android/server/pm/AppsFilterImpl.java +++ b/services/core/java/com/android/server/pm/AppsFilterImpl.java @@ -73,7 +73,6 @@ import com.android.server.utils.Snappable; import com.android.server.utils.SnapshotCache; import com.android.server.utils.Watchable; import com.android.server.utils.WatchableImpl; -import com.android.server.utils.WatchedArrayList; import com.android.server.utils.WatchedArraySet; import com.android.server.utils.WatchedSparseBooleanMatrix; import com.android.server.utils.WatchedSparseSetArray; @@ -223,7 +222,7 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable, mForceQueryable = new WatchedArraySet<>(); mForceQueryableSnapshot = new SnapshotCache.Auto<>( mForceQueryable, mForceQueryable, "AppsFilter.mForceQueryable"); - mProtectedBroadcasts = new WatchedArrayList<>(); + mProtectedBroadcasts = new WatchedArraySet<>(); mProtectedBroadcastsSnapshot = new SnapshotCache.Auto<>( mProtectedBroadcasts, mProtectedBroadcasts, "AppsFilter.mProtectedBroadcasts"); mPermissionToUids = new HashMap<>(); @@ -573,13 +572,17 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable, return null; } - final boolean protectedBroadcastsChanged; - synchronized (mProtectedBroadcastsLock) { - protectedBroadcastsChanged = - mProtectedBroadcasts.addAll(newPkg.getProtectedBroadcasts()); - } - if (protectedBroadcastsChanged) { - mQueriesViaComponentRequireRecompute.set(true); + final List newBroadcasts = newPkg.getProtectedBroadcasts(); + if (newBroadcasts.size() != 0) { + final boolean protectedBroadcastsChanged; + synchronized (mProtectedBroadcastsLock) { + final int oldSize = mProtectedBroadcasts.size(); + mProtectedBroadcasts.addAll(newBroadcasts); + protectedBroadcastsChanged = mProtectedBroadcasts.size() != oldSize; + } + if (protectedBroadcastsChanged) { + mQueriesViaComponentRequireRecompute.set(true); + } } final boolean newIsForceQueryable; @@ -1149,7 +1152,12 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable, final ArrayList protectedBroadcasts = new ArrayList<>( mProtectedBroadcasts.untrackedStorage()); collectProtectedBroadcasts(settings, removingPackageName); - protectedBroadcastsChanged = !mProtectedBroadcasts.containsAll(protectedBroadcasts); + for (int i = 0; i < protectedBroadcasts.size(); ++i) { + if (!mProtectedBroadcasts.contains(protectedBroadcasts.get(i))) { + protectedBroadcastsChanged = true; + break; + } + } } } diff --git a/services/core/java/com/android/server/pm/AppsFilterUtils.java b/services/core/java/com/android/server/pm/AppsFilterUtils.java index 7daa0b94000c2..483fa8ade150b 100644 --- a/services/core/java/com/android/server/pm/AppsFilterUtils.java +++ b/services/core/java/com/android/server/pm/AppsFilterUtils.java @@ -29,7 +29,7 @@ import com.android.server.pm.pkg.component.ParsedComponent; import com.android.server.pm.pkg.component.ParsedIntentInfo; import com.android.server.pm.pkg.component.ParsedMainComponent; import com.android.server.pm.pkg.component.ParsedProvider; -import com.android.server.utils.WatchedArrayList; +import com.android.server.utils.WatchedArraySet; import java.util.List; import java.util.Set; @@ -45,7 +45,7 @@ final class AppsFilterUtils { /** Returns true if the querying package may query for the potential target package */ public static boolean canQueryViaComponents(AndroidPackage querying, - AndroidPackage potentialTarget, WatchedArrayList protectedBroadcasts) { + AndroidPackage potentialTarget, WatchedArraySet protectedBroadcasts) { if (!querying.getQueriesIntents().isEmpty()) { for (Intent intent : querying.getQueriesIntents()) { if (matchesPackage(intent, potentialTarget, protectedBroadcasts)) { @@ -117,7 +117,7 @@ final class AppsFilterUtils { } private static boolean matchesPackage(Intent intent, AndroidPackage potentialTarget, - WatchedArrayList protectedBroadcasts) { + WatchedArraySet protectedBroadcasts) { if (matchesAnyComponents( intent, potentialTarget.getServices(), null /*protectedBroadcasts*/)) { return true; @@ -138,7 +138,7 @@ final class AppsFilterUtils { private static boolean matchesAnyComponents(Intent intent, List components, - WatchedArrayList protectedBroadcasts) { + WatchedArraySet protectedBroadcasts) { for (int i = ArrayUtils.size(components) - 1; i >= 0; i--) { ParsedMainComponent component = components.get(i); if (!component.isExported()) { @@ -152,7 +152,7 @@ final class AppsFilterUtils { } private static boolean matchesAnyFilter(Intent intent, ParsedComponent component, - WatchedArrayList protectedBroadcasts) { + WatchedArraySet protectedBroadcasts) { List intents = component.getIntents(); for (int i = ArrayUtils.size(intents) - 1; i >= 0; i--) { IntentFilter intentFilter = intents.get(i).getIntentFilter(); @@ -164,7 +164,7 @@ final class AppsFilterUtils { } private static boolean matchesIntentFilter(Intent intent, IntentFilter intentFilter, - @Nullable WatchedArrayList protectedBroadcasts) { + @Nullable WatchedArraySet protectedBroadcasts) { return intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(), intent.getData(), intent.getCategories(), "AppsFilter", true, protectedBroadcasts != null ? protectedBroadcasts.untrackedStorage() : null) > 0;