Loading core/java/android/permission/PermissionManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -1329,7 +1329,7 @@ public final class PermissionManager { // Lazily initialize the usage helper initializeUsageHelper(); boolean includeMicrophoneUsage = !micMuted; return mUsageHelper.getOpUsageDataByDevice(includeMicrophoneUsage, return mUsageHelper.getOpUsageDataForIndicatorsByDevice(includeMicrophoneUsage, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT); } Loading core/java/android/permission/PermissionUsageHelper.java +86 −3 Original line number Diff line number Diff line Loading @@ -40,10 +40,12 @@ import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_AC import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AppOpsManager; import android.companion.virtual.VirtualDevice; import android.companion.virtual.VirtualDeviceManager; import android.content.Context; import android.content.PermissionChecker; import android.content.pm.ApplicationInfo; import android.content.pm.Attribution; import android.content.pm.PackageInfo; Loading @@ -54,6 +56,7 @@ import android.location.LocationManager; import android.media.AudioManager; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.permission.flags.Flags; import android.provider.DeviceConfig; import android.telephony.TelephonyManager; Loading Loading @@ -103,7 +106,8 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis private static boolean shouldShowIndicators() { return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, PROPERTY_CAMERA_MIC_ICONS_ENABLED, true); PROPERTY_CAMERA_MIC_ICONS_ENABLED, true) || android.location.flags.Flags.locationIndicatorsEnabled(); } private static long getRecentThreshold(Long now) { Loading @@ -116,6 +120,11 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis RUNNING_ACCESS_TIME_MS, DEFAULT_RUNNING_TIME_MS); } private static final List<String> LOCATION_OPS = List.of( OPSTR_COARSE_LOCATION, OPSTR_FINE_LOCATION ); private static final List<String> MIC_OPS = List.of( OPSTR_PHONE_CALL_MICROPHONE, OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO, Loading Loading @@ -274,8 +283,10 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis /** * Return Op usage for CAMERA, LOCATION AND MICROPHONE for all packages for a device. * The returned data is to power privacy indicator. * * <p>The system apps and background apps are excluded for LOCATION Op usage. */ public @NonNull List<PermissionGroupUsage> getOpUsageDataByDevice( public @NonNull List<PermissionGroupUsage> getOpUsageDataForIndicatorsByDevice( boolean includeMicrophoneUsage, String deviceId) { List<PermissionGroupUsage> usages = new ArrayList<>(); Loading @@ -287,6 +298,9 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis if (includeMicrophoneUsage) { ops.addAll(MIC_OPS); } if (android.location.flags.Flags.locationIndicatorsEnabled()) { ops.addAll(LOCATION_OPS); } Map<String, List<OpUsage>> rawUsages = getOpUsagesByDevice(ops, deviceId); Loading Loading @@ -367,7 +381,7 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis for (int index = 0; index < persistentDeviceIds.size(); index++) { allUsages.addAll( getOpUsageDataByDevice(includeMicrophoneUsage, getOpUsageDataForIndicatorsByDevice(includeMicrophoneUsage, persistentDeviceIds.valueAt(index))); } } Loading Loading @@ -455,12 +469,75 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis mContext.getSystemService(LocationManager.class)).isProviderPackage(packageName); } /** * Returns true if the package is a system app. * * <p>TODO(b/422799135): refactor isSystemApp() and isBackgroundApp(). Before this is fixed, * make sure to update AppOpsPrivacyItemMonitor when changing this method */ private boolean isSystemApp(String op, String packageName, UserHandle user, int uid) { UserManager userManager = mContext.getSystemService(UserManager.class); if (userManager != null) { // Don't show apps belonging to background users except managed users. boolean foundUser = false; List<UserHandle> userProfiles = userManager.getUserProfiles(); for (UserHandle profile : userProfiles) { if (profile.equals(user)) { foundUser = true; break; } } if (!foundUser) { return true; } } String permission = mAppOpsManager.opToPermission(op); int permissionFlags = mPkgManager.getPermissionFlags(permission, packageName, user); if (PermissionChecker.checkPermissionForPreflight( mContext, permission, PermissionChecker.PID_UNKNOWN, uid, packageName) == PermissionChecker.PERMISSION_GRANTED) { return (permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) == 0; } else { return (permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) == 0; } } /** * Returns true if it is a background app * * <p>TODO(b/422799135): refactor isSystemApp() and isBackgroundApp(). Before this is fixed, * make sure to update AppOpsPrivacyItemMonitor when changing this method */ private boolean isBackgroundApp(int uid) { ActivityManager activityManager = mContext.getSystemService(ActivityManager.class); List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses(); if (runningAppProcesses == null) { return false; } for (ActivityManager.RunningAppProcessInfo processInfo : runningAppProcesses) { if (processInfo.uid == uid) { return processInfo.importance > ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; } } return false; } /** * Get the raw usages from the system, and then parse out the ones that are not recent enough, * determine which permission group each belongs in, and removes duplicates (if the same app * uses multiple permissions of the same group). Stores the package name, attribution tag, user, * running/recent info, if the usage is a phone call, per permission group. * * <p>The system apps and background apps are excluded for location Op usage. * * @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 Loading Loading @@ -532,6 +609,12 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis } String permGroupName = getGroupForOp(op); if (LOCATION.equals(permGroupName)) { if (isSystemApp(op, packageName, user, uid) || isBackgroundApp(uid)) { // Remove the system & background apps for location op continue; } } OpUsage usage = new OpUsage(packageName, attributionTag, op, uid, lastAccessTime, isRunning, proxyUsage); Loading packages/SystemUI/multivalentTests/src/com/android/systemui/privacy/PrivacyDialogV2Test.kt +7 −7 Original line number Diff line number Diff line Loading @@ -24,8 +24,8 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.widget.TextView import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.res.R import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before Loading Loading @@ -62,7 +62,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { isPhoneCall: Boolean = false, isService: Boolean = false, permGroupName: String = TEST_PERM_GROUP, navigationIntent: Intent = TEST_INTENT navigationIntent: Intent = TEST_INTENT, ) = PrivacyDialogV2.PrivacyElement( type, Loading @@ -77,7 +77,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { isPhoneCall, isService, permGroupName, navigationIntent navigationIntent, ) } Loading Loading @@ -184,7 +184,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { val list = listOf( createPrivacyElement(type = PrivacyType.TYPE_CAMERA, isActive = true), createPrivacyElement() createPrivacyElement(), ) dialog = PrivacyDialogV2(context, list, manageApp, closeApp, openPrivacyDashboard) Loading Loading @@ -275,7 +275,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { createPrivacyElement( attributionLabel = "For subattribution", isActive = true, isService = true isService = true, ) ) dialog = PrivacyDialogV2(context, list, manageApp, closeApp, openPrivacyDashboard) Loading @@ -293,7 +293,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { createPrivacyElement( attributionLabel = "For subattribution", proxyLabel = "proxy label", isActive = true isActive = true, ) ) dialog = PrivacyDialogV2(context, list, manageApp, closeApp, openPrivacyDashboard) Loading @@ -308,7 +308,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { dialog = PrivacyDialogV2(context, list, manageApp, closeApp, openPrivacyDashboard) dialog.show() assertThat(dialog.window?.attributes?.title).isEqualTo("Microphone & Camera") assertThat(dialog.window?.attributes?.title).isEqualTo("Microphone, Camera & Location") } @Test Loading packages/SystemUI/res/values/strings.xml +1 −1 Original line number Diff line number Diff line Loading @@ -3957,7 +3957,7 @@ <string name="connected_display_icon_desc">Display connected</string> <!-- Title of the privacy dialog, shown for active / recent app usage of some phone sensors [CHAR LIMIT=30] --> <string name="privacy_dialog_title">Microphone & Camera</string> <string name="privacy_dialog_title">Microphone, Camera & Location</string> <!-- Subtitle of the privacy dialog, shown for active / recent app usage of some phone sensors [CHAR LIMIT=NONE] --> <string name="privacy_dialog_summary">Recent app use</string> <!-- Label of the secondary button of the privacy dialog, used to check recent app usage of phone sensors [CHAR LIMIT=30] --> Loading packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt +12 −0 Original line number Diff line number Diff line Loading @@ -267,6 +267,12 @@ constructor( return true } /** * Returns true if the package is a system app. * * <p>TODO(b/422799135): refactor isSystemApp() and isBackgroundApp(). Before this is fixed, * make sure to update PermissionUsageHelper when changing this method. */ private fun isSystemApp(item: AppOpItem): Boolean { val user = UserHandle.getUserHandleForUid(item.uid) Loading Loading @@ -299,6 +305,12 @@ constructor( } } /** * Returns true if it is a background app * * <p>TODO(b/422799135): refactor isSystemApp() and isBackgroundApp(). Before this is fixed, * make sure to update PermissionUsageHelper when changing this method. */ private fun isBackgroundApp(item: AppOpItem): Boolean { for (processInfo in activityManager.runningAppProcesses) { if (processInfo.uid == item.uid) { Loading Loading
core/java/android/permission/PermissionManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -1329,7 +1329,7 @@ public final class PermissionManager { // Lazily initialize the usage helper initializeUsageHelper(); boolean includeMicrophoneUsage = !micMuted; return mUsageHelper.getOpUsageDataByDevice(includeMicrophoneUsage, return mUsageHelper.getOpUsageDataForIndicatorsByDevice(includeMicrophoneUsage, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT); } Loading
core/java/android/permission/PermissionUsageHelper.java +86 −3 Original line number Diff line number Diff line Loading @@ -40,10 +40,12 @@ import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_AC import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AppOpsManager; import android.companion.virtual.VirtualDevice; import android.companion.virtual.VirtualDeviceManager; import android.content.Context; import android.content.PermissionChecker; import android.content.pm.ApplicationInfo; import android.content.pm.Attribution; import android.content.pm.PackageInfo; Loading @@ -54,6 +56,7 @@ import android.location.LocationManager; import android.media.AudioManager; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.permission.flags.Flags; import android.provider.DeviceConfig; import android.telephony.TelephonyManager; Loading Loading @@ -103,7 +106,8 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis private static boolean shouldShowIndicators() { return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, PROPERTY_CAMERA_MIC_ICONS_ENABLED, true); PROPERTY_CAMERA_MIC_ICONS_ENABLED, true) || android.location.flags.Flags.locationIndicatorsEnabled(); } private static long getRecentThreshold(Long now) { Loading @@ -116,6 +120,11 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis RUNNING_ACCESS_TIME_MS, DEFAULT_RUNNING_TIME_MS); } private static final List<String> LOCATION_OPS = List.of( OPSTR_COARSE_LOCATION, OPSTR_FINE_LOCATION ); private static final List<String> MIC_OPS = List.of( OPSTR_PHONE_CALL_MICROPHONE, OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO, Loading Loading @@ -274,8 +283,10 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis /** * Return Op usage for CAMERA, LOCATION AND MICROPHONE for all packages for a device. * The returned data is to power privacy indicator. * * <p>The system apps and background apps are excluded for LOCATION Op usage. */ public @NonNull List<PermissionGroupUsage> getOpUsageDataByDevice( public @NonNull List<PermissionGroupUsage> getOpUsageDataForIndicatorsByDevice( boolean includeMicrophoneUsage, String deviceId) { List<PermissionGroupUsage> usages = new ArrayList<>(); Loading @@ -287,6 +298,9 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis if (includeMicrophoneUsage) { ops.addAll(MIC_OPS); } if (android.location.flags.Flags.locationIndicatorsEnabled()) { ops.addAll(LOCATION_OPS); } Map<String, List<OpUsage>> rawUsages = getOpUsagesByDevice(ops, deviceId); Loading Loading @@ -367,7 +381,7 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis for (int index = 0; index < persistentDeviceIds.size(); index++) { allUsages.addAll( getOpUsageDataByDevice(includeMicrophoneUsage, getOpUsageDataForIndicatorsByDevice(includeMicrophoneUsage, persistentDeviceIds.valueAt(index))); } } Loading Loading @@ -455,12 +469,75 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis mContext.getSystemService(LocationManager.class)).isProviderPackage(packageName); } /** * Returns true if the package is a system app. * * <p>TODO(b/422799135): refactor isSystemApp() and isBackgroundApp(). Before this is fixed, * make sure to update AppOpsPrivacyItemMonitor when changing this method */ private boolean isSystemApp(String op, String packageName, UserHandle user, int uid) { UserManager userManager = mContext.getSystemService(UserManager.class); if (userManager != null) { // Don't show apps belonging to background users except managed users. boolean foundUser = false; List<UserHandle> userProfiles = userManager.getUserProfiles(); for (UserHandle profile : userProfiles) { if (profile.equals(user)) { foundUser = true; break; } } if (!foundUser) { return true; } } String permission = mAppOpsManager.opToPermission(op); int permissionFlags = mPkgManager.getPermissionFlags(permission, packageName, user); if (PermissionChecker.checkPermissionForPreflight( mContext, permission, PermissionChecker.PID_UNKNOWN, uid, packageName) == PermissionChecker.PERMISSION_GRANTED) { return (permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) == 0; } else { return (permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) == 0; } } /** * Returns true if it is a background app * * <p>TODO(b/422799135): refactor isSystemApp() and isBackgroundApp(). Before this is fixed, * make sure to update AppOpsPrivacyItemMonitor when changing this method */ private boolean isBackgroundApp(int uid) { ActivityManager activityManager = mContext.getSystemService(ActivityManager.class); List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses(); if (runningAppProcesses == null) { return false; } for (ActivityManager.RunningAppProcessInfo processInfo : runningAppProcesses) { if (processInfo.uid == uid) { return processInfo.importance > ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; } } return false; } /** * Get the raw usages from the system, and then parse out the ones that are not recent enough, * determine which permission group each belongs in, and removes duplicates (if the same app * uses multiple permissions of the same group). Stores the package name, attribution tag, user, * running/recent info, if the usage is a phone call, per permission group. * * <p>The system apps and background apps are excluded for location Op usage. * * @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 Loading Loading @@ -532,6 +609,12 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis } String permGroupName = getGroupForOp(op); if (LOCATION.equals(permGroupName)) { if (isSystemApp(op, packageName, user, uid) || isBackgroundApp(uid)) { // Remove the system & background apps for location op continue; } } OpUsage usage = new OpUsage(packageName, attributionTag, op, uid, lastAccessTime, isRunning, proxyUsage); Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/privacy/PrivacyDialogV2Test.kt +7 −7 Original line number Diff line number Diff line Loading @@ -24,8 +24,8 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.widget.TextView import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.res.R import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before Loading Loading @@ -62,7 +62,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { isPhoneCall: Boolean = false, isService: Boolean = false, permGroupName: String = TEST_PERM_GROUP, navigationIntent: Intent = TEST_INTENT navigationIntent: Intent = TEST_INTENT, ) = PrivacyDialogV2.PrivacyElement( type, Loading @@ -77,7 +77,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { isPhoneCall, isService, permGroupName, navigationIntent navigationIntent, ) } Loading Loading @@ -184,7 +184,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { val list = listOf( createPrivacyElement(type = PrivacyType.TYPE_CAMERA, isActive = true), createPrivacyElement() createPrivacyElement(), ) dialog = PrivacyDialogV2(context, list, manageApp, closeApp, openPrivacyDashboard) Loading Loading @@ -275,7 +275,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { createPrivacyElement( attributionLabel = "For subattribution", isActive = true, isService = true isService = true, ) ) dialog = PrivacyDialogV2(context, list, manageApp, closeApp, openPrivacyDashboard) Loading @@ -293,7 +293,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { createPrivacyElement( attributionLabel = "For subattribution", proxyLabel = "proxy label", isActive = true isActive = true, ) ) dialog = PrivacyDialogV2(context, list, manageApp, closeApp, openPrivacyDashboard) Loading @@ -308,7 +308,7 @@ class PrivacyDialogV2Test : SysuiTestCase() { dialog = PrivacyDialogV2(context, list, manageApp, closeApp, openPrivacyDashboard) dialog.show() assertThat(dialog.window?.attributes?.title).isEqualTo("Microphone & Camera") assertThat(dialog.window?.attributes?.title).isEqualTo("Microphone, Camera & Location") } @Test Loading
packages/SystemUI/res/values/strings.xml +1 −1 Original line number Diff line number Diff line Loading @@ -3957,7 +3957,7 @@ <string name="connected_display_icon_desc">Display connected</string> <!-- Title of the privacy dialog, shown for active / recent app usage of some phone sensors [CHAR LIMIT=30] --> <string name="privacy_dialog_title">Microphone & Camera</string> <string name="privacy_dialog_title">Microphone, Camera & Location</string> <!-- Subtitle of the privacy dialog, shown for active / recent app usage of some phone sensors [CHAR LIMIT=NONE] --> <string name="privacy_dialog_summary">Recent app use</string> <!-- Label of the secondary button of the privacy dialog, used to check recent app usage of phone sensors [CHAR LIMIT=30] --> Loading
packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt +12 −0 Original line number Diff line number Diff line Loading @@ -267,6 +267,12 @@ constructor( return true } /** * Returns true if the package is a system app. * * <p>TODO(b/422799135): refactor isSystemApp() and isBackgroundApp(). Before this is fixed, * make sure to update PermissionUsageHelper when changing this method. */ private fun isSystemApp(item: AppOpItem): Boolean { val user = UserHandle.getUserHandleForUid(item.uid) Loading Loading @@ -299,6 +305,12 @@ constructor( } } /** * Returns true if it is a background app * * <p>TODO(b/422799135): refactor isSystemApp() and isBackgroundApp(). Before this is fixed, * make sure to update PermissionUsageHelper when changing this method. */ private fun isBackgroundApp(item: AppOpItem): Boolean { for (processInfo in activityManager.runningAppProcesses) { if (processInfo.uid == item.uid) { Loading