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
This commit is contained in:
Yurii Zubrytskyi
2022-11-11 15:41:23 -08:00
parent 0cacc5937c
commit da0b92b1ab
4 changed files with 43 additions and 33 deletions

View File

@@ -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<String> mActions;
private final ArraySet<String> mActions;
private ArrayList<String> mCategories = null;
private ArrayList<String> mDataSchemes = null;
private ArrayList<PatternMatcher> mDataSchemeSpecificParts = null;
@@ -433,7 +434,7 @@ public class IntentFilter implements Parcelable {
*/
public IntentFilter() {
mPriority = 0;
mActions = new ArrayList<String>();
mActions = new ArraySet<>();
}
/**
@@ -445,7 +446,7 @@ public class IntentFilter implements Parcelable {
*/
public IntentFilter(String action) {
mPriority = 0;
mActions = new ArrayList<String>();
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<String>();
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<String>(o.mActions);
mActions = new ArraySet<>(o.mActions);
if (o.mCategories != null) {
mCategories = new ArrayList<String>(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<N; i++) {
serializer.startTag(null, ACTION_STR);
serializer.attribute(null, NAME_STR, mActions.get(i));
serializer.attribute(null, NAME_STR, mActions.valueAt(i));
serializer.endTag(null, ACTION_STR);
}
N = countCategories();
@@ -2313,7 +2315,7 @@ public class IntentFilter implements Parcelable {
}
public final void writeToParcel(Parcel dest, int flags) {
dest.writeStringList(mActions);
dest.writeStringArray(mActions.toArray(new String[mActions.size()]));
if (mCategories != null) {
dest.writeInt(1);
dest.writeStringList(mCategories);
@@ -2407,8 +2409,9 @@ public class IntentFilter implements Parcelable {
/** @hide */
public IntentFilter(Parcel source) {
mActions = new ArrayList<String>();
source.readStringList(mActions);
List<String> actions = new ArrayList<>();
source.readStringList(actions);
mActions = new ArraySet<>(actions);
if (source.readInt() != 0) {
mCategories = new ArrayList<String>();
source.readStringList(mCategories);

View File

@@ -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<String> mProtectedBroadcasts;
protected WatchedArraySet<String> mProtectedBroadcasts;
@NonNull
protected SnapshotCache<WatchedArrayList<String>> mProtectedBroadcastsSnapshot;
protected SnapshotCache<WatchedArraySet<String>> mProtectedBroadcastsSnapshot;
/**
* This structure maps uid -> uid and indicates whether access from the first should be

View File

@@ -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<String> 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<String> 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;
}
}
}
}

View File

@@ -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<String> protectedBroadcasts) {
AndroidPackage potentialTarget, WatchedArraySet<String> 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<String> protectedBroadcasts) {
WatchedArraySet<String> protectedBroadcasts) {
if (matchesAnyComponents(
intent, potentialTarget.getServices(), null /*protectedBroadcasts*/)) {
return true;
@@ -138,7 +138,7 @@ final class AppsFilterUtils {
private static boolean matchesAnyComponents(Intent intent,
List<? extends ParsedMainComponent> components,
WatchedArrayList<String> protectedBroadcasts) {
WatchedArraySet<String> 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<String> protectedBroadcasts) {
WatchedArraySet<String> protectedBroadcasts) {
List<ParsedIntentInfo> 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<String> protectedBroadcasts) {
@Nullable WatchedArraySet<String> protectedBroadcasts) {
return intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(),
intent.getData(), intent.getCategories(), "AppsFilter", true,
protectedBroadcasts != null ? protectedBroadcasts.untrackedStorage() : null) > 0;