From 8fb048aede03cf2fa6ccfe5b5d30af91bf439572 Mon Sep 17 00:00:00 2001 From: Nate Myren Date: Tue, 7 Dec 2021 09:35:23 -0800 Subject: [PATCH] Lock mAttributionChains in PermissionUsageHelper Test: manual Fixes: 201451838 Change-Id: I4b17ed0e65fae45f393665f7f9d617a2acc1cbdd --- .../permission/PermissionUsageHelper.java | 110 ++++++++++-------- 1 file changed, 60 insertions(+), 50 deletions(-) diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java index 20f6c10f929e9..f0e6624f3f4fb 100644 --- a/core/java/android/permission/PermissionUsageHelper.java +++ b/core/java/android/permission/PermissionUsageHelper.java @@ -52,6 +52,8 @@ import android.telephony.TelephonyManager; import android.util.ArrayMap; import android.util.ArraySet; +import com.android.internal.annotations.GuardedBy; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -150,7 +152,9 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis private ArrayMap mUserContexts; private PackageManager mPkgManager; private AppOpsManager mAppOpsManager; - private ArrayMap> mAttributionChains = new ArrayMap<>(); + @GuardedBy("mAttributionChains") + private final ArrayMap> mAttributionChains = + new ArrayMap<>(); /** * Constructor for PermissionUsageHelper @@ -199,22 +203,24 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis // if any link in the chain is finished, remove the chain. Then, find any other chains that // contain this op/package/uid/tag combination, and remove them, as well. // TODO ntmyren: be smarter about this - mAttributionChains.remove(attributionChainId); - int numChains = mAttributionChains.size(); - ArrayList toRemove = new ArrayList<>(); - for (int i = 0; i < numChains; i++) { - int chainId = mAttributionChains.keyAt(i); - ArrayList chain = mAttributionChains.valueAt(i); - int chainSize = chain.size(); - for (int j = 0; j < chainSize; j++) { - AccessChainLink link = chain.get(j); - if (link.packageAndOpEquals(op, packageName, attributionTag, uid)) { - toRemove.add(chainId); - break; + synchronized (mAttributionChains) { + mAttributionChains.remove(attributionChainId); + int numChains = mAttributionChains.size(); + ArrayList toRemove = new ArrayList<>(); + for (int i = 0; i < numChains; i++) { + int chainId = mAttributionChains.keyAt(i); + ArrayList chain = mAttributionChains.valueAt(i); + int chainSize = chain.size(); + for (int j = 0; j < chainSize; j++) { + AccessChainLink link = chain.get(j); + if (link.packageAndOpEquals(op, packageName, attributionTag, uid)) { + toRemove.add(chainId); + break; + } } } + mAttributionChains.removeAll(toRemove); } - mAttributionChains.removeAll(toRemove); } @Override @@ -234,11 +240,13 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis // If this is not a successful start, or it is not a chain, or it is untrusted, return return; } - addLinkToChainIfNotPresent(AppOpsManager.opToPublicName(op), packageName, uid, - attributionTag, attributionFlags, attributionChainId); + synchronized (mAttributionChains) { + addLinkToChainIfNotPresentLocked(AppOpsManager.opToPublicName(op), packageName, uid, + attributionTag, attributionFlags, attributionChainId); + } } - private void addLinkToChainIfNotPresent(String op, String packageName, int uid, + private void addLinkToChainIfNotPresentLocked(String op, String packageName, int uid, String attributionTag, int attributionFlags, int attributionChainId) { ArrayList currentChain = mAttributionChains.computeIfAbsent( @@ -544,42 +552,44 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis } } - for (int i = 0; i < mAttributionChains.size(); i++) { - List usageList = mAttributionChains.valueAt(i); - int lastVisible = usageList.size() - 1; - // TODO ntmyren: remove this mic code once camera is converted to AttributionSource - // if the list is empty or incomplete, do not show it. - if (usageList.isEmpty() || !usageList.get(lastVisible).isEnd() - || !usageList.get(0).isStart() - || !usageList.get(lastVisible).usage.op.equals(OPSTR_RECORD_AUDIO)) { - continue; - } - - //TODO ntmyren: remove once camera etc. etc. - for (AccessChainLink link: usageList) { - proxyPackages.add(link.usage.getPackageIdHash()); - } - - AccessChainLink start = usageList.get(0); - AccessChainLink lastVisibleLink = usageList.get(lastVisible); - while (lastVisible > 0 && !shouldShowPackage(lastVisibleLink.usage.packageName)) { - lastVisible--; - lastVisibleLink = usageList.get(lastVisible); - } - String proxyLabel = null; - if (!lastVisibleLink.usage.packageName.equals(start.usage.packageName)) { - try { - PackageManager userPkgManager = - getUserContext(lastVisibleLink.usage.getUser()).getPackageManager(); - ApplicationInfo appInfo = userPkgManager.getApplicationInfo( - lastVisibleLink.usage.packageName, 0); - proxyLabel = appInfo.loadLabel(userPkgManager).toString(); - } catch (PackageManager.NameNotFoundException e) { - // do nothing + synchronized (mAttributionChains) { + for (int i = 0; i < mAttributionChains.size(); i++) { + List usageList = mAttributionChains.valueAt(i); + int lastVisible = usageList.size() - 1; + // TODO ntmyren: remove this mic code once camera is converted to AttributionSource + // if the list is empty or incomplete, do not show it. + if (usageList.isEmpty() || !usageList.get(lastVisible).isEnd() + || !usageList.get(0).isStart() + || !usageList.get(lastVisible).usage.op.equals(OPSTR_RECORD_AUDIO)) { + continue; } + //TODO ntmyren: remove once camera etc. etc. + for (AccessChainLink link : usageList) { + proxyPackages.add(link.usage.getPackageIdHash()); + } + + AccessChainLink start = usageList.get(0); + AccessChainLink lastVisibleLink = usageList.get(lastVisible); + while (lastVisible > 0 && !shouldShowPackage(lastVisibleLink.usage.packageName)) { + lastVisible--; + lastVisibleLink = usageList.get(lastVisible); + } + String proxyLabel = null; + if (!lastVisibleLink.usage.packageName.equals(start.usage.packageName)) { + try { + PackageManager userPkgManager = + getUserContext(lastVisibleLink.usage.getUser()).getPackageManager(); + ApplicationInfo appInfo = userPkgManager.getApplicationInfo( + lastVisibleLink.usage.packageName, 0); + proxyLabel = appInfo.loadLabel(userPkgManager).toString(); + } catch (PackageManager.NameNotFoundException e) { + // do nothing + } + + } + usagesAndLabels.put(start.usage, proxyLabel); } - usagesAndLabels.put(start.usage, proxyLabel); } for (int packageHash : mostRecentUsages.keySet()) {