Loading core/java/android/permission/PermissionUsageHelper.java +14 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.icu.text.ListFormatter; import android.location.LocationManager; import android.media.AudioManager; import android.os.Process; import android.os.UserHandle; Loading Loading @@ -411,10 +412,13 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis } /** * Returns true if the app supports subattribution. * Returns true if the app satisfies subattribution policies and supports it */ private boolean isSubattributionSupported(String packageName, int uid) { try { if (!isLocationProvider(packageName)) { return false; } PackageManager userPkgManager = getUserContext(UserHandle.getUserHandleForUid(uid)).getPackageManager(); ApplicationInfo appInfo = userPkgManager.getApplicationInfoAsUser(packageName, Loading @@ -429,6 +433,15 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis } } /** * @param packageName * @return If the package is location provider */ private boolean isLocationProvider(String packageName) { return Objects.requireNonNull( mContext.getSystemService(LocationManager.class)).isProviderPackage(packageName); } /** * 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 Loading packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt +20 −11 Original line number Diff line number Diff line Loading @@ -150,11 +150,12 @@ class PrivacyDialogController( packageName: String, userId: Int, permGroupName: CharSequence, attributionTag: CharSequence? attributionTag: CharSequence?, isAttributionSupported: Boolean ): Intent { lateinit var intent: Intent if (attributionTag != null) { if (attributionTag != null && isAttributionSupported) { intent = Intent(Intent.ACTION_MANAGE_PERMISSION_USAGE) intent.setPackage(packageName) intent.putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, permGroupName.toString()) Loading @@ -162,13 +163,15 @@ class PrivacyDialogController( intent.putExtra(Intent.EXTRA_SHOWING_ATTRIBUTION, true) val resolveInfo = packageManager.resolveActivity( intent, PackageManager.ResolveInfoFlags.of(0)) ?: return getDefaultManageAppPermissionsIntent(packageName, userId) if (resolveInfo != null && resolveInfo.activityInfo != null && resolveInfo.activityInfo.permission == android.Manifest.permission.START_VIEW_PERMISSION_USAGE) { intent.component = ComponentName(packageName, resolveInfo.activityInfo.name) return intent } else { return getDefaultManageAppPermissionsIntent(packageName, userId) } } return getDefaultManageAppPermissionsIntent(packageName, userId) } fun getDefaultManageAppPermissionsIntent(packageName: String, userId: Int): Intent { val intent = Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS) Loading Loading @@ -226,9 +229,15 @@ class PrivacyDialogController( userInfo?.isManagedProfile ?: false, it.isPhoneCall, it.permissionGroupName, getManagePermissionIntent(it.packageName, userId, getManagePermissionIntent( it.packageName, userId, it.permissionGroupName, it.attributionTag) it.attributionTag, // attributionLabel is set only when subattribution policies // are supported and satisfied it.attributionLabel != null ) ) } } else { Loading packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt +92 −0 Original line number Diff line number Diff line Loading @@ -19,8 +19,11 @@ package com.android.systemui.privacy import android.app.ActivityManager import android.content.Context import android.content.Intent import android.content.pm.ActivityInfo import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.content.pm.PackageManager.ResolveInfoFlags import android.content.pm.ResolveInfo import android.content.pm.UserInfo import android.os.Process.SYSTEM_UID import android.os.UserHandle Loading Loading @@ -648,6 +651,77 @@ class PrivacyDialogControllerTest : SysuiTestCase() { } } @Test fun testCorrectIntentSubAttribution() { val usage = createMockPermGroupUsage( attributionTag = TEST_ATTRIBUTION_TAG, attributionLabel = "TEST_LABEL" ) val activityInfo = createMockActivityInfo() val resolveInfo = createMockResolveInfo(activityInfo) `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage)) `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>())) .thenAnswer { resolveInfo } controller.showDialog(context) exhaustExecutors() dialogProvider.list?.let { list -> val navigationIntent = list.get(0).navigationIntent!! assertThat(navigationIntent.action).isEqualTo(Intent.ACTION_MANAGE_PERMISSION_USAGE) assertThat(navigationIntent.getStringExtra(Intent.EXTRA_PERMISSION_GROUP_NAME)) .isEqualTo(PERM_CAMERA) assertThat(navigationIntent.getStringArrayExtra(Intent.EXTRA_ATTRIBUTION_TAGS)) .isEqualTo(arrayOf(TEST_ATTRIBUTION_TAG.toString())) assertThat(navigationIntent.getBooleanExtra(Intent.EXTRA_SHOWING_ATTRIBUTION, false)) .isTrue() } } @Test fun testDefaultIntentOnMissingAttributionLabel() { val usage = createMockPermGroupUsage( attributionTag = TEST_ATTRIBUTION_TAG ) val activityInfo = createMockActivityInfo() val resolveInfo = createMockResolveInfo(activityInfo) `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage)) `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>())) .thenAnswer { resolveInfo } controller.showDialog(context) exhaustExecutors() dialogProvider.list?.let { list -> assertThat(isIntentEqual(list.get(0).navigationIntent!!, controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID))) .isTrue() } } @Test fun testDefaultIntentOnIncorrectPermission() { val usage = createMockPermGroupUsage( attributionTag = TEST_ATTRIBUTION_TAG ) val activityInfo = createMockActivityInfo( permission = "INCORRECT_PERMISSION" ) val resolveInfo = createMockResolveInfo(activityInfo) `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage)) `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>())) .thenAnswer { resolveInfo } controller.showDialog(context) exhaustExecutors() dialogProvider.list?.let { list -> assertThat(isIntentEqual(list.get(0).navigationIntent!!, controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID))) .isTrue() } } private fun exhaustExecutors() { FakeExecutor.exhaustExecutors(backgroundExecutor, uiExecutor) } Loading Loading @@ -680,6 +754,24 @@ class PrivacyDialogControllerTest : SysuiTestCase() { return user * UserHandle.PER_USER_RANGE + nextUid++ } private fun createMockResolveInfo( activityInfo: ActivityInfo? = null ): ResolveInfo { val resolveInfo = mock(ResolveInfo::class.java) resolveInfo.activityInfo = activityInfo return resolveInfo } private fun createMockActivityInfo( permission: String = android.Manifest.permission.START_VIEW_PERMISSION_USAGE, className: String = "TEST_CLASS_NAME" ): ActivityInfo { val activityInfo = mock(ActivityInfo::class.java) activityInfo.permission = permission activityInfo.name = className return activityInfo } private fun createMockPermGroupUsage( packageName: String = TEST_PACKAGE_NAME, uid: Int = generateUidForUser(USER_ID), Loading Loading
core/java/android/permission/PermissionUsageHelper.java +14 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.icu.text.ListFormatter; import android.location.LocationManager; import android.media.AudioManager; import android.os.Process; import android.os.UserHandle; Loading Loading @@ -411,10 +412,13 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis } /** * Returns true if the app supports subattribution. * Returns true if the app satisfies subattribution policies and supports it */ private boolean isSubattributionSupported(String packageName, int uid) { try { if (!isLocationProvider(packageName)) { return false; } PackageManager userPkgManager = getUserContext(UserHandle.getUserHandleForUid(uid)).getPackageManager(); ApplicationInfo appInfo = userPkgManager.getApplicationInfoAsUser(packageName, Loading @@ -429,6 +433,15 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis } } /** * @param packageName * @return If the package is location provider */ private boolean isLocationProvider(String packageName) { return Objects.requireNonNull( mContext.getSystemService(LocationManager.class)).isProviderPackage(packageName); } /** * 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 Loading
packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt +20 −11 Original line number Diff line number Diff line Loading @@ -150,11 +150,12 @@ class PrivacyDialogController( packageName: String, userId: Int, permGroupName: CharSequence, attributionTag: CharSequence? attributionTag: CharSequence?, isAttributionSupported: Boolean ): Intent { lateinit var intent: Intent if (attributionTag != null) { if (attributionTag != null && isAttributionSupported) { intent = Intent(Intent.ACTION_MANAGE_PERMISSION_USAGE) intent.setPackage(packageName) intent.putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, permGroupName.toString()) Loading @@ -162,13 +163,15 @@ class PrivacyDialogController( intent.putExtra(Intent.EXTRA_SHOWING_ATTRIBUTION, true) val resolveInfo = packageManager.resolveActivity( intent, PackageManager.ResolveInfoFlags.of(0)) ?: return getDefaultManageAppPermissionsIntent(packageName, userId) if (resolveInfo != null && resolveInfo.activityInfo != null && resolveInfo.activityInfo.permission == android.Manifest.permission.START_VIEW_PERMISSION_USAGE) { intent.component = ComponentName(packageName, resolveInfo.activityInfo.name) return intent } else { return getDefaultManageAppPermissionsIntent(packageName, userId) } } return getDefaultManageAppPermissionsIntent(packageName, userId) } fun getDefaultManageAppPermissionsIntent(packageName: String, userId: Int): Intent { val intent = Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS) Loading Loading @@ -226,9 +229,15 @@ class PrivacyDialogController( userInfo?.isManagedProfile ?: false, it.isPhoneCall, it.permissionGroupName, getManagePermissionIntent(it.packageName, userId, getManagePermissionIntent( it.packageName, userId, it.permissionGroupName, it.attributionTag) it.attributionTag, // attributionLabel is set only when subattribution policies // are supported and satisfied it.attributionLabel != null ) ) } } else { Loading
packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt +92 −0 Original line number Diff line number Diff line Loading @@ -19,8 +19,11 @@ package com.android.systemui.privacy import android.app.ActivityManager import android.content.Context import android.content.Intent import android.content.pm.ActivityInfo import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.content.pm.PackageManager.ResolveInfoFlags import android.content.pm.ResolveInfo import android.content.pm.UserInfo import android.os.Process.SYSTEM_UID import android.os.UserHandle Loading Loading @@ -648,6 +651,77 @@ class PrivacyDialogControllerTest : SysuiTestCase() { } } @Test fun testCorrectIntentSubAttribution() { val usage = createMockPermGroupUsage( attributionTag = TEST_ATTRIBUTION_TAG, attributionLabel = "TEST_LABEL" ) val activityInfo = createMockActivityInfo() val resolveInfo = createMockResolveInfo(activityInfo) `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage)) `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>())) .thenAnswer { resolveInfo } controller.showDialog(context) exhaustExecutors() dialogProvider.list?.let { list -> val navigationIntent = list.get(0).navigationIntent!! assertThat(navigationIntent.action).isEqualTo(Intent.ACTION_MANAGE_PERMISSION_USAGE) assertThat(navigationIntent.getStringExtra(Intent.EXTRA_PERMISSION_GROUP_NAME)) .isEqualTo(PERM_CAMERA) assertThat(navigationIntent.getStringArrayExtra(Intent.EXTRA_ATTRIBUTION_TAGS)) .isEqualTo(arrayOf(TEST_ATTRIBUTION_TAG.toString())) assertThat(navigationIntent.getBooleanExtra(Intent.EXTRA_SHOWING_ATTRIBUTION, false)) .isTrue() } } @Test fun testDefaultIntentOnMissingAttributionLabel() { val usage = createMockPermGroupUsage( attributionTag = TEST_ATTRIBUTION_TAG ) val activityInfo = createMockActivityInfo() val resolveInfo = createMockResolveInfo(activityInfo) `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage)) `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>())) .thenAnswer { resolveInfo } controller.showDialog(context) exhaustExecutors() dialogProvider.list?.let { list -> assertThat(isIntentEqual(list.get(0).navigationIntent!!, controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID))) .isTrue() } } @Test fun testDefaultIntentOnIncorrectPermission() { val usage = createMockPermGroupUsage( attributionTag = TEST_ATTRIBUTION_TAG ) val activityInfo = createMockActivityInfo( permission = "INCORRECT_PERMISSION" ) val resolveInfo = createMockResolveInfo(activityInfo) `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage)) `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>())) .thenAnswer { resolveInfo } controller.showDialog(context) exhaustExecutors() dialogProvider.list?.let { list -> assertThat(isIntentEqual(list.get(0).navigationIntent!!, controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID))) .isTrue() } } private fun exhaustExecutors() { FakeExecutor.exhaustExecutors(backgroundExecutor, uiExecutor) } Loading Loading @@ -680,6 +754,24 @@ class PrivacyDialogControllerTest : SysuiTestCase() { return user * UserHandle.PER_USER_RANGE + nextUid++ } private fun createMockResolveInfo( activityInfo: ActivityInfo? = null ): ResolveInfo { val resolveInfo = mock(ResolveInfo::class.java) resolveInfo.activityInfo = activityInfo return resolveInfo } private fun createMockActivityInfo( permission: String = android.Manifest.permission.START_VIEW_PERMISSION_USAGE, className: String = "TEST_CLASS_NAME" ): ActivityInfo { val activityInfo = mock(ActivityInfo::class.java) activityInfo.permission = permission activityInfo.name = className return activityInfo } private fun createMockPermGroupUsage( packageName: String = TEST_PACKAGE_NAME, uid: Int = generateUidForUser(USER_ID), Loading