diff options
| author | 2024-02-15 02:16:51 +0000 | |
|---|---|---|
| committer | 2024-02-15 07:04:51 +0000 | |
| commit | 3b4eb3573227c19f856e57f65ab0c99f2d5931b3 (patch) | |
| tree | 439ba51cb1c65a98473ebd397b18ca671337f6aa | |
| parent | 6371887903fe697cdf603c8a45f13aeead29bdfc (diff) | |
Add new AppOp APIs to facilitate Privacy Indicators
Bug: 308720988
Test: presubmit
Change-Id: I240263f03a014b790089436cabe4f348a445636c
| -rw-r--r-- | core/api/system-current.txt | 3 | ||||
| -rw-r--r-- | core/java/android/app/AppOpsManager.java | 68 | ||||
| -rw-r--r-- | core/java/android/permission/PermissionGroupUsage.java | 34 | ||||
| -rw-r--r-- | core/java/android/permission/PermissionManager.java | 4 | ||||
| -rw-r--r-- | core/java/android/permission/PermissionUsageHelper.java | 63 | ||||
| -rw-r--r-- | core/java/com/android/internal/app/IAppOpsService.aidl | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/appop/AppOpsService.java | 38 |
7 files changed, 182 insertions, 29 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 8fe38768b459..4407c427dbb2 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -625,6 +625,8 @@ package android.app { method public static String[] getOpStrs(); method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...); method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOps(@Nullable String[]); + method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOps(@Nullable String[], @NonNull String); + method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermissionGroupUsage> getPermissionGroupUsageForPrivacyIndicator(boolean); method public static int opToDefaultMode(@NonNull String); method @Nullable public static String opToPermission(@NonNull String); method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(@NonNull String, int, @Nullable String, int); @@ -11374,6 +11376,7 @@ package android.permission { method public long getLastAccessTimeMillis(); method @NonNull public String getPackageName(); method @NonNull public String getPermissionGroupName(); + method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") @NonNull public String getPersistentDeviceId(); method @Nullable public CharSequence getProxyLabel(); method public int getUid(); method public boolean isActive(); diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 409badb347c4..16c7753c7f46 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -72,6 +72,8 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; +import android.permission.PermissionGroupUsage; +import android.permission.PermissionUsageHelper; import android.provider.DeviceConfig; import android.util.ArrayMap; import android.util.ArraySet; @@ -226,6 +228,7 @@ public class AppOpsManager { private static Boolean sFullLog = null; final Context mContext; + private PermissionUsageHelper mUsageHelper; @UnsupportedAppUsage final IAppOpsService mService; @@ -7765,6 +7768,44 @@ public class AppOpsManager { } /** + * Retrieve current operation state for all applications for a device. + * + * The mode of the ops returned are set for the package but may not reflect their effective + * state due to UID policy or because it's controlled by a different global op. + * + * Use {@link #unsafeCheckOp(String, int, String)}} or + * {@link #noteOp(String, int, String, String, String)} if the effective mode is needed. + * + * @param ops The set of operations you are interested in, or null if you want all of them. + * @param persistentDeviceId The device that the ops are attributed to. + * + * @hide + */ + @SystemApi + @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) + public @NonNull List<AppOpsManager.PackageOps> getPackagesForOps(@Nullable String[] ops, + @NonNull String persistentDeviceId) { + final int[] opCodes; + if (ops != null) { + final int opCount = ops.length; + opCodes = new int[opCount]; + for (int i = 0; i < opCount; i++) { + opCodes[i] = sOpStrToOp.get(ops[i]); + } + } else { + opCodes = null; + } + final List<AppOpsManager.PackageOps> result; + try { + result = mService.getPackagesForOpsForDevice(opCodes, persistentDeviceId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + return (result != null) ? result : Collections.emptyList(); + } + + /** * Retrieve current operation state for all applications. * * The mode of the ops returned are set for the package but may not reflect their effective @@ -7780,7 +7821,8 @@ public class AppOpsManager { @UnsupportedAppUsage public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { try { - return mService.getPackagesForOps(ops); + return mService.getPackagesForOpsForDevice(ops, + VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -9946,6 +9988,30 @@ public class AppOpsManager { appOpsNotedForAttribution.set(op); } + /** + * Get recent op usage data for CAMERA, MICROPHONE and LOCATION from all connected devices + * to power privacy indicator. + * + * @param includeMicrophoneUsage whether to retrieve microphone usage + * @return A list of permission groups currently or recently used by all apps by all users in + * the current profile group. + * + * @hide + */ + @SystemApi + @NonNull + @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS) + public List<PermissionGroupUsage> getPermissionGroupUsageForPrivacyIndicator( + boolean includeMicrophoneUsage) { + // Lazily initialize the usage helper + if (mUsageHelper == null) { + mUsageHelper = new PermissionUsageHelper(mContext); + } + + return mUsageHelper.getOpUsageDataForAllDevices(includeMicrophoneUsage); + } + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { diff --git a/core/java/android/permission/PermissionGroupUsage.java b/core/java/android/permission/PermissionGroupUsage.java index 49b7463533e4..6895d3c67f06 100644 --- a/core/java/android/permission/PermissionGroupUsage.java +++ b/core/java/android/permission/PermissionGroupUsage.java @@ -17,6 +17,7 @@ package android.permission; import android.annotation.CurrentTimeMillisLong; +import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -26,8 +27,8 @@ import com.android.internal.util.DataClass; /** * Represents the usage of a permission group by an app. Supports package name, user, permission - * group, whether or not the access is running or recent, whether the access is tied to a phone - * call, and an optional special attribution tag, label and proxy label. + * group, persistent device Id, whether or not the access is running or recent, whether the access + * is tied to a phone call, and an optional special attribution tag, label and proxy label. * * @hide */ @@ -48,6 +49,7 @@ public final class PermissionGroupUsage implements Parcelable { private final @Nullable CharSequence mAttributionTag; private final @Nullable CharSequence mAttributionLabel; private final @Nullable CharSequence mProxyLabel; + private final @NonNull String mPersistentDeviceId; @@ -79,7 +81,8 @@ public final class PermissionGroupUsage implements Parcelable { boolean phoneCall, @Nullable CharSequence attributionTag, @Nullable CharSequence attributionLabel, - @Nullable CharSequence proxyLabel) { + @Nullable CharSequence proxyLabel, + @NonNull String persistentDeviceId) { this.mPackageName = packageName; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mPackageName); @@ -93,6 +96,9 @@ public final class PermissionGroupUsage implements Parcelable { this.mAttributionTag = attributionTag; this.mAttributionLabel = attributionLabel; this.mProxyLabel = proxyLabel; + this.mPersistentDeviceId = persistentDeviceId; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mPersistentDeviceId); // onConstructed(); // You can define this method to get a callback } @@ -170,6 +176,12 @@ public final class PermissionGroupUsage implements Parcelable { return mProxyLabel; } + @DataClass.Generated.Member + @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + public @NonNull String getPersistentDeviceId() { + return mPersistentDeviceId; + } + @Override @DataClass.Generated.Member public String toString() { @@ -185,7 +197,8 @@ public final class PermissionGroupUsage implements Parcelable { "phoneCall = " + mPhoneCall + ", " + "attributionTag = " + mAttributionTag + ", " + "attributionLabel = " + mAttributionLabel + ", " + - "proxyLabel = " + mProxyLabel + + "proxyLabel = " + mProxyLabel + ", " + + "persistentDeviceId = " + mPersistentDeviceId + " }"; } @@ -210,7 +223,8 @@ public final class PermissionGroupUsage implements Parcelable { && mPhoneCall == that.mPhoneCall && java.util.Objects.equals(mAttributionTag, that.mAttributionTag) && java.util.Objects.equals(mAttributionLabel, that.mAttributionLabel) - && java.util.Objects.equals(mProxyLabel, that.mProxyLabel); + && java.util.Objects.equals(mProxyLabel, that.mProxyLabel) + && java.util.Objects.equals(mPersistentDeviceId, that.mPersistentDeviceId); } @Override @@ -229,6 +243,7 @@ public final class PermissionGroupUsage implements Parcelable { _hash = 31 * _hash + java.util.Objects.hashCode(mAttributionTag); _hash = 31 * _hash + java.util.Objects.hashCode(mAttributionLabel); _hash = 31 * _hash + java.util.Objects.hashCode(mProxyLabel); + _hash = 31 * _hash + java.util.Objects.hashCode(mPersistentDeviceId); return _hash; } @@ -252,6 +267,7 @@ public final class PermissionGroupUsage implements Parcelable { if (mAttributionTag != null) dest.writeCharSequence(mAttributionTag); if (mAttributionLabel != null) dest.writeCharSequence(mAttributionLabel); if (mProxyLabel != null) dest.writeCharSequence(mProxyLabel); + dest.writeString(mPersistentDeviceId); } @Override @@ -275,6 +291,7 @@ public final class PermissionGroupUsage implements Parcelable { CharSequence attributionTag = (flg & 0x40) == 0 ? null : (CharSequence) in.readCharSequence(); CharSequence attributionLabel = (flg & 0x80) == 0 ? null : (CharSequence) in.readCharSequence(); CharSequence proxyLabel = (flg & 0x100) == 0 ? null : (CharSequence) in.readCharSequence(); + String persistentDeviceId = in.readString(); this.mPackageName = packageName; com.android.internal.util.AnnotationValidations.validate( @@ -289,6 +306,9 @@ public final class PermissionGroupUsage implements Parcelable { this.mAttributionTag = attributionTag; this.mAttributionLabel = attributionLabel; this.mProxyLabel = proxyLabel; + this.mPersistentDeviceId = persistentDeviceId; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mPersistentDeviceId); // onConstructed(); // You can define this method to get a callback } @@ -308,10 +328,10 @@ public final class PermissionGroupUsage implements Parcelable { }; @DataClass.Generated( - time = 1645067417023L, + time = 1706285211875L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/permission/PermissionGroupUsage.java", - inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final int mUid\nprivate final long mLastAccessTimeMillis\nprivate final @android.annotation.NonNull java.lang.String mPermissionGroupName\nprivate final boolean mActive\nprivate final boolean mPhoneCall\nprivate final @android.annotation.Nullable java.lang.CharSequence mAttributionTag\nprivate final @android.annotation.Nullable java.lang.CharSequence mAttributionLabel\nprivate final @android.annotation.Nullable java.lang.CharSequence mProxyLabel\nclass PermissionGroupUsage extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genEqualsHashCode=true, genToString=true)") + inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final int mUid\nprivate final long mLastAccessTimeMillis\nprivate final @android.annotation.NonNull java.lang.String mPermissionGroupName\nprivate final boolean mActive\nprivate final boolean mPhoneCall\nprivate final @android.annotation.Nullable java.lang.CharSequence mAttributionTag\nprivate final @android.annotation.Nullable java.lang.CharSequence mAttributionLabel\nprivate final @android.annotation.Nullable java.lang.CharSequence mProxyLabel\nprivate final @android.annotation.NonNull java.lang.String mPersistentDeviceId\nclass PermissionGroupUsage extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genEqualsHashCode=true, genToString=true)") @Deprecated private void __metadata() {} diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index e6b8102764eb..fd52c769e408 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -1329,7 +1329,9 @@ public final class PermissionManager { public List<PermissionGroupUsage> getIndicatorAppOpUsageData(boolean micMuted) { // Lazily initialize the usage helper initializeUsageHelper(); - return mUsageHelper.getOpUsageData(micMuted); + boolean includeMicrophoneUsage = !micMuted; + return mUsageHelper.getOpUsageDataByDevice(includeMicrophoneUsage, + VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT); } /** diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java index 1f798baf1bd6..460b4dd9b86c 100644 --- a/core/java/android/permission/PermissionUsageHelper.java +++ b/core/java/android/permission/PermissionUsageHelper.java @@ -41,6 +41,8 @@ import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_AC import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; +import android.companion.virtual.VirtualDevice; +import android.companion.virtual.VirtualDeviceManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.Attribution; @@ -52,10 +54,12 @@ import android.location.LocationManager; import android.media.AudioManager; import android.os.Process; import android.os.UserHandle; +import android.permission.flags.Flags; import android.provider.DeviceConfig; import android.telephony.TelephonyManager; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.Slog; import com.android.internal.annotations.GuardedBy; @@ -75,6 +79,8 @@ import java.util.Objects; public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedListener, AppOpsManager.OnOpStartedListener { + private static final String LOG_TAG = PermissionUsageHelper.class.getName(); + /** * Whether to show the mic and camera icons. */ @@ -159,6 +165,7 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis private ArrayMap<UserHandle, Context> mUserContexts; private PackageManager mPkgManager; private AppOpsManager mAppOpsManager; + private VirtualDeviceManager mVirtualDeviceManager; @GuardedBy("mAttributionChains") private final ArrayMap<Integer, ArrayList<AccessChainLink>> mAttributionChains = new ArrayMap<>(); @@ -172,6 +179,7 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis mContext = context; mPkgManager = context.getPackageManager(); mAppOpsManager = context.getSystemService(AppOpsManager.class); + mVirtualDeviceManager = context.getSystemService(VirtualDeviceManager.class); mUserContexts = new ArrayMap<>(); mUserContexts.put(Process.myUserHandle(), mContext); // TODO ntmyren: make this listen for flag enable/disable changes @@ -280,9 +288,11 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis } /** - * @see PermissionManager.getIndicatorAppOpUsageData + * Return Op usage for CAMERA, LOCATION AND MICROPHONE for all packages for a device. + * The returned data is to power privacy indicator. */ - public @NonNull List<PermissionGroupUsage> getOpUsageData(boolean isMicMuted) { + public @NonNull List<PermissionGroupUsage> getOpUsageDataByDevice( + boolean includeMicrophoneUsage, String deviceId) { List<PermissionGroupUsage> usages = new ArrayList<>(); if (!shouldShowIndicators()) { @@ -293,11 +303,11 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis if (shouldShowLocationIndicator()) { ops.addAll(LOCATION_OPS); } - if (!isMicMuted) { + if (includeMicrophoneUsage) { ops.addAll(MIC_OPS); } - Map<String, List<OpUsage>> rawUsages = getOpUsages(ops); + Map<String, List<OpUsage>> rawUsages = getOpUsagesByDevice(ops, deviceId); ArrayList<String> usedPermGroups = new ArrayList<>(rawUsages.keySet()); @@ -349,13 +359,40 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis new PermissionGroupUsage(usage.packageName, usage.uid, usage.lastAccessTime, permGroup, usage.isRunning, isPhone, usage.attributionTag, attributionLabel, - usagesWithLabels.valueAt(usageNum))); + usagesWithLabels.valueAt(usageNum), + VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT)); } } return usages; } + /** + * Return Op usage for CAMERA, LOCATION AND MICROPHONE for all packages and all connected + * devices. + * The returned data is to power privacy indicator. + */ + public @NonNull List<PermissionGroupUsage> getOpUsageDataForAllDevices( + boolean includeMicrophoneUsage) { + List<PermissionGroupUsage> allUsages = new ArrayList<>(); + List<VirtualDevice> virtualDevices = mVirtualDeviceManager.getVirtualDevices(); + ArraySet<String> persistentDeviceIds = new ArraySet<>(); + + for (int num = 0; num < virtualDevices.size(); num++) { + persistentDeviceIds.add(virtualDevices.get(num).getPersistentDeviceId()); + } + persistentDeviceIds.add(VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT); + + for (int index = 0; index < persistentDeviceIds.size(); index++) { + allUsages.addAll( + getOpUsageDataByDevice(includeMicrophoneUsage, + persistentDeviceIds.valueAt(index))); + } + + return allUsages; + } + + private void updateSubattributionLabelsMap(List<OpUsage> usages, ArrayMap<String, Map<String, String>> subAttributionLabelsMap) { if (usages == null || usages.isEmpty()) { @@ -443,12 +480,24 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis * running/recent info, if the usage is a phone call, per permission group. * * @param opNames a list of op names to get usage for + * @param deviceId which device to get op usage for * @return A map of permission group -> list of usages that are recent or running */ - private Map<String, List<OpUsage>> getOpUsages(List<String> opNames) { + private Map<String, List<OpUsage>> getOpUsagesByDevice(List<String> opNames, String deviceId) { List<AppOpsManager.PackageOps> ops; try { - ops = mAppOpsManager.getPackagesForOps(opNames.toArray(new String[opNames.size()])); + if (Flags.deviceAwarePermissionApisEnabled()) { + ops = mAppOpsManager.getPackagesForOps(opNames.toArray(new String[opNames.size()]), + deviceId); + } else if (!Objects.equals(deviceId, + VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT)) { + Slog.w(LOG_TAG, + "device_aware_permission_apis_enabled flag not enabled when deviceId is " + + "not default"); + return Collections.emptyMap(); + } else { + ops = mAppOpsManager.getPackagesForOps(opNames.toArray(new String[opNames.size()])); + } } catch (NullPointerException e) { // older builds might not support all the app-ops requested return Collections.emptyMap(); diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index 3a321e5c26f7..3ec70649294b 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -162,4 +162,5 @@ interface IAppOpsService { int attributionFlags, int attributionChainId); void finishOperationForDevice(IBinder clientId, int code, int uid, String packageName, @nullable String attributionTag, int virtualDeviceId); + List<AppOpsManager.PackageOps> getPackagesForOpsForDevice(in int[] ops, String persistentDeviceId); } diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index fd09ad187f2a..fca119917fd0 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -658,11 +658,11 @@ public class AppOpsService extends IAppOpsService.Stub { return attributedOp; } - @NonNull OpEntry createEntryLocked() { + @NonNull OpEntry createEntryLocked(String persistentDeviceId) { // TODO(b/308201969): Update this method when we introduce disk persistence of events // for accesses on external devices. final ArrayMap<String, AttributedOp> attributedOps = mDeviceAttributedOps.get( - PERSISTENT_DEVICE_ID_DEFAULT); + persistentDeviceId); final ArrayMap<String, AppOpsManager.AttributedOpEntry> attributionEntries = new ArrayMap<>(attributedOps.size()); for (int i = 0; i < attributedOps.size(); i++) { @@ -1550,13 +1550,14 @@ public class AppOpsService extends IAppOpsService.Stub { mHistoricalRegistry.shutdown(); } - private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) { + private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops, + String persistentDeviceId) { ArrayList<AppOpsManager.OpEntry> resOps = null; if (ops == null) { resOps = new ArrayList<>(); for (int j=0; j<pkgOps.size(); j++) { Op curOp = pkgOps.valueAt(j); - resOps.add(getOpEntryForResult(curOp)); + resOps.add(getOpEntryForResult(curOp, persistentDeviceId)); } } else { for (int j=0; j<ops.length; j++) { @@ -1565,7 +1566,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (resOps == null) { resOps = new ArrayList<>(); } - resOps.add(getOpEntryForResult(curOp)); + resOps.add(getOpEntryForResult(curOp, persistentDeviceId)); } } } @@ -1609,16 +1610,23 @@ public class AppOpsService extends IAppOpsService.Stub { return resOps; } - private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op) { - return op.createEntryLocked(); + private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, String persistentDeviceId) { + return op.createEntryLocked(persistentDeviceId); } @Override public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { + return getPackagesForOpsForDevice(ops, PERSISTENT_DEVICE_ID_DEFAULT); + } + + @Override + public List<AppOpsManager.PackageOps> getPackagesForOpsForDevice(int[] ops, + @NonNull String persistentDeviceId) { final int callingUid = Binder.getCallingUid(); final boolean hasAllPackageAccess = mContext.checkPermission( Manifest.permission.GET_APP_OPS_STATS, Binder.getCallingPid(), Binder.getCallingUid(), null) == PackageManager.PERMISSION_GRANTED; + ArrayList<AppOpsManager.PackageOps> res = null; synchronized (this) { final int uidStateCount = mUidStates.size(); @@ -1627,21 +1635,24 @@ public class AppOpsService extends IAppOpsService.Stub { if (uidState.pkgOps.isEmpty()) { continue; } + // Caller can always see their packages and with a permission all. + if (!hasAllPackageAccess && callingUid != uidState.uid) { + continue; + } + ArrayMap<String, Ops> packages = uidState.pkgOps; final int packageCount = packages.size(); for (int j = 0; j < packageCount; j++) { Ops pkgOps = packages.valueAt(j); - ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); + ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops, + persistentDeviceId); if (resOps != null) { if (res == null) { res = new ArrayList<>(); } AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( pkgOps.packageName, pkgOps.uidState.uid, resOps); - // Caller can always see their packages and with a permission all. - if (hasAllPackageAccess || callingUid == pkgOps.uidState.uid) { - res.add(resPackage); - } + res.add(resPackage); } } } @@ -1663,7 +1674,8 @@ public class AppOpsService extends IAppOpsService.Stub { if (pkgOps == null) { return null; } - ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); + ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops, + PERSISTENT_DEVICE_ID_DEFAULT); if (resOps == null || resOps.size() == 0) { return null; } |