summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-06 20:28:03 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-06 20:51:16 +0000
commit2d19b81dcf1d49abb601d5e7b42c973820e29b50 (patch)
treed8233d168aadb9eede68eaed91510dda3ca2db3e
parent33f5866afb1347c79c5fa1b91be1eef0aa5d5581 (diff)
parent453c6a1caed053b2f6f43bdcdb8f8c76758e0c07 (diff)
downloadPermission-2d19b81dcf1d49abb601d5e7b42c973820e29b50.tar.gz
Make change and version bump to aml_per_341310000 for mainline module file: PermissionController/AndroidManifest.xml
Make change and version bump to aml_per_341310000 for mainline module file: apex_manifest.json Snap for 11028996 from 453c6a1caed053b2f6f43bdcdb8f8c76758e0c07 to mainline-permission-release Change-Id: Ie62f8fe18e4332400c527ad3c65dce95f190cf78
-rw-r--r--PermissionController/AndroidManifest.xml4
-rw-r--r--PermissionController/res/drawable/ic_edit.xml24
-rw-r--r--PermissionController/res/layout-v33/preference_entries_top_padding.xml (renamed from PermissionController/res/layout-v33/spaced_preference_category_no_label.xml)4
-rw-r--r--PermissionController/res/layout/app_permission.xml47
-rw-r--r--PermissionController/res/values-af/strings.xml8
-rw-r--r--PermissionController/res/values-am/strings.xml2
-rw-r--r--PermissionController/res/values-ar/strings.xml4
-rw-r--r--PermissionController/res/values-as/strings.xml2
-rw-r--r--PermissionController/res/values-az/strings.xml2
-rw-r--r--PermissionController/res/values-b+sr+Latn/strings.xml28
-rw-r--r--PermissionController/res/values-be/strings.xml2
-rw-r--r--PermissionController/res/values-bg/strings.xml2
-rw-r--r--PermissionController/res/values-bn/strings.xml2
-rw-r--r--PermissionController/res/values-bs/strings.xml2
-rw-r--r--PermissionController/res/values-ca/strings.xml2
-rw-r--r--PermissionController/res/values-cs/strings.xml6
-rw-r--r--PermissionController/res/values-da/strings.xml2
-rw-r--r--PermissionController/res/values-de/strings.xml4
-rw-r--r--PermissionController/res/values-el-v33/strings.xml2
-rw-r--r--PermissionController/res/values-el/strings.xml62
-rw-r--r--PermissionController/res/values-en-rAU/strings.xml2
-rw-r--r--PermissionController/res/values-en-rCA/strings.xml1
-rw-r--r--PermissionController/res/values-en-rGB/strings.xml2
-rw-r--r--PermissionController/res/values-en-rIN/strings.xml2
-rw-r--r--PermissionController/res/values-en-rXC/strings.xml1
-rw-r--r--PermissionController/res/values-es-rUS/strings.xml4
-rw-r--r--PermissionController/res/values-es/strings.xml2
-rw-r--r--PermissionController/res/values-et/strings.xml2
-rw-r--r--PermissionController/res/values-eu/strings.xml20
-rw-r--r--PermissionController/res/values-fa/strings.xml2
-rw-r--r--PermissionController/res/values-fi/strings.xml4
-rw-r--r--PermissionController/res/values-fr-rCA/strings.xml2
-rw-r--r--PermissionController/res/values-fr/strings.xml2
-rw-r--r--PermissionController/res/values-gl/strings.xml2
-rw-r--r--PermissionController/res/values-gu/strings.xml6
-rw-r--r--PermissionController/res/values-hi/strings.xml6
-rw-r--r--PermissionController/res/values-hr/strings.xml2
-rw-r--r--PermissionController/res/values-hu/strings.xml2
-rw-r--r--PermissionController/res/values-hy/strings.xml2
-rw-r--r--PermissionController/res/values-in/strings.xml4
-rw-r--r--PermissionController/res/values-is/strings.xml2
-rw-r--r--PermissionController/res/values-it/strings.xml10
-rw-r--r--PermissionController/res/values-iw/strings.xml2
-rw-r--r--PermissionController/res/values-ja/strings.xml2
-rw-r--r--PermissionController/res/values-ka/strings.xml2
-rw-r--r--PermissionController/res/values-kk/strings.xml2
-rw-r--r--PermissionController/res/values-km/strings.xml2
-rw-r--r--PermissionController/res/values-kn/strings.xml8
-rw-r--r--PermissionController/res/values-ko/strings.xml2
-rw-r--r--PermissionController/res/values-ky/strings.xml2
-rw-r--r--PermissionController/res/values-lo/strings.xml2
-rw-r--r--PermissionController/res/values-lt/strings.xml2
-rw-r--r--PermissionController/res/values-lv/strings.xml2
-rw-r--r--PermissionController/res/values-mk/strings.xml2
-rw-r--r--PermissionController/res/values-ml/strings.xml2
-rw-r--r--PermissionController/res/values-mn/strings.xml2
-rw-r--r--PermissionController/res/values-mr/strings.xml2
-rw-r--r--PermissionController/res/values-ms/strings.xml2
-rw-r--r--PermissionController/res/values-my/strings.xml2
-rw-r--r--PermissionController/res/values-nb/strings.xml2
-rw-r--r--PermissionController/res/values-ne/strings.xml2
-rw-r--r--PermissionController/res/values-nl/strings.xml2
-rw-r--r--PermissionController/res/values-or/strings.xml4
-rw-r--r--PermissionController/res/values-pa/strings.xml2
-rw-r--r--PermissionController/res/values-pl/strings.xml6
-rw-r--r--PermissionController/res/values-pt-rBR/strings.xml4
-rw-r--r--PermissionController/res/values-pt-rPT/strings.xml2
-rw-r--r--PermissionController/res/values-pt/strings.xml4
-rw-r--r--PermissionController/res/values-ro/strings.xml2
-rw-r--r--PermissionController/res/values-ru/strings.xml6
-rw-r--r--PermissionController/res/values-si/strings.xml2
-rw-r--r--PermissionController/res/values-sk/strings.xml2
-rw-r--r--PermissionController/res/values-sl/strings.xml2
-rw-r--r--PermissionController/res/values-sq/strings.xml8
-rw-r--r--PermissionController/res/values-sr/strings.xml28
-rw-r--r--PermissionController/res/values-sv/strings.xml2
-rw-r--r--PermissionController/res/values-sw/strings.xml2
-rw-r--r--PermissionController/res/values-ta/strings.xml2
-rw-r--r--PermissionController/res/values-te/strings.xml4
-rw-r--r--PermissionController/res/values-th/strings.xml2
-rw-r--r--PermissionController/res/values-tl/strings.xml6
-rw-r--r--PermissionController/res/values-tr/strings.xml2
-rw-r--r--PermissionController/res/values-uk/strings.xml4
-rw-r--r--PermissionController/res/values-ur/strings.xml2
-rw-r--r--PermissionController/res/values-uz/strings.xml2
-rw-r--r--PermissionController/res/values-v31/styles.xml2
-rw-r--r--PermissionController/res/values-v33/styles.xml6
-rw-r--r--PermissionController/res/values-vi/strings.xml2
-rw-r--r--PermissionController/res/values-zh-rCN/strings.xml6
-rw-r--r--PermissionController/res/values-zh-rHK-v34/strings.xml2
-rw-r--r--PermissionController/res/values-zh-rHK/strings.xml6
-rw-r--r--PermissionController/res/values-zh-rTW/strings.xml4
-rw-r--r--PermissionController/res/values-zu/strings.xml2
-rw-r--r--PermissionController/res/values/strings.xml3
-rw-r--r--PermissionController/res/xml/safety_center_dashboard.xml7
-rw-r--r--PermissionController/src/com/android/permissioncontroller/DumpableLog.kt36
-rw-r--r--PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt200
-rw-r--r--PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt734
-rw-r--r--PermissionController/src/com/android/permissioncontroller/hibernation/v31/HibernationController.kt19
-rw-r--r--PermissionController/src/com/android/permissioncontroller/hibernation/v31/InstallerPackagesLiveData.kt12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/AllPackageInfosLiveData.kt8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/AppOpLiveData.kt19
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt224
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveData.kt61
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/AutoRevokedPackagesLiveData.kt26
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/BroadcastReceiverLiveData.kt57
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/CarrierPrivilegedStatusLiveData.kt13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/CustomPermGroupNamesLiveData.kt19
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/DataRepository.kt74
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/DisabledPrintServicesLiveData.kt23
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/EnabledAccessibilityServicesLiveData.kt11
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/EnabledDeviceAdminsLiveData.kt14
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/EnabledDreamServicesLiveData.kt23
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/EnabledInputMethodsLiveData.kt18
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/EnabledNotificationListenersLiveData.kt24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/ForegroundPermNamesLiveData.kt13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/FullStoragePermissionAppsLiveData.kt88
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/HasIntentAction.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/HibernatedPackagesLiveData.kt47
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt103
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/LauncherPackagesLiveData.kt34
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt77
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/LightPackageInfoLiveData.kt92
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/LightPermInfoLiveData.kt37
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/LoadAndFreezeLifeData.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/MicMutedLiveData.kt50
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/OpUsageLiveData.kt114
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PackageBroadcastReceiver.kt49
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PackagePermissionsLiveData.kt54
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupLiveData.kt52
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupUsageLiveData.kt56
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesLiveData.kt40
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesUiInfoLiveData.kt56
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PermStateLiveData.kt50
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PermissionChange.kt10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PermissionEvent.kt9
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PermissionListenerMultiplexer.kt15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PreinstalledUserPackageInfosLiveData.kt24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/RoleHoldersLiveData.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/RoleListenerMultiplexer.kt18
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/SelectedAutofillServiceLiveData.kt20
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/SelectedVoiceInteractionServiceLiveData.kt24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/SelectedWallpaperServiceLiveData.kt22
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/ServiceLiveData.kt134
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/SinglePermGroupPackagesUiInfoLiveData.kt81
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/SmartAsyncMediatorLiveData.kt16
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/SmartUpdateMediatorLiveData.kt47
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/StandardPermGroupNamesLiveData.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/UnusedPackagesLiveData.kt39
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/UsageStatsLiveData.kt15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/UserPackageInfosLiveData.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/UserSensitivityLiveData.kt108
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/UsersLiveData.kt21
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightPackageOpsLiveData.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/v33/RecentPermissionDecisionsLiveData.kt8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/v34/AppDataSharingUpdatesLiveData.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/v34/LightInstallSourceInfoLiveData.kt9
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/v34/SafetyLabelInfoLiveData.kt8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/HibernationSettingState.kt14
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt185
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermGroupInfo.kt17
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermInfo.kt24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermission.kt46
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/PermGroup.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/PermGroupPackagesUiInfo.kt18
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/UidSensitivityState.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt17
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightPackageOps.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v34/LightInstallSourceInfo.kt10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v34/SafetyLabelInfo.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt182
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/BackupHelper.java4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/BasePermissionEventStorage.kt57
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/CheckLifecycleRegistry.kt10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/ExemptRestrictedPermission.kt13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionChangeStorageImpl.kt57
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceModel.kt110
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventCleanupJobService.kt47
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventStorage.kt14
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventStorageImpls.kt11
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionStorageTimeChangeReceiver.kt42
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PersistedStoragePackageUninstalledReceiver.kt10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt580
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/SplitPermissionIndex.kt24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/v33/PermissionDecisionStorageImpl.kt62
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/Category.kt3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java7
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/RemovablePref.kt14
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/UnusedAppsFragment.kt172
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoDividerPreference.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoPermissionAppsFragment.java11
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsFragment.kt168
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsViewAllFragment.kt42
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoUnusedAppsFragment.kt27
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoUnusedAppsPreference.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionHistoryPreference.kt9
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageFragment.kt25
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java47
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/FooterPreference.kt8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt351
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/HandheldUnusedAppsFragment.kt21
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/HandheldUnusedAppsWrapperFragment.kt17
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java17
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SmartIconLoadPackagePermissionPreference.kt9
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/UnusedAppPreference.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/Utils.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/DashboardUtils.kt78
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionHistoryPreference.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionUsageDetailsFragment.java12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFragment.kt27
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageDetailsViewModelLegacy.kt89
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageViewModelLegacy.kt23
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/AllAppPermissionsViewModel.kt55
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt419
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt961
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt1560
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManageCustomPermissionsViewModel.kt26
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManagePermissionsViewModel.kt76
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManageStandardPermissionsViewModel.kt26
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt220
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/ReviewPermissionsViewModel.kt91
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/UnusedAppsViewModel.kt193
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageControlPreferenceUtils.kt61
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt128
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageViewModel.kt52
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/ReviewOngoingUsageViewModel.kt759
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/v33/ReviewPermissionDecisionsViewModel.kt149
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt102
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/television/TvUnusedAppsFragment.kt24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/television/TvUnusedAppsPreference.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/v33/AdvancedConfirmDialogArgs.kt3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/v33/widget/SafetyProtectionSectionView.kt18
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/v34/PermissionRationaleViewHandler.kt10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/AndroidUtils.kt55
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/DebugUtils.kt23
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt36
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt49
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/SystemTimeSource.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/TimeSource.kt14
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/UserSensitiveFlagsUtils.kt57
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySettingsUtil.kt43
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt399
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/AutoRevokePrivacySource.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/LocationAccessPrivacySource.kt3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerCheck.kt162
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySourceData.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySourceStorageRepository.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/TextStorageRepository.kt18
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/WorkPolicyInfo.kt36
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/v34/AppDataSharingUpdatesPrivacySource.kt13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/CollapsableGroupCardHelper.kt9
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ComparablePreference.kt7
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ComparablePreferenceCategory.kt14
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EntriesTopPaddingPreference.kt13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EqualWidthContainer.kt3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/InteractionLogger.kt5
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/MoreIssuesCardAnimator.kt16
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ParsedSafetyCenterIntent.kt9
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PositionInCardList.kt10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PrivacySubpageFragment.kt17
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterTouchTarget.kt1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java18
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SpacerPreference.kt59
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StatusAnimationResolver.kt31
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/TextFadeAnimator.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterQsViewModel.kt39
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryGroupView.kt10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistory.kt12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistoryPersistence.kt60
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetylabel/SafetyLabelChangedBroadcastReceiver.kt23
-rw-r--r--PermissionController/tests/inprocess/AppThatUsesCameraPermission/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt3
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/GetPermissionGroupInfoTest.kt10
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveDataTest.kt6
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/DataUtils.kt11
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt3
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt47
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt34
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt74
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/hibernation/HibernationControllerTest.kt35
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/hibernation/HibernationPolicyTest.kt56
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/data/FakeEventStorage.kt4
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/data/v33/RecentPermissionDecisionsLiveDataTest.kt16
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/BasePermissionEventStorageTest.kt63
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionChangeStorageImplTest.kt63
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionEventCleanupJobServiceTest.kt31
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionStorageTimeChangeReceiverTest.kt54
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PersistedStoragePackageUninstalledReceiverTest.kt38
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/RuntimePermissionsUpgradeControllerTest.kt319
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/v33/PermissionDecisionStorageImplTest.kt33
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/handheld/v31/DashboardUtilsTest.kt138
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/model/ReviewPermissionsViewModelTest.kt164
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt518
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/StringUtilsTest.kt58
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/AccessibilitySourceServiceTest.kt36
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/AppDataSharingUpdatesPrivacySourceTest.kt39
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerCheckInternalTest.kt51
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerPregrantsTest.kt8
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerPrivacySourceTest.kt173
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/SafetyCenterReceiverTest.kt71
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/TextStorageRepositoryTest.kt52
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/WorkPolicyInfoTest.kt64
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/StatusUiDataTest.kt51
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryPersistenceTest.kt195
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryTest.kt84
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/SafetyLabelChangesJobServiceTest.kt10
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/TestSafetyLabels.kt20
-rw-r--r--PermissionController/tests/outofprocess/src/com/android/permissioncontroller/tests/outofprocess/DumpTest.kt8
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionGroupPreferenceUtils.kt22
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionHub2Test.kt48
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/UiUtils.kt10
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AllAppPermissionsFragmentTest.kt36
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AppPermissionFragmentTest.kt41
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/BasePermissionUiTest.kt14
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/CustomPermissionAppsFragmentTest.kt26
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAllAppPermissionFragmentTest.kt40
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAppPermissionFragmentTest.kt29
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/LocationPermissionAppsFragmentTest.kt12
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/PermissionAppsFragmentTest.kt23
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/StoragePermissionAppsFragmentTest.kt14
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/TestAppUtils.kt11
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/BaseHandheldPermissionUiTest.kt5
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageCustomPermissionsFragmentTest.kt22
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageStandardPermissionsFragmentTest.kt47
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ReviewOngoingUsageFragmentTest.kt17
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/v31/PermissionUsageFragmentTest.kt5
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/ManagePermissionsFragmentTest.kt41
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/ManagePermissionsOtherFragmentTest.kt38
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/TelevisionUiBaseTest.kt16
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/TelevisionUtils.kt27
-rw-r--r--SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresTiramisuByDefault.java40
-rw-r--r--SafetyCenter/Resources/res/values-da/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-eu-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-it/strings.xml2
-rw-r--r--SafetyCenter/Resources/shared_res/values-ca/strings.xml2
-rw-r--r--SafetyCenter/Resources/shared_res/values-ja/strings.xml2
-rw-r--r--apex_manifest.json2
-rw-r--r--framework-s/java/android/app/role/RoleManager.java2
-rw-r--r--framework-s/java/android/safetycenter/SafetySourceIssue.java2
-rw-r--r--ktfmt_includes.txt1
-rw-r--r--service/java/com/android/safetycenter/PendingIntentFactory.java38
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterFlags.java79
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterService.java14
-rw-r--r--service/java/com/android/safetycenter/data/AndroidLockScreenFix.java148
-rw-r--r--service/java/com/android/safetycenter/data/DefaultActionOverrideFix.java180
-rw-r--r--service/java/com/android/safetycenter/data/SafetySourceDataFix.java76
-rw-r--r--service/java/com/android/safetycenter/data/SafetySourceDataOverrides.java81
-rw-r--r--service/java/com/android/safetycenter/data/package-info.java7
-rw-r--r--service/java/com/android/safetycenter/logging/package-info.java7
-rw-r--r--service/java/com/android/safetycenter/notifications/SafetyCenterNotificationFactory.java4
-rw-r--r--service/java/com/android/safetycenter/notifications/package-info.java7
-rw-r--r--service/java/com/android/safetycenter/package-info.java7
-rw-r--r--tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt105
-rw-r--r--tests/functional/safetycenter/safetycenteractivity/src/android/safetycenter/functional/ui/SafetyCenterActivityTest.kt31
-rw-r--r--tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt171
-rw-r--r--tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterNotificationTest.kt60
-rw-r--r--tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetySourceDataFixesTest.kt298
-rw-r--r--tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterStatusCardTest.kt25
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt17
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt61
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestData.kt23
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt146
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/TestNotificationListener.kt36
371 files changed, 10361 insertions, 7328 deletions
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml
index a0d9de9c2..ac7f8ef41 100644
--- a/PermissionController/AndroidManifest.xml
+++ b/PermissionController/AndroidManifest.xml
@@ -4,8 +4,8 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.android.permissioncontroller"
coreApp="true"
- android:versionCode="341110000"
- android:versionName="aml_per_341110000"
+ android:versionCode="341310000"
+ android:versionName="aml_per_341310000"
>
<original-package android:name="com.android.permissioncontroller" />
diff --git a/PermissionController/res/drawable/ic_edit.xml b/PermissionController/res/drawable/ic_edit.xml
new file mode 100644
index 000000000..6b806a894
--- /dev/null
+++ b/PermissionController/res/drawable/ic_edit.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+android:width="24dp"
+android:height="24dp"
+android:viewportWidth="24"
+android:viewportHeight="24"
+android:tint="?android:attr/colorControlNormal">
+<path android:fillColor="#FFFFFFFF"
+ android:pathData="M5,19H6.4L16.45,8.975L15.75,8.25L15.025,7.55L5,17.6ZM3,21V16.75L16.45,3.325Q17.025,2.75 17.863,2.75Q18.7,2.75 19.275,3.325L20.675,4.75Q21.25,5.325 21.25,6.15Q21.25,6.975 20.675,7.55L7.25,21ZM19.25,6.15 L17.85,4.75ZM16.45,8.975 L15.75,8.25 15.025,7.55 16.45,8.975Z"/>
+</vector> \ No newline at end of file
diff --git a/PermissionController/res/layout-v33/spaced_preference_category_no_label.xml b/PermissionController/res/layout-v33/preference_entries_top_padding.xml
index cecdc8bcd..0e6e27148 100644
--- a/PermissionController/res/layout-v33/spaced_preference_category_no_label.xml
+++ b/PermissionController/res/layout-v33/preference_entries_top_padding.xml
@@ -15,4 +15,6 @@
-->
<Space
- style="@style/SafetyCenterNoLabelPreferenceCategory"/> \ No newline at end of file
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/sc_spacing_xsmall" /> \ No newline at end of file
diff --git a/PermissionController/res/layout/app_permission.xml b/PermissionController/res/layout/app_permission.xml
index 6d68611fa..6520d79fa 100644
--- a/PermissionController/res/layout/app_permission.xml
+++ b/PermissionController/res/layout/app_permission.xml
@@ -83,12 +83,6 @@
android:id="@+id/permission_message"
style="@style/AppPermissionMessage" />
- <RadioGroup
- android:id="@+id/radiogroup"
- android:animateLayoutChanges="true"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
<RadioButton
android:id="@+id/allow_radio_button"
android:text="@string/app_permission_button_allow"
@@ -104,10 +98,42 @@
android:text="@string/app_permission_button_allow_foreground"
style="@style/AppPermissionRadioButton" />
- <RadioButton
- android:id="@+id/select_radio_button"
- android:text="@string/app_permission_button_ask"
- style="@style/AppPermissionRadioButton" />
+ <RelativeLayout
+ android:id="@+id/radio_select_layout"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_marginTop="16dp"
+ android:layout_height="wrap_content">
+
+ <RadioButton
+ android:id="@+id/select_radio_button"
+ android:text="@string/app_permission_button_ask"
+ android:layout_alignParentStart="true"
+ style="@style/AppPermissionRadioButton"
+ android:layout_marginTop="0dp" />
+
+ <View
+ android:id="@+id/edit_photos_divider"
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:layout_toStartOf="@id/edit_selected_button"
+ android:layout_alignParentTop="true"
+ android:layout_alignBottom="@+id/select_radio_button"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:theme="@style/PreferenceDivider"/>
+
+ <ImageButton
+ android:id="@+id/edit_selected_button"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_alignParentEnd="true"
+ android:layout_centerVertical="true"
+ android:contentDescription="@string/edit_photos_description"
+ style="SettingsActionButton"
+ android:background="@null"
+ android:src="@drawable/ic_edit"/>
+ </RelativeLayout>
<RadioButton
android:id="@+id/ask_one_time_radio_button"
@@ -129,7 +155,6 @@
android:text="@string/app_permission_button_deny"
style="@style/AppPermissionRadioButton" />
- </RadioGroup>
<LinearLayout
android:layout_width="match_parent"
diff --git a/PermissionController/res/values-af/strings.xml b/PermissionController/res/values-af/strings.xml
index 71ee7f3bc..637adc2f8 100644
--- a/PermissionController/res/values-af/strings.xml
+++ b/PermissionController/res/values-af/strings.xml
@@ -57,9 +57,11 @@
<string name="grant_dialog_button_allow_background" msgid="8236044729434367833">"Laat altyd toe"</string>
<string name="grant_dialog_button_allow_all_files" msgid="4955436994954829894">"Laat toe dat alle lêers bestuur word"</string>
<string name="grant_dialog_button_allow_media_only" msgid="4832877658422573832">"Laat toegang tot medialêers toe"</string>
- <string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Programme"</string>
+ <string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"Programtoestemmings"</string>
<string name="unused_apps" msgid="2058057455175955094">"Ongebruikte programme"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Geen ongebruikte programme nie"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 ongebruikte programme"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Onlangse toestemmingbesluite"</string>
@@ -337,7 +339,7 @@
<string name="app_perms_content_provider_7d_all_files" msgid="7962416229708835558">"In afgelope 7 dae gebruik • Alle lêers"</string>
<string name="no_permissions_allowed" msgid="6081976856354669209">"Geen toestemmings toegelaat nie"</string>
<string name="no_permissions_denied" msgid="8159923922804043282">"Geen toestemmings geweier nie"</string>
- <string name="no_apps_allowed" msgid="7718822655254468631">"Geen programme toegelaat nie"</string>
+ <string name="no_apps_allowed" msgid="7718822655254468631">"Geen apps toegelaat nie"</string>
<string name="no_apps_allowed_full" msgid="8011716991498934104">"Geen programme het toestemming vir alle lêers nie"</string>
<string name="no_apps_allowed_scoped" msgid="4908850477787659501">"Geen programme het toestemming net vir media nie"</string>
<string name="no_apps_denied" msgid="7663435886986784743">"Geen programme geweier nie"</string>
@@ -580,7 +582,7 @@
<string name="camera_toggle_title" msgid="1251201397431837666">"Kameratoegang"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Mikrofoontoegang"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"Vir apps en dienste"</string>
- <string name="mic_toggle_description" msgid="9163104307990677157">"Vir programme en dienste. As hierdie instelling af is, kan mikrofoondata steeds gedeel word wanneer jy ’n noodnommer bel."</string>
+ <string name="mic_toggle_description" msgid="9163104307990677157">"Vir apps en dienste. As hierdie instelling af is, kan mikrofoondata steeds gedeel word wanneer jy ’n noodnommer bel."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Sien programme en dienste met toegang tot ligging"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Wys knipbordtoegang"</string>
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Wys ’n boodskap wanneer apps toegang het tot teks, prente of ander inhoud wat jy gekopieer het"</string>
diff --git a/PermissionController/res/values-am/strings.xml b/PermissionController/res/values-am/strings.xml
index aa5edc983..6769dc0ea 100644
--- a/PermissionController/res/values-am/strings.xml
+++ b/PermissionController/res/values-am/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"መተግበሪያዎች"</string>
<string name="app_permissions" msgid="3369917736607944781">"የመተግበሪያ ፈቃዶች"</string>
<string name="unused_apps" msgid="2058057455175955094">"ጥቅም ላይ ያልዋሉ መተግበሪያዎች"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"አገልግሎት ላይ ያልዋሉ መተግበሪያዎች የሉም"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 ሥራ ላይ ያልዋሉ መተግበሪያዎች"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"የቅርብ ጊዜ የፈቃድ ውሳኔዎች"</string>
diff --git a/PermissionController/res/values-ar/strings.xml b/PermissionController/res/values-ar/strings.xml
index 92353fe85..a6c070b82 100644
--- a/PermissionController/res/values-ar/strings.xml
+++ b/PermissionController/res/values-ar/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"تطبيقات"</string>
<string name="app_permissions" msgid="3369917736607944781">"أذونات التطبيقات"</string>
<string name="unused_apps" msgid="2058057455175955094">"التطبيقات غير المستخدمة"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"ما مِن تطبيقات غير مستخدمة."</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"التطبيقات غير المستخدمة: 0"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"قرارات حديثة متعلقة بالأذونات"</string>
@@ -251,7 +253,7 @@
<string name="allowed_storage_scoped" msgid="5383645873719086975">"التطبيقات المسموح لها بالوصول إلى الوسائط فقط"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"التطبيقات المسموح لها بإدارة كل الملفات"</string>
<string name="ask_header" msgid="2633816846459944376">"الطلب في كل مرة"</string>
- <string name="denied_header" msgid="903209608358177654">"التطبيقات غير المسموح لها بالوصول"</string>
+ <string name="denied_header" msgid="903209608358177654">"التطبيقات غير المسموح لها"</string>
<string name="storage_footer_hyperlink_text" msgid="8873343987957834810">"الاطّلاع على تطبيقات أكثر يمكنها الوصول إلى كل الملفات"</string>
<string name="days" msgid="609563020985571393">"{count,plural, =1{يوم واحد}zero{# يوم}two{يومان}few{# أيام}many{# يومًا}other{# يوم}}"</string>
<string name="hours" msgid="7302866489666950038">"{count,plural, =1{ساعة واحدة}zero{# ساعة}two{ساعتان}few{# ساعات}many{# ساعةً}other{# ساعة}}"</string>
diff --git a/PermissionController/res/values-as/strings.xml b/PermissionController/res/values-as/strings.xml
index 2656530e4..f875aa75d 100644
--- a/PermissionController/res/values-as/strings.xml
+++ b/PermissionController/res/values-as/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"এপ্"</string>
<string name="app_permissions" msgid="3369917736607944781">"এপৰ অনুমতি"</string>
<string name="unused_apps" msgid="2058057455175955094">"অব্যৱহৃত এপ্‌সমূহ"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"ব্যৱহাৰ নকৰা কোনো এপ্‌ নাই"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"০ টা অব্যৱহৃত এপ্‌"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"শেহতীয়া অনুমতিৰ সিদ্ধান্তসমূহ"</string>
diff --git a/PermissionController/res/values-az/strings.xml b/PermissionController/res/values-az/strings.xml
index a517d458f..7971e3534 100644
--- a/PermissionController/res/values-az/strings.xml
+++ b/PermissionController/res/values-az/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Tətbiq"</string>
<string name="app_permissions" msgid="3369917736607944781">"Tətbiq icazələri"</string>
<string name="unused_apps" msgid="2058057455175955094">"İşlədilməyən tətbiqlər"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"İstifadə olunmayan tətbiq yoxdur"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 istifadə olunmayan tətbiq"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Son icazə qərarları"</string>
diff --git a/PermissionController/res/values-b+sr+Latn/strings.xml b/PermissionController/res/values-b+sr+Latn/strings.xml
index 510680ef7..e8ce29a88 100644
--- a/PermissionController/res/values-b+sr+Latn/strings.xml
+++ b/PermissionController/res/values-b+sr+Latn/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplikacije"</string>
<string name="app_permissions" msgid="3369917736607944781">"Dozvole za aplikacije"</string>
<string name="unused_apps" msgid="2058057455175955094">"Aplikacije koje se ne koriste"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nema aplik. koje se ne koriste"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 aplikac. koje se ne koriste"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Nedavne odluke o dozvolama"</string>
@@ -93,7 +95,7 @@
<string name="location_warning" msgid="2381649060929040962">"<xliff:g id="APP_NAME">%1$s</xliff:g> pruža usluge lokacije za ovaj uređaj. Pristup lokaciji možete da izmenite u podešavanjima lokacije."</string>
<string name="system_warning" msgid="1173400963234358816">"Ako odbijete ovu dozvolu, osnovne funkcije uređaja možda neće više ispravno raditi."</string>
<string name="deny_read_media_visual_warning" msgid="3982586279917232827">"Ova aplikacija je dizajnirana za stariju verziju Android-a. Ako ovoj aplikaciji odbijete pristup za slike i video snimke, povlači se i pristup muzici i drugim audio snimcima."</string>
- <string name="deny_read_media_aural_warning" msgid="8928699919508646732">"Ova aplikacija je dizajnirana za stariju verziju Android-a. Ako ovoj aplikaciji odbijete pristup za muziku i druge audio snimke, povlači se i pristup slikama i video snimcima."</string>
+ <string name="deny_read_media_aural_warning" msgid="8928699919508646732">"Ova aplikacija je dizajnirana za stariju verziju Android-a. Ako ovoj aplikaciji odbijete pristup za muziku i druge audio snimke, povlači se i pristup slikama i videima."</string>
<string name="cdm_profile_revoke_warning" msgid="4443893270719106700">"Ako odbijete ovu dozvolu, neke funkcije uređaja kojima upravlja ova aplikacija možda neće više ispravno raditi."</string>
<string name="permission_summary_enforced_by_policy" msgid="4443598170942950519">"Primenjuje se u skladu sa smernicama"</string>
<string name="permission_summary_disabled_by_policy_background_only" msgid="221995005556362660">"Pristup u pozadini je onemogućen smernicama"</string>
@@ -240,7 +242,7 @@
<string name="permission_description_summary_sms" msgid="725999468547768517">"Aplikacije sa ovom dozvolom mogu da šalju i pregledaju SMS-ove"</string>
<string name="permission_description_summary_storage" msgid="6575759089065303346">"Aplikacije sa ovom dozvolom mogu da pristupaju slikama, medijskom sadržaju i fajlovima na uređaju"</string>
<string name="permission_description_summary_read_media_aural" msgid="3354728149930482199">"Aplikacije sa ovom dozvolom mogu da pristupaju muzici i drugim audio fajlovima na ovom uređaju"</string>
- <string name="permission_description_summary_read_media_visual" msgid="4991801977881732641">"Aplikacije sa ovom dozvolom mogu da pristupaju slikama i video snimcima na ovom uređaju"</string>
+ <string name="permission_description_summary_read_media_visual" msgid="4991801977881732641">"Aplikacije sa ovom dozvolom mogu da pristupaju slikama i videima na ovom uređaju"</string>
<string name="app_permission_most_recent_summary" msgid="4292074449384040590">"Poslednji pristup: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_most_recent_denied_summary" msgid="7659497197737708112">"Trenutno odbijeno/poslednji pristup: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_never_accessed_summary" msgid="401346181461975090">"Bez pristupa"</string>
@@ -475,7 +477,7 @@
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Pristup slikama, videu, muzici, zvuku i drugom na uređaju za &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Dozvoljavate li pristup muzici i zvuku na ovom uređaju za &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Dozvoljavate li pristup slikama i videu na ovom uređaju za &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
- <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Dozvoljavate li da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa i drugim slikama i video snimcima na ovom uređaju?"</string>
+ <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Dozvoljavate li da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa i drugim slikama i videima na ovom uređaju?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snima zvuk?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Aplikacija će moći da snima zvuk samo dok koristite aplikaciju"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snima zvuk?"</string>
@@ -558,18 +560,18 @@
<string name="media_confirm_dialog_title_a_to_p_aural_deny" msgid="7841428716317307685">"Ni pristup drugim fajlovima neće biti dozvoljen"</string>
<string name="media_confirm_dialog_title_a_to_p_visual_allow" msgid="6469086448310893751">"Biće dozvoljen pristup i drugim fajlovima"</string>
<string name="media_confirm_dialog_title_a_to_p_visual_deny" msgid="5767849609024384226">"Ni pristup drugim fajlovima neće biti dozvoljen"</string>
- <string name="media_confirm_dialog_title_q_to_s_aural_allow" msgid="3191904399336990537">"Biće dozvoljen pristup i slikama i video snimcima"</string>
- <string name="media_confirm_dialog_title_q_to_s_aural_deny" msgid="3128147568953297969">"Ni pristup slikama i video snimcima neće biti dozvoljen"</string>
+ <string name="media_confirm_dialog_title_q_to_s_aural_allow" msgid="3191904399336990537">"Biće dozvoljen pristup i slikama i videima"</string>
+ <string name="media_confirm_dialog_title_q_to_s_aural_deny" msgid="3128147568953297969">"Ni pristup slikama i videima neće biti dozvoljen"</string>
<string name="media_confirm_dialog_title_q_to_s_visual_allow" msgid="6310682466493330434">"Biće dozvoljen pristup i muzici i audio fajlovima"</string>
<string name="media_confirm_dialog_title_q_to_s_visual_deny" msgid="1123845663785900471">"Ni pristup muzici i audio fajlovima neće biti dozvoljen"</string>
- <string name="media_confirm_dialog_message_a_to_p_aural_allow" msgid="7865167246140107623">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija može da pristupa muzici i audio fajlovima, biće joj dozvoljeno i da pristupa slikama, video snimcima i drugim fajlovima."</string>
- <string name="media_confirm_dialog_message_a_to_p_aural_deny" msgid="287502523664804786">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija ne može da pristupa muzici i audio fajlovima, neće joj biti dozvoljeno ni da pristupa slikama, video snimcima i drugim fajlovima."</string>
- <string name="media_confirm_dialog_message_a_to_p_visual_allow" msgid="4952410892939590487">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija može da pristupa slikama i video snimcima, biće joj dozvoljeno i da pristupa muzici, audio i drugim fajlovima."</string>
- <string name="media_confirm_dialog_message_a_to_p_visual_deny" msgid="6609500525590757681">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija ne može da pristupa slikama i video snimcima, neće joj biti dozvoljeno ni da pristupa muzici, audio i drugim fajlovima."</string>
- <string name="media_confirm_dialog_message_q_to_s_aural_allow" msgid="1702402580147536160">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija može da pristupa muzici i audio fajlovima, biće joj dozvoljeno i da pristupa slikama i video snimcima."</string>
- <string name="media_confirm_dialog_message_q_to_s_aural_deny" msgid="6832087393653561911">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija ne može da pristupa muzici i audio fajlovima, neće joj biti dozvoljeno ni da pristupa slikama i video snimcima."</string>
- <string name="media_confirm_dialog_message_q_to_s_visual_allow" msgid="3504335060843147760">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija može da pristupa slikama i video snimcima, biće joj dozvoljeno i da pristupa muzici i audio fajlovima."</string>
- <string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija ne može da pristupa muzici i audio fajlovima, neće joj biti dozvoljeno ni da pristupa slikama i video snimcima."</string>
+ <string name="media_confirm_dialog_message_a_to_p_aural_allow" msgid="7865167246140107623">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija može da pristupa muzici i audio fajlovima, biće joj dozvoljeno i da pristupa slikama, videima i drugim fajlovima."</string>
+ <string name="media_confirm_dialog_message_a_to_p_aural_deny" msgid="287502523664804786">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija ne može da pristupa muzici i audio fajlovima, neće joj biti dozvoljeno ni da pristupa slikama, videima i drugim fajlovima."</string>
+ <string name="media_confirm_dialog_message_a_to_p_visual_allow" msgid="4952410892939590487">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija može da pristupa slikama i videima, biće joj dozvoljeno i da pristupa muzici, audio i drugim fajlovima."</string>
+ <string name="media_confirm_dialog_message_a_to_p_visual_deny" msgid="6609500525590757681">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija ne može da pristupa slikama i videima, neće joj biti dozvoljeno ni da pristupa muzici, audio i drugim fajlovima."</string>
+ <string name="media_confirm_dialog_message_q_to_s_aural_allow" msgid="1702402580147536160">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija može da pristupa muzici i audio fajlovima, biće joj dozvoljeno i da pristupa slikama i videima."</string>
+ <string name="media_confirm_dialog_message_q_to_s_aural_deny" msgid="6832087393653561911">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija ne može da pristupa muzici i audio fajlovima, neće joj biti dozvoljeno ni da pristupa slikama i videima."</string>
+ <string name="media_confirm_dialog_message_q_to_s_visual_allow" msgid="3504335060843147760">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija može da pristupa slikama i videima, biće joj dozvoljeno i da pristupa muzici i audio fajlovima."</string>
+ <string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"Ova aplikacija ne podržava najnoviju verziju Android-a. Ako ova aplikacija ne može da pristupa muzici i audio fajlovima, neće joj biti dozvoljeno ni da pristupa slikama i videima."</string>
<string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"Pregledajte aplikaciju sa pristupom lokaciji u pozadini"</string>
<string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> uvek može da pristupa vašoj lokaciji, čak i kad je aplikacija zatvorena"</string>
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Pregledajte aplikaciju sa pristupom lokaciji u pozadini"</string>
diff --git a/PermissionController/res/values-be/strings.xml b/PermissionController/res/values-be/strings.xml
index c6e081982..328bd72be 100644
--- a/PermissionController/res/values-be/strings.xml
+++ b/PermissionController/res/values-be/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Праграмы"</string>
<string name="app_permissions" msgid="3369917736607944781">"Дазволы праграмы"</string>
<string name="unused_apps" msgid="2058057455175955094">"Праграмы, якія не выкарыстоўваюцца"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Няма нескарыстаных праграм"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 праграм не ў карыстанні"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Нядаўнія рашэнні наконт дазволаў"</string>
diff --git a/PermissionController/res/values-bg/strings.xml b/PermissionController/res/values-bg/strings.xml
index a8c0e6315..447404b32 100644
--- a/PermissionController/res/values-bg/strings.xml
+++ b/PermissionController/res/values-bg/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Приложения"</string>
<string name="app_permissions" msgid="3369917736607944781">"Разрешения за приложенията"</string>
<string name="unused_apps" msgid="2058057455175955094">"Неизползвани приложения"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Няма неизползвани приложения"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 неизползвани приложения"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Скорошни решения за разрешения"</string>
diff --git a/PermissionController/res/values-bn/strings.xml b/PermissionController/res/values-bn/strings.xml
index ca112b542..d297a5d18 100644
--- a/PermissionController/res/values-bn/strings.xml
+++ b/PermissionController/res/values-bn/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"অ্যাপ"</string>
<string name="app_permissions" msgid="3369917736607944781">"অ্যাপের অনুমতি"</string>
<string name="unused_apps" msgid="2058057455175955094">"অব্যবহৃত অ্যাপ"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"অব্যবহৃত কোনও অ্যাপ নেই"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"ব্যবহার না করা একটিও অ্যাপ নেই"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"অনুমতি সংক্রান্ত সাম্প্রতিক সিদ্ধান্ত"</string>
diff --git a/PermissionController/res/values-bs/strings.xml b/PermissionController/res/values-bs/strings.xml
index 069c6e418..41ec8cc16 100644
--- a/PermissionController/res/values-bs/strings.xml
+++ b/PermissionController/res/values-bs/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplikacije"</string>
<string name="app_permissions" msgid="3369917736607944781">"Odobrenja za aplikaciju"</string>
<string name="unused_apps" msgid="2058057455175955094">"Nekorištene aplikacije"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nema nekorištenih aplikacija"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 nekorištenih aplikacija"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Nedavne odluke o odobrenjima"</string>
diff --git a/PermissionController/res/values-ca/strings.xml b/PermissionController/res/values-ca/strings.xml
index 0187eabc6..501f69f94 100644
--- a/PermissionController/res/values-ca/strings.xml
+++ b/PermissionController/res/values-ca/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplicacions"</string>
<string name="app_permissions" msgid="3369917736607944781">"Permisos d\'aplicacions"</string>
<string name="unused_apps" msgid="2058057455175955094">"Aplicacions no utilitzades"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Cap aplicació sense utilitzar"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 aplicacions no utilitzades"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Decisions recents de permisos"</string>
diff --git a/PermissionController/res/values-cs/strings.xml b/PermissionController/res/values-cs/strings.xml
index 38faa7581..bac49ea51 100644
--- a/PermissionController/res/values-cs/strings.xml
+++ b/PermissionController/res/values-cs/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplikace"</string>
<string name="app_permissions" msgid="3369917736607944781">"Oprávnění aplikace"</string>
<string name="unused_apps" msgid="2058057455175955094">"Nepoužívané aplikace"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Žádné nepoužívané aplikace"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Žádné nepoužívané aplikace"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Nedávná rozhodnutí o oprávnění"</string>
@@ -196,7 +198,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Používat přesnou polohu"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Když je přesná poloha vypnutá, aplikace mají přístup k vaší přibližné poloze"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Oprávnění: <xliff:g id="PERM">%1$s</xliff:g>"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"<xliff:g id="PERM">%1$s</xliff:g>: přístup této aplikace"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Přístup této aplikace k oprávnění: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Zobrazit všechna oprávnění aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Zobrazit všechny aplikace s tímto oprávněním"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Zobrazit používání mikrofonu asistentem"</string>
@@ -516,7 +518,7 @@
<string name="exempt_info_label" msgid="6286190981253476699">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> je chráněna Androidem. Protože se vaše data zpracovávají na tomto zařízení, oprávnění používaná touto aplikací se nezobrazují na panelu ochrany soukromí."</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"Fotoaparát zařízení je blokován"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"Mikrofon zařízení je blokován"</string>
- <string name="blocked_location_title" msgid="2005608279812892383">"Ukládání polohy zařízení je vypnuté"</string>
+ <string name="blocked_location_title" msgid="2005608279812892383">"Zjišťování polohy zařízení je vypnuté"</string>
<string name="blocked_sensor_summary" msgid="4443707628305027375">"Pro aplikace a služby"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"Když zavoláte na číslo tísňového volání, mohou být nadále sdílena data z mikrofonu."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"Změnit"</string>
diff --git a/PermissionController/res/values-da/strings.xml b/PermissionController/res/values-da/strings.xml
index 7fe9f9309..dc6938e74 100644
--- a/PermissionController/res/values-da/strings.xml
+++ b/PermissionController/res/values-da/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"Apptilladelser"</string>
<string name="unused_apps" msgid="2058057455175955094">"Apps, du ikke bruger"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Ingen ubrugte apps"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Der er 0 ubrugte apps"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Nylige beslutninger om tilladelser"</string>
diff --git a/PermissionController/res/values-de/strings.xml b/PermissionController/res/values-de/strings.xml
index e4f6c29ed..162dd932f 100644
--- a/PermissionController/res/values-de/strings.xml
+++ b/PermissionController/res/values-de/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"App-Berech­tigungen"</string>
<string name="unused_apps" msgid="2058057455175955094">"Nicht verwendete Apps"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Keine nicht verwendeten Apps"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Keine nicht verwendeten Apps"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Aktuelle Berechtigungsentscheidungen"</string>
@@ -71,7 +73,7 @@
<string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{Heute}=1{Vor 1 Tag}other{Vor # Tagen}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"App deaktivieren"</string>
<string name="app_disable_dlg_text" msgid="3126943217146120240">"Bei Deaktivierung dieser App funktionieren Android und andere Apps möglicherweise nicht mehr ordnungsgemäß. Beachte hierbei, dass du diese App nicht löschen kannst, weil sie auf deinem Gerät vorinstalliert war. Durch die Deaktivierung schaltest du diese App ab und blendest sie auf deinem Gerät aus."</string>
- <string name="app_permission_manager" msgid="3903811137630909550">"Berechtigungs­manager"</string>
+ <string name="app_permission_manager" msgid="3903811137630909550">"Berechti­gungsmanager"</string>
<string name="never_ask_again" msgid="4728762438198560329">"Nicht mehr fragen"</string>
<string name="no_permissions" msgid="3881676756371148563">"Keine Berechtigungen"</string>
<string name="additional_permissions" msgid="5801285469338873430">"Zusätzliche Berechtigungen"</string>
diff --git a/PermissionController/res/values-el-v33/strings.xml b/PermissionController/res/values-el-v33/strings.xml
index 7d1cbfbac..4cefe7f04 100644
--- a/PermissionController/res/values-el-v33/strings.xml
+++ b/PermissionController/res/values-el-v33/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="role_dialer_request_description" msgid="6188305064871543419">"Αυτή η εφαρμογή θα μπορεί να σας στέλνει ειδοποιήσεις και θα έχει πρόσβαση στην κάμερα, τις επαφές, το μικρόφωνο, το τηλέφωνο και τα SMS."</string>
<string name="role_sms_request_description" msgid="1506966389698625395">"Αυτή η εφαρμογή θα μπορεί να σας στέλνει ειδοποιήσεις και θα έχει πρόσβαση στην κάμερα, τις επαφές, τα αρχεία, το μικρόφωνο, το τηλέφωνο και τα SMS."</string>
- <string name="permission_description_summary_storage" msgid="1917071243213043858">"Οι εφαρμογές με αυτήν την άδεια μπορούν να έχουν πρόσβαση σε όλα τα αρχεία αυτής της συσκευής"</string>
+ <string name="permission_description_summary_storage" msgid="1917071243213043858">"Οι εφαρμογές με αυτή την άδεια μπορούν να έχουν πρόσβαση σε όλα τα αρχεία αυτής της συσκευής"</string>
<string name="work_policy_title" msgid="832967780713677409">"Οι πληροφορίες πολιτικής εργασίας σας"</string>
<string name="work_policy_summary" msgid="3886113358084963931">"Η διαχείριση των ρυθμίσεων πραγματοποιείται από τον διαχειριστή IT"</string>
<string name="safety_center_entry_group_expand_action" msgid="5358289574941779652">"Ανάπτυξη και εμφάνιση λίστας"</string>
diff --git a/PermissionController/res/values-el/strings.xml b/PermissionController/res/values-el/strings.xml
index a28874ea9..0eb95b4c0 100644
--- a/PermissionController/res/values-el/strings.xml
+++ b/PermissionController/res/values-el/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Εφαρμογές"</string>
<string name="app_permissions" msgid="3369917736607944781">"Άδειες εφαρμογών"</string>
<string name="unused_apps" msgid="2058057455175955094">"Εφαρ. που δεν χρησιμοποιούνται"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Όλες οι εφαρμογές χρησ/νται"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 εφαρμογές που δεν χρησ/νται"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Πρόσφατες αποφάσεις για άδειες"</string>
@@ -70,7 +72,7 @@
<string name="denied_permission_decision" msgid="5308961501779563781">"Δεν επιτρέψατε στην εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> να έχει πρόσβαση στην άδεια <xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
<string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{Σήμερα}=1{Πριν από 1 ημέρα}other{Πριν από # ημέρες}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"Απενεργοποίηση εφαρμογής"</string>
- <string name="app_disable_dlg_text" msgid="3126943217146120240">"Εάν απενεργοποιήσετε αυτήν την εφαρμογή, η λειτουργία του Android και άλλων εφαρμογών ενδέχεται να μην είναι η αναμενόμενη. Λάβετε υπόψη ότι δεν είναι δυνατή η διαγραφή αυτής της εφαρμογής καθώς ήταν προεγκατεστημένη στη συσκευή σας. Με την απενεργοποίηση, απενεργοποιείτε αυτήν την εφαρμογή και την αποκρύπτετε στη συσκευή σας."</string>
+ <string name="app_disable_dlg_text" msgid="3126943217146120240">"Εάν απενεργοποιήσετε αυτή την εφαρμογή, η λειτουργία του Android και άλλων εφαρμογών ενδέχεται να μην είναι η αναμενόμενη. Λάβετε υπόψη ότι δεν είναι δυνατή η διαγραφή αυτής της εφαρμογής καθώς ήταν προεγκατεστημένη στη συσκευή σας. Με την απενεργοποίηση, απενεργοποιείτε αυτή την εφαρμογή και την αποκρύπτετε στη συσκευή σας."</string>
<string name="app_permission_manager" msgid="3903811137630909550">"Διαχείριση αδειών"</string>
<string name="never_ask_again" msgid="4728762438198560329">"Να μην ερωτηθώ ξανά"</string>
<string name="no_permissions" msgid="3881676756371148563">"Δεν υπάρχουν άδειες"</string>
@@ -78,8 +80,8 @@
<string name="app_permissions_info_button_label" msgid="7633312050729974623">"Άνοιγμα πληροφοριών εφαρμογής"</string>
<string name="additional_permissions_more" msgid="5681220714755304407">"{count,plural, =1{# ακόμη}other{# ακόμη}}"</string>
<string name="old_sdk_deny_warning" msgid="2382236998845153919">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Η άρνηση παραχώρησης άδειας μπορεί να έχει ως αποτέλεσμα να διακοπεί η κανονική λειτουργία της."</string>
- <string name="storage_supergroup_warning_allow" msgid="103093462784523190">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν επιτρέψετε αυτήν την άδεια, τότε θα επιτρέπεται η πρόσβαση σε όλο τον αποθηκευτικό χώρο (συμπεριλαμβανομένων φωτογραφιών, βίντεο, μουσικής, ήχου και άλλων αρχείων)."</string>
- <string name="storage_supergroup_warning_deny" msgid="6420765672683284347">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν δεν επιτρέψετε αυτήν την άδεια, τότε δεν θα επιτρέπεται η πρόσβαση σε όλο τον αποθηκευτικό χώρο (συμπεριλαμβανομένων φωτογραφιών, βίντεο, μουσικής, ήχου και άλλων αρχείων)."</string>
+ <string name="storage_supergroup_warning_allow" msgid="103093462784523190">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν επιτρέψετε αυτή την άδεια, τότε θα επιτρέπεται η πρόσβαση σε όλο τον αποθηκευτικό χώρο (συμπεριλαμβανομένων φωτογραφιών, βίντεο, μουσικής, ήχου και άλλων αρχείων)."</string>
+ <string name="storage_supergroup_warning_deny" msgid="6420765672683284347">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν δεν επιτρέψετε αυτή την άδεια, τότε δεν θα επιτρέπεται η πρόσβαση σε όλο τον αποθηκευτικό χώρο (συμπεριλαμβανομένων φωτογραφιών, βίντεο, μουσικής, ήχου και άλλων αρχείων)."</string>
<string name="default_permission_description" msgid="4624464917726285203">"εκτέλεση άγνωστης ενέργειας"</string>
<string name="app_permissions_group_summary" msgid="8788419008958284002">"Επιτρέπονται <xliff:g id="COUNT_0">%1$d</xliff:g> από <xliff:g id="COUNT_1">%2$d</xliff:g> εφαρμογές"</string>
<string name="app_permissions_group_summary2" msgid="4329922444840521150">"Επιτρέπονται <xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g> εφαρμογές"</string>
@@ -91,10 +93,10 @@
<string name="no_apps" msgid="2412612731628386816">"Δεν υπάρχουν εφαρμογές"</string>
<string name="location_settings" msgid="3624412509133422562">"Ρυθμίσεις τοποθεσίας"</string>
<string name="location_warning" msgid="2381649060929040962">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> είναι ο πάροχος των υπηρεσιών τοποθεσίας για τη συγκεκριμένη συσκευή. Μπορείτε να τροποποιήσετε την πρόσβαση τοποθεσίας από τις ρυθμίσεις τοποθεσίας."</string>
- <string name="system_warning" msgid="1173400963234358816">"Εάν αρνηθείτε να παραχωρήσετε αυτήν την άδεια, ορισμένες βασικές λειτουργίες της συσκευής σας μπορεί να μην εκτελούνται πλέον με τον αναμενόμενο τρόπο."</string>
+ <string name="system_warning" msgid="1173400963234358816">"Εάν αρνηθείτε να παραχωρήσετε αυτή την άδεια, ορισμένες βασικές λειτουργίες της συσκευής σας μπορεί να μην εκτελούνται πλέον με τον αναμενόμενο τρόπο."</string>
<string name="deny_read_media_visual_warning" msgid="3982586279917232827">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν δεν επιτρέψετε την πρόσβαση αυτής της εφαρμογής στις φωτογραφίες και τα βίντεο, δεν θα επιτρέπεται επίσης η πρόσβαση στη μουσική και άλλους ήχους."</string>
<string name="deny_read_media_aural_warning" msgid="8928699919508646732">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν δεν επιτρέψετε την πρόσβαση αυτής της εφαρμογής στη μουσική και άλλους ήχους, δεν θα επιτρέπεται επίσης η πρόσβαση στις φωτογραφίες και τα βίντεο."</string>
- <string name="cdm_profile_revoke_warning" msgid="4443893270719106700">"Εάν απορρίψετε αυτήν την άδεια, ορισμένες λειτουργίες της συσκευής σας τις οποίες διαχειρίζεται αυτή η εφαρμογή, ενδέχεται να μην λειτουργούν με τον αναμενόμενο τρόπο."</string>
+ <string name="cdm_profile_revoke_warning" msgid="4443893270719106700">"Εάν απορρίψετε αυτή την άδεια, ορισμένες λειτουργίες της συσκευής σας τις οποίες διαχειρίζεται αυτή η εφαρμογή, ενδέχεται να μην λειτουργούν με τον αναμενόμενο τρόπο."</string>
<string name="permission_summary_enforced_by_policy" msgid="4443598170942950519">"Επιβάλλεται βάσει πολιτικής"</string>
<string name="permission_summary_disabled_by_policy_background_only" msgid="221995005556362660">"Η πρόσβαση στο παρασκήνιο απενεργοποιήθηκε βάσει πολιτικής"</string>
<string name="permission_summary_enabled_by_policy_background_only" msgid="8287675974767104279">"Η πρόσβαση στο παρασκήνιο ενεργοποιήθηκε βάσει πολιτικής"</string>
@@ -196,16 +198,16 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Χρήση ακριβούς τοποθεσίας"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Όταν είναι απενεργοποιημένη η ακριβής τοποθεσία, οι εφαρμογές μπορούν να έχουν πρόσβαση στην κατά προσέγγιση τοποθεσία σας"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Άδεια - <xliff:g id="PERM">%1$s</xliff:g>"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"Πρόσβαση σε <xliff:g id="PERM">%1$s</xliff:g> για αυτήν την εφαρμογή"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Πρόσβαση σε <xliff:g id="PERM">%1$s</xliff:g> για αυτή την εφαρμογή"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Εμφάνιση όλων των αδειών της εφαρμογής <xliff:g id="APP">%1$s</xliff:g>"</string>
- <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Εμφάνιση όλων των εφαρμογών με αυτήν την άδεια"</string>
+ <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Εμφάνιση όλων των εφαρμογών με αυτή την άδεια"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Εμφάνιση χρήσης μικροφώνου βοηθού"</string>
<string name="unused_apps_category_title" msgid="2988455616845243901">"Ρυθμίσεις μη χρησιμοποιούμενων εφαρμογών"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Καταργήστε τις άδειες, εάν η εφαρμογή δεν χρησιμοποιείται."</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Κατάργηση αδειών και απελευθέρωση χώρου"</string>
<string name="unused_apps_label_v2" msgid="7058776770056517980">"Παύση δραστηριότητας αδρανούς εφαρμογής"</string>
<string name="unused_apps_summary" msgid="8839466950318403115">"Κατάργηση αδειών, διαγραφή προσωρινών αρχείων και διακοπή ειδοποιήσεων"</string>
- <string name="auto_revoke_summary" msgid="5867548789805911683">"Για την προστασία των δεδομένων σας, οι άδειες για αυτήν την εφαρμογή θα καταργηθούν εάν η εφαρμογή δεν χρησιμοποιηθεί για μερικούς μήνες."</string>
+ <string name="auto_revoke_summary" msgid="5867548789805911683">"Για την προστασία των δεδομένων σας, οι άδειες για αυτή την εφαρμογή θα καταργηθούν εάν η εφαρμογή δεν χρησιμοποιηθεί για μερικούς μήνες."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Για την προστασία των δεδομένων σας, εάν δεν έχει χρησιμοποιηθεί η εφαρμογή για μερικούς μήνες, οι παρακάτω άδειες θα καταργηθούν: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Για την προστασία των δεδομένων σας, έχουν καταργηθεί οι άδειες εφαρμογών που δεν έχετε χρησιμοποιήσει κατά τους τελευταίους μήνες."</string>
<string name="auto_revoke_open_app_message" msgid="8075556291711205039">"Εάν θέλετε να επιτραπούν ξανά οι άδειες, ανοίξτε την εφαρμογή."</string>
@@ -225,22 +227,22 @@
<string name="last_opened_summary" msgid="5248984030024968808">"Τελευταίο άνοιγμα εφαρμογής <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="last_opened_summary_short" msgid="1646067226191176825">"Τελευταίο άνοιγμα <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Εάν επιτρέψετε τη διαχείριση όλων των αρχείων, αυτή η εφαρμογή θα μπορεί να αποκτήσει πρόσβαση, να τροποποιήσει και να διαγράψει τυχόν αρχεία στον κοινό αποθηκευτικό χώρο αυτής της συσκευής ή συνδεδεμένων συσκευών αποθηκευτικού χώρου. Η εφαρμογή θα μπορεί να αποκτήσει πρόσβαση σε αρχεία χωρίς να σας ρωτήσει."</string>
- <string name="special_file_access_dialog" msgid="583804114020740610">"Να επιτρέπεται σε αυτήν την εφαρμογή η πρόσβαση, τροποποίηση και διαγραφή αρχείων στη συσκευή ή τυχόν συνδεδεμένες συσκευές αποθηκευτικού χώρου; Η εφαρμογή θα μπορεί να αποκτήσει πρόσβαση σε αρχεία χωρίς να σας ρωτήσει."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Οι εφαρμογές με αυτήν την άδεια μπορούν να <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
- <string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Οι εφαρμογές με αυτήν την άδεια έχουν πρόσβαση σε φυσικές δραστηριότητες, όπως το περπάτημα, η ποδηλασία, η οδήγηση, ο αριθμός βημάτων και άλλα"</string>
- <string name="permission_description_summary_calendar" msgid="103329982944411010">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στο ημερολόγιό σας"</string>
- <string name="permission_description_summary_call_log" msgid="7321437186317577624">"Οι εφαρμογές με αυτήν την άδεια, έχουν δυνατότητα ανάγνωσης και εγγραφής στο αρχείο καταγραφής κλήσεων"</string>
- <string name="permission_description_summary_camera" msgid="108004375101882069">"Οι εφαρμογές με αυτήν την άδεια μπορούν να τραβούν φωτογραφίες και να εγγράφουν βίντεο"</string>
- <string name="permission_description_summary_contacts" msgid="2337798886460408996">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στις επαφές σας"</string>
- <string name="permission_description_summary_location" msgid="2817531799933480694">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στην τοποθεσία αυτής της συσκευής"</string>
- <string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"Οι εφαρμογές με αυτήν την άδεια μπορούν να βρίσκουν, να συνδέονται και να προσδιορίζουν τη σχετική τοποθεσία κοντινών συσκευών"</string>
- <string name="permission_description_summary_microphone" msgid="630834800308329907">"Οι εφαρμογές με αυτήν την άδεια μπορούν να εγγράφουν ήχο"</string>
- <string name="permission_description_summary_phone" msgid="4515277217435233619">"Οι εφαρμογές με αυτήν την άδεια έχουν δυνατότητα πραγματοποίησης και διαχείρισης τηλεφωνικών κλήσεων"</string>
- <string name="permission_description_summary_sensors" msgid="1836045815643119949">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας"</string>
- <string name="permission_description_summary_sms" msgid="725999468547768517">"Οι εφαρμογές με αυτήν την άδεια μπορούν να στέλνουν και να προβάλλουν μηνύματα SMS"</string>
- <string name="permission_description_summary_storage" msgid="6575759089065303346">"Οι εφαρμογές με αυτήν την άδεια έχουν πρόσβαση σε φωτογραφίες, μέσα και αρχεία στη συσκευή σας"</string>
- <string name="permission_description_summary_read_media_aural" msgid="3354728149930482199">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στη μουσική και σε άλλα αρχεία ήχου αυτής της συσκευής"</string>
- <string name="permission_description_summary_read_media_visual" msgid="4991801977881732641">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στις φωτογραφίες και τα βίντεο αυτής της συσκευής"</string>
+ <string name="special_file_access_dialog" msgid="583804114020740610">"Να επιτρέπεται σε αυτή την εφαρμογή η πρόσβαση, τροποποίηση και διαγραφή αρχείων στη συσκευή ή τυχόν συνδεδεμένες συσκευές αποθηκευτικού χώρου; Η εφαρμογή θα μπορεί να αποκτήσει πρόσβαση σε αρχεία χωρίς να σας ρωτήσει."</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Οι εφαρμογές με αυτή την άδεια μπορούν να <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Οι εφαρμογές με αυτή την άδεια έχουν πρόσβαση σε φυσικές δραστηριότητες, όπως το περπάτημα, η ποδηλασία, η οδήγηση, ο αριθμός βημάτων και άλλα"</string>
+ <string name="permission_description_summary_calendar" msgid="103329982944411010">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στο ημερολόγιό σας"</string>
+ <string name="permission_description_summary_call_log" msgid="7321437186317577624">"Οι εφαρμογές με αυτή την άδεια, έχουν δυνατότητα ανάγνωσης και εγγραφής στο αρχείο καταγραφής κλήσεων"</string>
+ <string name="permission_description_summary_camera" msgid="108004375101882069">"Οι εφαρμογές με αυτή την άδεια μπορούν να τραβούν φωτογραφίες και να εγγράφουν βίντεο"</string>
+ <string name="permission_description_summary_contacts" msgid="2337798886460408996">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στις επαφές σας"</string>
+ <string name="permission_description_summary_location" msgid="2817531799933480694">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στην τοποθεσία αυτής της συσκευής"</string>
+ <string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"Οι εφαρμογές με αυτή την άδεια μπορούν να βρίσκουν, να συνδέονται και να προσδιορίζουν τη σχετική τοποθεσία κοντινών συσκευών"</string>
+ <string name="permission_description_summary_microphone" msgid="630834800308329907">"Οι εφαρμογές με αυτή την άδεια μπορούν να εγγράφουν ήχο"</string>
+ <string name="permission_description_summary_phone" msgid="4515277217435233619">"Οι εφαρμογές με αυτή την άδεια έχουν δυνατότητα πραγματοποίησης και διαχείρισης τηλεφωνικών κλήσεων"</string>
+ <string name="permission_description_summary_sensors" msgid="1836045815643119949">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας"</string>
+ <string name="permission_description_summary_sms" msgid="725999468547768517">"Οι εφαρμογές με αυτή την άδεια μπορούν να στέλνουν και να προβάλλουν μηνύματα SMS"</string>
+ <string name="permission_description_summary_storage" msgid="6575759089065303346">"Οι εφαρμογές με αυτή την άδεια έχουν πρόσβαση σε φωτογραφίες, μέσα και αρχεία στη συσκευή σας"</string>
+ <string name="permission_description_summary_read_media_aural" msgid="3354728149930482199">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στη μουσική και σε άλλα αρχεία ήχου αυτής της συσκευής"</string>
+ <string name="permission_description_summary_read_media_visual" msgid="4991801977881732641">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στις φωτογραφίες και τα βίντεο αυτής της συσκευής"</string>
<string name="app_permission_most_recent_summary" msgid="4292074449384040590">"Τελευταία πρόσβαση: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_most_recent_denied_summary" msgid="7659497197737708112">"Απορρίφθηκε αυτήν τη φορά/Τελευταία πρόσβαση: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_never_accessed_summary" msgid="401346181461975090">"Δεν έγινε ποτέ πρόσβαση"</string>
@@ -284,7 +286,7 @@
<string name="background_location_access_reminder_notification_content" msgid="7787084707336546245">"Αυτή η εφαρμογή μπορεί να έχει πάντα πρόσβαση στην τοποθεσία σας. Πατήστε για να αλλάξετε τη ρύθμιση."</string>
<string name="notification_listener_reminder_notification_title" msgid="3747210460187479091">"Έλεγχος εφαρμογής που έχει πρόσβαση στις ειδοποιήσεις σας"</string>
<string name="notification_listener_reminder_notification_content" msgid="831476101108863427">"Η εφαρμογή <xliff:g id="APP_NAME">%s</xliff:g> μπορεί να παραβλέψει ειδοποιήσεις, να εκτελέσει ενέργειες σε αυτές και να αποκτήσει πρόσβαση σε περιεχόμενο στο εσωτερικό τους"</string>
- <string name="notification_listener_warning_card_content" msgid="7840973324284115893">"Αυτή η εφαρμογή μπορεί να παραβλέψει ειδοποιήσεις, να εκτελέσει ενέργειες σε αυτές και να αποκτήσει πρόσβαση σε περιεχόμενο στο εσωτερικό τους. Ορισμένες εφαρμογές χρειάζονται αυτήν την πρόσβαση για να λειτουργούν όπως προβλέπεται."</string>
+ <string name="notification_listener_warning_card_content" msgid="7840973324284115893">"Αυτή η εφαρμογή μπορεί να παραβλέψει ειδοποιήσεις, να εκτελέσει ενέργειες σε αυτές και να αποκτήσει πρόσβαση σε περιεχόμενο στο εσωτερικό τους. Ορισμένες εφαρμογές χρειάζονται αυτή την πρόσβαση για να λειτουργούν όπως προβλέπεται."</string>
<string name="notification_listener_remove_access_button_label" msgid="7101898782417817097">"Κατάργηση πρόσβασης"</string>
<string name="notification_listener_review_app_button_label" msgid="3433073281029143924">"Εμφάνιση περισσότερων επιλογών"</string>
<string name="notification_listener_remove_access_success_label" msgid="2477611529875633107">"Η πρόσβαση καταργήθηκε"</string>
@@ -492,9 +494,9 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στα αρχεία καταγραφής τηλεφωνικών κλήσεών σας;"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πραγματοποίηση και η διαχείριση τηλεφωνικών κλήσεων;"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας;"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Αυτή η εφαρμογή θέλει πρόσβαση στα δεδομένα αισθητήρα για τις ζωτικές σας ενδείξεις, ακόμη και όταν δεν τη χρησιμοποιείτε. Για να κάνετε αυτήν την αλλαγή, "<annotation id="link">"μεταβείτε στις ρυθμίσεις."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Αυτή η εφαρμογή θέλει πρόσβαση στα δεδομένα αισθητήρα για τις ζωτικές σας ενδείξεις, ακόμη και όταν δεν τη χρησιμοποιείτε. Για να κάνετε αυτή την αλλαγή, "<annotation id="link">"μεταβείτε στις ρυθμίσεις."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πρόσβαση σε δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας;"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Για να επιτρέψετε σε αυτήν την εφαρμογή να έχει πρόσβαση σε δεδομένα αισθητήρων σώματος οποιαδήποτε στιγμή, ακόμα και όταν δεν χρησιμοποιείτε την εφαρμογή, "<annotation id="link">"μεταβείτε στις ρυθμίσεις."</annotation></string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Για να επιτρέψετε σε αυτή την εφαρμογή να έχει πρόσβαση σε δεδομένα αισθητήρων σώματος οποιαδήποτε στιγμή, ακόμα και όταν δεν χρησιμοποιείτε την εφαρμογή, "<annotation id="link">"μεταβείτε στις ρυθμίσεις."</annotation></string>
<string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Να συνεχίσει να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πρόσβαση σε δεδομένα αισθητήρων σώματος ενώ χρησιμοποιείται;"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να σας στέλνει ειδοποιήσεις;"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Ελεγχόμενες άδειες"</string>
@@ -540,8 +542,8 @@
<string name="permissions_removed_qs" msgid="8957319130625294572">"Η άδεια καταργήθηκε"</string>
<string name="camera_usage_qs" msgid="4394233566086665994">"Προβολή πρόσφατης χρήσης κάμερας"</string>
<string name="microphone_usage_qs" msgid="8527666682168170417">"Προβολή πρόσφατης χρήσης μικροφώνου"</string>
- <string name="remove_camera_qs" msgid="3649996161066883350">"Κατάργηση άδειας για αυτήν την εφαρμογή"</string>
- <string name="remove_microphone_qs" msgid="1276551965129953198">"Κατάργηση άδειας για αυτήν την εφαρμογή"</string>
+ <string name="remove_camera_qs" msgid="3649996161066883350">"Κατάργηση άδειας για αυτή την εφαρμογή"</string>
+ <string name="remove_microphone_qs" msgid="1276551965129953198">"Κατάργηση άδειας για αυτή την εφαρμογή"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Διαχείριση υπηρεσίας"</string>
<string name="manage_permissions_qs" msgid="3780541819763475434">"Διαχείριση αδειών"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Χρησιμοποιείται από την τηλεφωνική κλήση"</string>
@@ -581,7 +583,7 @@
<string name="mic_toggle_title" msgid="2649991093496110162">"Πρόσβαση μικροφώνου"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"Για εφαρμογές και υπηρεσίες"</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"Για εφαρμογές και υπηρεσίες. Εάν είναι απενεργοποιημένη αυτή η ρύθμιση, τα δεδομένα μικροφώνου ενδέχεται να κοινοποιούνται όταν καλείτε έναν αριθμό έκτακτης ανάγκης."</string>
- <string name="location_settings_subtitle" msgid="2328360561197430695">"Εμφάνιση εφαρμογών και υπηρεσιών που έχουν πρόσβαση σε αυτήν την τοποθεσία"</string>
+ <string name="location_settings_subtitle" msgid="2328360561197430695">"Εμφάνιση εφαρμογών και υπηρεσιών που έχουν πρόσβαση σε αυτή την τοποθεσία"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Εμφάνιση πρόσβασης στο πρόχειρο"</string>
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Να εμφανίζεται ένα μήνυμα όταν οι εφαρμογές αποκτούν πρόσβαση σε κείμενο, εικόνες ή άλλο περιεχόμενο που έχετε αντιγράψει"</string>
<string name="show_password_title" msgid="2877269286984684659">"Εμφάνιση κωδικών πρόσβασης"</string>
diff --git a/PermissionController/res/values-en-rAU/strings.xml b/PermissionController/res/values-en-rAU/strings.xml
index 77c6837ad..1c6119af7 100644
--- a/PermissionController/res/values-en-rAU/strings.xml
+++ b/PermissionController/res/values-en-rAU/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"App permissions"</string>
<string name="unused_apps" msgid="2058057455175955094">"Unused apps"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"No unused apps"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Zero unused apps"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Recent permission decisions"</string>
diff --git a/PermissionController/res/values-en-rCA/strings.xml b/PermissionController/res/values-en-rCA/strings.xml
index ef5fb9086..334f1541f 100644
--- a/PermissionController/res/values-en-rCA/strings.xml
+++ b/PermissionController/res/values-en-rCA/strings.xml
@@ -60,6 +60,7 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"App permissions"</string>
<string name="unused_apps" msgid="2058057455175955094">"Unused apps"</string>
+ <string name="edit_photos_description" msgid="5540108003480078892">"Edit selected photos for this app"</string>
<string name="no_unused_apps" msgid="12809387670415295">"No unused apps"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 unused apps"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Recent permission decisions"</string>
diff --git a/PermissionController/res/values-en-rGB/strings.xml b/PermissionController/res/values-en-rGB/strings.xml
index 9feaad707..0b4cf2e75 100644
--- a/PermissionController/res/values-en-rGB/strings.xml
+++ b/PermissionController/res/values-en-rGB/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"App permissions"</string>
<string name="unused_apps" msgid="2058057455175955094">"Unused apps"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"No unused apps"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Zero unused apps"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Recent permission decisions"</string>
diff --git a/PermissionController/res/values-en-rIN/strings.xml b/PermissionController/res/values-en-rIN/strings.xml
index 9feaad707..0b4cf2e75 100644
--- a/PermissionController/res/values-en-rIN/strings.xml
+++ b/PermissionController/res/values-en-rIN/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"App permissions"</string>
<string name="unused_apps" msgid="2058057455175955094">"Unused apps"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"No unused apps"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Zero unused apps"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Recent permission decisions"</string>
diff --git a/PermissionController/res/values-en-rXC/strings.xml b/PermissionController/res/values-en-rXC/strings.xml
index c712a6f2d..99c621f77 100644
--- a/PermissionController/res/values-en-rXC/strings.xml
+++ b/PermissionController/res/values-en-rXC/strings.xml
@@ -60,6 +60,7 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎Apps‎‏‎‎‏‎"</string>
<string name="app_permissions" msgid="3369917736607944781">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎App permissions‎‏‎‎‏‎"</string>
<string name="unused_apps" msgid="2058057455175955094">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‏‎‎Unused apps‎‏‎‎‏‎"</string>
+ <string name="edit_photos_description" msgid="5540108003480078892">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎Edit selected photos for this app‎‏‎‎‏‎"</string>
<string name="no_unused_apps" msgid="12809387670415295">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‎No unused apps‎‏‎‎‏‎"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‎‎‎‏‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‎‎‎0 unused apps‎‏‎‎‏‎"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‎‎‎‎Recent permission decisions‎‏‎‎‏‎"</string>
diff --git a/PermissionController/res/values-es-rUS/strings.xml b/PermissionController/res/values-es-rUS/strings.xml
index 5748aad3c..2178cac0d 100644
--- a/PermissionController/res/values-es-rUS/strings.xml
+++ b/PermissionController/res/values-es-rUS/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"Permisos de la app"</string>
<string name="unused_apps" msgid="2058057455175955094">"Apps que no usas"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"No hay ninguna app sin usar"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 apps en desuso"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Acciones recientes de permisos"</string>
@@ -513,7 +515,7 @@
<string name="privdash_label_24h" msgid="1512532123865375319">"Últimas\n24 horas"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"Últimos\n7 días"</string>
<string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"<xliff:g id="APP_NAME">%1$s</xliff:g> está protegida por Android. Tus datos se procesan en este dispositivo, por eso no se muestra el uso de permisos de esta app en la barra de estado ni en el panel de privacidad."</string>
- <string name="exempt_info_label" msgid="6286190981253476699">"protege <xliff:g id="APP_NAME">%1$s</xliff:g> está protegida por Android. Tus datos se procesan en este dispositivo, por eso no se muestra el uso de permisos de esta app en la barra de estado ni en el panel de privacidad."</string>
+ <string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g> está protegida por Android. Tus datos se procesan en este dispositivo, por eso no se muestra el uso de permisos de esta app en el panel de privacidad."</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"La cámara del dispositivo está bloqueada"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"El micrófono del dispositivo está bloqueado"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"La ubicación del dispositivo está desactivada"</string>
diff --git a/PermissionController/res/values-es/strings.xml b/PermissionController/res/values-es/strings.xml
index cb76d3560..c84f7cfee 100644
--- a/PermissionController/res/values-es/strings.xml
+++ b/PermissionController/res/values-es/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplicaciones"</string>
<string name="app_permissions" msgid="3369917736607944781">"Permisos de aplicaciones"</string>
<string name="unused_apps" msgid="2058057455175955094">"Aplicaciones no usadas"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"No hay aplicaciones no usadas"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 aplicaciones no usadas"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Decisiones recientes de permisos"</string>
diff --git a/PermissionController/res/values-et/strings.xml b/PermissionController/res/values-et/strings.xml
index 027b554e0..00403361b 100644
--- a/PermissionController/res/values-et/strings.xml
+++ b/PermissionController/res/values-et/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Rakendused"</string>
<string name="app_permissions" msgid="3369917736607944781">"Rakenduse load"</string>
<string name="unused_apps" msgid="2058057455175955094">"Kasutamata rakendused"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Kasutamata rakendusi pole"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 kasutamata rakendust"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Hiljutised lubade otsused"</string>
diff --git a/PermissionController/res/values-eu/strings.xml b/PermissionController/res/values-eu/strings.xml
index 931a85979..f3cf3eb12 100644
--- a/PermissionController/res/values-eu/strings.xml
+++ b/PermissionController/res/values-eu/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplikazioak"</string>
<string name="app_permissions" msgid="3369917736607944781">"Aplikazio-baimenak"</string>
<string name="unused_apps" msgid="2058057455175955094">"Erabiltzen ez diren aplikazioak"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Ez dago erabiltzen ez duzun aplikaziorik"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Erabiltzen ez diren 0 aplikazio"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Azkenaldian baimenen inguruan hartutako erabakiak"</string>
@@ -232,7 +234,7 @@
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Telefonoko deien erregistroa irakur dezakete baimen hau duten aplikazioek, baita bertan idatzi ere"</string>
<string name="permission_description_summary_camera" msgid="108004375101882069">"Argazkiak atera eta bideoak graba ditzakete baimen hau duten aplikazioek"</string>
<string name="permission_description_summary_contacts" msgid="2337798886460408996">"Zure kontaktuak atzi ditzakete baimen hau duten aplikazioek"</string>
- <string name="permission_description_summary_location" msgid="2817531799933480694">"Gailu honen kokapena atzi dezakete baimen hau duten aplikazioek"</string>
+ <string name="permission_description_summary_location" msgid="2817531799933480694">"Gailu honen kokapena erabil dezakete baimen hau duten aplikazioek"</string>
<string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"Inguruko gailuak aurkitu, haietara konektatu, eta haien arteko distantzia erlatiboa zehatz dezakete baimen hau duten aplikazioek"</string>
<string name="permission_description_summary_microphone" msgid="630834800308329907">"Audioa graba dezakete baimen hau duten aplikazioek"</string>
<string name="permission_description_summary_phone" msgid="4515277217435233619">"Telefono-deiak egin eta kudea ditzakete baimen hau duten aplikazioek"</string>
@@ -587,13 +589,13 @@
<string name="show_password_title" msgid="2877269286984684659">"Erakutsi pasahitzak"</string>
<string name="show_password_summary" msgid="1110166488865981610">"Idatzi ahala, erakutsi karaktereak laburki"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Agian hirugarrenekin kokapen-datuak partekatuko dituela adierazi du aplikazioaren garatzaileak"</string>
- <string name="permission_rationale_location_title" msgid="2404797182678793506">"Datuak partekatzeko moduak eta kokapena"</string>
- <string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Nondik dator datuak partekatzeko moduei buruzko informazioa?"</string>
+ <string name="permission_rationale_location_title" msgid="2404797182678793506">"Datuak partekatzeko aukera eta kokapena"</string>
+ <string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Nondik dator datuak partekatzeko aukerari buruzko informazioa?"</string>
<string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Aplikazioak datuak partekatzeko dituen moduei buruzko informazioa eman dio gailuaren fabrikatzaileari garatzaileak. Baliteke garatzaileak informazio hori eguneratzea denboran zehar."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Aplikazioak datuak partekatzeko dituen moduei buruzko informazioa eman du "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" dendan garatzaileak. Baliteke garatzaileak informazio hori eguneratzea denboran zehar."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Baliteke hauetarako partekatzea kokapen-datuak:"</string>
- <string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Datuak partekatzeko moduak aldatu egiten dira"</string>
- <string name="permission_rationale_data_sharing_varies_message" msgid="4224469559084489222">"Litekeena da datuen inguruko jardunbideak aplikazioaren bertsioaren, erabileraren, lurraldearen eta adinaren araberakoak izatea. "<annotation id="link">"Datuak partekatzeko moduei buruzko informazio gehiago"</annotation></string>
+ <string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Datuak partekatzeko aukerak aldatu egiten dira"</string>
+ <string name="permission_rationale_data_sharing_varies_message" msgid="4224469559084489222">"Litekeena da datuen inguruko jardunbideak aplikazioaren bertsioaren, erabileraren, lurraldearen eta adinaren araberakoak izatea. "<annotation id="link">"Datuak partekatzeko aukerari buruzko informazio gehiago"</annotation></string>
<string name="permission_rationale_data_sharing_varies_message_without_link" msgid="4912763761399025094">"Litekeena da datuen inguruko jardunbideak aplikazioaren bertsioaren, erabileraren, lurraldearen eta adinaren araberakoak izatea."</string>
<string name="permission_rationale_location_settings_title" msgid="7204145004850190953">"Kokapen-datuak"</string>
<string name="permission_rationale_permission_settings_message" msgid="631286040979660267">"Aldatu aplikazioaren sarbidea "<annotation id="link">"pribatutasun-ezarpenetan"</annotation></string>
@@ -607,16 +609,16 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Datuen babesa"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Baliteke kokapen-datuak partekatzea"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Agian hirugarrenekin kokapen-datuak partekatuko dituela adierazi du aplikazioaren garatzaileak"</string>
- <string name="data_sharing_updates_title" msgid="7996933386875213859">"Kokapen-datuak partekatzeko jardunbideen berritasunak"</string>
+ <string name="data_sharing_updates_title" msgid="7996933386875213859">"Kokapen-datuak partekatzeko aukeraren berritasunak"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Berrikusi kokapen-datuak partekatzeko modua aldatu duten aplikazioak"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Kokapen-datuak partekatzeko modua aldatu dute aplikazio hauek. Agian ez zuten daturik partekatzen lehen, edo baliteke orain publizitate- edo marketin-helburuetarako partekatzea."</string>
- <string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Datuak partekatzeko jardunbideei buruzko informazioa eman dute aplikazio-denda batean aplikazio hauen garatzaileek. Baliteke denboran zehar informazio hori eguneratzea.\n\nLitekeena da datuak partekatzeko jardunbideak aplikazioaren bertsioaren, erabileraren, lurraldearen eta adinaren araberakoak izatea."</string>
- <string name="learn_about_data_sharing" msgid="4200480587079488045">"Datuak partekatzeko jardunbideei buruzko informazio gehiago"</string>
+ <string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Datuak partekatzeko aukerari buruzko informazioa eman dute aplikazio-denda batean aplikazio hauen garatzaileek. Baliteke denboran zehar informazio hori eguneratzea.\n\nLitekeena da datuak partekatzeko aukera aplikazioaren bertsioaren, erabileraren, lurraldearen eta adinaren araberakoa izatea."</string>
+ <string name="learn_about_data_sharing" msgid="4200480587079488045">"Datuak partekatzeko aukerari buruzko informazio gehiago"</string>
<string name="shares_location_with_third_parties" msgid="2278051743742057767">"Orain, kokapen-datuak hirugarrenekin partekatzen dira"</string>
<string name="shares_location_with_third_parties_for_advertising" msgid="1918588064014480513">"Orain, kokapen-datuak hirugarrenekin partekatzen dira publizitate- edo marketin-helburuetarako"</string>
<string name="updated_in_last_days" msgid="8371811947153042322">"{count,plural, =0{Atzo jaso ziren berritasunak}=1{Atzo jaso ziren berritasunak}other{Azken # egunetan jaso dira berritasunak}}"</string>
<string name="no_updates_at_this_time" msgid="9031085635689982935">"Une honetan, ez dago berritasunik"</string>
- <string name="safety_label_changes_notification_title" msgid="4479955083472203839">"Datuak partekatzeko moduen inguruko berritasunak"</string>
+ <string name="safety_label_changes_notification_title" msgid="4479955083472203839">"Datuak partekatzeko aukeraren berritasunak"</string>
<string name="safety_label_changes_notification_desc" msgid="7808764283266234675">"Kokapen-datuak partekatzeko modua aldatu dute aplikazio batzuek"</string>
<string name="safety_label_changes_gear_description" msgid="2655887555599138509">"Ezarpenak"</string>
</resources>
diff --git a/PermissionController/res/values-fa/strings.xml b/PermissionController/res/values-fa/strings.xml
index a5c05ca32..2476efe91 100644
--- a/PermissionController/res/values-fa/strings.xml
+++ b/PermissionController/res/values-fa/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"برنامه‌ها"</string>
<string name="app_permissions" msgid="3369917736607944781">"اجازه‌های برنامه"</string>
<string name="unused_apps" msgid="2058057455175955094">"برنامه‌های استفاده‌نشده"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"برنامه استفاده‌نشده‌ای موجود نیست"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"برنامه استفاده‌نشده‌ای وجود ندارد"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"تصمیم‌های اخیر درباره اجازه‌ها"</string>
diff --git a/PermissionController/res/values-fi/strings.xml b/PermissionController/res/values-fi/strings.xml
index ab3ce18fd..d506aa255 100644
--- a/PermissionController/res/values-fi/strings.xml
+++ b/PermissionController/res/values-fi/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Sovell."</string>
<string name="app_permissions" msgid="3369917736607944781">"Sovellusluvat"</string>
<string name="unused_apps" msgid="2058057455175955094">"Käyttämättömät sovellukset"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Ei käyttämättömiä sovelluksia"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 käyttämätöntä sovellusta"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Viimeaikaiset lupapäätökset"</string>
@@ -476,7 +478,7 @@
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn tällä laitteella oleviin musiikki- ja audiotiedostoihin?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn laitteella oleviin kuviin ja mediaan?"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn useampiin laitteella oleviin kuviin ja mediaan?"</string>
- <string name="permgrouprequest_microphone" msgid="2825208549114811299">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; nauhoittaa audiota?"</string>
+ <string name="permgrouprequest_microphone" msgid="2825208549114811299">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tallentaa audiota?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Sovellus voi tallentaa audiota vain silloin, kun käytät sitä"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tallentaa audiota?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Sovellus voi haluta tallentaa audiota aina, myös silloin kun et käytä sitä. "<annotation id="link">"Myönnä lupa asetuksista"</annotation>"."</string>
diff --git a/PermissionController/res/values-fr-rCA/strings.xml b/PermissionController/res/values-fr-rCA/strings.xml
index 3e71c4d16..5943fa992 100644
--- a/PermissionController/res/values-fr-rCA/strings.xml
+++ b/PermissionController/res/values-fr-rCA/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Applications"</string>
<string name="app_permissions" msgid="3369917736607944781">"Autorisations des applications"</string>
<string name="unused_apps" msgid="2058057455175955094">"Applications non utilisées"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Aucune application inutilisée"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Aucune application inutilisée"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Décisions d\'autorisation récentes"</string>
diff --git a/PermissionController/res/values-fr/strings.xml b/PermissionController/res/values-fr/strings.xml
index 6af03ec38..2957b1197 100644
--- a/PermissionController/res/values-fr/strings.xml
+++ b/PermissionController/res/values-fr/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Applications"</string>
<string name="app_permissions" msgid="3369917736607944781">"Autorisations des applications"</string>
<string name="unused_apps" msgid="2058057455175955094">"Applications inutilisées"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Aucune appli inutilisée"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 appli inutilisée"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Décisions autorisations récentes"</string>
diff --git a/PermissionController/res/values-gl/strings.xml b/PermissionController/res/values-gl/strings.xml
index ad7705f59..c97228461 100644
--- a/PermissionController/res/values-gl/strings.xml
+++ b/PermissionController/res/values-gl/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplicacións"</string>
<string name="app_permissions" msgid="3369917736607944781">"Permisos de aplicacións"</string>
<string name="unused_apps" msgid="2058057455175955094">"Aplicacións que non se usan"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Non hai aplicacións sen usar"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 aplicacións que non se usan"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Decisións recentes de permisos"</string>
diff --git a/PermissionController/res/values-gu/strings.xml b/PermissionController/res/values-gu/strings.xml
index d85b35221..66ae04218 100644
--- a/PermissionController/res/values-gu/strings.xml
+++ b/PermissionController/res/values-gu/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"ઍપ"</string>
<string name="app_permissions" msgid="3369917736607944781">"ઍપની પરવાનગીઓ"</string>
<string name="unused_apps" msgid="2058057455175955094">"ન વપરાયેલી ઍપ"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"કોઈ બિનવપરાયેલી ઍપ નથી"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"બિનવપરાયેલી 0 ઍપ"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"પરવાનગી સંબંધિત નિર્ણયો"</string>
@@ -469,7 +471,7 @@
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ચોક્કસ"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"અંદાજિત"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારા કૅલેન્ડરને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
- <string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને SMS સંદેશા મોકલવા અને જોવાની મંજૂરી આપીએ?"</string>
+ <string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને SMS મેસેજ મોકલવા અને જોવાની મંજૂરી આપીએ?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારા ડિવાઇસ પરના ફોટા, મીડિયા અને ફાઇલોને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"શું &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને આ ડિવાઇસ પરના &lt;/b&gt;ફોટા, વીડિયો, મ્યુઝિક અને ઑડિયો&lt;/b&gt;ના ઍક્સેસની મંજૂરી આપીએ?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને આ ડિવાઇસ પર &lt;b&gt;ફોટા, વીડિયો, મ્યુઝિક, ઑડિયો અને અન્ય ફાઇલો&lt;b&gt;ના ઍક્સેસની મંજૂરી આપીએ?"</string>
@@ -516,7 +518,7 @@
<string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g>ને Android વડે સુરક્ષિત કરવામાં આવી છે. આ ડિવાઇસમાં તમારા ડેટા પર પ્રક્રિયા કરવામાં આવતી હોવાથી, આ ઍપની પરવાનગીના વપરાશની માહિતી તમારા પ્રાઇવસી ડૅશબોર્ડ પર બતાવવામાં આવતી નથી."</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"ડિવાઇસનો કૅમેરા બ્લૉક કરેલો છે"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"ડિવાઇસનું માઇક્રોફોન બ્લૉક કરેલું છે"</string>
- <string name="blocked_location_title" msgid="2005608279812892383">"ડિવાઇસનું સ્થાન બંધ છે"</string>
+ <string name="blocked_location_title" msgid="2005608279812892383">"ડિવાઇસનું લોકેશન બંધ છે"</string>
<string name="blocked_sensor_summary" msgid="4443707628305027375">"ઍપ અને સેવાઓ માટે"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"જ્યારે તમે ઇમર્જન્સી નંબર પર કૉલ કરો ત્યારે કદાચ માઇક્રોફોનનો ડેટા હજી પણ શેર કરવામાં આવી શકે છે."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"બદલો"</string>
diff --git a/PermissionController/res/values-hi/strings.xml b/PermissionController/res/values-hi/strings.xml
index 4a083e0cd..66a010d92 100644
--- a/PermissionController/res/values-hi/strings.xml
+++ b/PermissionController/res/values-hi/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"ऐप्लिकेशन"</string>
<string name="app_permissions" msgid="3369917736607944781">"ऐप्लिकेशन की अनुमतियां"</string>
<string name="unused_apps" msgid="2058057455175955094">"इस्तेमाल नहीं किए गए ऐप्लिकेशन"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"ऐसा कोई ऐप्लिकेशन नहींं है जिसका इस्तेमाल न किया गया हो"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"इस्तेमाल न किए जाने वाले ऐप"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"हाल ही में दी गई अनुमतियां"</string>
@@ -196,7 +198,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"जगह की सटीक जानकारी का इस्तेमाल करें"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"जगह की सटीक जानकारी देने वाली सुविधा बंद होने पर, ऐप्लिकेशन आपकी अनुमानित जगह की जानकारी को ऐक्सेस कर सकते हैं"</string>
<string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g> की अनुमति"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"इस ऐप्लिकेशन के लिए यह अनुमति चाहिए: <xliff:g id="PERM">%1$s</xliff:g>"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"इस ऐप्लिकेशन के लिए, <xliff:g id="PERM">%1$s</xliff:g> ऐक्सेस करने की अनुमति चाहिए"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g> को मिली सभी अनुमतियां देखें"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"इस अनुमति वाले सभी ऐप्लिकेशन देखें"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"असिस्टेंट माइक्रोफ़ोन के इस्तेमाल से जुड़ा डेटा दिखाएं"</string>
@@ -469,7 +471,7 @@
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"सटीक जगह"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"अनुमानित जगह"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपना कैलेंडर ऐक्सेस करने की अनुमति देना है?"</string>
- <string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को एसएमएस (मैसेज) भेजने और देखने की अनुमति देना चाहते हैं?"</string>
+ <string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को एसएमएस (मैसेज) भेजने और देखने की अनुमति देनी है?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को डिवाइस पर मौजूद फ़ोटो, ऑडियो-वीडियो, और फ़ाइलें ऐक्सेस करने की अनुमति देना चाहते हैं?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को इस डिवाइस में मौजूद &lt;b&gt;फ़ोटो, वीडियो, संगीत, और ऑडियो&lt;/b&gt; का ऐक्सेस देना है?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को डिवाइस में मौजूद &lt;b&gt;फ़ोटो, वीडियो, संगीत, ऑडियो, और अन्य फ़ाइल&lt;/b&gt; का ऐक्सेस देना है?"</string>
diff --git a/PermissionController/res/values-hr/strings.xml b/PermissionController/res/values-hr/strings.xml
index b63d820f2..a38e0c029 100644
--- a/PermissionController/res/values-hr/strings.xml
+++ b/PermissionController/res/values-hr/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplikacije"</string>
<string name="app_permissions" msgid="3369917736607944781">"Dopuštenja za aplikacije"</string>
<string name="unused_apps" msgid="2058057455175955094">"Nekorištene aplikacije"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nema nekorištenih aplikacija"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Nema nekorištenih aplikacija"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Nedavne odluke o dopuštenjima"</string>
diff --git a/PermissionController/res/values-hu/strings.xml b/PermissionController/res/values-hu/strings.xml
index 12ad687a6..aeed6cb5a 100644
--- a/PermissionController/res/values-hu/strings.xml
+++ b/PermissionController/res/values-hu/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Alkalmazások"</string>
<string name="app_permissions" msgid="3369917736607944781">"Alkalmazásengedélyek"</string>
<string name="unused_apps" msgid="2058057455175955094">"Nem használt alkalmazások"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nincsenek nem használt appok"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 nem használt alkalmazás"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Friss engedélyezési döntések"</string>
diff --git a/PermissionController/res/values-hy/strings.xml b/PermissionController/res/values-hy/strings.xml
index 73742eb53..0e7787de2 100644
--- a/PermissionController/res/values-hy/strings.xml
+++ b/PermissionController/res/values-hy/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Հավելվածներ"</string>
<string name="app_permissions" msgid="3369917736607944781">"Հավելվածների թույլտվություններ"</string>
<string name="unused_apps" msgid="2058057455175955094">"Չօգտագործվող հավելվածներ"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Չօգտագործվող հավելվածներ չկան"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Չօգտագործվող հավելվածներ չկան"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Թույլտվության որոշումներ"</string>
diff --git a/PermissionController/res/values-in/strings.xml b/PermissionController/res/values-in/strings.xml
index 777933785..7b52579c3 100644
--- a/PermissionController/res/values-in/strings.xml
+++ b/PermissionController/res/values-in/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplikasi"</string>
<string name="app_permissions" msgid="3369917736607944781">"Izin aplikasi"</string>
<string name="unused_apps" msgid="2058057455175955094">"Aplikasi tidak digunakan"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Tak ada aplikasi tidak dipakai"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 aplikasi tidak digunakan"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Keputusan izin terbaru"</string>
@@ -466,7 +468,7 @@
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; menemukan, terhubung ke, dan menentukan posisi relatif perangkat di sekitar? "<annotation id="link">"Izinkan di setelan."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Ubah akses lokasi <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> dari perkiraan ke lokasi presisi?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses perkiraan lokasi perangkat ini?"</string>
- <string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Akurat"</string>
+ <string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Presisi"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Perkiraan"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses kalender?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengirim dan melihat SMS?"</string>
diff --git a/PermissionController/res/values-is/strings.xml b/PermissionController/res/values-is/strings.xml
index ab698d6ab..deda67ff9 100644
--- a/PermissionController/res/values-is/strings.xml
+++ b/PermissionController/res/values-is/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Forrit"</string>
<string name="app_permissions" msgid="3369917736607944781">"Heimildir forrits"</string>
<string name="unused_apps" msgid="2058057455175955094">"Ónotuð forrit"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Engin ónotuð forrit"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 ónotuð forrit"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Nýlegar heimildaákvarðanir"</string>
diff --git a/PermissionController/res/values-it/strings.xml b/PermissionController/res/values-it/strings.xml
index 5aaf447b0..75b8828f1 100644
--- a/PermissionController/res/values-it/strings.xml
+++ b/PermissionController/res/values-it/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"App"</string>
<string name="app_permissions" msgid="3369917736607944781">"Autorizzazioni app"</string>
<string name="unused_apps" msgid="2058057455175955094">"App inutilizzate"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nessuna app inutilizzata"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 app inutilizzate"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Decisioni recenti per le autorizzazioni"</string>
@@ -245,13 +247,13 @@
<string name="app_permission_most_recent_denied_summary" msgid="7659497197737708112">"Al momento rifiutata/Ultimo accesso: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_never_accessed_summary" msgid="401346181461975090">"Accesso mai eseguito"</string>
<string name="app_permission_never_accessed_denied_summary" msgid="6596000497490905146">"Rifiutata/Accesso mai effettuato"</string>
- <string name="allowed_header" msgid="7769277978004790414">"Autorizzate"</string>
+ <string name="allowed_header" msgid="7769277978004790414">"Autorizzata"</string>
<string name="allowed_always_header" msgid="6455903312589013545">"Autorizzazione sempre concessa"</string>
<string name="allowed_foreground_header" msgid="6845655788447833353">"Autorizzazione concessa solo durante l\'uso"</string>
<string name="allowed_storage_scoped" msgid="5383645873719086975">"Autorizzate solo per contenuti multimediali"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"Autorizzate per gestire tutti i file"</string>
<string name="ask_header" msgid="2633816846459944376">"Chiedi ogni volta"</string>
- <string name="denied_header" msgid="903209608358177654">"Non autorizzate"</string>
+ <string name="denied_header" msgid="903209608358177654">"Non autorizzata"</string>
<string name="storage_footer_hyperlink_text" msgid="8873343987957834810">"Visualizza altre app che possono accedere a tutti i file"</string>
<string name="days" msgid="609563020985571393">"{count,plural, =1{1 giorno}many{# giorni}other{# giorni}}"</string>
<string name="hours" msgid="7302866489666950038">"{count,plural, =1{# ora}many{# ore}other{# ore}}"</string>
@@ -462,8 +464,8 @@
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Questa app potrebbe voler accedere sempre alla tua posizione, anche quando non la usi. "<annotation id="link">"Consenti l\'accesso nelle impostazioni"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Vuoi cambiare l\'accesso alla posizione per l\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Questa app vorrebbe accedere sempre alla tua posizione, anche quando non la usi. "<annotation id="link">"Consenti l\'accesso nelle impostazioni"</annotation>"."</string>
- <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di trovare e connettersi a dispositivi vicini, nonché stabilirne la posizione relativa?"</string>
- <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di trovare e connettersi a dispositivi vicini, nonché stabilirne la posizione relativa? "<annotation id="link">"Consenti nelle impostazioni."</annotation></string>
+ <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di trovare e connettersi ai dispositivi vicini, e di stabilirne la posizione relativa?"</string>
+ <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di trovare e connettersi ai dispositivi vicini, e di stabilirne la posizione relativa? "<annotation id="link">"Consenti nelle impostazioni."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Modificare l\'accesso alla posizione di <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> da approssimativa a esatta?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere alla posizione approssimativa di questo dispositivo?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Esatta"</string>
diff --git a/PermissionController/res/values-iw/strings.xml b/PermissionController/res/values-iw/strings.xml
index f261a0552..b82142a11 100644
--- a/PermissionController/res/values-iw/strings.xml
+++ b/PermissionController/res/values-iw/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"אפליקציות"</string>
<string name="app_permissions" msgid="3369917736607944781">"הרשאות לאפליקציות"</string>
<string name="unused_apps" msgid="2058057455175955094">"אפליקציות שמזמן לא השתמשת בהן"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"אין אפליקציות שאינן בשימוש"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"אין אפליקציות שאינן בשימוש"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"ההחלטות האחרונות לגבי הרשאות"</string>
diff --git a/PermissionController/res/values-ja/strings.xml b/PermissionController/res/values-ja/strings.xml
index 06ee27a95..949749991 100644
--- a/PermissionController/res/values-ja/strings.xml
+++ b/PermissionController/res/values-ja/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"アプリ"</string>
<string name="app_permissions" msgid="3369917736607944781">"アプリの権限"</string>
<string name="unused_apps" msgid="2058057455175955094">"使用されていないアプリ"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"使用されていないアプリはありません"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"使用していないアプリ: 0 個"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"最近の権限の許可 / 拒否"</string>
diff --git a/PermissionController/res/values-ka/strings.xml b/PermissionController/res/values-ka/strings.xml
index 15f434a33..e42d430b0 100644
--- a/PermissionController/res/values-ka/strings.xml
+++ b/PermissionController/res/values-ka/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"აპები"</string>
<string name="app_permissions" msgid="3369917736607944781">"აპის ნებართვები"</string>
<string name="unused_apps" msgid="2058057455175955094">"გამოუყენებელი აპები"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"გამოუყენებელი აპები არ არის"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 გამოუყენებელი აპი"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"ნებართვის შეს. უახ. გადაწყვეტ."</string>
diff --git a/PermissionController/res/values-kk/strings.xml b/PermissionController/res/values-kk/strings.xml
index 72320b1d0..c818d6530 100644
--- a/PermissionController/res/values-kk/strings.xml
+++ b/PermissionController/res/values-kk/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Қолданбалар"</string>
<string name="app_permissions" msgid="3369917736607944781">"Қолданба рұқсаттары"</string>
<string name="unused_apps" msgid="2058057455175955094">"Пайдаланылмайтын қолданбалар"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Пайдаланылмайтын қолданбалар жоқ"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 пайдаланылмайтын қолданба бар"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Рұқсат беру әрекеттері"</string>
diff --git a/PermissionController/res/values-km/strings.xml b/PermissionController/res/values-km/strings.xml
index a50189176..1a7e84100 100644
--- a/PermissionController/res/values-km/strings.xml
+++ b/PermissionController/res/values-km/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"កម្មវិធី"</string>
<string name="app_permissions" msgid="3369917736607944781">"ការអនុញ្ញាតកម្មវិធី"</string>
<string name="unused_apps" msgid="2058057455175955094">"កម្មវិធី​ដែលមិន​ប្រើ"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"មិនមានកម្មវិធីដែលមិនបានប្រើទេ"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"កម្មវិធី​ដែលមិន​ប្រើ 0"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"ការសម្រេចថ្មីៗលើការអនុញ្ញាត"</string>
diff --git a/PermissionController/res/values-kn/strings.xml b/PermissionController/res/values-kn/strings.xml
index 331da913b..05d524f18 100644
--- a/PermissionController/res/values-kn/strings.xml
+++ b/PermissionController/res/values-kn/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"ಆ್ಯಪ್‌ಗಳು"</string>
<string name="app_permissions" msgid="3369917736607944781">"ಆ್ಯಪ್ ಅನುಮತಿಗಳು"</string>
<string name="unused_apps" msgid="2058057455175955094">"ಬಳಕೆಯಾಗದ ಆ್ಯಪ್‌ಗಳು"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"ಯಾವುದೇ ಬಳಕೆಯಾಗದ ಆ್ಯಪ್‌ಗಳಿಲ್ಲ"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 ಬಳಕೆಯಾಗದ ಆ್ಯಪ್‌ಗಳು"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"ಇತ್ತೀಚಿನ ಅನುಮತಿ ನಿರ್ಧಾರಗಳು"</string>
@@ -469,7 +471,7 @@
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ನಿಖರ"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"ಅಂದಾಜು"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್ ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
- <string name="permgrouprequest_sms" msgid="5672063688745420991">"ಎಸ್‌ಎಂಎಸ್‌ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಮತ್ತು ವೀಕ್ಷಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <string name="permgrouprequest_sms" msgid="5672063688745420991">"SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಮತ್ತು ವೀಕ್ಷಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"ಸಾಧನದಲ್ಲಿ ಫೋಟೋಗಳು, ಮಾಧ್ಯಮ, ಫೈಲ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"ಈ ಸಾಧನದಲ್ಲಿರುವ &lt;b&gt;ಫೋಟೋಗಳು, ವೀಡಿಯೊಗಳು, ಸಂಗೀತ, ಆಡಿಯೊವನ್ನು&lt;/b&gt; ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೆ?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"ಈ ಸಾಧನದಲ್ಲಿರುವ &lt;b&gt;ಫೋಟೋಗಳು, ವೀಡಿಯೊಗಳು, ಸಂಗೀತ, ಆಡಿಯೋ, ಇತರ ಫೈಲ್‌ಗಳನ್ನು&lt;/b&gt; ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೆ?"</string>
@@ -512,8 +514,8 @@
<string name="privdash_label_none" msgid="5991866260360484858">"ಯಾವುದೂ ಅಲ್ಲ"</string>
<string name="privdash_label_24h" msgid="1512532123865375319">"ಕಳೆದ\n24 ಗಂಟೆಗಳು"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"ಕಳೆದ\n7 ದಿನಗಳಲ್ಲಿ"</string>
- <string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಅನ್ನು Android ನಿಂದ ರಕ್ಷಣೆ ಪಡೆದಿದೆ. ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲಾಗಿರುವುದರಿಂದ, ಈ ಆ್ಯಪ್‌ನ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಅಥವಾ ನಿಮ್ಮ ಗೌಪ್ಯತಾ ಡ್ಯಾಶ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವುದಿಲ್ಲ."</string>
- <string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಅನ್ನು Android ನಿಂದ ರಕ್ಷಣೆ ಪಡೆದಿದೆ. ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲಾಗಿರುವುದರಿಂದ, ಈ ಆ್ಯಪ್‌ನ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ನಿಮ್ಮ ಗೌಪ್ಯತಾ ಡ್ಯಾಶ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವುದಿಲ್ಲ."</string>
+ <string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"<xliff:g id="APP_NAME">%1$s</xliff:g>, Android ನಿಂದ ರಕ್ಷಣೆ ಪಡೆದಿದೆ. ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲಾಗಿರುವುದರಿಂದ, ಈ ಆ್ಯಪ್‌ನ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಅಥವಾ ನಿಮ್ಮ ಗೌಪ್ಯತಾ ಡ್ಯಾಶ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವುದಿಲ್ಲ."</string>
+ <string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g>, Android ನಿಂದ ರಕ್ಷಣೆ ಪಡೆದಿದೆ. ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲಾಗಿರುವುದರಿಂದ, ಈ ಆ್ಯಪ್‌ನ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ನಿಮ್ಮ ಗೌಪ್ಯತಾ ಡ್ಯಾಶ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವುದಿಲ್ಲ."</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"ಸಾಧನದ ಕ್ಯಾಮರಾವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"ಸಾಧನದ ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"ಸಾಧನದ ಸ್ಥಳವು ಆಫ್ ಆಗಿದೆ"</string>
diff --git a/PermissionController/res/values-ko/strings.xml b/PermissionController/res/values-ko/strings.xml
index 15256ebec..44fc0fc4b 100644
--- a/PermissionController/res/values-ko/strings.xml
+++ b/PermissionController/res/values-ko/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"앱"</string>
<string name="app_permissions" msgid="3369917736607944781">"앱 권한"</string>
<string name="unused_apps" msgid="2058057455175955094">"사용하지 않는 앱"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"사용하지 않는 앱 없음"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"사용하지 않는 앱 0개"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"최근 권한 결정"</string>
diff --git a/PermissionController/res/values-ky/strings.xml b/PermissionController/res/values-ky/strings.xml
index e8816f7fd..af5376f59 100644
--- a/PermissionController/res/values-ky/strings.xml
+++ b/PermissionController/res/values-ky/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Колдонмолор"</string>
<string name="app_permissions" msgid="3369917736607944781">"Колдонмонун уруксаттары"</string>
<string name="unused_apps" msgid="2058057455175955094">"Колдонулбаган колдонмолор"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Бардык колдонмолор колдонулууда"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Колдонулбаган колдонмолор: 0"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Уруксаттарга байланыштуу аракеттер"</string>
diff --git a/PermissionController/res/values-lo/strings.xml b/PermissionController/res/values-lo/strings.xml
index be8cf2947..857b81553 100644
--- a/PermissionController/res/values-lo/strings.xml
+++ b/PermissionController/res/values-lo/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"ແອັບ"</string>
<string name="app_permissions" msgid="3369917736607944781">"ສິດອະນຸຍາດແອັບ"</string>
<string name="unused_apps" msgid="2058057455175955094">"ແອັບທີ່ບໍ່ໄດ້ໃຊ້"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"ບໍ່ມີແອັບທີ່ບໍ່ໄດ້ໃຊ້"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 ແອັບທີ່ບໍ່ໄດ້ໃຊ້"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"ການຕັດສິນໃຈການອະນຸຍາດຫຼ້າສຸດ"</string>
diff --git a/PermissionController/res/values-lt/strings.xml b/PermissionController/res/values-lt/strings.xml
index 1c179457d..99ff34cf9 100644
--- a/PermissionController/res/values-lt/strings.xml
+++ b/PermissionController/res/values-lt/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Programos"</string>
<string name="app_permissions" msgid="3369917736607944781">"Programų leidimai"</string>
<string name="unused_apps" msgid="2058057455175955094">"Nenaudojamos programos"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nėra nenaudojamų programų"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Nenaudojamų programų: 0"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Nauj. sprendimai dėl leidimų"</string>
diff --git a/PermissionController/res/values-lv/strings.xml b/PermissionController/res/values-lv/strings.xml
index 530e2cc6c..0e3766a79 100644
--- a/PermissionController/res/values-lv/strings.xml
+++ b/PermissionController/res/values-lv/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Lietotnes"</string>
<string name="app_permissions" msgid="3369917736607944781">"Lietotņu atļaujas"</string>
<string name="unused_apps" msgid="2058057455175955094">"Neizmantotās lietotnes"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nav neizmantotu lietotņu"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 neizmantotu lietotņu"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Nesenās darbības ar atļaujām"</string>
diff --git a/PermissionController/res/values-mk/strings.xml b/PermissionController/res/values-mk/strings.xml
index d8c542b76..fd797809f 100644
--- a/PermissionController/res/values-mk/strings.xml
+++ b/PermissionController/res/values-mk/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Апликации"</string>
<string name="app_permissions" msgid="3369917736607944781">"Дозволи за апликации"</string>
<string name="unused_apps" msgid="2058057455175955094">"Некористени апликации"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Нема некористени апликации"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 некористени апликации"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Неодамнешни одлуки за дозволи"</string>
diff --git a/PermissionController/res/values-ml/strings.xml b/PermissionController/res/values-ml/strings.xml
index 81cf39cf5..3d0f839ab 100644
--- a/PermissionController/res/values-ml/strings.xml
+++ b/PermissionController/res/values-ml/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"ആപ്പുകൾ"</string>
<string name="app_permissions" msgid="3369917736607944781">"ആപ്പ് അനുമതികൾ"</string>
<string name="unused_apps" msgid="2058057455175955094">"ഉപയോഗിക്കാത്ത ആപ്പുകൾ"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"ഉപയോഗിക്കാത്ത ആപ്പുകൾ ഇല്ല"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"ഉപയോഗിക്കാത്ത 0 ആപ്പുകൾ"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"സമീപകാല അനുമതി തീരുമാനങ്ങൾ"</string>
diff --git a/PermissionController/res/values-mn/strings.xml b/PermissionController/res/values-mn/strings.xml
index 3332fe450..22581ea5d 100644
--- a/PermissionController/res/values-mn/strings.xml
+++ b/PermissionController/res/values-mn/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Аппууд"</string>
<string name="app_permissions" msgid="3369917736607944781">"Аппын зөвшөөрөл"</string>
<string name="unused_apps" msgid="2058057455175955094">"Ашиглаагүй аппууд"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Ашиглаагүй апп байхгүй байна"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 ашиглаагүй апп"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Саяхны зөвшөөрлийн шийдвэр"</string>
diff --git a/PermissionController/res/values-mr/strings.xml b/PermissionController/res/values-mr/strings.xml
index 18eccb6a7..cc04185c0 100644
--- a/PermissionController/res/values-mr/strings.xml
+++ b/PermissionController/res/values-mr/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"अ‍ॅप्स"</string>
<string name="app_permissions" msgid="3369917736607944781">"अ‍ॅप परवानग्या"</string>
<string name="unused_apps" msgid="2058057455175955094">"न वापरलेली अ‍ॅप्स"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"न वापरलेली कोणतीही ॲप्स नाहीत"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"न वापरलेली शून्य अ‍ॅप्स"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"अलीकडील परवानगीसंबंधित निर्णय"</string>
diff --git a/PermissionController/res/values-ms/strings.xml b/PermissionController/res/values-ms/strings.xml
index 7e560fa73..415dc8c7c 100644
--- a/PermissionController/res/values-ms/strings.xml
+++ b/PermissionController/res/values-ms/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apl"</string>
<string name="app_permissions" msgid="3369917736607944781">"Kebenaran apl"</string>
<string name="unused_apps" msgid="2058057455175955094">"Apl yang tidak digunakan"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Tiada apl yang tidak digunakan"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 apl yang tidak digunakan"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Keputusan kebenaran terbaharu"</string>
diff --git a/PermissionController/res/values-my/strings.xml b/PermissionController/res/values-my/strings.xml
index f83657838..495084e3d 100644
--- a/PermissionController/res/values-my/strings.xml
+++ b/PermissionController/res/values-my/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"အက်ပ်များ"</string>
<string name="app_permissions" msgid="3369917736607944781">"အက်ပ်ခွင့်ပြုချက်များ"</string>
<string name="unused_apps" msgid="2058057455175955094">"အသုံးမပြုသော အက်ပ်များ"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"အသုံးမပြုသောအက်ပ်များ မရှိပါ"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"အသုံးမပြုသောအက်ပ် 0 ခု"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"လတ်တလောခွင့်ပြုသည့် ဆုံးဖြတ်ချက်များ"</string>
diff --git a/PermissionController/res/values-nb/strings.xml b/PermissionController/res/values-nb/strings.xml
index 1e5f58453..44e851bc7 100644
--- a/PermissionController/res/values-nb/strings.xml
+++ b/PermissionController/res/values-nb/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apper"</string>
<string name="app_permissions" msgid="3369917736607944781">"Apptillatelser"</string>
<string name="unused_apps" msgid="2058057455175955094">"Ubrukte apper"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Ingen ubrukte apper"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 ubrukte apper"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Nylige tillatelsesavgjørelser"</string>
diff --git a/PermissionController/res/values-ne/strings.xml b/PermissionController/res/values-ne/strings.xml
index c418348bd..9845c5a3d 100644
--- a/PermissionController/res/values-ne/strings.xml
+++ b/PermissionController/res/values-ne/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"एपहरू"</string>
<string name="app_permissions" msgid="3369917736607944781">"एपसम्बन्धी अनुमति"</string>
<string name="unused_apps" msgid="2058057455175955094">"प्रयोग नगरिएका एपहरू"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"सबै एप चलाइएका छन्"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"प्रयोग नगरिएका एउटा पनि एप छैन"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"हालै दिइएका अनुमतिसम्बन्धी निर्णयहरू"</string>
diff --git a/PermissionController/res/values-nl/strings.xml b/PermissionController/res/values-nl/strings.xml
index f845b1de4..a2c901edb 100644
--- a/PermissionController/res/values-nl/strings.xml
+++ b/PermissionController/res/values-nl/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"App-rechten"</string>
<string name="unused_apps" msgid="2058057455175955094">"Niet-gebruikte apps"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Geen niet-gebruikte apps"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 niet-gebruikte apps"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Recente rechtenbeslissingen"</string>
diff --git a/PermissionController/res/values-or/strings.xml b/PermissionController/res/values-or/strings.xml
index 05fa1472a..aa43c2931 100644
--- a/PermissionController/res/values-or/strings.xml
+++ b/PermissionController/res/values-or/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"ଆପ୍ସ"</string>
<string name="app_permissions" msgid="3369917736607944781">"ଆପ ଅନୁମତିଗୁଡ଼ିକ"</string>
<string name="unused_apps" msgid="2058057455175955094">"ଅବ୍ୟବହୃତ ଆପ୍ସ"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"କୌଣସି ଅବ୍ୟବହୃତ ଆପ୍ ନାହିଁ"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0ଟି ଅବ୍ୟବହୃତ ଆପ୍"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"ବର୍ତ୍ତମାନର ଅନୁମତି ନିଷ୍ପତ୍ତି"</string>
@@ -315,7 +317,7 @@
<string name="permission_subtitle_media_only" msgid="8917869683764720717">"ମିଡିଆ"</string>
<string name="permission_subtitle_all_files" msgid="4982613338298067862">"ସମସ୍ତ ଫାଇଲ୍"</string>
<string name="permission_subtitle_background" msgid="8916750995309083180">"ସର୍ବଦା ଅନୁମତି ଦିଆଯାଇଛି"</string>
- <string name="app_perms_24h_access" msgid="99069906850627181">"<xliff:g id="TIME_DATE">%1$s</xliff:g>ରେ ଗତଥର ଆକ୍ସେସ୍ କରାଯାଇଛି"</string>
+ <string name="app_perms_24h_access" msgid="99069906850627181">"<xliff:g id="TIME_DATE">%1$s</xliff:g>ରେ ଗତଥର ଆକ୍ସେସ କରାଯାଇଛି"</string>
<string name="app_perms_24h_access_yest" msgid="5411926024794555022">"ଗତକାଲି <xliff:g id="TIME_DATE">%1$s</xliff:g>ରେ ଗତଥର ଆକ୍ସେସ୍ କରାଯାଇଛି"</string>
<string name="app_perms_7d_access" msgid="4945055548894683751">"<xliff:g id="TIME_DATE_0">%1$s</xliff:g> <xliff:g id="TIME_DATE_1">%2$s</xliff:g>ରେ ଗତଥର ଆକ୍ସେସ କରାଯାଇଛି"</string>
<string name="app_perms_content_provider_24h" msgid="1055526027667508972">"ଗତ 24 ଘଣ୍ଟାରେ ଆକ୍ସେସ କରାଯାଇଛି"</string>
diff --git a/PermissionController/res/values-pa/strings.xml b/PermissionController/res/values-pa/strings.xml
index f4e26680c..5a45d3416 100644
--- a/PermissionController/res/values-pa/strings.xml
+++ b/PermissionController/res/values-pa/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"ਐਪਾਂ"</string>
<string name="app_permissions" msgid="3369917736607944781">"ਐਪ ਇਜਾਜ਼ਤਾਂ"</string>
<string name="unused_apps" msgid="2058057455175955094">"ਅਣਵਰਤੀਆਂ ਐਪਾਂ"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"ਕੋਈ ਅਣਵਰਤੀ ਐਪ ਨਹੀਂ"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 ਅਣਵਰਤੀਆਂ ਐਪਾਂ"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"ਇਜਾਜ਼ਤ ਸੰਬੰਧੀ ਹਾਲੀਆ ਫ਼ੈਸਲੇ"</string>
diff --git a/PermissionController/res/values-pl/strings.xml b/PermissionController/res/values-pl/strings.xml
index cab2d9d2e..90705c738 100644
--- a/PermissionController/res/values-pl/strings.xml
+++ b/PermissionController/res/values-pl/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplikacje"</string>
<string name="app_permissions" msgid="3369917736607944781">"Uprawnienia aplikacji"</string>
<string name="unused_apps" msgid="2058057455175955094">"Nieużywane aplikacje"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Brak nieużywanych aplikacji"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 nieużywanych aplikacji"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Ostatnie decyzje dotyczące uprawnień"</string>
@@ -462,8 +464,8 @@
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Aplikacja chce mieć stały dostęp do Twojej lokalizacji, nawet gdy nie jest używana. "<annotation id="link">"Zezwól w ustawieniach"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Zmienić uprawnienia dostępu do lokalizacji w przypadku aplikacji „<xliff:g id="APP_NAME">%1$s</xliff:g>”?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Aplikacja chce mieć stały dostęp do Twojej lokalizacji, nawet gdy nie jest używana. "<annotation id="link">"Zezwól w ustawieniach"</annotation></string>
- <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na znalezienie, połączenie i ustalenie względnego położenia urządzeń w pobliżu?"</string>
- <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na znalezienie, połączenie i ustalenie względnego położenia urządzeń w pobliżu? "<annotation id="link">"Zezwól w ustawieniach."</annotation></string>
+ <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na znajdowanie urządzeń w pobliżu, ustalanie ich względnego położenia i łączenie się z nimi?"</string>
+ <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na znajdowanie urządzeń w pobliżu, ustalanie ich względnego położenia i łączenie się z nimi? "<annotation id="link">"Zezwól w ustawieniach."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Zmienić dostęp aplikacji <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> do lokalizacji przybliżonej na dostęp do lokalizacji dokładnej?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Zezwolić aplikacji „<xliff:g id="APP_NAME">%1$s</xliff:g>” na dostęp do przybliżonej lokalizacji urządzenia?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Dokładna"</string>
diff --git a/PermissionController/res/values-pt-rBR/strings.xml b/PermissionController/res/values-pt-rBR/strings.xml
index 73de80954..4975d7436 100644
--- a/PermissionController/res/values-pt-rBR/strings.xml
+++ b/PermissionController/res/values-pt-rBR/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"Permissões do app"</string>
<string name="unused_apps" msgid="2058057455175955094">"Apps não usados"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nenhum app não usado"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 app não usado"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Decisões recentes de permissão"</string>
@@ -198,7 +200,7 @@
<string name="app_permission_title" msgid="2090897901051370711">"Permissão para acessar <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_header" msgid="2951363137032603806">"Permitir que este app acesse: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todas as permissões do app <xliff:g id="APP">%1$s</xliff:g>"</string>
- <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todos os apps que têm esta permissão"</string>
+ <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Mostrar todos os apps que têm esta permissão"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar uso de microfone pelo Assistente"</string>
<string name="unused_apps_category_title" msgid="2988455616845243901">"Configurações de apps não usados"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Remover permissões se o app não for usado"</string>
diff --git a/PermissionController/res/values-pt-rPT/strings.xml b/PermissionController/res/values-pt-rPT/strings.xml
index 012608eee..c1e073ddd 100644
--- a/PermissionController/res/values-pt-rPT/strings.xml
+++ b/PermissionController/res/values-pt-rPT/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"Autorizações da app"</string>
<string name="unused_apps" msgid="2058057455175955094">"Apps não usadas"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nenhuma app não usada"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 apps não utilizadas"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Decisões de autorização recentes"</string>
diff --git a/PermissionController/res/values-pt/strings.xml b/PermissionController/res/values-pt/strings.xml
index 73de80954..4975d7436 100644
--- a/PermissionController/res/values-pt/strings.xml
+++ b/PermissionController/res/values-pt/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"Permissões do app"</string>
<string name="unused_apps" msgid="2058057455175955094">"Apps não usados"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nenhum app não usado"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 app não usado"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Decisões recentes de permissão"</string>
@@ -198,7 +200,7 @@
<string name="app_permission_title" msgid="2090897901051370711">"Permissão para acessar <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_header" msgid="2951363137032603806">"Permitir que este app acesse: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todas as permissões do app <xliff:g id="APP">%1$s</xliff:g>"</string>
- <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todos os apps que têm esta permissão"</string>
+ <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Mostrar todos os apps que têm esta permissão"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar uso de microfone pelo Assistente"</string>
<string name="unused_apps_category_title" msgid="2988455616845243901">"Configurações de apps não usados"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Remover permissões se o app não for usado"</string>
diff --git a/PermissionController/res/values-ro/strings.xml b/PermissionController/res/values-ro/strings.xml
index defbf3177..c86e6d8c9 100644
--- a/PermissionController/res/values-ro/strings.xml
+++ b/PermissionController/res/values-ro/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplicații"</string>
<string name="app_permissions" msgid="3369917736607944781">"Permisiuni pentru aplicații"</string>
<string name="unused_apps" msgid="2058057455175955094">"Aplicații nefolosite"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nu există aplicații nefolosite"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 aplicații nefolosite"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Decizii recente privind permisiunile"</string>
diff --git a/PermissionController/res/values-ru/strings.xml b/PermissionController/res/values-ru/strings.xml
index fa9bd96af..1c0a25a13 100644
--- a/PermissionController/res/values-ru/strings.xml
+++ b/PermissionController/res/values-ru/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Приложения"</string>
<string name="app_permissions" msgid="3369917736607944781">"Разрешения приложений"</string>
<string name="unused_apps" msgid="2058057455175955094">"Неиспользуемые приложения"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Неиспользуемых приложений нет"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Нет неиспользуемых приложений"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Действия с разрешениями"</string>
@@ -462,8 +464,8 @@
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Этому приложению может потребоваться доступ к вашему местоположению, даже когда вы им не пользуетесь. Предоставьте разрешение в "<annotation id="link">"настройках"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Изменить настройки доступа к данным о местоположении для приложения &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Этому приложению требуется доступ к вашему местоположению, даже когда вы им не пользуетесь. Предоставьте разрешение в "<annotation id="link">"настройках"</annotation>"."</string>
- <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Разрешить приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" находить устройства поблизости, подключаться к ним и определять их относительное положение?"</string>
- <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Разрешить приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" находить устройства поблизости, подключаться к ним и определять их относительное позиционирование? "<annotation id="link">"Открыть настройки"</annotation></string>
+ <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; находить устройства поблизости, подключаться к ним и определять их относительное положение?"</string>
+ <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; находить устройства поблизости, подключаться к ним и определять их относительное положение? "<annotation id="link">"Открыть настройки"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Изменить местоположение в приложении \"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>\" с приблизительного на точное?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к данным о приблизительном местоположении устройства?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Точно"</string>
diff --git a/PermissionController/res/values-si/strings.xml b/PermissionController/res/values-si/strings.xml
index 1899c6e70..a37a4c095 100644
--- a/PermissionController/res/values-si/strings.xml
+++ b/PermissionController/res/values-si/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"යෙදුම්"</string>
<string name="app_permissions" msgid="3369917736607944781">"යෙදුම් අවසර"</string>
<string name="unused_apps" msgid="2058057455175955094">"භාවිත නොකළ යෙදුම්"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"භාවිත නොකළ යෙදුම් නැත"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"භාවිත නොකළ යෙදුම් 0"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"මෑත අවසර තීරණ"</string>
diff --git a/PermissionController/res/values-sk/strings.xml b/PermissionController/res/values-sk/strings.xml
index ae8ea524c..561b31e28 100644
--- a/PermissionController/res/values-sk/strings.xml
+++ b/PermissionController/res/values-sk/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplikácie"</string>
<string name="app_permissions" msgid="3369917736607944781">"Povolenia aplikácií"</string>
<string name="unused_apps" msgid="2058057455175955094">"Nepoužívané aplikácie"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Žiadne nepoužívané aplikácie"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Žiadne nepoužívané aplikácie"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Nedávne rozhodnutia o povolení"</string>
diff --git a/PermissionController/res/values-sl/strings.xml b/PermissionController/res/values-sl/strings.xml
index 5265a0724..b799cfe72 100644
--- a/PermissionController/res/values-sl/strings.xml
+++ b/PermissionController/res/values-sl/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplikacije"</string>
<string name="app_permissions" msgid="3369917736607944781">"Dovoljenja za aplikacije"</string>
<string name="unused_apps" msgid="2058057455175955094">"Neuporabljene aplikacije"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Ni neuporabljenih aplikacij."</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 neuporabljenih aplikacij"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Nedavne odločitve o dovoljenjih"</string>
diff --git a/PermissionController/res/values-sq/strings.xml b/PermissionController/res/values-sq/strings.xml
index 42e412062..b30327631 100644
--- a/PermissionController/res/values-sq/strings.xml
+++ b/PermissionController/res/values-sq/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Aplikacionet"</string>
<string name="app_permissions" msgid="3369917736607944781">"Lejet e aplikacionit"</string>
<string name="unused_apps" msgid="2058057455175955094">"Aplikacionet e papërdorura"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Nuk ka aplikacione të papërdorura"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 aplikacione të papërdorura"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Vendimet e fundit për lejet"</string>
@@ -195,8 +197,8 @@
<string name="approximate_image_description" msgid="938803699637069884">"Vendndodhja e përafërt"</string>
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Përdor vendndodhjen e saktë"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Kur është joaktive vendndodhja e saktë, aplikacionet mund të qasen te vendndodhja jote e përafërt"</string>
- <string name="app_permission_title" msgid="2090897901051370711">"Leje për te <xliff:g id="PERM">%1$s</xliff:g>"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"Qasja te <xliff:g id="PERM">%1$s</xliff:g> për këtë aplikacion"</string>
+ <string name="app_permission_title" msgid="2090897901051370711">"Leje për te \"<xliff:g id="PERM">%1$s</xliff:g>\""</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Qasja te \"<xliff:g id="PERM">%1$s</xliff:g>\" për këtë aplikacion"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Shiko të gjitha lejet e aplikacionit \"<xliff:g id="APP">%1$s</xliff:g>\""</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Shiko të gjitha aplikacionet me këtë leje"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Shfaq përdorimin e mikrofonit të \"Asistentit\""</string>
@@ -211,7 +213,7 @@
<string name="auto_revoke_open_app_message" msgid="8075556291711205039">"Nëse dëshiron t\'i lejosh përsëri lejet, hap aplikacionin."</string>
<string name="auto_revoke_disabled" msgid="8697684442991567188">"Heqja automatike aktualisht është çaktivizuar për këtë aplikacion."</string>
<string name="auto_revocable_permissions_none" msgid="8334929619113991466">"Aktualisht nuk janë dhënë leje të revokueshme automatikisht"</string>
- <string name="auto_revocable_permissions_one" msgid="5299112369449458176">"Leja për \"<xliff:g id="PERM">%1$s</xliff:g>\" do të hiqet."</string>
+ <string name="auto_revocable_permissions_one" msgid="5299112369449458176">"Leja për te \"<xliff:g id="PERM">%1$s</xliff:g>\" do të hiqet."</string>
<string name="auto_revocable_permissions_two" msgid="4874067408752041716">"Lejet <xliff:g id="PERM_0">%1$s</xliff:g> dhe <xliff:g id="PERM_1">%2$s</xliff:g> do të hiqen."</string>
<string name="auto_revocable_permissions_many" msgid="1521807896206032992">"Lejet që do të hiqen: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_manage_title" msgid="7693181026874842935">"Menaxho automatikisht lejet"</string>
diff --git a/PermissionController/res/values-sr/strings.xml b/PermissionController/res/values-sr/strings.xml
index 0fd94a069..2795422b0 100644
--- a/PermissionController/res/values-sr/strings.xml
+++ b/PermissionController/res/values-sr/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Апликације"</string>
<string name="app_permissions" msgid="3369917736607944781">"Дозволе за апликације"</string>
<string name="unused_apps" msgid="2058057455175955094">"Апликације које се не користе"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Нема аплик. које се не користе"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 апликац. које се не користе"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Недавне одлуке о дозволама"</string>
@@ -93,7 +95,7 @@
<string name="location_warning" msgid="2381649060929040962">"<xliff:g id="APP_NAME">%1$s</xliff:g> пружа услуге локације за овај уређај. Приступ локацији можете да измените у подешавањима локације."</string>
<string name="system_warning" msgid="1173400963234358816">"Ако одбијете ову дозволу, основне функције уређаја можда неће више исправно радити."</string>
<string name="deny_read_media_visual_warning" msgid="3982586279917232827">"Ова апликација је дизајнирана за старију верзију Android-а. Ако овој апликацији одбијете приступ за слике и видео снимке, повлачи се и приступ музици и другим аудио снимцима."</string>
- <string name="deny_read_media_aural_warning" msgid="8928699919508646732">"Ова апликација је дизајнирана за старију верзију Android-а. Ако овој апликацији одбијете приступ за музику и друге аудио снимке, повлачи се и приступ сликама и видео снимцима."</string>
+ <string name="deny_read_media_aural_warning" msgid="8928699919508646732">"Ова апликација је дизајнирана за старију верзију Android-а. Ако овој апликацији одбијете приступ за музику и друге аудио снимке, повлачи се и приступ сликама и видеима."</string>
<string name="cdm_profile_revoke_warning" msgid="4443893270719106700">"Ако одбијете ову дозволу, неке функције уређаја којима управља ова апликација можда неће више исправно радити."</string>
<string name="permission_summary_enforced_by_policy" msgid="4443598170942950519">"Примењује се у складу са смерницама"</string>
<string name="permission_summary_disabled_by_policy_background_only" msgid="221995005556362660">"Приступ у позадини је онемогућен смерницама"</string>
@@ -240,7 +242,7 @@
<string name="permission_description_summary_sms" msgid="725999468547768517">"Апликације са овом дозволом могу да шаљу и прегледају SMS-ове"</string>
<string name="permission_description_summary_storage" msgid="6575759089065303346">"Апликације са овом дозволом могу да приступају сликама, медијском садржају и фајловима на уређају"</string>
<string name="permission_description_summary_read_media_aural" msgid="3354728149930482199">"Апликације са овом дозволом могу да приступају музици и другим аудио фајловима на овом уређају"</string>
- <string name="permission_description_summary_read_media_visual" msgid="4991801977881732641">"Апликације са овом дозволом могу да приступају сликама и видео снимцима на овом уређају"</string>
+ <string name="permission_description_summary_read_media_visual" msgid="4991801977881732641">"Апликације са овом дозволом могу да приступају сликама и видеима на овом уређају"</string>
<string name="app_permission_most_recent_summary" msgid="4292074449384040590">"Последњи приступ: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_most_recent_denied_summary" msgid="7659497197737708112">"Тренутно одбијено/последњи приступ: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_never_accessed_summary" msgid="401346181461975090">"Без приступа"</string>
@@ -475,7 +477,7 @@
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Приступ сликама, видеу, музици, звуку и другом на уређају за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Дозвољавате ли приступ музици и звуку на овом уређају за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Дозвољавате ли приступ сликама и видеу на овом уређају за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
- <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Дозвољавате ли да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа и другим сликама и видео снимцима на овом уређају?"</string>
+ <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Дозвољавате ли да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа и другим сликама и видеима на овом уређају?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; снима звук?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Апликација ће моћи да снима звук само док користите апликацију"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; снима звук?"</string>
@@ -558,18 +560,18 @@
<string name="media_confirm_dialog_title_a_to_p_aural_deny" msgid="7841428716317307685">"Ни приступ другим фајловима неће бити дозвољен"</string>
<string name="media_confirm_dialog_title_a_to_p_visual_allow" msgid="6469086448310893751">"Биће дозвољен приступ и другим фајловима"</string>
<string name="media_confirm_dialog_title_a_to_p_visual_deny" msgid="5767849609024384226">"Ни приступ другим фајловима неће бити дозвољен"</string>
- <string name="media_confirm_dialog_title_q_to_s_aural_allow" msgid="3191904399336990537">"Биће дозвољен приступ и сликама и видео снимцима"</string>
- <string name="media_confirm_dialog_title_q_to_s_aural_deny" msgid="3128147568953297969">"Ни приступ сликама и видео снимцима неће бити дозвољен"</string>
+ <string name="media_confirm_dialog_title_q_to_s_aural_allow" msgid="3191904399336990537">"Биће дозвољен приступ и сликама и видеима"</string>
+ <string name="media_confirm_dialog_title_q_to_s_aural_deny" msgid="3128147568953297969">"Ни приступ сликама и видеима неће бити дозвољен"</string>
<string name="media_confirm_dialog_title_q_to_s_visual_allow" msgid="6310682466493330434">"Биће дозвољен приступ и музици и аудио фајловима"</string>
<string name="media_confirm_dialog_title_q_to_s_visual_deny" msgid="1123845663785900471">"Ни приступ музици и аудио фајловима неће бити дозвољен"</string>
- <string name="media_confirm_dialog_message_a_to_p_aural_allow" msgid="7865167246140107623">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација може да приступа музици и аудио фајловима, биће јој дозвољено и да приступа сликама, видео снимцима и другим фајловима."</string>
- <string name="media_confirm_dialog_message_a_to_p_aural_deny" msgid="287502523664804786">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација не може да приступа музици и аудио фајловима, неће јој бити дозвољено ни да приступа сликама, видео снимцима и другим фајловима."</string>
- <string name="media_confirm_dialog_message_a_to_p_visual_allow" msgid="4952410892939590487">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација може да приступа сликама и видео снимцима, биће јој дозвољено и да приступа музици, аудио и другим фајловима."</string>
- <string name="media_confirm_dialog_message_a_to_p_visual_deny" msgid="6609500525590757681">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација не може да приступа сликама и видео снимцима, неће јој бити дозвољено ни да приступа музици, аудио и другим фајловима."</string>
- <string name="media_confirm_dialog_message_q_to_s_aural_allow" msgid="1702402580147536160">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација може да приступа музици и аудио фајловима, биће јој дозвољено и да приступа сликама и видео снимцима."</string>
- <string name="media_confirm_dialog_message_q_to_s_aural_deny" msgid="6832087393653561911">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација не може да приступа музици и аудио фајловима, неће јој бити дозвољено ни да приступа сликама и видео снимцима."</string>
- <string name="media_confirm_dialog_message_q_to_s_visual_allow" msgid="3504335060843147760">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација може да приступа сликама и видео снимцима, биће јој дозвољено и да приступа музици и аудио фајловима."</string>
- <string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација не може да приступа музици и аудио фајловима, неће јој бити дозвољено ни да приступа сликама и видео снимцима."</string>
+ <string name="media_confirm_dialog_message_a_to_p_aural_allow" msgid="7865167246140107623">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација може да приступа музици и аудио фајловима, биће јој дозвољено и да приступа сликама, видеима и другим фајловима."</string>
+ <string name="media_confirm_dialog_message_a_to_p_aural_deny" msgid="287502523664804786">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација не може да приступа музици и аудио фајловима, неће јој бити дозвољено ни да приступа сликама, видеима и другим фајловима."</string>
+ <string name="media_confirm_dialog_message_a_to_p_visual_allow" msgid="4952410892939590487">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација може да приступа сликама и видеима, биће јој дозвољено и да приступа музици, аудио и другим фајловима."</string>
+ <string name="media_confirm_dialog_message_a_to_p_visual_deny" msgid="6609500525590757681">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација не може да приступа сликама и видеима, неће јој бити дозвољено ни да приступа музици, аудио и другим фајловима."</string>
+ <string name="media_confirm_dialog_message_q_to_s_aural_allow" msgid="1702402580147536160">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација може да приступа музици и аудио фајловима, биће јој дозвољено и да приступа сликама и видеима."</string>
+ <string name="media_confirm_dialog_message_q_to_s_aural_deny" msgid="6832087393653561911">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација не може да приступа музици и аудио фајловима, неће јој бити дозвољено ни да приступа сликама и видеима."</string>
+ <string name="media_confirm_dialog_message_q_to_s_visual_allow" msgid="3504335060843147760">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација може да приступа сликама и видеима, биће јој дозвољено и да приступа музици и аудио фајловима."</string>
+ <string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"Ова апликација не подржава најновију верзију Android-а. Ако ова апликација не може да приступа музици и аудио фајловима, неће јој бити дозвољено ни да приступа сликама и видеима."</string>
<string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"Прегледајте апликацију са приступом локацији у позадини"</string>
<string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> увек може да приступа вашој локацији, чак и кад је апликација затворена"</string>
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Прегледајте апликацију са приступом локацији у позадини"</string>
diff --git a/PermissionController/res/values-sv/strings.xml b/PermissionController/res/values-sv/strings.xml
index 7d53baf1a..4898cfc4e 100644
--- a/PermissionController/res/values-sv/strings.xml
+++ b/PermissionController/res/values-sv/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Appar"</string>
<string name="app_permissions" msgid="3369917736607944781">"Appbehörigheter"</string>
<string name="unused_apps" msgid="2058057455175955094">"Appar som inte används"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Inga appar som inte används"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 appar som inte används"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Senaste behörighetsbesluten"</string>
diff --git a/PermissionController/res/values-sw/strings.xml b/PermissionController/res/values-sw/strings.xml
index 83a4ebe03..910366d7f 100644
--- a/PermissionController/res/values-sw/strings.xml
+++ b/PermissionController/res/values-sw/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Programu"</string>
<string name="app_permissions" msgid="3369917736607944781">"Ruhusa za programu"</string>
<string name="unused_apps" msgid="2058057455175955094">"Programu zisizotumika"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Hakuna programu zisizotumika"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Hakuna programu zisizotumika"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Uamuzi wa ruhusa wa hivi majuzi"</string>
diff --git a/PermissionController/res/values-ta/strings.xml b/PermissionController/res/values-ta/strings.xml
index ad2bea8a3..cc70d4f96 100644
--- a/PermissionController/res/values-ta/strings.xml
+++ b/PermissionController/res/values-ta/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"ஆப்ஸ்"</string>
<string name="app_permissions" msgid="3369917736607944781">"ஆப்ஸ் அனுமதிகள்"</string>
<string name="unused_apps" msgid="2058057455175955094">"பயன்படுத்தாத ஆப்ஸ்"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"பயன்படுத்தாத ஆப்ஸ் எதுவுமில்லை"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 பயன்படுத்தாத ஆப்ஸ்"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"அனுமதி தொடர்பான முடிவுகள்"</string>
diff --git a/PermissionController/res/values-te/strings.xml b/PermissionController/res/values-te/strings.xml
index 9c94db31b..9848f3c26 100644
--- a/PermissionController/res/values-te/strings.xml
+++ b/PermissionController/res/values-te/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"యాప్‌లు"</string>
<string name="app_permissions" msgid="3369917736607944781">"యాప్ అనుమతులు"</string>
<string name="unused_apps" msgid="2058057455175955094">"ఉపయోగించని యాప్‌లు"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"ఉపయోగించని యాప్‌లు లేవు"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 ఉపయోగించని యాప్‌లు"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"ఇటీవలి అనుమతి నిర్ణయాలు"</string>
@@ -196,7 +198,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"ఖచ్చితమైన లొకేషన్‌ను ఉపయోగించండి"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"ఖచ్చితమైన లొకేషన్ అనే సెట్టింగ్ ఆఫ్‌లో ఉన్నప్పుడు, యాప్‌లు మీ సుమారు లొకేషన్‌ను యాక్సెస్ చేయగలవు"</string>
<string name="app_permission_title" msgid="2090897901051370711">"\'<xliff:g id="PERM">%1$s</xliff:g>\' అనుమతి"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"ఈ యాప్ కోసం \'<xliff:g id="PERM">%1$s</xliff:g>\' యాక్సెస్"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"ఈ యాప్ కోసం \'<xliff:g id="PERM">%1$s</xliff:g>\' యాక్సెస్‌ను ఇవ్వాలా? వద్దా"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"అన్ని \'<xliff:g id="APP">%1$s</xliff:g>\' అనుమతులను చూడండి"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ఈ అనుమతి ఉన్న అన్ని యాప్‌లను చూడండి"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"అసిస్టెంట్ మైక్రోఫోన్ వినియోగాన్ని చూపు"</string>
diff --git a/PermissionController/res/values-th/strings.xml b/PermissionController/res/values-th/strings.xml
index c6b80ea1f..ddbcbba68 100644
--- a/PermissionController/res/values-th/strings.xml
+++ b/PermissionController/res/values-th/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"แอป"</string>
<string name="app_permissions" msgid="3369917736607944781">"สิทธิ์ของแอป"</string>
<string name="unused_apps" msgid="2058057455175955094">"แอปที่ไม่ได้ใช้"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"ไม่มีแอปที่ไม่ได้ใช้งาน"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"แอปที่ไม่ได้ใช้ 0 รายการ"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"สิทธิ์ที่กำหนดไว้ล่าสุด"</string>
diff --git a/PermissionController/res/values-tl/strings.xml b/PermissionController/res/values-tl/strings.xml
index b4038fca0..0608930cb 100644
--- a/PermissionController/res/values-tl/strings.xml
+++ b/PermissionController/res/values-tl/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Mga App"</string>
<string name="app_permissions" msgid="3369917736607944781">"Mga pahintulot sa app"</string>
<string name="unused_apps" msgid="2058057455175955094">"Mga hindi ginagamit na app"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Walang hindi ginagamit na app"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 hindi ginagamit na app"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Mga recent permission decision"</string>
@@ -196,7 +198,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Gamitin ang eksaktong lokasyon"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Kapag naka-off ang eksaktong lokasyon, puwedeng i-access ng mga app ang iyong tinatantyang lokasyon"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Pahintulot sa <xliff:g id="PERM">%1$s</xliff:g>"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"access sa <xliff:g id="PERM">%1$s</xliff:g> para sa app na ito"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Access sa <xliff:g id="PERM">%1$s</xliff:g> para sa app na ito"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Tingnan ang lahat ng pahintulot ng <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Tingnan ang lahat ng app na may ganitong pahintulot"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Ipakita ang paggamit ng mikropono ng assistant"</string>
@@ -462,7 +464,7 @@
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Posibleng gustong i-access ng app na ito ang iyong lokasyon sa lahat ng oras, kahit na hindi mo ginagamit ang app. "<annotation id="link">"Payagan sa mga setting."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Baguhin ang access sa lokasyon para sa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Gustong i-access ng app na ito ang iyong lokasyon sa lahat ng oras, kahit na hindi mo ginagamit ang app. "<annotation id="link">"Payagan sa mga setting."</annotation></string>
- <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na hanapin at tukuyin ang, at kumonekta sa relatibong posisyon ng mga kalapit na device?"</string>
+ <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na maghanap, kumonekta sa, at tukuyin ang relatibong posisyon ng mga kalapit na device?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na hanapin at tukuyin ang, at kumonekta sa relatibong posisyon ng mga kalapit na device? "<annotation id="link">"Payagan sa mga setting."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Gawing eksakto ang access sa lokasyon ng <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> mula sa pagiging tinatantya?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang tinatantyang lokasyon ng device na ito?"</string>
diff --git a/PermissionController/res/values-tr/strings.xml b/PermissionController/res/values-tr/strings.xml
index 9bda44775..44a6e6005 100644
--- a/PermissionController/res/values-tr/strings.xml
+++ b/PermissionController/res/values-tr/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Uygulamalar"</string>
<string name="app_permissions" msgid="3369917736607944781">"Uygulama izinleri"</string>
<string name="unused_apps" msgid="2058057455175955094">"Kullanılmayan uygulamalar"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Kullanılmayan uygulama yok"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Kullanılmayan 0 uygulama"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Son izin kararları"</string>
diff --git a/PermissionController/res/values-uk/strings.xml b/PermissionController/res/values-uk/strings.xml
index 6402b7dd1..69299093f 100644
--- a/PermissionController/res/values-uk/strings.xml
+++ b/PermissionController/res/values-uk/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Додатки"</string>
<string name="app_permissions" msgid="3369917736607944781">"Дозволи додатка"</string>
<string name="unused_apps" msgid="2058057455175955094">"Непотрібні додатки"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Усі додатки використовуються"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 додатків не використовуються"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Останні рішення щодо дозволів"</string>
@@ -513,7 +515,7 @@
<string name="privdash_label_24h" msgid="1512532123865375319">"Минулі\n24 години"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"Останні\n7 днів"</string>
<string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> захищено системою Android. Оскільки ваші дані обробляються на цьому пристрої, дозволи, які використовує цей додаток, не відображаються на панелі керування дозволами чи в рядку стану."</string>
- <string name="exempt_info_label" msgid="6286190981253476699">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> захищено системою Android. Оскільки ваші дані обробляються на цьому пристрої, дозволи, які використовує цей додаток, не відображаються на панелі керування дозволами чи в рядку стану."</string>
+ <string name="exempt_info_label" msgid="6286190981253476699">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> захищено системою Android. Оскільки ваші дані обробляються на цьому пристрої, дозволи, які використовує цей додаток, не відображаються на панелі керування дозволами."</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"Камеру пристрою заблоковано"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"Мікрофон пристрою заблоковано"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"Геодані пристрою вимкнено"</string>
diff --git a/PermissionController/res/values-ur/strings.xml b/PermissionController/res/values-ur/strings.xml
index 4cb926518..d442e0071 100644
--- a/PermissionController/res/values-ur/strings.xml
+++ b/PermissionController/res/values-ur/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"ایپس"</string>
<string name="app_permissions" msgid="3369917736607944781">"ایپ کی اجازتیں"</string>
<string name="unused_apps" msgid="2058057455175955094">"غیر مستعمل ایپس"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"کوئی غیر مستعمل ایپ نہیں ہے"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 غیر مستعمل ایپس"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"اجازت کے حالیہ فیصلے"</string>
diff --git a/PermissionController/res/values-uz/strings.xml b/PermissionController/res/values-uz/strings.xml
index 356df948e..ef7a72501 100644
--- a/PermissionController/res/values-uz/strings.xml
+++ b/PermissionController/res/values-uz/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Ilovalar"</string>
<string name="app_permissions" msgid="3369917736607944781">"Ilovalar uchun ruxsatlar"</string>
<string name="unused_apps" msgid="2058057455175955094">"Ishlatilmagan ilovalar"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Ishlatilmagan ilovalar yoʻq"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 ta ishlatilmagan ilova"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Yaqinda tekshirilgan ruxsatlar"</string>
diff --git a/PermissionController/res/values-v31/styles.xml b/PermissionController/res/values-v31/styles.xml
index 3b42a6e5b..e2f6378f5 100644
--- a/PermissionController/res/values-v31/styles.xml
+++ b/PermissionController/res/values-v31/styles.xml
@@ -105,7 +105,7 @@
<style name="AppPermissionRadioButton"
parent="@android:style/Widget.DeviceDefault.CompoundButton.RadioButton">
- <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:paddingStart">?android:attr/listPreferredItemPaddingStart</item>
diff --git a/PermissionController/res/values-v33/styles.xml b/PermissionController/res/values-v33/styles.xml
index 6b726fdb7..e4d8f5c54 100644
--- a/PermissionController/res/values-v33/styles.xml
+++ b/PermissionController/res/values-v33/styles.xml
@@ -793,12 +793,6 @@
<item name="android:layout_height">24dp</item>
</style>
- <style name="SafetyCenterNoLabelPreferenceCategory"
- parent="android:Widget.DeviceDefault">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">16dp</item>
- </style>
-
<style name="SafetyCenterGroupEntry"
parent="android:Widget.DeviceDefault">
<item name="android:layout_width">match_parent</item>
diff --git a/PermissionController/res/values-vi/strings.xml b/PermissionController/res/values-vi/strings.xml
index 3fa50ca58..99f500978 100644
--- a/PermissionController/res/values-vi/strings.xml
+++ b/PermissionController/res/values-vi/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Ứng dụng"</string>
<string name="app_permissions" msgid="3369917736607944781">"Quyền ứng dụng"</string>
<string name="unused_apps" msgid="2058057455175955094">"Ứng dụng không dùng đến"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Không có ứng dụng không dùng đến"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0 ứng dụng không dùng đến"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Quyết định cấp quyền gần đây"</string>
diff --git a/PermissionController/res/values-zh-rCN/strings.xml b/PermissionController/res/values-zh-rCN/strings.xml
index 46a66b59e..998313e89 100644
--- a/PermissionController/res/values-zh-rCN/strings.xml
+++ b/PermissionController/res/values-zh-rCN/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"应用"</string>
<string name="app_permissions" msgid="3369917736607944781">"应用权限"</string>
<string name="unused_apps" msgid="2058057455175955094">"闲置应用"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"无闲置应用"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"没有未使用的应用"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"最近的权限决定"</string>
@@ -513,7 +515,7 @@
<string name="privdash_label_24h" msgid="1512532123865375319">"过去 24 小时\n"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"过去\n7 天"</string>
<string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”受 Android 保护。由于您的数据是在此设备上处理,因此状态栏或隐私信息中心不会显示这个应用的权限使用情况。"</string>
- <string name="exempt_info_label" msgid="6286190981253476699">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”受 Android 保护。由于您的数据是在此设备上处理,因此隐私信息中心不会显示这个应用的权限使用情况。"</string>
+ <string name="exempt_info_label" msgid="6286190981253476699">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”受 Android 保护。由于您的数据是在此设备上处理的,因此隐私信息中心不会显示该应用的权限使用情况。"</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"设备摄像头已被屏蔽"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"设备麦克风已被屏蔽"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"设备位置信息功能已关闭"</string>
@@ -586,7 +588,7 @@
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"系统会在应用访问您复制的文字、图片或其他内容时显示一条消息"</string>
<string name="show_password_title" msgid="2877269286984684659">"显示密码"</string>
<string name="show_password_summary" msgid="1110166488865981610">"输入时短暂显示字符"</string>
- <string name="permission_rationale_message_location" msgid="2153841534298068414">"此应用已声明它可能会与第三方共享位置数据"</string>
+ <string name="permission_rationale_message_location" msgid="2153841534298068414">"此应用已声明它可能会与第三方分享位置数据"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"数据分享和位置信息"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"数据分享信息的来源"</string>
<string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"开发者已将此应用的数据分享方式相关信息提供给此设备的制造商。开发者可能会随时间推移更新此信息。"</string>
diff --git a/PermissionController/res/values-zh-rHK-v34/strings.xml b/PermissionController/res/values-zh-rHK-v34/strings.xml
index 99e078541..65ad05bdb 100644
--- a/PermissionController/res/values-zh-rHK-v34/strings.xml
+++ b/PermissionController/res/values-zh-rHK-v34/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="security_privacy_brand_name" msgid="7303621734258440812">"安全性和私隱權"</string>
+ <string name="security_privacy_brand_name" msgid="7303621734258440812">"保安和私隱"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"控制項"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
<string name="health_connect_summary" msgid="815473513776882296">"管理應用程式的健康資料存取權"</string>
diff --git a/PermissionController/res/values-zh-rHK/strings.xml b/PermissionController/res/values-zh-rHK/strings.xml
index 21bb30b35..1036151b4 100644
--- a/PermissionController/res/values-zh-rHK/strings.xml
+++ b/PermissionController/res/values-zh-rHK/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"應用程式"</string>
<string name="app_permissions" msgid="3369917736607944781">"應用程式權限"</string>
<string name="unused_apps" msgid="2058057455175955094">"不使用的應用程式"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"沒有不使用的應用程式"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"沒有未使用的應用程式"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"最近的權限決定"</string>
@@ -520,7 +522,7 @@
<string name="blocked_sensor_summary" msgid="4443707628305027375">"應用程式和服務"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"撥打緊急電話號碼時,系統仍可能會分享麥克風資料。"</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"變更"</string>
- <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"安全性和私隱權"</string>
+ <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"保安和私隱"</string>
<string name="safety_center_rescan_button" msgid="4517514567809409596">"掃瞄裝置"</string>
<string name="safety_center_issue_card_dismiss_button" msgid="5113965506144222402">"關閉"</string>
<string name="safety_center_issue_card_dismiss_confirmation_title" msgid="2734809473425036382">"要關閉此警示嗎?"</string>
@@ -531,7 +533,7 @@
<string name="safety_status_preference_title_and_summary_content_description" msgid="3511373256505058464">"安全性和私隱狀態。<xliff:g id="OVERALL_SAFETY_STATUS">%1$s</xliff:g>。<xliff:g id="SUMMARY_OF_DEVICE_STATUS">%2$s</xliff:g>"</string>
<string name="security_settings" msgid="3808106921175271317">"安全性設定"</string>
<string name="sensor_permissions_qs" msgid="1022267900031317472">"權限"</string>
- <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"安全性和私隱權"</string>
+ <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"保安和私隱"</string>
<string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"檢查狀態"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"你的私隱權設定"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"更多設定"</string>
diff --git a/PermissionController/res/values-zh-rTW/strings.xml b/PermissionController/res/values-zh-rTW/strings.xml
index 2eea326cc..533bd013e 100644
--- a/PermissionController/res/values-zh-rTW/strings.xml
+++ b/PermissionController/res/values-zh-rTW/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"應用程式"</string>
<string name="app_permissions" msgid="3369917736607944781">"應用程式權限"</string>
<string name="unused_apps" msgid="2058057455175955094">"未使用的應用程式"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"沒有未使用的應用程式"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"沒有未使用的應用程式"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"最近的權限決定"</string>
@@ -474,7 +476,7 @@
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置上的&lt;b&gt;相片、影片、音樂和音訊&lt;/b&gt;嗎?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置上的&lt;b&gt;相片、影片、音樂、音訊和其他檔案&lt;/b&gt;嗎?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置上的音樂和音訊嗎?"</string>
- <string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置上的相片和影片嗎?"</string>
+ <string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置上的相片和影片嗎?"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置上的其他相片和影片嗎?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」錄音嗎?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"這個應用程式只有在你使用時才能錄音"</string>
diff --git a/PermissionController/res/values-zu/strings.xml b/PermissionController/res/values-zu/strings.xml
index d1abf785d..617eda15a 100644
--- a/PermissionController/res/values-zu/strings.xml
+++ b/PermissionController/res/values-zu/strings.xml
@@ -60,6 +60,8 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Izinhlelo zokusebenza"</string>
<string name="app_permissions" msgid="3369917736607944781">"Izimvume zohlelo lokusebenza"</string>
<string name="unused_apps" msgid="2058057455175955094">"Izinhlelo zokusebenza ezingasetshenzisiwe"</string>
+ <!-- no translation found for edit_photos_description (5540108003480078892) -->
+ <skip />
<string name="no_unused_apps" msgid="12809387670415295">"Awekho ama-app angasetshenzisiwe"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Ama-app angasetshenzisiwe angu-0"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Izinqumo zemvume yakamuva"</string>
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index 08d1b6b2d..8f56046e2 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -164,6 +164,9 @@
<!-- Title for the page of manage unused apps [CHAR LIMIT=30] -->
<string name="unused_apps">Unused apps</string>
+ <!-- Description for the button that lets users change which photos an app has access to [CHAR LIMIT=none] -->
+ <string name="edit_photos_description">Edit selected photos for this app</string>
+
<!-- Label when there are no unused apps [CHAR LIMIT=30] -->
<string name="no_unused_apps">No unused apps</string>
diff --git a/PermissionController/res/xml/safety_center_dashboard.xml b/PermissionController/res/xml/safety_center_dashboard.xml
index 216ef318e..e3951ca83 100644
--- a/PermissionController/res/xml/safety_center_dashboard.xml
+++ b/PermissionController/res/xml/safety_center_dashboard.xml
@@ -29,6 +29,11 @@
android:layout="@layout/preference_category_no_label"
app:selectable="false" />
+ <!-- TODO: b/291574390 - Move this to the issue drawer or status card view instead of having a
+ separate preference just for this margin/padding -->
+ <com.android.permissioncontroller.safetycenter.ui.EntriesTopPaddingPreference
+ android:key="entries_top_padding" />
+
<com.android.permissioncontroller.safetycenter.ui.ComparablePreferenceCategory
android:key="entries_group"
android:title="@string/safety_center_entries_category_title"
@@ -36,7 +41,7 @@
<com.android.permissioncontroller.safetycenter.ui.ComparablePreferenceCategory
android:key="static_entries_group"
- android:layout="@layout/spaced_preference_category_no_label"
+ android:layout="@layout/preference_category_no_label"
app:selectable="false" />
<com.android.permissioncontroller.safetycenter.ui.SpacerPreference
diff --git a/PermissionController/src/com/android/permissioncontroller/DumpableLog.kt b/PermissionController/src/com/android/permissioncontroller/DumpableLog.kt
index bbce5bf5c..56682d018 100644
--- a/PermissionController/src/com/android/permissioncontroller/DumpableLog.kt
+++ b/PermissionController/src/com/android/permissioncontroller/DumpableLog.kt
@@ -20,9 +20,7 @@ import android.util.Log
import com.android.permissioncontroller.Constants.LOGS_TO_DUMP_FILE
import java.io.File
-/**
- * Like {@link Log} but stores the logs in a file which can later be dumped via {@link #dump}
- */
+/** Like {@link Log} but stores the logs in a file which can later be dumped via {@link #dump} */
object DumpableLog {
private const val MAX_FILE_SIZE = 64 * 1024
@@ -33,41 +31,31 @@ object DumpableLog {
file.createNewFile()
}
- /**
- * Equivalent to {@link Log.v}
- */
+ /** Equivalent to {@link Log.v} */
fun v(tag: String, message: String, exception: Throwable? = null) {
Log.v(tag, message, exception)
addLogToDump("v", tag, message, exception)
}
- /**
- * Equivalent to {@link Log.d}
- */
+ /** Equivalent to {@link Log.d} */
fun d(tag: String, message: String, exception: Throwable? = null) {
Log.d(tag, message, exception)
addLogToDump("d", tag, message, exception)
}
- /**
- * Equivalent to {@link Log.i}
- */
+ /** Equivalent to {@link Log.i} */
fun i(tag: String, message: String, exception: Throwable? = null) {
Log.i(tag, message, exception)
addLogToDump("i", tag, message, exception)
}
- /**
- * Equivalent to {@link Log.w}
- */
+ /** Equivalent to {@link Log.w} */
fun w(tag: String, message: String, exception: Throwable? = null) {
Log.w(tag, message, exception)
addLogToDump("w", tag, message, exception)
}
- /**
- * Equivalent to {@link Log.e}
- */
+ /** Equivalent to {@link Log.e} */
fun e(tag: String, message: String, exception: Throwable? = null) {
Log.e(tag, message, exception)
addLogToDump("e", tag, message, exception)
@@ -83,17 +71,17 @@ object DumpableLog {
dump.subList(dump.size / 2, dump.size).forEach { file.appendText(it + "\n") }
}
- file.appendText("${System.currentTimeMillis()} $tag:$level $message " +
- "${exception?.let { it.message + Log.getStackTraceString(it) } ?: ""}\n")
+ file.appendText(
+ "${System.currentTimeMillis()} $tag:$level $message " +
+ "${exception?.let { it.message + Log.getStackTraceString(it) } ?: ""}\n"
+ )
}
}
- /**
- * @return the previously logged entries
- */
+ /** @return the previously logged entries */
suspend fun get(): List<String> {
synchronized(lock) {
return file.readLines()
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt b/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
index b62f8d721..b2cf75fed 100644
--- a/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
@@ -55,9 +55,7 @@ import java.util.Random
*/
class DrivingDecisionReminderService : Service() {
- /**
- * Information needed to show a reminder about a permission decisions.
- */
+ /** Information needed to show a reminder about a permission decisions. */
data class PermissionReminder(
val packageName: String,
val permissionGroup: String,
@@ -109,22 +107,26 @@ class DrivingDecisionReminderService : Service() {
packageName: String,
permGroupName: String
) {
- Car.createCar(
- context,
- /* handler= */ null,
- Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT) { car: Car, ready: Boolean ->
+ Car.createCar(context, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT) {
+ car: Car,
+ ready: Boolean ->
// just give up if we can't connect to the car
if (ready) {
- val restrictionsManager = car.getCarManager(
- Car.CAR_UX_RESTRICTION_SERVICE) as CarUxRestrictionsManager
- if (restrictionsManager.currentCarUxRestrictions
- .isRequiresDistractionOptimization) {
+ val restrictionsManager =
+ car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE)
+ as CarUxRestrictionsManager
+ if (
+ restrictionsManager.currentCarUxRestrictions
+ .isRequiresDistractionOptimization
+ ) {
context.startService(
createIntent(
context,
packageName,
permGroupName,
- Process.myUserHandle()))
+ Process.myUserHandle()
+ )
+ )
}
}
car.disconnect()
@@ -156,28 +158,32 @@ class DrivingDecisionReminderService : Service() {
}
private fun scheduleNotificationForUnrestrictedState() {
- Car.createCar(this, null,
- Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT
- ) { createdCar: Car?, ready: Boolean ->
+ Car.createCar(this, null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT) {
+ createdCar: Car?,
+ ready: Boolean ->
car = createdCar
if (ready) {
onCarReady()
} else {
- DumpableLog.w(LOG_TAG,
- "Car service disconnected, no notification will be scheduled")
+ DumpableLog.w(
+ LOG_TAG,
+ "Car service disconnected, no notification will be scheduled"
+ )
stopSelf()
}
}
}
private fun onCarReady() {
- carUxRestrictionsManager = car?.getCarManager(
- Car.CAR_UX_RESTRICTION_SERVICE) as CarUxRestrictionsManager
+ carUxRestrictionsManager =
+ car?.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE) as CarUxRestrictionsManager
DumpableLog.d(LOG_TAG, "Registering UX restriction listener")
carUxRestrictionsManager?.registerListener { restrictions ->
if (!restrictions.isRequiresDistractionOptimization) {
- DumpableLog.d(LOG_TAG,
- "UX restrictions no longer required - showing reminder notification")
+ DumpableLog.d(
+ LOG_TAG,
+ "UX restrictions no longer required - showing reminder notification"
+ )
showRecentGrantDecisionsPostDriveNotification()
stopSelf()
}
@@ -185,10 +191,12 @@ class DrivingDecisionReminderService : Service() {
}
private fun parseStartIntent(intent: Intent?): PermissionReminder? {
- if (intent == null ||
- !intent.hasExtra(EXTRA_PACKAGE_NAME) ||
- !intent.hasExtra(EXTRA_PERMISSION_GROUP) ||
- !intent.hasExtra(EXTRA_USER)) {
+ if (
+ intent == null ||
+ !intent.hasExtra(EXTRA_PACKAGE_NAME) ||
+ !intent.hasExtra(EXTRA_PERMISSION_GROUP) ||
+ !intent.hasExtra(EXTRA_USER)
+ ) {
DumpableLog.e(LOG_TAG, "Missing extras from intent $intent")
return null
}
@@ -202,21 +210,25 @@ class DrivingDecisionReminderService : Service() {
fun showRecentGrantDecisionsPostDriveNotification() {
val notificationManager = getSystemService(NotificationManager::class.java)!!
- val permissionReminderChannel = NotificationChannel(
- Constants.PERMISSION_REMINDER_CHANNEL_ID, getString(R.string.permission_reminders),
- NotificationManager.IMPORTANCE_HIGH)
+ val permissionReminderChannel =
+ NotificationChannel(
+ Constants.PERMISSION_REMINDER_CHANNEL_ID,
+ getString(R.string.permission_reminders),
+ NotificationManager.IMPORTANCE_HIGH
+ )
notificationManager.createNotificationChannel(permissionReminderChannel)
- notificationManager.notify(DrivingDecisionReminderService::class.java.simpleName,
+ notificationManager.notify(
+ DrivingDecisionReminderService::class.java.simpleName,
Constants.PERMISSION_DECISION_REMINDER_NOTIFICATION_ID,
- createNotification(createNotificationTitle(), createNotificationContent()))
+ createNotification(createNotificationTitle(), createNotificationContent())
+ )
logNotificationPresented()
}
private fun createNotificationTitle(): String {
- return applicationContext
- .getString(R.string.post_drive_permission_decision_reminder_title)
+ return applicationContext.getString(R.string.post_drive_permission_decision_reminder_title)
}
@VisibleForTesting
@@ -224,76 +236,106 @@ class DrivingDecisionReminderService : Service() {
val packageLabels: MutableList<String> = mutableListOf()
val permissionGroupNames: MutableList<String> = mutableListOf()
for (permissionReminder in permissionReminders) {
- val packageLabel = getLabelForPackage(permissionReminder.packageName,
- permissionReminder.user)
- val permissionGroupLabel = getPermGroupLabel(applicationContext,
- permissionReminder.permissionGroup).toString()
+ val packageLabel =
+ getLabelForPackage(permissionReminder.packageName, permissionReminder.user)
+ val permissionGroupLabel =
+ getPermGroupLabel(applicationContext, permissionReminder.permissionGroup).toString()
packageLabels.add(packageLabel)
permissionGroupNames.add(permissionGroupLabel)
}
val packageLabelsDistinct = packageLabels.distinct()
val permissionGroupNamesDistinct = permissionGroupNames.distinct()
return if (packageLabelsDistinct.size > 1) {
- StringUtils.getIcuPluralsString(applicationContext,
+ StringUtils.getIcuPluralsString(
+ applicationContext,
R.string.post_drive_permission_decision_reminder_summary_multi_apps,
- (packageLabels.size - 1), packageLabelsDistinct[0])
+ (packageLabels.size - 1),
+ packageLabelsDistinct[0]
+ )
} else if (permissionGroupNamesDistinct.size == 2) {
getString(
R.string.post_drive_permission_decision_reminder_summary_1_app_2_permissions,
- packageLabelsDistinct[0], permissionGroupNamesDistinct[0],
- permissionGroupNamesDistinct[1])
+ packageLabelsDistinct[0],
+ permissionGroupNamesDistinct[0],
+ permissionGroupNamesDistinct[1]
+ )
} else if (permissionGroupNamesDistinct.size > 2) {
getString(
R.string.post_drive_permission_decision_reminder_summary_1_app_multi_permission,
- permissionGroupNamesDistinct.size, packageLabelsDistinct[0])
+ permissionGroupNamesDistinct.size,
+ packageLabelsDistinct[0]
+ )
} else {
getString(
R.string.post_drive_permission_decision_reminder_summary_1_app_1_permission,
- packageLabelsDistinct[0], permissionGroupNamesDistinct[0])
+ packageLabelsDistinct[0],
+ permissionGroupNamesDistinct[0]
+ )
}
}
@VisibleForTesting
fun getLabelForPackage(packageName: String, user: UserHandle): String {
- return BidiFormatter.getInstance().unicodeWrap(
- getPackageLabel(application, packageName, user))
+ return BidiFormatter.getInstance()
+ .unicodeWrap(getPackageLabel(application, packageName, user))
}
private fun createNotification(title: String, body: String): Notification {
- val clickIntent = Intent(PermissionManager.ACTION_REVIEW_PERMISSION_DECISIONS).apply {
- putExtra(Constants.EXTRA_SESSION_ID, sessionId)
- putExtra(AutoReviewPermissionDecisionsFragment.EXTRA_SOURCE,
- AutoReviewPermissionDecisionsFragment.EXTRA_SOURCE_NOTIFICATION)
- flags = Intent.FLAG_ACTIVITY_NEW_TASK
- }
- val pendingIntent = PendingIntent.getActivity(this, 0, clickIntent,
- PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_UPDATE_CURRENT or
- PendingIntent.FLAG_IMMUTABLE)
+ val clickIntent =
+ Intent(PermissionManager.ACTION_REVIEW_PERMISSION_DECISIONS).apply {
+ putExtra(Constants.EXTRA_SESSION_ID, sessionId)
+ putExtra(
+ AutoReviewPermissionDecisionsFragment.EXTRA_SOURCE,
+ AutoReviewPermissionDecisionsFragment.EXTRA_SOURCE_NOTIFICATION
+ )
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ }
+ val pendingIntent =
+ PendingIntent.getActivity(
+ this,
+ 0,
+ clickIntent,
+ PendingIntent.FLAG_ONE_SHOT or
+ PendingIntent.FLAG_UPDATE_CURRENT or
+ PendingIntent.FLAG_IMMUTABLE
+ )
- val settingsDrawable = KotlinUtils.getBadgedPackageIcon(
- application,
- getSettingsPackageName(applicationContext.packageManager),
- permissionReminders.first().user)
- val settingsIcon = if (settingsDrawable != null) {
- KotlinUtils.convertToBitmap(settingsDrawable)
- } else {
- null
- }
+ val settingsDrawable =
+ KotlinUtils.getBadgedPackageIcon(
+ application,
+ getSettingsPackageName(applicationContext.packageManager),
+ permissionReminders.first().user
+ )
+ val settingsIcon =
+ if (settingsDrawable != null) {
+ KotlinUtils.convertToBitmap(settingsDrawable)
+ } else {
+ null
+ }
- val b = Notification.Builder(this, Constants.PERMISSION_REMINDER_CHANNEL_ID)
- .setContentTitle(title)
- .setContentText(body)
- .setSmallIcon(R.drawable.ic_settings_24dp)
- .setLargeIcon(settingsIcon)
- .setColor(getColor(android.R.color.system_notification_accent_color))
- .setAutoCancel(true)
- .setContentIntent(pendingIntent)
- .addExtras(Bundle().apply {
- putBoolean("com.android.car.notification.EXTRA_USE_LAUNCHER_ICON", false)
- })
- // Auto doesn't show icons for actions
- .addAction(Notification.Action.Builder(/* icon= */ null,
- getString(R.string.go_to_settings), pendingIntent).build())
+ val b =
+ Notification.Builder(this, Constants.PERMISSION_REMINDER_CHANNEL_ID)
+ .setContentTitle(title)
+ .setContentText(body)
+ .setSmallIcon(R.drawable.ic_settings_24dp)
+ .setLargeIcon(settingsIcon)
+ .setColor(getColor(android.R.color.system_notification_accent_color))
+ .setAutoCancel(true)
+ .setContentIntent(pendingIntent)
+ .addExtras(
+ Bundle().apply {
+ putBoolean("com.android.car.notification.EXTRA_USE_LAUNCHER_ICON", false)
+ }
+ )
+ // Auto doesn't show icons for actions
+ .addAction(
+ Notification.Action.Builder(
+ /* icon= */ null,
+ getString(R.string.go_to_settings),
+ pendingIntent
+ )
+ .build()
+ )
Utils.getSettingsLabelForNotifications(applicationContext.packageManager)?.let { label ->
val extras = Bundle()
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, label.toString())
@@ -311,6 +353,8 @@ class DrivingDecisionReminderService : Service() {
private fun logNotificationPresented() {
PermissionControllerStatsLog.write(
PermissionControllerStatsLog.PERMISSION_REMINDER_NOTIFICATION_INTERACTED,
- sessionId, PERMISSION_REMINDER_NOTIFICATION_INTERACTED__RESULT__NOTIFICATION_PRESENTED)
+ sessionId,
+ PERMISSION_REMINDER_NOTIFICATION_INTERACTED__RESULT__NOTIFICATION_PRESENTED
+ )
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt b/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt
index 6e901fa26..6aa5d0f12 100644
--- a/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt
+++ b/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt
@@ -114,26 +114,31 @@ import kotlinx.coroutines.launch
private const val LOG_TAG = "HibernationPolicy"
const val DEBUG_OVERRIDE_THRESHOLDS = false
-// TODO eugenesusla: temporarily enabled for extra logs during dogfooding
-const val DEBUG_HIBERNATION_POLICY = true || DEBUG_OVERRIDE_THRESHOLDS
+const val DEBUG_HIBERNATION_POLICY = false
private var SKIP_NEXT_RUN = false
private val DEFAULT_UNUSED_THRESHOLD_MS = TimeUnit.DAYS.toMillis(90)
-fun getUnusedThresholdMs() = when {
- DEBUG_OVERRIDE_THRESHOLDS -> TimeUnit.SECONDS.toMillis(1)
- else -> DeviceConfig.getLong(DeviceConfig.NAMESPACE_PERMISSIONS,
- Utils.PROPERTY_HIBERNATION_UNUSED_THRESHOLD_MILLIS,
- DEFAULT_UNUSED_THRESHOLD_MS)
-}
+fun getUnusedThresholdMs() =
+ when {
+ DEBUG_OVERRIDE_THRESHOLDS -> TimeUnit.SECONDS.toMillis(1)
+ else ->
+ DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_PERMISSIONS,
+ Utils.PROPERTY_HIBERNATION_UNUSED_THRESHOLD_MILLIS,
+ DEFAULT_UNUSED_THRESHOLD_MS
+ )
+ }
private val DEFAULT_CHECK_FREQUENCY_MS = TimeUnit.DAYS.toMillis(15)
-private fun getCheckFrequencyMs() = DeviceConfig.getLong(
- DeviceConfig.NAMESPACE_PERMISSIONS,
+private fun getCheckFrequencyMs() =
+ DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_PERMISSIONS,
Utils.PROPERTY_HIBERNATION_CHECK_FREQUENCY_MILLIS,
- DEFAULT_CHECK_FREQUENCY_MS)
+ DEFAULT_CHECK_FREQUENCY_MS
+ )
// Intentionally kept value of the key same as before because we want to continue reading value of
// this shared preference stored by previous versions of PermissionController
@@ -150,8 +155,11 @@ val ONE_DAY_MS = TimeUnit.DAYS.toMillis(1)
fun isHibernationEnabled(): Boolean {
return SdkLevel.isAtLeastS() &&
- DeviceConfig.getBoolean(NAMESPACE_APP_HIBERNATION, Utils.PROPERTY_APP_HIBERNATION_ENABLED,
- true /* defaultValue */)
+ DeviceConfig.getBoolean(
+ NAMESPACE_APP_HIBERNATION,
+ Utils.PROPERTY_APP_HIBERNATION_ENABLED,
+ true /* defaultValue */
+ )
}
/**
@@ -159,30 +167,33 @@ fun isHibernationEnabled(): Boolean {
* [isHibernationEnabled] is false.
*/
fun hibernationTargetsPreSApps(): Boolean {
- return DeviceConfig.getBoolean(NAMESPACE_APP_HIBERNATION,
+ return DeviceConfig.getBoolean(
+ NAMESPACE_APP_HIBERNATION,
Utils.PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS,
- false /* defaultValue */)
+ false /* defaultValue */
+ )
}
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
fun isSystemExemptFromHibernationEnabled(): Boolean {
- return SdkLevel.isAtLeastU() && DeviceConfig.getBoolean(NAMESPACE_APP_HIBERNATION,
+ return SdkLevel.isAtLeastU() &&
+ DeviceConfig.getBoolean(
+ NAMESPACE_APP_HIBERNATION,
Utils.PROPERTY_SYSTEM_EXEMPT_HIBERNATION_ENABLED,
- true /* defaultValue */)
+ true /* defaultValue */
+ )
}
-/**
- * Remove the unused apps notification.
- */
+/** Remove the unused apps notification. */
fun cancelUnusedAppsNotification(context: Context) {
- context.getSystemService(NotificationManager::class.java)!!.cancel(
- HibernationJobService::class.java.simpleName,
- Constants.UNUSED_APPS_NOTIFICATION_ID)
+ context
+ .getSystemService(NotificationManager::class.java)!!
+ .cancel(HibernationJobService::class.java.simpleName, Constants.UNUSED_APPS_NOTIFICATION_ID)
}
/**
- * Checks if we need to show the safety center card and sends the appropriate source data. If
- * the user has not reviewed the latest auto-revoked apps, we show the card. Otherwise, we ensure
+ * Checks if we need to show the safety center card and sends the appropriate source data. If the
+ * user has not reviewed the latest auto-revoked apps, we show the card. Otherwise, we ensure
* nothing is shown.
*/
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@@ -194,36 +205,40 @@ fun rescanAndPushDataToSafetyCenter(
val safetyCenterManager: SafetyCenterManager =
context.getSystemService(SafetyCenterManager::class.java)!!
if (getUnusedAppsReviewNeeded(context)) {
- val seeUnusedAppsAction = Action.Builder(
- Constants.UNUSED_APPS_SAFETY_CENTER_SEE_UNUSED_APPS_ID,
- context.getString(R.string.unused_apps_safety_center_action_title),
- makeUnusedAppsIntent(context, sessionId))
- .build()
-
- val issue = SafetySourceIssue.Builder(
- Constants.UNUSED_APPS_SAFETY_CENTER_ISSUE_ID,
- context.getString(R.string.unused_apps_safety_center_card_title),
- context.getString(R.string.unused_apps_safety_center_card_content),
- SafetySourceData.SEVERITY_LEVEL_INFORMATION,
- Constants.UNUSED_APPS_SAFETY_CENTER_ISSUE_ID)
- .addAction(seeUnusedAppsAction)
- .setOnDismissPendingIntent(makeDismissIntent(context, sessionId))
- .setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DEVICE)
- .build()
-
- val safetySourceData = SafetySourceData.Builder()
- .addIssue(issue)
- .build()
+ val seeUnusedAppsAction =
+ Action.Builder(
+ Constants.UNUSED_APPS_SAFETY_CENTER_SEE_UNUSED_APPS_ID,
+ context.getString(R.string.unused_apps_safety_center_action_title),
+ makeUnusedAppsIntent(context, sessionId)
+ )
+ .build()
+
+ val issue =
+ SafetySourceIssue.Builder(
+ Constants.UNUSED_APPS_SAFETY_CENTER_ISSUE_ID,
+ context.getString(R.string.unused_apps_safety_center_card_title),
+ context.getString(R.string.unused_apps_safety_center_card_content),
+ SafetySourceData.SEVERITY_LEVEL_INFORMATION,
+ Constants.UNUSED_APPS_SAFETY_CENTER_ISSUE_ID
+ )
+ .addAction(seeUnusedAppsAction)
+ .setOnDismissPendingIntent(makeDismissIntent(context, sessionId))
+ .setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DEVICE)
+ .build()
+
+ val safetySourceData = SafetySourceData.Builder().addIssue(issue).build()
safetyCenterManager.setSafetySourceData(
Constants.UNUSED_APPS_SAFETY_CENTER_SOURCE_ID,
safetySourceData,
- safetyEvent)
+ safetyEvent
+ )
} else {
safetyCenterManager.setSafetySourceData(
Constants.UNUSED_APPS_SAFETY_CENTER_SOURCE_ID,
/* safetySourceData= */ null,
- safetyEvent)
+ safetyEvent
+ )
}
}
@@ -232,8 +247,10 @@ fun rescanAndPushDataToSafetyCenter(
*/
fun setUnusedAppsReviewNeeded(context: Context, needsReview: Boolean) {
val sharedPreferences = context.sharedPreferences
- if (sharedPreferences.contains(PREF_KEY_UNUSED_APPS_REVIEW) &&
- sharedPreferences.getBoolean(PREF_KEY_UNUSED_APPS_REVIEW, false) == needsReview) {
+ if (
+ sharedPreferences.contains(PREF_KEY_UNUSED_APPS_REVIEW) &&
+ sharedPreferences.getBoolean(PREF_KEY_UNUSED_APPS_REVIEW, false) == needsReview
+ ) {
return
}
sharedPreferences.edit().putBoolean(PREF_KEY_UNUSED_APPS_REVIEW, needsReview).apply()
@@ -246,10 +263,10 @@ private fun getUnusedAppsReviewNeeded(context: Context): Boolean {
/**
* Receiver of the following broadcasts:
* <ul>
- * <li> {@link Intent.ACTION_BOOT_COMPLETED}
- * <li> {@link #ACTION_SET_UP_HIBERNATION}
- * <li> {@link Intent.ACTION_TIME_CHANGED}
- * <li> {@link Intent.ACTION_TIMEZONE_CHANGED}
+ * <li> {@link Intent.ACTION_BOOT_COMPLETED}
+ * <li> {@link #ACTION_SET_UP_HIBERNATION}
+ * <li> {@link Intent.ACTION_TIME_CHANGED}
+ * <li> {@link Intent.ACTION_TIMEZONE_CHANGED}
* </ul>
*/
class HibernationBroadcastReceiver : BroadcastReceiver() {
@@ -258,9 +275,12 @@ class HibernationBroadcastReceiver : BroadcastReceiver() {
val action = intent.action
if (action == Intent.ACTION_BOOT_COMPLETED || action == ACTION_SET_UP_HIBERNATION) {
if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG, "scheduleHibernationJob " +
- "with frequency ${getCheckFrequencyMs()}ms " +
- "and threshold ${getUnusedThresholdMs()}ms")
+ DumpableLog.i(
+ LOG_TAG,
+ "scheduleHibernationJob " +
+ "with frequency ${getCheckFrequencyMs()}ms " +
+ "and threshold ${getUnusedThresholdMs()}ms"
+ )
}
initStartTimeOfUnusedAppTracking(context.sharedPreferences)
@@ -269,32 +289,40 @@ class HibernationBroadcastReceiver : BroadcastReceiver() {
// primary user
if (isProfile(context)) {
if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG,
- "user ${Process.myUserHandle().identifier} is a profile." +
- " Not running hibernation job.")
+ DumpableLog.i(
+ LOG_TAG,
+ "user ${Process.myUserHandle().identifier} is a profile." +
+ " Not running hibernation job."
+ )
}
return
} else if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG,
- "user ${Process.myUserHandle().identifier} is a profile" +
- "owner. Running hibernation job.")
+ DumpableLog.i(
+ LOG_TAG,
+ "user ${Process.myUserHandle().identifier} is a profile" +
+ "owner. Running hibernation job."
+ )
}
if (isNewJobScheduleRequired(context)) {
// periodic jobs normally run immediately, which is unnecessarily premature
SKIP_NEXT_RUN = true
- val jobInfo = JobInfo.Builder(
- Constants.HIBERNATION_JOB_ID,
- ComponentName(context, HibernationJobService::class.java))
- .setPeriodic(getCheckFrequencyMs())
- // persist this job across boots
- .setPersisted(true)
- .build()
- val status =
- context.getSystemService(JobScheduler::class.java)!!.schedule(jobInfo)
+ val jobInfo =
+ JobInfo.Builder(
+ Constants.HIBERNATION_JOB_ID,
+ ComponentName(context, HibernationJobService::class.java)
+ )
+ .setPeriodic(getCheckFrequencyMs())
+ // persist this job across boots
+ .setPersisted(true)
+ .build()
+ val status = context.getSystemService(JobScheduler::class.java)!!.schedule(jobInfo)
if (status != JobScheduler.RESULT_SUCCESS) {
- DumpableLog.e(LOG_TAG, "Could not schedule " +
- "${HibernationJobService::class.java.simpleName}: $status")
+ DumpableLog.e(
+ LOG_TAG,
+ "Could not schedule " +
+ "${HibernationJobService::class.java.simpleName}: $status"
+ )
}
}
}
@@ -319,8 +347,10 @@ class HibernationBroadcastReceiver : BroadcastReceiver() {
private fun isNewJobScheduleRequired(context: Context): Boolean {
// check if the job is already scheduled or needs a change
var scheduleNewJob = false
- val existingJob: JobInfo? = context.getSystemService(JobScheduler::class.java)!!
- .getPendingJob(Constants.HIBERNATION_JOB_ID)
+ val existingJob: JobInfo? =
+ context
+ .getSystemService(JobScheduler::class.java)!!
+ .getPendingJob(Constants.HIBERNATION_JOB_ID)
if (existingJob == null) {
if (DEBUG_HIBERNATION_POLICY) {
DumpableLog.i(LOG_TAG, "No existing job, scheduling a new one")
@@ -351,19 +381,24 @@ private suspend fun getAppsToHibernate(
val startTimeOfUnusedAppTracking = getStartTimeOfUnusedAppTracking(context.sharedPreferences)
val allPackagesByUser = AllPackageInfosLiveData.getInitializedValue(forceUpdate = true)
- val allPackagesByUserByUid = allPackagesByUser.mapValues { (_, pkgs) ->
- pkgs.groupBy { pkg -> pkg.uid }
- }
+ val allPackagesByUserByUid =
+ allPackagesByUser.mapValues { (_, pkgs) -> pkgs.groupBy { pkg -> pkg.uid } }
val unusedApps = allPackagesByUser.toMutableMap()
- val userStats = UsageStatsLiveData[getUnusedThresholdMs(),
- if (DEBUG_OVERRIDE_THRESHOLDS) INTERVAL_DAILY else INTERVAL_MONTHLY].getInitializedValue()
+ val userStats =
+ UsageStatsLiveData[
+ getUnusedThresholdMs(),
+ if (DEBUG_OVERRIDE_THRESHOLDS) INTERVAL_DAILY else INTERVAL_MONTHLY]
+ .getInitializedValue()
if (DEBUG_HIBERNATION_POLICY) {
for ((user, stats) in userStats) {
- DumpableLog.i(LOG_TAG, "Usage stats for user ${user.identifier}: " +
- stats.map { stat ->
- stat.packageName to Date(stat.lastTimePackageUsed())
- }.toMap())
+ DumpableLog.i(
+ LOG_TAG,
+ "Usage stats for user ${user.identifier}: " +
+ stats
+ .map { stat -> stat.packageName to Date(stat.lastTimePackageUsed()) }
+ .toMap()
+ )
}
}
for (user in unusedApps.keys.toList()) {
@@ -378,42 +413,52 @@ private suspend fun getAppsToHibernate(
for ((user, stats) in userStats) {
var unusedUserApps = unusedApps[user] ?: continue
- unusedUserApps = unusedUserApps.filter { packageInfo ->
- val pkgName = packageInfo.packageName
-
- val uidPackages = allPackagesByUserByUid[user]!![packageInfo.uid]
- ?.map { info -> info.packageName } ?: emptyList()
- if (pkgName !in uidPackages) {
- Log.wtf(LOG_TAG, "Package $pkgName not among packages for " +
- "its uid ${packageInfo.uid}: $uidPackages")
- }
- var lastTimePkgUsed: Long = stats.lastTimePackageUsed(uidPackages)
-
- // Limit by install time
- lastTimePkgUsed = Math.max(lastTimePkgUsed, packageInfo.firstInstallTime)
-
- // Limit by first boot time
- lastTimePkgUsed = Math.max(lastTimePkgUsed, startTimeOfUnusedAppTracking)
+ unusedUserApps =
+ unusedUserApps.filter { packageInfo ->
+ val pkgName = packageInfo.packageName
- // Handle cross-profile apps
- if (context.isPackageCrossProfile(pkgName)) {
- for ((otherUser, otherStats) in userStats) {
- if (otherUser == user) {
- continue
+ val uidPackages =
+ allPackagesByUserByUid[user]!![packageInfo.uid]?.map { info ->
+ info.packageName
+ }
+ ?: emptyList()
+ if (pkgName !in uidPackages) {
+ Log.wtf(
+ LOG_TAG,
+ "Package $pkgName not among packages for " +
+ "its uid ${packageInfo.uid}: $uidPackages"
+ )
+ }
+ var lastTimePkgUsed: Long = stats.lastTimePackageUsed(uidPackages)
+
+ // Limit by install time
+ lastTimePkgUsed = Math.max(lastTimePkgUsed, packageInfo.firstInstallTime)
+
+ // Limit by first boot time
+ lastTimePkgUsed = Math.max(lastTimePkgUsed, startTimeOfUnusedAppTracking)
+
+ // Handle cross-profile apps
+ if (context.isPackageCrossProfile(pkgName)) {
+ for ((otherUser, otherStats) in userStats) {
+ if (otherUser == user) {
+ continue
+ }
+ lastTimePkgUsed =
+ maxOf(lastTimePkgUsed, otherStats.lastTimePackageUsed(pkgName))
}
- lastTimePkgUsed =
- maxOf(lastTimePkgUsed, otherStats.lastTimePackageUsed(pkgName))
}
- }
- // Threshold check - whether app is unused
- now - lastTimePkgUsed > getUnusedThresholdMs()
- }
+ // Threshold check - whether app is unused
+ now - lastTimePkgUsed > getUnusedThresholdMs()
+ }
unusedApps[user] = unusedUserApps
if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG, "Unused apps for user ${user.identifier}: " +
- "${unusedUserApps.map { it.packageName }}")
+ DumpableLog.i(
+ LOG_TAG,
+ "Unused apps for user ${user.identifier}: " +
+ "${unusedUserApps.map { it.packageName }}"
+ )
}
}
@@ -435,25 +480,29 @@ private suspend fun getAppsToHibernate(
}
val packageName = pkg.packageName
- val packageImportance = context
- .getSystemService(ActivityManager::class.java)!!
- .getPackageImportance(packageName)
+ val packageImportance =
+ context
+ .getSystemService(ActivityManager::class.java)!!
+ .getPackageImportance(packageName)
if (packageImportance <= IMPORTANCE_CANT_SAVE_STATE) {
// Process is running in a state where it should not be killed
- DumpableLog.i(LOG_TAG,
+ DumpableLog.i(
+ LOG_TAG,
"Skipping hibernation - $packageName running with importance " +
- "$packageImportance")
+ "$packageImportance"
+ )
return@forEachInParallel
}
if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG, "unused app $packageName - last used on " +
- userStats[user]?.lastTimePackageUsed(packageName)?.let(::Date))
+ DumpableLog.i(
+ LOG_TAG,
+ "unused app $packageName - last used on " +
+ userStats[user]?.lastTimePackageUsed(packageName)?.let(::Date)
+ )
}
- synchronized(userAppsToHibernate) {
- userAppsToHibernate.add(pkg)
- }
+ synchronized(userAppsToHibernate) { userAppsToHibernate.add(pkg) }
}
appsToHibernate.put(user, userAppsToHibernate)
}
@@ -461,9 +510,9 @@ private suspend fun getAppsToHibernate(
}
/**
- * Gets the last time we consider the package used based off its usage stats. On pre-S devices
- * this looks at last time visible which tracks explicit usage. In S, we add component usage
- * which tracks various forms of implicit usage (e.g. service bindings).
+ * Gets the last time we consider the package used based off its usage stats. On pre-S devices this
+ * looks at last time visible which tracks explicit usage. In S, we add component usage which tracks
+ * various forms of implicit usage (e.g. service bindings).
*/
fun UsageStats.lastTimePackageUsed(): Long {
var lastTimePkgUsed = this.lastTimeVisible
@@ -487,9 +536,7 @@ private fun List<UsageStats>.lastTimePackageUsed(pkgName: String): Long {
return lastTimePackageUsed(listOf(pkgName))
}
-/**
- * Checks if the given package is exempt from hibernation in a way that's not user-overridable
- */
+/** Checks if the given package is exempt from hibernation in a way that's not user-overridable */
suspend fun isPackageHibernationExemptBySystem(
pkg: LightPackageInfo,
user: UserHandle,
@@ -500,23 +547,22 @@ suspend fun isPackageHibernationExemptBySystem(
}
return true
}
- if (!ExemptServicesLiveData[user]
- .getInitializedValue()[pkg.packageName]
- .isNullOrEmpty()) {
+ if (!ExemptServicesLiveData[user].getInitializedValue()[pkg.packageName].isNullOrEmpty()) {
return true
}
if (Utils.isUserDisabledOrWorkProfile(user)) {
if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG,
- "Exempted ${pkg.packageName} - $user is disabled or a work profile")
+ DumpableLog.i(
+ LOG_TAG,
+ "Exempted ${pkg.packageName} - $user is disabled or a work profile"
+ )
}
return true
}
- if (pkg.uid == Process.SYSTEM_UID){
+ if (pkg.uid == Process.SYSTEM_UID) {
if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG,
- "Exempted ${pkg.packageName} - Package shares system uid")
+ DumpableLog.i(LOG_TAG, "Exempted ${pkg.packageName} - Package shares system uid")
}
return true
}
@@ -524,8 +570,8 @@ suspend fun isPackageHibernationExemptBySystem(
val context = PermissionControllerApplication.get()
if (context.getSystemService(DevicePolicyManager::class.java)!!.isDeviceManaged) {
// TODO(b/237065504): Use proper system API to check if the device is financed in U.
- val isFinancedDevice = Settings.Global.getInt(
- context.contentResolver, "device_owner_type", 0) == 1
+ val isFinancedDevice =
+ Settings.Global.getInt(context.contentResolver, "device_owner_type", 0) == 1
if (!isFinancedDevice) {
if (DEBUG_HIBERNATION_POLICY) {
DumpableLog.i(LOG_TAG, "Exempted ${pkg.packageName} - device is managed")
@@ -534,12 +580,16 @@ suspend fun isPackageHibernationExemptBySystem(
}
}
- val carrierPrivilegedStatus = CarrierPrivilegedStatusLiveData[pkg.packageName]
- .getInitializedValue()
- if (carrierPrivilegedStatus != CARRIER_PRIVILEGE_STATUS_HAS_ACCESS &&
- carrierPrivilegedStatus != CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
- DumpableLog.w(LOG_TAG, "Error carrier privileged status for ${pkg.packageName}: " +
- carrierPrivilegedStatus)
+ val carrierPrivilegedStatus =
+ CarrierPrivilegedStatusLiveData[pkg.packageName].getInitializedValue()
+ if (
+ carrierPrivilegedStatus != CARRIER_PRIVILEGE_STATUS_HAS_ACCESS &&
+ carrierPrivilegedStatus != CARRIER_PRIVILEGE_STATUS_NO_ACCESS
+ ) {
+ DumpableLog.w(
+ LOG_TAG,
+ "Error carrier privileged status for ${pkg.packageName}: " + carrierPrivilegedStatus
+ )
}
if (carrierPrivilegedStatus == CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
if (DEBUG_HIBERNATION_POLICY) {
@@ -548,19 +598,24 @@ suspend fun isPackageHibernationExemptBySystem(
return true
}
- if (PermissionControllerApplication.get()
+ if (
+ PermissionControllerApplication.get()
.packageManager
- .checkPermission(
- Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
- pkg.packageName) == PERMISSION_GRANTED) {
+ .checkPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pkg.packageName) ==
+ PERMISSION_GRANTED
+ ) {
if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG, "Exempted ${pkg.packageName} " +
- "- holder of READ_PRIVILEGED_PHONE_STATE")
+ DumpableLog.i(
+ LOG_TAG,
+ "Exempted ${pkg.packageName} " + "- holder of READ_PRIVILEGED_PHONE_STATE"
+ )
}
return true
}
- val emergencyRoleHolders = context.getSystemService(android.app.role.RoleManager::class.java)!!
+ val emergencyRoleHolders =
+ context
+ .getSystemService(android.app.role.RoleManager::class.java)!!
.getRoleHolders(RoleManager.ROLE_EMERGENCY)
if (emergencyRoleHolders.contains(pkg.packageName)) {
if (DEBUG_HIBERNATION_POLICY) {
@@ -571,19 +626,19 @@ suspend fun isPackageHibernationExemptBySystem(
if (SdkLevel.isAtLeastS()) {
val hasInstallOrUpdatePermissions =
+ context.checkPermission(Manifest.permission.INSTALL_PACKAGES, -1 /* pid */, pkg.uid) ==
+ PERMISSION_GRANTED ||
context.checkPermission(
- Manifest.permission.INSTALL_PACKAGES, -1 /* pid */, pkg.uid) ==
- PERMISSION_GRANTED ||
- context.checkPermission(
- Manifest.permission.INSTALL_PACKAGE_UPDATES, -1 /* pid */, pkg.uid) ==
- PERMISSION_GRANTED
+ Manifest.permission.INSTALL_PACKAGE_UPDATES,
+ -1 /* pid */,
+ pkg.uid
+ ) == PERMISSION_GRANTED
val hasUpdatePackagesWithoutUserActionPermission =
- context.checkPermission(
- UPDATE_PACKAGES_WITHOUT_USER_ACTION, -1 /* pid */, pkg.uid) ==
- PERMISSION_GRANTED
+ context.checkPermission(UPDATE_PACKAGES_WITHOUT_USER_ACTION, -1 /* pid */, pkg.uid) ==
+ PERMISSION_GRANTED
val isInstallerOfRecord =
- InstallerPackagesLiveData[user].getInitializedValue().contains(pkg.packageName) &&
- hasUpdatePackagesWithoutUserActionPermission
+ InstallerPackagesLiveData[user].getInitializedValue().contains(pkg.packageName) &&
+ hasUpdatePackagesWithoutUserActionPermission
// Grant if app w/ privileged install/update permissions or app is an installer app that
// updates packages without user action.
if (hasInstallOrUpdatePermissions || isInstallerOfRecord) {
@@ -593,7 +648,9 @@ suspend fun isPackageHibernationExemptBySystem(
return true
}
- val roleHolders = context.getSystemService(android.app.role.RoleManager::class.java)!!
+ val roleHolders =
+ context
+ .getSystemService(android.app.role.RoleManager::class.java)!!
.getRoleHolders(RoleManager.ROLE_SYSTEM_WELLBEING)
if (roleHolders.contains(pkg.packageName)) {
if (DEBUG_HIBERNATION_POLICY) {
@@ -604,8 +661,10 @@ suspend fun isPackageHibernationExemptBySystem(
}
if (SdkLevel.isAtLeastT()) {
- val roleHolders = context.getSystemService(android.app.role.RoleManager::class.java)!!
- .getRoleHolders(RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT)
+ val roleHolders =
+ context
+ .getSystemService(android.app.role.RoleManager::class.java)!!
+ .getRoleHolders(RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT)
if (roleHolders.contains(pkg.packageName)) {
if (DEBUG_HIBERNATION_POLICY) {
DumpableLog.i(LOG_TAG, "Exempted ${pkg.packageName} - device policy manager app")
@@ -614,9 +673,12 @@ suspend fun isPackageHibernationExemptBySystem(
}
}
- if (isSystemExemptFromHibernationEnabled() && AppOpLiveData[pkg.packageName,
- AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION,
- pkg.uid].getInitializedValue() == AppOpsManager.MODE_ALLOWED) {
+ if (
+ isSystemExemptFromHibernationEnabled() &&
+ AppOpLiveData[
+ pkg.packageName, AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION, pkg.uid]
+ .getInitializedValue() == AppOpsManager.MODE_ALLOWED
+ ) {
if (DEBUG_HIBERNATION_POLICY) {
DumpableLog.i(
LOG_TAG,
@@ -641,8 +703,8 @@ suspend fun isPackageHibernationExemptByUser(
val packageUid = pkg.uid
val allowlistAppOpMode =
- AppOpLiveData[packageName,
- AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageUid]
+ AppOpLiveData[
+ packageName, AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageUid]
.getInitializedValue()
if (allowlistAppOpMode == AppOpsManager.MODE_DEFAULT) {
// Initial state - allowlist not explicitly overridden by either user or installer
@@ -658,11 +720,11 @@ suspend fun isPackageHibernationExemptByUser(
// Q- packages exempt by default, except R- on Auto since Auto-Revoke was skipped in R
val maxTargetSdkVersionForExemptApps =
- if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
- android.os.Build.VERSION_CODES.R
- } else {
- android.os.Build.VERSION_CODES.Q
- }
+ if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+ android.os.Build.VERSION_CODES.R
+ } else {
+ android.os.Build.VERSION_CODES.Q
+ }
return pkg.targetSdkVersion <= maxTargetSdkVersionForExemptApps
}
@@ -671,18 +733,18 @@ suspend fun isPackageHibernationExemptByUser(
}
private fun Context.isPackageCrossProfile(pkg: String): Boolean {
- return packageManager.checkPermission(
- Manifest.permission.INTERACT_ACROSS_PROFILES, pkg) == PERMISSION_GRANTED ||
- packageManager.checkPermission(
- Manifest.permission.INTERACT_ACROSS_USERS, pkg) == PERMISSION_GRANTED ||
- packageManager.checkPermission(
- Manifest.permission.INTERACT_ACROSS_USERS_FULL, pkg) == PERMISSION_GRANTED
+ return packageManager.checkPermission(Manifest.permission.INTERACT_ACROSS_PROFILES, pkg) ==
+ PERMISSION_GRANTED ||
+ packageManager.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS, pkg) ==
+ PERMISSION_GRANTED ||
+ packageManager.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, pkg) ==
+ PERMISSION_GRANTED
}
val Context.sharedPreferences: SharedPreferences
get() {
- return PreferenceManager.getDefaultSharedPreferences(this)
-}
+ return PreferenceManager.getDefaultSharedPreferences(this)
+ }
internal class SystemTime {
var actualSystemTime: Long = SNAPSHOT_UNINITIALIZED
@@ -692,15 +754,15 @@ internal class SystemTime {
private fun getSystemTime(sharedPreferences: SharedPreferences): SystemTime {
val systemTime = SystemTime()
- val systemTimeSnapshot = sharedPreferences.getLong(PREF_KEY_BOOT_TIME_SNAPSHOT,
- SNAPSHOT_UNINITIALIZED)
+ val systemTimeSnapshot =
+ sharedPreferences.getLong(PREF_KEY_BOOT_TIME_SNAPSHOT, SNAPSHOT_UNINITIALIZED)
if (systemTimeSnapshot == SNAPSHOT_UNINITIALIZED) {
DumpableLog.e(LOG_TAG, "PREF_KEY_BOOT_TIME_SNAPSHOT is not initialized")
return systemTime
}
- val realtimeSnapshot = sharedPreferences.getLong(PREF_KEY_ELAPSED_REALTIME_SNAPSHOT,
- SNAPSHOT_UNINITIALIZED)
+ val realtimeSnapshot =
+ sharedPreferences.getLong(PREF_KEY_ELAPSED_REALTIME_SNAPSHOT, SNAPSHOT_UNINITIALIZED)
if (realtimeSnapshot == SNAPSHOT_UNINITIALIZED) {
DumpableLog.e(LOG_TAG, "PREF_KEY_ELAPSED_REALTIME_SNAPSHOT is not initialized")
return systemTime
@@ -713,14 +775,19 @@ private fun getSystemTime(sharedPreferences: SharedPreferences): SystemTime {
}
fun getStartTimeOfUnusedAppTracking(sharedPreferences: SharedPreferences): Long {
- val startTimeOfUnusedAppTracking = sharedPreferences.getLong(
- PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING, SNAPSHOT_UNINITIALIZED)
+ val startTimeOfUnusedAppTracking =
+ sharedPreferences.getLong(
+ PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING,
+ SNAPSHOT_UNINITIALIZED
+ )
// If the preference is not initialized then use the current system time.
if (startTimeOfUnusedAppTracking == SNAPSHOT_UNINITIALIZED) {
val actualSystemTime = System.currentTimeMillis()
- sharedPreferences.edit()
- .putLong(PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING, actualSystemTime).apply()
+ sharedPreferences
+ .edit()
+ .putLong(PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING, actualSystemTime)
+ .apply()
return actualSystemTime
}
@@ -729,20 +796,28 @@ fun getStartTimeOfUnusedAppTracking(sharedPreferences: SharedPreferences): Long
if (diffSystemTime > ONE_DAY_MS) {
adjustStartTimeOfUnusedAppTracking(sharedPreferences)
}
- return sharedPreferences.getLong(PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING,
- SNAPSHOT_UNINITIALIZED)
+ return sharedPreferences.getLong(
+ PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING,
+ SNAPSHOT_UNINITIALIZED
+ )
}
private fun initStartTimeOfUnusedAppTracking(sharedPreferences: SharedPreferences) {
val systemTimeSnapshot = System.currentTimeMillis()
- if (sharedPreferences
- .getLong(PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING, SNAPSHOT_UNINITIALIZED)
- == SNAPSHOT_UNINITIALIZED) {
- sharedPreferences.edit()
- .putLong(PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING, systemTimeSnapshot).apply()
+ if (
+ sharedPreferences.getLong(
+ PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING,
+ SNAPSHOT_UNINITIALIZED
+ ) == SNAPSHOT_UNINITIALIZED
+ ) {
+ sharedPreferences
+ .edit()
+ .putLong(PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING, systemTimeSnapshot)
+ .apply()
}
val realtimeSnapshot = SystemClock.elapsedRealtime()
- sharedPreferences.edit()
+ sharedPreferences
+ .edit()
.putLong(PREF_KEY_BOOT_TIME_SNAPSHOT, systemTimeSnapshot)
.putLong(PREF_KEY_ELAPSED_REALTIME_SNAPSHOT, realtimeSnapshot)
.apply()
@@ -751,49 +826,52 @@ private fun initStartTimeOfUnusedAppTracking(sharedPreferences: SharedPreference
private fun adjustStartTimeOfUnusedAppTracking(sharedPreferences: SharedPreferences) {
val systemTime = getSystemTime(sharedPreferences)
val startTimeOfUnusedAppTracking =
- sharedPreferences.getLong(PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING,
- SNAPSHOT_UNINITIALIZED)
+ sharedPreferences.getLong(
+ PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING,
+ SNAPSHOT_UNINITIALIZED
+ )
if (startTimeOfUnusedAppTracking == SNAPSHOT_UNINITIALIZED) {
DumpableLog.e(LOG_TAG, "PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING is not initialized")
return
}
val adjustedStartTimeOfUnusedAppTracking =
startTimeOfUnusedAppTracking + systemTime.diffSystemTime
- sharedPreferences.edit()
+ sharedPreferences
+ .edit()
.putLong(PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING, adjustedStartTimeOfUnusedAppTracking)
.putLong(PREF_KEY_BOOT_TIME_SNAPSHOT, systemTime.actualSystemTime)
.putLong(PREF_KEY_ELAPSED_REALTIME_SNAPSHOT, systemTime.actualRealtime)
.apply()
}
-/**
- * Make intent to go to unused apps page.
- */
+/** Make intent to go to unused apps page. */
private fun makeUnusedAppsIntent(context: Context, sessionId: Long): PendingIntent {
- val clickIntent = Intent(Intent.ACTION_MANAGE_UNUSED_APPS).apply {
- putExtra(Constants.EXTRA_SESSION_ID, sessionId)
- flags = FLAG_ACTIVITY_NEW_TASK
- }
- val pendingIntent = PendingIntent.getActivity(context, 0, clickIntent,
- FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
+ val clickIntent =
+ Intent(Intent.ACTION_MANAGE_UNUSED_APPS).apply {
+ putExtra(Constants.EXTRA_SESSION_ID, sessionId)
+ flags = FLAG_ACTIVITY_NEW_TASK
+ }
+ val pendingIntent =
+ PendingIntent.getActivity(context, 0, clickIntent, FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
return pendingIntent
}
-/**
- * Make intent for when safety center card is dismissed.
- */
+/** Make intent for when safety center card is dismissed. */
private fun makeDismissIntent(context: Context, sessionId: Long): PendingIntent {
- val dismissIntent = Intent(context, DismissHandler::class.java).apply {
- putExtra(Constants.EXTRA_SESSION_ID, sessionId)
- flags = FLAG_RECEIVER_FOREGROUND
- }
- return PendingIntent.getBroadcast(context, /* requestCode= */ 0, dismissIntent,
- FLAG_ONE_SHOT or FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
+ val dismissIntent =
+ Intent(context, DismissHandler::class.java).apply {
+ putExtra(Constants.EXTRA_SESSION_ID, sessionId)
+ flags = FLAG_RECEIVER_FOREGROUND
+ }
+ return PendingIntent.getBroadcast(
+ context,
+ /* requestCode= */ 0,
+ dismissIntent,
+ FLAG_ONE_SHOT or FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
+ )
}
-/**
- * Broadcast receiver class for when safety center card is dismissed.
- */
+/** Broadcast receiver class for when safety center card is dismissed. */
class DismissHandler : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
setUnusedAppsReviewNeeded(context!!, false)
@@ -801,8 +879,8 @@ class DismissHandler : BroadcastReceiver() {
}
/**
- * A job to check for apps unused in the last [getUnusedThresholdMs]ms every
- * [getCheckFrequencyMs]ms and hibernate the app / revoke their runtime permissions.
+ * A job to check for apps unused in the last [getUnusedThresholdMs]ms every [getCheckFrequencyMs]ms
+ * and hibernate the app / revoke their runtime permissions.
*/
class HibernationJobService : JobService() {
var job: Job? = null
@@ -823,58 +901,75 @@ class HibernationJobService : JobService() {
}
jobStartTime = System.currentTimeMillis()
- job = GlobalScope.launch(Main) {
- try {
- var sessionId = Constants.INVALID_SESSION_ID
- while (sessionId == Constants.INVALID_SESSION_ID) {
- sessionId = Random().nextLong()
- }
+ job =
+ GlobalScope.launch(Main) {
+ try {
+ var sessionId = Constants.INVALID_SESSION_ID
+ while (sessionId == Constants.INVALID_SESSION_ID) {
+ sessionId = Random().nextLong()
+ }
- val appsToHibernate = getAppsToHibernate(this@HibernationJobService)
- var hibernatedApps: Set<Pair<String, UserHandle>> = emptySet()
- if (isHibernationEnabled()) {
- val hibernationController =
- HibernationController(this@HibernationJobService, getUnusedThresholdMs(),
- hibernationTargetsPreSApps())
- hibernatedApps = hibernationController.hibernateApps(appsToHibernate)
- }
- val revokedApps = revokeAppPermissions(
- appsToHibernate, this@HibernationJobService, sessionId)
- val unusedApps: Set<Pair<String, UserHandle>> = hibernatedApps + revokedApps
- if (unusedApps.isNotEmpty()) {
- showUnusedAppsNotification(unusedApps.size, sessionId)
- if (SdkLevel.isAtLeastT() &&
- revokedApps.isNotEmpty() &&
- getSystemService(SafetyCenterManager::class.java)!!.isSafetyCenterEnabled) {
- setUnusedAppsReviewNeeded(this@HibernationJobService, true)
- rescanAndPushDataToSafetyCenter(
- this@HibernationJobService,
- sessionId,
- SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED)
- .build())
+ val appsToHibernate = getAppsToHibernate(this@HibernationJobService)
+ var hibernatedApps: Set<Pair<String, UserHandle>> = emptySet()
+ if (isHibernationEnabled()) {
+ val hibernationController =
+ HibernationController(
+ this@HibernationJobService,
+ getUnusedThresholdMs(),
+ hibernationTargetsPreSApps()
+ )
+ hibernatedApps = hibernationController.hibernateApps(appsToHibernate)
}
+ val revokedApps =
+ revokeAppPermissions(appsToHibernate, this@HibernationJobService, sessionId)
+ val unusedApps: Set<Pair<String, UserHandle>> = hibernatedApps + revokedApps
+ if (unusedApps.isNotEmpty()) {
+ showUnusedAppsNotification(unusedApps.size, sessionId)
+ if (
+ SdkLevel.isAtLeastT() &&
+ revokedApps.isNotEmpty() &&
+ getSystemService(SafetyCenterManager::class.java)!!
+ .isSafetyCenterEnabled
+ ) {
+ setUnusedAppsReviewNeeded(this@HibernationJobService, true)
+ rescanAndPushDataToSafetyCenter(
+ this@HibernationJobService,
+ sessionId,
+ SafetyEvent.Builder(
+ SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
+ )
+ .build()
+ )
+ }
+ }
+ } catch (e: Exception) {
+ DumpableLog.e(LOG_TAG, "Failed to auto-revoke permissions", e)
}
- } catch (e: Exception) {
- DumpableLog.e(LOG_TAG, "Failed to auto-revoke permissions", e)
+ jobFinished(params, false)
}
- jobFinished(params, false)
- }
return true
}
private fun showUnusedAppsNotification(numUnused: Int, sessionId: Long) {
val notificationManager = getSystemService(NotificationManager::class.java)!!
- val permissionReminderChannel = NotificationChannel(
- Constants.PERMISSION_REMINDER_CHANNEL_ID, getString(R.string.permission_reminders),
- NotificationManager.IMPORTANCE_LOW)
+ val permissionReminderChannel =
+ NotificationChannel(
+ Constants.PERMISSION_REMINDER_CHANNEL_ID,
+ getString(R.string.permission_reminders),
+ NotificationManager.IMPORTANCE_LOW
+ )
notificationManager.createNotificationChannel(permissionReminderChannel)
var notifTitle: String
var notifContent: String
if (isHibernationEnabled()) {
- notifTitle = StringUtils.getIcuPluralsString(this,
- R.string.unused_apps_notification_title, numUnused)
+ notifTitle =
+ StringUtils.getIcuPluralsString(
+ this,
+ R.string.unused_apps_notification_title,
+ numUnused
+ )
notifContent = getString(R.string.unused_apps_notification_content)
} else {
notifTitle = getString(R.string.auto_revoke_permission_notification_title)
@@ -882,16 +977,19 @@ class HibernationJobService : JobService() {
}
// Notification won't appear on TV, because notifications are considered distruptive on TV
- val b = Notification.Builder(this, Constants.PERMISSION_REMINDER_CHANNEL_ID)
- .setContentTitle(notifTitle)
- .setContentText(notifContent)
- .setStyle(Notification.BigTextStyle().bigText(notifContent))
- .setColor(getColor(android.R.color.system_notification_accent_color))
- .setAutoCancel(true)
- .setContentIntent(makeUnusedAppsIntent(this, sessionId))
+ val b =
+ Notification.Builder(this, Constants.PERMISSION_REMINDER_CHANNEL_ID)
+ .setContentTitle(notifTitle)
+ .setContentText(notifContent)
+ .setStyle(Notification.BigTextStyle().bigText(notifContent))
+ .setColor(getColor(android.R.color.system_notification_accent_color))
+ .setAutoCancel(true)
+ .setContentIntent(makeUnusedAppsIntent(this, sessionId))
val extras = Bundle()
- if (SdkLevel.isAtLeastT() &&
- getSystemService(SafetyCenterManager::class.java)!!.isSafetyCenterEnabled) {
+ if (
+ SdkLevel.isAtLeastT() &&
+ getSystemService(SafetyCenterManager::class.java)!!.isSafetyCenterEnabled
+ ) {
val notificationResources = KotlinUtils.getSafetyCenterNotificationResources(this)
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, notificationResources.appLabel)
@@ -903,13 +1001,15 @@ class HibernationJobService : JobService() {
Utils.getSettingsLabelForNotifications(applicationContext.packageManager)?.let {
settingsLabel ->
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, settingsLabel.toString())
- b.setSmallIcon(R.drawable.ic_settings_24dp)
- .addExtras(extras)
+ b.setSmallIcon(R.drawable.ic_settings_24dp).addExtras(extras)
}
}
- notificationManager.notify(HibernationJobService::class.java.simpleName,
- Constants.UNUSED_APPS_NOTIFICATION_ID, b.build())
+ notificationManager.notify(
+ HibernationJobService::class.java.simpleName,
+ Constants.UNUSED_APPS_NOTIFICATION_ID,
+ b.build()
+ )
GlobalScope.launch(IPC) {
// Preload the unused packages
getUnusedPackages().getInitializedValue(staleOk = true)
@@ -929,47 +1029,39 @@ class HibernationJobService : JobService() {
*/
class ExemptServicesLiveData(private val user: UserHandle) :
SmartUpdateMediatorLiveData<Map<String, List<String>>>() {
- private val serviceLiveDatas: List<SmartUpdateMediatorLiveData<Set<String>>> = listOf(
- ServiceLiveData[InputMethod.SERVICE_INTERFACE,
- Manifest.permission.BIND_INPUT_METHOD,
- user],
+ private val serviceLiveDatas: List<SmartUpdateMediatorLiveData<Set<String>>> =
+ listOf(
ServiceLiveData[
- NotificationListenerService.SERVICE_INTERFACE,
- Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE,
- user],
+ InputMethod.SERVICE_INTERFACE, Manifest.permission.BIND_INPUT_METHOD, user],
ServiceLiveData[
- AccessibilityService.SERVICE_INTERFACE,
- Manifest.permission.BIND_ACCESSIBILITY_SERVICE,
- user],
+ NotificationListenerService.SERVICE_INTERFACE,
+ Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE,
+ user],
ServiceLiveData[
- WallpaperService.SERVICE_INTERFACE,
- Manifest.permission.BIND_WALLPAPER,
- user],
+ AccessibilityService.SERVICE_INTERFACE,
+ Manifest.permission.BIND_ACCESSIBILITY_SERVICE,
+ user],
ServiceLiveData[
- VoiceInteractionService.SERVICE_INTERFACE,
- Manifest.permission.BIND_VOICE_INTERACTION,
- user],
+ WallpaperService.SERVICE_INTERFACE, Manifest.permission.BIND_WALLPAPER, user],
ServiceLiveData[
- PrintService.SERVICE_INTERFACE,
- Manifest.permission.BIND_PRINT_SERVICE,
- user],
+ VoiceInteractionService.SERVICE_INTERFACE,
+ Manifest.permission.BIND_VOICE_INTERACTION,
+ user],
ServiceLiveData[
- DreamService.SERVICE_INTERFACE,
- Manifest.permission.BIND_DREAM_SERVICE,
- user],
+ PrintService.SERVICE_INTERFACE, Manifest.permission.BIND_PRINT_SERVICE, user],
ServiceLiveData[
- AutofillService.SERVICE_INTERFACE,
- Manifest.permission.BIND_AUTOFILL_SERVICE,
- user],
+ DreamService.SERVICE_INTERFACE, Manifest.permission.BIND_DREAM_SERVICE, user],
ServiceLiveData[
- DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE,
- Manifest.permission.BIND_DEVICE_ADMIN,
- user],
+ AutofillService.SERVICE_INTERFACE, Manifest.permission.BIND_AUTOFILL_SERVICE, user],
+ ServiceLiveData[
+ DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE,
+ Manifest.permission.BIND_DEVICE_ADMIN,
+ user],
BroadcastReceiverLiveData[
- DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
- Manifest.permission.BIND_DEVICE_ADMIN,
- user]
- )
+ DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
+ Manifest.permission.BIND_DEVICE_ADMIN,
+ user]
+ )
init {
serviceLiveDatas.forEach { addSource(it) { update() } }
@@ -981,8 +1073,9 @@ class ExemptServicesLiveData(private val user: UserHandle) :
serviceLiveDatas.forEach { serviceLD ->
serviceLD.value!!.forEach { packageName ->
- pksToServices.getOrPut(packageName, { mutableListOf() })
- .add((serviceLD as? HasIntentAction)?.intentAction ?: "???")
+ pksToServices
+ .getOrPut(packageName, { mutableListOf() })
+ .add((serviceLD as? HasIntentAction)?.intentAction ?: "???")
}
}
@@ -1002,23 +1095,26 @@ class ExemptServicesLiveData(private val user: UserHandle) :
}
}
-/**
- * Live data for whether the hibernation feature is enabled or not.
- */
-object HibernationEnabledLiveData :
- MutableLiveData<Boolean>() {
+/** Live data for whether the hibernation feature is enabled or not. */
+object HibernationEnabledLiveData : MutableLiveData<Boolean>() {
init {
- postValue(SdkLevel.isAtLeastS() &&
- DeviceConfig.getBoolean(NAMESPACE_APP_HIBERNATION,
- Utils.PROPERTY_APP_HIBERNATION_ENABLED, true /* defaultValue */))
+ postValue(
+ SdkLevel.isAtLeastS() &&
+ DeviceConfig.getBoolean(
+ NAMESPACE_APP_HIBERNATION,
+ Utils.PROPERTY_APP_HIBERNATION_ENABLED,
+ true /* defaultValue */
+ )
+ )
DeviceConfig.addOnPropertiesChangedListener(
NAMESPACE_APP_HIBERNATION,
PermissionControllerApplication.get().mainExecutor,
{ properties ->
for (key in properties.keyset) {
if (key == Utils.PROPERTY_APP_HIBERNATION_ENABLED) {
- value = SdkLevel.isAtLeastS() &&
- properties.getBoolean(key, true /* defaultValue */)
+ value =
+ SdkLevel.isAtLeastS() &&
+ properties.getBoolean(key, true /* defaultValue */)
break
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/hibernation/v31/HibernationController.kt b/PermissionController/src/com/android/permissioncontroller/hibernation/v31/HibernationController.kt
index 5aa07c232..e81c7a207 100644
--- a/PermissionController/src/com/android/permissioncontroller/hibernation/v31/HibernationController.kt
+++ b/PermissionController/src/com/android/permissioncontroller/hibernation/v31/HibernationController.kt
@@ -28,9 +28,7 @@ import com.android.permissioncontroller.DumpableLog
import com.android.permissioncontroller.permission.data.HibernatedPackagesLiveData
import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
-/**
- * Hibernation controller that handles modifying hibernation state.
- */
+/** Hibernation controller that handles modifying hibernation state. */
@RequiresApi(Build.VERSION_CODES.S)
class HibernationController(
private val context: Context,
@@ -62,8 +60,7 @@ class HibernationController(
if (hibernationManager.isHibernatingForUser(pkg.packageName)) {
continue
}
- if (!targetsPreS &&
- pkg.targetSdkVersion < Build.VERSION_CODES.S) {
+ if (!targetsPreS && pkg.targetSdkVersion < Build.VERSION_CODES.S) {
// Only apps targeting S or above can be truly hibernated.
continue
}
@@ -81,8 +78,10 @@ class HibernationController(
context.getSystemService(APP_HIBERNATION_SERVICE) as AppHibernationManager
val globallyHibernatedApps = mutableSetOf<String>()
for ((pkgName, _) in hibernatedApps) {
- if (globallyHibernatedApps.contains(pkgName) ||
- hibernationManager.isHibernatingGlobally(pkgName)) {
+ if (
+ globallyHibernatedApps.contains(pkgName) ||
+ hibernationManager.isHibernatingGlobally(pkgName)
+ ) {
continue
}
@@ -99,9 +98,11 @@ class HibernationController(
HibernatedPackagesLiveData.update()
}
if (DEBUG_HIBERNATION) {
- DumpableLog.i(LOG_TAG,
+ DumpableLog.i(
+ LOG_TAG,
"Done hibernating apps $hibernatedApps \n " +
- "Globally hibernating apps $globallyHibernatedApps")
+ "Globally hibernating apps $globallyHibernatedApps"
+ )
}
return hibernatedApps
diff --git a/PermissionController/src/com/android/permissioncontroller/hibernation/v31/InstallerPackagesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/hibernation/v31/InstallerPackagesLiveData.kt
index f1a19294a..ebe57ec36 100644
--- a/PermissionController/src/com/android/permissioncontroller/hibernation/v31/InstallerPackagesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/hibernation/v31/InstallerPackagesLiveData.kt
@@ -27,17 +27,13 @@ import com.android.permissioncontroller.permission.data.DataRepositoryForPackage
import com.android.permissioncontroller.permission.data.SmartAsyncMediatorLiveData
import kotlinx.coroutines.Job
-/**
- * Packages that are the installer of record for some package on the device.
- */
+/** Packages that are the installer of record for some package on the device. */
@RequiresApi(Build.VERSION_CODES.S)
-class InstallerPackagesLiveData(private val user: UserHandle)
- : SmartAsyncMediatorLiveData<Set<String>>() {
+class InstallerPackagesLiveData(private val user: UserHandle) :
+ SmartAsyncMediatorLiveData<Set<String>>() {
init {
- addSource(AllPackageInfosLiveData) {
- update()
- }
+ addSource(AllPackageInfosLiveData) { update() }
}
override suspend fun loadDataAndPostValue(job: Job) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/AllPackageInfosLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/AllPackageInfosLiveData.kt
index c2655ecff..b3a28eefe 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/AllPackageInfosLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/AllPackageInfosLiveData.kt
@@ -20,9 +20,7 @@ import android.os.UserHandle
import com.android.permissioncontroller.permission.data.AllPackageInfosLiveData.addSource
import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
-/**
- * A LiveData which tracks the PackageInfos of all of the packages in the system, for all users.
- */
+/** A LiveData which tracks the PackageInfos of all of the packages in the system, for all users. */
object AllPackageInfosLiveData :
SmartUpdateMediatorLiveData<Map<UserHandle, List<LightPackageInfo>>>() {
@@ -30,9 +28,7 @@ object AllPackageInfosLiveData :
private val userPackageInfos = mutableMapOf<UserHandle, List<LightPackageInfo>>()
init {
- addSource(UsersLiveData) {
- update()
- }
+ addSource(UsersLiveData) { update() }
}
override fun onUpdate() {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/AppOpLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/AppOpLiveData.kt
index 5a0abeaa1..1e44f16bd 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/AppOpLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/AppOpLiveData.kt
@@ -27,12 +27,12 @@ import com.android.permissioncontroller.PermissionControllerApplication
* @param packageName The name of the package
* @param op The name of the appop
* @param uid The uid of the package
- *
* @see AppOpsManager
*/
// TODO eugenesusla: observe appops
// TODO eugenesusla: use for external storage
-class AppOpLiveData private constructor(
+class AppOpLiveData
+private constructor(
private val app: Application,
private val packageName: String,
private val op: String,
@@ -52,13 +52,18 @@ class AppOpLiveData private constructor(
/**
* Repository for AppOpLiveData.
- * <p> Key value is a triple of string package name, string appop, and
- * package uid, value is its corresponding LiveData.
+ *
+ * <p> Key value is a triple of string package name, string appop, and package uid, value is its
+ * corresponding LiveData.
*/
companion object : DataRepository<Triple<String, String, Int>, AppOpLiveData>() {
override fun newValue(key: Triple<String, String, Int>): AppOpLiveData {
- return AppOpLiveData(PermissionControllerApplication.get(),
- key.first, key.second, key.third)
+ return AppOpLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second,
+ key.third
+ )
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt
index 7c69d6078..b17098a13 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt
@@ -32,17 +32,17 @@ import com.android.permissioncontroller.permission.model.livedatatypes.LightPack
import com.android.permissioncontroller.permission.model.livedatatypes.LightPermGroupInfo
import com.android.permissioncontroller.permission.model.livedatatypes.LightPermInfo
import com.android.permissioncontroller.permission.model.livedatatypes.PermState
-import com.android.permissioncontroller.permission.utils.PermissionMapping.isPlatformPermissionGroup
import com.android.permissioncontroller.permission.utils.LocationUtils
+import com.android.permissioncontroller.permission.utils.PermissionMapping.isPlatformPermissionGroup
import com.android.permissioncontroller.permission.utils.Utils
import kotlinx.coroutines.Job
/**
* A LiveData representing UI properties of an App Permission Group:
* <ul>
- * <li>shouldShow</li>
- * <li>isSystem</li>
- * <li>isGranted</li>
+ * <li>shouldShow</li>
+ * <li>isSystem</li>
+ * <li>isGranted</li>
* </ul>
*
* @param app The current application
@@ -50,7 +50,8 @@ import kotlinx.coroutines.Job
* @param permGroupName The name of the permission group whose permissions are observed
* @param user The user of the package
*/
-class AppPermGroupUiInfoLiveData private constructor(
+class AppPermGroupUiInfoLiveData
+private constructor(
private val app: Application,
private val packageName: String,
private val permGroupName: String,
@@ -65,21 +66,19 @@ class AppPermGroupUiInfoLiveData private constructor(
private val isHealth = Utils.isHealthPermissionGroup(permGroupName)
init {
- isSpecialLocation = LocationUtils.isLocationGroupAndProvider(app,
- permGroupName, packageName) ||
- LocationUtils.isLocationGroupAndControllerExtraPackage(app, permGroupName, packageName)
+ isSpecialLocation =
+ LocationUtils.isLocationGroupAndProvider(app, permGroupName, packageName) ||
+ LocationUtils.isLocationGroupAndControllerExtraPackage(
+ app,
+ permGroupName,
+ packageName
+ )
- addSource(packageInfoLiveData) {
- update()
- }
+ addSource(packageInfoLiveData) { update() }
- addSource(permGroupLiveData) {
- update()
- }
+ addSource(permGroupLiveData) { update() }
- addSource(permissionStateLiveData) {
- update()
- }
+ addSource(permissionStateLiveData) { update() }
}
override suspend fun loadDataAndPostValue(job: Job) {
@@ -91,27 +90,36 @@ class AppPermGroupUiInfoLiveData private constructor(
val permissionState = permissionStateLiveData.value
if (packageInfo == null || permissionGroup == null || permissionState == null) {
- if (packageInfoLiveData.isInitialized && permGroupLiveData.isInitialized &&
- permissionStateLiveData.isInitialized) {
+ if (
+ packageInfoLiveData.isInitialized &&
+ permGroupLiveData.isInitialized &&
+ permissionStateLiveData.isInitialized
+ ) {
invalidateSingle(Triple(packageName, permGroupName, user))
postValue(null)
}
return
}
- postValue(getAppPermGroupUiInfo(packageInfo, permissionGroup.groupInfo,
- permissionGroup.permissionInfos, permissionState))
+ postValue(
+ getAppPermGroupUiInfo(
+ packageInfo,
+ permissionGroup.groupInfo,
+ permissionGroup.permissionInfos,
+ permissionState
+ )
+ )
}
/**
- * Determines if the UI should show a given package, if that package is a system app, and
- * if it has granted permissions in this LiveData's permission group.
+ * Determines if the UI should show a given package, if that package is a system app, and if it
+ * has granted permissions in this LiveData's permission group.
*
* @param packageInfo The PackageInfo of the package we wish to examine
* @param groupInfo The groupInfo of the permission group we wish to examine
* @param allPermInfos All of the PermissionInfos in the permission group
- * @param permissionState The flags and grant state for all permissions in the permission
- * group that this package requests
+ * @param permissionState The flags and grant state for all permissions in the permission group
+ * that this package requests
*/
private fun getAppPermGroupUiInfo(
packageInfo: LightPackageInfo,
@@ -126,10 +134,11 @@ class AppPermGroupUiInfoLiveData private constructor(
val requestedPermissionInfos =
allPermInfos.filter { permissionState.containsKey(it.key) }.values
- val shouldShow = packageInfo.enabled &&
- isGrantableAndNotLegacyPlatform(packageInfo, groupInfo, requestedPermissionInfos) &&
- (!isStorage || Utils.shouldShowStorage(packageInfo)) &&
- (!isHealth || Utils.shouldShowHealthPermission(packageInfo, groupInfo.name))
+ val shouldShow =
+ packageInfo.enabled &&
+ isGrantableAndNotLegacyPlatform(packageInfo, groupInfo, requestedPermissionInfos) &&
+ (!isStorage || Utils.shouldShowStorage(packageInfo)) &&
+ (!isHealth || Utils.shouldShowHealthPermission(packageInfo, groupInfo.name))
val isSystemApp = !isUserSensitive(permissionState)
@@ -147,19 +156,17 @@ class AppPermGroupUiInfoLiveData private constructor(
*
* @param packageInfo The PackageInfo of the package we are examining
* @param groupInfo The Permission Group Info of the permission group we are examining
- * @param permissionInfos The LightPermInfos corresponding to the permissions in the
- * permission group that this package requests
- *
+ * @param permissionInfos The LightPermInfos corresponding to the permissions in the permission
+ * group that this package requests
* @return True if the app permission group is grantable, and is not a legacy system permission,
- * false otherwise.
+ * false otherwise.
*/
private fun isGrantableAndNotLegacyPlatform(
packageInfo: LightPackageInfo,
groupInfo: LightPermGroupInfo,
permissionInfos: Collection<LightPermInfo>
): Boolean {
- if (groupInfo.packageName == Utils.OS_PKG &&
- !isPlatformPermissionGroup(groupInfo.name)) {
+ if (groupInfo.packageName == Utils.OS_PKG && !isPlatformPermissionGroup(groupInfo.name)) {
return false
}
@@ -167,8 +174,9 @@ class AppPermGroupUiInfoLiveData private constructor(
var hasPreRuntime = false
for (permissionInfo in permissionInfos) {
- if (permissionInfo.protectionFlags and
- PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY == 0) {
+ if (
+ permissionInfo.protectionFlags and PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY == 0
+ ) {
hasPreRuntime = true
}
@@ -177,8 +185,9 @@ class AppPermGroupUiInfoLiveData private constructor(
}
}
- val isGrantingAllowed = (!packageInfo.isInstantApp || hasInstantPerm) &&
- (packageInfo.targetSdkVersion >= Build.VERSION_CODES.M || hasPreRuntime)
+ val isGrantingAllowed =
+ (!packageInfo.isInstantApp || hasInstantPerm) &&
+ (packageInfo.targetSdkVersion >= Build.VERSION_CODES.M || hasPreRuntime)
if (!isGrantingAllowed) {
return false
}
@@ -191,10 +200,9 @@ class AppPermGroupUiInfoLiveData private constructor(
* then it is considered a system app, and hidden in the UI by default.
*
* @param permissionState The permission flags and grant state corresponding to the permissions
- * in this group requested by a given app
- *
+ * in this group requested by a given app
* @return Whether or not this package requests a user sensitive permission in the given
- * permission group
+ * permission group
*/
private fun isUserSensitive(permissionState: Map<String, PermState>): Boolean {
if (!isPlatformPermissionGroup(permGroupName)) {
@@ -204,10 +212,12 @@ class AppPermGroupUiInfoLiveData private constructor(
for (permissionName in permissionState.keys) {
val flags = permissionState[permissionName]?.permFlags ?: return true
val granted = permissionState[permissionName]?.granted ?: return true
- if ((granted &&
+ if (
+ (granted &&
flags and PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED != 0) ||
- (!granted &&
- flags and PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED != 0)) {
+ (!granted &&
+ flags and PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED != 0)
+ ) {
return true
}
}
@@ -218,32 +228,30 @@ class AppPermGroupUiInfoLiveData private constructor(
* Determines if the app permission group is user set
*
* @param permissionState The permission flags and grant state corresponding to the permissions
- * in this group requested by a given app
- *
+ * in this group requested by a given app
* @return Whether or not any of the permissions in this group have been set or fixed by the
- * user
+ * user
*/
private fun isUserSet(permissionState: Map<String, PermState>): Boolean {
- val flagMask = PackageManager.FLAG_PERMISSION_USER_SET or
- PackageManager.FLAG_PERMISSION_USER_FIXED
+ val flagMask =
+ PackageManager.FLAG_PERMISSION_USER_SET or PackageManager.FLAG_PERMISSION_USER_FIXED
return permissionState.any { (it.value.permFlags and flagMask) != 0 }
}
/**
- * Determines if this app permission group is granted, granted in foreground only, or denied.
- * It is granted if it either requests no background permissions, and has at least one requested
- * permission that is granted, or has granted at least one requested background permission.
- * It is granted in foreground only if it has at least one non-background permission granted,
- * and has denied all requested background permissions. It is denied if all requested
- * permissions are denied.
+ * Determines if this app permission group is granted, granted in foreground only, or denied. It
+ * is granted if it either requests no background permissions, and has at least one requested
+ * permission that is granted, or has granted at least one requested background permission. It
+ * is granted in foreground only if it has at least one non-background permission granted, and
+ * has denied all requested background permissions. It is denied if all requested permissions
+ * are denied.
*
* @param permissionState The permission flags and grant state corresponding to the permissions
- * in this group requested by a given app
- * @param allPermInfos All of the permissionInfos in the permission group of this app
- * permission group
- *
+ * in this group requested by a given app
+ * @param allPermInfos All of the permissionInfos in the permission group of this app permission
+ * group
* @return The int code corresponding to the app permission group state, either allowed, allowed
- * in foreground only, or denied.
+ * in foreground only, or denied.
*/
private fun getGrantedIncludingBackground(
permissionState: Map<String, PermState>,
@@ -262,36 +270,46 @@ class AppPermGroupUiInfoLiveData private constructor(
val permInfo = allPermInfos[permName] ?: continue
permInfo.backgroundPermission?.let { backgroundPerm ->
hasPermWithBackground = true
- if (permissionState[backgroundPerm]?.granted == true &&
+ if (
+ permissionState[backgroundPerm]?.granted == true &&
(permissionState[backgroundPerm]!!.permFlags and
- PackageManager.FLAG_PERMISSION_ONE_TIME == 0) &&
- specialLocationState != false) {
+ PackageManager.FLAG_PERMISSION_ONE_TIME == 0) &&
+ specialLocationState != false
+ ) {
return PermGrantState.PERMS_ALLOWED_ALWAYS
}
}
- isUserFixed = isUserFixed ||
+ isUserFixed =
+ isUserFixed ||
permState.permFlags and PackageManager.FLAG_PERMISSION_USER_FIXED != 0
}
// isOneTime indicates whether all granted permissions in permission states are one-time
// permissions
- val isOneTime = permissionState.any {
- it.value.permFlags and PackageManager.FLAG_PERMISSION_ONE_TIME != 0 } &&
+ val isOneTime =
+ permissionState.any {
+ it.value.permFlags and PackageManager.FLAG_PERMISSION_ONE_TIME != 0
+ } &&
!permissionState.any {
it.value.permFlags and PackageManager.FLAG_PERMISSION_ONE_TIME == 0 &&
- it.value.granted }
+ it.value.granted
+ }
val supportsRuntime = pkg.targetSdkVersion >= Build.VERSION_CODES.M
- val anyAllowed = specialLocationState ?: permissionState.any { (_, state) ->
- state.granted || (supportsRuntime &&
- (state.permFlags and PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0)
- }
+ val anyAllowed =
+ specialLocationState
+ ?: permissionState.any { (_, state) ->
+ state.granted ||
+ (supportsRuntime &&
+ (state.permFlags and PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) !=
+ 0)
+ }
val onlySelectedPhotosGranted =
permissionState.containsKey(READ_MEDIA_VISUAL_USER_SELECTED) &&
- permissionState.all { (permName, state) ->
- (permName == READ_MEDIA_VISUAL_USER_SELECTED && state.granted) ||
- (permName != READ_MEDIA_VISUAL_USER_SELECTED && !state.granted)
- }
+ permissionState.all { (permName, state) ->
+ (permName == READ_MEDIA_VISUAL_USER_SELECTED && state.granted) ||
+ (permName != READ_MEDIA_VISUAL_USER_SELECTED && !state.granted)
+ }
if (anyAllowed && (hasPermWithBackground || shouldShowAsForegroundGroup())) {
return if (isOneTime) {
PermGrantState.PERMS_ASK
@@ -325,32 +343,38 @@ class AppPermGroupUiInfoLiveData private constructor(
}
// The permission of the extra location controller package is determined by the
// status of the controller package itself.
- if (LocationUtils.isLocationGroupAndControllerExtraPackage(userContext,
- permGroupName, packageName)) {
+ if (
+ LocationUtils.isLocationGroupAndControllerExtraPackage(
+ userContext,
+ permGroupName,
+ packageName
+ )
+ ) {
return LocationUtils.isExtraLocationControllerPackageEnabled(userContext)
}
return null
}
private fun isFullFilesAccessGranted(pkg: LightPackageInfo): Boolean {
- val packageState = if (!FullStoragePermissionAppsLiveData.isStale) {
- val fullStoragePackages = FullStoragePermissionAppsLiveData.value ?: return false
- fullStoragePackages.find {
- it.packageName == packageName && it.user == user
- } ?: return false
- } else {
- val appOpsManager = Utils.getUserContext(app, UserHandle.getUserHandleForUid(pkg.uid))
- .getSystemService(AppOpsManager::class.java)!!
- FullStoragePermissionAppsLiveData.getFullStorageStateForPackage(
- appOpsManager, pkg) ?: return false
- }
+ val packageState =
+ if (!FullStoragePermissionAppsLiveData.isStale) {
+ val fullStoragePackages = FullStoragePermissionAppsLiveData.value ?: return false
+ fullStoragePackages.find { it.packageName == packageName && it.user == user }
+ ?: return false
+ } else {
+ val appOpsManager =
+ Utils.getUserContext(app, UserHandle.getUserHandleForUid(pkg.uid))
+ .getSystemService(AppOpsManager::class.java)!!
+ FullStoragePermissionAppsLiveData.getFullStorageStateForPackage(appOpsManager, pkg)
+ ?: return false
+ }
return !packageState.isLegacy && packageState.isGranted
}
// TODO moltmann-team: Actually change mic/camera to be a foreground only permission
private fun shouldShowAsForegroundGroup(): Boolean {
return permGroupName.equals(Manifest.permission_group.CAMERA) ||
- permGroupName.equals(Manifest.permission_group.MICROPHONE)
+ permGroupName.equals(Manifest.permission_group.MICROPHONE)
}
override fun onLocationStateChange(enabled: Boolean) {
@@ -375,15 +399,19 @@ class AppPermGroupUiInfoLiveData private constructor(
/**
* Repository for AppPermGroupUiInfoLiveDatas.
- * <p> Key value is a triple of string package name, string permission group name, and UserHandle,
- * value is its corresponding LiveData.
+ *
+ * <p> Key value is a triple of string package name, string permission group name, and
+ * UserHandle, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<Triple<String, String, UserHandle>,
- AppPermGroupUiInfoLiveData>() {
- override fun newValue(key: Triple<String, String, UserHandle>):
- AppPermGroupUiInfoLiveData {
- return AppPermGroupUiInfoLiveData(PermissionControllerApplication.get(),
- key.first, key.second, key.third)
+ companion object :
+ DataRepositoryForPackage<Triple<String, String, UserHandle>, AppPermGroupUiInfoLiveData>() {
+ override fun newValue(key: Triple<String, String, UserHandle>): AppPermGroupUiInfoLiveData {
+ return AppPermGroupUiInfoLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second,
+ key.third
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveData.kt
index b55c736ad..fac901a04 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveData.kt
@@ -22,12 +22,12 @@ import android.content.res.Resources.ID_NULL
import android.os.UserHandle
import android.util.Log
import com.android.permissioncontroller.PermissionControllerApplication
+import java.io.FileNotFoundException
import kotlinx.coroutines.Job
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParser.END_DOCUMENT
import org.xmlpull.v1.XmlPullParser.END_TAG
import org.xmlpull.v1.XmlPullParser.START_TAG
-import java.io.FileNotFoundException
private const val MANIFEST_FILE_NAME = "AndroidManifest.xml"
private const val MANIFEST_TAG = "manifest"
@@ -43,7 +43,8 @@ private const val LABEL_ATTR = "label"
* <p>Obviously the resource is found in the package, hence needs to be loaded via a Resources
* object created for this package.
*/
-class AttributionLabelLiveData private constructor(
+class AttributionLabelLiveData
+private constructor(
private val app: Application,
private val attributionTag: String?,
private val packageName: String,
@@ -61,14 +62,15 @@ class AttributionLabelLiveData private constructor(
return
}
- val pkgContext = try {
- app.createPackageContextAsUser(packageName, 0, user)
- } catch (e: NameNotFoundException) {
- Log.e(LOG_TAG, "Cannot find $packageName for $user")
+ val pkgContext =
+ try {
+ app.createPackageContextAsUser(packageName, 0, user)
+ } catch (e: NameNotFoundException) {
+ Log.e(LOG_TAG, "Cannot find $packageName for $user")
- postValue(null)
- return
- }
+ postValue(null)
+ return
+ }
// TODO (moltmann): Read this from PackageInfo once available
var cookie = 0
@@ -76,11 +78,12 @@ class AttributionLabelLiveData private constructor(
// Some resources have multiple "AndroidManifest.xml" loaded and hence we need
// to find the right one
cookie++
- val parser = try {
- pkgContext.assets.openXmlResourceParser(cookie, MANIFEST_FILE_NAME)
- } catch (e: FileNotFoundException) {
- break
- }
+ val parser =
+ try {
+ pkgContext.assets.openXmlResourceParser(cookie, MANIFEST_FILE_NAME)
+ } catch (e: FileNotFoundException) {
+ break
+ }
try {
do {
@@ -109,8 +112,9 @@ class AttributionLabelLiveData private constructor(
}
if (parser.getAttributeValue(ANDROID_NS, TAG_ATTR) == attributionTag) {
- postValue(parser.getAttributeResourceValue(ANDROID_NS, LABEL_ATTR,
- ID_NULL))
+ postValue(
+ parser.getAttributeResourceValue(ANDROID_NS, LABEL_ATTR, ID_NULL)
+ )
return
} else {
parser.skipTag()
@@ -125,9 +129,7 @@ class AttributionLabelLiveData private constructor(
postValue(null)
}
- /**
- * Skip tag parser is currently pointing to (including all tags nested in it)
- */
+ /** Skip tag parser is currently pointing to (including all tags nested in it) */
private fun XmlPullParser.skipTag() {
var depth = 1
while (depth != 0) {
@@ -158,18 +160,25 @@ class AttributionLabelLiveData private constructor(
/**
* Repository for AttributionLiveData.
+ *
* <p> Key value is a pair of string attribution tag, string package name, user handle, value is
* its corresponding LiveData.
*/
- companion object : DataRepository<Triple<String?, String, UserHandle>,
- AttributionLabelLiveData>() {
+ companion object :
+ DataRepository<Triple<String?, String, UserHandle>, AttributionLabelLiveData>() {
override fun newValue(key: Triple<String?, String, UserHandle>): AttributionLabelLiveData {
- return AttributionLabelLiveData(PermissionControllerApplication.get(),
- key.first, key.second, key.third)
+ return AttributionLabelLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second,
+ key.third
+ )
}
- operator fun get(attributionTag: String?, packageName: String, user: UserHandle):
- AttributionLabelLiveData =
- get(Triple(attributionTag, packageName, user))
+ operator fun get(
+ attributionTag: String?,
+ packageName: String,
+ user: UserHandle
+ ): AttributionLabelLiveData = get(Triple(attributionTag, packageName, user))
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/AutoRevokedPackagesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/AutoRevokedPackagesLiveData.kt
index 70f857afb..2e6fab44d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/AutoRevokedPackagesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/AutoRevokedPackagesLiveData.kt
@@ -21,8 +21,8 @@ import android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED
import android.os.Build
import android.os.UserHandle
import android.util.Log
-import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.KotlinUtils
+import com.android.permissioncontroller.permission.utils.PermissionMapping
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
@@ -34,15 +34,13 @@ import kotlinx.coroutines.launch
*
* ```(packageName, user) -> [groupName]```
*/
-object AutoRevokedPackagesLiveData
- : SmartAsyncMediatorLiveData<Map<Pair<String, UserHandle>, Set<String>>>() {
+object AutoRevokedPackagesLiveData :
+ SmartAsyncMediatorLiveData<Map<Pair<String, UserHandle>, Set<String>>>() {
private val LOG_TAG = AutoRevokedPackagesLiveData::class.java.simpleName
init {
- addSource(AllPackageInfosLiveData) {
- update()
- }
+ addSource(AllPackageInfosLiveData) { update() }
}
private val permStateLiveDatas =
@@ -66,7 +64,8 @@ object AutoRevokedPackagesLiveData
for ((idx, requestedPerm) in pkg.requestedPermissions.withIndex()) {
val group =
PermissionMapping.getGroupOfPlatformPermission(requestedPerm) ?: continue
- val granted = (pkg.requestedPermissionsFlags[idx] and
+ val granted =
+ (pkg.requestedPermissionsFlags[idx] and
PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0
if (pkg.targetSdkVersion < Build.VERSION_CODES.M || !granted) {
pkgGroups.add(Triple(pkg.packageName, group, user))
@@ -85,7 +84,6 @@ object AutoRevokedPackagesLiveData
private fun observePermStateLiveDatas(packageGroups: Set<Triple<String, String, UserHandle>>) {
GlobalScope.launch(Main.immediate) {
-
val (toAdd, toRemove) =
KotlinUtils.getMapAndListDifferences(packageGroups, permStateLiveDatas)
@@ -118,7 +116,8 @@ object AutoRevokedPackagesLiveData
} else if (permState != null) {
for ((_, state) in permState) {
if (state.permFlags and FLAG_PERMISSION_AUTO_REVOKED != 0) {
- packageAutoRevokedPermsList.getOrPut(packageUser) { mutableSetOf() }
+ packageAutoRevokedPermsList
+ .getOrPut(packageUser) { mutableSetOf() }
.add(packagePermGroup.second)
added = true
break
@@ -142,8 +141,7 @@ object AutoRevokedPackagesLiveData
}
private fun postCopyOfMap() {
- val autoRevokedCopy =
- mutableMapOf<Pair<String, UserHandle>, Set<String>>()
+ val autoRevokedCopy = mutableMapOf<Pair<String, UserHandle>, Set<String>>()
for ((userPackage, permGroups) in packageAutoRevokedPermsList) {
autoRevokedCopy[userPackage] = permGroups.toSet()
}
@@ -155,9 +153,7 @@ object AutoRevokedPackagesLiveData
private val autoRevokedPackagesSetLiveData =
object : SmartUpdateMediatorLiveData<Set<Pair<String, UserHandle>>>() {
init {
- addSource(AutoRevokedPackagesLiveData) {
- update()
- }
+ addSource(AutoRevokedPackagesLiveData) { update() }
}
override fun onUpdate() {
@@ -168,4 +164,4 @@ private val autoRevokedPackagesSetLiveData =
}
}
-val unusedAutoRevokePackagesLiveData = UnusedPackagesLiveData(autoRevokedPackagesSetLiveData) \ No newline at end of file
+val unusedAutoRevokePackagesLiveData = UnusedPackagesLiveData(autoRevokedPackagesSetLiveData)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/BroadcastReceiverLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/BroadcastReceiverLiveData.kt
index 0a296d977..e14a02115 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/BroadcastReceiverLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/BroadcastReceiverLiveData.kt
@@ -41,9 +41,10 @@ class BroadcastReceiverLiveData(
override val intentAction: String,
private val permission: String,
private val user: UserHandle
-) : SmartAsyncMediatorLiveData<Set<String>>(),
- PackageBroadcastReceiver.PackageBroadcastListener,
- HasIntentAction {
+) :
+ SmartAsyncMediatorLiveData<Set<String>>(),
+ PackageBroadcastReceiver.PackageBroadcastListener,
+ HasIntentAction {
private val name = intentAction.substringAfterLast(".")
@@ -51,9 +52,7 @@ class BroadcastReceiverLiveData(
init {
if (intentAction == DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED) {
- addSource(enabledDeviceAdminsLiveDataLiveData) {
- updateAsync()
- }
+ addSource(enabledDeviceAdminsLiveDataLiveData) { updateAsync() }
}
}
@@ -65,15 +64,20 @@ class BroadcastReceiverLiveData(
if (job.isCancelled) {
return
}
- if (intentAction == DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED &&
- !enabledDeviceAdminsLiveDataLiveData.isInitialized) {
+ if (
+ intentAction == DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED &&
+ !enabledDeviceAdminsLiveDataLiveData.isInitialized
+ ) {
return
}
- val packageNames = getUserContext(app, user).packageManager
+ val packageNames =
+ getUserContext(app, user)
+ .packageManager
.queryBroadcastReceivers(
- Intent(intentAction),
- PackageManager.GET_RECEIVERS or PackageManager.GET_META_DATA)
+ Intent(intentAction),
+ PackageManager.GET_RECEIVERS or PackageManager.GET_META_DATA
+ )
.mapNotNull { resolveInfo ->
if (resolveInfo?.activityInfo?.permission != permission) {
return@mapNotNull null
@@ -81,17 +85,22 @@ class BroadcastReceiverLiveData(
val packageName = resolveInfo.activityInfo?.packageName
if (!isReceiverEnabled(packageName)) {
if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG,
- "Not exempting $packageName - not an active $name " +
- "for u${user.identifier}")
+ DumpableLog.i(
+ LOG_TAG,
+ "Not exempting $packageName - not an active $name " +
+ "for u${user.identifier}"
+ )
}
return@mapNotNull null
}
packageName
- }.toSet()
+ }
+ .toSet()
if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG,
- "Detected ${intentAction.substringAfterLast(".")}s: $packageNames")
+ DumpableLog.i(
+ LOG_TAG,
+ "Detected ${intentAction.substringAfterLast(".")}s: $packageNames"
+ )
}
postValue(packageNames)
@@ -127,13 +136,17 @@ class BroadcastReceiverLiveData(
* <p> Key value is a (string intent action, required permission, user) triple, value is its
* corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<Triple<String, String, UserHandle>,
- BroadcastReceiverLiveData>() {
+ companion object :
+ DataRepositoryForPackage<Triple<String, String, UserHandle>, BroadcastReceiverLiveData>() {
private const val LOG_TAG = "BroadcastReceiverLiveData"
override fun newValue(key: Triple<String, String, UserHandle>): BroadcastReceiverLiveData {
- return BroadcastReceiverLiveData(PermissionControllerApplication.get(),
- key.first, key.second, key.third)
+ return BroadcastReceiverLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second,
+ key.third
+ )
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/CarrierPrivilegedStatusLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/CarrierPrivilegedStatusLiveData.kt
index fae7f223b..d84db741c 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/CarrierPrivilegedStatusLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/CarrierPrivilegedStatusLiveData.kt
@@ -26,10 +26,9 @@ import com.android.permissioncontroller.PermissionControllerApplication
* @param app The current application
* @param packageName The name of the package
*/
-class CarrierPrivilegedStatusLiveData private constructor(
- private val app: Application,
- private val packageName: String
-) : SmartUpdateMediatorLiveData<Int>() {
+class CarrierPrivilegedStatusLiveData
+private constructor(private val app: Application, private val packageName: String) :
+ SmartUpdateMediatorLiveData<Int>() {
private val telephonyManager = app.getSystemService(TelephonyManager::class.java)!!
@@ -44,13 +43,13 @@ class CarrierPrivilegedStatusLiveData private constructor(
/**
* Repository for [CarrierPrivilegedStatusLiveData].
+ *
* <p> Key value is a package name, value is its corresponding LiveData of
* [android.telephony.Annotation.CarrierPrivilegeStatus]
*/
- companion object
- : DataRepository<String, CarrierPrivilegedStatusLiveData>() {
+ companion object : DataRepository<String, CarrierPrivilegedStatusLiveData>() {
override fun newValue(key: String): CarrierPrivilegedStatusLiveData {
return CarrierPrivilegedStatusLiveData(PermissionControllerApplication.get(), key)
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/CustomPermGroupNamesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/CustomPermGroupNamesLiveData.kt
index cb44c0a27..757472464 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/CustomPermGroupNamesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/CustomPermGroupNamesLiveData.kt
@@ -24,7 +24,6 @@ import com.android.permissioncontroller.permission.utils.PermissionMapping
/**
* A class which tracks the names of all custom permission groups in the system, including
* non-grouped runtime permissions, the UNDEFINED group, and any group not defined by the system.
- *
*/
object CustomPermGroupNamesLiveData : SmartUpdateMediatorLiveData<List<String>>() {
@@ -32,9 +31,7 @@ object CustomPermGroupNamesLiveData : SmartUpdateMediatorLiveData<List<String>>(
private val packagesLiveData = AllPackageInfosLiveData
init {
- addSource(packagesLiveData) {
- update()
- }
+ addSource(packagesLiveData) { update() }
}
override fun onUpdate() {
@@ -49,15 +46,19 @@ object CustomPermGroupNamesLiveData : SmartUpdateMediatorLiveData<List<String>>(
packageInfo.permissions.let {
for (permission in it) {
// We care only about installed runtime permissions.
- if (permission.protection != PermissionInfo.PROTECTION_DANGEROUS ||
- permission.flags and PermissionInfo.FLAG_INSTALLED == 0) {
+ if (
+ permission.protection != PermissionInfo.PROTECTION_DANGEROUS ||
+ permission.flags and PermissionInfo.FLAG_INSTALLED == 0
+ ) {
continue
}
// If this permission is already in a group, no more work to do
- if (groupNames.contains(permission.group) ||
- platformGroupNames.contains(permission.group) ||
- groupNames.contains(permission.name)) {
+ if (
+ groupNames.contains(permission.group) ||
+ platformGroupNames.contains(permission.group) ||
+ groupNames.contains(permission.name)
+ ) {
continue
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/DataRepository.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/DataRepository.kt
index 5cb91f5c5..c6c4ec2d6 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/DataRepository.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/DataRepository.kt
@@ -39,18 +39,16 @@ abstract class DataRepository<K, V : DataRepository.InactiveTimekeeper> : Compon
private val TIME_THRESHOLD_ALL_NANOS: Long = 0
protected val lock = Any()
- @GuardedBy("lock")
- protected val data = mutableMapOf<K, V>()
+ @GuardedBy("lock") protected val data = mutableMapOf<K, V>()
- /**
- * Whether or not this data repository has been registered as a component callback yet
- */
+ /** Whether or not this data repository has been registered as a component callback yet */
private var registered = false
- /**
- * Whether or not this device is a low-RAM device.
- */
- private var isLowMemoryDevice = PermissionControllerApplication.get().getSystemService(
- ActivityManager::class.java)?.isLowRamDevice ?: false
+ /** Whether or not this device is a low-RAM device. */
+ private var isLowMemoryDevice =
+ PermissionControllerApplication.get()
+ .getSystemService(ActivityManager::class.java)
+ ?.isLowRamDevice
+ ?: false
init {
PermissionControllerApplication.get().registerComponentCallbacks(this)
@@ -60,7 +58,6 @@ abstract class DataRepository<K, V : DataRepository.InactiveTimekeeper> : Compon
* Get a value from this repository, creating it if needed
*
* @param key The key associated with the desired Value
- *
* @return The cached or newly created Value for the given Key
*/
operator fun get(key: K): V {
@@ -73,11 +70,9 @@ abstract class DataRepository<K, V : DataRepository.InactiveTimekeeper> : Compon
* Generate a new value type from the given data
*
* @param key Information about this value object, used to instantiate it
- *
* @return The generated Value
*/
- @MainThread
- protected abstract fun newValue(key: K): V
+ @MainThread protected abstract fun newValue(key: K): V
/**
* Remove LiveData objects with no observer based on the severity of the memory pressure. If
@@ -91,15 +86,18 @@ abstract class DataRepository<K, V : DataRepository.InactiveTimekeeper> : Compon
return
}
- trimInactiveData(threshold = when (level) {
- ComponentCallbacks2.TRIM_MEMORY_BACKGROUND -> TIME_THRESHOLD_LAX_NANOS
- ComponentCallbacks2.TRIM_MEMORY_MODERATE -> TIME_THRESHOLD_TIGHT_NANOS
- ComponentCallbacks2.TRIM_MEMORY_COMPLETE -> TIME_THRESHOLD_ALL_NANOS
- ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE -> TIME_THRESHOLD_LAX_NANOS
- ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW -> TIME_THRESHOLD_TIGHT_NANOS
- ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL -> TIME_THRESHOLD_ALL_NANOS
- else -> return
- })
+ trimInactiveData(
+ threshold =
+ when (level) {
+ ComponentCallbacks2.TRIM_MEMORY_BACKGROUND -> TIME_THRESHOLD_LAX_NANOS
+ ComponentCallbacks2.TRIM_MEMORY_MODERATE -> TIME_THRESHOLD_TIGHT_NANOS
+ ComponentCallbacks2.TRIM_MEMORY_COMPLETE -> TIME_THRESHOLD_ALL_NANOS
+ ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE -> TIME_THRESHOLD_LAX_NANOS
+ ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW -> TIME_THRESHOLD_TIGHT_NANOS
+ ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL -> TIME_THRESHOLD_ALL_NANOS
+ else -> return
+ }
+ )
}
override fun onLowMemory() {
@@ -111,9 +109,7 @@ abstract class DataRepository<K, V : DataRepository.InactiveTimekeeper> : Compon
}
fun invalidateSingle(key: K) {
- synchronized(lock) {
- data.remove(key)
- }
+ synchronized(lock) { data.remove(key) }
}
private fun trimInactiveData(threshold: Long) {
@@ -127,8 +123,8 @@ abstract class DataRepository<K, V : DataRepository.InactiveTimekeeper> : Compon
}
/**
- * Interface which describes an object which can track how long it has been inactive, and if
- * it has any observers.
+ * Interface which describes an object which can track how long it has been inactive, and if it
+ * has any observers.
*/
interface InactiveTimekeeper {
@@ -156,8 +152,8 @@ abstract class DataRepository<K, V : DataRepository.InactiveTimekeeper> : Compon
* invalidating all values tied to a package. Expects key to be a pair or triple, with the package
* name as the first value of the key.
*/
-abstract class DataRepositoryForPackage<K, V : DataRepository.InactiveTimekeeper>
- : DataRepository<K, V>() {
+abstract class DataRepositoryForPackage<K, V : DataRepository.InactiveTimekeeper> :
+ DataRepository<K, V>() {
/**
* Invalidates every value with the packageName in the key.
@@ -175,9 +171,7 @@ abstract class DataRepositoryForPackage<K, V : DataRepository.InactiveTimekeeper
}
}
-/**
- * A convenience to retrieve data from a repository with a composite key
- */
+/** A convenience to retrieve data from a repository with a composite key */
operator fun <K1, K2, V : DataRepository.InactiveTimekeeper> DataRepository<Pair<K1, K2>, V>.get(
k1: K1,
k2: K2
@@ -185,14 +179,10 @@ operator fun <K1, K2, V : DataRepository.InactiveTimekeeper> DataRepository<Pair
return get(k1 to k2)
}
-/**
- * A convenience to retrieve data from a repository with a composite key
- */
-operator fun <K1, K2, K3, V : DataRepository.InactiveTimekeeper>
- DataRepository<Triple<K1, K2, K3>, V>.get(
- k1: K1,
- k2: K2,
- k3: K3
- ): V {
+/** A convenience to retrieve data from a repository with a composite key */
+operator fun <K1, K2, K3, V : DataRepository.InactiveTimekeeper> DataRepository<
+ Triple<K1, K2, K3>, V
+>
+ .get(k1: K1, k2: K2, k3: K3): V {
return get(Triple(k1, k2, k3))
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/DisabledPrintServicesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/DisabledPrintServicesLiveData.kt
index 3abb20564..4d9c2574b 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/DisabledPrintServicesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/DisabledPrintServicesLiveData.kt
@@ -30,28 +30,26 @@ import kotlinx.coroutines.Job
* @param app The current application
* @param user The user the services should be determined for
*/
-class DisabledPrintServicesLiveData(
- private val app: Application,
- private val user: UserHandle
-) : SmartAsyncMediatorLiveData<List<String>>() {
+class DisabledPrintServicesLiveData(private val app: Application, private val user: UserHandle) :
+ SmartAsyncMediatorLiveData<List<String>>() {
override suspend fun loadDataAndPostValue(job: Job) {
if (job.isCancelled) {
return
}
- val packageNames = Settings.Secure.getString(
- Utils.getUserContext(app, user).contentResolver, SETTING)
+ val packageNames =
+ Settings.Secure.getString(Utils.getUserContext(app, user).contentResolver, SETTING)
?.split(":")
?.map { pkgOrComponent ->
if ('/' in pkgOrComponent) {
- ComponentName.unflattenFromString(pkgOrComponent)
- ?.packageName
- ?: pkgOrComponent
+ ComponentName.unflattenFromString(pkgOrComponent)?.packageName
+ ?: pkgOrComponent
} else {
pkgOrComponent
}
- } ?: emptyList()
+ }
+ ?: emptyList()
postValue(packageNames)
}
@@ -61,8 +59,7 @@ class DisabledPrintServicesLiveData(
*
* <p> Key value is a user, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<UserHandle,
- DisabledPrintServicesLiveData>() {
+ companion object : DataRepositoryForPackage<UserHandle, DisabledPrintServicesLiveData>() {
/* Settings.Secure.DISABLED_PRINT_SERVICES */
private const val SETTING = "disabled_print_services"
@@ -70,4 +67,4 @@ class DisabledPrintServicesLiveData(
return DisabledPrintServicesLiveData(PermissionControllerApplication.get(), key)
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledAccessibilityServicesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledAccessibilityServicesLiveData.kt
index 2b1391a98..9717d949c 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledAccessibilityServicesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledAccessibilityServicesLiveData.kt
@@ -21,8 +21,8 @@ import android.app.Application
import android.os.UserHandle
import android.view.accessibility.AccessibilityManager
import com.android.permissioncontroller.PermissionControllerApplication
-import com.android.permissioncontroller.permission.utils.componentInfo
import com.android.permissioncontroller.permission.utils.Utils
+import com.android.permissioncontroller.permission.utils.componentInfo
import kotlinx.coroutines.Job
/**
@@ -42,7 +42,8 @@ class EnabledAccessibilityServicesLiveData(
return
}
- val packageNames = Utils.getUserContext(app, user)
+ val packageNames =
+ Utils.getUserContext(app, user)
.getSystemService(AccessibilityManager::class.java)!!
.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK)
.map { info: AccessibilityServiceInfo ->
@@ -62,10 +63,10 @@ class EnabledAccessibilityServicesLiveData(
*
* <p> Key value is a user, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<UserHandle,
- EnabledAccessibilityServicesLiveData>() {
+ companion object :
+ DataRepositoryForPackage<UserHandle, EnabledAccessibilityServicesLiveData>() {
override fun newValue(key: UserHandle): EnabledAccessibilityServicesLiveData {
return EnabledAccessibilityServicesLiveData(PermissionControllerApplication.get(), key)
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledDeviceAdminsLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledDeviceAdminsLiveData.kt
index 60dcf59b0..eebcac06f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledDeviceAdminsLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledDeviceAdminsLiveData.kt
@@ -29,17 +29,16 @@ import kotlinx.coroutines.Job
* @param app The current application
* @param user The user the services should be determined for
*/
-class EnabledDeviceAdminsLiveData(
- private val app: Application,
- private val user: UserHandle
-) : SmartAsyncMediatorLiveData<List<String>>() {
+class EnabledDeviceAdminsLiveData(private val app: Application, private val user: UserHandle) :
+ SmartAsyncMediatorLiveData<List<String>>() {
override suspend fun loadDataAndPostValue(job: Job) {
if (job.isCancelled) {
return
}
- val packageNames = Utils.getUserContext(app, user)
+ val packageNames =
+ Utils.getUserContext(app, user)
.getSystemService(DevicePolicyManager::class.java)!!
.activeAdmins
?.map { component -> component.packageName }
@@ -53,10 +52,9 @@ class EnabledDeviceAdminsLiveData(
*
* <p> Key value is a user, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<UserHandle,
- EnabledDeviceAdminsLiveData>() {
+ companion object : DataRepositoryForPackage<UserHandle, EnabledDeviceAdminsLiveData>() {
override fun newValue(key: UserHandle): EnabledDeviceAdminsLiveData {
return EnabledDeviceAdminsLiveData(PermissionControllerApplication.get(), key)
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledDreamServicesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledDreamServicesLiveData.kt
index 200384aab..9b8554e80 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledDreamServicesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledDreamServicesLiveData.kt
@@ -30,28 +30,26 @@ import kotlinx.coroutines.Job
* @param app The current application
* @param user The user the services should be determined for
*/
-class EnabledDreamServicesLiveData(
- private val app: Application,
- private val user: UserHandle
-) : SmartAsyncMediatorLiveData<List<String>>() {
+class EnabledDreamServicesLiveData(private val app: Application, private val user: UserHandle) :
+ SmartAsyncMediatorLiveData<List<String>>() {
override suspend fun loadDataAndPostValue(job: Job) {
if (job.isCancelled) {
return
}
- val packageNames = Settings.Secure.getString(
- Utils.getUserContext(app, user).contentResolver, SETTING)
+ val packageNames =
+ Settings.Secure.getString(Utils.getUserContext(app, user).contentResolver, SETTING)
?.split(",")
?.map { pkgOrComponent ->
if ('/' in pkgOrComponent) {
- ComponentName.unflattenFromString(pkgOrComponent)
- ?.packageName
- ?: pkgOrComponent
+ ComponentName.unflattenFromString(pkgOrComponent)?.packageName
+ ?: pkgOrComponent
} else {
pkgOrComponent
}
- } ?: emptyList()
+ }
+ ?: emptyList()
postValue(packageNames)
}
@@ -61,8 +59,7 @@ class EnabledDreamServicesLiveData(
*
* <p> Key value is a user, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<UserHandle,
- EnabledDreamServicesLiveData>() {
+ companion object : DataRepositoryForPackage<UserHandle, EnabledDreamServicesLiveData>() {
/* Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */
private const val SETTING = "enabled_notification_listeners"
@@ -70,4 +67,4 @@ class EnabledDreamServicesLiveData(
return EnabledDreamServicesLiveData(PermissionControllerApplication.get(), key)
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledInputMethodsLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledInputMethodsLiveData.kt
index d0d2783ab..e48c432d8 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledInputMethodsLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledInputMethodsLiveData.kt
@@ -30,22 +30,19 @@ import kotlinx.coroutines.Job
* @param app The current application
* @param user The user the services should be determined for
*/
-class EnabledInputMethodsLiveData(
- private val app: Application,
- private val user: UserHandle
-) : SmartAsyncMediatorLiveData<List<String>>() {
+class EnabledInputMethodsLiveData(private val app: Application, private val user: UserHandle) :
+ SmartAsyncMediatorLiveData<List<String>>() {
override suspend fun loadDataAndPostValue(job: Job) {
if (job.isCancelled) {
return
}
- val packageNames = Utils.getUserContext(app, user)
+ val packageNames =
+ Utils.getUserContext(app, user)
.getSystemService(InputMethodManager::class.java)!!
.enabledInputMethodList
- .map { info: InputMethodInfo ->
- info.component.packageName
- }
+ .map { info: InputMethodInfo -> info.component.packageName }
postValue(packageNames)
}
@@ -55,10 +52,9 @@ class EnabledInputMethodsLiveData(
*
* <p> Key value is a user, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<UserHandle,
- EnabledInputMethodsLiveData>() {
+ companion object : DataRepositoryForPackage<UserHandle, EnabledInputMethodsLiveData>() {
override fun newValue(key: UserHandle): EnabledInputMethodsLiveData {
return EnabledInputMethodsLiveData(PermissionControllerApplication.get(), key)
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledNotificationListenersLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledNotificationListenersLiveData.kt
index f5c5d4bf1..7dd1567e4 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledNotificationListenersLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/EnabledNotificationListenersLiveData.kt
@@ -40,20 +40,22 @@ class EnabledNotificationListenersLiveData(
return
}
- val packageNames = Settings.Secure.getString(
- Utils.getUserContext(app, user).contentResolver,
- /* Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */
- "enabled_notification_listeners")
+ val packageNames =
+ Settings.Secure.getString(
+ Utils.getUserContext(app, user).contentResolver,
+ /* Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */
+ "enabled_notification_listeners"
+ )
?.split(":")
?.map { pkgOrComponent ->
if ('/' in pkgOrComponent) {
- ComponentName.unflattenFromString(pkgOrComponent)
- ?.packageName
- ?: pkgOrComponent
+ ComponentName.unflattenFromString(pkgOrComponent)?.packageName
+ ?: pkgOrComponent
} else {
pkgOrComponent
}
- } ?: emptyList()
+ }
+ ?: emptyList()
postValue(packageNames)
}
@@ -63,10 +65,10 @@ class EnabledNotificationListenersLiveData(
*
* <p> Key value is a user, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<UserHandle,
- EnabledNotificationListenersLiveData>() {
+ companion object :
+ DataRepositoryForPackage<UserHandle, EnabledNotificationListenersLiveData>() {
override fun newValue(key: UserHandle): EnabledNotificationListenersLiveData {
return EnabledNotificationListenersLiveData(PermissionControllerApplication.get(), key)
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/ForegroundPermNamesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/ForegroundPermNamesLiveData.kt
index 1471ed15f..513f5fc4e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/ForegroundPermNamesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/ForegroundPermNamesLiveData.kt
@@ -39,11 +39,12 @@ object ForegroundPermNamesLiveData : SmartAsyncMediatorLiveData<Map<String, List
val systemGroups = PermissionMapping.getPlatformPermissionGroups()
val permMap = mutableMapOf<String, MutableList<String>>()
for (groupName in systemGroups) {
- val permInfos = try {
- Utils.getInstalledRuntimePermissionInfosForGroup(app.packageManager, groupName)
- } catch (e: PackageManager.NameNotFoundException) {
- continue
- }
+ val permInfos =
+ try {
+ Utils.getInstalledRuntimePermissionInfosForGroup(app.packageManager, groupName)
+ } catch (e: PackageManager.NameNotFoundException) {
+ continue
+ }
for (permInfo in permInfos) {
val backgroundPerm: String? = permInfo.backgroundPermission
if (backgroundPerm != null) {
@@ -54,4 +55,4 @@ object ForegroundPermNamesLiveData : SmartAsyncMediatorLiveData<Map<String, List
}
postValue(permMap)
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/FullStoragePermissionAppsLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/FullStoragePermissionAppsLiveData.kt
index 0b27dbff0..4a2d3b68a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/FullStoragePermissionAppsLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/FullStoragePermissionAppsLiveData.kt
@@ -34,14 +34,13 @@ import kotlinx.coroutines.Job
/**
* A liveData which tracks all packages in the system which have full file permissions, as
* represented by the OPSTR_LEGACY_STORAGE app op, not just media-only storage permissions.
- *
*/
object FullStoragePermissionAppsLiveData :
SmartAsyncMediatorLiveData<List<FullStoragePermissionAppsLiveData.FullStoragePackageState>>() {
private val app: Application = PermissionControllerApplication.get()
- private val standardPermGroupsPackagesLiveData = PermGroupsPackagesLiveData.get(
- customGroups = false)
+ private val standardPermGroupsPackagesLiveData =
+ PermGroupsPackagesLiveData.get(customGroups = false)
data class FullStoragePackageState(
val packageName: String,
@@ -51,12 +50,8 @@ object FullStoragePermissionAppsLiveData :
)
init {
- addSource(standardPermGroupsPackagesLiveData) {
- updateAsync()
- }
- addSource(AllPackageInfosLiveData) {
- updateAsync()
- }
+ addSource(standardPermGroupsPackagesLiveData) { updateAsync() }
+ addSource(AllPackageInfosLiveData) { updateAsync() }
}
override suspend fun loadDataAndPostValue(job: Job) {
@@ -65,14 +60,16 @@ object FullStoragePermissionAppsLiveData :
val fullStoragePackages = mutableListOf<FullStoragePackageState>()
for ((user, packageInfoList) in AllPackageInfosLiveData.value ?: emptyMap()) {
- val userPackages = packageInfoList.filter {
- storagePackages.contains(it.packageName to user) ||
- it.requestedPermissions.contains(MANAGE_EXTERNAL_STORAGE)
- }
+ val userPackages =
+ packageInfoList.filter {
+ storagePackages.contains(it.packageName to user) ||
+ it.requestedPermissions.contains(MANAGE_EXTERNAL_STORAGE)
+ }
for (packageInfo in userPackages) {
- fullStoragePackages.add(getFullStorageStateForPackage(appOpsManager,
- packageInfo, user) ?: continue)
+ fullStoragePackages.add(
+ getFullStorageStateForPackage(appOpsManager, packageInfo, user) ?: continue
+ )
}
}
@@ -85,9 +82,8 @@ object FullStoragePermissionAppsLiveData :
* @param appOpsManager The App Ops manager to use, if applicable
* @param packageInfo The package whose state is to be determined
* @param userHandle A preexisting UserHandle object to use. Otherwise, one will be created
- *
* @return the FullStoragePackageState for the package, or null if the package does not request
- * full storage permissions
+ * full storage permissions
*/
fun getFullStorageStateForPackage(
appOpsManager: AppOpsManager,
@@ -97,31 +93,51 @@ object FullStoragePermissionAppsLiveData :
val sdk = packageInfo.targetSdkVersion
val user = userHandle ?: UserHandle.getUserHandleForUid(packageInfo.uid)
if (sdk < Build.VERSION_CODES.P) {
- return FullStoragePackageState(packageInfo.packageName, user,
- isLegacy = true, isGranted = true)
- } else if (sdk <= Build.VERSION_CODES.Q &&
- appOpsManager.unsafeCheckOpNoThrow(OPSTR_LEGACY_STORAGE, packageInfo.uid,
- packageInfo.packageName) == MODE_ALLOWED) {
- return FullStoragePackageState(packageInfo.packageName, user,
- isLegacy = true, isGranted = true)
+ return FullStoragePackageState(
+ packageInfo.packageName,
+ user,
+ isLegacy = true,
+ isGranted = true
+ )
+ } else if (
+ sdk <= Build.VERSION_CODES.Q &&
+ appOpsManager.unsafeCheckOpNoThrow(
+ OPSTR_LEGACY_STORAGE,
+ packageInfo.uid,
+ packageInfo.packageName
+ ) == MODE_ALLOWED
+ ) {
+ return FullStoragePackageState(
+ packageInfo.packageName,
+ user,
+ isLegacy = true,
+ isGranted = true
+ )
}
if (MANAGE_EXTERNAL_STORAGE in packageInfo.requestedPermissions) {
- val mode = appOpsManager.unsafeCheckOpNoThrow(OPSTR_MANAGE_EXTERNAL_STORAGE,
- packageInfo.uid, packageInfo.packageName)
- val granted = mode == MODE_ALLOWED || mode == MODE_FOREGROUND ||
- (mode == MODE_DEFAULT &&
- MANAGE_EXTERNAL_STORAGE in packageInfo.grantedPermissions)
- return FullStoragePackageState(packageInfo.packageName, user,
- isLegacy = false, isGranted = granted)
+ val mode =
+ appOpsManager.unsafeCheckOpNoThrow(
+ OPSTR_MANAGE_EXTERNAL_STORAGE,
+ packageInfo.uid,
+ packageInfo.packageName
+ )
+ val granted =
+ mode == MODE_ALLOWED ||
+ mode == MODE_FOREGROUND ||
+ (mode == MODE_DEFAULT &&
+ MANAGE_EXTERNAL_STORAGE in packageInfo.grantedPermissions)
+ return FullStoragePackageState(
+ packageInfo.packageName,
+ user,
+ isLegacy = false,
+ isGranted = granted
+ )
}
return null
}
- /**
- * Recalculate the LiveData
- * TODO ntmyren: Make livedata properly observe app ops
- */
+ /** Recalculate the LiveData TODO ntmyren: Make livedata properly observe app ops */
fun recalculate() {
updateAsync()
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/HasIntentAction.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/HasIntentAction.kt
index 91557e441..1c0325ec6 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/HasIntentAction.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/HasIntentAction.kt
@@ -16,9 +16,7 @@
package com.android.permissioncontroller.permission.data
-/**
- * An interface for classes that have an [Intent] action
- */
+/** An interface for classes that have an [Intent] action */
interface HasIntentAction {
val intentAction: String
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/HibernatedPackagesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/HibernatedPackagesLiveData.kt
index 887998a2e..9fdb8411a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/HibernatedPackagesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/HibernatedPackagesLiveData.kt
@@ -25,17 +25,12 @@ import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.permission.utils.Utils.getUserContext
import kotlinx.coroutines.Job
-/**
- * Tracks which packages have been hibernated.
- */
-object HibernatedPackagesLiveData
- : SmartAsyncMediatorLiveData<Set<Pair<String, UserHandle>>>() {
+/** Tracks which packages have been hibernated. */
+object HibernatedPackagesLiveData : SmartAsyncMediatorLiveData<Set<Pair<String, UserHandle>>>() {
private val LOG_TAG = HibernatedPackagesLiveData::class.java.simpleName
init {
- addSource(AllPackageInfosLiveData) {
- update()
- }
+ addSource(AllPackageInfosLiveData) { update() }
}
override suspend fun loadDataAndPostValue(job: Job) {
@@ -57,8 +52,10 @@ object HibernatedPackagesLiveData
hibernatingPackages.add(pkg.packageName to user)
}
} catch (e: Exception) {
- DumpableLog.e(LOG_TAG,
- "Failed to get hibernation state of package: ${pkg.packageName}")
+ DumpableLog.e(
+ LOG_TAG,
+ "Failed to get hibernation state of package: ${pkg.packageName}"
+ )
}
}
}
@@ -69,25 +66,23 @@ object HibernatedPackagesLiveData
}
}
-private val hibernatedOrRevokedPackagesLiveData = object
- : SmartUpdateMediatorLiveData<Set<Pair<String, UserHandle>>>() {
+private val hibernatedOrRevokedPackagesLiveData =
+ object : SmartUpdateMediatorLiveData<Set<Pair<String, UserHandle>>>() {
- init {
- addSource(AutoRevokedPackagesLiveData) {
- update()
- }
- addSource(HibernatedPackagesLiveData) {
- update()
+ init {
+ addSource(AutoRevokedPackagesLiveData) { update() }
+ addSource(HibernatedPackagesLiveData) { update() }
}
- }
- override fun onUpdate() {
- if (!AutoRevokedPackagesLiveData.isInitialized ||
- !HibernatedPackagesLiveData.isInitialized) {
- return
+ override fun onUpdate() {
+ if (
+ !AutoRevokedPackagesLiveData.isInitialized ||
+ !HibernatedPackagesLiveData.isInitialized
+ ) {
+ return
+ }
+ value = AutoRevokedPackagesLiveData.value!!.keys + HibernatedPackagesLiveData.value!!
}
- value = AutoRevokedPackagesLiveData.value!!.keys + HibernatedPackagesLiveData.value!!
}
-}
val unusedHibernatedOrRevokedPackagesLiveData =
- UnusedPackagesLiveData(hibernatedOrRevokedPackagesLiveData) \ No newline at end of file
+ UnusedPackagesLiveData(hibernatedOrRevokedPackagesLiveData)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt
index 606562641..75d965d02 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt
@@ -34,6 +34,7 @@ import com.android.permissioncontroller.hibernation.isPackageHibernationExemptBy
import com.android.permissioncontroller.hibernation.isPackageHibernationExemptByUser
import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData.Companion.NON_RUNTIME_NORMAL_PERMS
import com.android.permissioncontroller.permission.model.livedatatypes.HibernationSettingState
+import com.android.permissioncontroller.permission.service.AUTO_REVOKE_EXEMPT_PERMISSIONS
import kotlinx.coroutines.Job
/**
@@ -43,14 +44,14 @@ import kotlinx.coroutines.Job
* @param packageName The package name whose state we want
* @param user The user for whom we want the package
*/
-class HibernationSettingStateLiveData private constructor(
+class HibernationSettingStateLiveData
+private constructor(
private val app: Application,
private val packageName: String,
private val user: UserHandle
) : SmartAsyncMediatorLiveData<HibernationSettingState>(), AppOpsManager.OnOpChangedListener {
- private val packagePermsLiveData =
- PackagePermissionsLiveData[packageName, user]
+ private val packagePermsLiveData = PackagePermissionsLiveData[packageName, user]
private val packageLiveData = LightPackageInfoLiveData[packageName, user]
private val permStateLiveDatas = mutableMapOf<String, PermStateLiveData>()
private val exemptServicesLiveData = ExemptServicesLiveData[user]
@@ -64,26 +65,19 @@ class HibernationSettingStateLiveData private constructor(
private var gotPastIsSystemExempt: Boolean = false
init {
- addSource(packagePermsLiveData) {
- update()
- }
- addSource(packageLiveData) {
- update()
- }
- addSource(exemptServicesLiveData) {
- update()
- }
- addSource(HibernationEnabledLiveData) {
- update()
- }
- Handler(app.mainLooper).postDelayed({
- logState()
- }, DELAY_MS)
+ addSource(packagePermsLiveData) { update() }
+ addSource(packageLiveData) { update() }
+ addSource(exemptServicesLiveData) { update() }
+ addSource(HibernationEnabledLiveData) { update() }
+ Handler(app.mainLooper).postDelayed({ logState() }, DELAY_MS)
}
override suspend fun loadDataAndPostValue(job: Job) {
- if (!packageLiveData.isInitialized || !packagePermsLiveData.isInitialized ||
- !exemptServicesLiveData.isInitialized) {
+ if (
+ !packageLiveData.isInitialized ||
+ !packagePermsLiveData.isInitialized ||
+ !exemptServicesLiveData.isInitialized
+ ) {
return
}
@@ -103,21 +97,30 @@ class HibernationSettingStateLiveData private constructor(
val exemptBySystem = isPackageHibernationExemptBySystem(packageInfo, user)
val exemptByUser = isPackageHibernationExemptByUser(app, packageInfo)
- val eligibility = when {
- !exemptBySystem && !exemptByUser -> HIBERNATION_ELIGIBILITY_ELIGIBLE
- exemptBySystem -> HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM
- else -> HIBERNATION_ELIGIBILITY_EXEMPT_BY_USER
- }
+ val eligibility =
+ when {
+ !exemptBySystem && !exemptByUser -> HIBERNATION_ELIGIBILITY_ELIGIBLE
+ exemptBySystem -> HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM
+ else -> HIBERNATION_ELIGIBILITY_EXEMPT_BY_USER
+ }
gotPastIsUserExempt = true
val revocableGroups = mutableListOf<String>()
if (!isPackageHibernationExemptBySystem(packageInfo, user)) {
gotPastIsSystemExempt = true
permStateLiveDatas.forEach { (groupName, liveData) ->
- val default = liveData.value?.any { (_, permState) ->
- permState.permFlags and (FLAG_PERMISSION_GRANTED_BY_DEFAULT or
- FLAG_PERMISSION_GRANTED_BY_ROLE) != 0
- } ?: false
- if (!default) {
+ val default =
+ liveData.value?.any { (_, permState) ->
+ permState.permFlags and
+ (FLAG_PERMISSION_GRANTED_BY_DEFAULT or
+ FLAG_PERMISSION_GRANTED_BY_ROLE) != 0
+ }
+ ?: false
+ val allExempt =
+ liveData.value?.all { (permName, _) ->
+ permName in AUTO_REVOKE_EXEMPT_PERMISSIONS
+ }
+ ?: false
+ if (!default && !allExempt) {
revocableGroups.add(groupName)
}
}
@@ -148,29 +151,45 @@ class HibernationSettingStateLiveData private constructor(
if (!isStale) {
return
}
- Log.i(LOG_TAG, "overall state: isStale:$isStale, isInitialized:$isInitialized, " +
+ Log.i(
+ LOG_TAG,
+ "overall state: isStale:$isStale, isInitialized:$isInitialized, " +
"value:$value, got perm LiveDatas:$gotPermLiveDatas, " +
- "got isUserExempt$gotPastIsUserExempt, got isSystemExempt$gotPastIsSystemExempt")
- Log.i(LOG_TAG, "packagePermsLivedata isStale:${packagePermsLiveData.isStale}, " +
- "isInitialized:${packagePermsLiveData.isInitialized}")
- Log.i(LOG_TAG, "ExemptServicesLiveData isStale:${exemptServicesLiveData.isStale}, " +
- "isInitialized:${exemptServicesLiveData.isInitialized}")
+ "got isUserExempt$gotPastIsUserExempt, got isSystemExempt$gotPastIsSystemExempt"
+ )
+ Log.i(
+ LOG_TAG,
+ "packagePermsLivedata isStale:${packagePermsLiveData.isStale}, " +
+ "isInitialized:${packagePermsLiveData.isInitialized}"
+ )
+ Log.i(
+ LOG_TAG,
+ "ExemptServicesLiveData isStale:${exemptServicesLiveData.isStale}, " +
+ "isInitialized:${exemptServicesLiveData.isInitialized}"
+ )
Log.i(LOG_TAG, "HibernationEnabledLivedata value:${HibernationEnabledLiveData.value}")
for ((group, liveData) in permStateLiveDatas) {
- Log.i(LOG_TAG, "permStateLivedata $group isStale:${liveData.isStale}, " +
- "isInitialized:${liveData.isInitialized}")
+ Log.i(
+ LOG_TAG,
+ "permStateLivedata $group isStale:${liveData.isStale}, " +
+ "isInitialized:${liveData.isInitialized}"
+ )
}
}
/**
* Repository for HibernationSettingStateLiveDatas.
+ *
* <p> Key value is a pair of string package name and UserHandle, value is its corresponding
* LiveData.
*/
- companion object : DataRepositoryForPackage<Pair<String, UserHandle>,
- HibernationSettingStateLiveData>() {
+ companion object :
+ DataRepositoryForPackage<Pair<String, UserHandle>, HibernationSettingStateLiveData>() {
override fun newValue(key: Pair<String, UserHandle>): HibernationSettingStateLiveData {
- return HibernationSettingStateLiveData(PermissionControllerApplication.get(),
- key.first, key.second)
+ return HibernationSettingStateLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/LauncherPackagesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/LauncherPackagesLiveData.kt
index b512c7e4a..94bf230d7 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/LauncherPackagesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/LauncherPackagesLiveData.kt
@@ -18,39 +18,43 @@
package com.android.permissioncontroller.permission.data
import android.content.Intent
+import android.content.pm.PackageManager.FEATURE_LEANBACK
import android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE
import android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE
-import android.content.pm.PackageManager.FEATURE_LEANBACK
import com.android.permissioncontroller.PermissionControllerApplication
import kotlinx.coroutines.Job
-/**
- * A livedata which stores a list of package names of packages which have launcher icons.
- */
-object LauncherPackagesLiveData : SmartAsyncMediatorLiveData<Set<String>>(),
- PackageBroadcastReceiver.PackageBroadcastListener {
+/** A livedata which stores a list of package names of packages which have launcher icons. */
+object LauncherPackagesLiveData :
+ SmartAsyncMediatorLiveData<Set<String>>(), PackageBroadcastReceiver.PackageBroadcastListener {
- private val LAUNCHER_INTENT = Intent(Intent.ACTION_MAIN, null)
- .addCategory(Intent.CATEGORY_LAUNCHER)
+ private val LAUNCHER_INTENT =
+ Intent(Intent.ACTION_MAIN, null).addCategory(Intent.CATEGORY_LAUNCHER)
// On ATV some apps may have a leanback launcher icon but no regular launcher icon
- private val LEANBACK_LAUNCHER_INTENT = Intent(Intent.ACTION_MAIN, null)
- .addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER)
+ private val LEANBACK_LAUNCHER_INTENT =
+ Intent(Intent.ACTION_MAIN, null).addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER)
override suspend fun loadDataAndPostValue(job: Job) {
val launcherPkgs = mutableSetOf<String>()
loadPkgsFromIntent(launcherPkgs, LAUNCHER_INTENT)
- if (PermissionControllerApplication.get().packageManager
- .hasSystemFeature(FEATURE_LEANBACK)) {
+ if (
+ PermissionControllerApplication.get().packageManager.hasSystemFeature(FEATURE_LEANBACK)
+ ) {
loadPkgsFromIntent(launcherPkgs, LEANBACK_LAUNCHER_INTENT)
}
postValue(launcherPkgs)
}
private fun loadPkgsFromIntent(launcherPkgs: MutableSet<String>, intent: Intent) {
- for (info in PermissionControllerApplication.get().packageManager.queryIntentActivities(
- intent, MATCH_DIRECT_BOOT_AWARE or MATCH_DIRECT_BOOT_UNAWARE)) {
+ for (info in
+ PermissionControllerApplication.get()
+ .packageManager
+ .queryIntentActivities(
+ intent,
+ MATCH_DIRECT_BOOT_AWARE or MATCH_DIRECT_BOOT_UNAWARE
+ )) {
launcherPkgs.add(info.activityInfo.packageName)
}
}
@@ -69,4 +73,4 @@ object LauncherPackagesLiveData : SmartAsyncMediatorLiveData<Set<String>>(),
super.onInactive()
PackageBroadcastReceiver.removeAllCallback(this)
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt
index 3621319a6..db606f68d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt
@@ -39,7 +39,8 @@ import com.android.permissioncontroller.permission.utils.Utils.OS_PKG
* @param permGroupName The name of the permission group
* @param user The user of the package
*/
-class LightAppPermGroupLiveData private constructor(
+class LightAppPermGroupLiveData
+private constructor(
private val app: Application,
private val packageName: String,
private val permGroupName: String,
@@ -55,13 +56,15 @@ class LightAppPermGroupLiveData private constructor(
private val fgPermNamesLiveData = ForegroundPermNamesLiveData
init {
- isSpecialLocation = LocationUtils.isLocationGroupAndProvider(app,
- permGroupName, packageName) ||
- LocationUtils.isLocationGroupAndControllerExtraPackage(app, permGroupName, packageName)
+ isSpecialLocation =
+ LocationUtils.isLocationGroupAndProvider(app, permGroupName, packageName) ||
+ LocationUtils.isLocationGroupAndControllerExtraPackage(
+ app,
+ permGroupName,
+ packageName
+ )
- addSource(fgPermNamesLiveData) {
- update()
- }
+ addSource(fgPermNamesLiveData) { update() }
val key = Triple(packageName, permGroupName, user)
@@ -100,8 +103,10 @@ class LightAppPermGroupLiveData private constructor(
val allForegroundPerms = fgPermNamesLiveData.value ?: return
// Do not allow toggling pre-M custom perm groups
- if (packageInfo.targetSdkVersion < Build.VERSION_CODES.M &&
- permGroup.groupInfo.packageName != OS_PKG) {
+ if (
+ packageInfo.targetSdkVersion < Build.VERSION_CODES.M &&
+ permGroup.groupInfo.packageName != OS_PKG
+ ) {
value = LightAppPermGroup(packageInfo, permGroup.groupInfo, emptyMap())
return
}
@@ -110,8 +115,8 @@ class LightAppPermGroupLiveData private constructor(
for ((permName, permState) in permStates) {
val permInfo = permGroup.permissionInfos[permName] ?: continue
val foregroundPerms = allForegroundPerms[permName]
- permissionMap[permName] = LightPermission(packageInfo, permInfo, permState,
- foregroundPerms)
+ permissionMap[permName] =
+ LightPermission(packageInfo, permInfo, permState, foregroundPerms)
}
// Determine if this app permission group is a special location package or provider
@@ -119,17 +124,24 @@ class LightAppPermGroupLiveData private constructor(
val userContext = Utils.getUserContext(app, user)
if (LocationUtils.isLocationGroupAndProvider(userContext, permGroupName, packageName)) {
specialLocationGrant = LocationUtils.isLocationEnabled(userContext)
- } else if (LocationUtils.isLocationGroupAndControllerExtraPackage(app, permGroupName,
- packageName)) {
+ } else if (
+ LocationUtils.isLocationGroupAndControllerExtraPackage(app, permGroupName, packageName)
+ ) {
// The permission of the extra location controller package is determined by the status
// of the controller package itself.
- specialLocationGrant = LocationUtils.isExtraLocationControllerPackageEnabled(
- userContext)
+ specialLocationGrant =
+ LocationUtils.isExtraLocationControllerPackageEnabled(userContext)
}
val hasInstallToRuntimeSplit = hasInstallToRuntimeSplit(packageInfo, permissionMap)
- value = LightAppPermGroup(packageInfo, permGroup.groupInfo, permissionMap,
- hasInstallToRuntimeSplit, specialLocationGrant)
+ value =
+ LightAppPermGroup(
+ packageInfo,
+ permGroup.groupInfo,
+ permissionMap,
+ hasInstallToRuntimeSplit,
+ specialLocationGrant
+ )
}
/**
@@ -147,12 +159,13 @@ class LightAppPermGroupLiveData private constructor(
for (spi in permissionManager.splitPermissions) {
val splitPerm = spi.splitPermission
- val pi = try {
- app.packageManager.getPermissionInfo(splitPerm, 0)
- } catch (e: PackageManager.NameNotFoundException) {
- Log.w(LOG_TAG, "No such permission: $splitPerm", e)
- continue
- }
+ val pi =
+ try {
+ app.packageManager.getPermissionInfo(splitPerm, 0)
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.w(LOG_TAG, "No such permission: $splitPerm", e)
+ continue
+ }
// Skip if split permission is not "install" permission.
if (pi.protection != PermissionInfo.PROTECTION_NORMAL) {
@@ -199,15 +212,19 @@ class LightAppPermGroupLiveData private constructor(
/**
* Repository for AppPermGroupLiveDatas.
+ *
* <p> Key value is a triple of string package name, string permission group name, and
* UserHandle, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<Triple<String, String, UserHandle>,
- LightAppPermGroupLiveData>() {
- override fun newValue(key: Triple<String, String, UserHandle>):
- LightAppPermGroupLiveData {
- return LightAppPermGroupLiveData(PermissionControllerApplication.get(),
- key.first, key.second, key.third)
+ companion object :
+ DataRepositoryForPackage<Triple<String, String, UserHandle>, LightAppPermGroupLiveData>() {
+ override fun newValue(key: Triple<String, String, UserHandle>): LightAppPermGroupLiveData {
+ return LightAppPermGroupLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second,
+ key.third
+ )
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/LightPackageInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/LightPackageInfoLiveData.kt
index 27681cd90..e657a6869 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/LightPackageInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/LightPackageInfoLiveData.kt
@@ -37,11 +37,13 @@ import kotlinx.coroutines.Job
* @param packageName The name of the package this LiveData will watch for mode changes for
* @param user The user for whom the packageInfo will be defined
*/
-class LightPackageInfoLiveData private constructor(
+class LightPackageInfoLiveData
+private constructor(
private val app: Application,
private val packageName: String,
private val user: UserHandle
-) : SmartAsyncMediatorLiveData<LightPackageInfo?>(alwaysUpdateOnActive = false),
+) :
+ SmartAsyncMediatorLiveData<LightPackageInfo?>(alwaysUpdateOnActive = false),
PackageBroadcastReceiver.PackageBroadcastListener,
PermissionListenerMultiplexer.PermissionChangeCallback {
@@ -49,13 +51,9 @@ class LightPackageInfoLiveData private constructor(
private val userPackagesLiveData = UserPackageInfosLiveData[user]
private var uid: Int? = null
- /**
- * The currently registered UID on which this LiveData is listening for permission changes.
- */
+ /** The currently registered UID on which this LiveData is listening for permission changes. */
private var registeredUid: Int? = null
- /**
- * Whether or not this package livedata is watching the UserPackageInfosLiveData
- */
+ /** Whether or not this package livedata is watching the UserPackageInfosLiveData */
private var watchingUserPackagesLiveData: Boolean = false
/**
@@ -73,8 +71,11 @@ class LightPackageInfoLiveData private constructor(
uid = packageInfo.uid
if (hasActiveObservers()) {
- PermissionListenerMultiplexer.addOrReplaceCallback(registeredUid,
- packageInfo.uid, this)
+ PermissionListenerMultiplexer.addOrReplaceCallback(
+ registeredUid,
+ packageInfo.uid,
+ this
+ )
registeredUid = uid
}
}
@@ -95,30 +96,37 @@ class LightPackageInfoLiveData private constructor(
if (job.isCancelled) {
return
}
- postValue(try {
- var flags = PackageManager.GET_PERMISSIONS
- if (SdkLevel.isAtLeastS()) {
- flags = flags or PackageManager.GET_ATTRIBUTIONS
- }
+ postValue(
+ try {
+ var flags = PackageManager.GET_PERMISSIONS
+ if (SdkLevel.isAtLeastS()) {
+ flags = flags or PackageManager.GET_ATTRIBUTIONS
+ }
- LightPackageInfo(Utils.getUserContext(app, user).packageManager
- .getPackageInfo(packageName, flags))
- } catch (e: Exception) {
- if (e is PackageManager.NameNotFoundException) {
- Log.w(LOG_TAG, "Package \"$packageName\" not found for user $user")
- } else {
- val profiles = app.getSystemService(UserManager::class.java)!!.userProfiles
- Log.e(LOG_TAG, "Failed to create context for user $user. " +
- "User exists : ${user in profiles }", e)
+ LightPackageInfo(
+ Utils.getUserContext(app, user)
+ .packageManager
+ .getPackageInfo(packageName, flags)
+ )
+ } catch (e: Exception) {
+ if (e is PackageManager.NameNotFoundException) {
+ Log.w(LOG_TAG, "Package \"$packageName\" not found for user $user")
+ } else {
+ val profiles = app.getSystemService(UserManager::class.java)!!.userProfiles
+ Log.e(
+ LOG_TAG,
+ "Failed to create context for user $user. " +
+ "User exists : ${user in profiles }",
+ e
+ )
+ }
+ invalidateSingle(packageName to user)
+ null
}
- invalidateSingle(packageName to user)
- null
- })
+ )
}
- /**
- * Callback from the PermissionListener. Either deletes or generates package data.
- */
+ /** Callback from the PermissionListener. Either deletes or generates package data. */
override fun onPermissionChange() {
updateAsync()
}
@@ -131,8 +139,11 @@ class LightPackageInfoLiveData private constructor(
registeredUid = uid
PermissionListenerMultiplexer.addCallback(it, this)
}
- if (userPackagesLiveData.hasActiveObservers() && !watchingUserPackagesLiveData &&
- !userPackagesLiveData.permChangeStale) {
+ if (
+ userPackagesLiveData.hasActiveObservers() &&
+ !watchingUserPackagesLiveData &&
+ !userPackagesLiveData.permChangeStale
+ ) {
watchingUserPackagesLiveData = true
addSource(userPackagesLiveData, userPackageInfosObserver)
} else {
@@ -140,9 +151,8 @@ class LightPackageInfoLiveData private constructor(
}
}
- private val userPackageInfosObserver = Observer<List<LightPackageInfo>> {
- updateFromUserPackageInfosLiveData()
- }
+ private val userPackageInfosObserver =
+ Observer<List<LightPackageInfo>> { updateFromUserPackageInfosLiveData() }
@MainThread
private fun updateFromUserPackageInfosLiveData() {
@@ -183,14 +193,18 @@ class LightPackageInfoLiveData private constructor(
/**
* Repository for LightPackageInfoLiveDatas
+ *
* <p> Key value is a string package name and UserHandle pair, value is its corresponding
* LiveData.
*/
- companion object : DataRepositoryForPackage<Pair<String, UserHandle>,
- LightPackageInfoLiveData>() {
+ companion object :
+ DataRepositoryForPackage<Pair<String, UserHandle>, LightPackageInfoLiveData>() {
override fun newValue(key: Pair<String, UserHandle>): LightPackageInfoLiveData {
- return LightPackageInfoLiveData(PermissionControllerApplication.get(),
- key.first, key.second)
+ return LightPackageInfoLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/LightPermInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/LightPermInfoLiveData.kt
index 6f33cb199..091c45b92 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/LightPermInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/LightPermInfoLiveData.kt
@@ -20,8 +20,8 @@ import android.app.Application
import android.content.pm.PackageManager
import android.util.Log
import com.android.permissioncontroller.PermissionControllerApplication
-import com.android.permissioncontroller.permission.utils.PermissionMapping.isRuntimePlatformPermission
import com.android.permissioncontroller.permission.model.livedatatypes.LightPermInfo
+import com.android.permissioncontroller.permission.utils.PermissionMapping.isRuntimePlatformPermission
import com.android.permissioncontroller.permission.utils.Utils.OS_PKG
import kotlinx.coroutines.Job
@@ -31,11 +31,9 @@ import kotlinx.coroutines.Job
* @param app current Application
* @param permissionName name of the permission this LiveData will watch for mode changes for
*/
-class LightPermInfoLiveData private constructor(
- private val app: Application,
- private val permissionName: String
-) : SmartAsyncMediatorLiveData<LightPermInfo>(),
- PackageBroadcastReceiver.PackageBroadcastListener {
+class LightPermInfoLiveData
+private constructor(private val app: Application, private val permissionName: String) :
+ SmartAsyncMediatorLiveData<LightPermInfo>(), PackageBroadcastReceiver.PackageBroadcastListener {
private val LOG_TAG = LightPermInfoLiveData::class.java.simpleName
@@ -67,13 +65,14 @@ class LightPermInfoLiveData private constructor(
return
}
- val newValue = try {
- LightPermInfo(app.packageManager.getPermissionInfo(permissionName, 0))
- } catch (e: PackageManager.NameNotFoundException) {
- Log.w(LOG_TAG, "Permission \"$permissionName\" not found")
- invalidateSingle(permissionName)
- null
- }
+ val newValue =
+ try {
+ LightPermInfo(app.packageManager.getPermissionInfo(permissionName, 0))
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.w(LOG_TAG, "Permission \"$permissionName\" not found")
+ invalidateSingle(permissionName)
+ null
+ }
if (isImmutable()) {
stopListeningForChanges()
@@ -82,9 +81,7 @@ class LightPermInfoLiveData private constructor(
postValue(newValue)
}
- /**
- * @return if the permission state can never change
- */
+ /** @return if the permission state can never change */
private fun isImmutable(): Boolean {
// The os package never changes
value?.let {
@@ -97,9 +94,7 @@ class LightPermInfoLiveData private constructor(
return isRuntimePlatformPermission(permissionName)
}
- /**
- * Start listing for changes to this permission if needed
- */
+ /** Start listing for changes to this permission if needed */
private fun startListeningForChanges() {
if (!isListeningForChanges && !isImmutable()) {
isListeningForChanges = true
@@ -107,9 +102,7 @@ class LightPermInfoLiveData private constructor(
}
}
- /**
- * Stop listing for changes to this permission
- */
+ /** Stop listing for changes to this permission */
private fun stopListeningForChanges() {
if (isListeningForChanges) {
PackageBroadcastReceiver.removeAllCallback(this)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/LoadAndFreezeLifeData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/LoadAndFreezeLifeData.kt
index 5e8789a38..fd572e019 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/LoadAndFreezeLifeData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/LoadAndFreezeLifeData.kt
@@ -23,8 +23,8 @@ import androidx.lifecycle.SavedStateHandle
* value forever.
*
* This even extends over live-cycle events as the data is stored in the {@link SaveStateHandle}.
- * This means that the data has to be writable to {@link SavedStateHandle} though, i.e.
- * Serialzable, Parcelable, list, set, map, or a literal
+ * This means that the data has to be writable to {@link SavedStateHandle} though, i.e. Serialzable,
+ * Parcelable, list, set, map, or a literal
*/
class LoadAndFreezeLifeData<T>(
private val state: SavedStateHandle,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/MicMutedLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/MicMutedLiveData.kt
index f53f60345..0bd045e80 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/MicMutedLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/MicMutedLiveData.kt
@@ -24,33 +24,35 @@ import android.media.AudioManager
import com.android.permissioncontroller.PermissionControllerApplication
import kotlinx.coroutines.Job
-/**
- * Tracks whether the mic is muted or not
- */
-val micMutedLiveData = object : SmartAsyncMediatorLiveData<Boolean>() {
- private val app = PermissionControllerApplication.get()
-
- private val isMicMuteRecevicer = object : BroadcastReceiver() {
- override fun onReceive(context: Context?, intent: Intent?) {
- update()
+/** Tracks whether the mic is muted or not */
+val micMutedLiveData =
+ object : SmartAsyncMediatorLiveData<Boolean>() {
+ private val app = PermissionControllerApplication.get()
+
+ private val isMicMuteRecevicer =
+ object : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ update()
+ }
+ }
+
+ override suspend fun loadDataAndPostValue(job: Job) {
+ postValue(app.getSystemService(AudioManager::class.java).isMicrophoneMute())
}
- }
-
- override suspend fun loadDataAndPostValue(job: Job) {
- postValue(app.getSystemService(AudioManager::class.java).isMicrophoneMute())
- }
- override fun onActive() {
- super.onActive()
+ override fun onActive() {
+ super.onActive()
- app.registerReceiver(isMicMuteRecevicer,
- IntentFilter(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED))
- update()
- }
+ app.registerReceiver(
+ isMicMuteRecevicer,
+ IntentFilter(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
+ )
+ update()
+ }
- override fun onInactive() {
- super.onInactive()
+ override fun onInactive() {
+ super.onInactive()
- app.unregisterReceiver(isMicMuteRecevicer)
+ app.unregisterReceiver(isMicMuteRecevicer)
+ }
}
-}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/OpUsageLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/OpUsageLiveData.kt
index 805d497c4..7ca0f2d96 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/OpUsageLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/OpUsageLiveData.kt
@@ -45,26 +45,28 @@ class OpUsageLiveData(
private val app: Application,
private val opNames: List<String>,
private val usageDurationMs: Long
-) : SmartAsyncMediatorLiveData<@JvmSuppressWildcards Map<String, List<OpAccess>>>(),
- AppOpsManager.OnOpActiveChangedListener {
+) :
+ SmartAsyncMediatorLiveData<@JvmSuppressWildcards Map<String, List<OpAccess>>>(),
+ AppOpsManager.OnOpActiveChangedListener {
private val appOpsManager = app.getSystemService(AppOpsManager::class.java)!!
override suspend fun loadDataAndPostValue(job: Job) {
val now = System.currentTimeMillis()
val opMap = mutableMapOf<String, MutableList<OpAccess>>()
- val packageOps = try {
- appOpsManager.getPackagesForOps(opNames.toTypedArray())
- } catch (e: NullPointerException) {
- // older builds might not support all the app-ops requested
- emptyList<AppOpsManager.PackageOps>()
- }
+ val packageOps =
+ try {
+ appOpsManager.getPackagesForOps(opNames.toTypedArray())
+ } catch (e: NullPointerException) {
+ // older builds might not support all the app-ops requested
+ emptyList<AppOpsManager.PackageOps>()
+ }
for (packageOp in packageOps) {
for (opEntry in packageOp.ops) {
for ((attributionTag, attributedOpEntry) in opEntry.attributedOpEntries) {
val user = UserHandle.getUserHandleForUid(packageOp.uid)
- val lastAccessTime: Long = attributedOpEntry.getLastAccessTime(
- OP_FLAGS_ALL_TRUSTED)
+ val lastAccessTime: Long =
+ attributedOpEntry.getLastAccessTime(OP_FLAGS_ALL_TRUSTED)
if (lastAccessTime == -1L) {
// There was no access, so skip
@@ -78,34 +80,55 @@ class OpUsageLiveData(
lastAccessDuration = 0
}
- if (attributedOpEntry.isRunning ||
- lastAccessTime + lastAccessDuration > (now - usageDurationMs)) {
+ if (
+ attributedOpEntry.isRunning ||
+ lastAccessTime + lastAccessDuration > (now - usageDurationMs)
+ ) {
val accessList = opMap.getOrPut(opEntry.opStr) { mutableListOf() }
- val accessTime = if (attributedOpEntry.isRunning) {
- OpAccess.IS_RUNNING
- } else {
- lastAccessTime
- }
+ val accessTime =
+ if (attributedOpEntry.isRunning) {
+ OpAccess.IS_RUNNING
+ } else {
+ lastAccessTime
+ }
val proxy = attributedOpEntry.getLastProxyInfo(OP_FLAGS_ALL_TRUSTED)
var proxyAccess: OpAccess? = null
if (proxy != null && proxy.packageName != null) {
- proxyAccess = OpAccess(proxy.packageName!!, proxy.attributionTag,
- UserHandle.getUserHandleForUid(proxy.uid), accessTime)
+ proxyAccess =
+ OpAccess(
+ proxy.packageName!!,
+ proxy.attributionTag,
+ UserHandle.getUserHandleForUid(proxy.uid),
+ accessTime
+ )
}
- accessList.add(OpAccess(packageOp.packageName, attributionTag,
- user, accessTime, proxyAccess))
+ accessList.add(
+ OpAccess(
+ packageOp.packageName,
+ attributionTag,
+ user,
+ accessTime,
+ proxyAccess
+ )
+ )
// TODO ntmyren: remove logs once b/160724034 is fixed
- Log.i("OpUsageLiveData", "adding ${opEntry.opStr} for " +
+ Log.i(
+ "OpUsageLiveData",
+ "adding ${opEntry.opStr} for " +
"${packageOp.packageName}/$attributionTag, access time of " +
"$lastAccessTime, isRunning: ${attributedOpEntry.isRunning} " +
"current time $now, duration $lastAccessDuration, proxy: " +
- "${proxy?.packageName}")
+ "${proxy?.packageName}"
+ )
} else {
- Log.i("OpUsageLiveData", "NOT adding ${opEntry.opStr} for " +
+ Log.i(
+ "OpUsageLiveData",
+ "NOT adding ${opEntry.opStr} for " +
"${packageOp.packageName}/$attributionTag, access time of " +
"$lastAccessTime, isRunning: ${attributedOpEntry.isRunning} " +
- "current time $now, duration $lastAccessDuration")
+ "current time $now, duration $lastAccessDuration"
+ )
}
}
}
@@ -180,26 +203,31 @@ data class OpAccess(
const val IS_RUNNING = -1L
@JvmField
- val CREATOR = object : Parcelable.Creator<OpAccess> {
- override fun createFromParcel(parcel: Parcel): OpAccess {
- val packageName = parcel.readString()!!
- val attributionTag = parcel.readString()
- val user: UserHandle = parcel.readParcelable(UserHandle::class.java.classLoader)!!
- val lastAccessTime = parcel.readLong()
- var proxyAccess: OpAccess? = null
- val proxyPackageName = parcel.readString()
- if (proxyPackageName != null) {
- proxyAccess = OpAccess(proxyPackageName,
- parcel.readString(),
- parcel.readParcelable(UserHandle::class.java.classLoader)!!,
- lastAccessTime)
+ val CREATOR =
+ object : Parcelable.Creator<OpAccess> {
+ override fun createFromParcel(parcel: Parcel): OpAccess {
+ val packageName = parcel.readString()!!
+ val attributionTag = parcel.readString()
+ val user: UserHandle =
+ parcel.readParcelable(UserHandle::class.java.classLoader)!!
+ val lastAccessTime = parcel.readLong()
+ var proxyAccess: OpAccess? = null
+ val proxyPackageName = parcel.readString()
+ if (proxyPackageName != null) {
+ proxyAccess =
+ OpAccess(
+ proxyPackageName,
+ parcel.readString(),
+ parcel.readParcelable(UserHandle::class.java.classLoader)!!,
+ lastAccessTime
+ )
+ }
+ return OpAccess(packageName, attributionTag, user, lastAccessTime, proxyAccess)
}
- return OpAccess(packageName, attributionTag, user, lastAccessTime, proxyAccess)
- }
- override fun newArray(size: Int): Array<OpAccess?> {
- return arrayOfNulls(size)
+ override fun newArray(size: Int): Array<OpAccess?> {
+ return arrayOfNulls(size)
+ }
}
- }
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PackageBroadcastReceiver.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PackageBroadcastReceiver.kt
index b2e0236fa..09a7bb1e4 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PackageBroadcastReceiver.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PackageBroadcastReceiver.kt
@@ -29,31 +29,24 @@ import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
-/**
- * Listens for package additions, replacements, and removals, and notifies listeners.
- */
+/** Listens for package additions, replacements, and removals, and notifies listeners. */
object PackageBroadcastReceiver : BroadcastReceiver() {
private val app: Application = PermissionControllerApplication.get()
- private val intentFilter = IntentFilter(Intent.ACTION_PACKAGE_ADDED).apply {
- addAction(Intent.ACTION_PACKAGE_REMOVED)
- addAction(Intent.ACTION_PACKAGE_REPLACED)
- addAction(Intent.ACTION_PACKAGE_CHANGED)
- addDataScheme("package")
- }
+ private val intentFilter =
+ IntentFilter(Intent.ACTION_PACKAGE_ADDED).apply {
+ addAction(Intent.ACTION_PACKAGE_REMOVED)
+ addAction(Intent.ACTION_PACKAGE_REPLACED)
+ addAction(Intent.ACTION_PACKAGE_CHANGED)
+ addDataScheme("package")
+ }
- /**
- * Map<packageName, callbacks listenening to package>
- */
+ /** Map<packageName, callbacks listenening to package> */
private val changeCallbacks = mutableMapOf<String, MutableSet<PackageBroadcastListener>>()
- /**
- * A list of listener IDs, which listen to all package additions, changes, and removals.
- */
+ /** A list of listener IDs, which listen to all package additions, changes, and removals. */
private val allCallbacks = mutableSetOf<PackageBroadcastListener>()
- /**
- * Add a callback which will be notified when the specified packaged is changed or removed.
- */
+ /** Add a callback which will be notified when the specified packaged is changed or removed. */
fun addChangeCallback(packageName: String, listener: PackageBroadcastListener) {
GlobalScope.launch(Main.immediate) {
val wasEmpty = hasNoListeners()
@@ -61,8 +54,12 @@ object PackageBroadcastReceiver : BroadcastReceiver() {
changeCallbacks.getOrPut(packageName, { mutableSetOf() }).add(listener)
if (wasEmpty) {
- app.applicationContext.registerReceiverForAllUsers(this@PackageBroadcastReceiver,
- intentFilter, null, null)
+ app.applicationContext.registerReceiverForAllUsers(
+ this@PackageBroadcastReceiver,
+ intentFilter,
+ null,
+ null
+ )
}
}
}
@@ -80,8 +77,12 @@ object PackageBroadcastReceiver : BroadcastReceiver() {
allCallbacks.add(listener)
if (wasEmpty) {
- app.applicationContext.registerReceiverForAllUsers(this@PackageBroadcastReceiver,
- intentFilter, null, null)
+ app.applicationContext.registerReceiverForAllUsers(
+ this@PackageBroadcastReceiver,
+ intentFilter,
+ null,
+ null
+ )
}
}
}
@@ -171,9 +172,7 @@ object PackageBroadcastReceiver : BroadcastReceiver() {
}
}
- /**
- * A listener interface for objects desiring to be notified of package broadcasts.
- */
+ /** A listener interface for objects desiring to be notified of package broadcasts. */
interface PackageBroadcastListener {
/**
* To be called when a specific package has been changed, or when any package has been
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PackagePermissionsLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PackagePermissionsLiveData.kt
index 49be1fbd0..cc050fae2 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PackagePermissionsLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PackagePermissionsLiveData.kt
@@ -35,11 +35,9 @@ import kotlinx.coroutines.Job
* @param packageName The name of the package this LiveData will watch for mode changes for
* @param user The user for whom the packageInfo will be defined
*/
-class PackagePermissionsLiveData private constructor(
- private val app: Application,
- packageName: String,
- user: UserHandle
-) : SmartAsyncMediatorLiveData<Map<String, List<String>>?>() {
+class PackagePermissionsLiveData
+private constructor(private val app: Application, packageName: String, user: UserHandle) :
+ SmartAsyncMediatorLiveData<Map<String, List<String>>?>() {
private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user]
@@ -60,25 +58,32 @@ class PackagePermissionsLiveData private constructor(
for (permName in packageInfo.requestedPermissions) {
var groupName = PermissionMapping.getGroupOfPlatformPermission(permName)
if (groupName == null) {
- val permInfo = try {
- app.packageManager.getPermissionInfo(permName, 0)
- } catch (e: PackageManager.NameNotFoundException) {
- continue
- }
+ val permInfo =
+ try {
+ app.packageManager.getPermissionInfo(permName, 0)
+ } catch (e: PackageManager.NameNotFoundException) {
+ continue
+ }
- if (permInfo.flags and PermissionInfo.FLAG_INSTALLED == 0 ||
- permInfo.flags and PermissionInfo.FLAG_REMOVED != 0) {
+ if (
+ permInfo.flags and PermissionInfo.FLAG_INSTALLED == 0 ||
+ permInfo.flags and PermissionInfo.FLAG_REMOVED != 0
+ ) {
continue
}
- if (packageInfo.isInstantApp && permInfo.protectionFlags and
- PermissionInfo.PROTECTION_FLAG_INSTANT == 0) {
+ if (
+ packageInfo.isInstantApp &&
+ permInfo.protectionFlags and PermissionInfo.PROTECTION_FLAG_INSTANT == 0
+ ) {
continue
}
- if (packageInfo.targetSdkVersion < Build.VERSION_CODES.M &&
- (permInfo.protectionFlags and PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) !=
- 0) {
+ if (
+ packageInfo.targetSdkVersion < Build.VERSION_CODES.M &&
+ (permInfo.protectionFlags and
+ PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0
+ ) {
continue
}
@@ -104,14 +109,17 @@ class PackagePermissionsLiveData private constructor(
/**
* Repository for PackagePermissionsLiveData objects
+ *
* <p> Key value is a string package name and userHandle, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<Pair<String, UserHandle>,
- PackagePermissionsLiveData>() {
- override fun newValue(key: Pair<String, UserHandle>):
- PackagePermissionsLiveData {
- return PackagePermissionsLiveData(PermissionControllerApplication.get(), key.first,
- key.second)
+ companion object :
+ DataRepositoryForPackage<Pair<String, UserHandle>, PackagePermissionsLiveData>() {
+ override fun newValue(key: Pair<String, UserHandle>): PackagePermissionsLiveData {
+ return PackagePermissionsLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second
+ )
}
const val NON_RUNTIME_NORMAL_PERMS = "nonRuntimeNormalPerms"
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupLiveData.kt
index 78f2f72c6..d44fea233 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupLiveData.kt
@@ -36,19 +36,15 @@ import com.android.permissioncontroller.permission.utils.Utils
* @param app The current application
* @param groupName The name of the permission group this LiveData represents
*/
-class PermGroupLiveData private constructor(
- private val app: Application,
- private val groupName: String
-) : SmartUpdateMediatorLiveData<PermGroup>(),
- PackageBroadcastReceiver.PackageBroadcastListener {
+class PermGroupLiveData
+private constructor(private val app: Application, private val groupName: String) :
+ SmartUpdateMediatorLiveData<PermGroup>(), PackageBroadcastReceiver.PackageBroadcastListener {
private val LOG_TAG = this::class.java.simpleName
private val context = app.applicationContext!!
- /**
- * Map<packageName, LiveData<PackageInfo>>
- */
+ /** Map<packageName, LiveData<PackageInfo>> */
private val packageLiveDatas = mutableMapOf<String, LightPackageInfoLiveData>()
private lateinit var groupInfo: PackageItemInfo
@@ -69,25 +65,30 @@ class PermGroupLiveData private constructor(
override fun onUpdate() {
val permissionInfos = mutableMapOf<String, LightPermInfo>()
- groupInfo = Utils.getGroupInfo(groupName, context) ?: run {
- Log.e(LOG_TAG, "Invalid permission group $groupName")
- invalidateSingle(groupName)
- value = null
- return
- }
-
- when (groupInfo) {
- is PermissionGroupInfo -> {
- val permInfos = try {
- Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager,
- groupName)
- } catch (e: PackageManager.NameNotFoundException) {
+ groupInfo =
+ Utils.getGroupInfo(groupName, context)
+ ?: run {
Log.e(LOG_TAG, "Invalid permission group $groupName")
invalidateSingle(groupName)
value = null
return
}
+ when (groupInfo) {
+ is PermissionGroupInfo -> {
+ val permInfos =
+ try {
+ Utils.getInstalledRuntimePermissionInfosForGroup(
+ context.packageManager,
+ groupName
+ )
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.e(LOG_TAG, "Invalid permission group $groupName")
+ invalidateSingle(groupName)
+ value = null
+ return
+ }
+
for (permInfo in permInfos) {
permissionInfos[permInfo.name] = LightPermInfo(permInfo)
}
@@ -105,8 +106,8 @@ class PermGroupLiveData private constructor(
value = permGroup
- val packageNames = permissionInfos.values.map { permInfo -> permInfo.packageName }
- .toMutableSet()
+ val packageNames =
+ permissionInfos.values.map { permInfo -> permInfo.packageName }.toMutableSet()
packageNames.add(groupInfo.packageName)
// TODO ntmyren: What if the package isn't installed for the system user?
@@ -123,8 +124,8 @@ class PermGroupLiveData private constructor(
}
/**
- * Load data, and register a package change listener. We must watch for package changes,
- * because there is currently no listener for permission changes.
+ * Load data, and register a package change listener. We must watch for package changes, because
+ * there is currently no listener for permission changes.
*/
override fun onActive() {
update()
@@ -136,6 +137,7 @@ class PermGroupLiveData private constructor(
/**
* Repository for PermGroupLiveDatas.
+ *
* <p> Key value is a string permission group name, value is its corresponding LiveData.
*/
companion object : DataRepository<String, PermGroupLiveData>() {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupUsageLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupUsageLiveData.kt
index 08f9bbfb4..175f389fa 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupUsageLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupUsageLiveData.kt
@@ -41,19 +41,21 @@ class PermGroupUsageLiveData(
private val usageDurationMs: Long
) : SmartUpdateMediatorLiveData<Map<String, List<OpAccess>>>() {
/** Perm group name -> OpUsageLiveData */
- private val permGroupUsages = permGroupsNames.map { permGroup ->
- val appops = getPlatformPermissionNamesOfGroup(permGroup).mapNotNull { permName ->
- permissionToOp(permName)
- }
+ private val permGroupUsages =
+ permGroupsNames
+ .map { permGroup ->
+ val appops =
+ getPlatformPermissionNamesOfGroup(permGroup).mapNotNull { permName ->
+ permissionToOp(permName)
+ }
- permGroup to OpUsageLiveData[appops, usageDurationMs]
- }.toMap()
+ permGroup to OpUsageLiveData[appops, usageDurationMs]
+ }
+ .toMap()
init {
for (usage in permGroupUsages.values) {
- addSource(usage) {
- update()
- }
+ addSource(usage) { update() }
}
}
@@ -68,25 +70,33 @@ class PermGroupUsageLiveData(
}
// Only keep the last access for a permission group
- value = permGroupUsages.map { (permGroupName, usageLiveData) ->
- // (packageName, attributionTag) -> access
- val lastAccess = mutableMapOf<Pair<String, String?>, OpAccess>()
- for (access in usageLiveData.value!!.values.flatten()) {
- val key = access.packageName to access.attributionTag
- if (access.isRunning ||
- lastAccess[key]?.lastAccessTime ?: 0 < access.lastAccessTime) {
- lastAccess[key] = access
- }
- }
+ value =
+ permGroupUsages
+ .map { (permGroupName, usageLiveData) ->
+ // (packageName, attributionTag) -> access
+ val lastAccess = mutableMapOf<Pair<String, String?>, OpAccess>()
+ for (access in usageLiveData.value!!.values.flatten()) {
+ val key = access.packageName to access.attributionTag
+ if (
+ access.isRunning ||
+ lastAccess[key]?.lastAccessTime ?: 0 < access.lastAccessTime
+ ) {
+ lastAccess[key] = access
+ }
+ }
- permGroupName to lastAccess.values.toList()
- }.toMap()
+ permGroupName to lastAccess.values.toList()
+ }
+ .toMap()
}
companion object : DataRepository<Pair<List<String>, Long>, PermGroupUsageLiveData>() {
override fun newValue(key: Pair<List<String>, Long>): PermGroupUsageLiveData {
- return PermGroupUsageLiveData(PermissionControllerApplication.get(), key.first,
- key.second)
+ return PermGroupUsageLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesLiveData.kt
index c44c2b473..ae9963538 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesLiveData.kt
@@ -31,10 +31,9 @@ import com.android.permissioncontroller.permission.utils.Utils.OS_PKG
*
* @param app The current application
*/
-class PermGroupsPackagesLiveData private constructor(
- private val app: Application,
- groupNamesLiveData: LiveData<List<String>>
-) : SmartUpdateMediatorLiveData<Map<String, Set<Pair<String, UserHandle>>>>() {
+class PermGroupsPackagesLiveData
+private constructor(private val app: Application, groupNamesLiveData: LiveData<List<String>>) :
+ SmartUpdateMediatorLiveData<Map<String, Set<Pair<String, UserHandle>>>>() {
private val packagesLiveData = AllPackageInfosLiveData
private val permGroupLiveDatas = mutableMapOf<String, PermGroupLiveData>()
@@ -47,8 +46,10 @@ class PermGroupsPackagesLiveData private constructor(
val getLiveData = { groupName: String -> PermGroupLiveData[groupName] }
setSourcesToDifference(groupNames, permGroupLiveDatas, getLiveData) {
- if (packagesLiveData.isInitialized &&
- permGroupLiveDatas.all { it.value.isInitialized }) {
+ if (
+ packagesLiveData.isInitialized &&
+ permGroupLiveDatas.all { it.value.isInitialized }
+ ) {
update()
}
}
@@ -62,9 +63,9 @@ class PermGroupsPackagesLiveData private constructor(
}
/**
- * Using the current list of permission groups, go through all packages in the system,
- * and figure out which permission groups they have permissions for. If applicable, remove
- * any lone-permission permission that are not requested by any packages.
+ * Using the current list of permission groups, go through all packages in the system, and
+ * figure out which permission groups they have permissions for. If applicable, remove any
+ * lone-permission permission that are not requested by any packages.
*/
override fun onUpdate() {
if (groupNames.isEmpty()) {
@@ -108,8 +109,10 @@ class PermGroupsPackagesLiveData private constructor(
* group, if also empty.
*/
for (permGroup in permGroups) {
- if (permGroup.groupInfo.isSinglePermGroup ||
- permGroup.name == Manifest.permission_group.UNDEFINED) {
+ if (
+ permGroup.groupInfo.isSinglePermGroup ||
+ permGroup.name == Manifest.permission_group.UNDEFINED
+ ) {
val groupPackages = groupApps[permGroup.name] ?: continue
if (groupPackages.isEmpty()) {
groupApps.remove(permGroup.name)
@@ -121,17 +124,22 @@ class PermGroupsPackagesLiveData private constructor(
}
companion object {
- private val customInstance = PermGroupsPackagesLiveData(
- PermissionControllerApplication.get(), CustomPermGroupNamesLiveData)
- private val standardInstance = PermGroupsPackagesLiveData(
- PermissionControllerApplication.get(), StandardPermGroupNamesLiveData)
+ private val customInstance =
+ PermGroupsPackagesLiveData(
+ PermissionControllerApplication.get(),
+ CustomPermGroupNamesLiveData
+ )
+ private val standardInstance =
+ PermGroupsPackagesLiveData(
+ PermissionControllerApplication.get(),
+ StandardPermGroupNamesLiveData
+ )
/**
* Get either the PermGroupsPackageLiveData instance corresponding either to the custom
* permission groups, or the standard permission group.
*
* @param customGroups Whether to get the custom groups instance, or the standard
- *
* @return The specified PermGroupsPackageLiveData
*/
@JvmStatic
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesUiInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesUiInfoLiveData.kt
index 5d91ebfda..8bb33d1a9 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesUiInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesUiInfoLiveData.kt
@@ -37,8 +37,10 @@ import com.android.permissioncontroller.permission.utils.Utils
class PermGroupsPackagesUiInfoLiveData(
private val app: Application,
private val groupNamesLiveData: LiveData<List<String>>
-) : SmartUpdateMediatorLiveData<
- @kotlin.jvm.JvmSuppressWildcards Map<String, PermGroupPackagesUiInfo?>>() {
+) :
+ SmartUpdateMediatorLiveData<
+ @kotlin.jvm.JvmSuppressWildcards Map<String, PermGroupPackagesUiInfo?>
+ >() {
private val SYSTEM_SHELL = "android.app.role.SYSTEM_SHELL"
private val STAGGER_LOAD_TIME_MS = 50L
@@ -54,11 +56,9 @@ class PermGroupsPackagesUiInfoLiveData(
private val handler: Handler = Handler(Looper.getMainLooper())
- /**
- * Map<permission group name, PermGroupUiLiveDatas>
- */
- private val permGroupPackagesLiveDatas = mutableMapOf<String,
- SinglePermGroupPackagesUiInfoLiveData>()
+ /** Map<permission group name, PermGroupUiLiveDatas> */
+ private val permGroupPackagesLiveDatas =
+ mutableMapOf<String, SinglePermGroupPackagesUiInfoLiveData>()
private val allPackageData = mutableMapOf<String, PermGroupPackagesUiInfo?>()
private lateinit var groupNames: List<String>
@@ -78,7 +78,7 @@ class PermGroupsPackagesUiInfoLiveData(
private fun isGranted(grantState: AppPermGroupUiInfo.PermGrantState): Boolean {
return grantState != AppPermGroupUiInfo.PermGrantState.PERMS_DENIED &&
- grantState != AppPermGroupUiInfo.PermGrantState.PERMS_ASK
+ grantState != AppPermGroupUiInfo.PermGrantState.PERMS_ASK
}
private fun createPermGroupPackageUiInfo(
@@ -118,10 +118,19 @@ class PermGroupsPackagesUiInfoLiveData(
}
}
}
- val onlyShellGranted = grantedNonSystem == 0 && grantedSystem == 1 &&
+ val onlyShellGranted =
+ grantedNonSystem == 0 &&
+ grantedSystem == 1 &&
isPackageShell(firstGrantedSystemPackageName)
- return PermGroupPackagesUiInfo(groupName, nonSystem, grantedNonSystem,
- userInteractedNonSystem, grantedSystem, userInteractedSystem, onlyShellGranted)
+ return PermGroupPackagesUiInfo(
+ groupName,
+ nonSystem,
+ grantedNonSystem,
+ userInteractedNonSystem,
+ grantedSystem,
+ userInteractedSystem,
+ onlyShellGranted
+ )
}
private fun isPackageShell(packageName: String?): Boolean {
@@ -130,27 +139,30 @@ class PermGroupsPackagesUiInfoLiveData(
}
// This method is only called at most once per permission group, so no need to cache value
- val roleManager = Utils.getSystemServiceSafe(PermissionControllerApplication.get(),
- RoleManager::class.java)
+ val roleManager =
+ Utils.getSystemServiceSafe(
+ PermissionControllerApplication.get(),
+ RoleManager::class.java
+ )
return roleManager.getRoleHolders(SYSTEM_SHELL).contains(packageName)
}
override fun onUpdate() {
/**
- * Only update when either-
- * We have a list of groups, and none have loaded their data, or
+ * Only update when either- We have a list of groups, and none have loaded their data, or
* All packages have loaded their data
*/
val haveAllLiveDatas = groupNames.all { permGroupPackagesLiveDatas.contains(it) }
val allInitialized = permGroupPackagesLiveDatas.all { it.value.isInitialized }
for (groupName in groupNames) {
- allPackageData[groupName] = if (haveAllLiveDatas && allInitialized) {
- permGroupPackagesLiveDatas[groupName]?.value?.let { uiInfo ->
- createPermGroupPackageUiInfo(groupName, uiInfo)
+ allPackageData[groupName] =
+ if (haveAllLiveDatas && allInitialized) {
+ permGroupPackagesLiveDatas[groupName]?.value?.let { uiInfo ->
+ createPermGroupPackageUiInfo(groupName, uiInfo)
+ }
+ } else {
+ null
}
- } else {
- null
- }
}
value = allPackageData.toMap()
}
@@ -172,7 +184,7 @@ class PermGroupsPackagesUiInfoLiveData(
private fun addLiveDataDelayed(groupName: String, delayTimeMs: Long) {
val liveData = SinglePermGroupPackagesUiInfoLiveData[groupName]
permGroupPackagesLiveDatas[groupName] = liveData
- handler.postDelayed( { addSource(liveData) { update() } }, delayTimeMs)
+ handler.postDelayed({ addSource(liveData) { update() } }, delayTimeMs)
}
override fun onActive() {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PermStateLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PermStateLiveData.kt
index c385cf0e5..53d0da6f5 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PermStateLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PermStateLiveData.kt
@@ -28,21 +28,22 @@ import kotlinx.coroutines.Job
/**
* A LiveData which tracks the permission state for one permission group for one package. It
- * includes both the granted state of every permission in the group, and the flags stored
- * in the PermissionController service.
+ * includes both the granted state of every permission in the group, and the flags stored in the
+ * PermissionController service.
*
* @param app The current application
* @param packageName The name of the package this LiveData will watch for mode changes for
- * @param permGroupName The name of the permission group whose app ops this LiveData
- * will watch
+ * @param permGroupName The name of the permission group whose app ops this LiveData will watch
* @param user The user of the package
*/
-class PermStateLiveData private constructor(
+class PermStateLiveData
+private constructor(
private val app: Application,
private val packageName: String,
private val permGroupName: String,
private val user: UserHandle
-) : SmartAsyncMediatorLiveData<Map<String, PermState>>(),
+) :
+ SmartAsyncMediatorLiveData<Map<String, PermState>>(),
PermissionListenerMultiplexer.PermissionChangeCallback {
private val context = Utils.getUserContext(app, user)
@@ -58,9 +59,7 @@ class PermStateLiveData private constructor(
updateAsync()
}
- addSource(groupLiveData) {
- updateAsync()
- }
+ addSource(groupLiveData) { updateAsync() }
}
/**
@@ -84,10 +83,11 @@ class PermStateLiveData private constructor(
permissionGroup.permissionInfos[permissionName]?.let { permInfo ->
val packageFlags = packageInfo.requestedPermissionsFlags[index]
- val permFlags = context.packageManager.getPermissionFlags(permInfo.name,
- packageName, user)
- val granted = packageFlags and PackageInfo.REQUESTED_PERMISSION_GRANTED != 0 &&
- permFlags and PackageManager.FLAG_PERMISSION_REVOKED_COMPAT == 0
+ val permFlags =
+ context.packageManager.getPermissionFlags(permInfo.name, packageName, user)
+ val granted =
+ packageFlags and PackageInfo.REQUESTED_PERMISSION_GRANTED != 0 &&
+ permFlags and PackageManager.FLAG_PERMISSION_REVOKED_COMPAT == 0
if (job.isCancelled) {
return
@@ -105,15 +105,12 @@ class PermStateLiveData private constructor(
private fun checkForUidUpdate(packageInfo: LightPackageInfo?) {
if (packageInfo == null) {
- registeredUid?.let {
- PermissionListenerMultiplexer.removeCallback(it, this)
- }
+ registeredUid?.let { PermissionListenerMultiplexer.removeCallback(it, this) }
return
}
uid = packageInfo.uid
if (uid != registeredUid && hasActiveObservers()) {
- PermissionListenerMultiplexer.addOrReplaceCallback(
- registeredUid, packageInfo.uid, this)
+ PermissionListenerMultiplexer.addOrReplaceCallback(registeredUid, packageInfo.uid, this)
registeredUid = uid
}
}
@@ -136,14 +133,19 @@ class PermStateLiveData private constructor(
/**
* Repository for PermStateLiveDatas.
- * <p> Key value is a triple of string package name, string permission group name, and UserHandle,
- * value is its corresponding LiveData.
+ *
+ * <p> Key value is a triple of string package name, string permission group name, and
+ * UserHandle, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<Triple<String, String, UserHandle>,
- PermStateLiveData>() {
+ companion object :
+ DataRepositoryForPackage<Triple<String, String, UserHandle>, PermStateLiveData>() {
override fun newValue(key: Triple<String, String, UserHandle>): PermStateLiveData {
- return PermStateLiveData(PermissionControllerApplication.get(),
- key.first, key.second, key.third)
+ return PermStateLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second,
+ key.third
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionChange.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionChange.kt
index 29789b0f7..4959a7fba 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionChange.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionChange.kt
@@ -19,10 +19,8 @@ package com.android.permissioncontroller.permission.data
/**
* A record of the user changing permissions for the app but not including any information on what
* actual decision was made. This information is not included for privacy reasons and allows us to
- * persist the data for longer periods of time than we'd be able to otherwise
- * (e.g. [PermissionDecision]).
+ * persist the data for longer periods of time than we'd be able to otherwise (e.g.
+ * [PermissionDecision]).
*/
-data class PermissionChange(
- override val packageName: String,
- override val eventTime: Long
-) : PermissionEvent(packageName, eventTime)
+data class PermissionChange(override val packageName: String, override val eventTime: Long) :
+ PermissionEvent(packageName, eventTime)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionEvent.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionEvent.kt
index ad759795b..2fa64cd43 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionEvent.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionEvent.kt
@@ -20,10 +20,7 @@ package com.android.permissioncontroller.permission.data
* A record of a permission event caused by the user.
*
* @param packageName package name of the app the event is for
- * @param eventTime the time of the event, in epoch time. Should be rounded to day-level
- * precision for user privacy.
+ * @param eventTime the time of the event, in epoch time. Should be rounded to day-level precision
+ * for user privacy.
*/
-abstract class PermissionEvent(
- open val packageName: String,
- open val eventTime: Long
-)
+abstract class PermissionEvent(open val packageName: String, open val eventTime: Long)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionListenerMultiplexer.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionListenerMultiplexer.kt
index d6d532341..fb0f3077a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionListenerMultiplexer.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PermissionListenerMultiplexer.kt
@@ -20,24 +20,19 @@ import android.app.Application
import android.content.pm.PackageManager
import com.android.permissioncontroller.PermissionControllerApplication
-/**
- * Serves as a single shared Permission Change Listener for all AppPermissionGroupLiveDatas.
- *
- */
+/** Serves as a single shared Permission Change Listener for all AppPermissionGroupLiveDatas. */
object PermissionListenerMultiplexer : PackageManager.OnPermissionsChangedListener {
private val app: Application = PermissionControllerApplication.get()
/**
- * Map<UID, list of PermissionChangeCallbacks that wish to be informed when
- * permissions are updated for that UID>
+ * Map<UID, list of PermissionChangeCallbacks that wish to be informed when permissions are
+ * updated for that UID>
*/
private val callbacks = mutableMapOf<Int, MutableList<PermissionChangeCallback>>()
private val pm = app.applicationContext.packageManager
override fun onPermissionsChanged(uid: Int) {
- callbacks[uid]?.toList()?.forEach { callback ->
- callback.onPermissionChange()
- }
+ callbacks[uid]?.toList()?.forEach { callback -> callback.onPermissionChange() }
}
fun addOrReplaceCallback(oldUid: Int?, newUid: Int, callback: PermissionChangeCallback) {
@@ -78,4 +73,4 @@ object PermissionListenerMultiplexer : PackageManager.OnPermissionsChangedListen
interface PermissionChangeCallback {
fun onPermissionChange()
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PreinstalledUserPackageInfosLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PreinstalledUserPackageInfosLiveData.kt
index b4205acff..243fe5b03 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PreinstalledUserPackageInfosLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PreinstalledUserPackageInfosLiveData.kt
@@ -33,23 +33,23 @@ import kotlinx.coroutines.Job
* @param app The current application
* @param user The user whose packages are desired
*/
-class PreinstalledUserPackageInfosLiveData private constructor(
- private val app: Application,
- private val user: UserHandle
-) : SmartAsyncMediatorLiveData<@kotlin.jvm.JvmSuppressWildcards List<LightPackageInfo>>(
- isStaticVal = true, alwaysUpdateOnActive = false
-) {
+class PreinstalledUserPackageInfosLiveData
+private constructor(private val app: Application, private val user: UserHandle) :
+ SmartAsyncMediatorLiveData<@kotlin.jvm.JvmSuppressWildcards List<LightPackageInfo>>(
+ isStaticVal = true,
+ alwaysUpdateOnActive = false
+ ) {
- /**
- * Get all of the preinstalled packages in the system for this user
- */
+ /** Get all of the preinstalled packages in the system for this user */
override suspend fun loadDataAndPostValue(job: Job) {
if (job.isCancelled) {
return
}
- val packageInfos = app.applicationContext.packageManager
- .getInstalledPackagesAsUser(GET_PERMISSIONS or MATCH_UNINSTALLED_PACKAGES
- or MATCH_FACTORY_ONLY, user.identifier)
+ val packageInfos =
+ app.applicationContext.packageManager.getInstalledPackagesAsUser(
+ GET_PERMISSIONS or MATCH_UNINSTALLED_PACKAGES or MATCH_FACTORY_ONLY,
+ user.identifier
+ )
postValue(packageInfos.map { packageInfo -> LightPackageInfo(packageInfo) })
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/RoleHoldersLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/RoleHoldersLiveData.kt
index 2cf17fb95..744b5bdbd 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/RoleHoldersLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/RoleHoldersLiveData.kt
@@ -29,7 +29,8 @@ import kotlinx.coroutines.Job
* @param app The current application
* @param roleName The name of the role
*/
-class RoleHoldersLiveData private constructor(
+class RoleHoldersLiveData
+private constructor(
private val app: Application,
private val roleName: String,
private val user: UserHandle
@@ -57,6 +58,7 @@ class RoleHoldersLiveData private constructor(
/**
* Repository for RoleHoldersLiveData.
+ *
* <p> Key value is the name of the role.
*/
companion object : DataRepository<Pair<String, UserHandle>, RoleHoldersLiveData>() {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/RoleListenerMultiplexer.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/RoleListenerMultiplexer.kt
index ac853439d..fefaa5fc4 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/RoleListenerMultiplexer.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/RoleListenerMultiplexer.kt
@@ -23,16 +23,14 @@ import android.os.UserHandle
import androidx.annotation.GuardedBy
import com.android.permissioncontroller.PermissionControllerApplication
-/**
- * Serves as a single shared Role Change Listener.
- */
+/** Serves as a single shared Role Change Listener. */
object RoleListenerMultiplexer : OnRoleHoldersChangedListener {
private val app: Application = PermissionControllerApplication.get()
@GuardedBy("lock")
- private val callbacks = mutableMapOf<UserHandle,
- MutableMap<String, MutableList<RoleHoldersChangeCallback>>>()
+ private val callbacks =
+ mutableMapOf<UserHandle, MutableMap<String, MutableList<RoleHoldersChangeCallback>>>()
private val roleManager = app.getSystemService(RoleManager::class.java)!!
@@ -40,12 +38,8 @@ object RoleListenerMultiplexer : OnRoleHoldersChangedListener {
override fun onRoleHoldersChanged(roleName: String, user: UserHandle) {
val callbacksCopy: List<RoleHoldersChangeCallback>?
- synchronized(lock) {
- callbacksCopy = callbacks[user]?.get(roleName)?.toList()
- }
- callbacksCopy?.forEach { listener ->
- listener.onRoleHoldersChanged()
- }
+ synchronized(lock) { callbacksCopy = callbacks[user]?.get(roleName)?.toList() }
+ callbacksCopy?.forEach { listener -> listener.onRoleHoldersChanged() }
}
fun addCallback(roleName: String, user: UserHandle, callback: RoleHoldersChangeCallback) {
@@ -88,4 +82,4 @@ object RoleListenerMultiplexer : OnRoleHoldersChangedListener {
interface RoleHoldersChangeCallback {
fun onRoleHoldersChanged()
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedAutofillServiceLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedAutofillServiceLiveData.kt
index 9aced3e2b..3ab59237c 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedAutofillServiceLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedAutofillServiceLiveData.kt
@@ -29,20 +29,19 @@ import kotlinx.coroutines.Job
* @param app The current application
* @param user The user the services should be determined for
*/
-class SelectedAutofillServiceLiveData(
- private val app: Application,
- private val user: UserHandle
-) : SmartAsyncMediatorLiveData<String?>() {
+class SelectedAutofillServiceLiveData(private val app: Application, private val user: UserHandle) :
+ SmartAsyncMediatorLiveData<String?>() {
override suspend fun loadDataAndPostValue(job: Job) {
if (job.isCancelled) {
return
}
- val packageName = Utils.getUserContext(app, user)
- .getSystemService(AutofillManager::class.java)
- ?.autofillServiceComponentName
- ?.packageName
+ val packageName =
+ Utils.getUserContext(app, user)
+ .getSystemService(AutofillManager::class.java)
+ ?.autofillServiceComponentName
+ ?.packageName
postValue(packageName)
}
@@ -52,10 +51,9 @@ class SelectedAutofillServiceLiveData(
*
* <p> Key value is a user, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<UserHandle,
- SelectedAutofillServiceLiveData>() {
+ companion object : DataRepositoryForPackage<UserHandle, SelectedAutofillServiceLiveData>() {
override fun newValue(key: UserHandle): SelectedAutofillServiceLiveData {
return SelectedAutofillServiceLiveData(PermissionControllerApplication.get(), key)
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedVoiceInteractionServiceLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedVoiceInteractionServiceLiveData.kt
index 72a6da139..9bb749323 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedVoiceInteractionServiceLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedVoiceInteractionServiceLiveData.kt
@@ -40,12 +40,14 @@ class SelectedVoiceInteractionServiceLiveData(
return
}
- val packageName = Settings.Secure.getString(
- Utils.getUserContext(app, user).contentResolver,
- // Settings.Secure.VOICE_INTERACTION_SERVICE
- "voice_interaction_service")
- ?.let(ComponentName::unflattenFromString)
- ?.packageName
+ val packageName =
+ Settings.Secure.getString(
+ Utils.getUserContext(app, user).contentResolver,
+ // Settings.Secure.VOICE_INTERACTION_SERVICE
+ "voice_interaction_service"
+ )
+ ?.let(ComponentName::unflattenFromString)
+ ?.packageName
postValue(packageName)
}
@@ -55,11 +57,13 @@ class SelectedVoiceInteractionServiceLiveData(
*
* <p> Key value is a user, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<UserHandle,
- SelectedVoiceInteractionServiceLiveData>() {
+ companion object :
+ DataRepositoryForPackage<UserHandle, SelectedVoiceInteractionServiceLiveData>() {
override fun newValue(key: UserHandle): SelectedVoiceInteractionServiceLiveData {
return SelectedVoiceInteractionServiceLiveData(
- PermissionControllerApplication.get(), key)
+ PermissionControllerApplication.get(),
+ key
+ )
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedWallpaperServiceLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedWallpaperServiceLiveData.kt
index e4c1314c1..d004f79dc 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedWallpaperServiceLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/SelectedWallpaperServiceLiveData.kt
@@ -29,24 +29,23 @@ import kotlinx.coroutines.Job
* @param app The current application
* @param user The user the services should be determined for
*/
-class SelectedWallpaperServiceLiveData(
- private val app: Application,
- private val user: UserHandle
-) : SmartAsyncMediatorLiveData<String?>() {
+class SelectedWallpaperServiceLiveData(private val app: Application, private val user: UserHandle) :
+ SmartAsyncMediatorLiveData<String?>() {
override suspend fun loadDataAndPostValue(job: Job) {
if (job.isCancelled) {
return
}
- val packageName = try {
- Utils.getUserContext(app, user)
+ val packageName =
+ try {
+ Utils.getUserContext(app, user)
.getSystemService(WallpaperManager::class.java)
?.wallpaperInfo
?.packageName
- } catch (e: NullPointerException) {
- null
- }
+ } catch (e: NullPointerException) {
+ null
+ }
postValue(packageName)
}
@@ -56,10 +55,9 @@ class SelectedWallpaperServiceLiveData(
*
* <p> Key value is a user, value is its corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<UserHandle,
- SelectedWallpaperServiceLiveData>() {
+ companion object : DataRepositoryForPackage<UserHandle, SelectedWallpaperServiceLiveData>() {
override fun newValue(key: UserHandle): SelectedWallpaperServiceLiveData {
return SelectedWallpaperServiceLiveData(PermissionControllerApplication.get(), key)
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/ServiceLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/ServiceLiveData.kt
index 6d59fd585..2deae79cc 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/ServiceLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/ServiceLiveData.kt
@@ -49,9 +49,10 @@ class ServiceLiveData(
override val intentAction: String,
private val permission: String,
private val user: UserHandle
-) : SmartAsyncMediatorLiveData<Set<String>>(),
- PackageBroadcastReceiver.PackageBroadcastListener,
- HasIntentAction {
+) :
+ SmartAsyncMediatorLiveData<Set<String>>(),
+ PackageBroadcastReceiver.PackageBroadcastListener,
+ HasIntentAction {
private val name = intentAction.substringAfterLast(".")
@@ -60,7 +61,7 @@ class ServiceLiveData(
private val enabledNotificationListenersLiveData = EnabledNotificationListenersLiveData[user]
private val selectedWallpaperServiceLiveData = SelectedWallpaperServiceLiveData[user]
private val selectedVoiceInteractionServiceLiveData =
- SelectedVoiceInteractionServiceLiveData[user]
+ SelectedVoiceInteractionServiceLiveData[user]
private val selectedAutofillServiceLiveData = SelectedAutofillServiceLiveData[user]
private val enabledDreamServicesLiveData = EnabledDreamServicesLiveData[user]
private val disabledPrintServicesLiveData = DisabledPrintServicesLiveData[user]
@@ -68,49 +69,31 @@ class ServiceLiveData(
init {
if (intentAction == AccessibilityService.SERVICE_INTERFACE) {
- addSource(enabledAccessibilityServicesLiveData) {
- updateAsync()
- }
+ addSource(enabledAccessibilityServicesLiveData) { updateAsync() }
}
if (intentAction == InputMethod.SERVICE_INTERFACE) {
- addSource(enabledInputMethodsLiveData) {
- updateAsync()
- }
+ addSource(enabledInputMethodsLiveData) { updateAsync() }
}
if (intentAction == NotificationListenerService.SERVICE_INTERFACE) {
- addSource(enabledNotificationListenersLiveData) {
- updateAsync()
- }
+ addSource(enabledNotificationListenersLiveData) { updateAsync() }
}
if (intentAction == WallpaperService.SERVICE_INTERFACE) {
- addSource(selectedWallpaperServiceLiveData) {
- updateAsync()
- }
+ addSource(selectedWallpaperServiceLiveData) { updateAsync() }
}
if (intentAction == VoiceInteractionService.SERVICE_INTERFACE) {
- addSource(selectedVoiceInteractionServiceLiveData) {
- updateAsync()
- }
+ addSource(selectedVoiceInteractionServiceLiveData) { updateAsync() }
}
if (intentAction == AutofillService.SERVICE_INTERFACE) {
- addSource(selectedAutofillServiceLiveData) {
- updateAsync()
- }
+ addSource(selectedAutofillServiceLiveData) { updateAsync() }
}
if (intentAction == DreamService.SERVICE_INTERFACE) {
- addSource(enabledDreamServicesLiveData) {
- updateAsync()
- }
+ addSource(enabledDreamServicesLiveData) { updateAsync() }
}
if (intentAction == PrintService.SERVICE_INTERFACE) {
- addSource(disabledPrintServicesLiveData) {
- updateAsync()
- }
+ addSource(disabledPrintServicesLiveData) { updateAsync() }
}
if (intentAction == DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE) {
- addSource(enabledDeviceAdminsLiveDataLiveData) {
- updateAsync()
- }
+ addSource(enabledDeviceAdminsLiveDataLiveData) { updateAsync() }
}
}
@@ -122,48 +105,69 @@ class ServiceLiveData(
if (job.isCancelled) {
return
}
- if (intentAction == AccessibilityService.SERVICE_INTERFACE &&
- !enabledAccessibilityServicesLiveData.isInitialized) {
+ if (
+ intentAction == AccessibilityService.SERVICE_INTERFACE &&
+ !enabledAccessibilityServicesLiveData.isInitialized
+ ) {
return
}
- if (intentAction == InputMethod.SERVICE_INTERFACE &&
- !enabledInputMethodsLiveData.isInitialized) {
+ if (
+ intentAction == InputMethod.SERVICE_INTERFACE &&
+ !enabledInputMethodsLiveData.isInitialized
+ ) {
return
}
- if (intentAction == NotificationListenerService.SERVICE_INTERFACE &&
- !enabledNotificationListenersLiveData.isInitialized) {
+ if (
+ intentAction == NotificationListenerService.SERVICE_INTERFACE &&
+ !enabledNotificationListenersLiveData.isInitialized
+ ) {
return
}
- if (intentAction == WallpaperService.SERVICE_INTERFACE &&
- !selectedWallpaperServiceLiveData.isInitialized) {
+ if (
+ intentAction == WallpaperService.SERVICE_INTERFACE &&
+ !selectedWallpaperServiceLiveData.isInitialized
+ ) {
return
}
- if (intentAction == VoiceInteractionService.SERVICE_INTERFACE &&
- !selectedVoiceInteractionServiceLiveData.isInitialized) {
+ if (
+ intentAction == VoiceInteractionService.SERVICE_INTERFACE &&
+ !selectedVoiceInteractionServiceLiveData.isInitialized
+ ) {
return
}
- if (intentAction == AutofillService.SERVICE_INTERFACE &&
- !selectedAutofillServiceLiveData.isInitialized) {
+ if (
+ intentAction == AutofillService.SERVICE_INTERFACE &&
+ !selectedAutofillServiceLiveData.isInitialized
+ ) {
return
}
- if (intentAction == DreamService.SERVICE_INTERFACE &&
- !enabledDreamServicesLiveData.isInitialized) {
+ if (
+ intentAction == DreamService.SERVICE_INTERFACE &&
+ !enabledDreamServicesLiveData.isInitialized
+ ) {
return
}
- if (intentAction == PrintService.SERVICE_INTERFACE &&
- !disabledPrintServicesLiveData.isInitialized) {
+ if (
+ intentAction == PrintService.SERVICE_INTERFACE &&
+ !disabledPrintServicesLiveData.isInitialized
+ ) {
return
}
- if (intentAction == DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE &&
- !enabledDeviceAdminsLiveDataLiveData.isInitialized) {
+ if (
+ intentAction == DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE &&
+ !enabledDeviceAdminsLiveDataLiveData.isInitialized
+ ) {
return
}
- val packageNames = getUserContext(app, user).packageManager
+ val packageNames =
+ getUserContext(app, user)
+ .packageManager
.queryIntentServices(
- Intent(intentAction),
- PackageManager.GET_SERVICES or PackageManager.GET_META_DATA)
+ Intent(intentAction),
+ PackageManager.GET_SERVICES or PackageManager.GET_META_DATA
+ )
.mapNotNull { resolveInfo ->
if (resolveInfo?.serviceInfo?.permission != permission) {
return@mapNotNull null
@@ -171,17 +175,19 @@ class ServiceLiveData(
val packageName = resolveInfo.serviceInfo?.packageName
if (!isServiceEnabled(packageName)) {
if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG,
- "Not exempting $packageName - not an active $name " +
- "for u${user.identifier}")
+ DumpableLog.i(
+ LOG_TAG,
+ "Not exempting $packageName - not an active $name " +
+ "for u${user.identifier}"
+ )
}
return@mapNotNull null
}
packageName
- }.toSet()
+ }
+ .toSet()
if (DEBUG_HIBERNATION_POLICY) {
- DumpableLog.i(LOG_TAG,
- "Detected ${name}s: $packageNames")
+ DumpableLog.i(LOG_TAG, "Detected ${name}s: $packageNames")
}
postValue(packageNames)
@@ -241,13 +247,17 @@ class ServiceLiveData(
* <p> Key value is a (string service name, required permission, user) triple, value is its
* corresponding LiveData.
*/
- companion object : DataRepositoryForPackage<Triple<String, String, UserHandle>,
- ServiceLiveData>() {
+ companion object :
+ DataRepositoryForPackage<Triple<String, String, UserHandle>, ServiceLiveData>() {
private const val LOG_TAG = "ServiceLiveData"
override fun newValue(key: Triple<String, String, UserHandle>): ServiceLiveData {
- return ServiceLiveData(PermissionControllerApplication.get(),
- key.first, key.second, key.third)
+ return ServiceLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second,
+ key.third
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/SinglePermGroupPackagesUiInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/SinglePermGroupPackagesUiInfoLiveData.kt
index a46882c04..b2348a17a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/SinglePermGroupPackagesUiInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/SinglePermGroupPackagesUiInfoLiveData.kt
@@ -19,8 +19,8 @@ package com.android.permissioncontroller.permission.data
import android.app.Application
import android.os.UserHandle
import com.android.permissioncontroller.PermissionControllerApplication
-import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo
+import com.android.permissioncontroller.permission.utils.PermissionMapping
/**
* LiveData for the UI info for all packages in a single permission group. Tracks which packages
@@ -30,26 +30,21 @@ import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGr
* @param app The current application
* @param permGroupName The name of the permission group this LiveData represents
*/
-class SinglePermGroupPackagesUiInfoLiveData private constructor(
- private val app: Application,
- private val permGroupName: String
-) : SmartUpdateMediatorLiveData<Map<Pair<String, UserHandle>, AppPermGroupUiInfo>>() {
+class SinglePermGroupPackagesUiInfoLiveData
+private constructor(private val app: Application, private val permGroupName: String) :
+ SmartUpdateMediatorLiveData<Map<Pair<String, UserHandle>, AppPermGroupUiInfo>>() {
private val permGroupLiveData = PermGroupLiveData[permGroupName]
private val isCustomGroup =
!PermissionMapping.getPlatformPermissionGroups().contains(permGroupName)
- private val permGroupPackagesLiveData = PermGroupsPackagesLiveData.get(
- customGroups = isCustomGroup)
+ private val permGroupPackagesLiveData =
+ PermGroupsPackagesLiveData.get(customGroups = isCustomGroup)
- /**
- * Map<Pair<package name, UserHandle>, UI data LiveData>
- */
- private val appPermGroupLiveDatas = mutableMapOf<Pair<String, UserHandle>,
- AppPermGroupUiInfoLiveData>()
+ /** Map<Pair<package name, UserHandle>, UI data LiveData> */
+ private val appPermGroupLiveDatas =
+ mutableMapOf<Pair<String, UserHandle>, AppPermGroupUiInfoLiveData>()
- /**
- * Map<Pair<packageName, userHandle>, UI data>.
- */
+ /** Map<Pair<packageName, userHandle>, UI data>. */
private val shownPackages = mutableMapOf<Pair<String, UserHandle>, AppPermGroupUiInfo>()
init {
@@ -60,9 +55,7 @@ class SinglePermGroupPackagesUiInfoLiveData private constructor(
}
}
- addSource(permGroupPackagesLiveData) {
- update()
- }
+ addSource(permGroupPackagesLiveData) { update() }
}
override fun onUpdate() {
@@ -71,9 +64,7 @@ class SinglePermGroupPackagesUiInfoLiveData private constructor(
addAndRemoveAppPermGroupLiveDatas(thisPermGroupPackages.toList())
if (thisPermGroupPackages.isEmpty()) {
- permGroupLiveData.value?.groupInfo?.let {
- value = emptyMap()
- }
+ permGroupLiveData.value?.groupInfo?.let { value = emptyMap() }
}
}
}
@@ -83,48 +74,46 @@ class SinglePermGroupPackagesUiInfoLiveData private constructor(
AppPermGroupUiInfoLiveData[key.first, permGroupName, key.second]
}
- val (_, removed) = setSourcesToDifference(pkgs, appPermGroupLiveDatas, getLiveData) { key ->
- val appPermGroupUiInfoLiveData = appPermGroupLiveDatas[key]
- val appPermGroupUiInfo = appPermGroupUiInfoLiveData?.value
- shownPackages.remove(key)
-
- if (appPermGroupUiInfo == null) {
- if (appPermGroupUiInfoLiveData != null &&
- appPermGroupUiInfoLiveData.isInitialized) {
- removeSource(appPermGroupUiInfoLiveData)
- appPermGroupLiveDatas.remove(key)
+ val (_, removed) =
+ setSourcesToDifference(pkgs, appPermGroupLiveDatas, getLiveData) { key ->
+ val appPermGroupUiInfoLiveData = appPermGroupLiveDatas[key]
+ val appPermGroupUiInfo = appPermGroupUiInfoLiveData?.value
+ shownPackages.remove(key)
+
+ if (appPermGroupUiInfo == null) {
+ if (
+ appPermGroupUiInfoLiveData != null &&
+ appPermGroupUiInfoLiveData.isInitialized
+ ) {
+ removeSource(appPermGroupUiInfoLiveData)
+ appPermGroupLiveDatas.remove(key)
+ }
+ } else {
+ shownPackages[key] = appPermGroupUiInfo
}
- } else {
- shownPackages[key] = appPermGroupUiInfo
- }
- if (appPermGroupLiveDatas.all { entry -> entry.value.isInitialized }) {
- permGroupLiveData.value?.groupInfo?.let {
- value = shownPackages.toMap()
+ if (appPermGroupLiveDatas.all { entry -> entry.value.isInitialized }) {
+ permGroupLiveData.value?.groupInfo?.let { value = shownPackages.toMap() }
}
}
- }
for (removedKey in removed) {
shownPackages.remove(removedKey)
}
if (appPermGroupLiveDatas.all { entry -> entry.value.isInitialized }) {
- permGroupLiveData.value?.groupInfo?.let {
- value = shownPackages.toMap()
- }
+ permGroupLiveData.value?.groupInfo?.let { value = shownPackages.toMap() }
}
}
/**
* Repository for SinglePermGroupPackagesUiInfoLiveData objects.
+ *
* <p> Key value is a string permission group name, value is its corresponding LiveData.
*/
- companion object : DataRepository<String,
- SinglePermGroupPackagesUiInfoLiveData>() {
+ companion object : DataRepository<String, SinglePermGroupPackagesUiInfoLiveData>() {
override fun newValue(key: String): SinglePermGroupPackagesUiInfoLiveData {
- return SinglePermGroupPackagesUiInfoLiveData(PermissionControllerApplication.get(),
- key)
+ return SinglePermGroupPackagesUiInfoLiveData(PermissionControllerApplication.get(), key)
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/SmartAsyncMediatorLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/SmartAsyncMediatorLiveData.kt
index b7491a7a4..1cc248956 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/SmartAsyncMediatorLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/SmartAsyncMediatorLiveData.kt
@@ -36,14 +36,12 @@ abstract class SmartAsyncMediatorLiveData<T>(
) : SmartUpdateMediatorLiveData<T>(isStaticVal) {
private var currentJob: Job? = null
- @Volatile
- private var jobQueued = false
- @Volatile
- private var jobRunning = false
+ @Volatile private var jobQueued = false
+ @Volatile private var jobRunning = false
/**
- * The main function which will load data. It should periodically check isCancelled to see if
- * it should stop working. If data is loaded, it should call "postValue".
+ * The main function which will load data. It should periodically check isCancelled to see if it
+ * should stop working. If data is loaded, it should call "postValue".
*/
abstract suspend fun loadDataAndPostValue(job: Job)
@@ -67,9 +65,7 @@ abstract class SmartAsyncMediatorLiveData<T>(
jobRunning = false
if (jobQueued) {
jobQueued = false
- GlobalScope.launch(Main.immediate) {
- updateAsync()
- }
+ GlobalScope.launch(Main.immediate) { updateAsync() }
}
}
}
@@ -95,4 +91,4 @@ abstract class SmartAsyncMediatorLiveData<T>(
}
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/SmartUpdateMediatorLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/SmartUpdateMediatorLiveData.kt
index d7fe4fb2e..9cc100e38 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/SmartUpdateMediatorLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/SmartUpdateMediatorLiveData.kt
@@ -31,8 +31,8 @@ import kotlinx.coroutines.launch
/**
* A MediatorLiveData which tracks how long it has been inactive, compares new values before setting
- * its value (avoiding unnecessary updates), and can calculate the set difference between a list
- * and a map (used when determining whether or not to add a LiveData as a source).
+ * its value (avoiding unnecessary updates), and can calculate the set difference between a list and
+ * a map (used when determining whether or not to add a LiveData as a source).
*
* @param isStaticVal Whether or not this LiveData value is expected to change
*/
@@ -46,8 +46,8 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
/**
* Boolean, whether or not the value of this uiDataLiveData has been explicitly set yet.
- * Differentiates between "null value because liveData is new" and "null value because
- * liveData is invalid"
+ * Differentiates between "null value because liveData is new" and "null value because liveData
+ * is invalid"
*/
var isInitialized = false
private set
@@ -105,8 +105,7 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
onUpdate()
}
- @MainThread
- protected abstract fun onUpdate()
+ @MainThread protected abstract fun onUpdate()
override var timeWentInactive: Long? = System.nanoTime()
@@ -116,7 +115,6 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
*
* @param valOne The first T to be compared
* @param valTwo The second T to be compared
- *
* @return True if the two values are different, false otherwise
*/
protected open fun valueNotEqual(valOne: T?, valTwo: T?): Boolean {
@@ -124,8 +122,11 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
}
override fun <S : Any?> addSource(source: LiveData<S>, onChanged: Observer<in S>) {
- addSourceWithStackTraceAttribution(source, onChanged,
- IllegalStateException().getStackTrace())
+ addSourceWithStackTraceAttribution(
+ source,
+ onChanged,
+ IllegalStateException().getStackTrace()
+ )
}
private fun <S : Any?> addSourceWithStackTraceAttribution(
@@ -167,8 +168,7 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
* @param have The map of livedatas we currently have as sources
* @param getLiveDataFun A function to turn a key into a liveData
* @param onUpdateFun An optional function which will update differently based on different
- * LiveDatas. If blank, will simply call update.
- *
+ * LiveDatas. If blank, will simply call update.
* @return a pair of (all keys added, all keys removed)
*/
fun <K, V : LiveData<*>> setSourcesToDifference(
@@ -176,7 +176,7 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
have: MutableMap<K, V>,
getLiveDataFun: (K) -> V,
onUpdateFun: ((K) -> Unit)? = null
- ): Pair<Set<K>, Set<K>>{
+ ): Pair<Set<K>, Set<K>> {
// Ensure the map is correct when method returns
val (toAdd, toRemove) = KotlinUtils.getMapAndListDifferences(desired, have)
for (key in toAdd) {
@@ -201,13 +201,14 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
val liveData = getLiveDataFun(key)
// Should be a no op, but there is a slight possibility it isn't
have[key] = liveData
- val observer = Observer<Any?> {
- if (onUpdateFun != null) {
- onUpdateFun(key)
- } else {
- update()
+ val observer =
+ Observer<Any?> {
+ if (onUpdateFun != null) {
+ onUpdateFun(key)
+ } else {
+ update()
+ }
}
- }
addSourceWithStackTraceAttribution(liveData, observer, stackTrace)
}
}
@@ -218,8 +219,11 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
timeWentInactive = null
// If this is not an async livedata, and we have sources, and all sources are non-stale,
// force update our value
- if (sources.isNotEmpty() && sources.all { !it.isStale } &&
- this !is SmartAsyncMediatorLiveData<T>) {
+ if (
+ sources.isNotEmpty() &&
+ sources.all { !it.isStale } &&
+ this !is SmartAsyncMediatorLiveData<T>
+ ) {
update()
}
super.onActive()
@@ -247,6 +251,7 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
update()
}
},
- isInitialized = { isInitialized && (staleOk || !isStale) })
+ isInitialized = { isInitialized && (staleOk || !isStale) }
+ )
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/StandardPermGroupNamesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/StandardPermGroupNamesLiveData.kt
index 3b3b76171..a3b1799de 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/StandardPermGroupNamesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/StandardPermGroupNamesLiveData.kt
@@ -19,9 +19,7 @@ package com.android.permissioncontroller.permission.data
import androidx.lifecycle.LiveData
import com.android.permissioncontroller.permission.utils.PermissionMapping
-/**
- * A LiveData which tracks Platform Permission Group names.
- */
+/** A LiveData which tracks Platform Permission Group names. */
object StandardPermGroupNamesLiveData : LiveData<List<String>>() {
init {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/UnusedPackagesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/UnusedPackagesLiveData.kt
index b97c27501..89bb93dbd 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/UnusedPackagesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/UnusedPackagesLiveData.kt
@@ -28,11 +28,12 @@ import com.android.permissioncontroller.hibernation.lastTimePackageUsed
import com.android.permissioncontroller.permission.utils.Utils
/**
- * Gets all unused packages from an existing live data that have not been opened in a few months
- * and the permission groups that have been revoked for them, if any. This will let us removed used
- * apps from the Unused Apps screen.
+ * Gets all unused packages from an existing live data that have not been opened in a few months and
+ * the permission groups that have been revoked for them, if any. This will let us removed used apps
+ * from the Unused Apps screen.
*
* @param sourceLiveData the live data for packages to base this list of unused apps on
+ *
* ```(packageName, user) -> [groupName]```
*/
class UnusedPackagesLiveData(
@@ -45,15 +46,9 @@ class UnusedPackagesLiveData(
private var usageStatsLiveData = UsageStatsLiveData[unusedThreshold]
init {
- addSource(usageStatsLiveData) {
- update()
- }
- addSource(AutoRevokedPackagesLiveData) {
- update()
- }
- addSource(sourceLiveData) {
- update()
- }
+ addSource(usageStatsLiveData) { update() }
+ addSource(AutoRevokedPackagesLiveData) { update() }
+ addSource(sourceLiveData) { update() }
DeviceConfig.addOnPropertiesChangedListener(
NAMESPACE_PERMISSIONS,
PermissionControllerApplication.get().mainExecutor,
@@ -63,9 +58,7 @@ class UnusedPackagesLiveData(
removeSource(usageStatsLiveData)
unusedThreshold = getUnusedThresholdMs()
usageStatsLiveData = UsageStatsLiveData[unusedThreshold]
- addSource(usageStatsLiveData) {
- update()
- }
+ addSource(usageStatsLiveData) { update() }
}
}
}
@@ -73,9 +66,11 @@ class UnusedPackagesLiveData(
}
override fun onUpdate() {
- if (!usageStatsLiveData.isInitialized ||
- !AutoRevokedPackagesLiveData.isInitialized ||
- !sourceLiveData.isInitialized) {
+ if (
+ !usageStatsLiveData.isInitialized ||
+ !AutoRevokedPackagesLiveData.isInitialized ||
+ !sourceLiveData.isInitialized
+ ) {
return
}
@@ -92,8 +87,10 @@ class UnusedPackagesLiveData(
for ((user, stats) in usageStatsLiveData.value!!) {
for (stat in stats) {
val userPackage = stat.packageName to user
- if (userPackage in autoRevokedPackages &&
- (now - stat.lastTimePackageUsed()) < unusedThreshold) {
+ if (
+ userPackage in autoRevokedPackages &&
+ (now - stat.lastTimePackageUsed()) < unusedThreshold
+ ) {
unusedPackages.remove(userPackage)
}
}
@@ -111,4 +108,4 @@ fun getUnusedPackages(): UnusedPackagesLiveData {
} else {
unusedAutoRevokePackagesLiveData
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/UsageStatsLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/UsageStatsLiveData.kt
index b7a44d1d3..72ff21a0a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/UsageStatsLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/UsageStatsLiveData.kt
@@ -30,19 +30,18 @@ import kotlinx.coroutines.Job
*
* @param app The current application
* @param searchTimeMs The length of time, in milliseconds, that this LiveData will track. The time
- * will start when the liveData is loaded, and extend backwards searchTimeMs milliseconds.
+ * will start when the liveData is loaded, and extend backwards searchTimeMs milliseconds.
* @param interval The interval to measure in. Default is monthly.
*/
-class UsageStatsLiveData private constructor(
+class UsageStatsLiveData
+private constructor(
private val app: Application,
private val searchTimeMs: Long,
private val interval: Int = INTERVAL_MONTHLY
) : SmartAsyncMediatorLiveData<Map<UserHandle, List<UsageStats>>>() {
init {
- addSource(UsersLiveData) {
- update()
- }
+ addSource(UsersLiveData) { update() }
}
override suspend fun loadDataAndPostValue(job: Job) {
@@ -58,8 +57,8 @@ class UsageStatsLiveData private constructor(
if (Utils.isUserDisabledOrWorkProfile(user)) {
continue
}
- val statsManager = Utils.getUserContext(app, user).getSystemService(
- UsageStatsManager::class.java)!!
+ val statsManager =
+ Utils.getUserContext(app, user).getSystemService(UsageStatsManager::class.java)!!
statsManager.queryUsageStats(interval, now - searchTimeMs, now)?.let { stats ->
userMap[user] = stats
}
@@ -77,4 +76,4 @@ class UsageStatsLiveData private constructor(
return get(interval to INTERVAL_MONTHLY)
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/UserPackageInfosLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/UserPackageInfosLiveData.kt
index 02285809c..884772f37 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/UserPackageInfosLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/UserPackageInfosLiveData.kt
@@ -85,11 +85,13 @@ private constructor(private val app: Application, private val user: UserHandle)
)
} else if (SdkLevel.isAtLeastS()) {
app.applicationContext.packageManager.getInstalledPackagesAsUser(
- GET_PERMISSIONS or GET_ATTRIBUTIONS or MATCH_ALL, user.identifier
+ GET_PERMISSIONS or GET_ATTRIBUTIONS or MATCH_ALL,
+ user.identifier
)
} else {
app.applicationContext.packageManager.getInstalledPackagesAsUser(
- GET_PERMISSIONS or MATCH_ALL, user.identifier
+ GET_PERMISSIONS or MATCH_ALL,
+ user.identifier
)
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/UserSensitivityLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/UserSensitivityLiveData.kt
index c138dc36d..fe4517173 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/UserSensitivityLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/UserSensitivityLiveData.kt
@@ -23,25 +23,25 @@ import android.content.pm.PackageManager
import android.os.Process
import android.os.Process.INVALID_UID
import android.os.UserHandle
-
import com.android.permissioncontroller.PermissionControllerApplication
-import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.model.livedatatypes.UidSensitivityState
import com.android.permissioncontroller.permission.utils.KotlinUtils
+import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.Utils
-import kotlinx.coroutines.Job
import java.lang.IllegalArgumentException
+import kotlinx.coroutines.Job
/**
- * Live data of the user sensitivity of either one uid, or all uids that belong to a user.
- * Maps <uid, user sensitive state>
+ * Live data of the user sensitivity of either one uid, or all uids that belong to a user. Maps
+ * <uid, user sensitive state>
*
* @param app The current application
* @param uid The uid whose user sensitivity we would like to observer, or INVALID_UID if we want
- * all uids for a user
+ * all uids for a user
* @param user The user for whom we want the uid/s
*/
-class UserSensitivityLiveData private constructor(
+class UserSensitivityLiveData
+private constructor(
private val app: Application,
private val uid: Int,
private val user: UserHandle
@@ -60,12 +60,8 @@ class UserSensitivityLiveData private constructor(
}
if (getAllUids) {
- addSource(userPackageInfosLiveData) {
- update()
- }
- addSource(LauncherPackagesLiveData) {
- update()
- }
+ addSource(userPackageInfosLiveData) { update() }
+ addSource(LauncherPackagesLiveData) { update() }
} else {
update()
}
@@ -76,10 +72,10 @@ class UserSensitivityLiveData private constructor(
if (!getAllUids) {
val uidHasPackages = getAndObservePackageLiveDatas()
- if (!uidHasPackages || packageLiveDatas.all {
- it.value.isInitialized &&
- it.value.value == null
- }) {
+ if (
+ !uidHasPackages ||
+ packageLiveDatas.all { it.value.isInitialized && it.value.value == null }
+ ) {
packageLiveDatas.clear()
invalidateSingle(uid to user)
postValue(null)
@@ -88,11 +84,12 @@ class UserSensitivityLiveData private constructor(
return
}
}
- val pkgs = if (getAllUids) {
- userPackageInfosLiveData.value ?: return
- } else {
- packageLiveDatas.mapNotNull { it.value.value }
- }
+ val pkgs =
+ if (getAllUids) {
+ userPackageInfosLiveData.value ?: return
+ } else {
+ packageLiveDatas.mapNotNull { it.value.value }
+ }
if (job.isCancelled) {
return
}
@@ -105,17 +102,19 @@ class UserSensitivityLiveData private constructor(
for (pkg in pkgs) {
// sensitivityState for one uid
- val userSensitiveState = sensitiveStatePerUid.getOrPut(pkg.uid) {
- UidSensitivityState(mutableSetOf(), mutableMapOf())
- }
+ val userSensitiveState =
+ sensitiveStatePerUid.getOrPut(pkg.uid) {
+ UidSensitivityState(mutableSetOf(), mutableMapOf())
+ }
userSensitiveState.packages.add(pkg)
- val pkgHasLauncherIcon = if (getAllUids) {
- // The launcher packages set will only be null when it is uninitialized.
- LauncherPackagesLiveData.value?.contains(pkg.packageName) ?: return
- } else {
- KotlinUtils.packageHasLaunchIntent(context, pkg.packageName)
- }
+ val pkgHasLauncherIcon =
+ if (getAllUids) {
+ // The launcher packages set will only be null when it is uninitialized.
+ LauncherPackagesLiveData.value?.contains(pkg.packageName) ?: return
+ } else {
+ KotlinUtils.packageHasLaunchIntent(context, pkg.packageName)
+ }
val pkgIsSystemApp = pkg.appFlags and ApplicationInfo.FLAG_SYSTEM != 0
// Iterate through all runtime perms, setting their keys
for (perm in pkg.requestedPermissions.intersect(runtimePerms)) {
@@ -125,18 +124,20 @@ class UserSensitivityLiveData private constructor(
* - the permission is not pre-granted, or
* - the package is not a system app (i.e. not preinstalled)
*/
- var flags = if (pkgIsSystemApp && !pkgHasLauncherIcon) {
- val permGrantedByDefault = pm.getPermissionFlags(perm, pkg.packageName,
- user) and PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT != 0
-
- if (permGrantedByDefault) {
- 0
+ var flags =
+ if (pkgIsSystemApp && !pkgHasLauncherIcon) {
+ val permGrantedByDefault =
+ pm.getPermissionFlags(perm, pkg.packageName, user) and
+ PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT != 0
+
+ if (permGrantedByDefault) {
+ 0
+ } else {
+ PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED
+ }
} else {
- PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED
+ Utils.FLAGS_ALWAYS_USER_SENSITIVE
}
- } else {
- Utils.FLAGS_ALWAYS_USER_SENSITIVE
- }
/*
* If two packages share a UID there can be two cases:
@@ -147,11 +148,12 @@ class UserSensitivityLiveData private constructor(
*/
val previousFlags = userSensitiveState.permStates[perm]
if (previousFlags != null) {
- flags = if (pkg.uid < Process.FIRST_APPLICATION_UID) {
- flags and previousFlags
- } else {
- flags or previousFlags
- }
+ flags =
+ if (pkg.uid < Process.FIRST_APPLICATION_UID) {
+ flags and previousFlags
+ } else {
+ flags or previousFlags
+ }
}
userSensitiveState.permStates[perm] = flags
@@ -173,13 +175,17 @@ class UserSensitivityLiveData private constructor(
/**
* Repository for a UserSensitivityLiveData
- * <p> Key value is a pair of int uid (INVALID_UID for all uids), and UserHandle,
- * value is its corresponding LiveData.
+ *
+ * <p> Key value is a pair of int uid (INVALID_UID for all uids), and UserHandle, value is its
+ * corresponding LiveData.
*/
companion object : DataRepository<Pair<Int, UserHandle>, UserSensitivityLiveData>() {
override fun newValue(key: Pair<Int, UserHandle>): UserSensitivityLiveData {
- return UserSensitivityLiveData(PermissionControllerApplication.get(), key.first,
- key.second)
+ return UserSensitivityLiveData(
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second
+ )
}
/**
@@ -187,7 +193,6 @@ class UserSensitivityLiveData private constructor(
* throw an exception if the uid is INVALID_UID.
*
* @param uid The uid for which we want the liveData
- *
* @return The liveData associated with the given UID
*/
operator fun get(uid: Int): UserSensitivityLiveData {
@@ -201,7 +206,6 @@ class UserSensitivityLiveData private constructor(
* Gets a liveData for a user, which will track all uids under
*
* @param user The user for whom we want the liveData
- *
* @return The liveData associated with that user, for all uids
*/
operator fun get(user: UserHandle): UserSensitivityLiveData {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/UsersLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/UsersLiveData.kt
index 0e78ec5f6..0fe3f6007 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/UsersLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/UsersLiveData.kt
@@ -23,31 +23,26 @@ import android.content.Intent
import android.content.IntentFilter
import android.os.UserHandle
import android.os.UserManager
-
import com.android.permissioncontroller.PermissionControllerApplication
-import com.android.permissioncontroller.permission.utils.Utils
/**
* Live data of the users of the current profile group.
*
- *
* Data source: system server
*/
object UsersLiveData : SmartUpdateMediatorLiveData<List<UserHandle>>() {
- @SuppressLint("StaticFieldLeak")
- private val app = PermissionControllerApplication.get()
+ @SuppressLint("StaticFieldLeak") private val app = PermissionControllerApplication.get()
- /** Monitors changes to the users on this device */
- private val mUserMonitor = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- onUpdate()
+ /** Monitors changes to the users on this device */
+ private val mUserMonitor =
+ object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ onUpdate()
+ }
}
- }
- /**
- * Update the encapsulated data with the current list of users.
- */
+ /** Update the encapsulated data with the current list of users. */
override fun onUpdate() {
value = app.getSystemService(UserManager::class.java)!!.userProfiles
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightPackageOpsLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightPackageOpsLiveData.kt
index 6483c9f9c..74b29043d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightPackageOpsLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightPackageOpsLiveData.kt
@@ -117,7 +117,9 @@ class AllLightPackageOpsLiveData(app: Application) :
.filter { UserHandle.getUserHandleForUid(it.uid) in allProfilesInCurrentUser }
.associateBy(
{ Pair(it.packageName, UserHandle.getUserHandleForUid(it.uid)) },
- { LightPackageOps(opNames, it) }))
+ { LightPackageOps(opNames, it) }
+ )
+ )
}
override fun onOpChanged(op: String?, packageName: String?) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/v33/RecentPermissionDecisionsLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/v33/RecentPermissionDecisionsLiveData.kt
index 4c18d6987..ec4f936b7 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/v33/RecentPermissionDecisionsLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/v33/RecentPermissionDecisionsLiveData.kt
@@ -20,8 +20,8 @@ import android.os.Build
import androidx.annotation.RequiresApi
import androidx.annotation.VisibleForTesting
import com.android.permissioncontroller.permission.data.SmartAsyncMediatorLiveData
-import com.android.permissioncontroller.permission.service.v33.PermissionDecisionStorageImpl
import com.android.permissioncontroller.permission.service.PermissionEventStorage
+import com.android.permissioncontroller.permission.service.v33.PermissionDecisionStorageImpl
import kotlinx.coroutines.Job
/** Gets all recent permission decisions made by the user. */
@@ -39,8 +39,6 @@ class RecentPermissionDecisionsLiveData(
// no need to subscribe to decision changes, since those will also be bubbled up through
// package info changes
- recentDecisionsStorage.loadEvents().also {
- postValue(it)
- }
+ recentDecisionsStorage.loadEvents().also { postValue(it) }
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/v34/AppDataSharingUpdatesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/v34/AppDataSharingUpdatesLiveData.kt
index d5fd59242..7844a172f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/v34/AppDataSharingUpdatesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/v34/AppDataSharingUpdatesLiveData.kt
@@ -40,14 +40,16 @@ class AppDataSharingUpdatesLiveData(val app: Application) :
DeviceConfig.getLong(
DeviceConfig.NAMESPACE_PRIVACY,
PROPERTY_DATA_SHARING_UPDATE_PERIOD_MILLIS,
- Duration.ofDays(DEFAULT_DATA_SHARING_UPDATE_PERIOD_DAYS).toMillis())
+ Duration.ofDays(DEFAULT_DATA_SHARING_UPDATE_PERIOD_DAYS).toMillis()
+ )
val file =
AppsSafetyLabelHistoryPersistence.getSafetyLabelHistoryFile(app.applicationContext)
val appSafetyLabelDiffsFromPersistence =
AppsSafetyLabelHistoryPersistence.getAppSafetyLabelDiffs(
Instant.now().atZone(ZoneId.systemDefault()).toInstant().minusMillis(updatePeriod),
- file)
+ file
+ )
val updatesFromPersistence =
appSafetyLabelDiffsFromPersistence.mapNotNull { it.buildUpdateIfSignificantChange() }
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/v34/LightInstallSourceInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/v34/LightInstallSourceInfoLiveData.kt
index bbc62dfc9..716d8dfe5 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/v34/LightInstallSourceInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/v34/LightInstallSourceInfoLiveData.kt
@@ -74,7 +74,9 @@ private constructor(
try {
val installSourceInfo = getInstallSourceInfo(packageName)
LightInstallSourceInfo(
- installSourceInfo.packageSource, installSourceInfo.initiatingPackageName)
+ installSourceInfo.packageSource,
+ installSourceInfo.initiatingPackageName
+ )
} catch (e: PackageManager.NameNotFoundException) {
Log.w(LOG_TAG, "InstallSourceInfo for $packageName not found")
invalidateSingle(packageName to user)
@@ -101,7 +103,10 @@ private constructor(
override fun newValue(key: Pair<String, UserHandle>): LightInstallSourceInfoLiveData {
return LightInstallSourceInfoLiveData(
- PermissionControllerApplication.get(), key.first, key.second)
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/v34/SafetyLabelInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/v34/SafetyLabelInfoLiveData.kt
index 6229218d4..5c63de6ce 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/v34/SafetyLabelInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/v34/SafetyLabelInfoLiveData.kt
@@ -115,7 +115,8 @@ private constructor(
}
return SafetyLabel.getSafetyLabelFromMetadata(
- userContext.packageManager.getAppMetadata(packageName))
+ userContext.packageManager.getAppMetadata(packageName)
+ )
}
companion object :
@@ -124,7 +125,10 @@ private constructor(
override fun newValue(key: Pair<String, UserHandle>): SafetyLabelInfoLiveData {
return SafetyLabelInfoLiveData(
- PermissionControllerApplication.get(), key.first, key.second)
+ PermissionControllerApplication.get(),
+ key.first,
+ key.second
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/HibernationSettingState.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/HibernationSettingState.kt
index 7b5b7994a..fd9c49f3d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/HibernationSettingState.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/HibernationSettingState.kt
@@ -23,25 +23,23 @@ import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_EX
* Tracks the setting state of hibernation and auto revoke for a package
*
* @param hibernationEligibility state saying whether the package is eligible for hibernation. See
- * [HIBERNATION_ELIGIBILITY_ELIGIBLE].
+ * [HIBERNATION_ELIGIBILITY_ELIGIBLE].
* @param revocableGroupNames A list of which permission groups of this package are eligible for
- * auto-revoke. A permission group is auto-revocable if it does not contain a default granted
- * permission.
+ * auto-revoke. A permission group is auto-revocable if it does not contain a default granted
+ * permission.
*/
data class HibernationSettingState(
val hibernationEligibility: Int,
val revocableGroupNames: List<String>
) {
- /**
- * Whether package will hibernate if it is unused.
- */
+ /** Whether package will hibernate if it is unused. */
fun isEligibleForHibernation(): Boolean {
return hibernationEligibility == HIBERNATION_ELIGIBILITY_ELIGIBLE
}
/**
- * Whether the package is exempt from hibernation by the system. This means the app can never
- * be hibernated, and the user setting to exempt it is disabled.
+ * Whether the package is exempt from hibernation by the system. This means the app can never be
+ * hibernated, and the user setting to exempt it is disabled.
*/
fun isExemptBySystem(): Boolean {
return hibernationEligibility == HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt
index 3c87f0b7a..a82387820 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt
@@ -28,12 +28,12 @@ import android.os.UserHandle
* @param packageInfo Information about the package
* @param permGroupInfo Information about the permission group
* @param allPermissions The permissions in the permission group that the package requests
- * (including restricted ones).
+ * (including restricted ones).
* @param hasInstallToRuntimeSplit If this group contains a permission that was previously an
- * install permission, but is currently a runtime permission
+ * install permission, but is currently a runtime permission
* @param specialLocationGrant If this package is the location provider, or the extra location
- * package, then the grant state of the group is not determined by the grant state of individual
- * permissions, but by other system properties
+ * package, then the grant state of the group is not determined by the grant state of individual
+ * permissions, but by other system properties
*/
data class LightAppPermGroup(
val packageInfo: LightPackageInfo,
@@ -48,25 +48,17 @@ data class LightAppPermGroup(
perms: Map<String, LightPermission>
) : this(pI, pGI, perms, false, null)
- /**
- * All unrestricted permissions. Usually restricted permissions are ignored
- */
+ /** All unrestricted permissions. Usually restricted permissions are ignored */
val permissions: Map<String, LightPermission> =
- allPermissions.filter { (_, permission) -> !permission.isRestricted }
+ allPermissions.filter { (_, permission) -> !permission.isRestricted }
- /**
- * The package name of this group
- */
+ /** The package name of this group */
val packageName = packageInfo.packageName
- /**
- * The permission group name of this group
- */
+ /** The permission group name of this group */
val permGroupName = permGroupInfo.name
- /**
- * The current userHandle of this AppPermGroup.
- */
+ /** The current userHandle of this AppPermGroup. */
val userHandle: UserHandle = UserHandle.getUserHandleForUid(packageInfo.uid)
/**
@@ -75,34 +67,36 @@ data class LightAppPermGroup(
*/
val backgroundPermNames = permissions.mapNotNull { it.value.backgroundPermission }
- /**
- * All foreground permissions in the permission group which are requested by the package.
- */
- val foregroundPermNames get() = permissions.mapNotNull { (name, _) ->
- if (name !in backgroundPermNames) name else null
- }
-
- val foreground = AppPermSubGroup(permissions.filter { it.key in foregroundPermNames },
- packageInfo, specialLocationGrant)
-
- val background = AppPermSubGroup(permissions.filter { it.key in backgroundPermNames },
- packageInfo, specialLocationGrant)
-
- /**
- * Whether or not this App Permission Group has a permission which has a background mode
- */
+ /** All foreground permissions in the permission group which are requested by the package. */
+ val foregroundPermNames
+ get() =
+ permissions.mapNotNull { (name, _) -> if (name !in backgroundPermNames) name else null }
+
+ val foreground =
+ AppPermSubGroup(
+ permissions.filter { it.key in foregroundPermNames },
+ packageInfo,
+ specialLocationGrant
+ )
+
+ val background =
+ AppPermSubGroup(
+ permissions.filter { it.key in backgroundPermNames },
+ packageInfo,
+ specialLocationGrant
+ )
+
+ /** Whether or not this App Permission Group has a permission which has a background mode */
val hasPermWithBackgroundMode = backgroundPermNames.isNotEmpty()
- /**
- * Whether or not this App Permission Group requests a background permission
- */
+ /** Whether or not this App Permission Group requests a background permission */
val hasBackgroundGroup = backgroundPermNames.any { permissions.contains(it) }
/**
* Whether this App Permission Group's background and foreground permissions are fixed by policy
*/
- val isPolicyFullyFixed = foreground.isPolicyFixed && (!hasBackgroundGroup ||
- background.isPolicyFixed)
+ val isPolicyFullyFixed =
+ foreground.isPolicyFixed && (!hasBackgroundGroup || background.isPolicyFixed)
/**
* Whether this App Permission Group's background permissions are fixed by the system or policy
@@ -114,107 +108,91 @@ data class LightAppPermGroup(
*/
val isForegroundFixed = foreground.isPolicyFixed || foreground.isSystemFixed
- /**
- * Whether or not this group supports runtime permissions
- */
+ /** Whether or not this group supports runtime permissions */
val supportsRuntimePerms = packageInfo.targetSdkVersion >= Build.VERSION_CODES.M
/**
* Whether this App Permission Group is one-time. 2 cases:
* 1. If the perm group is not LOCATION, check if any of the permissions is one-time and none of
- * the granted permissions are not one-time.
+ * the granted permissions are not one-time.
* 2. If the perm group is LOCATION, check if ACCESS_COARSE_LOCATION is one-time.
*/
- val isOneTime = (permGroupName != Manifest.permission_group.LOCATION &&
+ val isOneTime =
+ (permGroupName != Manifest.permission_group.LOCATION &&
permissions.any { it.value.isOneTime } &&
permissions.none { !it.value.isOneTime && it.value.isGrantedIncludingAppOp }) ||
(permGroupName == Manifest.permission_group.LOCATION &&
- permissions[ACCESS_COARSE_LOCATION]?.isOneTime == true)
+ permissions[ACCESS_COARSE_LOCATION]?.isOneTime == true)
- /**
- * Whether any permissions in this group are granted by default (pregrant)
- */
+ /** Whether any permissions in this group are granted by default (pregrant) */
val isGrantedByDefault = foreground.isGrantedByDefault || background.isGrantedByDefault
- /**
- * Whether any permissions in this group are granted by being a role holder
- */
+ /** Whether any permissions in this group are granted by being a role holder */
val isGrantedByRole = foreground.isGrantedByRole || background.isGrantedByRole
- /**
- * Whether any of the permission (foreground/background) is fixed by the system
- */
+ /** Whether any of the permission (foreground/background) is fixed by the system */
val isSystemFixed = foreground.isSystemFixed || background.isSystemFixed
- /**
- * Whether any of the permission (foreground/background) in this group requires a review
- */
+ /** Whether any of the permission (foreground/background) in this group requires a review */
val isReviewRequired = foreground.isReviewRequired || background.isReviewRequired
- /**
- * Whether any of the permission (foreground/background) is granted in this permission group
- */
+ /** Whether any of the permission (foreground/background) is granted in this permission group */
var isGranted = foreground.isGranted || background.isGranted
- /**
- * Whether any permissions in this group are user sensitive
- */
+ /** Whether any permissions in this group are user sensitive */
val isUserSensitive = permissions.any { it.value.isUserSensitive }
- /**
- * Whether any permissions in this group are revoke-when-requested
- */
+ /** Whether any permissions in this group are revoke-when-requested */
val isRevokeWhenRequested = permissions.any { it.value.isRevokeWhenRequested }
- /**
- * Whether any of this App Permission Groups permissions are fixed by the user
- */
+ /** Whether any of this App Permission Groups permissions are fixed by the user */
val isUserFixed = foreground.isUserFixed || background.isUserFixed
- /**
- * Whether any of this App Permission Group's permissions are set by the user
- */
+ /** Whether any of this App Permission Group's permissions are set by the user */
val isUserSet = foreground.isUserSet || background.isUserSet
/**
- * A subset of the AppPermissionGroup, representing either the background or foreground permissions
- * of the full group.
+ * A subset of the AppPermissionGroup, representing either the background or foreground
+ * permissions of the full group.
*
- * @param permissions The permissions contained within this subgroup, a subset of those contained
- * in the full group
+ * @param permissions The permissions contained within this subgroup, a subset of those
+ * contained in the full group
* @param specialLocationGrant Whether this is a special location package
*/
- data class AppPermSubGroup internal constructor(
+ data class AppPermSubGroup
+ internal constructor(
private val permissions: Map<String, LightPermission>,
private val packageInfo: LightPackageInfo,
private val specialLocationGrant: Boolean?
) {
- /**
- * Whether any of this App Permission SubGroup's permissions are granted
- */
+ /** Whether any of this App Permission SubGroup's permissions are granted */
val isGranted = specialLocationGrant ?: permissions.any { it.value.isGrantedIncludingAppOp }
/**
* Whether this App Permission SubGroup should be treated as granted. This means either:
* 1) At least one permission was granted excluding auto-granted permissions (i.e., granted
- * during install time with flag RevokeWhenRequested.) Or,
+ * during install time with flag RevokeWhenRequested.) Or,
* 2) All permissions were auto-granted (all permissions are all granted and all
- * RevokeWhenRequested.)
- */
- val isGrantedExcludingRWROrAllRWR = specialLocationGrant ?: (permissions
- .any { it.value.isGrantedIncludingAppOp && !it.value.isRevokeWhenRequested } ||
- permissions.all { it.value.isGrantedIncludingAppOp && it.value.isRevokeWhenRequested })
-
- /**
- * Whether any of this App Permission SubGroup's permissions are granted by default
+ * RevokeWhenRequested.)
*/
+ val isGrantedExcludingRWROrAllRWR =
+ specialLocationGrant
+ ?: (permissions.any {
+ it.value.isGrantedIncludingAppOp && !it.value.isRevokeWhenRequested
+ } ||
+ permissions.all {
+ it.value.isGrantedIncludingAppOp && it.value.isRevokeWhenRequested
+ })
+
+ /** Whether any of this App Permission SubGroup's permissions are granted by default */
val isGrantedByDefault = permissions.any { it.value.isGrantedByDefault }
/**
- * Whether at least one of this App Permission SubGroup's permissions is one-time and
- * none of the granted permissions are not one-time.
+ * Whether at least one of this App Permission SubGroup's permissions is one-time and none
+ * of the granted permissions are not one-time.
*/
- val isOneTime = permissions.any { it.value.isOneTime } &&
+ val isOneTime =
+ permissions.any { it.value.isOneTime } &&
permissions.none { it.value.isGrantedIncludingAppOp && !it.value.isOneTime }
/**
@@ -222,24 +200,16 @@ data class LightAppPermGroup(
*/
val isPolicyFixed = permissions.any { it.value.isPolicyFixed }
- /**
- * Whether any of this App Permission Subgroup's permissions are fixed by the system
- */
+ /** Whether any of this App Permission Subgroup's permissions are fixed by the system */
val isSystemFixed = permissions.any { it.value.isSystemFixed }
- /**
- * Whether any of this App Permission Subgroup's permissions are fixed by the user
- */
+ /** Whether any of this App Permission Subgroup's permissions are fixed by the user */
val isUserFixed = permissions.any { it.value.isUserFixed }
- /**
- * Whether any of this App Permission Subgroup's permissions are set by the user
- */
+ /** Whether any of this App Permission Subgroup's permissions are set by the user */
val isUserSet = permissions.any { it.value.isUserSet }
- /**
- * whether review is required or not for the permission group
- */
+ /** whether review is required or not for the permission group */
val isReviewRequired = permissions.any { it.value.isReviewRequired }
/**
@@ -251,10 +221,9 @@ data class LightAppPermGroup(
private val hasInstantPerm = permissions.any { (_, perm) -> perm.isInstantPerm }
- /**
- * Whether or not any permissions in this App Permission Subgroup can be granted
- */
- val isGrantable = (!packageInfo.isInstantApp || hasInstantPerm) &&
+ /** Whether or not any permissions in this App Permission Subgroup can be granted */
+ val isGrantable =
+ (!packageInfo.isInstantApp || hasInstantPerm) &&
(packageInfo.targetSdkVersion >= Build.VERSION_CODES.M || hasPreRuntimePerm)
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt
index 0f6b6c000..b50cf72d0 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt
@@ -69,15 +69,17 @@ data class LightPackageInfo(
pI.firstInstallTime,
pI.lastUpdateTime,
if (SdkLevel.isAtLeastS()) pI.applicationInfo.areAttributionsUserVisible() else false,
- if (SdkLevel.isAtLeastS()) buildAttributionTagsToLabelsMap(pI.attributions) else emptyMap())
+ if (SdkLevel.isAtLeastS()) buildAttributionTagsToLabelsMap(pI.attributions) else emptyMap()
+ )
/** Permissions which are granted according to the [requestedPermissionsFlags] */
val grantedPermissions: List<String>
get() {
val grantedPermissions = mutableListOf<String>()
for (i in 0 until requestedPermissions.size) {
- if ((requestedPermissionsFlags[i] and PackageInfo.REQUESTED_PERMISSION_GRANTED) !=
- 0) {
+ if (
+ (requestedPermissionsFlags[i] and PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0
+ ) {
grantedPermissions.add(requestedPermissions[i])
}
}
@@ -89,9 +91,8 @@ data class LightPackageInfo(
* often.
*
* @param app The current application, which will be used to get the ApplicationInfo
- *
* @return The ApplicationInfo corresponding to this package, with this UID, or null, if no such
- * package exists
+ * package exists
*/
fun getApplicationInfo(app: Application): ApplicationInfo? {
try {
@@ -112,7 +113,9 @@ data class LightPackageInfo(
try {
val userContext = Utils.getUserContext(app, UserHandle.getUserHandleForUid(uid))
return userContext.packageManager.getPackageInfo(
- packageName, PackageManager.GET_PERMISSIONS)
+ packageName,
+ PackageManager.GET_PERMISSIONS
+ )
} catch (e: PackageManager.NameNotFoundException) {}
return null
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermGroupInfo.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermGroupInfo.kt
index 6aff2f3c9..7abf5ff1a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermGroupInfo.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermGroupInfo.kt
@@ -41,21 +41,22 @@ data class LightPermGroupInfo(
val isSinglePermGroup: Boolean
) {
- constructor(pII: PackageItemInfo) : this(pII.name, pII.packageName, pII.labelRes, pII.icon,
- 0, pII is PermissionInfo)
+ constructor(
+ pII: PackageItemInfo
+ ) : this(pII.name, pII.packageName, pII.labelRes, pII.icon, 0, pII is PermissionInfo)
- constructor(pGI: PermissionGroupInfo) : this(pGI.name, pGI.packageName, pGI.labelRes, pGI.icon,
- pGI.descriptionRes, false)
+ constructor(
+ pGI: PermissionGroupInfo
+ ) : this(pGI.name, pGI.packageName, pGI.labelRes, pGI.icon, pGI.descriptionRes, false)
/**
* Gets the PackageItemInfo for this permission group from the system.
*
* @param app The current application, which will be used to get the PackageItemInfo
- *
- * @return The PackageItemInfo corresponding to this permission group, or null, if no
- * such group exists
+ * @return The PackageItemInfo corresponding to this permission group, or null, if no such group
+ * exists
*/
fun toPackageItemInfo(app: Application): PackageItemInfo? {
return Utils.getGroupInfo(name, app.applicationContext)
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermInfo.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermInfo.kt
index 3954b7472..c1d271098 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermInfo.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermInfo.kt
@@ -40,23 +40,29 @@ data class LightPermInfo(
val protectionFlags: Int,
val flags: Int
) {
- constructor (permInfo: PermissionInfo): this(permInfo.name, permInfo.packageName,
- permInfo.group, permInfo.backgroundPermission, permInfo.protection,
- permInfo.protectionFlags, permInfo.flags)
+ constructor(
+ permInfo: PermissionInfo
+ ) : this(
+ permInfo.name,
+ permInfo.packageName,
+ permInfo.group,
+ permInfo.backgroundPermission,
+ permInfo.protection,
+ permInfo.protectionFlags,
+ permInfo.flags
+ )
/**
* Gets the PermissionInfo for this permission from the system.
*
* @param app The current application, which will be used to get the PermissionInfo
- *
- * @return The PermissionInfo corresponding to this permission, or null, if no
- * such permission exists
+ * @return The PermissionInfo corresponding to this permission, or null, if no such permission
+ * exists
*/
fun toPermissionInfo(app: Application): PermissionInfo? {
try {
return app.packageManager.getPermissionInfo(name, 0)
- } catch (e: PackageManager.NameNotFoundException) {
- }
+ } catch (e: PackageManager.NameNotFoundException) {}
return null
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermission.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermission.kt
index fd7d82dfc..7492ea6e0 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermission.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPermission.kt
@@ -28,11 +28,11 @@ import com.android.permissioncontroller.permission.utils.Utils
*
* @param pkgInfo The package requesting the permission
* @param permInfo The permissionInfo this represents
- * @param isGrantedIncludingAppOp Whether or not this permission is functionally granted.
- * A non-granted app op but granted permission is counted as not granted
+ * @param isGrantedIncludingAppOp Whether or not this permission is functionally granted. A
+ * non-granted app op but granted permission is counted as not granted
* @param flags The PermissionController flags for this permission
* @param foregroundPerms The foreground permission names corresponding to this permission, if this
- * permission is a background permission
+ * permission is a background permission
*/
data class LightPermission(
val pkgInfo: LightPackageInfo,
@@ -47,14 +47,13 @@ data class LightPermission(
permInfo: LightPermInfo,
permState: PermState,
foregroundPerms: List<String>?
- ) :
- this(pkgInfo, permInfo, permState.granted, permState.permFlags, foregroundPerms)
+ ) : this(pkgInfo, permInfo, permState.granted, permState.permFlags, foregroundPerms)
/** The name of this permission */
val name = permInfo.name
/** The background permission name of this permission, if it exists */
val backgroundPermission: String? = permInfo.backgroundPermission
- /** If this is a background permission **/
+ /** If this is a background permission */
val isBackgroundPermission = foregroundPerms?.isNotEmpty() ?: false
/** Whether this permission is fixed by policy */
val isPolicyFixed = flags and PackageManager.FLAG_PERMISSION_POLICY_FIXED != 0
@@ -76,9 +75,10 @@ data class LightPermission(
val isImplicit: Boolean by lazy {
var implicit = false
for ((permName, permFlags) in
- pkgInfo.requestedPermissions.zip(pkgInfo.requestedPermissionsFlags)) {
- if (permName == permInfo.name &&
- (permFlags and PackageInfo.REQUESTED_PERMISSION_IMPLICIT) != 0
+ pkgInfo.requestedPermissions.zip(pkgInfo.requestedPermissionsFlags)) {
+ if (
+ permName == permInfo.name &&
+ (permFlags and PackageInfo.REQUESTED_PERMISSION_IMPLICIT) != 0
) {
implicit = true
break
@@ -96,23 +96,25 @@ data class LightPermission(
/** Whether this permission is set to be revoked upon being requested */
val isRevokeWhenRequested = flags and PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED != 0
/** Whether this permission is user sensitive in its current grant state */
- val isUserSensitive = !isRuntimePlatformPermission(permInfo.name) ||
+ val isUserSensitive =
+ !isRuntimePlatformPermission(permInfo.name) ||
(isGrantedIncludingAppOp &&
- (flags and PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) != 0) ||
+ (flags and PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) != 0) ||
(!isGrantedIncludingAppOp &&
- (flags and PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) != 0)
+ (flags and PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) != 0)
/** Whether the permission is restricted */
- val isRestricted = when {
- (permInfo.flags and PermissionInfo.FLAG_HARD_RESTRICTED) != 0 -> {
- flags and Utils.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT == 0
- }
- (permInfo.flags and PermissionInfo.FLAG_SOFT_RESTRICTED) != 0 -> {
- !SoftRestrictedPermissionPolicy.shouldShow(pkgInfo, permInfo.name, flags)
- }
- else -> {
- false
+ val isRestricted =
+ when {
+ (permInfo.flags and PermissionInfo.FLAG_HARD_RESTRICTED) != 0 -> {
+ flags and Utils.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT == 0
+ }
+ (permInfo.flags and PermissionInfo.FLAG_SOFT_RESTRICTED) != 0 -> {
+ !SoftRestrictedPermissionPolicy.shouldShow(pkgInfo, permInfo.name, flags)
+ }
+ else -> {
+ false
+ }
}
- }
/** Whether the permission is auto revoked */
val isAutoRevoked = flags and PackageManager.FLAG_PERMISSION_AUTO_REVOKED != 0
/**
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/PermGroup.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/PermGroup.kt
index c5079a950..e6913f57e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/PermGroup.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/PermGroup.kt
@@ -17,8 +17,8 @@
package com.android.permissioncontroller.permission.model.livedatatypes
/**
- * A permission Group, represented as a PackageItemInfo groupInfo, and a map of permission name
- * to PermissionInfo objects.
+ * A permission Group, represented as a PackageItemInfo groupInfo, and a map of permission name to
+ * PermissionInfo objects.
*
* @param groupInfo information about the permission group
* @param permissionInfos the Permissions in this group
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/PermGroupPackagesUiInfo.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/PermGroupPackagesUiInfo.kt
index e11e895a9..ba4aa0a20 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/PermGroupPackagesUiInfo.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/PermGroupPackagesUiInfo.kt
@@ -22,17 +22,17 @@ package com.android.permissioncontroller.permission.model.livedatatypes
*
* @param name The name of the permission group whose UI data this represents
* @param nonSystemTotal The total number of non-system applications that request permissions in
- * this group
+ * this group
* @param nonSystemGranted The total number of non-system applications that request permissions in
- * this group, and have at least one permission in this group granted.
+ * this group, and have at least one permission in this group granted.
* @param nonSystemUserSetOrPreGranted The total number of non-system applications that request
- * permissions in this group, and have at least one permission in this group granted, or one
- * permission denied by the user
- * @param systemGranted The total number of system applications that request permissions in
- * this group, and have at least one permission in this group granted.
- * @param systemUserSetOrPreGranted The total number of system applications that request
- * permissions in this group, and have at least one permission in this group granted, or one
- * permission denied by the user
+ * permissions in this group, and have at least one permission in this group granted, or one
+ * permission denied by the user
+ * @param systemGranted The total number of system applications that request permissions in this
+ * group, and have at least one permission in this group granted.
+ * @param systemUserSetOrPreGranted The total number of system applications that request permissions
+ * in this group, and have at least one permission in this group granted, or one permission denied
+ * by the user
*/
data class PermGroupPackagesUiInfo(
val name: String,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/UidSensitivityState.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/UidSensitivityState.kt
index 3d0be0c0a..d8cdf01d6 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/UidSensitivityState.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/UidSensitivityState.kt
@@ -22,8 +22,8 @@ package com.android.permissioncontroller.permission.model.livedatatypes
*
* @param packages A LightPackageInfo for every package with this uid
* @param permStates A map <requested permission name, use sensitive state>, with the state being a
- * combination of FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED and
- * FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED
+ * combination of FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED and
+ * FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED
*/
data class UidSensitivityState(
val packages: MutableSet<LightPackageInfo>,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt
index 4c2051f9c..d5451c208 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt
@@ -82,7 +82,10 @@ data class LightHistoricalPackageOps(
this.getDiscreteAccesses(permissionToOpNames.value)?.let {
appPermissionDiscreteAccesses.add(
AppPermissionDiscreteAccesses(
- AppPermissionId(packageName, userHandle, permissionToOpNames.key), it))
+ AppPermissionId(packageName, userHandle, permissionToOpNames.key),
+ it
+ )
+ )
}
}
@@ -117,7 +120,9 @@ data class LightHistoricalPackageOps(
mutableMapOf()
}
attributedAppPermissionDiscreteAccesses[appPermissionId]?.put(
- attributedHistoricalOps.tag ?: NO_ATTRIBUTION_TAG, discAccessData)
+ attributedHistoricalOps.tag ?: NO_ATTRIBUTION_TAG,
+ discAccessData
+ )
}
}
}
@@ -152,7 +157,9 @@ data class LightHistoricalPackageOps(
DiscreteAccess(
opEntry.getLastAccessTime(DISCRETE_ACCESS_OP_FLAGS),
opEntry.getLastDuration(DISCRETE_ACCESS_OP_FLAGS),
- opEntry.getLastProxyInfo(DISCRETE_ACCESS_OP_FLAGS)))
+ opEntry.getLastProxyInfo(DISCRETE_ACCESS_OP_FLAGS)
+ )
+ )
}
}
@@ -187,7 +194,9 @@ data class LightHistoricalPackageOps(
DiscreteAccess(
attributedOpEntry.getLastAccessTime(DISCRETE_ACCESS_OP_FLAGS),
attributedOpEntry.getLastDuration(DISCRETE_ACCESS_OP_FLAGS),
- attributedOpEntry.getLastProxyInfo(DISCRETE_ACCESS_OP_FLAGS)))
+ attributedOpEntry.getLastProxyInfo(DISCRETE_ACCESS_OP_FLAGS)
+ )
+ )
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightPackageOps.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightPackageOps.kt
index dde4857e2..b65fda5ea 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightPackageOps.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightPackageOps.kt
@@ -44,7 +44,8 @@ data class LightPackageOps(
) : this(
packageOps.packageName,
UserHandle.getUserHandleForUid(packageOps.uid),
- createLastPermissionGroupAccessTimesMap(ops, packageOps))
+ createLastPermissionGroupAccessTimesMap(ops, packageOps)
+ )
/** Companion object for [LightPackageOps]. */
companion object {
@@ -70,7 +71,8 @@ data class LightPackageOps(
lastAccessTimeMs[permissionGroupOfOp] =
maxOf(
lastAccessTimeMs[permissionGroupOfOp] ?: -1,
- opEntry.getLastAccessTime(OPS_LAST_ACCESS_FLAGS))
+ opEntry.getLastAccessTime(OPS_LAST_ACCESS_FLAGS)
+ )
}
return lastAccessTimeMs
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v34/LightInstallSourceInfo.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v34/LightInstallSourceInfo.kt
index e75c1eadf..85f77b823 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v34/LightInstallSourceInfo.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v34/LightInstallSourceInfo.kt
@@ -36,12 +36,12 @@ class LightInstallSourceInfo {
// default source of unspecified. All other sources should be explicitly set to another
// PACKAGE_SOURCE_ value
val isStoreInstalled =
- initiatingPackageName != null &&
- (packageSource == PACKAGE_SOURCE_STORE ||
- packageSource == PACKAGE_SOURCE_UNSPECIFIED)
+ initiatingPackageName != null &&
+ (packageSource == PACKAGE_SOURCE_STORE ||
+ packageSource == PACKAGE_SOURCE_UNSPECIFIED)
- isPreloadedApp = initiatingPackageName == null &&
- packageSource == PACKAGE_SOURCE_UNSPECIFIED
+ isPreloadedApp =
+ initiatingPackageName == null && packageSource == PACKAGE_SOURCE_UNSPECIFIED
supportsSafetyLabel = isStoreInstalled || isPreloadedApp
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v34/SafetyLabelInfo.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v34/SafetyLabelInfo.kt
index 7128e3069..2107e9944 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v34/SafetyLabelInfo.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v34/SafetyLabelInfo.kt
@@ -28,7 +28,7 @@ import com.android.permissioncontroller.permission.model.livedatatypes.v34.Light
class SafetyLabelInfo(
val safetyLabel: SafetyLabel?,
val installSourceInfo: LightInstallSourceInfo
- ) {
+) {
companion object {
/** Default definition of unavailable or no safety label found */
val UNAVAILABLE = SafetyLabelInfo(null, INSTALL_SOURCE_UNAVAILABLE)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt
index 52e89e972..4b0192ba6 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt
@@ -32,7 +32,6 @@ import com.android.permissioncontroller.PermissionControllerStatsLog
import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED
import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_UNUSED_APP_PERMISSION_REVOKED
import com.android.permissioncontroller.hibernation.getUnusedThresholdMs
-import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.data.AutoRevokedPackagesLiveData
import com.android.permissioncontroller.permission.data.LightAppPermGroupLiveData
import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData
@@ -40,18 +39,18 @@ import com.android.permissioncontroller.permission.data.get
import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
import com.android.permissioncontroller.permission.utils.KotlinUtils
+import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.application
import com.android.permissioncontroller.permission.utils.forEachInParallel
import com.android.permissioncontroller.permission.utils.updatePermissionFlags
-import kotlinx.coroutines.Dispatchers.Main
import java.util.concurrent.atomic.AtomicBoolean
+import kotlinx.coroutines.Dispatchers.Main
private const val LOG_TAG = "AutoRevokePermissions"
const val DEBUG_AUTO_REVOKE = true
-private val EXEMPT_PERMISSIONS = listOf(
- Manifest.permission.ACTIVITY_RECOGNITION,
- Manifest.permission.POST_NOTIFICATIONS)
+val AUTO_REVOKE_EXEMPT_PERMISSIONS =
+ listOf(Manifest.permission.ACTIVITY_RECOGNITION, Manifest.permission.POST_NOTIFICATIONS)
private val SERVER_LOG_ID =
PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_UNUSED_APP_PERMISSION_REVOKED
@@ -79,10 +78,10 @@ suspend fun revokeAppPermissions(
continue
}
- val pkgPermChanges = PermissionChangeStorageImpl.getInstance().loadEvents()
- .associateBy { it.packageName }
+ val pkgPermChanges =
+ PermissionChangeStorageImpl.getInstance().loadEvents().associateBy { it.packageName }
// For each autorevoke-eligible app...
- userApps.forEachInParallel(Main) forEachInParallelOuter@ { pkg: LightPackageInfo ->
+ userApps.forEachInParallel(Main) forEachInParallelOuter@{ pkg: LightPackageInfo ->
if (pkg.grantedPermissions.isEmpty()) {
return@forEachInParallelOuter
}
@@ -91,15 +90,18 @@ suspend fun revokeAppPermissions(
val now = System.currentTimeMillis()
if (pkgPermChange != null && now - pkgPermChange.eventTime < getUnusedThresholdMs()) {
if (DEBUG_AUTO_REVOKE) {
- DumpableLog.i(LOG_TAG, "Not revoking because permissions were changed " +
- "recently for package $packageName")
+ DumpableLog.i(
+ LOG_TAG,
+ "Not revoking because permissions were changed " +
+ "recently for package $packageName"
+ )
}
return@forEachInParallelOuter
}
val targetSdk = pkg.targetSdkVersion
val pkgPermGroups: Map<String, List<String>> =
- PackagePermissionsLiveData[packageName, user]
- .getInitializedValue() ?: return@forEachInParallelOuter
+ PackagePermissionsLiveData[packageName, user].getInitializedValue()
+ ?: return@forEachInParallelOuter
// Determine which permGroups are revocable
val revocableGroups = mutableSetOf<String>()
@@ -111,26 +113,30 @@ suspend fun revokeAppPermissions(
continue
}
val group: LightAppPermGroup =
- LightAppPermGroupLiveData[packageName, groupName, user]
- .getInitializedValue() ?: continue
+ LightAppPermGroupLiveData[packageName, groupName, user].getInitializedValue()
+ ?: continue
val fixed = group.isBackgroundFixed || group.isForegroundFixed
- val granted = group.permissions.any { (_, perm) ->
- perm.isGrantedIncludingAppOp && perm.name !in EXEMPT_PERMISSIONS
- }
- if (!fixed && granted &&
- !group.isGrantedByDefault &&
- !group.isGrantedByRole &&
- !group.isRevokeWhenRequested &&
- group.isUserSensitive) {
+ val granted =
+ group.permissions.any { (_, perm) ->
+ perm.isGrantedIncludingAppOp && perm.name !in AUTO_REVOKE_EXEMPT_PERMISSIONS
+ }
+ if (
+ !fixed &&
+ granted &&
+ !group.isGrantedByDefault &&
+ !group.isGrantedByRole &&
+ !group.isRevokeWhenRequested &&
+ group.isUserSensitive
+ ) {
revocableGroups.add(groupName)
}
}
// Mark any groups that split from an install-time permission as unrevocable
for (fromPerm in
- pkgPermGroups[PackagePermissionsLiveData.NON_RUNTIME_NORMAL_PERMS] ?: emptyList()) {
+ pkgPermGroups[PackagePermissionsLiveData.NON_RUNTIME_NORMAL_PERMS] ?: emptyList()) {
for (toGroup in
- splitPermissionIndex.getPermToGroupSplitsFrom(fromPerm, targetSdk)) {
+ splitPermissionIndex.getPermToGroupSplitsFrom(fromPerm, targetSdk)) {
revocableGroups.remove(toGroup)
}
}
@@ -139,11 +145,11 @@ suspend fun revokeAppPermissions(
for (groupName in pkgPermGroups.keys) {
if (!revocableGroups.contains(groupName)) {
for (fromGroup in
- splitPermissionIndex.getGroupToGroupSplitsTo(groupName, targetSdk)) {
+ splitPermissionIndex.getGroupToGroupSplitsTo(groupName, targetSdk)) {
revocableGroups.remove(fromGroup)
}
for (toGroup in
- splitPermissionIndex.getGroupToGroupSplitsFrom(groupName, targetSdk)) {
+ splitPermissionIndex.getGroupToGroupSplitsFrom(groupName, targetSdk)) {
revocableGroups.remove(toGroup)
}
}
@@ -153,72 +159,92 @@ suspend fun revokeAppPermissions(
val anyPermsRevoked = AtomicBoolean(false)
pkgPermGroups.entries
.filter { revocableGroups.contains(it.key) }
- .forEachInParallel(Main) forEachInParallelInner@ { (groupName, _) ->
- val group: LightAppPermGroup =
- LightAppPermGroupLiveData[packageName, groupName, user]
- .getInitializedValue()!!
+ .forEachInParallel(Main) forEachInParallelInner@{ (groupName, _) ->
+ val group: LightAppPermGroup =
+ LightAppPermGroupLiveData[packageName, groupName, user]
+ .getInitializedValue()!!
- val revocablePermissions = group.permissions.keys.toList()
+ val revocablePermissions = group.permissions.keys.toList()
- if (revocablePermissions.isEmpty()) {
- return@forEachInParallelInner
- }
-
- if (DEBUG_AUTO_REVOKE) {
- DumpableLog.i(LOG_TAG,
- "revokeUnused $packageName - $revocablePermissions")
- }
+ if (revocablePermissions.isEmpty()) {
+ return@forEachInParallelInner
+ }
- val uid = group.packageInfo.uid
- for (permName in revocablePermissions) {
- PermissionControllerStatsLog.write(
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED,
- sessionId, uid, packageName, permName, false, SERVER_LOG_ID,
- /* permission_rationale_shown = */ false)
- }
+ if (DEBUG_AUTO_REVOKE) {
+ DumpableLog.i(LOG_TAG, "revokeUnused $packageName - $revocablePermissions")
+ }
- if (DEBUG_AUTO_REVOKE) {
- DumpableLog.i(LOG_TAG, "revoking $packageName - $revocablePermissions")
- DumpableLog.i(LOG_TAG, "State pre revocation: ${group.allPermissions}")
- }
- anyPermsRevoked.compareAndSet(false, true)
+ val uid = group.packageInfo.uid
+ for (permName in revocablePermissions) {
+ PermissionControllerStatsLog.write(
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED,
+ sessionId,
+ uid,
+ packageName,
+ permName,
+ false,
+ SERVER_LOG_ID,
+ /* permission_rationale_shown = */ false
+ )
+ }
- val bgRevokedState = KotlinUtils.revokeBackgroundRuntimePermissions(
- context.application, group,
- userFixed = false, oneTime = false,
- filterPermissions = revocablePermissions)
- if (DEBUG_AUTO_REVOKE) {
- DumpableLog.i(LOG_TAG,
- "Bg state post revocation: ${bgRevokedState.allPermissions}")
- }
- val fgRevokedState = KotlinUtils.revokeForegroundRuntimePermissions(
- context.application, group,
- userFixed = false, oneTime = false,
- filterPermissions = revocablePermissions)
- if (DEBUG_AUTO_REVOKE) {
- DumpableLog.i(LOG_TAG,
- "Fg state post revocation: ${fgRevokedState.allPermissions}")
- }
+ if (DEBUG_AUTO_REVOKE) {
+ DumpableLog.i(LOG_TAG, "revoking $packageName - $revocablePermissions")
+ DumpableLog.i(LOG_TAG, "State pre revocation: ${group.allPermissions}")
+ }
+ anyPermsRevoked.compareAndSet(false, true)
+
+ val bgRevokedState =
+ KotlinUtils.revokeBackgroundRuntimePermissions(
+ context.application,
+ group,
+ userFixed = false,
+ oneTime = false,
+ filterPermissions = revocablePermissions
+ )
+ if (DEBUG_AUTO_REVOKE) {
+ DumpableLog.i(
+ LOG_TAG,
+ "Bg state post revocation: ${bgRevokedState.allPermissions}"
+ )
+ }
+ val fgRevokedState =
+ KotlinUtils.revokeForegroundRuntimePermissions(
+ context.application,
+ group,
+ userFixed = false,
+ oneTime = false,
+ filterPermissions = revocablePermissions
+ )
+ if (DEBUG_AUTO_REVOKE) {
+ DumpableLog.i(
+ LOG_TAG,
+ "Fg state post revocation: ${fgRevokedState.allPermissions}"
+ )
+ }
- for (permission in revocablePermissions) {
- context.packageManager.updatePermissionFlags(
- permission, packageName, user,
- FLAG_PERMISSION_AUTO_REVOKED to true,
- FLAG_PERMISSION_USER_SET to false)
+ for (permission in revocablePermissions) {
+ context.packageManager.updatePermissionFlags(
+ permission,
+ packageName,
+ user,
+ FLAG_PERMISSION_AUTO_REVOKED to true,
+ FLAG_PERMISSION_USER_SET to false
+ )
+ }
}
- }
if (anyPermsRevoked.get()) {
- synchronized(revokedApps) {
- revokedApps.add(packageName to user)
- }
+ synchronized(revokedApps) { revokedApps.add(packageName to user) }
}
}
if (DEBUG_AUTO_REVOKE) {
synchronized(revokedApps) {
- DumpableLog.i(LOG_TAG,
- "Done auto-revoke for user ${user.identifier} - revoked $revokedApps")
+ DumpableLog.i(
+ LOG_TAG,
+ "Done auto-revoke for user ${user.identifier} - revoked $revokedApps"
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/BackupHelper.java b/PermissionController/src/com/android/permissioncontroller/permission/service/BackupHelper.java
index 9082b6931..bea110f70 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/BackupHelper.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/BackupHelper.java
@@ -136,8 +136,8 @@ public class BackupHelper {
case END_TAG:
numOpenTags--;
break;
- default:
- // ignore
+ case END_DOCUMENT:
+ return;
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/BasePermissionEventStorage.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/BasePermissionEventStorage.kt
index 840b7e483..8bbb41c56 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/BasePermissionEventStorage.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/BasePermissionEventStorage.kt
@@ -22,17 +22,14 @@ import android.util.AtomicFile
import android.util.Log
import com.android.permissioncontroller.DumpableLog
import com.android.permissioncontroller.permission.data.PermissionEvent
-import org.xmlpull.v1.XmlPullParserException
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
+import org.xmlpull.v1.XmlPullParserException
-/**
- * Thread-safe implementation of [PermissionEventStorage] using an XML file as the
- * database.
- */
+/** Thread-safe implementation of [PermissionEventStorage] using an XML file as the database. */
abstract class BasePermissionEventStorage<T : PermissionEvent>(
private val context: Context,
jobScheduler: JobScheduler = context.getSystemService(JobScheduler::class.java)!!
@@ -75,9 +72,7 @@ abstract class BasePermissionEventStorage<T : PermissionEvent>(
}
override suspend fun clearEvents() {
- synchronized(fileLock) {
- dbFile.delete()
- }
+ synchronized(fileLock) { dbFile.delete() }
}
override suspend fun removeOldData(): Boolean {
@@ -85,12 +80,15 @@ abstract class BasePermissionEventStorage<T : PermissionEvent>(
val existingEvents = readData()
val originalCount = existingEvents.size
- val newEvents = existingEvents.filter {
- (System.currentTimeMillis() - it.eventTime) <= getMaxDataAgeMs()
- }
+ val newEvents =
+ existingEvents.filter {
+ (System.currentTimeMillis() - it.eventTime) <= getMaxDataAgeMs()
+ }
- DumpableLog.d(LOG_TAG,
- "${originalCount - newEvents.size} old permission events removed")
+ DumpableLog.d(
+ LOG_TAG,
+ "${originalCount - newEvents.size} old permission events removed"
+ )
return writeData(newEvents)
}
@@ -109,20 +107,19 @@ abstract class BasePermissionEventStorage<T : PermissionEvent>(
synchronized(fileLock) {
val existingEvents = readData()
- val newEvents = existingEvents.map {
- it.copyWithTimeDelta(diffSystemTimeMillis)
- }
+ val newEvents = existingEvents.map { it.copyWithTimeDelta(diffSystemTimeMillis) }
return writeData(newEvents)
}
}
private fun writeData(events: List<T>): Boolean {
- val stream: FileOutputStream = try {
- dbFile.startWrite()
- } catch (e: IOException) {
- Log.e(LOG_TAG, "Failed to save db file", e)
- return false
- }
+ val stream: FileOutputStream =
+ try {
+ dbFile.startWrite()
+ } catch (e: IOException) {
+ Log.e(LOG_TAG, "Failed to save db file", e)
+ return false
+ }
try {
serialize(stream, events)
dbFile.finishWrite(stream)
@@ -167,23 +164,15 @@ abstract class BasePermissionEventStorage<T : PermissionEvent>(
@Throws(XmlPullParserException::class, IOException::class)
abstract fun parse(inputStream: InputStream): List<T>
- /**
- * Returns file name for database.
- */
+ /** Returns file name for database. */
abstract fun getDatabaseFileName(): String
- /**
- * Returns max time that data should be persisted before being removed.
- */
+ /** Returns max time that data should be persisted before being removed. */
abstract fun getMaxDataAgeMs(): Long
- /**
- * Returns true if the two events have the same primary key for the database store.
- */
+ /** Returns true if the two events have the same primary key for the database store. */
abstract fun hasTheSamePrimaryKey(first: T, second: T): Boolean
- /**
- * Copies the event with the time delta applied to the [PermissionEvent.eventTime].
- */
+ /** Copies the event with the time delta applied to the [PermissionEvent.eventTime]. */
abstract fun T.copyWithTimeDelta(timeDelta: Long): T
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/CheckLifecycleRegistry.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/CheckLifecycleRegistry.kt
index 506fa0ef0..678caa168 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/CheckLifecycleRegistry.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/CheckLifecycleRegistry.kt
@@ -29,17 +29,13 @@ class CheckLifecycleRegistry(provider: LifecycleOwner) : LifecycleRegistry(provi
if (Looper.myLooper() != Looper.getMainLooper()) {
throw IllegalStateException("Lifecycle running on non main thread")
}
- synchronized(observerLock) {
- super.addObserver(observer)
- }
+ synchronized(observerLock) { super.addObserver(observer) }
}
override fun removeObserver(observer: LifecycleObserver) {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw IllegalStateException("Lifecycle running on non main thread")
}
- synchronized(observerLock) {
- super.removeObserver(observer)
- }
+ synchronized(observerLock) { super.removeObserver(observer) }
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/ExemptRestrictedPermission.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/ExemptRestrictedPermission.kt
index dbf844b27..33e579eef 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/ExemptRestrictedPermission.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/ExemptRestrictedPermission.kt
@@ -8,8 +8,8 @@ import android.os.Process
import android.os.UserHandle
/**
- * For manually exempting a restricted permission.
- * STOPSHIP This functionality should not be in the final release.
+ * For manually exempting a restricted permission. STOPSHIP This functionality should not be in the
+ * final release.
*/
class ExemptRestrictedPermission : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@@ -21,7 +21,10 @@ class ExemptRestrictedPermission : BroadcastReceiver() {
// Use upgrade flag. If the permission needs to be manually exempted then it probably
// should have been done on upgrade.
- userContext.packageManager.addWhitelistedRestrictedPermission(packageName, permission,
- PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE)
+ userContext.packageManager.addWhitelistedRestrictedPermission(
+ packageName,
+ permission,
+ PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ )
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionChangeStorageImpl.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionChangeStorageImpl.kt
index bdcf833fc..5a49b7ebe 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionChangeStorageImpl.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionChangeStorageImpl.kt
@@ -25,12 +25,6 @@ import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.hibernation.getUnusedThresholdMs
import com.android.permissioncontroller.permission.data.PermissionChange
import com.android.permissioncontroller.permission.utils.Utils
-import kotlinx.coroutines.DelicateCoroutinesApi
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
-import org.xmlpull.v1.XmlPullParser
-import org.xmlpull.v1.XmlPullParserException
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
@@ -39,6 +33,12 @@ import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import org.xmlpull.v1.XmlPullParser
+import org.xmlpull.v1.XmlPullParserException
/**
* Implementation of [BasePermissionEventStorage] for storing [PermissionChange] events for long
@@ -52,14 +52,10 @@ class PermissionChangeStorageImpl(
// We don't use namespaces
private val ns: String? = null
- /**
- * The format for how dates are stored.
- */
+ /** The format for how dates are stored. */
private val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US)
- /**
- * Exact format if [PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME] is true
- */
+ /** Exact format if [PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME] is true */
private val exactTimeFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US)
companion object {
@@ -67,9 +63,7 @@ class PermissionChangeStorageImpl(
private const val DB_VERSION = 1
- /**
- * Config store file name for general shared store file.
- */
+ /** Config store file name for general shared store file. */
private const val STORE_FILE_NAME = "permission_changes.xml"
private const val TAG_PERMISSION_CHANGES = "permission-changes"
@@ -79,13 +73,10 @@ class PermissionChangeStorageImpl(
private const val ATTR_PACKAGE_NAME = "package-name"
private const val ATTR_EVENT_TIME = "event-time"
- @Volatile
- private var INSTANCE: PermissionEventStorage<PermissionChange>? = null
+ @Volatile private var INSTANCE: PermissionEventStorage<PermissionChange>? = null
fun getInstance(): PermissionEventStorage<PermissionChange> =
- INSTANCE ?: synchronized(this) {
- INSTANCE ?: createInstance().also { INSTANCE = it }
- }
+ INSTANCE ?: synchronized(this) { INSTANCE ?: createInstance().also { INSTANCE = it } }
private fun createInstance(): PermissionEventStorage<PermissionChange> {
return PermissionChangeStorageImpl(PermissionControllerApplication.get())
@@ -142,9 +133,7 @@ class PermissionChangeStorageImpl(
val storesExactTime = storesExactTime()
val truncateToDay = didStoreExactTime != storesExactTime && !storesExactTime
while (parser.next() != XmlPullParser.END_TAG) {
- readPermissionChange(parser, format, truncateToDay)?.let {
- entries.add(it)
- }
+ readPermissionChange(parser, format, truncateToDay)?.let { entries.add(it) }
}
return entries
}
@@ -160,9 +149,11 @@ class PermissionChangeStorageImpl(
try {
val packageName = parser.getAttributeValueNullSafe(ns, ATTR_PACKAGE_NAME)
val changeDate = parser.getAttributeValueNullSafe(ns, ATTR_EVENT_TIME)
- var changeTime = format.parse(changeDate)?.time
- ?: throw IllegalArgumentException(
- "Could not parse date $changeDate on package $packageName")
+ var changeTime =
+ format.parse(changeDate)?.time
+ ?: throw IllegalArgumentException(
+ "Could not parse date $changeDate on package $packageName"
+ )
if (truncateToDay) {
changeTime = dateFormat.parse(dateFormat.format(Date(changeTime)))!!.time
}
@@ -184,7 +175,8 @@ class PermissionChangeStorageImpl(
private fun XmlPullParser.getAttributeValueNullSafe(namespace: String?, name: String): String {
return this.getAttributeValue(namespace, name)
?: throw XmlPullParserException(
- "Could not find attribute: namespace $namespace, name $name")
+ "Could not find attribute: namespace $namespace, name $name"
+ )
}
override fun getDatabaseFileName(): String {
@@ -204,11 +196,12 @@ class PermissionChangeStorageImpl(
return this.copy(eventTime = this.eventTime + timeDelta)
}
- /**
- * Should only be true in tests and never true in prod.
- */
+ /** Should only be true in tests and never true in prod. */
private fun storesExactTime(): Boolean {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PERMISSIONS,
- Utils.PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME, /* defaultValue= */ false)
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PERMISSIONS,
+ Utils.PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME,
+ /* defaultValue= */ false
+ )
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceModel.kt
index 49a465898..05fee9797 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceModel.kt
@@ -28,7 +28,6 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.Transformations
import com.android.permissioncontroller.DumpableLog
import com.android.permissioncontroller.PermissionControllerProto.PermissionControllerDumpProto
-import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.data.AppPermGroupUiInfoLiveData
import com.android.permissioncontroller.permission.data.HibernationSettingStateLiveData
import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData
@@ -39,14 +38,15 @@ import com.android.permissioncontroller.permission.data.getUnusedPackages
import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo
import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo.PermGrantState
import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
+import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.Utils
+import java.util.function.IntConsumer
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
-import java.util.function.IntConsumer
/**
* A model for the PermissionControllerServiceImpl. Handles the data gathering for some methods of
@@ -57,10 +57,10 @@ class PermissionControllerServiceModel(private val service: PermissionController
private val observedLiveDatas = mutableListOf<LiveData<*>>()
/**
- * *Must* be used instead of LiveData.observe, in order to allow the lifecycle state to
- * be set to "started" correctly. If the liveData was inactive, create a no op observer, which
- * will survive until the service goes inactive. Will remove the provided observer after one
- * update (one non-stale update, in the case of a SmartUpdateMediatorLiveData).
+ * *Must* be used instead of LiveData.observe, in order to allow the lifecycle state to be set
+ * to "started" correctly. If the liveData was inactive, create a no op observer, which will
+ * survive until the service goes inactive. Will remove the provided observer after one update
+ * (one non-stale update, in the case of a SmartUpdateMediatorLiveData).
*
* @param liveData The livedata we wish to observe
* @param onChangedFun The function we wish to be called upon livedata updates
@@ -72,14 +72,13 @@ class PermissionControllerServiceModel(private val service: PermissionController
onChangedFun: (t: T?) -> Unit
) {
GlobalScope.launch(Main.immediate) {
-
if (service.lifecycle.currentState != Lifecycle.State.STARTED) {
service.setLifecycleToStarted()
}
if (!liveData.hasActiveObservers()) {
observedLiveDatas.add(liveData)
- liveData.observe(service, Observer { })
+ liveData.observe(service, Observer {})
}
if (forceUpdate && liveData is SmartUpdateMediatorLiveData<T>) {
@@ -87,27 +86,28 @@ class PermissionControllerServiceModel(private val service: PermissionController
}
var updated = false
- val observer = object : Observer<T> {
- override fun onChanged(data: T) {
- if (updated) {
- return
- }
- if ((liveData is SmartUpdateMediatorLiveData<T> && !liveData.isStale) ||
- liveData !is SmartUpdateMediatorLiveData<T>) {
- onChangedFun(data)
- liveData.removeObserver(this)
- updated = true
+ val observer =
+ object : Observer<T> {
+ override fun onChanged(data: T) {
+ if (updated) {
+ return
+ }
+ if (
+ (liveData is SmartUpdateMediatorLiveData<T> && !liveData.isStale) ||
+ liveData !is SmartUpdateMediatorLiveData<T>
+ ) {
+ onChangedFun(data)
+ liveData.removeObserver(this)
+ updated = true
+ }
}
}
- }
liveData.observe(service, observer)
}
}
- /**
- * Stop observing all currently observed liveDatas
- */
+ /** Stop observing all currently observed liveDatas */
fun removeObservers() {
GlobalScope.launch(Main.immediate) {
for (liveData in observedLiveDatas) {
@@ -133,17 +133,16 @@ class PermissionControllerServiceModel(private val service: PermissionController
) {
val packageInfosLiveData = UserPackageInfosLiveData[Process.myUserHandle()]
observeAndCheckForLifecycleState(packageInfosLiveData) { packageInfos ->
- onPackagesLoadedForCountPermissionApps(permissionNames, flags, callback,
- packageInfos)
+ onPackagesLoadedForCountPermissionApps(permissionNames, flags, callback, packageInfos)
}
}
/**
- * Called upon receiving a list of packages which we want to filter by a list of permissions
- * and flags. Observes the AppPermGroupUiInfoLiveData for every app, and, upon receiving a
- * non-stale update, adds it to the count if it matches the permission list and flags. Will
- * only use the first non-stale update, so if an app is updated after this update, but before
- * execution is complete, the changes will not be reflected until the method is called again.
+ * Called upon receiving a list of packages which we want to filter by a list of permissions and
+ * flags. Observes the AppPermGroupUiInfoLiveData for every app, and, upon receiving a non-stale
+ * update, adds it to the count if it matches the permission list and flags. Will only use the
+ * first non-stale update, so if an app is updated after this update, but before execution is
+ * complete, the changes will not be reflected until the method is called again.
*
* @param permissionNames The list of permission names whose apps we want to count
* @param flags Flags specifying if we want to count system apps, and count only granted apps
@@ -167,11 +166,12 @@ class PermissionControllerServiceModel(private val service: PermissionController
// Store the group of all installed, runtime permissions in permissionNames
val permToGroup = mutableMapOf<String, String?>()
for (permName in permissionNames) {
- val permInfo = try {
- service.packageManager.getPermissionInfo(permName, 0)
- } catch (e: PackageManager.NameNotFoundException) {
- continue
- }
+ val permInfo =
+ try {
+ service.packageManager.getPermissionInfo(permName, 0)
+ } catch (e: PackageManager.NameNotFoundException) {
+ continue
+ }
if (Utils.isPermissionDangerousInstalledNotRemoved(permInfo)) {
permToGroup[permName] = PermissionMapping.getGroupOfPermission(permInfo)
@@ -184,8 +184,10 @@ class PermissionControllerServiceModel(private val service: PermissionController
val packageUiLiveDatas = mutableSetOf<AppPermGroupUiInfoLiveData>()
for (permName in permToGroup.keys) {
if (requestedPermissions.contains(permName)) {
- packageUiLiveDatas.add(AppPermGroupUiInfoLiveData[packageName,
- permToGroup[permName]!!, Process.myUserHandle()])
+ packageUiLiveDatas.add(
+ AppPermGroupUiInfoLiveData[
+ packageName, permToGroup[permName]!!, Process.myUserHandle()]
+ )
}
}
if (packageUiLiveDatas.isNotEmpty()) {
@@ -211,8 +213,9 @@ class PermissionControllerServiceModel(private val service: PermissionController
numPermAppsChecked++
if (uiInfo != null && uiInfo.shouldShow && (!uiInfo.isSystem || countSystem)) {
- val granted = uiInfo.permGrantState != PermGrantState.PERMS_DENIED &&
- uiInfo.permGrantState != PermGrantState.PERMS_ASK
+ val granted =
+ uiInfo.permGrantState != PermGrantState.PERMS_DENIED &&
+ uiInfo.permGrantState != PermGrantState.PERMS_ASK
if (granted || !countOnlyGranted && !packageAdded) {
// The permission might not be granted, but some permissions of the
// group are granted. In this case the permission is granted silently
@@ -244,8 +247,7 @@ class PermissionControllerServiceModel(private val service: PermissionController
packageName: String,
callback: Consumer<List<Pair<String, AppPermGroupUiInfo>>>
) {
- val packageGroupsLiveData = PackagePermissionsLiveData[packageName,
- Process.myUserHandle()]
+ val packageGroupsLiveData = PackagePermissionsLiveData[packageName, Process.myUserHandle()]
observeAndCheckForLifecycleState(packageGroupsLiveData) { groups ->
val groupNames = groups?.keys?.toMutableList() ?: mutableListOf()
groupNames.remove(PackagePermissionsLiveData.NON_RUNTIME_NORMAL_PERMS)
@@ -260,8 +262,8 @@ class PermissionControllerServiceModel(private val service: PermissionController
// live datas, because this method is used primarily for UI, and there is inherent
// delay when calling this method, due to binder calls, so some staleness is
// acceptable
- val uiInfoLiveData = AppPermGroupUiInfoLiveData[packageName, groupName,
- Process.myUserHandle()]
+ val uiInfoLiveData =
+ AppPermGroupUiInfoLiveData[packageName, groupName, Process.myUserHandle()]
observeAndCheckForLifecycleState(uiInfoLiveData, forceUpdate = true) { uiInfo ->
numLiveDatasUpdated++
@@ -285,31 +287,25 @@ class PermissionControllerServiceModel(private val service: PermissionController
*
* @param callback The callback our result will be returned to
*/
- fun onCountUnusedApps(
- callback: IntConsumer
- ) {
- val unusedAppsCount = Transformations.map(getUnusedPackages()) {
- it?.size ?: 0
- }
+ fun onCountUnusedApps(callback: IntConsumer) {
+ val unusedAppsCount = Transformations.map(getUnusedPackages()) { it?.size ?: 0 }
observeAndCheckForLifecycleState(unusedAppsCount) { count -> callback.accept(count ?: 0) }
}
/**
- * Gets whether the package is eligible for hibernation. The logic is the same logic used by
- * the app hibernation job when determining which apps to hibernate.
+ * Gets whether the package is eligible for hibernation. The logic is the same logic used by the
+ * app hibernation job when determining which apps to hibernate.
*
* @param packageName The package to check eligibility for
* @param callback The callback the result will be returned to
*/
- fun onGetHibernationEligibility(
- packageName: String,
- callback: IntConsumer
- ) {
+ fun onGetHibernationEligibility(packageName: String, callback: IntConsumer) {
val user = Process.myUserHandle()
val hibernationSettingLiveData = HibernationSettingStateLiveData[packageName, user]
observeAndCheckForLifecycleState(hibernationSettingLiveData) { hibernationSettingState ->
callback.accept(
- hibernationSettingState?.hibernationEligibility ?: HIBERNATION_ELIGIBILITY_UNKNOWN)
+ hibernationSettingState?.hibernationEligibility ?: HIBERNATION_ELIGIBILITY_UNKNOWN
+ )
}
}
@@ -323,9 +319,7 @@ class PermissionControllerServiceModel(private val service: PermissionController
return withTimeout(9000) {
val dumpedLogs = GlobalScope.async(IO) { DumpableLog.get() }
- PermissionControllerDumpProto.newBuilder()
- .addAllLogs(dumpedLogs.await())
- .build()
+ PermissionControllerDumpProto.newBuilder().addAllLogs(dumpedLogs.await()).build()
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventCleanupJobService.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventCleanupJobService.kt
index d22b63e9a..45501cd25 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventCleanupJobService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventCleanupJobService.kt
@@ -26,15 +26,13 @@ import android.provider.DeviceConfig
import com.android.permissioncontroller.Constants
import com.android.permissioncontroller.DumpableLog
import com.android.permissioncontroller.permission.utils.Utils
+import java.util.concurrent.TimeUnit
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
-import java.util.concurrent.TimeUnit
-/**
- * A job to clean up old permission events.
- */
+/** A job to clean up old permission events. */
class PermissionEventCleanupJobService : JobService() {
companion object {
@@ -43,13 +41,15 @@ class PermissionEventCleanupJobService : JobService() {
fun scheduleOldDataCleanupIfNecessary(context: Context, jobScheduler: JobScheduler) {
if (isNewJobScheduleRequired(jobScheduler)) {
- val jobInfo = JobInfo.Builder(
- Constants.OLD_PERMISSION_EVENT_CLEANUP_JOB_ID,
- ComponentName(context, PermissionEventCleanupJobService::class.java))
- .setPeriodic(getClearOldEventsCheckFrequencyMs())
- // persist this job across boots
- .setPersisted(true)
- .build()
+ val jobInfo =
+ JobInfo.Builder(
+ Constants.OLD_PERMISSION_EVENT_CLEANUP_JOB_ID,
+ ComponentName(context, PermissionEventCleanupJobService::class.java)
+ )
+ .setPeriodic(getClearOldEventsCheckFrequencyMs())
+ // persist this job across boots
+ .setPersisted(true)
+ .build()
val status = jobScheduler.schedule(jobInfo)
if (status != JobScheduler.RESULT_SUCCESS) {
DumpableLog.e(LOG_TAG, "Could not schedule job: $status")
@@ -64,8 +64,8 @@ class PermissionEventCleanupJobService : JobService() {
*/
private fun isNewJobScheduleRequired(jobScheduler: JobScheduler): Boolean {
var scheduleNewJob = false
- val existingJob: JobInfo? = jobScheduler
- .getPendingJob(Constants.OLD_PERMISSION_EVENT_CLEANUP_JOB_ID)
+ val existingJob: JobInfo? =
+ jobScheduler.getPendingJob(Constants.OLD_PERMISSION_EVENT_CLEANUP_JOB_ID)
when {
existingJob == null -> {
DumpableLog.i(LOG_TAG, "No existing job, scheduling a new one")
@@ -83,9 +83,11 @@ class PermissionEventCleanupJobService : JobService() {
}
private fun getClearOldEventsCheckFrequencyMs() =
- DeviceConfig.getLong(DeviceConfig.NAMESPACE_PERMISSIONS,
+ DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_PERMISSIONS,
Utils.PROPERTY_PERMISSION_EVENTS_CHECK_OLD_FREQUENCY_MILLIS,
- DEFAULT_CLEAR_OLD_EVENTS_CHECK_FREQUENCY)
+ DEFAULT_CLEAR_OLD_EVENTS_CHECK_FREQUENCY
+ )
}
var job: Job? = null
@@ -98,15 +100,16 @@ class PermissionEventCleanupJobService : JobService() {
return false
}
jobStartTime = System.currentTimeMillis()
- job = GlobalScope.launch(Dispatchers.IO) {
- for (storage in storages) {
- val success = storage.removeOldData()
- if (!success) {
- DumpableLog.e(LOG_TAG, "Failed to remove old data for $storage")
+ job =
+ GlobalScope.launch(Dispatchers.IO) {
+ for (storage in storages) {
+ val success = storage.removeOldData()
+ if (!success) {
+ DumpableLog.e(LOG_TAG, "Failed to remove old data for $storage")
+ }
}
+ jobFinished(params, false)
}
- jobFinished(params, false)
- }
return true
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventStorage.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventStorage.kt
index 67a1cb4a4..fb73bcf75 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventStorage.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventStorage.kt
@@ -18,9 +18,7 @@ package com.android.permissioncontroller.permission.service
import com.android.permissioncontroller.permission.data.PermissionEvent
-/**
- * Persistent storage for retrieving persisted permission event data.
- */
+/** Persistent storage for retrieving persisted permission event data. */
interface PermissionEventStorage<T : PermissionEvent> {
/**
* Persist a permission event for retrieval later.
@@ -36,9 +34,7 @@ interface PermissionEventStorage<T : PermissionEvent> {
*/
suspend fun loadEvents(): List<T>
- /**
- * Clear all events.
- */
+ /** Clear all events. */
suspend fun clearEvents()
/**
@@ -60,9 +56,9 @@ interface PermissionEventStorage<T : PermissionEvent> {
* Update event timestamps based on the delta in system time.
*
* @param diffSystemTimeMillis the difference between the current and old system times. Positive
- * values mean that the time has changed in the future and negative means the time was changed
- * into the past.
+ * values mean that the time has changed in the future and negative means the time was changed
+ * into the past.
* @return whether the storage was successful
*/
suspend fun updateEventsBySystemTimeDelta(diffSystemTimeMillis: Long): Boolean
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventStorageImpls.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventStorageImpls.kt
index de6a0d9e2..33dc128f6 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventStorageImpls.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionEventStorageImpls.kt
@@ -21,18 +21,13 @@ import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.permission.data.PermissionEvent
import com.android.permissioncontroller.permission.service.v33.PermissionDecisionStorageImpl
-/**
- * Singleton of all supported [PermissionEventStorage] on the device.
- */
+/** Singleton of all supported [PermissionEventStorage] on the device. */
class PermissionEventStorageImpls {
companion object {
- @Volatile
- private var INSTANCE: List<PermissionEventStorage<out PermissionEvent>>? = null
+ @Volatile private var INSTANCE: List<PermissionEventStorage<out PermissionEvent>>? = null
fun getInstance(): List<PermissionEventStorage<out PermissionEvent>> =
- INSTANCE ?: synchronized(this) {
- INSTANCE ?: createInstance().also { INSTANCE = it }
- }
+ INSTANCE ?: synchronized(this) { INSTANCE ?: createInstance().also { INSTANCE = it } }
@SuppressLint("NewApi")
private fun createInstance(): List<PermissionEventStorage<out PermissionEvent>> {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionStorageTimeChangeReceiver.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionStorageTimeChangeReceiver.kt
index 43970dd13..ccb3acbad 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionStorageTimeChangeReceiver.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionStorageTimeChangeReceiver.kt
@@ -26,10 +26,10 @@ import com.android.permissioncontroller.DumpableLog
import com.android.permissioncontroller.permission.data.PermissionEvent
import com.android.permissioncontroller.permission.utils.SystemTimeSource
import com.android.permissioncontroller.permission.utils.TimeSource
+import kotlin.math.abs
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
-import kotlin.math.abs
/**
* [BroadcastReceiver] to update the persisted timestamps when the date changes. Receives broadcasts
@@ -51,8 +51,7 @@ class PermissionStorageTimeChangeReceiver(
* Key for the last known system time from the system. First initialized after boot
* complete.
*/
- @VisibleForTesting
- const val PREF_KEY_SYSTEM_TIME_SNAPSHOT = "system_time_snapshot"
+ @VisibleForTesting const val PREF_KEY_SYSTEM_TIME_SNAPSHOT = "system_time_snapshot"
/**
* Key for the last known elapsed time since boot. First initialized after boot complete.
@@ -60,12 +59,9 @@ class PermissionStorageTimeChangeReceiver(
@VisibleForTesting
const val PREF_KEY_ELAPSED_REALTIME_SNAPSHOT = "elapsed_realtime_snapshot"
- @VisibleForTesting
- const val SNAPSHOT_UNINITIALIZED = -1L
+ @VisibleForTesting const val SNAPSHOT_UNINITIALIZED = -1L
- /**
- * The millisecond threshold for a time delta to be considered a time change.
- */
+ /** The millisecond threshold for a time delta to be considered a time change. */
private const val TIME_CHANGE_THRESHOLD_MILLIS = 60 * 1000L
}
@@ -75,8 +71,11 @@ class PermissionStorageTimeChangeReceiver(
}
when (val action = intent.action) {
Intent.ACTION_BOOT_COMPLETED -> {
- persistTimeSnapshots(context, timeSource.currentTimeMillis(),
- timeSource.elapsedRealtime())
+ persistTimeSnapshots(
+ context,
+ timeSource.currentTimeMillis(),
+ timeSource.elapsedRealtime()
+ )
}
Intent.ACTION_TIME_CHANGED -> {
checkForTimeChanged(context)
@@ -90,15 +89,16 @@ class PermissionStorageTimeChangeReceiver(
private fun checkForTimeChanged(context: Context) {
val systemTimeSnapshot = getSystemTimeSnapshot(context)
val realtimeSnapshot = getElapsedRealtimeSnapshot(context)
- if (realtimeSnapshot == SNAPSHOT_UNINITIALIZED ||
- systemTimeSnapshot == SNAPSHOT_UNINITIALIZED) {
+ if (
+ realtimeSnapshot == SNAPSHOT_UNINITIALIZED ||
+ systemTimeSnapshot == SNAPSHOT_UNINITIALIZED
+ ) {
DumpableLog.e(LOG_TAG, "Snapshots not initialized")
return
}
val actualSystemTime = timeSource.currentTimeMillis()
val actualRealtime = timeSource.elapsedRealtime()
- val expectedSystemTime = (actualRealtime - realtimeSnapshot) +
- systemTimeSnapshot
+ val expectedSystemTime = (actualRealtime - realtimeSnapshot) + systemTimeSnapshot
val diffSystemTime = actualSystemTime - expectedSystemTime
if (abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
DumpableLog.d(LOG_TAG, "Time changed by ${diffSystemTime / 1000} seconds")
@@ -131,17 +131,21 @@ class PermissionStorageTimeChangeReceiver(
}
private fun getSystemTimeSnapshot(context: Context): Long {
- return context.sharedPreferences.getLong(PREF_KEY_SYSTEM_TIME_SNAPSHOT,
- SNAPSHOT_UNINITIALIZED)
+ return context.sharedPreferences.getLong(
+ PREF_KEY_SYSTEM_TIME_SNAPSHOT,
+ SNAPSHOT_UNINITIALIZED
+ )
}
private fun getElapsedRealtimeSnapshot(context: Context): Long {
- return context.sharedPreferences.getLong(PREF_KEY_ELAPSED_REALTIME_SNAPSHOT,
- SNAPSHOT_UNINITIALIZED)
+ return context.sharedPreferences.getLong(
+ PREF_KEY_ELAPSED_REALTIME_SNAPSHOT,
+ SNAPSHOT_UNINITIALIZED
+ )
}
val Context.sharedPreferences: SharedPreferences
get() {
return PreferenceManager.getDefaultSharedPreferences(this)
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PersistedStoragePackageUninstalledReceiver.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/PersistedStoragePackageUninstalledReceiver.kt
index 37fa2b36d..383e52dfc 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PersistedStoragePackageUninstalledReceiver.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PersistedStoragePackageUninstalledReceiver.kt
@@ -29,8 +29,8 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
/**
- * [BroadcastReceiver] to clear user decision information when a package has its data cleared or
- * is fully removed.
+ * [BroadcastReceiver] to clear user decision information when a package has its data cleared or is
+ * fully removed.
*/
class PersistedStoragePackageUninstalledReceiver(
@VisibleForTesting
@@ -48,8 +48,10 @@ class PersistedStoragePackageUninstalledReceiver(
return
}
val action = intent.action
- if (!(action == Intent.ACTION_PACKAGE_DATA_CLEARED ||
- action == Intent.ACTION_PACKAGE_FULLY_REMOVED)) {
+ if (
+ !(action == Intent.ACTION_PACKAGE_DATA_CLEARED ||
+ action == Intent.ACTION_PACKAGE_FULLY_REMOVED)
+ ) {
return
}
intent.data?.let {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt
index 11299def9..d8fc48bbc 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt
@@ -49,20 +49,19 @@ import com.android.permissioncontroller.permission.utils.application
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
-/**
- * This class handles upgrading the runtime permissions database
- */
+/** This class handles upgrading the runtime permissions database */
internal object RuntimePermissionsUpgradeController {
private val LOG_TAG = RuntimePermissionsUpgradeController::class.java.simpleName
// The latest version of the runtime permissions database
- private val LATEST_VERSION = if (SdkLevel.isAtLeastU()) {
- 11
- } else if (SdkLevel.isAtLeastT()) {
- 10
- } else {
- 9
- }
+ private val LATEST_VERSION =
+ if (SdkLevel.isAtLeastU()) {
+ 11
+ } else if (SdkLevel.isAtLeastT()) {
+ 10
+ } else {
+ 9
+ }
fun upgradeIfNeeded(context: Context, onComplete: Runnable) {
val permissionManager = context.getSystemService(PermissionManager::class.java)
@@ -72,9 +71,13 @@ internal object RuntimePermissionsUpgradeController {
GlobalScope.launch(IPC) {
val upgradedVersion = onUpgradeLocked(context, currentVersion)
if (upgradedVersion != LATEST_VERSION) {
- Log.wtf("PermissionControllerService", "warning: upgrading permission database" +
- " to version $LATEST_VERSION left it at $currentVersion instead; this is " +
- "probably a bug. Did you update LATEST_VERSION?", Throwable())
+ Log.wtf(
+ "PermissionControllerService",
+ "warning: upgrading permission database" +
+ " to version $LATEST_VERSION left it at $currentVersion instead; this is " +
+ "probably a bug. Did you update LATEST_VERSION?",
+ Throwable()
+ )
throw RuntimeException("db upgrade error")
}
@@ -90,7 +93,6 @@ internal object RuntimePermissionsUpgradeController {
*
* @param permissionInfos permissions to exempt
* @param pkgs packages to exempt
- *
* @return the exemptions to apply
*/
private fun getExemptions(
@@ -110,9 +112,8 @@ internal object RuntimePermissionsUpgradeController {
}
/**
- * You must perform all necessary mutations to bring the runtime permissions
- * database from the old to the new version. When you add a new upgrade step
- * you *must* update LATEST_VERSION.
+ * You must perform all necessary mutations to bring the runtime permissions database from the
+ * old to the new version. When you add a new upgrade step you *must* update LATEST_VERSION.
*
* <p> NOTE: Relies upon the fact that the system will attempt to upgrade every version after
* currentVersion in order, without skipping any versions. Should this become the case, this
@@ -121,10 +122,7 @@ internal object RuntimePermissionsUpgradeController {
* @param context The current context
* @param currentVersion The current version of the permission database
*/
- private suspend fun onUpgradeLocked(
- context: Context,
- currentVersion: Int
- ): Int {
+ private suspend fun onUpgradeLocked(context: Context, currentVersion: Int): Int {
var sdkUpgradedFromP = false
var isNewUser = false
@@ -143,188 +141,232 @@ internal object RuntimePermissionsUpgradeController {
// All data needed by this method.
//
// All data is loaded once and then not updated.
- val upgradeDataProvider = object : SmartUpdateMediatorLiveData<UpgradeData>() {
- /** Provides all preinstalled packages in the system */
- private val preinstalledPkgInfoProvider =
+ val upgradeDataProvider =
+ object : SmartUpdateMediatorLiveData<UpgradeData>() {
+ /** Provides all preinstalled packages in the system */
+ private val preinstalledPkgInfoProvider =
PreinstalledUserPackageInfosLiveData[myUserHandle()]
- /** Provides all platform runtime permission infos */
- private val platformRuntimePermissionInfoProviders =
+ /** Provides all platform runtime permission infos */
+ private val platformRuntimePermissionInfoProviders =
mutableListOf<LightPermInfoLiveData>()
- /** {@link #platformRuntimePermissionInfoProvider} that already provided a result */
- private val platformRuntimePermissionInfoProvidersDone =
+ /** {@link #platformRuntimePermissionInfoProvider} that already provided a result */
+ private val platformRuntimePermissionInfoProvidersDone =
mutableSetOf<LightPermInfoLiveData>()
- /** Provides all packages in the system */
- private val pkgInfoProvider = UserPackageInfosLiveData[myUserHandle()]
+ /** Provides all packages in the system */
+ private val pkgInfoProvider = UserPackageInfosLiveData[myUserHandle()]
- /** Provides all {@link LightAppPermGroup} this upgrade needs */
- private var permGroupProviders: MutableSet<LightAppPermGroupLiveData>? = null
+ /** Provides all {@link LightAppPermGroup} this upgrade needs */
+ private var permGroupProviders: MutableSet<LightAppPermGroupLiveData>? = null
- /** {@link #permGroupProviders} that already provided a result */
- private val permGroupProvidersDone = mutableSetOf<LightAppPermGroupLiveData>()
+ /** {@link #permGroupProviders} that already provided a result */
+ private val permGroupProvidersDone = mutableSetOf<LightAppPermGroupLiveData>()
- init {
- // First step: Load packages + perm infos
- addSource(pkgInfoProvider) { pkgInfos ->
- if (pkgInfos != null) {
- removeSource(pkgInfoProvider)
+ init {
+ // First step: Load packages + perm infos
+ addSource(pkgInfoProvider) { pkgInfos ->
+ if (pkgInfos != null) {
+ removeSource(pkgInfoProvider)
- addSource(preinstalledPkgInfoProvider) { preinstalledPkgInfos ->
- if (preinstalledPkgInfos != null) {
- removeSource(preinstalledPkgInfoProvider)
+ addSource(preinstalledPkgInfoProvider) { preinstalledPkgInfos ->
+ if (preinstalledPkgInfos != null) {
+ removeSource(preinstalledPkgInfoProvider)
- update()
+ update()
+ }
}
}
}
- }
- for (platformRuntimePermission in getRuntimePlatformPermissionNames()) {
- val permProvider = LightPermInfoLiveData[platformRuntimePermission]
- platformRuntimePermissionInfoProviders.add(permProvider)
+ for (platformRuntimePermission in getRuntimePlatformPermissionNames()) {
+ val permProvider = LightPermInfoLiveData[platformRuntimePermission]
+ platformRuntimePermissionInfoProviders.add(permProvider)
- addSource(permProvider) { permInfo ->
- if (permInfo != null) {
- platformRuntimePermissionInfoProvidersDone.add(permProvider)
- removeSource(permProvider)
+ addSource(permProvider) { permInfo ->
+ if (permInfo != null) {
+ platformRuntimePermissionInfoProvidersDone.add(permProvider)
+ removeSource(permProvider)
- update()
+ update()
+ }
}
}
}
- }
- override fun onUpdate() {
- if (permGroupProviders == null && pkgInfoProvider.value != null) {
- // Second step: Trigger load of app-perm-groups
+ override fun onUpdate() {
+ if (permGroupProviders == null && pkgInfoProvider.value != null) {
+ // Second step: Trigger load of app-perm-groups
- permGroupProviders = mutableSetOf()
+ permGroupProviders = mutableSetOf()
- // Only load app-perm-groups needed for this upgrade
- if (needBackgroundAppPermGroups || needAccessMediaAppPermGroups ||
- needGrantedExternalStorage || needGrantedReadMediaVisual) {
- for ((pkgName, _, requestedPerms, requestedPermFlags) in
+ // Only load app-perm-groups needed for this upgrade
+ if (
+ needBackgroundAppPermGroups ||
+ needAccessMediaAppPermGroups ||
+ needGrantedExternalStorage ||
+ needGrantedReadMediaVisual
+ ) {
+ for ((pkgName, _, requestedPerms, requestedPermFlags) in
pkgInfoProvider.value!!) {
- var requestsAccessMediaLocation = false
- var hasGrantedExternalStorage = false
- var hasGrantedReadMediaVisual = false
-
- for ((perm, flags) in requestedPerms.zip(requestedPermFlags)) {
- if (needBackgroundAppPermGroups &&
- perm == permission.ACCESS_BACKGROUND_LOCATION) {
- permGroupProviders!!.add(LightAppPermGroupLiveData[pkgName,
- permission_group.LOCATION, myUserHandle()])
- }
-
- if (needAccessMediaAppPermGroups || needGrantedExternalStorage ||
- needGrantedReadMediaVisual) {
- if (needAccessMediaAppPermGroups &&
- perm == permission.ACCESS_MEDIA_LOCATION) {
- requestsAccessMediaLocation = true
+ var requestsAccessMediaLocation = false
+ var hasGrantedExternalStorage = false
+ var hasGrantedReadMediaVisual = false
+
+ for ((perm, flags) in requestedPerms.zip(requestedPermFlags)) {
+ if (
+ needBackgroundAppPermGroups &&
+ perm == permission.ACCESS_BACKGROUND_LOCATION
+ ) {
+ permGroupProviders!!.add(
+ LightAppPermGroupLiveData[
+ pkgName, permission_group.LOCATION, myUserHandle()]
+ )
}
- val isGranted =
- flags and PackageInfo.REQUESTED_PERMISSION_GRANTED != 0
- if (perm == permission.READ_EXTERNAL_STORAGE && isGranted) {
- hasGrantedExternalStorage = true
- }
- if (PermissionMapping.getGroupOfPlatformPermission(perm)
- == permission_group.READ_MEDIA_VISUAL && isGranted) {
- hasGrantedReadMediaVisual = true
+ if (
+ needAccessMediaAppPermGroups ||
+ needGrantedExternalStorage ||
+ needGrantedReadMediaVisual
+ ) {
+ if (
+ needAccessMediaAppPermGroups &&
+ perm == permission.ACCESS_MEDIA_LOCATION
+ ) {
+ requestsAccessMediaLocation = true
+ }
+
+ val isGranted =
+ flags and PackageInfo.REQUESTED_PERMISSION_GRANTED != 0
+ if (perm == permission.READ_EXTERNAL_STORAGE && isGranted) {
+ hasGrantedExternalStorage = true
+ }
+ if (
+ PermissionMapping.getGroupOfPlatformPermission(perm) ==
+ permission_group.READ_MEDIA_VISUAL && isGranted
+ ) {
+ hasGrantedReadMediaVisual = true
+ }
}
}
- }
- val accessMediaLocationPermGroup =
- if (SdkLevel.isAtLeastT())
- permission_group.READ_MEDIA_VISUAL
- else
- permission_group.STORAGE
-
- if (hasGrantedExternalStorage) {
- if (needGrantedExternalStorage) {
- permGroupProviders!!.add(LightAppPermGroupLiveData[pkgName,
- permission_group.STORAGE, myUserHandle()])
- if (SdkLevel.isAtLeastT()) {
- permGroupProviders!!.add(LightAppPermGroupLiveData[pkgName,
- permission_group.READ_MEDIA_VISUAL, myUserHandle()])
- permGroupProviders!!.add(LightAppPermGroupLiveData[pkgName,
- permission_group.READ_MEDIA_AURAL, myUserHandle()])
+ val accessMediaLocationPermGroup =
+ if (SdkLevel.isAtLeastT()) permission_group.READ_MEDIA_VISUAL
+ else permission_group.STORAGE
+
+ if (hasGrantedExternalStorage) {
+ if (needGrantedExternalStorage) {
+ permGroupProviders!!.add(
+ LightAppPermGroupLiveData[
+ pkgName, permission_group.STORAGE, myUserHandle()]
+ )
+ if (SdkLevel.isAtLeastT()) {
+ permGroupProviders!!.add(
+ LightAppPermGroupLiveData[
+ pkgName,
+ permission_group.READ_MEDIA_VISUAL,
+ myUserHandle()]
+ )
+ permGroupProviders!!.add(
+ LightAppPermGroupLiveData[
+ pkgName,
+ permission_group.READ_MEDIA_AURAL,
+ myUserHandle()]
+ )
+ }
+ } else if (requestsAccessMediaLocation) {
+ permGroupProviders!!.add(
+ LightAppPermGroupLiveData[
+ pkgName,
+ accessMediaLocationPermGroup,
+ myUserHandle()]
+ )
}
- } else if (requestsAccessMediaLocation) {
- permGroupProviders!!.add(LightAppPermGroupLiveData[pkgName,
- accessMediaLocationPermGroup, myUserHandle()])
}
- }
- if (hasGrantedReadMediaVisual && needGrantedReadMediaVisual) {
- permGroupProviders!!.add(LightAppPermGroupLiveData[pkgName,
- permission_group.READ_MEDIA_VISUAL, myUserHandle()])
+ if (hasGrantedReadMediaVisual && needGrantedReadMediaVisual) {
+ permGroupProviders!!.add(
+ LightAppPermGroupLiveData[
+ pkgName,
+ permission_group.READ_MEDIA_VISUAL,
+ myUserHandle()]
+ )
+ }
}
}
- }
- // Wait until groups are loaded and then trigger third step
- for (permGroupProvider in permGroupProviders!!) {
- addSource(permGroupProvider) { group ->
- if (group != null) {
- permGroupProvidersDone.add(permGroupProvider)
- removeSource(permGroupProvider)
+ // Wait until groups are loaded and then trigger third step
+ for (permGroupProvider in permGroupProviders!!) {
+ addSource(permGroupProvider) { group ->
+ if (group != null) {
+ permGroupProvidersDone.add(permGroupProvider)
+ removeSource(permGroupProvider)
- update()
+ update()
+ }
}
}
- }
- // If no group need to be loaded, directly switch to third step
- if (permGroupProviders!!.isEmpty()) {
- update()
- }
- } else if (permGroupProviders != null &&
- permGroupProvidersDone.size == permGroupProviders!!.size &&
- preinstalledPkgInfoProvider.value != null &&
- platformRuntimePermissionInfoProviders.size
- == platformRuntimePermissionInfoProvidersDone.size) {
- // Third step: All packages, perm infos and perm groups are loaded, set value
-
- val bgGroups = mutableListOf<LightAppPermGroup>()
- val storageGroups = mutableListOf<LightAppPermGroup>()
-
- for (group in permGroupProviders!!.mapNotNull { it.value }) {
- when (group.permGroupName) {
- permission_group.LOCATION -> {
- bgGroups.add(group)
- }
- permission_group.STORAGE -> {
- storageGroups.add(group)
- }
- permission_group.READ_MEDIA_AURAL -> {
- storageGroups.add(group)
- }
- permission_group.READ_MEDIA_VISUAL -> {
- storageGroups.add(group)
+ // If no group need to be loaded, directly switch to third step
+ if (permGroupProviders!!.isEmpty()) {
+ update()
+ }
+ } else if (
+ permGroupProviders != null &&
+ permGroupProvidersDone.size == permGroupProviders!!.size &&
+ preinstalledPkgInfoProvider.value != null &&
+ platformRuntimePermissionInfoProviders.size ==
+ platformRuntimePermissionInfoProvidersDone.size
+ ) {
+ // Third step: All packages, perm infos and perm groups are loaded, set
+ // value
+
+ val bgGroups = mutableListOf<LightAppPermGroup>()
+ val storageGroups = mutableListOf<LightAppPermGroup>()
+
+ for (group in permGroupProviders!!.mapNotNull { it.value }) {
+ when (group.permGroupName) {
+ permission_group.LOCATION -> {
+ bgGroups.add(group)
+ }
+ permission_group.STORAGE -> {
+ storageGroups.add(group)
+ }
+ permission_group.READ_MEDIA_AURAL -> {
+ storageGroups.add(group)
+ }
+ permission_group.READ_MEDIA_VISUAL -> {
+ storageGroups.add(group)
+ }
}
}
- }
- val restrictedPermissions = mutableSetOf<String>()
- for (permInfoLiveDt in platformRuntimePermissionInfoProviders) {
- val permInfo = permInfoLiveDt.value!!
+ val restrictedPermissions = mutableSetOf<String>()
+ for (permInfoLiveDt in platformRuntimePermissionInfoProviders) {
+ val permInfo = permInfoLiveDt.value!!
+
+ if (
+ permInfo.flags and
+ (PermissionInfo.FLAG_HARD_RESTRICTED or
+ PermissionInfo.FLAG_SOFT_RESTRICTED) == 0
+ ) {
+ continue
+ }
- if (permInfo.flags and (PermissionInfo.FLAG_HARD_RESTRICTED or
- PermissionInfo.FLAG_SOFT_RESTRICTED) == 0) {
- continue
+ restrictedPermissions.add(permInfo.name)
}
- restrictedPermissions.add(permInfo.name)
+ value =
+ UpgradeData(
+ preinstalledPkgInfoProvider.value!!,
+ restrictedPermissions,
+ pkgInfoProvider.value!!,
+ bgGroups,
+ storageGroups
+ )
}
-
- value = UpgradeData(preinstalledPkgInfoProvider.value!!, restrictedPermissions,
- pkgInfoProvider.value!!, bgGroups, storageGroups)
}
}
- }
// Trigger loading of data and wait until data is loaded
val upgradeData = upgradeDataProvider.getInitializedValue(forceUpdate = true)
@@ -334,14 +376,18 @@ internal object RuntimePermissionsUpgradeController {
// always exempting them. For non-OTA updates the installer should do the exemption.
// If a restricted permission can't be exempted by the installer then it should be filtered
// out here.
- val preinstalledAppExemptions = getExemptions(
- upgradeData.restrictedPermissions,
- upgradeData.preinstalledPkgs)
+ val preinstalledAppExemptions =
+ getExemptions(upgradeData.restrictedPermissions, upgradeData.preinstalledPkgs)
- val (newVersion, upgradeExemptions, grants) = onUpgradeLockedDataLoaded(currentVersion,
- upgradeData.pkgs, upgradeData.restrictedPermissions,
- upgradeData.bgGroups, upgradeData.storageGroups,
- isDeviceUpgrading)
+ val (newVersion, upgradeExemptions, grants) =
+ onUpgradeLockedDataLoaded(
+ currentVersion,
+ upgradeData.pkgs,
+ upgradeData.restrictedPermissions,
+ upgradeData.bgGroups,
+ upgradeData.storageGroups,
+ isDeviceUpgrading
+ )
// Do not run in parallel. Measurements have shown that this is slower than sequential
for (exemption in (preinstalledAppExemptions union upgradeExemptions)) {
@@ -387,9 +433,10 @@ internal object RuntimePermissionsUpgradeController {
if (currentVersion == 0) {
Log.i(LOG_TAG, "Grandfathering SMS and CallLog permissions")
- val permissions = restrictedPermissions intersect
+ val permissions =
+ restrictedPermissions intersect
(getPlatformPermissionNamesOfGroup(permission_group.SMS) +
- getPlatformPermissionNamesOfGroup(permission_group.CALL_LOG))
+ getPlatformPermissionNamesOfGroup(permission_group.CALL_LOG))
exemptions.addAll(getExemptions(permissions, pkgs))
@@ -409,8 +456,7 @@ internal object RuntimePermissionsUpgradeController {
if (currentVersion == 3) {
Log.i(LOG_TAG, "Grandfathering location background permissions")
- val bgLocExemptions = getExemptions(setOf(permission.ACCESS_BACKGROUND_LOCATION),
- pkgs)
+ val bgLocExemptions = getExemptions(setOf(permission.ACCESS_BACKGROUND_LOCATION), pkgs)
// Adjust bgApps as if the exemption was applied
for ((pkgName, _) in bgLocExemptions) {
@@ -419,13 +465,22 @@ internal object RuntimePermissionsUpgradeController {
val allPermissionsWithxemption = bgApp.allPermissions.toMutableMap()
allPermissionsWithxemption[permission.ACCESS_BACKGROUND_LOCATION] =
- LightPermission(perm.pkgInfo, perm.permInfo, perm.isGrantedIncludingAppOp,
+ LightPermission(
+ perm.pkgInfo,
+ perm.permInfo,
+ perm.isGrantedIncludingAppOp,
perm.flags or FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
- perm.foregroundPerms)
-
- bgAppsWithExemption[pkgName] = LightAppPermGroup(bgApp.packageInfo,
- bgApp.permGroupInfo, allPermissionsWithxemption,
- bgApp.hasInstallToRuntimeSplit, bgApp.specialLocationGrant)
+ perm.foregroundPerms
+ )
+
+ bgAppsWithExemption[pkgName] =
+ LightAppPermGroup(
+ bgApp.packageInfo,
+ bgApp.permGroupInfo,
+ allPermissionsWithxemption,
+ bgApp.hasInstallToRuntimeSplit,
+ bgApp.specialLocationGrant
+ )
}
exemptions.addAll(bgLocExemptions)
@@ -441,7 +496,8 @@ internal object RuntimePermissionsUpgradeController {
if (currentVersion == 5) {
Log.i(LOG_TAG, "Grandfathering Storage permissions")
- val permissions = restrictedPermissions intersect
+ val permissions =
+ restrictedPermissions intersect
getPlatformPermissionNamesOfGroup(permission_group.STORAGE)
// We don't want to allow modification of storage post install, so put it
@@ -455,18 +511,23 @@ internal object RuntimePermissionsUpgradeController {
if (sdkUpgradedFromP) {
Log.i(LOG_TAG, "Expanding location permissions")
for (appPermGroup in bgAppsWithExemption.values) {
- if (appPermGroup.foreground.isGranted &&
- appPermGroup.hasBackgroundGroup &&
- !appPermGroup.background.isUserSet &&
- !appPermGroup.background.isSystemFixed &&
- !appPermGroup.background.isPolicyFixed &&
- !appPermGroup.background.isUserFixed) {
+ if (
+ appPermGroup.foreground.isGranted &&
+ appPermGroup.hasBackgroundGroup &&
+ !appPermGroup.background.isUserSet &&
+ !appPermGroup.background.isSystemFixed &&
+ !appPermGroup.background.isPolicyFixed &&
+ !appPermGroup.background.isUserFixed
+ ) {
grants.add(Grant(true, appPermGroup))
}
}
} else {
- Log.i(LOG_TAG, "Not expanding location permissions as this is not an upgrade " +
- "from Android P")
+ Log.i(
+ LOG_TAG,
+ "Not expanding location permissions as this is not an upgrade " +
+ "from Android P"
+ )
}
currentVersion = 7
@@ -477,18 +538,25 @@ internal object RuntimePermissionsUpgradeController {
Log.i(LOG_TAG, "Expanding read storage to access media location")
for (appPermGroup in storageAndMediaAppPermGroups) {
- val perm = appPermGroup.permissions[permission.ACCESS_MEDIA_LOCATION]
- ?: continue
-
- if (!perm.isUserSet && !perm.isSystemFixed && !perm.isPolicyFixed &&
- !perm.isGrantedIncludingAppOp) {
- grants.add(Grant(false, appPermGroup,
- listOf(permission.ACCESS_MEDIA_LOCATION)))
+ val perm =
+ appPermGroup.permissions[permission.ACCESS_MEDIA_LOCATION] ?: continue
+
+ if (
+ !perm.isUserSet &&
+ !perm.isSystemFixed &&
+ !perm.isPolicyFixed &&
+ !perm.isGrantedIncludingAppOp
+ ) {
+ grants.add(
+ Grant(false, appPermGroup, listOf(permission.ACCESS_MEDIA_LOCATION))
+ )
}
}
} else {
- Log.i(LOG_TAG, "Not expanding read storage to access media location as this is " +
- "a new user")
+ Log.i(
+ LOG_TAG,
+ "Not expanding read storage to access media location as this is " + "a new user"
+ )
}
currentVersion = 8
@@ -502,35 +570,47 @@ internal object RuntimePermissionsUpgradeController {
if (currentVersion == 9 && SdkLevel.isAtLeastT()) {
if (isNewUser) {
- Log.i(LOG_TAG, "Not migrating STORAGE permissions to READ_MEDIA permissions as" +
- " this is a new user")
+ Log.i(
+ LOG_TAG,
+ "Not migrating STORAGE permissions to READ_MEDIA permissions as" +
+ " this is a new user"
+ )
} else if (!isDeviceUpgrading) {
- Log.i(LOG_TAG, "Not migrating STORAGE permissions to READ_MEDIA permissions as" +
- " this device is not performing an upgrade")
+ Log.i(
+ LOG_TAG,
+ "Not migrating STORAGE permissions to READ_MEDIA permissions as" +
+ " this device is not performing an upgrade"
+ )
} else {
Log.i(LOG_TAG, "Migrating STORAGE permissions to READ_MEDIA permissions")
// Upon upgrading to platform 33, for all targetSdk>=33 apps, do the following:
// If STORAGE is granted, and the user has not set READ_MEDIA_AURAL or
// READ_MEDIA_VISUAL, grant READ_MEDIA_AURAL and READ_MEDIA_VISUAL
- val storageAppPermGroups = storageAndMediaAppPermGroups.filter {
- it.packageInfo.targetSdkVersion >= Build.VERSION_CODES.TIRAMISU &&
- it.permGroupInfo.name == permission_group.STORAGE &&
- it.isGranted && it.isUserSet
- }
+ val storageAppPermGroups =
+ storageAndMediaAppPermGroups.filter {
+ it.packageInfo.targetSdkVersion >= Build.VERSION_CODES.TIRAMISU &&
+ it.permGroupInfo.name == permission_group.STORAGE &&
+ it.isGranted &&
+ it.isUserSet
+ }
for (storageAppPermGroup in storageAppPermGroups) {
val pkgName = storageAppPermGroup.packageInfo.packageName
- val auralAppPermGroup = storageAndMediaAppPermGroups.firstOrNull {
- it.packageInfo.packageName == pkgName &&
- it.permGroupInfo.name == permission_group.READ_MEDIA_AURAL &&
- !it.isUserSet && !it.isUserFixed
- }
- val visualAppPermGroup = storageAndMediaAppPermGroups.firstOrNull {
- it.packageInfo.packageName == pkgName &&
- it.permGroupInfo.name == permission_group.READ_MEDIA_VISUAL &&
- !it.permissions.filter { it.key != permission.ACCESS_MEDIA_LOCATION }
- .any { it.value.isUserSet || it.value.isUserFixed }
- }
+ val auralAppPermGroup =
+ storageAndMediaAppPermGroups.firstOrNull {
+ it.packageInfo.packageName == pkgName &&
+ it.permGroupInfo.name == permission_group.READ_MEDIA_AURAL &&
+ !it.isUserSet &&
+ !it.isUserFixed
+ }
+ val visualAppPermGroup =
+ storageAndMediaAppPermGroups.firstOrNull {
+ it.packageInfo.packageName == pkgName &&
+ it.permGroupInfo.name == permission_group.READ_MEDIA_VISUAL &&
+ !it.permissions
+ .filter { it.key != permission.ACCESS_MEDIA_LOCATION }
+ .any { it.value.isUserSet || it.value.isUserFixed }
+ }
if (auralAppPermGroup != null) {
grants.add(Grant(false, auralAppPermGroup))
@@ -547,16 +627,19 @@ internal object RuntimePermissionsUpgradeController {
// On U, if the app is granted READ_MEDIA_VISUAL, expand the grant to
// READ_MEDIA_VISUAL_USER_SELECTED
if (isDeviceUpgrading && !isNewUser) {
- Log.i(LOG_TAG, "Grandfathering READ_MEDIA_VISUAL_USER_SELECTED to apps already " +
- "granted visual permissions")
- val visualAppPermGroups = storageAndMediaAppPermGroups.filter {
- it.packageInfo.targetSdkVersion >= Build.VERSION_CODES.TIRAMISU &&
- it.permGroupInfo.name == permission_group.READ_MEDIA_VISUAL &&
- it.isGranted && it.isUserSet
- }
- visualAppPermGroups.forEach {
- grants.add(Grant(false, it))
- }
+ Log.i(
+ LOG_TAG,
+ "Grandfathering READ_MEDIA_VISUAL_USER_SELECTED to apps already " +
+ "granted visual permissions"
+ )
+ val visualAppPermGroups =
+ storageAndMediaAppPermGroups.filter {
+ it.packageInfo.targetSdkVersion >= Build.VERSION_CODES.TIRAMISU &&
+ it.permGroupInfo.name == permission_group.READ_MEDIA_VISUAL &&
+ it.isGranted &&
+ it.isUserSet
+ }
+ visualAppPermGroups.forEach { grants.add(Grant(false, it)) }
}
currentVersion = 11
}
@@ -566,9 +649,7 @@ internal object RuntimePermissionsUpgradeController {
return Triple(currentVersion, exemptions, grants)
}
- /**
- * All data needed by {@link #onUpgradeLocked}
- */
+ /** All data needed by {@link #onUpgradeLocked} */
private data class UpgradeData(
/** Preinstalled packages */
val preinstalledPkgs: List<LightPackageInfo>,
@@ -581,15 +662,11 @@ internal object RuntimePermissionsUpgradeController {
* {@link #onUpgradeLockedDataLoaded}
*/
val bgGroups: List<LightAppPermGroup>,
- /**
- * Storage groups that need to be inspected by {@link #onUpgradeLockedDataLoaded}
- */
+ /** Storage groups that need to be inspected by {@link #onUpgradeLockedDataLoaded} */
val storageGroups: List<LightAppPermGroup>,
)
- /**
- * A restricted permission of an app that should be exempted
- */
+ /** A restricted permission of an app that should be exempted */
private data class RestrictionExemption(
/** Name of package to exempt */
val pkgName: String,
@@ -608,9 +685,7 @@ internal object RuntimePermissionsUpgradeController {
}
}
- /**
- * A permission group of an app that should get granted
- */
+ /** A permission group of an app that should get granted */
private data class Grant(
/** Should the grant be for the foreground or background permissions */
private val isBackground: Boolean,
@@ -626,17 +701,21 @@ internal object RuntimePermissionsUpgradeController {
*/
fun applyToPlatform(context: Context) {
if (isBackground) {
- val newGroup = grantBackgroundRuntimePermissions(context.application, group,
- permissions)
+ val newGroup =
+ grantBackgroundRuntimePermissions(context.application, group, permissions)
- logRuntimePermissionUpgradeResult(newGroup,
- permissions intersect newGroup.backgroundPermNames)
+ logRuntimePermissionUpgradeResult(
+ newGroup,
+ permissions intersect newGroup.backgroundPermNames
+ )
} else {
- val newGroup = grantForegroundRuntimePermissions(context.application, group,
- permissions)
+ val newGroup =
+ grantForegroundRuntimePermissions(context.application, group, permissions)
- logRuntimePermissionUpgradeResult(newGroup,
- permissions intersect newGroup.foregroundPermNames)
+ logRuntimePermissionUpgradeResult(
+ newGroup,
+ permissions intersect newGroup.foregroundPermNames
+ )
}
}
@@ -654,10 +733,21 @@ internal object RuntimePermissionsUpgradeController {
val packageName = permissionGroup.packageName
for (permName in filterPermissions) {
val permission = permissionGroup.permissions[permName] ?: continue
- PermissionControllerStatsLog.write(RUNTIME_PERMISSIONS_UPGRADE_RESULT,
- permission.name, uid, packageName)
- Log.v(LOG_TAG, "Runtime permission upgrade logged for permissionName=" +
- permission.name + " uid=" + uid + " packageName=" + packageName)
+ PermissionControllerStatsLog.write(
+ RUNTIME_PERMISSIONS_UPGRADE_RESULT,
+ permission.name,
+ uid,
+ packageName
+ )
+ Log.v(
+ LOG_TAG,
+ "Runtime permission upgrade logged for permissionName=" +
+ permission.name +
+ " uid=" +
+ uid +
+ " packageName=" +
+ packageName
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/SplitPermissionIndex.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/SplitPermissionIndex.kt
index 115200b2f..eb3f2e9af 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/SplitPermissionIndex.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/SplitPermissionIndex.kt
@@ -40,12 +40,14 @@ class SplitPermissionIndex() {
val oldPermGroup = PermissionMapping.getGroupOfPlatformPermission(oldPerm)
val newPermGroup = PermissionMapping.getGroupOfPlatformPermission(newPerm)
if (newPermGroup != null) {
- permToGroupSplits.add(SplitPermissionIndexEntry(
- oldPerm, splitPerm.targetSdk, newPermGroup))
+ permToGroupSplits.add(
+ SplitPermissionIndexEntry(oldPerm, splitPerm.targetSdk, newPermGroup)
+ )
}
if (oldPermGroup != null && newPermGroup != null) {
- groupToGroupSplits.add(SplitPermissionIndexEntry(
- oldPermGroup, splitPerm.targetSdk, newPermGroup))
+ groupToGroupSplits.add(
+ SplitPermissionIndexEntry(oldPermGroup, splitPerm.targetSdk, newPermGroup)
+ )
}
}
}
@@ -53,9 +55,7 @@ class SplitPermissionIndex() {
this.groupToGroupSplits = groupToGroupSplits
}
- /**
- * Given a permission, return which groups split *from* it for the given targetSdk.
- */
+ /** Given a permission, return which groups split *from* it for the given targetSdk. */
fun getPermToGroupSplitsFrom(oldPermission: String, targetSdk: Int): List<String> {
return permToGroupSplits
.filter { it.oldPerm == oldPermission && it.targetSdk < targetSdk }
@@ -63,9 +63,7 @@ class SplitPermissionIndex() {
.toList()
}
- /**
- * Given a permission group, return which groups split *from* it for the given targetSdk.
- */
+ /** Given a permission group, return which groups split *from* it for the given targetSdk. */
fun getGroupToGroupSplitsFrom(oldPermissionGroup: String, targetSdk: Int): List<String> {
return groupToGroupSplits
.filter { it.oldPerm == oldPermissionGroup && it.targetSdk < targetSdk }
@@ -73,9 +71,7 @@ class SplitPermissionIndex() {
.toList()
}
- /**
- * Given a permission group, return which permissions split *to* it for the given targetSdk.
- */
+ /** Given a permission group, return which permissions split *to* it for the given targetSdk. */
fun getGroupToGroupSplitsTo(newPermissionGroup: String, targetSdk: Int): List<String> {
return groupToGroupSplits
.filter { it.newPerm == newPermissionGroup && it.targetSdk < targetSdk }
@@ -88,4 +84,4 @@ class SplitPermissionIndex() {
val targetSdk: Int,
val newPerm: String
)
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/v33/PermissionDecisionStorageImpl.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/v33/PermissionDecisionStorageImpl.kt
index 578b74783..18c40e0e4 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/v33/PermissionDecisionStorageImpl.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/v33/PermissionDecisionStorageImpl.kt
@@ -29,11 +29,6 @@ import com.android.permissioncontroller.permission.data.v33.PermissionDecision
import com.android.permissioncontroller.permission.service.BasePermissionEventStorage
import com.android.permissioncontroller.permission.service.PermissionEventStorage
import com.android.permissioncontroller.permission.utils.Utils
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
-import org.xmlpull.v1.XmlPullParser
-import org.xmlpull.v1.XmlPullParserException
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
@@ -43,10 +38,13 @@ import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.concurrent.TimeUnit
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import org.xmlpull.v1.XmlPullParser
+import org.xmlpull.v1.XmlPullParserException
-/**
- * Implementation of [BasePermissionEventStorage] for storing [PermissionDecision] events.
- */
+/** Implementation of [BasePermissionEventStorage] for storing [PermissionDecision] events. */
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
class PermissionDecisionStorageImpl(
context: Context,
@@ -56,9 +54,7 @@ class PermissionDecisionStorageImpl(
// We don't use namespaces
private val ns: String? = null
- /**
- * The format for how dates are stored.
- */
+ /** The format for how dates are stored. */
private val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US)
companion object {
@@ -66,9 +62,7 @@ class PermissionDecisionStorageImpl(
private const val DB_VERSION = 1
- /**
- * Config store file name for general shared store file.
- */
+ /** Config store file name for general shared store file. */
private const val STORE_FILE_NAME = "recent_permission_decisions.xml"
private const val TAG_RECENT_PERMISSION_DECISIONS = "recent-permission-decisions"
@@ -81,13 +75,10 @@ class PermissionDecisionStorageImpl(
private val DEFAULT_MAX_DATA_AGE_MS = TimeUnit.DAYS.toMillis(7)
- @Volatile
- private var INSTANCE: PermissionEventStorage<PermissionDecision>? = null
+ @Volatile private var INSTANCE: PermissionEventStorage<PermissionDecision>? = null
fun getInstance(): PermissionEventStorage<PermissionDecision> =
- INSTANCE ?: synchronized(this) {
- INSTANCE ?: createInstance().also { INSTANCE = it }
- }
+ INSTANCE ?: synchronized(this) { INSTANCE ?: createInstance().also { INSTANCE = it } }
private fun createInstance(): PermissionEventStorage<PermissionDecision> {
return PermissionDecisionStorageImpl(PermissionControllerApplication.get())
@@ -101,9 +92,15 @@ class PermissionDecisionStorageImpl(
) {
if (isRecordPermissionsSupported(context)) {
GlobalScope.launch(Dispatchers.IO) {
- getInstance().storeEvent(
- PermissionDecision(packageName, System.currentTimeMillis(), permGroupName,
- isGranted))
+ getInstance()
+ .storeEvent(
+ PermissionDecision(
+ packageName,
+ System.currentTimeMillis(),
+ permGroupName,
+ isGranted
+ )
+ )
}
}
}
@@ -148,9 +145,7 @@ class PermissionDecisionStorageImpl(
parser.require(XmlPullParser.START_TAG, ns, TAG_RECENT_PERMISSION_DECISIONS)
while (parser.next() != XmlPullParser.END_TAG) {
- readPermissionDecision(parser)?.let {
- entries.add(it)
- }
+ readPermissionDecision(parser)?.let { entries.add(it) }
}
return entries
}
@@ -163,9 +158,11 @@ class PermissionDecisionStorageImpl(
val packageName = parser.getAttributeValueNullSafe(ns, ATTR_PACKAGE_NAME)
val permissionGroup = parser.getAttributeValueNullSafe(ns, ATTR_PERMISSION_GROUP)
val decisionDate = parser.getAttributeValueNullSafe(ns, ATTR_DECISION_TIME)
- val decisionTime = dateFormat.parse(decisionDate)?.time
- ?: throw IllegalArgumentException(
- "Could not parse date $decisionDate on package $packageName")
+ val decisionTime =
+ dateFormat.parse(decisionDate)?.time
+ ?: throw IllegalArgumentException(
+ "Could not parse date $decisionDate on package $packageName"
+ )
val isGranted = parser.getAttributeValueNullSafe(ns, ATTR_IS_GRANTED).toBoolean()
decision = PermissionDecision(packageName, decisionTime, permissionGroup, isGranted)
} catch (e: XmlPullParserException) {
@@ -185,7 +182,8 @@ class PermissionDecisionStorageImpl(
private fun XmlPullParser.getAttributeValueNullSafe(namespace: String?, name: String): String {
return this.getAttributeValue(namespace, name)
?: throw XmlPullParserException(
- "Could not find attribute: namespace $namespace, name $name")
+ "Could not find attribute: namespace $namespace, name $name"
+ )
}
override fun getDatabaseFileName(): String {
@@ -193,9 +191,11 @@ class PermissionDecisionStorageImpl(
}
override fun getMaxDataAgeMs(): Long {
- return DeviceConfig.getLong(DeviceConfig.NAMESPACE_PERMISSIONS,
+ return DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_PERMISSIONS,
Utils.PROPERTY_PERMISSION_DECISIONS_MAX_DATA_AGE_MILLIS,
- DEFAULT_MAX_DATA_AGE_MS)
+ DEFAULT_MAX_DATA_AGE_MS
+ )
}
override fun hasTheSamePrimaryKey(
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt
index 9231dc17b..b627664d4 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt
@@ -56,10 +56,10 @@ import com.android.permissioncontroller.PermissionControllerStatsLog.APP_DATA_SH
import com.android.permissioncontroller.PermissionControllerStatsLog.APP_DATA_SHARING_UPDATES_NOTIFICATION_INTERACTION__ACTION__DISMISSED
import com.android.permissioncontroller.PermissionControllerStatsLog.APP_DATA_SHARING_UPDATES_NOTIFICATION_INTERACTION__ACTION__NOTIFICATION_SHOWN
import com.android.permissioncontroller.R
-import com.android.permissioncontroller.permission.data.v34.LightInstallSourceInfoLiveData
import com.android.permissioncontroller.permission.data.LightPackageInfoLiveData
import com.android.permissioncontroller.permission.data.SinglePermGroupPackagesUiInfoLiveData
import com.android.permissioncontroller.permission.data.v34.AppDataSharingUpdatesLiveData
+import com.android.permissioncontroller.permission.data.v34.LightInstallSourceInfoLiveData
import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo
import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo.PermGrantState.PERMS_ALLOWED_ALWAYS
import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo.PermGrantState.PERMS_ALLOWED_FOREGROUND_ONLY
@@ -419,9 +419,7 @@ class SafetyLabelChangesJobService : JobService() {
// preinstalled apps.
private suspend fun getAllStoreInstalledPackagesRequestingLocation():
Set<Pair<String, UserHandle>> =
- getAllPackagesRequestingLocation()
- .filter { isSafetyLabelSupported(it) }
- .toSet()
+ getAllPackagesRequestingLocation().filter { isSafetyLabelSupported(it) }.toSet()
private suspend fun getAllPackagesRequestingLocation(): Set<Pair<String, UserHandle>> =
SinglePermGroupPackagesUiInfoLiveData[Manifest.permission_group.LOCATION]
@@ -439,7 +437,7 @@ class SafetyLabelChangesJobService : JobService() {
private suspend fun isSafetyLabelSupported(packageUser: Pair<String, UserHandle>): Boolean {
val lightInstallSourceInfo =
- LightInstallSourceInfoLiveData[packageUser].getInitializedValue()
+ LightInstallSourceInfoLiveData[packageUser].getInitializedValue()
return lightInstallSourceInfo.supportsSafetyLabel
}
@@ -531,8 +529,9 @@ class SafetyLabelChangesJobService : JobService() {
createNotificationChannel(context, notificationManager)
val (appLabel, smallIcon, color) = KotlinUtils.getSafetyCenterNotificationResources(this)
- val smallIconCompat = IconCompat.createFromIcon(smallIcon)
- ?: IconCompat.createWithResource(this, R.drawable.ic_info)
+ val smallIconCompat =
+ IconCompat.createFromIcon(smallIcon)
+ ?: IconCompat.createWithResource(this, R.drawable.ic_info)
val title = context.getString(R.string.safety_label_changes_notification_title)
val text = context.getString(R.string.safety_label_changes_notification_desc)
var notificationBuilder =
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/Category.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/Category.kt
index 61336cdce..5daf26883 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/Category.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/Category.kt
@@ -24,5 +24,6 @@ enum class Category(val categoryName: String) {
ALLOWED("allowed"),
ALLOWED_FOREGROUND("allowed_foreground"),
ASK("ask"),
- DENIED("denied")
+ DENIED("denied"),
+ STORAGE_FOOTER("storage_footer_category"),
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
index c173146eb..a6e521138 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
@@ -546,8 +546,11 @@ public class GrantPermissionsActivity extends SettingsActivity
getWindow().setDimAmount(mOriginalDimAmount);
if (mRootView.getVisibility() == View.GONE) {
- InputMethodManager manager = getSystemService(InputMethodManager.class);
- manager.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
+ if (mIsSystemTriggered) {
+ // We don't want the keyboard obscuring system-triggered dialogs
+ InputMethodManager manager = getSystemService(InputMethodManager.class);
+ manager.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
+ }
mRootView.setVisibility(View.VISIBLE);
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/RemovablePref.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/RemovablePref.kt
index 2525c191c..df4e7947a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/RemovablePref.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/RemovablePref.kt
@@ -16,17 +16,11 @@
package com.android.permissioncontroller.permission.ui
-/**
- * Preference with a clickable UI component for removal.
- */
+/** Preference with a clickable UI component for removal. */
interface RemovablePref {
- /**
- * Sets the action to run when the remove UI component is clicked.
- */
+ /** Sets the action to run when the remove UI component is clicked. */
fun setRemoveClickRunnable(runnable: Runnable)
- /**
- * Set whether the UI component for removal should be enabled or not.
- */
+ /** Set whether the UI component for removal should be enabled or not. */
fun setRemoveComponentEnabled(enabled: Boolean)
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/UnusedAppsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/UnusedAppsFragment.kt
index 68fb493eb..69aef1a4f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/UnusedAppsFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/UnusedAppsFragment.kt
@@ -52,12 +52,14 @@ import com.android.permissioncontroller.permission.utils.KotlinUtils
import java.text.Collator
/**
- * A fragment displaying all applications that are unused as well as the option to remove them
- * and to open them.
+ * A fragment displaying all applications that are unused as well as the option to remove them and
+ * to open them.
*/
-class UnusedAppsFragment<PF, UnusedAppPref> : Fragment()
- where PF : PreferenceFragmentCompat, PF : UnusedAppsFragment.Parent<UnusedAppPref>,
- UnusedAppPref : Preference, UnusedAppPref : RemovablePref {
+class UnusedAppsFragment<PF, UnusedAppPref> : Fragment() where
+PF : PreferenceFragmentCompat,
+PF : UnusedAppsFragment.Parent<UnusedAppPref>,
+UnusedAppPref : Preference,
+UnusedAppPref : RemovablePref {
private lateinit var viewModel: UnusedAppsViewModel
private lateinit var collator: Collator
@@ -72,9 +74,11 @@ class UnusedAppsFragment<PF, UnusedAppPref> : Fragment()
private val LOG_TAG = UnusedAppsFragment::class.java.simpleName
@JvmStatic
- fun <PF, UnusedAppPref> newInstance(): UnusedAppsFragment<PF, UnusedAppPref>
- where PF : PreferenceFragmentCompat, PF : UnusedAppsFragment.Parent<UnusedAppPref>,
- UnusedAppPref : Preference, UnusedAppPref : RemovablePref {
+ fun <PF, UnusedAppPref> newInstance(): UnusedAppsFragment<PF, UnusedAppPref> where
+ PF : PreferenceFragmentCompat,
+ PF : UnusedAppsFragment.Parent<UnusedAppPref>,
+ UnusedAppPref : Preference,
+ UnusedAppPref : RemovablePref {
return UnusedAppsFragment()
}
@@ -82,7 +86,6 @@ class UnusedAppsFragment<PF, UnusedAppPref> : Fragment()
* Create the args needed for this fragment
*
* @param sessionId The current session Id
- *
* @return A bundle containing the session Id
*/
@JvmStatic
@@ -101,29 +104,35 @@ class UnusedAppsFragment<PF, UnusedAppPref> : Fragment()
val preferenceFragment: PF = requirePreferenceFragment()
isFirstLoad = true
- collator = Collator.getInstance(
- context!!.getResources().getConfiguration().getLocales().get(0))
+ collator =
+ Collator.getInstance(context!!.getResources().getConfiguration().getLocales().get(0))
sessionId = arguments!!.getLong(EXTRA_SESSION_ID, INVALID_SESSION_ID)
val factory = UnusedAppsViewModelFactory(activity!!.application, sessionId)
viewModel = ViewModelProvider(this, factory).get(UnusedAppsViewModel::class.java)
- viewModel.unusedPackageCategoriesLiveData.observe(this, Observer {
- it?.let { pkgs ->
- updatePackages(pkgs)
- preferenceFragment.setLoadingState(loading = false, animate = true)
+ viewModel.unusedPackageCategoriesLiveData.observe(
+ this,
+ Observer {
+ it?.let { pkgs ->
+ updatePackages(pkgs)
+ preferenceFragment.setLoadingState(loading = false, animate = true)
+ }
}
- })
+ )
activity?.getActionBar()?.setDisplayHomeAsUpEnabled(true)
if (!viewModel.unusedPackageCategoriesLiveData.isInitialized) {
val handler = Handler(Looper.getMainLooper())
- handler.postDelayed({
- if (!viewModel.unusedPackageCategoriesLiveData.isInitialized) {
- preferenceFragment.setLoadingState(loading = true, animate = true)
- } else {
- updatePackages(viewModel.unusedPackageCategoriesLiveData.value!!)
- }
- }, SHOW_LOAD_DELAY_MS)
+ handler.postDelayed(
+ {
+ if (!viewModel.unusedPackageCategoriesLiveData.isInitialized) {
+ preferenceFragment.setLoadingState(loading = true, animate = true)
+ } else {
+ updatePackages(viewModel.unusedPackageCategoriesLiveData.value!!)
+ }
+ },
+ SHOW_LOAD_DELAY_MS
+ )
} else {
updatePackages(viewModel.unusedPackageCategoriesLiveData.value!!)
}
@@ -150,15 +159,15 @@ class UnusedAppsFragment<PF, UnusedAppPref> : Fragment()
return requireParentFragment() as PF
}
- /**
- * Create [PreferenceScreen] in the parent fragment.
- */
+ /** Create [PreferenceScreen] in the parent fragment. */
private fun createPreferenceScreen() {
val preferenceFragment: PF = requirePreferenceFragment()
- val preferenceScreen = preferenceFragment.preferenceManager.inflateFromResource(
- context!!,
- R.xml.unused_app_categories,
- /* rootPreferences= */ null)
+ val preferenceScreen =
+ preferenceFragment.preferenceManager.inflateFromResource(
+ context!!,
+ R.xml.unused_app_categories,
+ /* rootPreferences= */ null
+ )
for (period in allPeriods) {
val periodCat = PreferenceCategory(context!!)
@@ -208,8 +217,10 @@ class UnusedAppsFragment<PF, UnusedAppPref> : Fragment()
val category = preferenceScreen.findPreference<PreferenceCategory>(period.name)!!
val months = period.months
category.title =
- MessageFormat.format(getString(R.string.last_opened_category_title),
- mapOf("count" to months))
+ MessageFormat.format(
+ getString(R.string.last_opened_category_title),
+ mapOf("count" to months)
+ )
category.isVisible = packages.isNotEmpty()
if (packages.isNotEmpty()) {
allCategoriesEmpty = false
@@ -221,39 +232,53 @@ class UnusedAppsFragment<PF, UnusedAppPref> : Fragment()
var pref = category.findPreference<UnusedAppPref>(key)
if (pref == null) {
- pref = removedPrefs[key] ?: preferenceFragment.createUnusedAppPref(
- activity!!.application, pkgName, user)
+ pref =
+ removedPrefs[key]
+ ?: preferenceFragment.createUnusedAppPref(
+ activity!!.application,
+ pkgName,
+ user
+ )
pref.key = key
pref.title = KotlinUtils.getPackageLabel(activity!!.application, pkgName, user)
}
- pref.setRemoveClickRunnable {
- viewModel.requestUninstallApp(this, pkgName, user)
- }
+ pref.setRemoveClickRunnable { viewModel.requestUninstallApp(this, pkgName, user) }
pref.setRemoveComponentEnabled(!isSystemApp)
- pref.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ ->
- viewModel.navigateToAppInfo(pkgName, user, sessionId)
- true
- }
+ pref.onPreferenceClickListener =
+ Preference.OnPreferenceClickListener { _ ->
+ viewModel.navigateToAppInfo(pkgName, user, sessionId)
+ true
+ }
val mostImportant = getMostImportantGroup(revokedPerms)
val importantLabel = KotlinUtils.getPermGroupLabel(context!!, mostImportant)
- pref.summary = when {
- revokedPerms.isEmpty() -> null
- revokedPerms.size == 1 -> getString(R.string.auto_revoked_app_summary_one,
- importantLabel)
- revokedPerms.size == 2 -> {
- val otherLabel = if (revokedPerms[0] == mostImportant) {
- KotlinUtils.getPermGroupLabel(context!!, revokedPerms[1])
- } else {
- KotlinUtils.getPermGroupLabel(context!!, revokedPerms[0])
+ pref.summary =
+ when {
+ revokedPerms.isEmpty() -> null
+ revokedPerms.size == 1 ->
+ getString(R.string.auto_revoked_app_summary_one, importantLabel)
+ revokedPerms.size == 2 -> {
+ val otherLabel =
+ if (revokedPerms[0] == mostImportant) {
+ KotlinUtils.getPermGroupLabel(context!!, revokedPerms[1])
+ } else {
+ KotlinUtils.getPermGroupLabel(context!!, revokedPerms[0])
+ }
+ getString(
+ R.string.auto_revoked_app_summary_two,
+ importantLabel,
+ otherLabel
+ )
}
- getString(R.string.auto_revoked_app_summary_two, importantLabel, otherLabel)
+ else ->
+ getString(
+ R.string.auto_revoked_app_summary_many,
+ importantLabel,
+ "${revokedPerms.size - 1}"
+ )
}
- else -> getString(R.string.auto_revoked_app_summary_many, importantLabel,
- "${revokedPerms.size - 1}")
- }
category.addPreference(pref)
KotlinUtils.sortPreferenceGroup(category, this::comparePreference, false)
}
@@ -267,13 +292,19 @@ class UnusedAppsFragment<PF, UnusedAppPref> : Fragment()
}
Log.i(LOG_TAG, "sessionId: $sessionId Showed Auto Revoke Page")
for (period in allPeriods) {
- Log.i(LOG_TAG, "sessionId: $sessionId $period unused: " +
- "${categorizedPackages[period]}")
+ Log.i(
+ LOG_TAG,
+ "sessionId: $sessionId $period unused: " + "${categorizedPackages[period]}"
+ )
for (revokedPackageInfo in categorizedPackages[period]!!) {
for (groupName in revokedPackageInfo.revokedGroups) {
val isNewlyRevoked = period.isNewlyUnused()
- viewModel.logAppView(revokedPackageInfo.packageName,
- revokedPackageInfo.user, groupName, isNewlyRevoked)
+ viewModel.logAppView(
+ revokedPackageInfo.packageName,
+ revokedPackageInfo.user,
+ groupName,
+ isNewlyRevoked
+ )
}
}
}
@@ -281,8 +312,7 @@ class UnusedAppsFragment<PF, UnusedAppPref> : Fragment()
}
private fun comparePreference(lhs: Preference, rhs: Preference): Int {
- var result = collator.compare(lhs.title.toString(),
- rhs.title.toString())
+ var result = collator.compare(lhs.title.toString(), rhs.title.toString())
if (result == 0) {
result = lhs.key.compareTo(rhs.key)
}
@@ -324,23 +354,23 @@ class UnusedAppsFragment<PF, UnusedAppPref> : Fragment()
val fragment = parentFragment as UnusedAppsFragment<*, *>
val packageName = arguments!!.getString(Intent.EXTRA_PACKAGE_NAME)!!
val user = arguments!!.getParcelable<UserHandle>(Intent.EXTRA_USER)!!
- val b = AlertDialog.Builder(context!!)
- .setMessage(R.string.app_disable_dlg_text)
- .setPositiveButton(R.string.app_disable_dlg_positive) { _, _ ->
- fragment.viewModel.disableApp(packageName, user)
- }
- .setNegativeButton(R.string.cancel, null)
+ val b =
+ AlertDialog.Builder(context!!)
+ .setMessage(R.string.app_disable_dlg_text)
+ .setPositiveButton(R.string.app_disable_dlg_positive) { _, _ ->
+ fragment.viewModel.disableApp(packageName, user)
+ }
+ .setNegativeButton(R.string.cancel, null)
val d: Dialog = b.create()
d.setCanceledOnTouchOutside(true)
return d
}
}
- /**
- * Interface that the parent fragment must implement.
- */
- interface Parent<UnusedAppPref> where UnusedAppPref : Preference,
- UnusedAppPref : RemovablePref {
+ /** Interface that the parent fragment must implement. */
+ interface Parent<UnusedAppPref> where
+ UnusedAppPref : Preference,
+ UnusedAppPref : RemovablePref {
/**
* Set the title of the current settings page.
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java
index 2de936469..d3a89c3ed 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java
@@ -418,7 +418,7 @@ public class AutoAppPermissionFragment extends AutoSettingsFrameFragment
// TODO(b/229024576): This code is duplicated, refactor ConfirmDialog for easier
// NFF sharing
boolean isGrantFileAccess = getArguments().getSerializable(CHANGE_REQUEST)
- == ChangeRequest.GRANT_All_FILE_ACCESS;
+ == ChangeRequest.GRANT_ALL_FILE_ACCESS;
boolean isGrantStorageSupergroup = getArguments().getSerializable(CHANGE_REQUEST)
== ChangeRequest.GRANT_STORAGE_SUPERGROUP;
int positiveButtonStringResId = R.string.grant_dialog_button_deny_anyway;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoDividerPreference.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoDividerPreference.kt
index aa3c7ffd7..7bb4ccb05 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoDividerPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoDividerPreference.kt
@@ -20,9 +20,7 @@ import android.util.AttributeSet
import androidx.preference.Preference
import com.android.permissioncontroller.R
-/**
- * Non-interactive preference that displays a horizontal divider.
- */
+/** Non-interactive preference that displays a horizontal divider. */
class AutoDividerPreference : Preference {
constructor(
context: Context?,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoPermissionAppsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoPermissionAppsFragment.java
index 29fcb43b2..3b8419bcf 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoPermissionAppsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoPermissionAppsFragment.java
@@ -22,6 +22,7 @@ import static com.android.permissioncontroller.permission.ui.Category.ALLOWED;
import static com.android.permissioncontroller.permission.ui.Category.ALLOWED_FOREGROUND;
import static com.android.permissioncontroller.permission.ui.Category.ASK;
import static com.android.permissioncontroller.permission.ui.Category.DENIED;
+import static com.android.permissioncontroller.permission.ui.Category.STORAGE_FOOTER;
import static com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_CALLER_NAME;
import android.content.Context;
@@ -52,15 +53,15 @@ import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.Utils;
import com.android.settingslib.utils.applications.AppUtils;
+import kotlin.Pair;
+import kotlin.Triple;
+
import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
-import kotlin.Pair;
-import kotlin.Triple;
-
/** Shows the list of applications which have (or do not have) the given permission. */
public class AutoPermissionAppsFragment extends AutoSettingsFrameFragment implements
PermissionUsages.PermissionsUsagesChangeCallback {
@@ -172,6 +173,10 @@ public class AutoPermissionAppsFragment extends AutoSettingsFrameFragment implem
}
// Hide allowed foreground label by default, to avoid briefly showing it before updating
findPreference(ALLOWED_FOREGROUND.getCategoryName()).setVisible(false);
+
+ // Hide storage footer category
+ findPreference(STORAGE_FOOTER.getCategoryName()).setVisible(false);
+
Context context = getPreferenceManager().getContext();
if (context == null || getActivity() == null || categories == null) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsFragment.kt
index 92917a342..99f5c85e4 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsFragment.kt
@@ -53,20 +53,19 @@ class AutoReviewPermissionDecisionsFragment : AutoSettingsFrameFragment() {
private const val LOG_TAG = "AutoReviewPermissionDecisionsFragment"
private const val MAX_DECISIONS = 3
- /**
- * Creates a new instance of [AutoReviewPermissionDecisionsFragment].
- */
+ /** Creates a new instance of [AutoReviewPermissionDecisionsFragment]. */
fun newInstance(
sessionId: Long,
userHandle: UserHandle,
source: String?
): AutoReviewPermissionDecisionsFragment {
return AutoReviewPermissionDecisionsFragment().apply {
- arguments = Bundle().apply {
- putLong(Constants.EXTRA_SESSION_ID, sessionId)
- putParcelable(Intent.EXTRA_USER, userHandle)
- putString(EXTRA_SOURCE, source)
- }
+ arguments =
+ Bundle().apply {
+ putLong(Constants.EXTRA_SESSION_ID, sessionId)
+ putParcelable(Intent.EXTRA_USER, userHandle)
+ putString(EXTRA_SOURCE, source)
+ }
}
}
}
@@ -95,21 +94,23 @@ class AutoReviewPermissionDecisionsFragment : AutoSettingsFrameFragment() {
}
user = requireArguments().getParcelable<UserHandle>(Intent.EXTRA_USER)!!
sessionId = requireArguments().getLong(Constants.EXTRA_SESSION_ID)
- if (requireArguments().containsKey(EXTRA_SOURCE) &&
- (requireArguments().getString(EXTRA_SOURCE) == EXTRA_SOURCE_NOTIFICATION)) {
+ if (
+ requireArguments().containsKey(EXTRA_SOURCE) &&
+ (requireArguments().getString(EXTRA_SOURCE) == EXTRA_SOURCE_NOTIFICATION)
+ ) {
logDecisionReminderNotificationClicked()
}
- val factory = ReviewPermissionDecisionsViewModelFactory(
- requireActivity().getApplication()!!, user)
- viewModel = ViewModelProvider(this,
- factory)[ReviewPermissionDecisionsViewModel::class.java]
+ val factory =
+ ReviewPermissionDecisionsViewModelFactory(requireActivity().getApplication()!!, user)
+ viewModel = ViewModelProvider(this, factory)[ReviewPermissionDecisionsViewModel::class.java]
addPrivacyDashboardPreference()
addPermissionManagerPreference()
preferenceScreen.addPreference(AutoDividerPreference(context))
- recentPermissionsGroup = PreferenceCategory(context!!).apply {
- title = getString(R.string.review_permission_decisions)
- }
+ recentPermissionsGroup =
+ PreferenceCategory(context!!).apply {
+ title = getString(R.string.review_permission_decisions)
+ }
preferenceScreen.addPreference(recentPermissionsGroup)
viewModel.recentPermissionDecisionsLiveData.observe(this) { recentDecisions ->
@@ -138,34 +139,43 @@ class AutoReviewPermissionDecisionsFragment : AutoSettingsFrameFragment() {
}
private fun addPrivacyDashboardPreference() {
- val preference = CarUiPreference(context).apply {
- title = getString(R.string.permission_usage_title)
- summary = getString(R.string.auto_permission_usage_summary)
- onPreferenceClickListener = Preference.OnPreferenceClickListener { _ ->
- val intent = Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE).apply {
- putExtra(Constants.EXTRA_SESSION_ID, sessionId)
- }
- startActivity(intent)
- true
+ val preference =
+ CarUiPreference(context).apply {
+ title = getString(R.string.permission_usage_title)
+ summary = getString(R.string.auto_permission_usage_summary)
+ onPreferenceClickListener =
+ Preference.OnPreferenceClickListener { _ ->
+ val intent =
+ Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE).apply {
+ putExtra(Constants.EXTRA_SESSION_ID, sessionId)
+ }
+ startActivity(intent)
+ true
+ }
}
- }
preferenceScreen.addPreference(preference)
}
private fun addPermissionManagerPreference() {
- val preference = CarUiPreference(context).apply {
- title = getString(R.string.app_permission_manager)
- summary = getString(R.string.auto_permission_manager_summary)
- onPreferenceClickListener = Preference.OnPreferenceClickListener { _ ->
- val intent = Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply {
- putExtra(Intent.EXTRA_USER, user)
- putExtra(ManagePermissionsActivity.EXTRA_CALLER_NAME, javaClass.name)
- putExtra(Constants.EXTRA_SESSION_ID, sessionId)
- }
- startActivity(intent)
- true
+ val preference =
+ CarUiPreference(context).apply {
+ title = getString(R.string.app_permission_manager)
+ summary = getString(R.string.auto_permission_manager_summary)
+ onPreferenceClickListener =
+ Preference.OnPreferenceClickListener { _ ->
+ val intent =
+ Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply {
+ putExtra(Intent.EXTRA_USER, user)
+ putExtra(
+ ManagePermissionsActivity.EXTRA_CALLER_NAME,
+ javaClass.name
+ )
+ putExtra(Constants.EXTRA_SESSION_ID, sessionId)
+ }
+ startActivity(intent)
+ true
+ }
}
- }
preferenceScreen.addPreference(preference)
}
@@ -175,46 +185,57 @@ class AutoReviewPermissionDecisionsFragment : AutoSettingsFrameFragment() {
) {
for (i in 0 until min(recentDecisions.size, MAX_DECISIONS)) {
val recentDecision = recentDecisions[i]
- val decisionPreference = CarUiPreference(context).apply {
- icon = viewModel.getAppIcon(recentDecision.packageName)
- title = viewModel.createPreferenceTitle(recentDecision)
- summary = viewModel.createSummaryText(recentDecision)
- onPreferenceClickListener = Preference.OnPreferenceClickListener {
- viewModel.createManageAppPermissionIntent(recentDecision).also {
- startActivity(it)
- }
- logPermissionDecisionClicked(recentDecision.packageName,
- recentDecision.permissionGroupName)
- true
+ val decisionPreference =
+ CarUiPreference(context).apply {
+ icon = viewModel.getAppIcon(recentDecision.packageName)
+ title = viewModel.createPreferenceTitle(recentDecision)
+ summary = viewModel.createSummaryText(recentDecision)
+ onPreferenceClickListener =
+ Preference.OnPreferenceClickListener {
+ viewModel.createManageAppPermissionIntent(recentDecision).also {
+ startActivity(it)
+ }
+ logPermissionDecisionClicked(
+ recentDecision.packageName,
+ recentDecision.permissionGroupName
+ )
+ true
+ }
}
- }
preferenceGroup.addPreference(decisionPreference)
}
}
private fun addViewAllPreference(preferenceGroup: PreferenceGroup) {
val viewAllIcon = requireContext().getDrawable(R.drawable.car_ic_apps)
- val preference = CarUiPreference(context).apply {
- icon = Utils.applyTint(context, viewAllIcon, android.R.attr.colorControlNormal)
- title = getString(R.string.review_permission_decisions_view_all)
- onPreferenceClickListener = Preference.OnPreferenceClickListener {
- val frag = AutoReviewPermissionDecisionsViewAllFragment.newInstance(sessionId,
- user)
- getParentFragmentManager().beginTransaction()
- .replace(android.R.id.content, frag)
- .addToBackStack(null)
- .commit()
- logViewAllClicked()
- true
+ val preference =
+ CarUiPreference(context).apply {
+ icon = Utils.applyTint(context, viewAllIcon, android.R.attr.colorControlNormal)
+ title = getString(R.string.review_permission_decisions_view_all)
+ onPreferenceClickListener =
+ Preference.OnPreferenceClickListener {
+ val frag =
+ AutoReviewPermissionDecisionsViewAllFragment.newInstance(
+ sessionId,
+ user
+ )
+ getParentFragmentManager()
+ .beginTransaction()
+ .replace(android.R.id.content, frag)
+ .addToBackStack(null)
+ .commit()
+ logViewAllClicked()
+ true
+ }
}
- }
preferenceGroup.addPreference(preference)
}
private fun addNoRecentDecisionsPreference(preferenceGroup: PreferenceGroup) {
- val preference = CarUiPreference(context).apply {
- title = getString(R.string.review_permission_decisions_empty)
- }
+ val preference =
+ CarUiPreference(context).apply {
+ title = getString(R.string.review_permission_decisions_empty)
+ }
preferenceGroup.addPreference(preference)
}
@@ -224,7 +245,8 @@ class AutoReviewPermissionDecisionsFragment : AutoSettingsFrameFragment() {
sessionId,
RECENT_PERMISSION_DECISIONS_INTERACTED__ACTION__SCREEN_VIEWED,
0,
- null)
+ null
+ )
}
private fun logViewAllClicked() {
@@ -233,7 +255,8 @@ class AutoReviewPermissionDecisionsFragment : AutoSettingsFrameFragment() {
sessionId,
RECENT_PERMISSION_DECISIONS_INTERACTED__ACTION__VIEW_ALL_CLICKED,
0,
- null)
+ null
+ )
}
private fun logPermissionDecisionClicked(packageName: String, permissionGroupName: String) {
@@ -243,12 +266,15 @@ class AutoReviewPermissionDecisionsFragment : AutoSettingsFrameFragment() {
sessionId,
RECENT_PERMISSION_DECISIONS_INTERACTED__ACTION__REVIEW_DECISION,
uid,
- permissionGroupName)
+ permissionGroupName
+ )
}
private fun logDecisionReminderNotificationClicked() {
PermissionControllerStatsLog.write(
PermissionControllerStatsLog.PERMISSION_REMINDER_NOTIFICATION_INTERACTED,
- sessionId, PERMISSION_REMINDER_NOTIFICATION_INTERACTED__RESULT__NOTIFICATION_CLICKED)
+ sessionId,
+ PERMISSION_REMINDER_NOTIFICATION_INTERACTED__RESULT__NOTIFICATION_CLICKED
+ )
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsViewAllFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsViewAllFragment.kt
index 9f9471fdf..11cca4693 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsViewAllFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsViewAllFragment.kt
@@ -39,18 +39,17 @@ class AutoReviewPermissionDecisionsViewAllFragment : AutoSettingsFrameFragment()
companion object {
private const val LOG_TAG = "AutoReviewPermissionDecisionsViewAllFragment"
- /**
- * Creates a new instance of [AutoReviewPermissionDecisionsViewAllFragment].
- */
+ /** Creates a new instance of [AutoReviewPermissionDecisionsViewAllFragment]. */
fun newInstance(
sessionId: Long,
userHandle: UserHandle
): AutoReviewPermissionDecisionsViewAllFragment {
return AutoReviewPermissionDecisionsViewAllFragment().apply {
- arguments = Bundle().apply {
- putLong(Constants.EXTRA_SESSION_ID, sessionId)
- putParcelable(Intent.EXTRA_USER, userHandle)
- }
+ arguments =
+ Bundle().apply {
+ putLong(Constants.EXTRA_SESSION_ID, sessionId)
+ putParcelable(Intent.EXTRA_USER, userHandle)
+ }
}
}
}
@@ -71,10 +70,9 @@ class AutoReviewPermissionDecisionsViewAllFragment : AutoSettingsFrameFragment()
return
}
user = requireArguments().getParcelable<UserHandle>(Intent.EXTRA_USER)!!
- val factory = ReviewPermissionDecisionsViewModelFactory(
- requireActivity().getApplication()!!, user)
- viewModel = ViewModelProvider(this,
- factory)[ReviewPermissionDecisionsViewModel::class.java]
+ val factory =
+ ReviewPermissionDecisionsViewModelFactory(requireActivity().getApplication()!!, user)
+ viewModel = ViewModelProvider(this, factory)[ReviewPermissionDecisionsViewModel::class.java]
viewModel.recentPermissionDecisionsLiveData.observe(this) { recentDecisions ->
onRecentDecisionsChanged(recentDecisions)
}
@@ -88,17 +86,19 @@ class AutoReviewPermissionDecisionsViewAllFragment : AutoSettingsFrameFragment()
private fun onRecentDecisionsChanged(recentDecisions: List<PermissionDecision>) {
preferenceScreen.removeAll()
for (recentDecision in recentDecisions) {
- val decisionPreference = CarUiPreference(context).apply {
- icon = viewModel.getAppIcon(recentDecision.packageName)
- title = viewModel.createPreferenceTitle(recentDecision)
- summary = viewModel.createSummaryText(recentDecision)
- onPreferenceClickListener = Preference.OnPreferenceClickListener {
- viewModel.createManageAppPermissionIntent(recentDecision).also {
- startActivity(it)
- }
- false
+ val decisionPreference =
+ CarUiPreference(context).apply {
+ icon = viewModel.getAppIcon(recentDecision.packageName)
+ title = viewModel.createPreferenceTitle(recentDecision)
+ summary = viewModel.createSummaryText(recentDecision)
+ onPreferenceClickListener =
+ Preference.OnPreferenceClickListener {
+ viewModel.createManageAppPermissionIntent(recentDecision).also {
+ startActivity(it)
+ }
+ false
+ }
}
- }
preferenceScreen.addPreference(decisionPreference)
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoUnusedAppsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoUnusedAppsFragment.kt
index 61f77c81a..d798291e0 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoUnusedAppsFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoUnusedAppsFragment.kt
@@ -30,16 +30,14 @@ import com.android.permissioncontroller.hibernation.isHibernationEnabled
import com.android.permissioncontroller.permission.ui.UnusedAppsFragment
import com.android.permissioncontroller.permission.ui.UnusedAppsFragment.Companion.INFO_MSG_CATEGORY
-/**
- * Auto wrapper, with customizations, around [UnusedAppsFragment].
- */
-class AutoUnusedAppsFragment : AutoSettingsFrameFragment(),
- UnusedAppsFragment.Parent<AutoUnusedAppsPreference> {
+/** Auto wrapper, with customizations, around [UnusedAppsFragment]. */
+class AutoUnusedAppsFragment :
+ AutoSettingsFrameFragment(), UnusedAppsFragment.Parent<AutoUnusedAppsPreference> {
companion object {
private const val UNUSED_PREFERENCE_KEY = "unused_pref_row_key"
- /** Create a new instance of this fragment. */
+ /** Create a new instance of this fragment. */
@JvmStatic
fun newInstance(): AutoUnusedAppsFragment {
return AutoUnusedAppsFragment()
@@ -53,15 +51,12 @@ class AutoUnusedAppsFragment : AutoSettingsFrameFragment(),
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (savedInstanceState == null) {
- val fragment:
- UnusedAppsFragment<AutoUnusedAppsFragment, AutoUnusedAppsPreference> =
+ val fragment: UnusedAppsFragment<AutoUnusedAppsFragment, AutoUnusedAppsPreference> =
UnusedAppsFragment.newInstance()
fragment.arguments = arguments
// child fragment does not have its own UI - it will add to the preferences of this
// parent fragment
- childFragmentManager.beginTransaction()
- .add(fragment, null)
- .commit()
+ childFragmentManager.beginTransaction().add(fragment, null).commit()
}
// initially focus on focus parking view and then shift focus to recyclerview once it has
@@ -76,10 +71,12 @@ class AutoUnusedAppsFragment : AutoSettingsFrameFragment(),
if (isHibernationEnabled()) {
preference.summary = getString(R.string.unused_apps_page_summary)
} else {
- preference.summary = """
+ preference.summary =
+ """
${getString(R.string.auto_revoked_apps_page_summary)}
${getString(R.string.auto_revoke_open_app_message)}
- """.trimIndent()
+ """
+ .trimIndent()
}
preference.setIcon(R.drawable.ic_info_outline)
preference.isSelectable = false
@@ -104,9 +101,9 @@ class AutoUnusedAppsFragment : AutoSettingsFrameFragment(),
override fun setEmptyState(empty: Boolean) {
val infoMsgCategory =
- preferenceScreen.findPreference<PreferenceCategory>(INFO_MSG_CATEGORY)!!
+ preferenceScreen.findPreference<PreferenceCategory>(INFO_MSG_CATEGORY)!!
val noUnusedAppsPreference: Preference? =
- infoMsgCategory.findPreference<Preference>(UNUSED_PREFERENCE_KEY)
+ infoMsgCategory.findPreference<Preference>(UNUSED_PREFERENCE_KEY)
if (empty && noUnusedAppsPreference == null) {
infoMsgCategory.addPreference(createNoUnusedAppsPreference())
} else if (noUnusedAppsPreference != null) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoUnusedAppsPreference.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoUnusedAppsPreference.kt
index 9835a90f4..f1b65b38f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoUnusedAppsPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoUnusedAppsPreference.kt
@@ -52,4 +52,4 @@ class AutoUnusedAppsPreference(
override fun setRemoveComponentEnabled(enabled: Boolean) {
setSecondaryActionEnabled(enabled)
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionHistoryPreference.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionHistoryPreference.kt
index 7ea400127..08460178c 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionHistoryPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionHistoryPreference.kt
@@ -23,8 +23,8 @@ import androidx.annotation.RequiresApi
import androidx.preference.Preference.OnPreferenceClickListener
import com.android.car.ui.preference.CarUiPreference
import com.android.permissioncontroller.R
-import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel
import com.android.permissioncontroller.permission.ui.legacy.PermissionUsageDetailsViewModelLegacy
+import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel
/** Preference that displays a permission usage for an app. */
@RequiresApi(Build.VERSION_CODES.S)
@@ -40,7 +40,8 @@ class AutoPermissionHistoryPreference(
context.getString(
R.string.auto_permission_usage_timeline_summary,
DateFormat.getTimeFormat(context).format(historyPreferenceData.accessEndTime),
- historyPreferenceData.summaryText)
+ historyPreferenceData.summaryText
+ )
} else {
DateFormat.getTimeFormat(context).format(historyPreferenceData.accessEndTime)
}
@@ -60,7 +61,9 @@ class AutoPermissionHistoryPreference(
accessEndTime = historyPreferenceData.accessEndTime,
accessStartTime = historyPreferenceData.accessStartTime,
showingAttribution = historyPreferenceData.showingAttribution,
- attributionTags = historyPreferenceData.attributionTags))
+ attributionTags = historyPreferenceData.attributionTags
+ )
+ )
true
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageFragment.kt
index d4a2a073e..c11129514 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageFragment.kt
@@ -38,11 +38,11 @@ import com.android.permissioncontroller.permission.model.livedatatypes.PermGroup
import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage
import com.android.permissioncontroller.permission.model.v31.PermissionUsages
import com.android.permissioncontroller.permission.model.v31.PermissionUsages.PermissionsUsagesChangeCallback
-import com.android.permissioncontroller.permission.ui.model.ManagePermissionsViewModel
-import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageControlPreferenceUtils
import com.android.permissioncontroller.permission.ui.legacy.PermissionUsageViewModelFactoryLegacy
import com.android.permissioncontroller.permission.ui.legacy.PermissionUsageViewModelLegacy
import com.android.permissioncontroller.permission.ui.legacy.PermissionUsageViewModelLegacy.PermissionGroupWithUsageCount
+import com.android.permissioncontroller.permission.ui.model.ManagePermissionsViewModel
+import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageControlPreferenceUtils
import com.android.permissioncontroller.permission.utils.Utils
@RequiresApi(Build.VERSION_CODES.S)
@@ -95,7 +95,9 @@ class AutoPermissionUsageFragment : AutoSettingsFrameFragment(), PermissionsUsag
PermissionUsageViewModelLegacy::class.java]
managePermissionsViewModel.standardPermGroupsLiveData.observe(
- this, this::onPermissionGroupsChanged)
+ this,
+ this::onPermissionGroupsChanged
+ )
setLoading(true)
reloadData()
}
@@ -119,7 +121,8 @@ class AutoPermissionUsageFragment : AutoSettingsFrameFragment(), PermissionsUsag
PermissionControllerStatsLog.write(
PERMISSION_USAGE_FRAGMENT_INTERACTION,
sessionId,
- PERMISSION_USAGE_FRAGMENT_INTERACTION__ACTION__SHOW_SYSTEM_CLICKED)
+ PERMISSION_USAGE_FRAGMENT_INTERACTION__ACTION__SHOW_SYSTEM_CLICKED
+ )
}
showSystem = !showSystem
updateAction()
@@ -143,7 +146,10 @@ class AutoPermissionUsageFragment : AutoSettingsFrameFragment(), PermissionsUsag
/** Reloads the data to show. */
private fun reloadData() {
usageViewModel.loadPermissionUsages(
- requireActivity().getLoaderManager(), permissionUsages, this)
+ requireActivity().getLoaderManager(),
+ permissionUsages,
+ this
+ )
if (finishedInitialLoad) {
setLoading(false)
}
@@ -165,7 +171,11 @@ class AutoPermissionUsageFragment : AutoSettingsFrameFragment(), PermissionsUsag
val permissionUsagesUiData =
usageViewModel.buildPermissionUsagesUiData(
- appPermissionUsages, show7Days, showSystem, requireContext())
+ appPermissionUsages,
+ show7Days,
+ showSystem,
+ requireContext()
+ )
val permissionApps = permissionUsagesUiData.permissionApps
val displayShowSystemToggle = permissionUsagesUiData.displayShowSystemToggle
@@ -213,7 +223,8 @@ class AutoPermissionUsageFragment : AutoSettingsFrameFragment(), PermissionsUsag
count,
showSystem,
sessionId,
- show7Days)
+ show7Days
+ )
getPreferenceScreen().addPreference(permissionUsagePreference)
}
finishedInitialLoad = true
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java
index cab0de15e..7fa51dd8a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java
@@ -103,6 +103,7 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
implements AppPermissionViewModel.ConfirmDialogShowingFragment {
private static final String LOG_TAG = "AppPermissionFragment";
private static final long POST_DELAY_MS = 20;
+ private static final long EDIT_PHOTOS_BUTTON_ANIMATION_LENGTH_MS = 200L;
static final String GRANT_CATEGORY = "grant_category";
@@ -117,6 +118,9 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
private @NonNull RadioButton mSelectPhotosButton;
private @NonNull RadioButton mDenyButton;
private @NonNull RadioButton mDenyForegroundButton;
+ private @NonNull ImageView mEditPhotosButton;
+ private @NonNull View mSelectPhotosLayout;
+ private @NonNull View mEditPhotosDivider;
private @NonNull View mLocationAccuracy;
private @NonNull Switch mLocationAccuracySwitch;
private @NonNull View mDivider;
@@ -128,6 +132,8 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
private @NonNull UserHandle mUser;
private boolean mIsStorageGroup;
private boolean mIsInitialLoad;
+ // This prevents the user from clicking the photo picker button multiple times in succession
+ private boolean mPhotoPickerTriggered;
private long mSessionId;
private @NonNull String mPackageLabel;
@@ -209,7 +215,6 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
if (mIsStorageGroup) {
mViewModel.getFullStorageStateLiveData().observe(this, this::setSpecialStorageState);
}
- mViewModel.registerPhotoPickerResultIfNeeded(this);
mRoleManager = Utils.getSystemServiceSafe(getContext(), RoleManager.class);
}
@@ -261,12 +266,15 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
mSelectPhotosButton = root.requireViewById(R.id.select_radio_button);
mDenyButton = root.requireViewById(R.id.deny_radio_button);
mDenyForegroundButton = root.requireViewById(R.id.deny_foreground_radio_button);
+
mDivider = root.requireViewById(R.id.two_target_divider);
mWidgetFrame = root.requireViewById(R.id.widget_frame);
mPermissionDetails = root.requireViewById(R.id.permission_details);
mLocationAccuracy = root.requireViewById(R.id.location_accuracy);
mLocationAccuracySwitch = root.requireViewById(R.id.location_accuracy_switch);
-
+ mSelectPhotosLayout = root.requireViewById(R.id.radio_select_layout);
+ mEditPhotosButton = root.requireViewById(R.id.edit_selected_button);
+ mEditPhotosDivider = root.requireViewById(R.id.edit_photos_divider);
mNestedScrollView = root.requireViewById(R.id.nested_scroll_view);
if (mViewModel.getButtonStateLiveData().getValue() != null) {
@@ -280,6 +288,9 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
mDenyButton.setVisibility(View.GONE);
mDenyForegroundButton.setVisibility(View.GONE);
mLocationAccuracy.setVisibility(View.GONE);
+ mSelectPhotosLayout.setVisibility(View.GONE);
+ mEditPhotosDivider.setAlpha(0f);
+ mEditPhotosButton.setAlpha(0f);
}
if (mViewModel.getFullStorageStateLiveData().isInitialized() && mIsStorageGroup) {
@@ -302,6 +313,12 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
return root;
}
+ public void onResume() {
+ super.onResume();
+ // If we're returning to the fragment, photo picker hasn't been triggered
+ mPhotoPickerTriggered = false;
+ }
+
private void showPermissionRationaleDialog(boolean showPermissionRationale) {
if (!showPermissionRationale) {
mAppPermissionRationaleContainer.setVisibility(View.GONE);
@@ -380,7 +397,7 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
});
mAllowAlwaysButton.setOnClickListener((v) -> {
if (mIsStorageGroup) {
- showConfirmDialog(ChangeRequest.GRANT_All_FILE_ACCESS,
+ showConfirmDialog(ChangeRequest.GRANT_ALL_FILE_ACCESS,
R.string.special_file_access_dialog, -1, false);
} else {
mViewModel.requestChange(false, this, this, ChangeRequest.GRANT_BOTH,
@@ -412,6 +429,13 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
mViewModel.requestChange(false, this, this, ChangeRequest.PHOTOS_SELECTED,
buttonPressed);
});
+ mEditPhotosButton.setOnClickListener((v) -> {
+ ButtonState selectState = states.get(ButtonType.SELECT_PHOTOS);
+ if (selectState != null && selectState.isChecked() && !mPhotoPickerTriggered) {
+ mPhotoPickerTriggered = true;
+ mViewModel.openPhotoPicker(this);
+ }
+ });
mDenyButton.setOnClickListener((v) -> {
if (mViewModel.getFullStorageStateLiveData().getValue() != null
&& !mViewModel.getFullStorageStateLiveData().getValue().isLegacy()) {
@@ -485,6 +509,21 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
if (mIsInitialLoad) {
button.jumpDrawablesToCurrentState();
}
+
+ if (button == mSelectPhotosButton) {
+ mSelectPhotosLayout.setVisibility(visible);
+ float endOpacity = state.isChecked() ? 1f : 0f;
+ // On initial load, do not show the fade in/out animation
+ if (mIsInitialLoad) {
+ mEditPhotosDivider.setAlpha(endOpacity);
+ mEditPhotosButton.setAlpha(endOpacity);
+ return;
+ }
+ mEditPhotosButton.animate().alpha(endOpacity)
+ .setDuration(EDIT_PHOTOS_BUTTON_ANIMATION_LENGTH_MS);
+ mEditPhotosDivider.animate().alpha(endOpacity)
+ .setDuration(EDIT_PHOTOS_BUTTON_ANIMATION_LENGTH_MS);
+ }
}
private void setSpecialStorageState(FullStoragePackageState storageState, View v) {
@@ -630,7 +669,7 @@ public class AppPermissionFragment extends SettingsWithLargeHeader
// NFF sharing
AppPermissionFragment fragment = (AppPermissionFragment) getParentFragment();
boolean isGrantFileAccess = getArguments().getSerializable(CHANGE_REQUEST)
- == ChangeRequest.GRANT_All_FILE_ACCESS;
+ == ChangeRequest.GRANT_ALL_FILE_ACCESS;
int positiveButtonStringResId = R.string.grant_dialog_button_deny_anyway;
if (isGrantFileAccess) {
positiveButtonStringResId = R.string.grant_dialog_button_allow;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
index a8b79bfde..5b24b52ec 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
@@ -23,6 +23,7 @@ import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_
import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSIONS_FRAGMENT_VIEWED__CATEGORY__ALLOWED_FOREGROUND;
import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSIONS_FRAGMENT_VIEWED__CATEGORY__DENIED;
import static com.android.permissioncontroller.hibernation.HibernationPolicyKt.isHibernationEnabled;
+import static com.android.permissioncontroller.permission.ui.Category.STORAGE_FOOTER;
import static com.android.permissioncontroller.permission.ui.handheld.UtilsKt.pressBack;
import static java.util.concurrent.TimeUnit.DAYS;
@@ -318,6 +319,9 @@ public final class AppPermissionGroupsFragment extends SettingsWithLargeHeader i
findPreference(Category.ALLOWED_FOREGROUND.getCategoryName()).setVisible(false);
+ // Hide storage footer category
+ findPreference(STORAGE_FOOTER.getCategoryName()).setVisible(false);
+
long sessionId = getArguments().getLong(EXTRA_SESSION_ID, INVALID_SESSION_ID);
for (Category grantCategory : groupMap.keySet()) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/FooterPreference.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/FooterPreference.kt
index 7864abbb2..278243f09 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/FooterPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/FooterPreference.kt
@@ -28,10 +28,10 @@ import com.android.permissioncontroller.R
* placement.
*/
class FooterPreference : Preference {
- constructor(c: Context): super(c)
- constructor(c: Context, a: AttributeSet): super(c, a)
- constructor(c: Context, a: AttributeSet, attr: Int): super(c, a, attr)
- constructor(c: Context, a: AttributeSet, attr: Int, res: Int): super(c, a, attr, res)
+ constructor(c: Context) : super(c)
+ constructor(c: Context, a: AttributeSet) : super(c, a)
+ constructor(c: Context, a: AttributeSet, attr: Int) : super(c, a, attr)
+ constructor(c: Context, a: AttributeSet, attr: Int, res: Int) : super(c, a, attr, res)
init {
layoutResource = R.layout.footer_preference
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt
index decbfe590..394c2d113 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt
@@ -83,10 +83,14 @@ class GrantPermissionsViewHandlerImpl(
private val resultListener: ResultListener
) : GrantPermissionsViewHandler, OnClickListener {
- private val LOCATION_ACCURACY_DIALOGS = listOf(DIALOG_WITH_BOTH_LOCATIONS,
- DIALOG_WITH_FINE_LOCATION_ONLY, DIALOG_WITH_COARSE_LOCATION_ONLY)
- private val LOCATION_ACCURACY_IMAGE_DIAMETER = mActivity.resources.getDimension(
- R.dimen.location_accuracy_image_size)
+ private val LOCATION_ACCURACY_DIALOGS =
+ listOf(
+ DIALOG_WITH_BOTH_LOCATIONS,
+ DIALOG_WITH_FINE_LOCATION_ONLY,
+ DIALOG_WITH_COARSE_LOCATION_ONLY
+ )
+ private val LOCATION_ACCURACY_IMAGE_DIAMETER =
+ mActivity.resources.getDimension(R.dimen.location_accuracy_image_size)
// Configuration of the current dialog
private var groupName: String? = null
@@ -124,8 +128,10 @@ class GrantPermissionsViewHandlerImpl(
arguments.putParcelable(ARG_GROUP_ICON, groupIcon)
arguments.putCharSequence(ARG_GROUP_MESSAGE, groupMessage)
arguments.putCharSequence(ARG_GROUP_DETAIL_MESSAGE, detailMessage)
- arguments.putCharSequence(ARG_GROUP_PERMISSION_RATIONALE_MESSAGE,
- permissionRationaleMessage)
+ arguments.putCharSequence(
+ ARG_GROUP_PERMISSION_RATIONALE_MESSAGE,
+ permissionRationaleMessage
+ )
arguments.putBooleanArray(ARG_DIALOG_BUTTON_VISIBILITIES, buttonVisibilities)
arguments.putBooleanArray(ARG_DIALOG_LOCATION_VISIBILITIES, locationVisibilities)
arguments.putInt(ARG_DIALOG_SELECTED_PRECISION, selectedPrecision)
@@ -141,8 +147,9 @@ class GrantPermissionsViewHandlerImpl(
permissionRationaleMessage =
savedInstanceState.getCharSequence(ARG_GROUP_PERMISSION_RATIONALE_MESSAGE)
setButtonVisibilities(savedInstanceState.getBooleanArray(ARG_DIALOG_BUTTON_VISIBILITIES))
- setLocationVisibilities(savedInstanceState.getBooleanArray(
- ARG_DIALOG_LOCATION_VISIBILITIES))
+ setLocationVisibilities(
+ savedInstanceState.getBooleanArray(ARG_DIALOG_LOCATION_VISIBILITIES)
+ )
selectedPrecision = savedInstanceState.getInt(ARG_DIALOG_SELECTED_PRECISION)
updateAll()
@@ -187,21 +194,22 @@ class GrantPermissionsViewHandlerImpl(
// Grow or shrink the content container to size of new content
val growShrinkToNewContentSize = ChangeBounds()
growShrinkToNewContentSize.duration = ANIMATION_DURATION_MILLIS
- growShrinkToNewContentSize.interpolator = AnimationUtils.loadInterpolator(mActivity,
- android.R.interpolator.fast_out_slow_in)
+ growShrinkToNewContentSize.interpolator =
+ AnimationUtils.loadInterpolator(mActivity, android.R.interpolator.fast_out_slow_in)
TransitionManager.beginDelayedTransition(rootView, growShrinkToNewContentSize)
}
override fun createView(): View {
- val useMaterial3PermissionGrantDialog = mActivity.resources
- .getBoolean(R.bool.config_useMaterial3PermissionGrantDialog)
- val rootView = if (useMaterial3PermissionGrantDialog || SdkLevel.isAtLeastT()) {
- LayoutInflater.from(mActivity)
- .inflate(R.layout.grant_permissions_material3, null) as ViewGroup
- } else {
- LayoutInflater.from(mActivity)
- .inflate(R.layout.grant_permissions, null) as ViewGroup
- }
+ val useMaterial3PermissionGrantDialog =
+ mActivity.resources.getBoolean(R.bool.config_useMaterial3PermissionGrantDialog)
+ val rootView =
+ if (useMaterial3PermissionGrantDialog || SdkLevel.isAtLeastT()) {
+ LayoutInflater.from(mActivity).inflate(R.layout.grant_permissions_material3, null)
+ as ViewGroup
+ } else {
+ LayoutInflater.from(mActivity).inflate(R.layout.grant_permissions, null)
+ as ViewGroup
+ }
this.rootView = rootView
// Uses the vertical gravity of the PermissionGrantSingleton style to position the window
@@ -257,14 +265,15 @@ class GrantPermissionsViewHandlerImpl(
private fun getLottieDrawable(@RawRes rawResId: Int): LottieDrawable {
val composition = LottieCompositionFactory.fromRawResSync(mActivity, rawResId).value!!
val scale = LOCATION_ACCURACY_IMAGE_DIAMETER / composition.bounds.width()
- val drawable = object : LottieDrawable() {
- override fun getIntrinsicHeight(): Int {
- return (super.getIntrinsicHeight() * scale).toInt()
- }
- override fun getIntrinsicWidth(): Int {
- return (super.getIntrinsicWidth() * scale).toInt()
+ val drawable =
+ object : LottieDrawable() {
+ override fun getIntrinsicHeight(): Int {
+ return (super.getIntrinsicHeight() * scale).toInt()
+ }
+ override fun getIntrinsicWidth(): Int {
+ return (super.getIntrinsicWidth() * scale).toInt()
+ }
}
- }
drawable.composition = composition
return drawable
}
@@ -282,21 +291,23 @@ class GrantPermissionsViewHandlerImpl(
private fun setButtonVisibilities(visibilities: BooleanArray?) {
for (i in buttonVisibilities.indices) {
- buttonVisibilities[i] = if (visibilities != null && i < visibilities.size) {
- visibilities[i]
- } else {
- false
- }
+ buttonVisibilities[i] =
+ if (visibilities != null && i < visibilities.size) {
+ visibilities[i]
+ } else {
+ false
+ }
}
}
private fun setLocationVisibilities(visibilities: BooleanArray?) {
for (i in locationVisibilities.indices) {
- locationVisibilities[i] = if (visibilities != null && i < visibilities.size) {
- visibilities[i]
- } else {
- false
- }
+ locationVisibilities[i] =
+ if (visibilities != null && i < visibilities.size) {
+ visibilities[i]
+ } else {
+ false
+ }
}
}
@@ -329,29 +340,38 @@ class GrantPermissionsViewHandlerImpl(
private fun updateButtons() {
for (i in 0 until BUTTON_RES_ID_TO_NUM.size()) {
val pos = BUTTON_RES_ID_TO_NUM.valueAt(i)
- buttons[pos]?.visibility = if (buttonVisibilities[pos]) {
- View.VISIBLE
- } else {
- View.GONE
- }
+ buttons[pos]?.visibility =
+ if (buttonVisibilities[pos]) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
if (pos == ALLOW_FOREGROUND_BUTTON && buttonVisibilities[pos]) {
- if (locationVisibilities[LOCATION_ACCURACY_LAYOUT] &&
- locationVisibilities[DIALOG_WITH_FINE_LOCATION_ONLY]) {
- buttons[pos]?.text = mActivity.resources.getString(
- R.string.grant_dialog_button_change_to_precise_location)
+ if (
+ locationVisibilities[LOCATION_ACCURACY_LAYOUT] &&
+ locationVisibilities[DIALOG_WITH_FINE_LOCATION_ONLY]
+ ) {
+ buttons[pos]?.text =
+ mActivity.resources.getString(
+ R.string.grant_dialog_button_change_to_precise_location
+ )
} else {
- buttons[pos]?.text = mActivity.resources.getString(
- R.string.grant_dialog_button_allow_foreground)
+ buttons[pos]?.text =
+ mActivity.resources.getString(R.string.grant_dialog_button_allow_foreground)
}
}
if ((pos == DENY_BUTTON || pos == DENY_AND_DONT_ASK_AGAIN_BUTTON)) {
- if (locationVisibilities[LOCATION_ACCURACY_LAYOUT] &&
- locationVisibilities[DIALOG_WITH_FINE_LOCATION_ONLY]) {
- buttons[pos]?.text = mActivity.resources.getString(
- R.string.grant_dialog_button_keey_approximate_location)
+ if (
+ locationVisibilities[LOCATION_ACCURACY_LAYOUT] &&
+ locationVisibilities[DIALOG_WITH_FINE_LOCATION_ONLY]
+ ) {
+ buttons[pos]?.text =
+ mActivity.resources.getString(
+ R.string.grant_dialog_button_keey_approximate_location
+ )
} else {
- buttons[pos]?.text = mActivity.resources.getString(
- R.string.grant_dialog_button_deny)
+ buttons[pos]?.text =
+ mActivity.resources.getString(R.string.grant_dialog_button_deny)
}
}
buttons[pos]?.requestLayout()
@@ -365,11 +385,12 @@ class GrantPermissionsViewHandlerImpl(
}
locationViews[LOCATION_ACCURACY_LAYOUT]?.visibility = View.VISIBLE
for (i in LOCATION_ACCURACY_DIALOGS) {
- locationViews[i]?.visibility = if (locationVisibilities[i]) {
- View.VISIBLE
- } else {
- View.GONE
- }
+ locationViews[i]?.visibility =
+ if (locationVisibilities[i]) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
}
if (locationVisibilities[DIALOG_WITH_BOTH_LOCATIONS]) {
coarseRadioButton?.visibility = View.VISIBLE
@@ -388,11 +409,13 @@ class GrantPermissionsViewHandlerImpl(
}
} else if (locationVisibilities[DIALOG_WITH_COARSE_LOCATION_ONLY]) {
(locationViews[DIALOG_WITH_COARSE_LOCATION_ONLY] as ImageView).setImageDrawable(
- coarseOnDrawable)
+ coarseOnDrawable
+ )
coarseOnDrawable?.start()
} else if (locationVisibilities[DIALOG_WITH_FINE_LOCATION_ONLY]) {
(locationViews[DIALOG_WITH_FINE_LOCATION_ONLY] as ImageView).setImageDrawable(
- fineOnDrawable)
+ fineOnDrawable
+ )
fineOnDrawable?.start()
}
} else {
@@ -408,10 +431,18 @@ class GrantPermissionsViewHandlerImpl(
if (isFineSelected) {
coarseOnDrawable?.stop()
fineOffDrawable?.stop()
- coarseRadioButton?.setCompoundDrawablesWithIntrinsicBounds(null, coarseOffDrawable,
- null, null)
- fineRadioButton?.setCompoundDrawablesWithIntrinsicBounds(null, fineOnDrawable,
- null, null)
+ coarseRadioButton?.setCompoundDrawablesWithIntrinsicBounds(
+ null,
+ coarseOffDrawable,
+ null,
+ null
+ )
+ fineRadioButton?.setCompoundDrawablesWithIntrinsicBounds(
+ null,
+ fineOnDrawable,
+ null,
+ null
+ )
coarseOffDrawable?.start()
fineOnDrawable?.start()
fineRadioButton?.setTypeface(null, Typeface.BOLD)
@@ -419,10 +450,18 @@ class GrantPermissionsViewHandlerImpl(
} else {
coarseOffDrawable?.stop()
fineOnDrawable?.stop()
- coarseRadioButton?.setCompoundDrawablesWithIntrinsicBounds(null, coarseOnDrawable,
- null, null)
- fineRadioButton?.setCompoundDrawablesWithIntrinsicBounds(null, fineOffDrawable,
- null, null)
+ coarseRadioButton?.setCompoundDrawablesWithIntrinsicBounds(
+ null,
+ coarseOnDrawable,
+ null,
+ null
+ )
+ fineRadioButton?.setCompoundDrawablesWithIntrinsicBounds(
+ null,
+ fineOffDrawable,
+ null,
+ null
+ )
fineOffDrawable?.start()
coarseOnDrawable?.start()
coarseRadioButton?.setTypeface(null, Typeface.BOLD)
@@ -471,8 +510,8 @@ class GrantPermissionsViewHandlerImpl(
R.id.permission_location_accuracy_radio_coarse ->
affectedForegroundPermissions = listOf(ACCESS_COARSE_LOCATION)
R.id.permission_location_accuracy_radio_fine ->
- affectedForegroundPermissions = listOf(ACCESS_FINE_LOCATION,
- ACCESS_COARSE_LOCATION)
+ affectedForegroundPermissions =
+ listOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION)
}
} else if (locationVisibilities[DIALOG_WITH_FINE_LOCATION_ONLY]) {
affectedForegroundPermissions = listOf(ACCESS_FINE_LOCATION)
@@ -481,52 +520,94 @@ class GrantPermissionsViewHandlerImpl(
}
when (BUTTON_RES_ID_TO_NUM.get(id, -1)) {
- ALLOW_ALL_BUTTON, ALLOW_BUTTON -> {
+ ALLOW_ALL_BUTTON,
+ ALLOW_BUTTON -> {
view.performAccessibilityAction(
- AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null)
- resultListener.onPermissionGrantResult(groupName, affectedForegroundPermissions,
- GRANTED_ALWAYS)
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS,
+ null
+ )
+ resultListener.onPermissionGrantResult(
+ groupName,
+ affectedForegroundPermissions,
+ GRANTED_ALWAYS
+ )
}
ALLOW_FOREGROUND_BUTTON -> {
view.performAccessibilityAction(
- AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null)
- resultListener.onPermissionGrantResult(groupName, affectedForegroundPermissions,
- GRANTED_FOREGROUND_ONLY)
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS,
+ null
+ )
+ resultListener.onPermissionGrantResult(
+ groupName,
+ affectedForegroundPermissions,
+ GRANTED_FOREGROUND_ONLY
+ )
}
ALLOW_ALWAYS_BUTTON -> {
view.performAccessibilityAction(
- AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null)
- resultListener.onPermissionGrantResult(groupName, affectedForegroundPermissions,
- GRANTED_ALWAYS)
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS,
+ null
+ )
+ resultListener.onPermissionGrantResult(
+ groupName,
+ affectedForegroundPermissions,
+ GRANTED_ALWAYS
+ )
}
ALLOW_ONE_TIME_BUTTON -> {
view.performAccessibilityAction(
- AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null)
- resultListener.onPermissionGrantResult(groupName, affectedForegroundPermissions,
- GRANTED_ONE_TIME)
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS,
+ null
+ )
+ resultListener.onPermissionGrantResult(
+ groupName,
+ affectedForegroundPermissions,
+ GRANTED_ONE_TIME
+ )
}
ALLOW_SELECTED_BUTTON -> {
view.performAccessibilityAction(
- AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null)
- resultListener.onPermissionGrantResult(groupName, affectedForegroundPermissions,
- GRANTED_USER_SELECTED)
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS,
+ null
+ )
+ resultListener.onPermissionGrantResult(
+ groupName,
+ affectedForegroundPermissions,
+ GRANTED_USER_SELECTED
+ )
}
DONT_ALLOW_MORE_SELECTED_BUTTON -> {
- resultListener.onPermissionGrantResult(groupName, affectedForegroundPermissions,
- DENIED_MORE)
+ resultListener.onPermissionGrantResult(
+ groupName,
+ affectedForegroundPermissions,
+ DENIED_MORE
+ )
}
- DENY_BUTTON, NO_UPGRADE_BUTTON, NO_UPGRADE_OT_BUTTON -> {
+ DENY_BUTTON,
+ NO_UPGRADE_BUTTON,
+ NO_UPGRADE_OT_BUTTON -> {
view.performAccessibilityAction(
- AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null)
- resultListener.onPermissionGrantResult(groupName, affectedForegroundPermissions,
- DENIED)
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS,
+ null
+ )
+ resultListener.onPermissionGrantResult(
+ groupName,
+ affectedForegroundPermissions,
+ DENIED
+ )
}
- DENY_AND_DONT_ASK_AGAIN_BUTTON, NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON,
+ DENY_AND_DONT_ASK_AGAIN_BUTTON,
+ NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON,
NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON -> {
view.performAccessibilityAction(
- AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null)
- resultListener.onPermissionGrantResult(groupName, affectedForegroundPermissions,
- DENIED_DO_NOT_ASK_AGAIN)
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS,
+ null
+ )
+ resultListener.onPermissionGrantResult(
+ groupName,
+ affectedForegroundPermissions,
+ DENIED_DO_NOT_ASK_AGAIN
+ )
}
}
}
@@ -567,39 +648,57 @@ class GrantPermissionsViewHandlerImpl(
init {
BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_button, ALLOW_BUTTON)
- BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_foreground_only_button,
- ALLOW_FOREGROUND_BUTTON)
+ BUTTON_RES_ID_TO_NUM.put(
+ R.id.permission_allow_foreground_only_button,
+ ALLOW_FOREGROUND_BUTTON
+ )
BUTTON_RES_ID_TO_NUM.put(R.id.permission_deny_button, DENY_BUTTON)
- BUTTON_RES_ID_TO_NUM.put(R.id.permission_deny_and_dont_ask_again_button,
- DENY_AND_DONT_ASK_AGAIN_BUTTON)
- BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_one_time_button,
- ALLOW_ONE_TIME_BUTTON)
- BUTTON_RES_ID_TO_NUM.put(R.id.permission_no_upgrade_button,
- NO_UPGRADE_BUTTON)
- BUTTON_RES_ID_TO_NUM.put(R.id.permission_no_upgrade_and_dont_ask_again_button,
- NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON)
- BUTTON_RES_ID_TO_NUM.put(R.id.permission_no_upgrade_one_time_button,
- NO_UPGRADE_OT_BUTTON)
- BUTTON_RES_ID_TO_NUM.put(R.id.permission_no_upgrade_one_time_and_dont_ask_again_button,
- NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON)
- BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_all_button,
- ALLOW_ALL_BUTTON)
- BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_selected_button,
- ALLOW_SELECTED_BUTTON)
- BUTTON_RES_ID_TO_NUM.put(R.id.permission_dont_allow_more_selected_button,
- DONT_ALLOW_MORE_SELECTED_BUTTON)
+ BUTTON_RES_ID_TO_NUM.put(
+ R.id.permission_deny_and_dont_ask_again_button,
+ DENY_AND_DONT_ASK_AGAIN_BUTTON
+ )
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_one_time_button, ALLOW_ONE_TIME_BUTTON)
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_no_upgrade_button, NO_UPGRADE_BUTTON)
+ BUTTON_RES_ID_TO_NUM.put(
+ R.id.permission_no_upgrade_and_dont_ask_again_button,
+ NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON
+ )
+ BUTTON_RES_ID_TO_NUM.put(
+ R.id.permission_no_upgrade_one_time_button,
+ NO_UPGRADE_OT_BUTTON
+ )
+ BUTTON_RES_ID_TO_NUM.put(
+ R.id.permission_no_upgrade_one_time_and_dont_ask_again_button,
+ NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON
+ )
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_all_button, ALLOW_ALL_BUTTON)
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_selected_button, ALLOW_SELECTED_BUTTON)
+ BUTTON_RES_ID_TO_NUM.put(
+ R.id.permission_dont_allow_more_selected_button,
+ DONT_ALLOW_MORE_SELECTED_BUTTON
+ )
LOCATION_RES_ID_TO_NUM.put(R.id.permission_location_accuracy, LOCATION_ACCURACY_LAYOUT)
- LOCATION_RES_ID_TO_NUM.put(R.id.permission_location_accuracy_radio_fine,
- FINE_RADIO_BUTTON)
- LOCATION_RES_ID_TO_NUM.put(R.id.permission_location_accuracy_radio_coarse,
- COARSE_RADIO_BUTTON)
- LOCATION_RES_ID_TO_NUM.put(R.id.permission_location_accuracy_radio_group,
- DIALOG_WITH_BOTH_LOCATIONS)
- LOCATION_RES_ID_TO_NUM.put(R.id.permission_location_accuracy_fine_only,
- DIALOG_WITH_FINE_LOCATION_ONLY)
- LOCATION_RES_ID_TO_NUM.put(R.id.permission_location_accuracy_coarse_only,
- DIALOG_WITH_COARSE_LOCATION_ONLY)
+ LOCATION_RES_ID_TO_NUM.put(
+ R.id.permission_location_accuracy_radio_fine,
+ FINE_RADIO_BUTTON
+ )
+ LOCATION_RES_ID_TO_NUM.put(
+ R.id.permission_location_accuracy_radio_coarse,
+ COARSE_RADIO_BUTTON
+ )
+ LOCATION_RES_ID_TO_NUM.put(
+ R.id.permission_location_accuracy_radio_group,
+ DIALOG_WITH_BOTH_LOCATIONS
+ )
+ LOCATION_RES_ID_TO_NUM.put(
+ R.id.permission_location_accuracy_fine_only,
+ DIALOG_WITH_FINE_LOCATION_ONLY
+ )
+ LOCATION_RES_ID_TO_NUM.put(
+ R.id.permission_location_accuracy_coarse_only,
+ DIALOG_WITH_COARSE_LOCATION_ONLY
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/HandheldUnusedAppsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/HandheldUnusedAppsFragment.kt
index e2fdfc86e..37ac50bb8 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/HandheldUnusedAppsFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/HandheldUnusedAppsFragment.kt
@@ -28,14 +28,12 @@ import com.android.permissioncontroller.hibernation.isHibernationEnabled
import com.android.permissioncontroller.permission.ui.UnusedAppsFragment
import com.android.permissioncontroller.permission.ui.UnusedAppsFragment.Companion.INFO_MSG_CATEGORY
-/**
- * Handheld wrapper, with customizations, around [UnusedAppsFragment].
- */
-class HandheldUnusedAppsFragment : PermissionsFrameFragment(),
- UnusedAppsFragment.Parent<UnusedAppPreference> {
+/** Handheld wrapper, with customizations, around [UnusedAppsFragment]. */
+class HandheldUnusedAppsFragment :
+ PermissionsFrameFragment(), UnusedAppsFragment.Parent<UnusedAppPreference> {
companion object {
- /** Create a new instance of this fragment. */
+ /** Create a new instance of this fragment. */
@JvmStatic
fun newInstance(): HandheldUnusedAppsFragment {
return HandheldUnusedAppsFragment()
@@ -55,15 +53,12 @@ class HandheldUnusedAppsFragment : PermissionsFrameFragment(),
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (savedInstanceState == null) {
- val fragment:
- UnusedAppsFragment<HandheldUnusedAppsFragment, UnusedAppPreference> =
+ val fragment: UnusedAppsFragment<HandheldUnusedAppsFragment, UnusedAppPreference> =
UnusedAppsFragment.newInstance()
fragment.arguments = arguments
// child fragment does not have its own UI - it will add to the preferences of this
// parent fragment
- childFragmentManager.beginTransaction()
- .add(fragment, null)
- .commit()
+ childFragmentManager.beginTransaction().add(fragment, null).commit()
}
}
@@ -113,7 +108,7 @@ class HandheldUnusedAppsFragment : PermissionsFrameFragment(),
override fun setEmptyState(empty: Boolean) {
val infoMsgCategory =
- preferenceScreen.findPreference<PreferenceCategory>(INFO_MSG_CATEGORY)!!
+ preferenceScreen.findPreference<PreferenceCategory>(INFO_MSG_CATEGORY)!!
infoMsgCategory.isVisible = !empty
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/HandheldUnusedAppsWrapperFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/HandheldUnusedAppsWrapperFragment.kt
index 44a9f3d08..7565e6d17 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/HandheldUnusedAppsWrapperFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/HandheldUnusedAppsWrapperFragment.kt
@@ -24,12 +24,10 @@ import android.view.ViewGroup
import com.android.permissioncontroller.R
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseFragment
-/**
- * Wrapper over HandheldUnusedAppsFragment
- */
+/** Wrapper over HandheldUnusedAppsFragment */
class HandheldUnusedAppsWrapperFragment : CollapsingToolbarBaseFragment() {
companion object {
- /** Create a new instance of this fragment. */
+ /** Create a new instance of this fragment. */
@JvmStatic
fun newInstance(): HandheldUnusedAppsWrapperFragment {
return HandheldUnusedAppsWrapperFragment()
@@ -48,15 +46,16 @@ class HandheldUnusedAppsWrapperFragment : CollapsingToolbarBaseFragment() {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
- var preferenceFragment = childFragmentManager
- .findFragmentById(R.id.preference_fragment_container)
+ var preferenceFragment =
+ childFragmentManager.findFragmentById(R.id.preference_fragment_container)
as HandheldUnusedAppsFragment?
if (preferenceFragment == null) {
preferenceFragment = HandheldUnusedAppsFragment.newInstance()
preferenceFragment.arguments = arguments
- childFragmentManager.beginTransaction()
- .add(R.id.preference_fragment_container, preferenceFragment)
- .commit()
+ childFragmentManager
+ .beginTransaction()
+ .add(R.id.preference_fragment_container, preferenceFragment)
+ .commit()
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
index 220507426..6bcf926d3 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
@@ -21,6 +21,7 @@ import static com.android.permissioncontroller.permission.ui.Category.ALLOWED;
import static com.android.permissioncontroller.permission.ui.Category.ALLOWED_FOREGROUND;
import static com.android.permissioncontroller.permission.ui.Category.ASK;
import static com.android.permissioncontroller.permission.ui.Category.DENIED;
+import static com.android.permissioncontroller.permission.ui.Category.STORAGE_FOOTER;
import static com.android.permissioncontroller.permission.ui.handheld.UtilsKt.pressBack;
import android.Manifest;
@@ -62,15 +63,15 @@ import com.android.settingslib.HelpUtils;
import com.android.settingslib.utils.applications.AppUtils;
import com.android.settingslib.widget.FooterPreference;
+import kotlin.Pair;
+import kotlin.Triple;
+
import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
-import kotlin.Pair;
-import kotlin.Triple;
-
/**
* Show and manage apps which request a single permission group.
*
@@ -87,7 +88,6 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
private static final String STORAGE_ALLOWED_FULL = "allowed_storage_full";
private static final String STORAGE_ALLOWED_SCOPED = "allowed_storage_scoped";
private static final String BLOCKED_SENSOR_PREF_KEY = "sensor_card";
- private static final String STORAGE_FOOTER_CATEGORY_KEY = "storage_footer_category";
private static final String STORAGE_FOOTER_PREFERENCE_KEY = "storage_footer_preference";
private static final int SHOW_LOAD_DELAY_MS = 200;
@@ -303,7 +303,7 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
private void addStorageFooterSeeAllFilesAccess() {
PreferenceScreen screen = getPreferenceScreen();
Context context = screen.getPreferenceManager().getContext();
- PreferenceCategory preferenceCategory = findPreference(STORAGE_FOOTER_CATEGORY_KEY);
+ PreferenceCategory preferenceCategory = findPreference(STORAGE_FOOTER.getCategoryName());
Preference existingPreference = findPreference(STORAGE_FOOTER_PREFERENCE_KEY);
if (preferenceCategory == null || existingPreference != null) {
@@ -502,6 +502,13 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
if (SdkLevel.isAtLeastT() && Manifest.permission_group.STORAGE.equals(mPermGroupName)) {
addStorageFooterSeeAllFilesAccess();
+ } else {
+ // Hide storage footer category
+ PreferenceCategory storageFooterPreferenceCategory =
+ findPreference(STORAGE_FOOTER.getCategoryName());
+ if (storageFooterPreferenceCategory != null) {
+ storageFooterPreferenceCategory.setVisible(false);
+ }
}
mViewModel.setCreationLogged(true);
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SmartIconLoadPackagePermissionPreference.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SmartIconLoadPackagePermissionPreference.kt
index 27cbd8c15..f7178bdbb 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SmartIconLoadPackagePermissionPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SmartIconLoadPackagePermissionPreference.kt
@@ -30,16 +30,17 @@ import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.utils.KotlinUtils
/**
- * A Preference representing a package for a user, which loads and displays its icon only upon
- * being bound to a viewHolder. This lets us synchronously load package icons and labels, while
- * still displaying the PermissionAppsFragment instantly.
+ * A Preference representing a package for a user, which loads and displays its icon only upon being
+ * bound to a viewHolder. This lets us synchronously load package icons and labels, while still
+ * displaying the PermissionAppsFragment instantly.
*
* @param app The current application
* @param packageName The name of the package whose icon this preference will retrieve
* @param user The user whose package icon will be retrieved
* @param context The current context
*/
-open class SmartIconLoadPackagePermissionPreference constructor(
+open class SmartIconLoadPackagePermissionPreference
+constructor(
private val app: Application,
private val packageName: String,
private val user: UserHandle,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/UnusedAppPreference.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/UnusedAppPreference.kt
index dfab55ed7..02eb6c090 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/UnusedAppPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/UnusedAppPreference.kt
@@ -50,9 +50,7 @@ class UnusedAppPreference(
super.onBindViewHolder(holder)
val removeButton = holder.findViewById(R.id.uninstall_button) as ImageButton
- removeButton.setOnClickListener {
- removeRunnable?.run()
- }
+ removeButton.setOnClickListener { removeRunnable?.run() }
removeButton.isEnabled = removeButtonEnabled
}
@@ -63,4 +61,4 @@ class UnusedAppPreference(
override fun setRemoveComponentEnabled(enabled: Boolean) {
removeButtonEnabled = enabled
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/Utils.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/Utils.kt
index e2acb498c..f6a387e9d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/Utils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/Utils.kt
@@ -19,12 +19,10 @@ package com.android.permissioncontroller.permission.ui.handheld
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
-/**
- * Press back and close the activity if this is the last fragment.
- */
+/** Press back and close the activity if this is the last fragment. */
fun Fragment.pressBack() {
val wasBackExecuted = findNavController().popBackStack()
if (!wasBackExecuted) {
activity?.let { it.finishAfterTransition() }
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/DashboardUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/DashboardUtils.kt
index 5b92dd36d..b36d5174c 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/DashboardUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/DashboardUtils.kt
@@ -49,7 +49,6 @@ fun shouldShowSubattributionInPermissionsDashboard(): Boolean {
*
* @param context the context.
* @param lastAccessTime the time in milliseconds.
- *
* @return a string representing the time or date of the given time or null if the time is 0.
*/
fun getAbsoluteTimeString(context: Context, lastAccessTime: Long): String? {
@@ -64,14 +63,13 @@ fun getAbsoluteTimeString(context: Context, lastAccessTime: Long): String? {
}
/**
- * Build a string representing the time of the most recent permission usage if it happened on
- * the current day and the date otherwise.
+ * Build a string representing the time of the most recent permission usage if it happened on the
+ * current day and the date otherwise.
*
* @param context the context.
* @param groupUsage the permission usage.
- *
- * @return a string representing the time or date of the most recent usage or null if there are
- * no usages.
+ * @return a string representing the time or date of the most recent usage or null if there are no
+ * usages.
*/
@RequiresApi(Build.VERSION_CODES.S)
fun getAbsoluteLastUsageString(context: Context, groupUsage: GroupUsage?): String? {
@@ -83,8 +81,7 @@ fun getAbsoluteLastUsageString(context: Context, groupUsage: GroupUsage?): Strin
/**
* Build a string representing the duration of a permission usage.
*
- * @return a string representing the duration of this app's usage or null if there are no
- * usages.
+ * @return a string representing the duration of this app's usage or null if there are no usages.
*/
@RequiresApi(Build.VERSION_CODES.S)
fun getUsageDurationString(context: Context, groupUsage: GroupUsage?): String? {
@@ -94,9 +91,9 @@ fun getUsageDurationString(context: Context, groupUsage: GroupUsage?): String? {
}
/**
- * Build a string representing the number of milliseconds passed in. It rounds to the nearest
- * unit. For example, given a duration of 3500 and an English locale, this can return
- * "3 seconds".
+ * Build a string representing the number of milliseconds passed in. It rounds to the nearest unit.
+ * For example, given a duration of 3500 and an English locale, this can return "3 seconds".
+ *
* @param context The context.
* @param duration The number of milliseconds.
* @return a string representing the given number of milliseconds.
@@ -104,37 +101,63 @@ fun getUsageDurationString(context: Context, groupUsage: GroupUsage?): String? {
fun getTimeDiffStr(context: Context, duration: Long): String {
val timeDiffAndUnit = calculateTimeDiffAndUnit(duration)
return when (timeDiffAndUnit.second) {
- SECONDS -> StringUtils.getIcuPluralsString(context,
- R.string.seconds, timeDiffAndUnit.first.toInt())
- MINUTES -> StringUtils.getIcuPluralsString(context,
- R.string.minutes, timeDiffAndUnit.first.toInt())
- HOURS -> StringUtils.getIcuPluralsString(context,
- R.string.hours, timeDiffAndUnit.first.toInt())
- else -> StringUtils.getIcuPluralsString(context,
- R.string.days, timeDiffAndUnit.first.toInt())
+ SECONDS ->
+ StringUtils.getIcuPluralsString(
+ context,
+ R.string.seconds,
+ timeDiffAndUnit.first.toInt()
+ )
+ MINUTES ->
+ StringUtils.getIcuPluralsString(
+ context,
+ R.string.minutes,
+ timeDiffAndUnit.first.toInt()
+ )
+ HOURS ->
+ StringUtils.getIcuPluralsString(context, R.string.hours, timeDiffAndUnit.first.toInt())
+ else ->
+ StringUtils.getIcuPluralsString(context, R.string.days, timeDiffAndUnit.first.toInt())
}
}
/**
* Build a string representing the duration used of milliseconds passed in.
+ *
* @return a string representing the duration used in the nearest unit. ex: Used for 3 mins
*/
fun getDurationUsedStr(context: Context, duration: Long): String {
val timeDiffAndUnit = calculateTimeDiffAndUnit(duration)
return when (timeDiffAndUnit.second) {
- SECONDS -> StringUtils.getIcuPluralsString(context,
- R.string.duration_used_seconds, timeDiffAndUnit.first.toInt())
- MINUTES -> StringUtils.getIcuPluralsString(context,
- R.string.duration_used_minutes, timeDiffAndUnit.first.toInt())
- HOURS -> StringUtils.getIcuPluralsString(context,
- R.string.duration_used_hours, timeDiffAndUnit.first.toInt())
- else -> StringUtils.getIcuPluralsString(context,
- R.string.duration_used_days, timeDiffAndUnit.first.toInt())
+ SECONDS ->
+ StringUtils.getIcuPluralsString(
+ context,
+ R.string.duration_used_seconds,
+ timeDiffAndUnit.first.toInt()
+ )
+ MINUTES ->
+ StringUtils.getIcuPluralsString(
+ context,
+ R.string.duration_used_minutes,
+ timeDiffAndUnit.first.toInt()
+ )
+ HOURS ->
+ StringUtils.getIcuPluralsString(
+ context,
+ R.string.duration_used_hours,
+ timeDiffAndUnit.first.toInt()
+ )
+ else ->
+ StringUtils.getIcuPluralsString(
+ context,
+ R.string.duration_used_days,
+ timeDiffAndUnit.first.toInt()
+ )
}
}
/**
* Given the duration in milliseconds, calculate the time of that duration in the nearest unit.
+ *
* @return a Pair of the <duration in the nearest unit, the nearest unit>
*/
fun calculateTimeDiffAndUnit(duration: Long): Pair<Long, Int> {
@@ -159,7 +182,6 @@ fun calculateTimeDiffAndUnit(duration: Long): Pair<Long, Int> {
* Check whether the given time (in milliseconds) is in the current day.
*
* @param time the time in milliseconds
- *
* @return whether the given time is in the current day.
*/
private fun isToday(time: Long): Boolean {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionHistoryPreference.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionHistoryPreference.java
index bcca75fcc..5c20ef9df 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionHistoryPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionHistoryPreference.java
@@ -77,7 +77,7 @@ public class PermissionHistoryPreference extends Preference {
public PermissionHistoryPreference(@NonNull Context context,
@NonNull UserHandle userHandle, @NonNull String pkgName,
- @NonNull Drawable appIcon,
+ @Nullable Drawable appIcon,
@NonNull String preferenceTitle,
@NonNull String permissionGroup,
@NonNull long accessStartTime,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionUsageDetailsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionUsageDetailsFragment.java
index 15ee31a54..5d4343639 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionUsageDetailsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionUsageDetailsFragment.java
@@ -368,15 +368,9 @@ public class PermissionUsageDetailsFragment extends SettingsWithLargeHeader {
new PermissionHistoryPreference(
getContext(),
appPermissionAccessUiInfo.getUserHandle(),
- appPermissionAccessUiInfo.getPkgName(),
- KotlinUtils.INSTANCE.getBadgedPackageIcon(
- mViewModel.getApplication(),
- appPermissionAccessUiInfo.getPkgName(),
- appPermissionAccessUiInfo.getUserHandle()),
- KotlinUtils.INSTANCE.getPackageLabel(
- mViewModel.getApplication(),
- appPermissionAccessUiInfo.getPkgName(),
- appPermissionAccessUiInfo.getUserHandle()),
+ appPermissionAccessUiInfo.getPackageName(),
+ appPermissionAccessUiInfo.getBadgedPackageIcon(),
+ appPermissionAccessUiInfo.getPackageLabel(),
appPermissionAccessUiInfo.getPermissionGroup(),
appPermissionAccessUiInfo.getAccessStartTime(),
appPermissionAccessUiInfo.getAccessEndTime(),
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt
index 88b5ebe87..e74022291 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt
@@ -76,7 +76,8 @@ class AppDataSharingUpdatesFooterPreference : Preference {
},
0,
footerLink.length,
- 0)
+ 0
+ )
footerLinkView?.let {
it.visibility = if (onFooterLinkClick == null) View.GONE else View.VISIBLE
it.text = footerLinkText
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFragment.kt
index 2db9bc4b4..b58de90a5 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFragment.kt
@@ -98,7 +98,8 @@ class AppDataSharingUpdatesFragment : PermissionsFrameFragment() {
val updatesCategory =
preferenceScreen.findPreference<PreferenceCategory>(
LAST_PERIOD_UPDATES_PREFERENCE_CATEGORY_ID
- ) ?: return
+ )
+ ?: return
val preferencesToRemove = mutableSetOf<Preference>()
for (i in 0 until (updatesCategory.preferenceCount)) {
@@ -192,11 +193,12 @@ class AppDataSharingUpdatesFragment : PermissionsFrameFragment() {
it.isVisible = true
}
- val onFooterLinkClick = if (viewModel.canLinkToHelpCenter(requireActivity())) {
- View.OnClickListener { viewModel.openSafetyLabelsHelpCenterPage(requireActivity()) }
- } else {
- null
- }
+ val onFooterLinkClick =
+ if (viewModel.canLinkToHelpCenter(requireActivity())) {
+ View.OnClickListener { viewModel.openSafetyLabelsHelpCenterPage(requireActivity()) }
+ } else {
+ null
+ }
footerPreference?.let {
it.footerMessage = getString(R.string.data_sharing_updates_footer_message)
it.footerLink = getString(R.string.learn_about_data_sharing)
@@ -231,11 +233,14 @@ class AppDataSharingUpdatesFragment : PermissionsFrameFragment() {
footerPreference?.let {
it.footerMessage = getString(R.string.data_sharing_updates_footer_message)
it.footerLink = getString(R.string.learn_about_data_sharing)
- it.onFooterLinkClick = if (viewModel.canLinkToHelpCenter(requireActivity())) {
- View.OnClickListener { viewModel.openSafetyLabelsHelpCenterPage(requireActivity()) }
- } else {
- null
- }
+ it.onFooterLinkClick =
+ if (viewModel.canLinkToHelpCenter(requireActivity())) {
+ View.OnClickListener {
+ viewModel.openSafetyLabelsHelpCenterPage(requireActivity())
+ }
+ } else {
+ null
+ }
it.isVisible = true
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt
index 3998ca141..93e6b6336 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt
@@ -122,14 +122,14 @@ class PermissionRationaleViewHandlerImpl(
// Grow or shrink the content container to size of new content
val growShrinkToNewContentSize = ChangeBounds()
growShrinkToNewContentSize.duration = ANIMATION_DURATION_MILLIS
- growShrinkToNewContentSize.interpolator = AnimationUtils.loadInterpolator(mActivity,
- android.R.interpolator.fast_out_slow_in)
+ growShrinkToNewContentSize.interpolator =
+ AnimationUtils.loadInterpolator(mActivity, android.R.interpolator.fast_out_slow_in)
TransitionManager.beginDelayedTransition(rootView, growShrinkToNewContentSize)
}
override fun createView(): View {
- val rootView = LayoutInflater.from(mActivity)
- .inflate(R.layout.permission_rationale, null) as ViewGroup
+ val rootView =
+ LayoutInflater.from(mActivity).inflate(R.layout.permission_rationale, null) as ViewGroup
// Uses the vertical gravity of the PermissionGrantSingleton style to position the window
val gravity =
@@ -160,13 +160,15 @@ class PermissionRationaleViewHandlerImpl(
val settingsSectionView: ViewGroup? = rootView.findViewById(R.id.settings_section)
settingsSectionView?.visibility = View.GONE
}
- backButton = rootView.findViewById<Button>(R.id.back_button)!!.apply {
- setOnClickListener(this@PermissionRationaleViewHandlerImpl)
-
- // Load the text color from the activity theme rather than the Material Design theme
- val textColor = getColorStateListForAttr(mActivity, android.R.attr.textColorPrimary)!!
- setTextColor(textColor)
- }
+ backButton =
+ rootView.findViewById<Button>(R.id.back_button)!!.apply {
+ setOnClickListener(this@PermissionRationaleViewHandlerImpl)
+
+ // Load the text color from the activity theme rather than the Material Design theme
+ val textColor =
+ getColorStateListForAttr(mActivity, android.R.attr.textColorPrimary)!!
+ setTextColor(textColor)
+ }
this.rootView = rootView
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageDetailsViewModelLegacy.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageDetailsViewModelLegacy.kt
index e219153f3..14aff67ba 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageDetailsViewModelLegacy.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageDetailsViewModelLegacy.kt
@@ -44,8 +44,8 @@ import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils.getPackageLabel
import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.StringUtils
-import com.android.permissioncontroller.permission.utils.v31.SubattributionUtils
import com.android.permissioncontroller.permission.utils.Utils
+import com.android.permissioncontroller.permission.utils.v31.SubattributionUtils
import java.time.Instant
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeUnit.DAYS
@@ -93,7 +93,8 @@ class PermissionUsageDetailsViewModelLegacy(
/* getUiInfo= */ false,
/* getNonPlatformPermissions= */ false,
/* callback= */ callback,
- /* sync= */ false)
+ /* sync= */ false
+ )
}
/**
@@ -116,19 +117,26 @@ class PermissionUsageDetailsViewModelLegacy(
}
val startTime =
(System.currentTimeMillis() - showPermissionUsagesDuration).coerceAtLeast(
- Instant.EPOCH.toEpochMilli())
+ Instant.EPOCH.toEpochMilli()
+ )
val appPermissionTimelineUsages: List<AppPermissionTimelineUsage> =
extractAppPermissionTimelineUsagesForGroup(appPermissionUsages, permissionGroup)
val shouldDisplayShowSystemToggle =
shouldDisplayShowSystemToggle(appPermissionTimelineUsages)
val permissionApps: List<PermissionApp> =
getPermissionAppsWithRecentDiscreteUsage(
- appPermissionTimelineUsages, showSystem, startTime)
+ appPermissionTimelineUsages,
+ showSystem,
+ startTime
+ )
val appPermissionUsageEntries =
buildDiscreteAccessClusterData(appPermissionTimelineUsages, showSystem, startTime)
return PermissionUsageDetailsUiData(
- permissionApps, shouldDisplayShowSystemToggle, appPermissionUsageEntries)
+ permissionApps,
+ shouldDisplayShowSystemToggle,
+ appPermissionUsageEntries
+ )
}
private fun getHistoryPreferenceData(
@@ -141,14 +149,14 @@ class PermissionUsageDetailsViewModelLegacy(
getDurationSummary(discreteAccessClusterData, accessTimeList, context)
val proxyLabel = getProxyPackageLabel(discreteAccessClusterData)
val subattributionLabel = getSubattributionLabel(discreteAccessClusterData)
- val showingSubattribution =
- subattributionLabel != null && subattributionLabel.isNotEmpty()
+ val showingSubattribution = subattributionLabel != null && subattributionLabel.isNotEmpty()
val summary =
buildUsageSummary(durationSummaryLabel, proxyLabel, subattributionLabel, context)
return HistoryPreferenceData(
UserHandle.getUserHandleForUid(
- discreteAccessClusterData.appPermissionTimelineUsage.permissionApp.uid),
+ discreteAccessClusterData.appPermissionTimelineUsage.permissionApp.uid
+ ),
discreteAccessClusterData.appPermissionTimelineUsage.permissionApp.packageName,
discreteAccessClusterData.appPermissionTimelineUsage.permissionApp.icon,
discreteAccessClusterData.appPermissionTimelineUsage.permissionApp.label,
@@ -158,7 +166,8 @@ class PermissionUsageDetailsViewModelLegacy(
summary,
showingSubattribution,
discreteAccessClusterData.appPermissionTimelineUsage.attributionTags,
- sessionId)
+ sessionId
+ )
}
/**
@@ -180,7 +189,8 @@ class PermissionUsageDetailsViewModelLegacy(
.map { appPermissionUsage ->
getAppPermissionTimelineUsages(
appPermissionUsage.app,
- appPermissionUsage.groupUsages.firstOrNull { it.group.name == group })
+ appPermissionUsage.groupUsages.firstOrNull { it.group.name == group }
+ )
}
.flatten()
@@ -221,7 +231,10 @@ class PermissionUsageDetailsViewModelLegacy(
.map { appPermissionTimelineUsages ->
val accessDataList =
extractRecentDiscreteAccessData(
- appPermissionTimelineUsages.timelineUsage, showSystem, startTime)
+ appPermissionTimelineUsages.timelineUsage,
+ showSystem,
+ startTime
+ )
if (accessDataList.size <= 1) {
return@map accessDataList.map {
@@ -235,7 +248,9 @@ class PermissionUsageDetailsViewModelLegacy(
.sortedWith(
compareBy(
{ -it.discreteAccessDataList.first().accessTimeMs },
- { it.appPermissionTimelineUsage.permissionApp.label }))
+ { it.appPermissionTimelineUsage.permissionApp.label }
+ )
+ )
.toList()
/**
@@ -253,11 +268,15 @@ class PermissionUsageDetailsViewModelLegacy(
for (discreteAccessData in discreteAccessDataList) {
if (currentDiscreteAccessDataList.isEmpty()) {
currentDiscreteAccessDataList.add(discreteAccessData)
- } else if (!canAccessBeAddedToCluster(
- discreteAccessData, currentDiscreteAccessDataList)) {
+ } else if (
+ !canAccessBeAddedToCluster(discreteAccessData, currentDiscreteAccessDataList)
+ ) {
clusterDataList.add(
DiscreteAccessClusterData(
- appPermissionTimelineUsage, currentDiscreteAccessDataList.toMutableList()))
+ appPermissionTimelineUsage,
+ currentDiscreteAccessDataList.toMutableList()
+ )
+ )
currentDiscreteAccessDataList.clear()
currentDiscreteAccessDataList.add(discreteAccessData)
} else {
@@ -266,8 +285,8 @@ class PermissionUsageDetailsViewModelLegacy(
}
if (currentDiscreteAccessDataList.isNotEmpty()) {
clusterDataList.add(
- DiscreteAccessClusterData(
- appPermissionTimelineUsage, currentDiscreteAccessDataList))
+ DiscreteAccessClusterData(appPermissionTimelineUsage, currentDiscreteAccessDataList)
+ )
}
return clusterDataList
}
@@ -282,8 +301,9 @@ class PermissionUsageDetailsViewModelLegacy(
showSystem: Boolean,
startTime: Long
): List<DiscreteAccessData> {
- return if (timelineUsages.hasDiscreteData() &&
- (showSystem || !timelineUsages.group.isSystem())) {
+ return if (
+ timelineUsages.hasDiscreteData() && (showSystem || !timelineUsages.group.isSystem())
+ ) {
getRecentDiscreteAccessData(timelineUsages, startTime)
.sortedWith(compareBy { -it.accessTimeMs })
.toList()
@@ -377,7 +397,8 @@ class PermissionUsageDetailsViewModelLegacy(
getPackageLabel(
PermissionControllerApplication.get(),
it.proxy!!.packageName!!,
- UserHandle.getUserHandleForUid(it.proxy.uid))
+ UserHandle.getUserHandleForUid(it.proxy.uid)
+ )
}
/** Returns the attribution label for the permission access, if any. */
@@ -406,10 +427,14 @@ class PermissionUsageDetailsViewModelLegacy(
R.string.history_preference_subtext_3,
subTextStrings[0],
subTextStrings[1],
- subTextStrings[2])
+ subTextStrings[2]
+ )
2 ->
context.getString(
- R.string.history_preference_subtext_2, subTextStrings[0], subTextStrings[1])
+ R.string.history_preference_subtext_2,
+ subTextStrings[0],
+ subTextStrings[1]
+ )
1 -> subTextStrings[0]
else -> null
}
@@ -434,7 +459,8 @@ class PermissionUsageDetailsViewModelLegacy(
}
return listOf(
- AppPermissionTimelineUsage(permissionGroup, app, groupUsage, Resources.ID_NULL))
+ AppPermissionTimelineUsage(permissionGroup, app, groupUsage, Resources.ID_NULL)
+ )
}
/** Extracts to a set all the permission groups declared by the platform. */
@@ -448,15 +474,20 @@ class PermissionUsageDetailsViewModelLegacy(
/** Initialize all relevant [TimeFilterItemMs] values. */
private fun initializeTimeFilterItems(context: Context) {
mTimeFilterItemMs.add(
- TimeFilterItemMs(Long.MAX_VALUE, context.getString(R.string.permission_usage_any_time)))
+ TimeFilterItemMs(Long.MAX_VALUE, context.getString(R.string.permission_usage_any_time))
+ )
mTimeFilterItemMs.add(
TimeFilterItemMs(
DAYS.toMillis(7),
- StringUtils.getIcuPluralsString(context, R.string.permission_usage_last_n_days, 7)))
+ StringUtils.getIcuPluralsString(context, R.string.permission_usage_last_n_days, 7)
+ )
+ )
mTimeFilterItemMs.add(
TimeFilterItemMs(
DAYS.toMillis(1),
- StringUtils.getIcuPluralsString(context, R.string.permission_usage_last_n_days, 1)))
+ StringUtils.getIcuPluralsString(context, R.string.permission_usage_last_n_days, 1)
+ )
+ )
// TODO: theianchen add code for filtering by time here.
}
@@ -554,7 +585,11 @@ class PermissionUsageDetailsViewModelFactoryLegacy(
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
return PermissionUsageDetailsViewModelLegacy(
- application, roleManager, filterGroup, sessionId)
+ application,
+ roleManager,
+ filterGroup,
+ sessionId
+ )
as T
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageViewModelLegacy.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageViewModelLegacy.kt
index d0e751f7d..3032dece5 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageViewModelLegacy.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/legacy/PermissionUsageViewModelLegacy.kt
@@ -57,7 +57,8 @@ class PermissionUsageViewModelLegacy(val roleManager: RoleManager) : ViewModel()
mapOf(
Manifest.permission_group.LOCATION to 0,
Manifest.permission_group.CAMERA to 1,
- Manifest.permission_group.MICROPHONE to 2)
+ Manifest.permission_group.MICROPHONE to 2
+ )
private const val DEFAULT_ORDER = 3
}
@@ -79,7 +80,8 @@ class PermissionUsageViewModelLegacy(val roleManager: RoleManager) : ViewModel()
false /*getUiInfo*/,
false /*getNonPlatformPermissions*/,
callback /*callback*/,
- false /*sync*/)
+ false /*sync*/
+ )
}
/**
@@ -108,10 +110,16 @@ class PermissionUsageViewModelLegacy(val roleManager: RoleManager) : ViewModel()
val permissionApps = filteredAppPermissionUsages.getRecentPermissionApps(startTime)
val orderedPermissionGroupsWithUsage =
filteredAppPermissionUsages.buildOrderedPermissionGroupsWithUsageCount(
- context, startTime, showSystem)
+ context,
+ startTime,
+ showSystem
+ )
return PermissionUsagesUiData(
- permissionApps, displayShowSystemToggle, orderedPermissionGroupsWithUsage)
+ permissionApps,
+ displayShowSystemToggle,
+ orderedPermissionGroupsWithUsage
+ )
}
/**
@@ -150,7 +158,9 @@ class PermissionUsageViewModelLegacy(val roleManager: RoleManager) : ViewModel()
.sortedWith(
compareBy(
{ PERMISSION_GROUP_ORDER.getOrDefault(it.permGroup, DEFAULT_ORDER) },
- { getPermGroupLabel(context, it.permGroup).toString() }))
+ { getPermGroupLabel(context, it.permGroup).toString() }
+ )
+ )
}
/** Extracts [PermissionApp] where there has been recent permission usage. */
@@ -163,7 +173,8 @@ class PermissionUsageViewModelLegacy(val roleManager: RoleManager) : ViewModel()
.filter { !EXEMPTED_PERMISSION_GROUPS.contains(it.group.name) }
.any { it.lastAccessTime >= startTime || it.lastAccessTime == 0L }
}
- .map { it.app })
+ .map { it.app }
+ )
}
/**
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AllAppPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AllAppPermissionsViewModel.kt
index 226208041..3e651dd9f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AllAppPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AllAppPermissionsViewModel.kt
@@ -33,41 +33,34 @@ import com.android.permissioncontroller.permission.utils.Utils
*
* @param packageName The name of the package this viewModel is representing
* @param user The user of the package this viewModel is representing
- * @param filterGroup An optional single group that should be shown, no other groups will be
- * shown
+ * @param filterGroup An optional single group that should be shown, no other groups will be shown
*/
-class AllAppPermissionsViewModel(
- packageName: String,
- user: UserHandle,
- filterGroup: String?
-) : ViewModel() {
+class AllAppPermissionsViewModel(packageName: String, user: UserHandle, filterGroup: String?) :
+ ViewModel() {
- val allPackagePermissionsLiveData = AllPackagePermissionsLiveData(packageName, user,
- filterGroup)
+ val allPackagePermissionsLiveData =
+ AllPackagePermissionsLiveData(packageName, user, filterGroup)
class AllPackagePermissionsLiveData(
packageName: String,
user: UserHandle,
private val filterGroup: String?
- ) : SmartUpdateMediatorLiveData<@kotlin.jvm.JvmSuppressWildcards
- Map<String, List<String>>>() {
+ ) : SmartUpdateMediatorLiveData<@kotlin.jvm.JvmSuppressWildcards Map<String, List<String>>>() {
- private val packagePermsLiveData =
- PackagePermissionsLiveData[packageName, user]
+ private val packagePermsLiveData = PackagePermissionsLiveData[packageName, user]
private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user]
init {
- addSource(packagePermsLiveData) {
- update()
- }
- addSource(packageInfoLiveData) {
- update()
- }
+ addSource(packagePermsLiveData) { update() }
+ addSource(packageInfoLiveData) { update() }
}
override fun onUpdate() {
- if (!packagePermsLiveData.isInitialized || packagePermsLiveData.isStale ||
- !packageInfoLiveData.isInitialized) {
+ if (
+ !packagePermsLiveData.isInitialized ||
+ packagePermsLiveData.isStale ||
+ !packageInfoLiveData.isInitialized
+ ) {
return
}
val permissions = packagePermsLiveData.value
@@ -77,12 +70,17 @@ class AllAppPermissionsViewModel(
return
}
- value = permissions
- .filter { filterGroup == null || it.key == filterGroup }
- .filter { (it.key != Manifest.permission_group.STORAGE ||
- Utils.shouldShowStorage(packageInfo)) }
- .filter { (!Utils.isHealthPermissionGroup(it.key) ||
- Utils.shouldShowHealthPermission(packageInfo, it.key))}
+ value =
+ permissions
+ .filter { filterGroup == null || it.key == filterGroup }
+ .filter {
+ (it.key != Manifest.permission_group.STORAGE ||
+ Utils.shouldShowStorage(packageInfo))
+ }
+ .filter {
+ (!Utils.isHealthPermissionGroup(it.key) ||
+ Utils.shouldShowHealthPermission(packageInfo, it.key))
+ }
}
}
}
@@ -93,8 +91,7 @@ class AllAppPermissionsViewModel(
* @param app The current application
* @param packageName The name of the package this viewModel is representing
* @param user The user of the package this viewModel is representing
- * @param filterGroup An optional single group that should be shown, no other groups will be
- * shown
+ * @param filterGroup An optional single group that should be shown, no other groups will be shown
*/
class AllAppPermissionsViewModelFactory(
private val packageName: String,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt
index 741c93aab..5ecab1527 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt
@@ -95,135 +95,165 @@ class AppPermissionGroupsViewModel(
val isSystem: Boolean = false,
val subtitle: PermSubtitle
) {
- constructor(groupName: String, isSystem: Boolean) :
- this(groupName, isSystem, PermSubtitle.NONE)
+ constructor(
+ groupName: String,
+ isSystem: Boolean
+ ) : this(groupName, isSystem, PermSubtitle.NONE)
}
// Auto-revoke and hibernation share the same settings
val autoRevokeLiveData = HibernationSettingStateLiveData[packageName, user]
- private val packagePermsLiveData =
- PackagePermissionsLiveData[packageName, user]
+ private val packagePermsLiveData = PackagePermissionsLiveData[packageName, user]
private val appPermGroupUiInfoLiveDatas = mutableMapOf<String, AppPermGroupUiInfoLiveData>()
private val fullStoragePermsLiveData = FullStoragePermissionAppsLiveData
/**
- * LiveData whose data is a map of grant category (either allowed or denied) to a list
- * of permission group names that match the key, and two booleans representing if this is a
- * system group, and a subtitle resource ID, if applicable.
+ * LiveData whose data is a map of grant category (either allowed or denied) to a list of
+ * permission group names that match the key, and two booleans representing if this is a system
+ * group, and a subtitle resource ID, if applicable.
*/
- val packagePermGroupsLiveData = object : SmartUpdateMediatorLiveData<@JvmSuppressWildcards
- Map<Category, List<GroupUiInfo>>>() {
-
- init {
- addSource(packagePermsLiveData) {
- update()
- }
- addSource(fullStoragePermsLiveData) {
- update()
- }
- addSource(autoRevokeLiveData) {
- removeSource(autoRevokeLiveData)
+ val packagePermGroupsLiveData =
+ object :
+ SmartUpdateMediatorLiveData<@JvmSuppressWildcards Map<Category, List<GroupUiInfo>>>() {
+
+ init {
+ addSource(packagePermsLiveData) { update() }
+ addSource(fullStoragePermsLiveData) { update() }
+ addSource(autoRevokeLiveData) {
+ removeSource(autoRevokeLiveData)
+ update()
+ }
update()
}
- update()
- }
- override fun onUpdate() {
- val groups = packagePermsLiveData.value?.keys?.filter { it != NON_RUNTIME_NORMAL_PERMS }
- if (groups == null && packagePermsLiveData.isInitialized) {
- value = null
- return
- } else if (groups == null || (Manifest.permission_group.STORAGE in groups &&
- !fullStoragePermsLiveData.isInitialized) || !autoRevokeLiveData.isInitialized) {
- return
- }
-
- val getLiveData = { groupName: String ->
- AppPermGroupUiInfoLiveData[packageName, groupName, user]
- }
- setSourcesToDifference(groups, appPermGroupUiInfoLiveDatas, getLiveData)
+ override fun onUpdate() {
+ val groups =
+ packagePermsLiveData.value?.keys?.filter { it != NON_RUNTIME_NORMAL_PERMS }
+ if (groups == null && packagePermsLiveData.isInitialized) {
+ value = null
+ return
+ } else if (
+ groups == null ||
+ (Manifest.permission_group.STORAGE in groups &&
+ !fullStoragePermsLiveData.isInitialized) ||
+ !autoRevokeLiveData.isInitialized
+ ) {
+ return
+ }
- if (!appPermGroupUiInfoLiveDatas.all { it.value.isInitialized }) {
- return
- }
+ val getLiveData = { groupName: String ->
+ AppPermGroupUiInfoLiveData[packageName, groupName, user]
+ }
+ setSourcesToDifference(groups, appPermGroupUiInfoLiveDatas, getLiveData)
- val groupGrantStates = mutableMapOf<Category,
- MutableList<GroupUiInfo>>()
- groupGrantStates[Category.ALLOWED] = mutableListOf()
- groupGrantStates[Category.ASK] = mutableListOf()
- groupGrantStates[Category.DENIED] = mutableListOf()
+ if (!appPermGroupUiInfoLiveDatas.all { it.value.isInitialized }) {
+ return
+ }
- val fullStorageState = fullStoragePermsLiveData.value?.find { pkg ->
- pkg.packageName == packageName && pkg.user == user
- }
+ val groupGrantStates = mutableMapOf<Category, MutableList<GroupUiInfo>>()
+ groupGrantStates[Category.ALLOWED] = mutableListOf()
+ groupGrantStates[Category.ASK] = mutableListOf()
+ groupGrantStates[Category.DENIED] = mutableListOf()
- for (groupName in groups) {
- val isSystem = PermissionMapping.getPlatformPermissionGroups().contains(groupName)
- appPermGroupUiInfoLiveDatas[groupName]?.value?.let { uiInfo ->
- if (SdkLevel.isAtLeastT() && !uiInfo.shouldShow) {
- return@let
+ val fullStorageState =
+ fullStoragePermsLiveData.value?.find { pkg ->
+ pkg.packageName == packageName && pkg.user == user
}
- if (groupName == Manifest.permission_group.STORAGE &&
- (fullStorageState?.isGranted == true && !fullStorageState.isLegacy)) {
- groupGrantStates[Category.ALLOWED]!!.add(
- GroupUiInfo(groupName, isSystem, PermSubtitle.ALL_FILES))
- return@let
- }
- when (uiInfo.permGrantState) {
- PermGrantState.PERMS_ALLOWED -> {
- val subtitle = if (groupName == Manifest.permission_group.STORAGE) {
- if (SdkLevel.isAtLeastT()) {
- PermSubtitle.NONE
- } else {
- if (fullStorageState?.isLegacy == true) {
- PermSubtitle.ALL_FILES
+
+ for (groupName in groups) {
+ val isSystem =
+ PermissionMapping.getPlatformPermissionGroups().contains(groupName)
+ appPermGroupUiInfoLiveDatas[groupName]?.value?.let { uiInfo ->
+ if (SdkLevel.isAtLeastT() && !uiInfo.shouldShow) {
+ return@let
+ }
+ if (
+ groupName == Manifest.permission_group.STORAGE &&
+ (fullStorageState?.isGranted == true && !fullStorageState.isLegacy)
+ ) {
+ groupGrantStates[Category.ALLOWED]!!.add(
+ GroupUiInfo(groupName, isSystem, PermSubtitle.ALL_FILES)
+ )
+ return@let
+ }
+ when (uiInfo.permGrantState) {
+ PermGrantState.PERMS_ALLOWED -> {
+ val subtitle =
+ if (groupName == Manifest.permission_group.STORAGE) {
+ if (SdkLevel.isAtLeastT()) {
+ PermSubtitle.NONE
+ } else {
+ if (fullStorageState?.isLegacy == true) {
+ PermSubtitle.ALL_FILES
+ } else {
+ PermSubtitle.MEDIA_ONLY
+ }
+ }
} else {
- PermSubtitle.MEDIA_ONLY
+ PermSubtitle.NONE
}
- }
- } else {
- PermSubtitle.NONE
+ groupGrantStates[Category.ALLOWED]!!.add(
+ GroupUiInfo(groupName, isSystem, subtitle)
+ )
}
- groupGrantStates[Category.ALLOWED]!!.add(
- GroupUiInfo(groupName, isSystem, subtitle))
+ PermGrantState.PERMS_ALLOWED_ALWAYS ->
+ groupGrantStates[Category.ALLOWED]!!.add(
+ GroupUiInfo(groupName, isSystem, PermSubtitle.BACKGROUND)
+ )
+ PermGrantState.PERMS_ALLOWED_FOREGROUND_ONLY ->
+ groupGrantStates[Category.ALLOWED]!!.add(
+ GroupUiInfo(groupName, isSystem, PermSubtitle.FOREGROUND_ONLY)
+ )
+ PermGrantState.PERMS_DENIED ->
+ groupGrantStates[Category.DENIED]!!.add(
+ GroupUiInfo(groupName, isSystem)
+ )
+ PermGrantState.PERMS_ASK ->
+ groupGrantStates[Category.ASK]!!.add(
+ GroupUiInfo(groupName, isSystem)
+ )
}
- PermGrantState.PERMS_ALLOWED_ALWAYS -> groupGrantStates[
- Category.ALLOWED]!!.add(GroupUiInfo(groupName, isSystem,
- PermSubtitle.BACKGROUND))
- PermGrantState.PERMS_ALLOWED_FOREGROUND_ONLY -> groupGrantStates[
- Category.ALLOWED]!!.add(GroupUiInfo(groupName, isSystem,
- PermSubtitle.FOREGROUND_ONLY))
- PermGrantState.PERMS_DENIED -> groupGrantStates[Category.DENIED]!!.add(
- GroupUiInfo(groupName, isSystem))
- PermGrantState.PERMS_ASK -> groupGrantStates[Category.ASK]!!.add(
- GroupUiInfo(groupName, isSystem))
}
}
- }
- value = groupGrantStates
+ value = groupGrantStates
+ }
}
- }
// TODO 206455664: remove once issue is identified
fun logLiveDataState() {
- Log.i(LOG_TAG, "Overall liveData isStale: ${packagePermGroupsLiveData.isStale}, " +
+ Log.i(
+ LOG_TAG,
+ "Overall liveData isStale: ${packagePermGroupsLiveData.isStale}, " +
"isInitialized: ${packagePermGroupsLiveData.isInitialized}, " +
- "value: ${packagePermGroupsLiveData.value}")
- Log.i(LOG_TAG, "AutoRevoke liveData isStale: ${autoRevokeLiveData.isStale}, " +
+ "value: ${packagePermGroupsLiveData.value}"
+ )
+ Log.i(
+ LOG_TAG,
+ "AutoRevoke liveData isStale: ${autoRevokeLiveData.isStale}, " +
"isInitialized: ${autoRevokeLiveData.isInitialized}, " +
- "value: ${autoRevokeLiveData.value}")
- Log.i(LOG_TAG, "PackagePerms liveData isStale: ${packagePermsLiveData.isStale}, " +
+ "value: ${autoRevokeLiveData.value}"
+ )
+ Log.i(
+ LOG_TAG,
+ "PackagePerms liveData isStale: ${packagePermsLiveData.isStale}, " +
"isInitialized: ${packagePermsLiveData.isInitialized}, " +
- "value: ${packagePermsLiveData.value}")
- Log.i(LOG_TAG, "FullStorage liveData isStale: ${fullStoragePermsLiveData.isStale}, " +
+ "value: ${packagePermsLiveData.value}"
+ )
+ Log.i(
+ LOG_TAG,
+ "FullStorage liveData isStale: ${fullStoragePermsLiveData.isStale}, " +
"isInitialized: ${fullStoragePermsLiveData.isInitialized}, " +
- "value size: ${fullStoragePermsLiveData.value?.size}")
+ "value size: ${fullStoragePermsLiveData.value?.size}"
+ )
for ((group, liveData) in appPermGroupUiInfoLiveDatas) {
- Log.i(LOG_TAG, "$group ui liveData isStale: ${liveData.isStale}, " +
+ Log.i(
+ LOG_TAG,
+ "$group ui liveData isStale: ${liveData.isStale}, " +
"isInitialized: ${liveData.isInitialized}, " +
- "value size: ${liveData.value}")
+ "value size: ${liveData.value}"
+ )
}
}
@@ -233,26 +263,33 @@ class AppPermissionGroupsViewModel(
val lightPackageInfo = LightPackageInfoLiveData[packageName, user].getInitializedValue()
if (lightPackageInfo != null) {
- Log.i(LOG_TAG, "sessionId $sessionId setting auto revoke enabled to $enabled for" +
- "$packageName $user")
- val tag = if (enabled) {
- APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION__ACTION__SWITCH_ENABLED
- } else {
- APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION__ACTION__SWITCH_DISABLED
- }
+ Log.i(
+ LOG_TAG,
+ "sessionId $sessionId setting auto revoke enabled to $enabled for" +
+ "$packageName $user"
+ )
+ val tag =
+ if (enabled) {
+ APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION__ACTION__SWITCH_ENABLED
+ } else {
+ APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION__ACTION__SWITCH_DISABLED
+ }
PermissionControllerStatsLog.write(
- APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION, sessionId,
- lightPackageInfo.uid, packageName, tag)
-
- val mode = if (enabled) {
- MODE_ALLOWED
- } else {
- MODE_IGNORED
- }
+ APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION,
+ sessionId,
+ lightPackageInfo.uid,
+ packageName,
+ tag
+ )
+
+ val mode =
+ if (enabled) {
+ MODE_ALLOWED
+ } else {
+ MODE_IGNORED
+ }
aom.setUidMode(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, lightPackageInfo.uid, mode)
- if (isHibernationEnabled() &&
- SdkLevel.isAtLeastSv2() &&
- !enabled) {
+ if (isHibernationEnabled() && SdkLevel.isAtLeastSv2() && !enabled) {
// Only unhibernate on S_V2+ to have consistent toggle behavior w/ Settings
val ahm = app.getSystemService(AppHibernationManager::class.java)!!
ahm.setHibernatingForUser(packageName, false)
@@ -281,13 +318,17 @@ class AppPermissionGroupsViewModel(
return
}
- val aggregateDataFilterBeginDays = if (KotlinUtils.is7DayToggleEnabled())
- AGGREGATE_DATA_FILTER_BEGIN_DAYS_7 else AGGREGATE_DATA_FILTER_BEGIN_DAYS_1
+ val aggregateDataFilterBeginDays =
+ if (KotlinUtils.is7DayToggleEnabled()) AGGREGATE_DATA_FILTER_BEGIN_DAYS_7
+ else AGGREGATE_DATA_FILTER_BEGIN_DAYS_1
accessTime.clear()
- val filterTimeBeginMillis = max(System.currentTimeMillis() -
- TimeUnit.DAYS.toMillis(aggregateDataFilterBeginDays.toLong()),
- Instant.EPOCH.toEpochMilli())
+ val filterTimeBeginMillis =
+ max(
+ System.currentTimeMillis() -
+ TimeUnit.DAYS.toMillis(aggregateDataFilterBeginDays.toLong()),
+ Instant.EPOCH.toEpochMilli()
+ )
val numApps: Int = appPermissionUsages.size
for (appIndex in 0 until numApps) {
val appUsage: AppPermissionUsage = appPermissionUsages[appIndex]
@@ -307,96 +348,128 @@ class AppPermissionGroupsViewModel(
// We might have another AppPermissionUsage entry that's of the same packageName
// but with a different uid. In that case, we want to grab the max lastAccessTime
// as the last usage to show.
- lastAccessTime = Math.max(
+ lastAccessTime =
+ Math.max(
accessTime.getOrDefault(groupName, Instant.EPOCH.toEpochMilli()),
- lastAccessTime)
+ lastAccessTime
+ )
accessTime[groupName] = lastAccessTime
}
}
}
- fun getPreferenceSummary(groupInfo: GroupUiInfo, context: Context, lastAccessTime: Long?):
- String {
- val summaryTimestamp = Utils
- .getPermissionLastAccessSummaryTimestamp(
- lastAccessTime, context, groupInfo.groupName)
+ fun getPreferenceSummary(
+ groupInfo: GroupUiInfo,
+ context: Context,
+ lastAccessTime: Long?
+ ): String {
+ val summaryTimestamp =
+ Utils.getPermissionLastAccessSummaryTimestamp(
+ lastAccessTime,
+ context,
+ groupInfo.groupName
+ )
@AppPermsLastAccessType val lastAccessType: Int = summaryTimestamp.second
return when (groupInfo.subtitle) {
PermSubtitle.BACKGROUND ->
when (lastAccessType) {
- Utils.LAST_24H_CONTENT_PROVIDER -> context.getString(
- R.string.app_perms_content_provider_24h_background)
- Utils.LAST_7D_CONTENT_PROVIDER -> context.getString(
- R.string.app_perms_content_provider_7d_background)
- Utils.LAST_24H_SENSOR_TODAY -> context.getString(
+ Utils.LAST_24H_CONTENT_PROVIDER ->
+ context.getString(R.string.app_perms_content_provider_24h_background)
+ Utils.LAST_7D_CONTENT_PROVIDER ->
+ context.getString(R.string.app_perms_content_provider_7d_background)
+ Utils.LAST_24H_SENSOR_TODAY ->
+ context.getString(
R.string.app_perms_24h_access_background,
- summaryTimestamp.first)
- Utils.LAST_24H_SENSOR_YESTERDAY -> context.getString(
+ summaryTimestamp.first
+ )
+ Utils.LAST_24H_SENSOR_YESTERDAY ->
+ context.getString(
R.string.app_perms_24h_access_yest_background,
- summaryTimestamp.first)
- Utils.LAST_7D_SENSOR -> context.getString(
+ summaryTimestamp.first
+ )
+ Utils.LAST_7D_SENSOR ->
+ context.getString(
R.string.app_perms_7d_access_background,
- summaryTimestamp.third, summaryTimestamp.first)
- Utils.NOT_IN_LAST_7D -> context.getString(
- R.string.permission_subtitle_background)
- else -> context.getString(
- R.string.permission_subtitle_background)
+ summaryTimestamp.third,
+ summaryTimestamp.first
+ )
+ Utils.NOT_IN_LAST_7D ->
+ context.getString(R.string.permission_subtitle_background)
+ else -> context.getString(R.string.permission_subtitle_background)
}
PermSubtitle.MEDIA_ONLY ->
when (lastAccessType) {
- Utils.LAST_24H_CONTENT_PROVIDER -> context.getString(
- R.string.app_perms_content_provider_24h_media_only)
- Utils.LAST_7D_CONTENT_PROVIDER -> context.getString(
- R.string.app_perms_content_provider_7d_media_only)
- Utils.LAST_24H_SENSOR_TODAY -> context.getString(
+ Utils.LAST_24H_CONTENT_PROVIDER ->
+ context.getString(R.string.app_perms_content_provider_24h_media_only)
+ Utils.LAST_7D_CONTENT_PROVIDER ->
+ context.getString(R.string.app_perms_content_provider_7d_media_only)
+ Utils.LAST_24H_SENSOR_TODAY ->
+ context.getString(
R.string.app_perms_24h_access_media_only,
- summaryTimestamp.first)
- Utils.LAST_24H_SENSOR_YESTERDAY -> context.getString(
+ summaryTimestamp.first
+ )
+ Utils.LAST_24H_SENSOR_YESTERDAY ->
+ context.getString(
R.string.app_perms_24h_access_yest_media_only,
- summaryTimestamp.first)
- Utils.LAST_7D_SENSOR -> context.getString(
+ summaryTimestamp.first
+ )
+ Utils.LAST_7D_SENSOR ->
+ context.getString(
R.string.app_perms_7d_access_media_only,
- summaryTimestamp.third, summaryTimestamp.first)
- Utils.NOT_IN_LAST_7D -> context.getString(
- R.string.permission_subtitle_media_only)
+ summaryTimestamp.third,
+ summaryTimestamp.first
+ )
+ Utils.NOT_IN_LAST_7D ->
+ context.getString(R.string.permission_subtitle_media_only)
else -> context.getString(R.string.permission_subtitle_media_only)
}
PermSubtitle.ALL_FILES ->
when (lastAccessType) {
- Utils.LAST_24H_CONTENT_PROVIDER -> context.getString(
- R.string.app_perms_content_provider_24h_all_files)
- Utils.LAST_7D_CONTENT_PROVIDER -> context.getString(
- R.string.app_perms_content_provider_7d_all_files)
- Utils.LAST_24H_SENSOR_TODAY -> context.getString(
+ Utils.LAST_24H_CONTENT_PROVIDER ->
+ context.getString(R.string.app_perms_content_provider_24h_all_files)
+ Utils.LAST_7D_CONTENT_PROVIDER ->
+ context.getString(R.string.app_perms_content_provider_7d_all_files)
+ Utils.LAST_24H_SENSOR_TODAY ->
+ context.getString(
R.string.app_perms_24h_access_all_files,
- summaryTimestamp.first)
- Utils.LAST_24H_SENSOR_YESTERDAY -> context.getString(
+ summaryTimestamp.first
+ )
+ Utils.LAST_24H_SENSOR_YESTERDAY ->
+ context.getString(
R.string.app_perms_24h_access_yest_all_files,
- summaryTimestamp.first)
- Utils.LAST_7D_SENSOR -> context.getString(
+ summaryTimestamp.first
+ )
+ Utils.LAST_7D_SENSOR ->
+ context.getString(
R.string.app_perms_7d_access_all_files,
- summaryTimestamp.third, summaryTimestamp.first)
- Utils.NOT_IN_LAST_7D -> context.getString(
- R.string.permission_subtitle_all_files)
+ summaryTimestamp.third,
+ summaryTimestamp.first
+ )
+ Utils.NOT_IN_LAST_7D ->
+ context.getString(R.string.permission_subtitle_all_files)
else -> context.getString(R.string.permission_subtitle_all_files)
}
else ->
// PermSubtitle.FOREGROUND_ONLY should fall into this as well
when (lastAccessType) {
- Utils.LAST_24H_CONTENT_PROVIDER -> context.getString(
- R.string.app_perms_content_provider_24h)
- Utils.LAST_7D_CONTENT_PROVIDER -> context.getString(
- R.string.app_perms_content_provider_7d)
- Utils.LAST_24H_SENSOR_TODAY -> context.getString(
- R.string.app_perms_24h_access,
- summaryTimestamp.first)
- Utils.LAST_24H_SENSOR_YESTERDAY -> context.getString(
+ Utils.LAST_24H_CONTENT_PROVIDER ->
+ context.getString(R.string.app_perms_content_provider_24h)
+ Utils.LAST_7D_CONTENT_PROVIDER ->
+ context.getString(R.string.app_perms_content_provider_7d)
+ Utils.LAST_24H_SENSOR_TODAY ->
+ context.getString(R.string.app_perms_24h_access, summaryTimestamp.first)
+ Utils.LAST_24H_SENSOR_YESTERDAY ->
+ context.getString(
R.string.app_perms_24h_access_yest,
- summaryTimestamp.first)
- Utils.LAST_7D_SENSOR -> context.getString(
+ summaryTimestamp.first
+ )
+ Utils.LAST_7D_SENSOR ->
+ context.getString(
R.string.app_perms_7d_access,
- summaryTimestamp.third, summaryTimestamp.first)
+ summaryTimestamp.third,
+ summaryTimestamp.first
+ )
Utils.NOT_IN_LAST_7D -> ""
else -> ""
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
index 99b40d8a7..cc29acbd7 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
@@ -20,6 +20,7 @@ package com.android.permissioncontroller.permission.ui.model
import android.Manifest
import android.Manifest.permission.ACCESS_COARSE_LOCATION
import android.Manifest.permission.ACCESS_FINE_LOCATION
+import android.Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
import android.Manifest.permission_group.READ_MEDIA_VISUAL
import android.annotation.SuppressLint
import android.app.Activity
@@ -28,19 +29,14 @@ import android.app.AppOpsManager.MODE_ALLOWED
import android.app.AppOpsManager.MODE_ERRORED
import android.app.AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE
import android.app.Application
-import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.UserHandle
-import android.provider.MediaStore
import android.util.Log
-import androidx.activity.result.ActivityResultLauncher
-import androidx.activity.result.contract.ActivityResultContract
import androidx.annotation.ChecksSdkIntAtLeast
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
-import androidx.core.util.Consumer
import androidx.fragment.app.Fragment
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
@@ -56,14 +52,13 @@ import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.data.FullStoragePermissionAppsLiveData
import com.android.permissioncontroller.permission.data.FullStoragePermissionAppsLiveData.FullStoragePackageState
import com.android.permissioncontroller.permission.data.LightAppPermGroupLiveData
-import com.android.permissioncontroller.permission.data.v34.SafetyLabelInfoLiveData
import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData
import com.android.permissioncontroller.permission.data.get
+import com.android.permissioncontroller.permission.data.v34.SafetyLabelInfoLiveData
import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
import com.android.permissioncontroller.permission.model.livedatatypes.LightPermission
import com.android.permissioncontroller.permission.service.PermissionChangeStorageImpl
import com.android.permissioncontroller.permission.service.v33.PermissionDecisionStorageImpl
-import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogArgs
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType.ALLOW
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType.ALLOW_ALWAYS
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType.ALLOW_FOREGROUND
@@ -73,12 +68,14 @@ import com.android.permissioncontroller.permission.ui.model.AppPermissionViewMod
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType.DENY_FOREGROUND
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType.LOCATION_ACCURACY
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType.SELECT_PHOTOS
+import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogArgs
import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleActivity
import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleActivity.EXTRA_SHOULD_SHOW_SETTINGS_SECTION
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils.getDefaultPrecision
import com.android.permissioncontroller.permission.utils.KotlinUtils.isLocationAccuracyEnabled
import com.android.permissioncontroller.permission.utils.KotlinUtils.isPhotoPickerPromptEnabled
+import com.android.permissioncontroller.permission.utils.KotlinUtils.openPhotoPickerForApp
import com.android.permissioncontroller.permission.utils.LocationUtils
import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.PermissionMapping.getPartialStorageGrantPermissionsForGroup
@@ -112,7 +109,6 @@ class AppPermissionViewModel(
companion object {
private val LOG_TAG = AppPermissionViewModel::class.java.simpleName
private const val DEVICE_PROFILE_ROLE_PREFIX = "android.app.role"
- const val PHOTO_PICKER_REQUEST_CODE = 1
}
interface ConfirmDialogShowingFragment {
@@ -134,15 +130,16 @@ class AppPermissionViewModel(
GRANT_BOTH(GRANT_FOREGROUND.value or GRANT_BACKGROUND.value),
REVOKE_BOTH(REVOKE_FOREGROUND.value or REVOKE_BACKGROUND.value),
GRANT_FOREGROUND_ONLY(GRANT_FOREGROUND.value or REVOKE_BACKGROUND.value),
- GRANT_All_FILE_ACCESS(1 shl 4),
+ GRANT_ALL_FILE_ACCESS(1 shl 4),
GRANT_FINE_LOCATION(1 shl 5),
REVOKE_FINE_LOCATION(1 shl 6),
GRANT_STORAGE_SUPERGROUP(1 shl 7),
REVOKE_STORAGE_SUPERGROUP(1 shl 8),
GRANT_STORAGE_SUPERGROUP_CONFIRMED(
- GRANT_STORAGE_SUPERGROUP.value or GRANT_FOREGROUND.value),
+ GRANT_STORAGE_SUPERGROUP.value or GRANT_FOREGROUND.value
+ ),
REVOKE_STORAGE_SUPERGROUP_CONFIRMED(REVOKE_STORAGE_SUPERGROUP.value or REVOKE_BOTH.value),
- PHOTOS_SELECTED( 1 shl 9);
+ PHOTOS_SELECTED(1 shl 9);
infix fun andValue(other: ChangeRequest): Int {
return value and other.value
@@ -158,89 +155,86 @@ class AppPermissionViewModel(
DENY(5),
DENY_FOREGROUND(6),
LOCATION_ACCURACY(7),
- SELECT_PHOTOS( 8);
+ SELECT_PHOTOS(8)
}
private val isStorageAndLessThanT =
permGroupName == Manifest.permission_group.STORAGE && !SdkLevel.isAtLeastT()
private var hasConfirmedRevoke = false
private var lightAppPermGroup: LightAppPermGroup? = null
- private var photoPickerLauncher: ActivityResultLauncher<Unit>? = null
- private var photoPickerResultConsumer: Consumer<Int>? = null
private val mediaStorageSupergroupPermGroups = mutableMapOf<String, LightAppPermGroup>()
/* Whether the current ViewModel is Location permission with both Coarse and Fine */
private var shouldShowLocationAccuracy: Boolean? = null
- /**
- * A livedata which determines which detail string, if any, should be shown
- */
+ /** A livedata which determines which detail string, if any, should be shown */
val detailResIdLiveData = MutableLiveData<Pair<Int, Int?>>()
- /**
- * A livedata which stores the device admin, if there is one
- */
+ /** A livedata which stores the device admin, if there is one */
val showAdminSupportLiveData = MutableLiveData<RestrictedLockUtils.EnforcedAdmin>()
- /**
- * A livedata for determining the display state of safety label information
- */
- val showPermissionRationaleLiveData = object : SmartUpdateMediatorLiveData<Boolean>() {
- private val safetyLabelInfoLiveData = if (SdkLevel.isAtLeastU()) {
- SafetyLabelInfoLiveData[packageName, user]
- } else {
- null
- }
+ /** A livedata for determining the display state of safety label information */
+ val showPermissionRationaleLiveData =
+ object : SmartUpdateMediatorLiveData<Boolean>() {
+ private val safetyLabelInfoLiveData =
+ if (SdkLevel.isAtLeastU()) {
+ SafetyLabelInfoLiveData[packageName, user]
+ } else {
+ null
+ }
- init {
- if (safetyLabelInfoLiveData != null &&
- PermissionMapping.isSafetyLabelAwarePermissionGroup(permGroupName)) {
- addSource(safetyLabelInfoLiveData) { update() }
- } else {
- value = false
+ init {
+ if (
+ safetyLabelInfoLiveData != null &&
+ PermissionMapping.isSafetyLabelAwarePermissionGroup(permGroupName)
+ ) {
+ addSource(safetyLabelInfoLiveData) { update() }
+ } else {
+ value = false
+ }
}
- }
- override fun onUpdate() {
- if (safetyLabelInfoLiveData != null && safetyLabelInfoLiveData.isStale) {
- return
- }
+ override fun onUpdate() {
+ if (safetyLabelInfoLiveData != null && safetyLabelInfoLiveData.isStale) {
+ return
+ }
- val safetyLabel = safetyLabelInfoLiveData?.value?.safetyLabel
- if (safetyLabel == null) {
- value = false
- return
- }
+ val safetyLabel = safetyLabelInfoLiveData?.value?.safetyLabel
+ if (safetyLabel == null) {
+ value = false
+ return
+ }
- value = SafetyLabelUtils.getSafetyLabelSharingPurposesForGroup(
- safetyLabel, permGroupName).any()
+ value =
+ SafetyLabelUtils.getSafetyLabelSharingPurposesForGroup(
+ safetyLabel,
+ permGroupName
+ )
+ .any()
+ }
}
- }
- /**
- * A livedata which determines which detail string, if any, should be shown
- */
- val fullStorageStateLiveData = object : SmartUpdateMediatorLiveData<FullStoragePackageState>() {
- init {
- if (isStorageAndLessThanT) {
- addSource(FullStoragePermissionAppsLiveData) {
- update()
+ /** A livedata which determines which detail string, if any, should be shown */
+ val fullStorageStateLiveData =
+ object : SmartUpdateMediatorLiveData<FullStoragePackageState>() {
+ init {
+ if (isStorageAndLessThanT) {
+ addSource(FullStoragePermissionAppsLiveData) { update() }
+ } else {
+ value = null
}
- } else {
- value = null
}
- }
- override fun onUpdate() {
- for (state in FullStoragePermissionAppsLiveData.value ?: return) {
- if (state.packageName == packageName && state.user == user) {
- value = state
- return
+ override fun onUpdate() {
+ for (state in FullStoragePermissionAppsLiveData.value ?: return) {
+ if (state.packageName == packageName && state.user == user) {
+ value = state
+ return
+ }
}
+ value = null
+ return
}
- value = null
- return
}
- }
data class ButtonState(
var isChecked: Boolean,
@@ -251,182 +245,201 @@ class AppPermissionViewModel(
constructor() : this(false, true, false, null)
}
- /**
- * A livedata which computes the state of the radio buttons
- */
- val buttonStateLiveData = object :
- SmartUpdateMediatorLiveData<@JvmSuppressWildcards Map<ButtonType, ButtonState>>() {
+ /** A livedata which computes the state of the radio buttons */
+ val buttonStateLiveData =
+ object : SmartUpdateMediatorLiveData<@JvmSuppressWildcards Map<ButtonType, ButtonState>>() {
- private val appPermGroupLiveData = LightAppPermGroupLiveData[packageName, permGroupName,
- user]
- private val mediaStorageSupergroupLiveData =
- mutableMapOf<String, LightAppPermGroupLiveData>()
+ private val appPermGroupLiveData =
+ LightAppPermGroupLiveData[packageName, permGroupName, user]
+ private val mediaStorageSupergroupLiveData =
+ mutableMapOf<String, LightAppPermGroupLiveData>()
- init {
+ init {
- addSource(appPermGroupLiveData) { appPermGroup ->
- lightAppPermGroup = appPermGroup
- if (permGroupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS) {
- onMediaPermGroupUpdate(permGroupName, appPermGroup)
- }
- if (appPermGroupLiveData.isInitialized && appPermGroup == null) {
- value = null
- } else if (appPermGroup != null) {
- if (isStorageAndLessThanT && !fullStorageStateLiveData.isInitialized) {
- return@addSource
+ addSource(appPermGroupLiveData) { appPermGroup ->
+ lightAppPermGroup = appPermGroup
+ if (permGroupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS) {
+ onMediaPermGroupUpdate(permGroupName, appPermGroup)
+ }
+ if (appPermGroupLiveData.isInitialized && appPermGroup == null) {
+ value = null
+ } else if (appPermGroup != null) {
+ if (isStorageAndLessThanT && !fullStorageStateLiveData.isInitialized) {
+ return@addSource
+ }
+ update()
}
- update()
}
- }
- if (isStorageAndLessThanT) {
- addSource(fullStorageStateLiveData) {
- update()
+ if (isStorageAndLessThanT) {
+ addSource(fullStorageStateLiveData) { update() }
}
- }
- if (permGroupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS) {
- for (permGroupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS) {
- val liveData = LightAppPermGroupLiveData[packageName, permGroupName, user]
- mediaStorageSupergroupLiveData[permGroupName] = liveData
- }
- for (permGroupName in mediaStorageSupergroupLiveData.keys) {
- val liveData = mediaStorageSupergroupLiveData[permGroupName]!!
- addSource(liveData) { permGroup ->
- onMediaPermGroupUpdate(permGroupName, permGroup)
+ if (permGroupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS) {
+ for (permGroupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS) {
+ val liveData = LightAppPermGroupLiveData[packageName, permGroupName, user]
+ mediaStorageSupergroupLiveData[permGroupName] = liveData
+ }
+ for (permGroupName in mediaStorageSupergroupLiveData.keys) {
+ val liveData = mediaStorageSupergroupLiveData[permGroupName]!!
+ addSource(liveData) { permGroup ->
+ onMediaPermGroupUpdate(permGroupName, permGroup)
+ }
}
}
- }
- addSource(showPermissionRationaleLiveData) {
- update()
- }
- }
-
- private fun onMediaPermGroupUpdate(permGroupName: String, permGroup: LightAppPermGroup?) {
- if (permGroup == null) {
- mediaStorageSupergroupPermGroups.remove(permGroupName)
- value = null
- } else {
- mediaStorageSupergroupPermGroups[permGroupName] = permGroup
- update()
+ addSource(showPermissionRationaleLiveData) { update() }
}
- }
- override fun onUpdate() {
- val group = appPermGroupLiveData.value ?: return
- for (mediaGroupLiveData in mediaStorageSupergroupLiveData.values) {
- if (!mediaGroupLiveData.isInitialized) {
- return
+ private fun onMediaPermGroupUpdate(
+ permGroupName: String,
+ permGroup: LightAppPermGroup?
+ ) {
+ if (permGroup == null) {
+ mediaStorageSupergroupPermGroups.remove(permGroupName)
+ value = null
+ } else {
+ mediaStorageSupergroupPermGroups[permGroupName] = permGroup
+ update()
}
}
- if (!showPermissionRationaleLiveData.isInitialized) {
- return
- }
-
- val admin = RestrictedLockUtils.getProfileOrDeviceOwner(app, user)
-
- val allowedState = ButtonState()
- val allowedAlwaysState = ButtonState()
- val allowedForegroundState = ButtonState()
- val askOneTimeState = ButtonState()
- val askState = ButtonState()
- val deniedState = ButtonState()
- val deniedForegroundState = ButtonState()
- val selectState = ButtonState()
-
- askOneTimeState.isShown = group.foreground.isGranted && group.isOneTime
- askState.isShown = PermissionMapping.supportsOneTimeGrant(permGroupName) &&
- !(group.foreground.isGranted && group.isOneTime)
- deniedState.isShown = true
-
- if (group.hasPermWithBackgroundMode) {
- // Background / Foreground / Deny case
- allowedForegroundState.isShown = true
- if (group.hasBackgroundGroup) {
- allowedAlwaysState.isShown = true
+ override fun onUpdate() {
+ val group = appPermGroupLiveData.value ?: return
+ for (mediaGroupLiveData in mediaStorageSupergroupLiveData.values) {
+ if (!mediaGroupLiveData.isInitialized) {
+ return
+ }
}
- allowedAlwaysState.isChecked = group.background.isGranted &&
- group.foreground.isGranted && !group.background.isOneTime
- allowedForegroundState.isChecked = group.foreground.isGranted &&
- (!group.background.isGranted || group.background.isOneTime) &&
- !group.foreground.isOneTime
- askState.isChecked = !group.foreground.isGranted && group.isOneTime
- askOneTimeState.isChecked = group.foreground.isGranted && group.isOneTime
- askOneTimeState.isShown = askOneTimeState.isChecked
- deniedState.isChecked = !group.foreground.isGranted && !group.isOneTime
- if (applyFixToForegroundBackground(group, group.foreground.isSystemFixed,
- group.background.isSystemFixed, allowedAlwaysState,
- allowedForegroundState, askState, deniedState,
- deniedForegroundState) ||
- applyFixToForegroundBackground(group, group.foreground.isPolicyFixed,
- group.background.isPolicyFixed, allowedAlwaysState,
- allowedForegroundState, askState, deniedState,
- deniedForegroundState)) {
- showAdminSupportLiveData.value = admin
- val detailId = getDetailResIdForFixedByPolicyPermissionGroup(group,
- admin != null)
- if (detailId != 0) {
- detailResIdLiveData.value = detailId to null
- }
- } else if (Utils.areGroupPermissionsIndividuallyControlled(app, permGroupName)) {
- val detailId = getIndividualPermissionDetailResId(group)
- detailResIdLiveData.value = detailId.first to detailId.second
+ if (!showPermissionRationaleLiveData.isInitialized) {
+ return
}
- } else if (KotlinUtils.isPhotoPickerPromptEnabled() &&
- group.permGroupName == READ_MEDIA_VISUAL &&
- group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.TIRAMISU) {
- // Allow / Select Photos / Deny case
- allowedState.isShown = true
+
+ val admin = RestrictedLockUtils.getProfileOrDeviceOwner(app, user)
+
+ val allowedState = ButtonState()
+ val allowedAlwaysState = ButtonState()
+ val allowedForegroundState = ButtonState()
+ val askOneTimeState = ButtonState()
+ val askState = ButtonState()
+ val deniedState = ButtonState()
+ val deniedForegroundState = ButtonState()
+ val selectState = ButtonState()
+
+ askOneTimeState.isShown = group.foreground.isGranted && group.isOneTime
+ askState.isShown =
+ PermissionMapping.supportsOneTimeGrant(permGroupName) &&
+ !(group.foreground.isGranted && group.isOneTime)
deniedState.isShown = true
- selectState.isShown = true
- deniedState.isChecked = !group.isGranted
- selectState.isChecked = isPartialStorageGrant(group)
- allowedState.isChecked = group.isGranted && !isPartialStorageGrant(group)
- } else {
- // Allow / Deny case
- allowedState.isShown = true
-
- allowedState.isChecked = group.foreground.isGranted && !group.foreground.isOneTime
- askState.isChecked = !group.foreground.isGranted && group.isOneTime
- askOneTimeState.isChecked = group.foreground.isGranted && group.isOneTime
- askOneTimeState.isShown = askOneTimeState.isChecked
- deniedState.isChecked = !group.foreground.isGranted && !group.isOneTime
-
- if (group.foreground.isPolicyFixed || group.foreground.isSystemFixed) {
- allowedState.isEnabled = false
- askState.isEnabled = false
- deniedState.isEnabled = false
- showAdminSupportLiveData.value = admin
- val detailId = getDetailResIdForFixedByPolicyPermissionGroup(group,
- admin != null)
- if (detailId != 0) {
- detailResIdLiveData.value = detailId to null
+ if (group.hasPermWithBackgroundMode) {
+ // Background / Foreground / Deny case
+ allowedForegroundState.isShown = true
+ if (group.hasBackgroundGroup) {
+ allowedAlwaysState.isShown = true
+ }
+
+ allowedAlwaysState.isChecked =
+ group.background.isGranted &&
+ group.foreground.isGranted &&
+ !group.background.isOneTime
+ allowedForegroundState.isChecked =
+ group.foreground.isGranted &&
+ (!group.background.isGranted || group.background.isOneTime) &&
+ !group.foreground.isOneTime
+ askState.isChecked = !group.foreground.isGranted && group.isOneTime
+ askOneTimeState.isChecked = group.foreground.isGranted && group.isOneTime
+ askOneTimeState.isShown = askOneTimeState.isChecked
+ deniedState.isChecked = !group.foreground.isGranted && !group.isOneTime
+ if (
+ applyFixToForegroundBackground(
+ group,
+ group.foreground.isSystemFixed,
+ group.background.isSystemFixed,
+ allowedAlwaysState,
+ allowedForegroundState,
+ askState,
+ deniedState,
+ deniedForegroundState
+ ) ||
+ applyFixToForegroundBackground(
+ group,
+ group.foreground.isPolicyFixed,
+ group.background.isPolicyFixed,
+ allowedAlwaysState,
+ allowedForegroundState,
+ askState,
+ deniedState,
+ deniedForegroundState
+ )
+ ) {
+ showAdminSupportLiveData.value = admin
+ val detailId =
+ getDetailResIdForFixedByPolicyPermissionGroup(group, admin != null)
+ if (detailId != 0) {
+ detailResIdLiveData.value = detailId to null
+ }
+ } else if (
+ Utils.areGroupPermissionsIndividuallyControlled(app, permGroupName)
+ ) {
+ val detailId = getIndividualPermissionDetailResId(group)
+ detailResIdLiveData.value = detailId.first to detailId.second
+ }
+ } else if (
+ group.permGroupName == READ_MEDIA_VISUAL &&
+ shouldShowPhotoPickerPromptForApp(group)
+ ) {
+ // Allow / Select Photos / Deny case
+ allowedState.isShown = true
+ deniedState.isShown = true
+ selectState.isShown = true
+
+ deniedState.isChecked = !group.isGranted
+ selectState.isChecked = isPartialStorageGrant(group)
+ allowedState.isChecked = group.isGranted && !isPartialStorageGrant(group)
+ } else {
+ // Allow / Deny case
+ allowedState.isShown = true
+
+ allowedState.isChecked =
+ group.foreground.isGranted && !group.foreground.isOneTime
+ askState.isChecked = !group.foreground.isGranted && group.isOneTime
+ askOneTimeState.isChecked = group.foreground.isGranted && group.isOneTime
+ askOneTimeState.isShown = askOneTimeState.isChecked
+ deniedState.isChecked = !group.foreground.isGranted && !group.isOneTime
+
+ if (group.foreground.isPolicyFixed || group.foreground.isSystemFixed) {
+ allowedState.isEnabled = false
+ askState.isEnabled = false
+ deniedState.isEnabled = false
+ showAdminSupportLiveData.value = admin
+ val detailId =
+ getDetailResIdForFixedByPolicyPermissionGroup(group, admin != null)
+ if (detailId != 0) {
+ detailResIdLiveData.value = detailId to null
+ }
+ }
+ if (isForegroundGroupSpecialCase(permGroupName)) {
+ allowedForegroundState.isShown = true
+ allowedState.isShown = false
+ allowedForegroundState.isChecked = allowedState.isChecked
+ allowedForegroundState.isEnabled = allowedState.isEnabled
}
}
- if (isForegroundGroupSpecialCase(permGroupName)) {
- allowedForegroundState.isShown = true
- allowedState.isShown = false
- allowedForegroundState.isChecked = allowedState.isChecked
- allowedForegroundState.isEnabled = allowedState.isEnabled
+ if (group.packageInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+ // Pre-M app's can't ask for runtime permissions
+ askState.isShown = false
+ deniedState.isChecked = askState.isChecked || deniedState.isChecked
+ deniedForegroundState.isChecked =
+ askState.isChecked || deniedForegroundState.isChecked
}
- }
- if (group.packageInfo.targetSdkVersion < Build.VERSION_CODES.M) {
- // Pre-M app's can't ask for runtime permissions
- askState.isShown = false
- deniedState.isChecked = askState.isChecked || deniedState.isChecked
- deniedForegroundState.isChecked = askState.isChecked ||
- deniedForegroundState.isChecked
- }
- val storageState = fullStorageStateLiveData.value
- if (isStorageAndLessThanT && storageState?.isLegacy != true) {
- val allowedAllFilesState = allowedAlwaysState
- val allowedMediaOnlyState = allowedForegroundState
- if (storageState != null) {
+ val storageState = fullStorageStateLiveData.value
+ if (isStorageAndLessThanT && storageState?.isLegacy != true) {
+ val allowedAllFilesState = allowedAlwaysState
+ val allowedMediaOnlyState = allowedForegroundState
+ if (storageState != null) {
// Set up the tri state permission for storage
allowedAllFilesState.isEnabled = allowedState.isEnabled
allowedAllFilesState.isShown = true
@@ -434,62 +447,63 @@ class AppPermissionViewModel(
allowedAllFilesState.isChecked = true
deniedState.isChecked = false
}
- } else {
- allowedAllFilesState.isEnabled = false
- allowedAllFilesState.isShown = false
+ } else {
+ allowedAllFilesState.isEnabled = false
+ allowedAllFilesState.isShown = false
+ }
+ allowedMediaOnlyState.isShown = true
+ allowedMediaOnlyState.isEnabled = allowedState.isEnabled
+ allowedMediaOnlyState.isChecked =
+ allowedState.isChecked && storageState?.isGranted != true
+ allowedState.isChecked = false
+ allowedState.isShown = false
}
- allowedMediaOnlyState.isShown = true
- allowedMediaOnlyState.isEnabled = allowedState.isEnabled
- allowedMediaOnlyState.isChecked = allowedState.isChecked &&
- storageState?.isGranted != true
- allowedState.isChecked = false
- allowedState.isShown = false
- }
- if (shouldShowLocationAccuracy == null) {
- shouldShowLocationAccuracy = isLocationAccuracyEnabled() &&
- group.permissions.containsKey(ACCESS_FINE_LOCATION)
- }
- val locationAccuracyState = ButtonState(isFineLocationChecked(group),
- true, false, null)
- if (shouldShowLocationAccuracy == true && !deniedState.isChecked) {
- locationAccuracyState.isShown = true
- }
- if (group.foreground.isSystemFixed || group.foreground.isPolicyFixed) {
- locationAccuracyState.isEnabled = false
- }
+ if (shouldShowLocationAccuracy == null) {
+ shouldShowLocationAccuracy =
+ isLocationAccuracyEnabled() &&
+ group.permissions.containsKey(ACCESS_FINE_LOCATION)
+ }
+ val locationAccuracyState =
+ ButtonState(isFineLocationChecked(group), true, false, null)
+ if (shouldShowLocationAccuracy == true && !deniedState.isChecked) {
+ locationAccuracyState.isShown = true
+ }
+ if (group.foreground.isSystemFixed || group.foreground.isPolicyFixed) {
+ locationAccuracyState.isEnabled = false
+ }
- if (value == null) {
- logAppPermissionFragmentViewed()
- }
+ if (value == null) {
+ logAppPermissionFragmentViewed()
+ }
- value = mapOf(
- ALLOW to allowedState, ALLOW_ALWAYS to allowedAlwaysState,
- ALLOW_FOREGROUND to allowedForegroundState, ASK_ONCE to askOneTimeState,
- ASK to askState, DENY to deniedState, DENY_FOREGROUND to deniedForegroundState,
- LOCATION_ACCURACY to locationAccuracyState, SELECT_PHOTOS to selectState)
+ value =
+ mapOf(
+ ALLOW to allowedState,
+ ALLOW_ALWAYS to allowedAlwaysState,
+ ALLOW_FOREGROUND to allowedForegroundState,
+ ASK_ONCE to askOneTimeState,
+ ASK to askState,
+ DENY to deniedState,
+ DENY_FOREGROUND to deniedForegroundState,
+ LOCATION_ACCURACY to locationAccuracyState,
+ SELECT_PHOTOS to selectState
+ )
+ }
}
- }
- fun registerPhotoPickerResultIfNeeded(fragment: Fragment) {
- if (permGroupName != READ_MEDIA_VISUAL) {
- return
+ private fun shouldShowPhotoPickerPromptForApp(group: LightAppPermGroup): Boolean {
+ if (
+ !isPhotoPickerPromptEnabled() ||
+ group.packageInfo.targetSdkVersion < Build.VERSION_CODES.TIRAMISU
+ ) {
+ return false
}
- photoPickerLauncher = fragment.registerForActivityResult(
- object : ActivityResultContract<Unit, Int>() {
- override fun parseResult(resultCode: Int, intent: Intent?): Int {
- return resultCode
- }
-
- override fun createIntent(context: Context, input: Unit): Intent {
- return Intent(MediaStore.ACTION_USER_SELECT_IMAGES_FOR_APP)
- .putExtra(Intent.EXTRA_UID, lightAppPermGroup?.packageInfo?.uid)
- .setType(KotlinUtils.getMimeTypeForPermissions(
- lightAppPermGroup?.foregroundPermNames ?: emptyList()))
- }
- }) { result ->
- photoPickerResultConsumer?.accept(result)
+ if (group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ return true
}
+ val userSelectedPerm = group.permissions[READ_MEDIA_VISUAL_USER_SELECTED] ?: return false
+ return !userSelectedPerm.isImplicit
}
private fun isFineLocationChecked(group: LightAppPermGroup): Boolean {
@@ -501,11 +515,13 @@ class AppPermissionViewModel(
// 2. Else if FINE or COARSE have the isSelectedLocationAccuracy flag set, then return
// true if FINE isSelectedLocationAccuracy is set.
// 3. Else, return default precision from device config.
- return if (fineLocation.isGrantedIncludingAppOp ||
- coarseLocation.isGrantedIncludingAppOp) {
+ return if (
+ fineLocation.isGrantedIncludingAppOp || coarseLocation.isGrantedIncludingAppOp
+ ) {
fineLocation.isGrantedIncludingAppOp
- } else if (fineLocation.isSelectedLocationAccuracy ||
- coarseLocation.isSelectedLocationAccuracy) {
+ } else if (
+ fineLocation.isSelectedLocationAccuracy || coarseLocation.isSelectedLocationAccuracy
+ ) {
fineLocation.isSelectedLocationAccuracy
} else {
getDefaultPrecision()
@@ -517,7 +533,7 @@ class AppPermissionViewModel(
// TODO evanseverson: Actually change mic/camera to be a foreground only permission
private fun isForegroundGroupSpecialCase(permissionGroupName: String): Boolean {
return permissionGroupName.equals(Manifest.permission_group.CAMERA) ||
- permissionGroupName.equals(Manifest.permission_group.MICROPHONE)
+ permissionGroupName.equals(Manifest.permission_group.MICROPHONE)
}
/**
@@ -608,10 +624,12 @@ class AppPermissionViewModel(
logAppPermissionFragmentActionReportedForPermissionGroup(
/* changeId= */ Random().nextLong(),
group,
- APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__PERMISSION_RATIONALE)
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__PERMISSION_RATIONALE
+ )
}
- val intent = Intent(activity, PermissionRationaleActivity::class.java).apply {
+ val intent =
+ Intent(activity, PermissionRationaleActivity::class.java).apply {
putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName)
putExtra(Constants.EXTRA_SESSION_ID, sessionId)
@@ -622,6 +640,7 @@ class AppPermissionViewModel(
/**
* Navigate to either the App Permission Groups screen, or the Permission Apps Screen.
+ *
* @param fragment The current fragment
* @param action The action to be taken
* @param args The arguments to pass to the fragment
@@ -635,26 +654,29 @@ class AppPermissionViewModel(
fragment.findNavController().navigateSafe(actionId, args)
}
+ fun openPhotoPicker(fragment: Fragment) {
+ val appPermGroup = lightAppPermGroup ?: return
+ openPhotoPickerForApp(fragment.requireActivity(), appPermGroup.packageInfo.uid,
+ appPermGroup.foregroundPermNames, 0)
+ }
+
/**
* Request to grant/revoke permissions group.
*
* Does <u>not</u> handle:
- *
- * * Individually granted permissions
- * * Permission groups with background permissions
+ * * Individually granted permissions
+ * * Permission groups with background permissions
*
* <u>Does</u> handle:
- *
- * * Default grant permissions
+ * * Default grant permissions
*
* @param setOneTime Whether or not to set this permission as one time
* @param fragment The fragment calling this method
* @param defaultDeny The system which will show the default deny dialog. Usually the same as
- * the fragment.
+ * the fragment.
* @param changeRequest Which permission group (foreground/background/both) should be changed
* @param buttonClicked button which was pressed to initiate the change, one of
- * AppPermissionFragmentActionReported.button_pressed constants
- *
+ * AppPermissionFragmentActionReported.button_pressed constants
* @return The dialogue to show, if applicable, or if the request was processed.
*/
fun requestChange(
@@ -685,8 +707,12 @@ class AppPermissionViewModel(
if (changeRequest == ChangeRequest.REVOKE_FINE_LOCATION) {
if (!group.isOneTime) {
- val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group,
- filterPermissions = listOf(ACCESS_FINE_LOCATION))
+ val newGroup =
+ KotlinUtils.revokeForegroundRuntimePermissions(
+ app,
+ group,
+ filterPermissions = listOf(ACCESS_FINE_LOCATION)
+ )
logPermissionChanges(group, newGroup, buttonClicked)
}
KotlinUtils.setFlagsWhenLocationAccuracyChanged(app, group, false)
@@ -696,10 +722,18 @@ class AppPermissionViewModel(
if (changeRequest == ChangeRequest.PHOTOS_SELECTED) {
val partialGrantPerms = getPartialStorageGrantPermissionsForGroup(group)
val nonSelectedPerms = group.permissions.keys.filter { it !in partialGrantPerms }
- var newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group,
- filterPermissions = nonSelectedPerms)
- newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, newGroup,
- filterPermissions = partialGrantPerms.toList())
+ var newGroup =
+ KotlinUtils.revokeForegroundRuntimePermissions(
+ app,
+ group,
+ filterPermissions = nonSelectedPerms
+ )
+ newGroup =
+ KotlinUtils.grantForegroundRuntimePermissions(
+ app,
+ newGroup,
+ filterPermissions = partialGrantPerms.toList()
+ )
logPermissionChanges(group, newGroup, buttonClicked)
return
}
@@ -713,27 +747,31 @@ class AppPermissionViewModel(
var showCDMWarning = false
if (shouldRevokeForeground && wasForegroundGranted) {
- showDefaultDenyDialog = (group.foreground.isGrantedByDefault ||
+ showDefaultDenyDialog =
+ (group.foreground.isGrantedByDefault ||
!group.supportsRuntimePerms ||
group.hasInstallToRuntimeSplit)
- showGrantedByDefaultWarning = showGrantedByDefaultWarning ||
- group.foreground.isGrantedByDefault
+ showGrantedByDefaultWarning =
+ showGrantedByDefaultWarning || group.foreground.isGrantedByDefault
showCDMWarning = showCDMWarning || group.foreground.isGrantedByRole
}
if (shouldRevokeBackground && wasBackgroundGranted) {
- showDefaultDenyDialog = showDefaultDenyDialog ||
+ showDefaultDenyDialog =
+ showDefaultDenyDialog ||
group.background.isGrantedByDefault ||
!group.supportsRuntimePerms ||
group.hasInstallToRuntimeSplit
- showGrantedByDefaultWarning = showGrantedByDefaultWarning ||
- group.background.isGrantedByDefault
+ showGrantedByDefaultWarning =
+ showGrantedByDefaultWarning || group.background.isGrantedByDefault
showCDMWarning = showCDMWarning || group.background.isGrantedByRole
}
if (showCDMWarning) {
// Refine showCDMWarning to only trigger for apps holding a device profile role
- val heldRoles = context.getSystemService(android.app.role.RoleManager::class.java)
+ val heldRoles =
+ context
+ .getSystemService(android.app.role.RoleManager::class.java)
.getHeldRolesFromController(packageName)
val heldProfiles = heldRoles.filter { it.startsWith(DEVICE_PROFILE_ROLE_PREFIX) }
showCDMWarning = showCDMWarning && heldProfiles.isNotEmpty()
@@ -743,14 +781,24 @@ class AppPermissionViewModel(
if (group.permGroupName == Manifest.permission_group.STORAGE) {
showDefaultDenyDialog = false
} else if (changeRequest == ChangeRequest.GRANT_FOREGROUND) {
- showMediaConfirmDialog(setOneTime, defaultDeny,
- ChangeRequest.GRANT_STORAGE_SUPERGROUP, buttonClicked, group.permGroupName,
- group.packageInfo.targetSdkVersion)
+ showMediaConfirmDialog(
+ setOneTime,
+ defaultDeny,
+ ChangeRequest.GRANT_STORAGE_SUPERGROUP,
+ buttonClicked,
+ group.permGroupName,
+ group.packageInfo.targetSdkVersion
+ )
return
} else if (changeRequest == ChangeRequest.REVOKE_BOTH) {
- showMediaConfirmDialog(setOneTime, defaultDeny,
- ChangeRequest.REVOKE_STORAGE_SUPERGROUP, buttonClicked, group.permGroupName,
- group.packageInfo.targetSdkVersion)
+ showMediaConfirmDialog(
+ setOneTime,
+ defaultDeny,
+ ChangeRequest.REVOKE_STORAGE_SUPERGROUP,
+ buttonClicked,
+ group.permGroupName,
+ group.packageInfo.targetSdkVersion
+ )
return
} else {
showDefaultDenyDialog = false
@@ -758,20 +806,32 @@ class AppPermissionViewModel(
}
if (showDefaultDenyDialog && !hasConfirmedRevoke && showGrantedByDefaultWarning) {
- defaultDeny.showConfirmDialog(changeRequest, R.string.system_warning, buttonClicked,
- setOneTime)
+ defaultDeny.showConfirmDialog(
+ changeRequest,
+ R.string.system_warning,
+ buttonClicked,
+ setOneTime
+ )
return
}
if (showDefaultDenyDialog && !hasConfirmedRevoke) {
- defaultDeny.showConfirmDialog(changeRequest, R.string.old_sdk_deny_warning,
- buttonClicked, setOneTime)
+ defaultDeny.showConfirmDialog(
+ changeRequest,
+ R.string.old_sdk_deny_warning,
+ buttonClicked,
+ setOneTime
+ )
return
}
if (showCDMWarning) {
- defaultDeny.showConfirmDialog(changeRequest,
- R.string.cdm_profile_revoke_warning, buttonClicked, setOneTime)
+ defaultDeny.showConfirmDialog(
+ changeRequest,
+ R.string.cdm_profile_revoke_warning,
+ buttonClicked,
+ setOneTime
+ )
return
}
@@ -780,12 +840,20 @@ class AppPermissionViewModel(
var newGroup = group2
val oldGroup = group2
- if (shouldRevokeBackground && group2.hasBackgroundGroup &&
- (wasBackgroundGranted || group2.background.isUserFixed ||
- group2.isOneTime != setOneTime)) {
- newGroup = KotlinUtils
- .revokeBackgroundRuntimePermissions(app, newGroup, oneTime = setOneTime,
- forceRemoveRevokedCompat = shouldClearOneTimeRevokedCompat(newGroup))
+ if (
+ shouldRevokeBackground &&
+ group2.hasBackgroundGroup &&
+ (wasBackgroundGranted ||
+ group2.background.isUserFixed ||
+ group2.isOneTime != setOneTime)
+ ) {
+ newGroup =
+ KotlinUtils.revokeBackgroundRuntimePermissions(
+ app,
+ newGroup,
+ oneTime = setOneTime,
+ forceRemoveRevokedCompat = shouldClearOneTimeRevokedCompat(newGroup)
+ )
// only log if we have actually denied permissions, not if we switch from
// "ask every time" to denied
@@ -794,12 +862,17 @@ class AppPermissionViewModel(
}
}
- if (shouldRevokeForeground &&
- (wasForegroundGranted || group2.isOneTime != setOneTime)) {
- newGroup = KotlinUtils
- .revokeForegroundRuntimePermissions(app, newGroup, userFixed = false,
- oneTime = setOneTime,
- forceRemoveRevokedCompat = shouldClearOneTimeRevokedCompat(newGroup))
+ if (
+ shouldRevokeForeground && (wasForegroundGranted || group2.isOneTime != setOneTime)
+ ) {
+ newGroup =
+ KotlinUtils.revokeForegroundRuntimePermissions(
+ app,
+ newGroup,
+ userFixed = false,
+ oneTime = setOneTime,
+ forceRemoveRevokedCompat = shouldClearOneTimeRevokedCompat(newGroup)
+ )
// only log if we have actually denied permissions, not if we switch from
// "ask every time" to denied
@@ -809,13 +882,16 @@ class AppPermissionViewModel(
}
if (shouldGrantForeground) {
- newGroup = if (shouldShowLocationAccuracy == true &&
- !isFineLocationChecked(newGroup)) {
- KotlinUtils.grantForegroundRuntimePermissions(app, newGroup,
- filterPermissions = listOf(ACCESS_COARSE_LOCATION))
- } else {
- KotlinUtils.grantForegroundRuntimePermissions(app, newGroup)
- }
+ newGroup =
+ if (shouldShowLocationAccuracy == true && !isFineLocationChecked(newGroup)) {
+ KotlinUtils.grantForegroundRuntimePermissions(
+ app,
+ newGroup,
+ filterPermissions = listOf(ACCESS_COARSE_LOCATION)
+ )
+ } else {
+ KotlinUtils.grantForegroundRuntimePermissions(app, newGroup)
+ }
if (!wasForegroundGranted) {
SafetyNetLogger.logPermissionToggled(newGroup)
@@ -832,15 +908,14 @@ class AppPermissionViewModel(
logPermissionChanges(oldGroup, newGroup, buttonClicked)
- fullStorageStateLiveData.value?.let {
- FullStoragePermissionAppsLiveData.recalculate()
- }
+ fullStorageStateLiveData.value?.let { FullStoragePermissionAppsLiveData.recalculate() }
}
}
private fun shouldClearOneTimeRevokedCompat(group: LightAppPermGroup): Boolean {
- return isPhotoPickerPromptEnabled() && permGroupName == READ_MEDIA_VISUAL &&
- group.permissions.values.any { it.isCompatRevoked && it.isOneTime }
+ return isPhotoPickerPromptEnabled() &&
+ permGroupName == READ_MEDIA_VISUAL &&
+ group.permissions.values.any { it.isCompatRevoked && it.isOneTime }
}
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
@@ -850,8 +925,10 @@ class AppPermissionViewModel(
}
private fun expandToSupergroup(group: LightAppPermGroup): List<LightAppPermGroup> {
- val mediaSupergroup = PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS
- .mapNotNull { mediaStorageSupergroupPermGroups[it] }
+ val mediaSupergroup =
+ PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS.mapNotNull {
+ mediaStorageSupergroupPermGroups[it]
+ }
return if (expandsToStorageSupergroup(group)) {
mediaSupergroup
} else {
@@ -860,21 +937,23 @@ class AppPermissionViewModel(
}
private fun getPermGroupIcon(permGroup: String) =
- Utils.getGroupInfo(permGroup, app.applicationContext)?.icon ?: R.drawable.ic_empty_icon
+ Utils.getGroupInfo(permGroup, app.applicationContext)?.icon ?: R.drawable.ic_empty_icon
private val storagePermGroupIcon = getPermGroupIcon(Manifest.permission_group.STORAGE)
- private val auralPermGroupIcon = if (SdkLevel.isAtLeastT()) {
- getPermGroupIcon(Manifest.permission_group.READ_MEDIA_AURAL)
- } else {
- R.drawable.ic_empty_icon
- }
+ private val auralPermGroupIcon =
+ if (SdkLevel.isAtLeastT()) {
+ getPermGroupIcon(Manifest.permission_group.READ_MEDIA_AURAL)
+ } else {
+ R.drawable.ic_empty_icon
+ }
- private val visualPermGroupIcon = if (SdkLevel.isAtLeastT()) {
- getPermGroupIcon(Manifest.permission_group.READ_MEDIA_VISUAL)
- } else {
- R.drawable.ic_empty_icon
- }
+ private val visualPermGroupIcon =
+ if (SdkLevel.isAtLeastT()) {
+ getPermGroupIcon(Manifest.permission_group.READ_MEDIA_VISUAL)
+ } else {
+ R.drawable.ic_empty_icon
+ }
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private fun showMediaConfirmDialog(
@@ -885,56 +964,63 @@ class AppPermissionViewModel(
groupName: String,
targetSdk: Int
) {
-
val aural = groupName == Manifest.permission_group.READ_MEDIA_AURAL
val visual = groupName == Manifest.permission_group.READ_MEDIA_VISUAL
val allow = changeRequest === ChangeRequest.GRANT_STORAGE_SUPERGROUP
val deny = changeRequest === ChangeRequest.REVOKE_STORAGE_SUPERGROUP
- val (iconId, titleId, messageId) = when {
- targetSdk < Build.VERSION_CODES.Q && aural && allow ->
- Triple(
- storagePermGroupIcon,
- R.string.media_confirm_dialog_title_a_to_p_aural_allow,
- R.string.media_confirm_dialog_message_a_to_p_aural_allow)
- targetSdk < Build.VERSION_CODES.Q && aural && deny ->
- Triple(
- storagePermGroupIcon,
- R.string.media_confirm_dialog_title_a_to_p_aural_deny,
- R.string.media_confirm_dialog_message_a_to_p_aural_deny)
- targetSdk < Build.VERSION_CODES.Q && visual && allow ->
- Triple(
- storagePermGroupIcon,
- R.string.media_confirm_dialog_title_a_to_p_visual_allow,
- R.string.media_confirm_dialog_message_a_to_p_visual_allow)
- targetSdk < Build.VERSION_CODES.Q && visual && deny ->
- Triple(
- storagePermGroupIcon,
- R.string.media_confirm_dialog_title_a_to_p_visual_deny,
- R.string.media_confirm_dialog_message_a_to_p_visual_deny)
- targetSdk <= Build.VERSION_CODES.S_V2 && aural && allow ->
- Triple(
- visualPermGroupIcon,
- R.string.media_confirm_dialog_title_q_to_s_aural_allow,
- R.string.media_confirm_dialog_message_q_to_s_aural_allow)
- targetSdk <= Build.VERSION_CODES.S_V2 && aural && deny ->
- Triple(
- visualPermGroupIcon,
- R.string.media_confirm_dialog_title_q_to_s_aural_deny,
- R.string.media_confirm_dialog_message_q_to_s_aural_deny)
- targetSdk <= Build.VERSION_CODES.S_V2 && visual && allow ->
- Triple(
- auralPermGroupIcon,
- R.string.media_confirm_dialog_title_q_to_s_visual_allow,
- R.string.media_confirm_dialog_message_q_to_s_visual_allow)
- targetSdk <= Build.VERSION_CODES.S_V2 && visual && deny ->
- Triple(
- auralPermGroupIcon,
- R.string.media_confirm_dialog_title_q_to_s_visual_deny,
- R.string.media_confirm_dialog_message_q_to_s_visual_deny)
- else ->
- Triple(0, 0, 0)
- }
+ val (iconId, titleId, messageId) =
+ when {
+ targetSdk < Build.VERSION_CODES.Q && aural && allow ->
+ Triple(
+ storagePermGroupIcon,
+ R.string.media_confirm_dialog_title_a_to_p_aural_allow,
+ R.string.media_confirm_dialog_message_a_to_p_aural_allow
+ )
+ targetSdk < Build.VERSION_CODES.Q && aural && deny ->
+ Triple(
+ storagePermGroupIcon,
+ R.string.media_confirm_dialog_title_a_to_p_aural_deny,
+ R.string.media_confirm_dialog_message_a_to_p_aural_deny
+ )
+ targetSdk < Build.VERSION_CODES.Q && visual && allow ->
+ Triple(
+ storagePermGroupIcon,
+ R.string.media_confirm_dialog_title_a_to_p_visual_allow,
+ R.string.media_confirm_dialog_message_a_to_p_visual_allow
+ )
+ targetSdk < Build.VERSION_CODES.Q && visual && deny ->
+ Triple(
+ storagePermGroupIcon,
+ R.string.media_confirm_dialog_title_a_to_p_visual_deny,
+ R.string.media_confirm_dialog_message_a_to_p_visual_deny
+ )
+ targetSdk <= Build.VERSION_CODES.S_V2 && aural && allow ->
+ Triple(
+ visualPermGroupIcon,
+ R.string.media_confirm_dialog_title_q_to_s_aural_allow,
+ R.string.media_confirm_dialog_message_q_to_s_aural_allow
+ )
+ targetSdk <= Build.VERSION_CODES.S_V2 && aural && deny ->
+ Triple(
+ visualPermGroupIcon,
+ R.string.media_confirm_dialog_title_q_to_s_aural_deny,
+ R.string.media_confirm_dialog_message_q_to_s_aural_deny
+ )
+ targetSdk <= Build.VERSION_CODES.S_V2 && visual && allow ->
+ Triple(
+ auralPermGroupIcon,
+ R.string.media_confirm_dialog_title_q_to_s_visual_allow,
+ R.string.media_confirm_dialog_message_q_to_s_visual_allow
+ )
+ targetSdk <= Build.VERSION_CODES.S_V2 && visual && deny ->
+ Triple(
+ auralPermGroupIcon,
+ R.string.media_confirm_dialog_title_q_to_s_visual_deny,
+ R.string.media_confirm_dialog_message_q_to_s_visual_deny
+ )
+ else -> Triple(0, 0, 0)
+ }
if (iconId == 0 || titleId == 0 || messageId == 0) {
throw UnsupportedOperationException()
@@ -962,9 +1048,8 @@ class AppPermissionViewModel(
*
* @param changeRequest whether to change foreground, background, or both.
* @param buttonPressed button pressed to initiate the change, one of
- * AppPermissionFragmentActionReported.button_pressed constants
+ * AppPermissionFragmentActionReported.button_pressed constants
* @param oneTime whether the change should show that the permission was selected as one-time
- *
*/
fun onDenyAnyWay(changeRequest: ChangeRequest, buttonPressed: Int, oneTime: Boolean) {
val unexpandedGroup = lightAppPermGroup ?: return
@@ -977,16 +1062,17 @@ class AppPermissionViewModel(
var newGroup = group
val oldGroup = group
- if (changeRequest andValue ChangeRequest.REVOKE_BACKGROUND != 0 &&
- group.hasBackgroundGroup) {
+ if (
+ changeRequest andValue ChangeRequest.REVOKE_BACKGROUND != 0 &&
+ group.hasBackgroundGroup
+ ) {
newGroup =
KotlinUtils.revokeBackgroundRuntimePermissions(app, newGroup, false, oneTime)
if (wasBackgroundGranted) {
SafetyNetLogger.logPermissionToggled(newGroup)
}
- hasDefaultPermissions = hasDefaultPermissions ||
- group.background.isGrantedByDefault
+ hasDefaultPermissions = hasDefaultPermissions || group.background.isGrantedByDefault
}
if (changeRequest andValue ChangeRequest.REVOKE_FOREGROUND != 0) {
@@ -1003,9 +1089,7 @@ class AppPermissionViewModel(
hasConfirmedRevoke = true
}
- fullStorageStateLiveData.value?.let {
- FullStoragePermissionAppsLiveData.recalculate()
- }
+ fullStorageStateLiveData.value?.let { FullStoragePermissionAppsLiveData.recalculate() }
}
}
@@ -1017,11 +1101,12 @@ class AppPermissionViewModel(
fun setAllFilesAccess(granted: Boolean) {
val aom = app.getSystemService(AppOpsManager::class.java)!!
val uid = lightAppPermGroup?.packageInfo?.uid ?: return
- val mode = if (granted) {
- MODE_ALLOWED
- } else {
- MODE_ERRORED
- }
+ val mode =
+ if (granted) {
+ MODE_ALLOWED
+ } else {
+ MODE_ERRORED
+ }
val fullStorageGrant = fullStorageStateLiveData.value?.isGranted
if (fullStorageGrant != null && fullStorageGrant != granted) {
aom.setUidMode(OPSTR_MANAGE_EXTERNAL_STORAGE, uid, mode)
@@ -1039,8 +1124,9 @@ class AppPermissionViewModel(
}
private fun getIndividualPermissionDetailResId(group: LightAppPermGroup): Pair<Int, Int> {
- return when (val numRevoked =
- group.permissions.filter { !it.value.isGrantedIncludingAppOp }.size) {
+ return when (
+ val numRevoked = group.permissions.filter { !it.value.isGrantedIncludingAppOp }.size
+ ) {
0 -> R.string.permission_revoked_none to numRevoked
group.permissions.size -> R.string.permission_revoked_all to numRevoked
else -> R.string.permission_revoked_count to numRevoked
@@ -1055,8 +1141,8 @@ class AppPermissionViewModel(
hasAdmin: Boolean
): Int {
val isForegroundPolicyDenied = group.foreground.isPolicyFixed && !group.foreground.isGranted
- val isPolicyFullyFixedWithGrantedOrNoBkg = group.isPolicyFullyFixed &&
- (group.background.isGranted || !group.hasBackgroundGroup)
+ val isPolicyFullyFixedWithGrantedOrNoBkg =
+ group.isPolicyFullyFixed && (group.background.isGranted || !group.hasBackgroundGroup)
if (group.foreground.isSystemFixed || group.background.isSystemFixed) {
return R.string.permission_summary_enabled_system_fixed
} else if (hasAdmin) {
@@ -1110,11 +1196,17 @@ class AppPermissionViewModel(
for ((permName, permission) in oldGroup.permissions) {
val newPermission = newGroup.permissions[permName] ?: continue
- if (permission.isGrantedIncludingAppOp != newPermission.isGrantedIncludingAppOp ||
- permission.flags != newPermission.flags) {
+ if (
+ permission.isGrantedIncludingAppOp != newPermission.isGrantedIncludingAppOp ||
+ permission.flags != newPermission.flags
+ ) {
logAppPermissionFragmentActionReported(changeId, newPermission, buttonPressed)
- PermissionDecisionStorageImpl.recordPermissionDecision(app.applicationContext,
- packageName, permGroupName, newPermission.isGrantedIncludingAppOp)
+ PermissionDecisionStorageImpl.recordPermissionDecision(
+ app.applicationContext,
+ packageName,
+ permGroupName,
+ newPermission.isGrantedIncludingAppOp
+ )
PermissionChangeStorageImpl.recordPermissionChange(packageName)
}
}
@@ -1136,13 +1228,28 @@ class AppPermissionViewModel(
buttonPressed: Int
) {
val uid = KotlinUtils.getPackageUid(app, packageName, user) ?: return
- PermissionControllerStatsLog.write(APP_PERMISSION_FRAGMENT_ACTION_REPORTED, sessionId,
- changeId, uid, packageName, permission.permInfo.name,
- permission.isGrantedIncludingAppOp, permission.flags, buttonPressed)
- Log.v(LOG_TAG, "Permission changed via UI with sessionId=$sessionId changeId=" +
- "$changeId uid=$uid packageName=$packageName permission=" + permission.permInfo.name +
- " isGranted=" + permission.isGrantedIncludingAppOp + " permissionFlags=" +
- permission.flags + " buttonPressed=$buttonPressed")
+ PermissionControllerStatsLog.write(
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED,
+ sessionId,
+ changeId,
+ uid,
+ packageName,
+ permission.permInfo.name,
+ permission.isGrantedIncludingAppOp,
+ permission.flags,
+ buttonPressed
+ )
+ Log.v(
+ LOG_TAG,
+ "Permission changed via UI with sessionId=$sessionId changeId=" +
+ "$changeId uid=$uid packageName=$packageName permission=" +
+ permission.permInfo.name +
+ " isGranted=" +
+ permission.isGrantedIncludingAppOp +
+ " permissionFlags=" +
+ permission.flags +
+ " buttonPressed=$buttonPressed"
+ )
}
/** Logs information about this AppPermissionGroup and view session */
@@ -1156,19 +1263,20 @@ class AppPermissionViewModel(
uid,
packageName,
permGroupName,
- permissionRationaleShown)
+ permissionRationaleShown
+ )
Log.v(
LOG_TAG,
"AppPermission fragment viewed with sessionId=$sessionId uid=$uid " +
"packageName=$packageName permGroupName=$permGroupName " +
- "permissionRationaleShown=$permissionRationaleShown")
+ "permissionRationaleShown=$permissionRationaleShown"
+ )
}
/**
- * A partial storage grant happens when:
- * An app which doesn't support the photo picker has READ_MEDIA_VISUAL_USER_SELECTED granted, or
- * An app which does support the photo picker has READ_MEDIA_VISUAL_USER_SELECTED and/or
- * ACCESS_MEDIA_LOCATION granted
+ * A partial storage grant happens when: An app which doesn't support the photo picker has
+ * READ_MEDIA_VISUAL_USER_SELECTED granted, or An app which does support the photo picker has
+ * READ_MEDIA_VISUAL_USER_SELECTED and/or ACCESS_MEDIA_LOCATION granted
*/
private fun isPartialStorageGrant(group: LightAppPermGroup): Boolean {
if (!isPhotoPickerPromptEnabled() || group.permGroupName != READ_MEDIA_VISUAL) {
@@ -1177,9 +1285,10 @@ class AppPermissionViewModel(
val partialPerms = getPartialStorageGrantPermissionsForGroup(group)
- return group.isGranted && group.permissions.values.all {
- it.name in partialPerms || (it.name !in partialPerms && !it.isGrantedIncludingAppOp)
- }
+ return group.isGranted &&
+ group.permissions.values.all {
+ it.name in partialPerms || (it.name !in partialPerms && !it.isGrantedIncludingAppOp)
+ }
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
index 8a2216469..3f19db475 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
@@ -39,9 +39,7 @@ import android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP
import android.os.Build
import android.os.Bundle
import android.os.Process
-import android.os.UserManager
import android.permission.PermissionManager
-import android.provider.MediaStore
import android.util.Log
import androidx.core.util.Consumer
import androidx.lifecycle.ViewModel
@@ -72,9 +70,9 @@ import com.android.permissioncontroller.auto.DrivingDecisionReminderService
import com.android.permissioncontroller.permission.data.LightAppPermGroupLiveData
import com.android.permissioncontroller.permission.data.LightPackageInfoLiveData
import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData
-import com.android.permissioncontroller.permission.data.v34.SafetyLabelInfoLiveData
import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData
import com.android.permissioncontroller.permission.data.get
+import com.android.permissioncontroller.permission.data.v34.SafetyLabelInfoLiveData
import com.android.permissioncontroller.permission.model.AppPermissionGroup
import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
@@ -118,25 +116,27 @@ import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_INTERACTED
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_RESULT
import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleActivity
-import com.android.permissioncontroller.permission.utils.v31.AdminRestrictedPermissionsUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils.getDefaultPrecision
import com.android.permissioncontroller.permission.utils.KotlinUtils.grantBackgroundRuntimePermissions
import com.android.permissioncontroller.permission.utils.KotlinUtils.grantForegroundRuntimePermissions
import com.android.permissioncontroller.permission.utils.KotlinUtils.isLocationAccuracyEnabled
+import com.android.permissioncontroller.permission.utils.KotlinUtils.isPhotoPickerPromptEnabled
import com.android.permissioncontroller.permission.utils.KotlinUtils.isPhotoPickerPromptSupported
+import com.android.permissioncontroller.permission.utils.KotlinUtils.openPhotoPickerForApp
import com.android.permissioncontroller.permission.utils.KotlinUtils.revokeBackgroundRuntimePermissions
import com.android.permissioncontroller.permission.utils.KotlinUtils.revokeForegroundRuntimePermissions
import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.PermissionMapping.getPartialStorageGrantPermissionsForGroup
import com.android.permissioncontroller.permission.utils.SafetyNetLogger
import com.android.permissioncontroller.permission.utils.Utils
+import com.android.permissioncontroller.permission.utils.v31.AdminRestrictedPermissionsUtils
import com.android.permissioncontroller.permission.utils.v34.SafetyLabelUtils
/**
- * ViewModel for the GrantPermissionsActivity. Tracks all permission groups that are affected by
- * the permissions requested by the user, and generates a RequestInfo object for each group, if
- * action is needed. It will not return any data if one of the requests is malformed.
+ * ViewModel for the GrantPermissionsActivity. Tracks all permission groups that are affected by the
+ * permissions requested by the user, and generates a RequestInfo object for each group, if action
+ * is needed. It will not return any data if one of the requests is malformed.
*
* @param app: The current application
* @param packageName: The packageName permissions are being requested for
@@ -155,9 +155,12 @@ class GrantPermissionsViewModel(
private val user = Process.myUserHandle()
private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user]
private val safetyLabelInfoLiveData =
- if (SdkLevel.isAtLeastU() && requestedPermissions
- .mapNotNull { PermissionMapping.getGroupOfPlatformPermission(it) }
- .any { PermissionMapping.isSafetyLabelAwarePermissionGroup(it) }) {
+ if (
+ SdkLevel.isAtLeastU() &&
+ requestedPermissions
+ .mapNotNull { PermissionMapping.getGroupOfPlatformPermission(it) }
+ .any { PermissionMapping.isSafetyLabelAwarePermissionGroup(it) }
+ ) {
SafetyLabelInfoLiveData[packageName, user]
} else {
null
@@ -201,416 +204,492 @@ class GrantPermissionsViewModel(
var activityResultCallback: Consumer<Intent>? = null
- /**
- * A LiveData which holds a list of the currently pending RequestInfos
- */
- val requestInfosLiveData = object :
- SmartUpdateMediatorLiveData<List<RequestInfo>>() {
- private val LOG_TAG = GrantPermissionsViewModel::class.java.simpleName
- private val packagePermissionsLiveData = PackagePermissionsLiveData[packageName, user]
-
- init {
- addSource(packagePermissionsLiveData) { onPackageLoaded() }
- addSource(packageInfoLiveData) { onPackageLoaded() }
- if (safetyLabelInfoLiveData != null) {
- addSource(safetyLabelInfoLiveData) { onPackageLoaded() }
- }
-
- // Load package state, if available
- onPackageLoaded()
- }
+ /** A LiveData which holds a list of the currently pending RequestInfos */
+ val requestInfosLiveData =
+ object : SmartUpdateMediatorLiveData<List<RequestInfo>>() {
+ private val LOG_TAG = GrantPermissionsViewModel::class.java.simpleName
+ private val packagePermissionsLiveData = PackagePermissionsLiveData[packageName, user]
+
+ init {
+ addSource(packagePermissionsLiveData) { onPackageLoaded() }
+ addSource(packageInfoLiveData) { onPackageLoaded() }
+ if (safetyLabelInfoLiveData != null) {
+ addSource(safetyLabelInfoLiveData) { onPackageLoaded() }
+ }
- private fun onPackageLoaded() {
- if (packageInfoLiveData.isStale ||
- packagePermissionsLiveData.isStale ||
- (safetyLabelInfoLiveData != null && safetyLabelInfoLiveData.isStale)) {
- return
+ // Load package state, if available
+ onPackageLoaded()
}
- val groups = packagePermissionsLiveData.value
- val pI = packageInfoLiveData.value
- if (groups == null || groups.isEmpty() || pI == null) {
- Log.e(LOG_TAG, "Package $packageName not found")
- value = null
- return
- }
- packageInfo = pI
+ private fun onPackageLoaded() {
+ if (
+ packageInfoLiveData.isStale ||
+ packagePermissionsLiveData.isStale ||
+ (safetyLabelInfoLiveData != null && safetyLabelInfoLiveData.isStale)
+ ) {
+ return
+ }
- if (packageInfo.requestedPermissions.isEmpty() ||
- packageInfo.targetSdkVersion < Build.VERSION_CODES.M) {
- Log.e(LOG_TAG, "Package $packageName has no requested permissions, or " +
- "is a pre-M app")
- value = null
- return
- }
+ val groups = packagePermissionsLiveData.value
+ val pI = packageInfoLiveData.value
+ if (groups == null || groups.isEmpty() || pI == null) {
+ Log.e(LOG_TAG, "Package $packageName not found")
+ value = null
+ return
+ }
+ packageInfo = pI
+
+ if (
+ packageInfo.requestedPermissions.isEmpty() ||
+ packageInfo.targetSdkVersion < Build.VERSION_CODES.M
+ ) {
+ Log.e(
+ LOG_TAG,
+ "Package $packageName has no requested permissions, or " + "is a pre-M app"
+ )
+ value = null
+ return
+ }
- val allAffectedPermissions = requestedPermissions.toMutableSet()
- for (requestedPerm in requestedPermissions) {
- allAffectedPermissions.addAll(computeAffectedPermissions(requestedPerm, groups))
- }
- unfilteredAffectedPermissions = allAffectedPermissions.toList()
+ val allAffectedPermissions = requestedPermissions.toMutableSet()
+ for (requestedPerm in requestedPermissions) {
+ allAffectedPermissions.addAll(computeAffectedPermissions(requestedPerm, groups))
+ }
+ unfilteredAffectedPermissions = allAffectedPermissions.toList()
- setAppPermGroupsLiveDatas(groups.toMutableMap().apply {
- remove(PackagePermissionsLiveData.NON_RUNTIME_NORMAL_PERMS)
- })
+ setAppPermGroupsLiveDatas(
+ groups.toMutableMap().apply {
+ remove(PackagePermissionsLiveData.NON_RUNTIME_NORMAL_PERMS)
+ }
+ )
- for (splitPerm in app.getSystemService(
- PermissionManager::class.java)!!.splitPermissions) {
- splitPermissionTargetSdkMap[splitPerm.splitPermission] = splitPerm.targetSdk
+ for (splitPerm in
+ app.getSystemService(PermissionManager::class.java)!!.splitPermissions) {
+ splitPermissionTargetSdkMap[splitPerm.splitPermission] = splitPerm.targetSdk
+ }
}
- }
- private fun setAppPermGroupsLiveDatas(groups: Map<String, List<String>>) {
+ private fun setAppPermGroupsLiveDatas(groups: Map<String, List<String>>) {
- val requestedGroups = groups.filter { (_, perms) ->
- perms.any { it in unfilteredAffectedPermissions }
- }
+ val requestedGroups =
+ groups.filter { (_, perms) ->
+ perms.any { it in unfilteredAffectedPermissions }
+ }
- if (requestedGroups.isEmpty()) {
- Log.e(LOG_TAG, "None of " +
- "$unfilteredAffectedPermissions in $groups")
- value = null
- return
- }
+ if (requestedGroups.isEmpty()) {
+ Log.e(LOG_TAG, "None of " + "$unfilteredAffectedPermissions in $groups")
+ value = null
+ return
+ }
- val getLiveDataFun = { groupName: String ->
- LightAppPermGroupLiveData[packageName, groupName, user]
+ val getLiveDataFun = { groupName: String ->
+ LightAppPermGroupLiveData[packageName, groupName, user]
+ }
+ setSourcesToDifference(requestedGroups.keys, appPermGroupLiveDatas, getLiveDataFun)
}
- setSourcesToDifference(requestedGroups.keys, appPermGroupLiveDatas, getLiveDataFun)
- }
- override fun onUpdate() {
- if (appPermGroupLiveDatas.any { it.value.isStale }) {
- return
- }
- var newGroups = false
- for ((groupName, groupLiveData) in appPermGroupLiveDatas) {
- val appPermGroup = groupLiveData.value
- if (appPermGroup == null || groupName in permGroupsToSkip) {
- if (appPermGroup == null) {
- Log.e(LOG_TAG, "Group $packageName $groupName invalid")
- }
- groupStates[groupName to true]?.state = STATE_SKIPPED
- groupStates[groupName to false]?.state = STATE_SKIPPED
- continue
+ override fun onUpdate() {
+ if (appPermGroupLiveDatas.any { it.value.isStale }) {
+ return
}
-
- packageInfo = appPermGroup.packageInfo
-
- val states = groupStates.filter { it.key.first == groupName }
- if (states.isNotEmpty()) {
- for ((key, state) in states) {
- val allAffectedGranted = state.affectedPermissions.all { perm ->
- appPermGroup.permissions[perm]?.isGrantedIncludingAppOp == true &&
- appPermGroup.permissions[perm]?.isRevokeWhenRequested == false
- }
- if (allAffectedGranted) {
- groupStates[key]!!.state = STATE_ALLOWED
+ var newGroups = false
+ for ((groupName, groupLiveData) in appPermGroupLiveDatas) {
+ val appPermGroup = groupLiveData.value
+ if (appPermGroup == null || groupName in permGroupsToSkip) {
+ if (appPermGroup == null) {
+ Log.e(LOG_TAG, "Group $packageName $groupName invalid")
}
+ groupStates[groupName to true]?.state = STATE_SKIPPED
+ groupStates[groupName to false]?.state = STATE_SKIPPED
+ continue
}
- } else {
- newGroups = true
- }
- }
-
- if (newGroups) {
- groupStates = getRequiredGroupStates(
- appPermGroupLiveDatas.mapNotNull { it.value.value })
- }
- setRequestInfosFromGroupStates()
- }
- private fun setRequestInfosFromGroupStates() {
- val requestInfos = mutableListOf<RequestInfo>()
- for ((key, groupState) in groupStates) {
- val groupInfo = groupState.group.permGroupInfo
- val (groupName, isBackground) = key
- if (groupState.state != STATE_UNKNOWN) {
- continue
- }
- val fgState = groupStates[groupName to false]
- val bgState = groupStates[groupName to true]
- var needFgPermissions = false
- var needBgPermissions = false
- var isFgUserSet = false
- var isBgUserSet = false
- var minSdkForOrderedSplitPermissions = Build.VERSION_CODES.R
- if (fgState?.group != null) {
- val fgGroup = fgState.group
- for (perm in fgState.affectedPermissions) {
- minSdkForOrderedSplitPermissions = maxOf(minSdkForOrderedSplitPermissions,
- splitPermissionTargetSdkMap.getOrDefault(perm, 0))
- if (fgGroup.permissions[perm]?.isGrantedIncludingAppOp == false) {
- // If any of the requested permissions is not granted,
- // needFgPermissions = true
- needFgPermissions = true
- // If any of the requested permission's UserSet is true and the
- // permission is not granted, isFgUserSet = true.
- if (fgGroup.permissions[perm]?.isUserSet == true) {
- isFgUserSet = true
+ packageInfo = appPermGroup.packageInfo
+
+ val states = groupStates.filter { it.key.first == groupName }
+ if (states.isNotEmpty()) {
+ for ((key, state) in states) {
+ val allAffectedGranted =
+ state.affectedPermissions.all { perm ->
+ appPermGroup.permissions[perm]?.isGrantedIncludingAppOp ==
+ true &&
+ appPermGroup.permissions[perm]?.isRevokeWhenRequested ==
+ false
+ }
+ if (allAffectedGranted) {
+ groupStates[key]!!.state = STATE_ALLOWED
}
}
+ } else {
+ newGroups = true
}
}
- if (bgState?.group?.background?.isGranted == false) {
- needBgPermissions = true
- isBgUserSet = bgState.group.background.isUserSet
+
+ if (newGroups) {
+ groupStates =
+ getRequiredGroupStates(appPermGroupLiveDatas.mapNotNull { it.value.value })
}
+ setRequestInfosFromGroupStates()
+ }
- val buttonVisibilities = MutableList(NEXT_BUTTON) { false }
- buttonVisibilities[ALLOW_BUTTON] = true
- buttonVisibilities[DENY_BUTTON] = true
- buttonVisibilities[ALLOW_ONE_TIME_BUTTON] =
- PermissionMapping.supportsOneTimeGrant(groupName)
- var message = RequestMessage.FG_MESSAGE
- // Whether or not to use the foreground, background, or no detail message.
- // null ==
- var detailMessage = RequestMessage.NO_MESSAGE
-
- if (KotlinUtils.isPhotoPickerPromptEnabled() &&
- groupState.group.permGroupName == READ_MEDIA_VISUAL &&
- groupState.group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.TIRAMISU) {
- // If the USER_SELECTED permission is user fixed and granted, or the app is only
- // requesting USER_SELECTED, direct straight to photo picker
- val userPerm = groupState.group.permissions[READ_MEDIA_VISUAL_USER_SELECTED]
- if ((userPerm?.isUserFixed == true && userPerm.isGrantedIncludingAppOp) ||
- groupState.affectedPermissions == listOf(READ_MEDIA_VISUAL_USER_SELECTED)) {
- requestInfos.add(RequestInfo(groupInfo, openPhotoPicker = true))
+ private fun setRequestInfosFromGroupStates() {
+ val requestInfos = mutableListOf<RequestInfo>()
+ for ((key, groupState) in groupStates) {
+ val groupInfo = groupState.group.permGroupInfo
+ val (groupName, isBackground) = key
+ if (groupState.state != STATE_UNKNOWN) {
continue
- } else if (isPartialStorageGrant(groupState.group)) {
- // More photos dialog
- message = RequestMessage.MORE_PHOTOS_MESSAGE
- buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] = false
- buttonVisibilities[DENY_BUTTON] = false
- buttonVisibilities[DONT_ALLOW_MORE_SELECTED_BUTTON] = true
- } else {
- // Standard photos dialog
- buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] = isFgUserSet
- buttonVisibilities[DENY_BUTTON] = !isFgUserSet
}
- buttonVisibilities[ALLOW_SELECTED_BUTTON] = true
- buttonVisibilities[ALLOW_BUTTON] = false
- buttonVisibilities[ALLOW_ALL_BUTTON] = true
- } else if (groupState.group.packageInfo.targetSdkVersion >=
- minSdkForOrderedSplitPermissions) {
- if (isBackground || Utils.hasPermWithBackgroundModeCompat(groupState.group)) {
- if (needFgPermissions) {
- if (needBgPermissions) {
- if (groupState.group.permGroupName
- .equals(Manifest.permission_group.CAMERA) ||
- groupState.group.permGroupName
- .equals(Manifest.permission_group.MICROPHONE)) {
- if (groupState.group.packageInfo.targetSdkVersion >=
- Build.VERSION_CODES.S) {
- Log.e(LOG_TAG,
+ val fgState = groupStates[groupName to false]
+ val bgState = groupStates[groupName to true]
+ var needFgPermissions = false
+ var needBgPermissions = false
+ var isFgUserSet = false
+ var isBgUserSet = false
+ var minSdkForOrderedSplitPermissions = Build.VERSION_CODES.R
+ if (fgState?.group != null) {
+ val fgGroup = fgState.group
+ for (perm in fgState.affectedPermissions) {
+ minSdkForOrderedSplitPermissions =
+ maxOf(
+ minSdkForOrderedSplitPermissions,
+ splitPermissionTargetSdkMap.getOrDefault(perm, 0)
+ )
+ if (fgGroup.permissions[perm]?.isGrantedIncludingAppOp == false) {
+ // If any of the requested permissions is not granted,
+ // needFgPermissions = true
+ needFgPermissions = true
+ // If any of the requested permission's UserSet is true and the
+ // permission is not granted, isFgUserSet = true.
+ if (fgGroup.permissions[perm]?.isUserSet == true) {
+ isFgUserSet = true
+ }
+ }
+ }
+ }
+ if (bgState?.group?.background?.isGranted == false) {
+ needBgPermissions = true
+ isBgUserSet = bgState.group.background.isUserSet
+ }
+
+ val buttonVisibilities = MutableList(NEXT_BUTTON) { false }
+ buttonVisibilities[ALLOW_BUTTON] = true
+ buttonVisibilities[DENY_BUTTON] = true
+ buttonVisibilities[ALLOW_ONE_TIME_BUTTON] =
+ PermissionMapping.supportsOneTimeGrant(groupName)
+ var message = RequestMessage.FG_MESSAGE
+ // Whether or not to use the foreground, background, or no detail message.
+ // null ==
+ var detailMessage = RequestMessage.NO_MESSAGE
+
+ if (
+ groupState.group.permGroupName == READ_MEDIA_VISUAL &&
+ shouldShowPhotoPickerPromptForApp(groupState.group)
+ ) {
+ // If the USER_SELECTED permission is user fixed and granted, or the app is
+ // only
+ // requesting USER_SELECTED, direct straight to photo picker
+ val userPerm = groupState.group.permissions[READ_MEDIA_VISUAL_USER_SELECTED]
+ if (
+ (userPerm?.isUserFixed == true && userPerm.isGrantedIncludingAppOp) ||
+ groupState.affectedPermissions ==
+ listOf(READ_MEDIA_VISUAL_USER_SELECTED)
+ ) {
+ requestInfos.add(RequestInfo(groupInfo, openPhotoPicker = true))
+ continue
+ } else if (isPartialStorageGrant(groupState.group)) {
+ // More photos dialog
+ message = RequestMessage.MORE_PHOTOS_MESSAGE
+ buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] = false
+ buttonVisibilities[DENY_BUTTON] = false
+ buttonVisibilities[DONT_ALLOW_MORE_SELECTED_BUTTON] = true
+ } else {
+ // Standard photos dialog
+ buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] = isFgUserSet
+ buttonVisibilities[DENY_BUTTON] = !isFgUserSet
+ }
+ buttonVisibilities[ALLOW_SELECTED_BUTTON] = true
+ buttonVisibilities[ALLOW_BUTTON] = false
+ buttonVisibilities[ALLOW_ALL_BUTTON] = true
+ } else if (
+ groupState.group.packageInfo.targetSdkVersion >=
+ minSdkForOrderedSplitPermissions
+ ) {
+ if (
+ isBackground || Utils.hasPermWithBackgroundModeCompat(groupState.group)
+ ) {
+ if (needFgPermissions) {
+ if (needBgPermissions) {
+ if (
+ groupState.group.permGroupName.equals(
+ Manifest.permission_group.CAMERA
+ ) ||
+ groupState.group.permGroupName.equals(
+ Manifest.permission_group.MICROPHONE
+ )
+ ) {
+ if (
+ groupState.group.packageInfo.targetSdkVersion >=
+ Build.VERSION_CODES.S
+ ) {
+ Log.e(
+ LOG_TAG,
"For S apps, background permissions must be " +
- "requested after foreground permissions are" +
- " already granted")
- value = null
- return
- } else {
- // Case: sdk < S, BG&FG mic/camera permission requested
- buttonVisibilities[ALLOW_BUTTON] = false
- buttonVisibilities[ALLOW_FOREGROUND_BUTTON] = true
- buttonVisibilities[DENY_BUTTON] = !isFgUserSet
- buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] =
+ "requested after foreground permissions are" +
+ " already granted"
+ )
+ value = null
+ return
+ } else {
+ // Case: sdk < S, BG&FG mic/camera permission requested
+ buttonVisibilities[ALLOW_BUTTON] = false
+ buttonVisibilities[ALLOW_FOREGROUND_BUTTON] = true
+ buttonVisibilities[DENY_BUTTON] = !isFgUserSet
+ buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] =
isFgUserSet
- if (needBgPermissions) {
- // Case: sdk < R, BG/FG permission requesting both
- message = RequestMessage.BG_MESSAGE
- detailMessage = RequestMessage.BG_MESSAGE
+ if (needBgPermissions) {
+ // Case: sdk < R, BG/FG permission requesting both
+ message = RequestMessage.BG_MESSAGE
+ detailMessage = RequestMessage.BG_MESSAGE
+ }
}
+ } else {
+ // Shouldn't be reached as background must be requested as a
+ // singleton
+ Log.e(
+ LOG_TAG,
+ "For R+ apps, background permissions must be " +
+ "requested after foreground permissions are already" +
+ " granted"
+ )
+ value = null
+ return
}
} else {
- // Shouldn't be reached as background must be requested as a
- // singleton
- Log.e(LOG_TAG, "For R+ apps, background permissions must be " +
- "requested after foreground permissions are already" +
- " granted")
- value = null
- return
+ buttonVisibilities[ALLOW_BUTTON] = false
+ buttonVisibilities[ALLOW_FOREGROUND_BUTTON] = true
+ buttonVisibilities[DENY_BUTTON] = !isFgUserSet
+ buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] = isFgUserSet
+ }
+ } else if (needBgPermissions) {
+ // Case: sdk >= R, BG/FG permission requesting BG only
+ if (
+ storedState != null &&
+ storedState.containsKey(
+ getInstanceStateKey(
+ groupInfo.name,
+ groupState.isBackground
+ )
+ )
+ ) {
+ // If we're restoring state, and we had this groupInfo in our
+ // previous state, that means that we likely sent the user to
+ // settings already. Don't send the user back.
+ permGroupsToSkip.add(groupInfo.name)
+ groupState.state = STATE_SKIPPED
+ } else {
+ requestInfos.add(
+ RequestInfo(groupInfo, sendToSettingsImmediately = true)
+ )
}
+ continue
} else {
+ // Not reached as the permissions should be auto-granted
+ value = null
+ return
+ }
+ } else {
+ // Case: sdk >= R, Requesting normal permission
+ buttonVisibilities[DENY_BUTTON] = !isFgUserSet
+ buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] = isFgUserSet
+ }
+ } else {
+ if (
+ isBackground || Utils.hasPermWithBackgroundModeCompat(groupState.group)
+ ) {
+ if (needFgPermissions) {
+ // Case: sdk < R, BG/FG permission requesting both or FG only
buttonVisibilities[ALLOW_BUTTON] = false
buttonVisibilities[ALLOW_FOREGROUND_BUTTON] = true
buttonVisibilities[DENY_BUTTON] = !isFgUserSet
buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] = isFgUserSet
- }
- } else if (needBgPermissions) {
- // Case: sdk >= R, BG/FG permission requesting BG only
- if (storedState != null && storedState.containsKey(getInstanceStateKey(
- groupInfo.name, groupState.isBackground))) {
- // If we're restoring state, and we had this groupInfo in our
- // previous state, that means that we likely sent the user to
- // settings already. Don't send the user back.
- permGroupsToSkip.add(groupInfo.name)
- groupState.state = STATE_SKIPPED
+ if (needBgPermissions) {
+ // Case: sdk < R, BG/FG permission requesting both
+ message = RequestMessage.BG_MESSAGE
+ detailMessage = RequestMessage.BG_MESSAGE
+ }
+ } else if (needBgPermissions) {
+ // Case: sdk < R, BG/FG permission requesting BG only
+ if (!groupState.group.foreground.isGranted) {
+ Log.e(
+ LOG_TAG,
+ "Background permissions can't be requested " +
+ "solely before foreground permissions are granted."
+ )
+ value = null
+ return
+ }
+ message = RequestMessage.UPGRADE_MESSAGE
+ detailMessage = RequestMessage.UPGRADE_MESSAGE
+ buttonVisibilities[ALLOW_BUTTON] = false
+ buttonVisibilities[DENY_BUTTON] = false
+ buttonVisibilities[ALLOW_ONE_TIME_BUTTON] = false
+ if (groupState.group.isOneTime) {
+ buttonVisibilities[NO_UPGRADE_OT_BUTTON] = !isBgUserSet
+ buttonVisibilities[NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON] =
+ isBgUserSet
+ } else {
+ buttonVisibilities[NO_UPGRADE_BUTTON] = !isBgUserSet
+ buttonVisibilities[NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON] =
+ isBgUserSet
+ }
} else {
- requestInfos.add(RequestInfo(
- groupInfo, sendToSettingsImmediately = true))
+ // Not reached as the permissions should be auto-granted
+ value = null
+ return
}
- continue
} else {
- // Not reached as the permissions should be auto-granted
- value = null
- return
- }
- } else {
- // Case: sdk >= R, Requesting normal permission
- buttonVisibilities[DENY_BUTTON] = !isFgUserSet
- buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] = isFgUserSet
- }
- } else {
- if (isBackground || Utils.hasPermWithBackgroundModeCompat(groupState.group)) {
- if (needFgPermissions) {
- // Case: sdk < R, BG/FG permission requesting both or FG only
- buttonVisibilities[ALLOW_BUTTON] = false
- buttonVisibilities[ALLOW_FOREGROUND_BUTTON] = true
- buttonVisibilities[DENY_BUTTON] = !isFgUserSet
- buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] = isFgUserSet
- if (needBgPermissions) {
- // Case: sdk < R, BG/FG permission requesting both
- message = RequestMessage.BG_MESSAGE
- detailMessage = RequestMessage.BG_MESSAGE
- }
- } else if (needBgPermissions) {
- // Case: sdk < R, BG/FG permission requesting BG only
- if (!groupState.group.foreground.isGranted) {
- Log.e(LOG_TAG, "Background permissions can't be requested " +
- "solely before foreground permissions are granted.")
+ // If no permissions needed, do nothing
+ if (!needFgPermissions && !needBgPermissions) {
value = null
return
}
- message = RequestMessage.UPGRADE_MESSAGE
- detailMessage = RequestMessage.UPGRADE_MESSAGE
- buttonVisibilities[ALLOW_BUTTON] = false
- buttonVisibilities[DENY_BUTTON] = false
- buttonVisibilities[ALLOW_ONE_TIME_BUTTON] = false
- if (groupState.group.isOneTime) {
- buttonVisibilities[NO_UPGRADE_OT_BUTTON] = !isBgUserSet
- buttonVisibilities[NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON] =
- isBgUserSet
- } else {
- buttonVisibilities[NO_UPGRADE_BUTTON] = !isBgUserSet
- buttonVisibilities[NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON] =
- isBgUserSet
- }
- } else {
- // Not reached as the permissions should be auto-granted
- value = null
- return
- }
- } else {
- // If no permissions needed, do nothing
- if (!needFgPermissions && !needBgPermissions) {
- value = null
- return
+ // Case: sdk < R, Requesting normal permission
+ buttonVisibilities[DENY_BUTTON] = !isFgUserSet
+ buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] = isFgUserSet
}
- // Case: sdk < R, Requesting normal permission
- buttonVisibilities[DENY_BUTTON] = !isFgUserSet
- buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON] = isFgUserSet
}
- }
- buttonVisibilities[LINK_TO_SETTINGS] =
- detailMessage != RequestMessage.NO_MESSAGE
-
- // Show location permission dialogs based on location permissions
- val locationVisibilities = MutableList(NEXT_LOCATION_DIALOG) { false }
- if (groupState.group.permGroupName == LOCATION &&
- isLocationAccuracyEnabledForApp(groupState.group)) {
- if (needFgPermissions) {
- locationVisibilities[LOCATION_ACCURACY_LAYOUT] = true
- if (fgState != null &&
- fgState.affectedPermissions.contains(ACCESS_FINE_LOCATION)) {
- val coarseLocationPerm =
- groupState.group.allPermissions[ACCESS_COARSE_LOCATION]
- if (coarseLocationPerm?.isGrantedIncludingAppOp == true) {
- // Upgrade flow
- locationVisibilities[DIALOG_WITH_FINE_LOCATION_ONLY] = true
- message = RequestMessage.FG_FINE_LOCATION_MESSAGE
- // If COARSE was granted one time, hide 'While in use' button
- if (coarseLocationPerm.isOneTime) {
- buttonVisibilities[ALLOW_FOREGROUND_BUTTON] = false
- }
- } else {
- if (!fgState.affectedPermissions.contains(ACCESS_COARSE_LOCATION)) {
- Log.e(LOG_TAG, "ACCESS_FINE_LOCATION must be requested " +
- "with ACCESS_COARSE_LOCATION.")
- value = null
- return
- }
- // Normal flow with both Coarse and Fine locations
- locationVisibilities[DIALOG_WITH_BOTH_LOCATIONS] = true
- // Steps to decide location accuracy default state
- // 1. If none of the FINE and COARSE isSelectedLocationAccuracy
- // flags is set, then use default precision from device config.
- // 2. Otherwise set to whichever isSelectedLocationAccuracy is true.
- val fineLocationPerm =
+ buttonVisibilities[LINK_TO_SETTINGS] =
+ detailMessage != RequestMessage.NO_MESSAGE
+
+ // Show location permission dialogs based on location permissions
+ val locationVisibilities = MutableList(NEXT_LOCATION_DIALOG) { false }
+ if (
+ groupState.group.permGroupName == LOCATION &&
+ isLocationAccuracyEnabledForApp(groupState.group)
+ ) {
+ if (needFgPermissions) {
+ locationVisibilities[LOCATION_ACCURACY_LAYOUT] = true
+ if (
+ fgState != null &&
+ fgState.affectedPermissions.contains(ACCESS_FINE_LOCATION)
+ ) {
+ val coarseLocationPerm =
+ groupState.group.allPermissions[ACCESS_COARSE_LOCATION]
+ if (coarseLocationPerm?.isGrantedIncludingAppOp == true) {
+ // Upgrade flow
+ locationVisibilities[DIALOG_WITH_FINE_LOCATION_ONLY] = true
+ message = RequestMessage.FG_FINE_LOCATION_MESSAGE
+ // If COARSE was granted one time, hide 'While in use' button
+ if (coarseLocationPerm.isOneTime) {
+ buttonVisibilities[ALLOW_FOREGROUND_BUTTON] = false
+ }
+ } else {
+ if (
+ !fgState.affectedPermissions.contains(
+ ACCESS_COARSE_LOCATION
+ )
+ ) {
+ Log.e(
+ LOG_TAG,
+ "ACCESS_FINE_LOCATION must be requested " +
+ "with ACCESS_COARSE_LOCATION."
+ )
+ value = null
+ return
+ }
+ // Normal flow with both Coarse and Fine locations
+ locationVisibilities[DIALOG_WITH_BOTH_LOCATIONS] = true
+ // Steps to decide location accuracy default state
+ // 1. If none of the FINE and COARSE isSelectedLocationAccuracy
+ // flags is set, then use default precision from device
+ // config.
+ // 2. Otherwise set to whichever isSelectedLocationAccuracy is
+ // true.
+ val fineLocationPerm =
groupState.group.allPermissions[ACCESS_FINE_LOCATION]
- if (coarseLocationPerm?.isSelectedLocationAccuracy == false &&
- fineLocationPerm?.isSelectedLocationAccuracy == false) {
- if (getDefaultPrecision()) {
- locationVisibilities[FINE_RADIO_BUTTON] = true
- } else {
+ if (
+ coarseLocationPerm?.isSelectedLocationAccuracy == false &&
+ fineLocationPerm?.isSelectedLocationAccuracy == false
+ ) {
+ if (getDefaultPrecision()) {
+ locationVisibilities[FINE_RADIO_BUTTON] = true
+ } else {
+ locationVisibilities[COARSE_RADIO_BUTTON] = true
+ }
+ } else if (
+ coarseLocationPerm?.isSelectedLocationAccuracy == true
+ ) {
locationVisibilities[COARSE_RADIO_BUTTON] = true
+ } else {
+ locationVisibilities[FINE_RADIO_BUTTON] = true
}
- } else if (coarseLocationPerm?.isSelectedLocationAccuracy == true) {
- locationVisibilities[COARSE_RADIO_BUTTON] = true
- } else {
- locationVisibilities[FINE_RADIO_BUTTON] = true
}
+ } else if (
+ fgState != null &&
+ fgState.affectedPermissions.contains(ACCESS_COARSE_LOCATION)
+ ) {
+ // Request Coarse only
+ locationVisibilities[DIALOG_WITH_COARSE_LOCATION_ONLY] = true
+ message = RequestMessage.FG_COARSE_LOCATION_MESSAGE
}
- } else if (fgState != null && fgState.affectedPermissions
- .contains(ACCESS_COARSE_LOCATION)) {
- // Request Coarse only
- locationVisibilities[DIALOG_WITH_COARSE_LOCATION_ONLY] = true
- message = RequestMessage.FG_COARSE_LOCATION_MESSAGE
}
}
- }
- if (SdkLevel.isAtLeastT()) {
- // If app is T+, requests for the STORAGE group are ignored
- if (packageInfo.targetSdkVersion > Build.VERSION_CODES.S_V2 &&
- groupState.group.permGroupName == Manifest.permission_group.STORAGE) {
- continue
- }
- // If app is <T and requests STORAGE, grant dialogs has special text
- if (groupState.group.permGroupName in
- PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS) {
- if (packageInfo.targetSdkVersion < Build.VERSION_CODES.Q) {
- message = RequestMessage.STORAGE_SUPERGROUP_MESSAGE_PRE_Q
- } else if (packageInfo.targetSdkVersion <= Build.VERSION_CODES.S_V2) {
- message = RequestMessage.STORAGE_SUPERGROUP_MESSAGE_Q_TO_S
+ if (SdkLevel.isAtLeastT()) {
+ // If app is T+, requests for the STORAGE group are ignored
+ if (
+ packageInfo.targetSdkVersion > Build.VERSION_CODES.S_V2 &&
+ groupState.group.permGroupName == Manifest.permission_group.STORAGE
+ ) {
+ continue
+ }
+ // If app is <T and requests STORAGE, grant dialogs has special text
+ if (
+ groupState.group.permGroupName in
+ PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS
+ ) {
+ if (packageInfo.targetSdkVersion < Build.VERSION_CODES.Q) {
+ message = RequestMessage.STORAGE_SUPERGROUP_MESSAGE_PRE_Q
+ } else if (packageInfo.targetSdkVersion <= Build.VERSION_CODES.S_V2) {
+ message = RequestMessage.STORAGE_SUPERGROUP_MESSAGE_Q_TO_S
+ }
}
}
- }
-
- val safetyLabel = safetyLabelInfoLiveData?.value?.safetyLabel
- val showPermissionRationale =
- shouldShowPermissionRationale(safetyLabel, groupState.group.permGroupName)
- buttonVisibilities[LINK_TO_PERMISSION_RATIONALE] = showPermissionRationale
-
- requestInfos.add(RequestInfo(
- groupInfo,
- buttonVisibilities,
- locationVisibilities,
- message,
- detailMessage))
- }
- sortPermissionGroups(requestInfos)
+ val safetyLabel = safetyLabelInfoLiveData?.value?.safetyLabel
+ val showPermissionRationale =
+ shouldShowPermissionRationale(safetyLabel, groupState.group.permGroupName)
+ buttonVisibilities[LINK_TO_PERMISSION_RATIONALE] = showPermissionRationale
+
+ requestInfos.add(
+ RequestInfo(
+ groupInfo,
+ buttonVisibilities,
+ locationVisibilities,
+ message,
+ detailMessage
+ )
+ )
+ }
- value = if (requestInfos.any { it.sendToSettingsImmediately } &&
- requestInfos.size > 1) {
- Log.e(LOG_TAG, "For R+ apps, background permissions must be requested " +
- "individually")
- null
- } else {
- requestInfos
+ sortPermissionGroups(requestInfos)
+
+ value =
+ if (
+ requestInfos.any { it.sendToSettingsImmediately } && requestInfos.size > 1
+ ) {
+ Log.e(
+ LOG_TAG,
+ "For R+ apps, background permissions must be requested " +
+ "individually"
+ )
+ null
+ } else {
+ requestInfos
+ }
}
}
- }
fun sortPermissionGroups(requestInfos: MutableList<RequestInfo>) {
requestInfos.sortWith { rhs, lhs ->
@@ -618,8 +697,8 @@ class GrantPermissionsViewModel(
val lhsHasOneTime = lhs.buttonVisibilities[ALLOW_ONE_TIME_BUTTON]
if (rhsHasOneTime && !lhsHasOneTime) {
-1
- } else if ((!rhsHasOneTime && lhsHasOneTime) ||
- Utils.isHealthPermissionGroup(rhs.groupName)
+ } else if (
+ (!rhsHasOneTime && lhsHasOneTime) || Utils.isHealthPermissionGroup(rhs.groupName)
) {
1
} else {
@@ -636,34 +715,37 @@ class GrantPermissionsViewModel(
return false
}
- val purposes = SafetyLabelUtils.getSafetyLabelSharingPurposesForGroup(safetyLabel,
- permissionGroupName)
+ val purposes =
+ SafetyLabelUtils.getSafetyLabelSharingPurposesForGroup(safetyLabel, permissionGroupName)
return purposes.isNotEmpty()
}
- /**
- * Converts a list of LightAppPermGroups into a list of GroupStates
- */
+ /** Converts a list of LightAppPermGroups into a list of GroupStates */
private fun getRequiredGroupStates(
groups: List<LightAppPermGroup>
): MutableMap<Pair<String, Boolean>, GroupState> {
val groupStates = mutableMapOf<Pair<String, Boolean>, GroupState>()
- val filteredPermissions = unfilteredAffectedPermissions.filter { perm ->
- val group = getGroupWithPerm(perm, groups)
- group != null && isPermissionGrantableAndNotFixed(perm, group)
- }
+ val filteredPermissions =
+ unfilteredAffectedPermissions.filter { perm ->
+ val group = getGroupWithPerm(perm, groups)
+ group != null && isPermissionGrantableAndNotFixed(perm, group)
+ }
for (perm in filteredPermissions) {
val group = getGroupWithPerm(perm, groups)!!
val isBackground = perm in group.backgroundPermNames
- val groupStateInfo = groupStates.getOrPut(group.permGroupName to isBackground) {
- GroupState(group, isBackground)
- }
+ val groupStateInfo =
+ groupStates.getOrPut(group.permGroupName to isBackground) {
+ GroupState(group, isBackground)
+ }
var currGroupState = groupStateInfo.state
if (storedState != null && currGroupState != STATE_UNKNOWN) {
- currGroupState = storedState.getInt(getInstanceStateKey(group.permGroupName,
- isBackground), STATE_UNKNOWN)
+ currGroupState =
+ storedState.getInt(
+ getInstanceStateKey(group.permGroupName, isBackground),
+ STATE_UNKNOWN
+ )
}
val otherGroupPermissions = filteredPermissions.filter { it in group.permissions }
@@ -694,7 +776,6 @@ class GrantPermissionsViewModel(
* target an SDK before the split, this method automatically adds the split off permission.
*
* @param perm The requested permission
- *
* @return The actually requested permissions
*/
private fun computeAffectedPermissions(
@@ -742,8 +823,10 @@ class GrantPermissionsViewModel(
// If the permission is restricted it does not show in the UI and
// is not added to the group at all, so check that first.
if (perm in group.packageInfo.requestedPermissions && perm !in group.permissions) {
- reportRequestResult(perm,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_RESTRICTED_PERMISSION)
+ reportRequestResult(
+ perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_RESTRICTED_PERMISSION
+ )
return false
}
@@ -751,11 +834,12 @@ class GrantPermissionsViewModel(
return !(group.permissions[perm]?.isUserFixed ?: true)
}
- val subGroup = if (perm in group.backgroundPermNames) {
- group.background
- } else {
- group.foreground
- }
+ val subGroup =
+ if (perm in group.backgroundPermNames) {
+ group.background
+ } else {
+ group.foreground
+ }
val lightPermission = group.permissions[perm] ?: return false
@@ -772,18 +856,24 @@ class GrantPermissionsViewModel(
// is still grantable.
return true
}
- } else if (perm in getPartialStorageGrantPermissionsForGroup(group) &&
- lightPermission.isGrantedIncludingAppOp) {
+ } else if (
+ perm in getPartialStorageGrantPermissionsForGroup(group) &&
+ lightPermission.isGrantedIncludingAppOp
+ ) {
// If a partial storage permission is granted as fixed, we should immediately show
// the photo picker
return true
}
- reportRequestResult(perm,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_USER_FIXED)
+ reportRequestResult(
+ perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_USER_FIXED
+ )
return false
} else if (subGroup.isPolicyFixed && !subGroup.isGranted || lightPermission.isPolicyFixed) {
- reportRequestResult(perm,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_POLICY_FIXED)
+ reportRequestResult(
+ perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_POLICY_FIXED
+ )
return false
}
@@ -800,15 +890,18 @@ class GrantPermissionsViewModel(
return policyState
}
- if (perm == POST_NOTIFICATIONS &&
- packageInfo.targetSdkVersion <= Build.VERSION_CODES.S_V2 &&
- group.foreground.isUserSet) {
+ if (
+ perm == POST_NOTIFICATIONS &&
+ packageInfo.targetSdkVersion <= Build.VERSION_CODES.S_V2 &&
+ group.foreground.isUserSet
+ ) {
return STATE_SKIPPED
} else if (perm == READ_MEDIA_VISUAL_USER_SELECTED) {
val partialPerms = getPartialStorageGrantPermissionsForGroup(group)
- val otherRequestedPerms = unfilteredAffectedPermissions.filter { otherPerm ->
- otherPerm in group.permissions && otherPerm !in partialPerms
- }
+ val otherRequestedPerms =
+ unfilteredAffectedPermissions.filter { otherPerm ->
+ otherPerm in group.permissions && otherPerm !in partialPerms
+ }
if (otherRequestedPerms.isEmpty()) {
// If the app requested USER_SELECTED while not supporting the photo picker, or if
// the app explicitly requested only USER_SELECTED and/or ACCESS_MEDIA_LOCATION,
@@ -819,37 +912,50 @@ class GrantPermissionsViewModel(
val isBackground = perm in group.backgroundPermNames
- val hasForegroundRequest = groupRequestedPermissions.any {
- it !in group.backgroundPermNames
- }
+ val hasForegroundRequest =
+ groupRequestedPermissions.any { it !in group.backgroundPermNames }
// Do not attempt to grant background access if foreground access is not either already
// granted or requested
- if (isBackground && !group.foreground.isGrantedExcludingRWROrAllRWR &&
- !hasForegroundRequest) {
- Log.w(LOG_TAG, "Cannot grant $perm as the matching foreground permission is not " +
- "already granted.")
- val affectedPermissions = groupRequestedPermissions.filter {
- it in group.backgroundPermNames
- }
- reportRequestResult(affectedPermissions,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED)
+ if (
+ isBackground && !group.foreground.isGrantedExcludingRWROrAllRWR && !hasForegroundRequest
+ ) {
+ Log.w(
+ LOG_TAG,
+ "Cannot grant $perm as the matching foreground permission is not " +
+ "already granted."
+ )
+ val affectedPermissions =
+ groupRequestedPermissions.filter { it in group.backgroundPermNames }
+ reportRequestResult(
+ affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED
+ )
return STATE_SKIPPED
}
- if ((isBackground && group.background.isGrantedExcludingRWROrAllRWR ||
- !isBackground && group.foreground.isGrantedExcludingRWROrAllRWR) &&
- canAutoGrantWholeGroup(group)) {
+ if (
+ (isBackground && group.background.isGrantedExcludingRWROrAllRWR ||
+ !isBackground && group.foreground.isGrantedExcludingRWROrAllRWR) &&
+ canAutoGrantWholeGroup(group)
+ ) {
if (group.permissions[perm]?.isGrantedIncludingAppOp == false) {
if (isBackground) {
grantBackgroundRuntimePermissions(app, group, listOf(perm))
} else {
grantForegroundRuntimePermissions(app, group, listOf(perm), group.isOneTime)
}
- KotlinUtils.setGroupFlags(app, group, FLAG_PERMISSION_USER_SET to false,
- FLAG_PERMISSION_USER_FIXED to false, filterPermissions = listOf(perm))
- reportRequestResult(perm,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_GRANTED)
+ KotlinUtils.setGroupFlags(
+ app,
+ group,
+ FLAG_PERMISSION_USER_SET to false,
+ FLAG_PERMISSION_USER_FIXED to false,
+ filterPermissions = listOf(perm)
+ )
+ reportRequestResult(
+ perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_GRANTED
+ )
}
return if (storedState == null) {
@@ -862,14 +968,17 @@ class GrantPermissionsViewModel(
}
/**
- * Determines if remaining permissions in the group can be auto granted based on
- * granted permissions in the group.
+ * Determines if remaining permissions in the group can be auto granted based on granted
+ * permissions in the group.
*/
private fun canAutoGrantWholeGroup(group: LightAppPermGroup): Boolean {
// If FINE location is not granted, do not grant it automatically when COARSE
// location is already granted.
- if (group.permGroupName == LOCATION && isLocationAccuracyEnabledForApp(group) &&
- group.allPermissions[ACCESS_FINE_LOCATION]?.isGrantedIncludingAppOp == false) {
+ if (
+ group.permGroupName == LOCATION &&
+ isLocationAccuracyEnabledForApp(group) &&
+ group.allPermissions[ACCESS_FINE_LOCATION]?.isGrantedIncludingAppOp == false
+ ) {
return false
}
// If READ_MEDIA_VISUAL_USER_SELECTED is the only permission in the group that is granted,
@@ -881,10 +990,9 @@ class GrantPermissionsViewModel(
}
/**
- * A partial storage grant happens when:
- * An app which doesn't support the photo picker has READ_MEDIA_VISUAL_USER_SELECTED granted, or
- * An app which does support the photo picker has READ_MEDIA_VISUAL_USER_SELECTED and/or
- * ACCESS_MEDIA_LOCATION granted
+ * A partial storage grant happens when: An app which doesn't support the photo picker has
+ * READ_MEDIA_VISUAL_USER_SELECTED granted, or An app which does support the photo picker has
+ * READ_MEDIA_VISUAL_USER_SELECTED and/or ACCESS_MEDIA_LOCATION granted
*/
private fun isPartialStorageGrant(group: LightAppPermGroup): Boolean {
if (!isPhotoPickerPromptSupported() || group.permGroupName != READ_MEDIA_VISUAL) {
@@ -892,9 +1000,24 @@ class GrantPermissionsViewModel(
}
val partialPerms = getPartialStorageGrantPermissionsForGroup(group)
- return group.isGranted && group.permissions.values.all {
- it.name in partialPerms || (it.name !in partialPerms && !it.isGrantedIncludingAppOp)
+ return group.isGranted &&
+ group.permissions.values.all {
+ it.name in partialPerms || (it.name !in partialPerms && !it.isGrantedIncludingAppOp)
+ }
+ }
+
+ private fun shouldShowPhotoPickerPromptForApp(group: LightAppPermGroup): Boolean {
+ if (
+ !isPhotoPickerPromptEnabled() ||
+ group.packageInfo.targetSdkVersion < Build.VERSION_CODES.TIRAMISU
+ ) {
+ return false
+ }
+ if (group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ return true
}
+ val userSelectedPerm = group.permissions[READ_MEDIA_VISUAL_USER_SELECTED] ?: return false
+ return !userSelectedPerm.isImplicit
}
private fun getStateFromPolicy(perm: String, group: LightAppPermGroup): Int {
@@ -903,36 +1026,54 @@ class GrantPermissionsViewModel(
var state = STATE_UNKNOWN
when (permissionPolicy) {
DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT -> {
- if (AdminRestrictedPermissionsUtils.mayAdminGrantPermission(
- app, perm, user.identifier)) {
+ if (
+ AdminRestrictedPermissionsUtils.mayAdminGrantPermission(
+ app,
+ perm,
+ user.identifier
+ )
+ ) {
if (isBackground) {
grantBackgroundRuntimePermissions(app, group, listOf(perm))
} else {
grantForegroundRuntimePermissions(app, group, listOf(perm))
}
- KotlinUtils.setGroupFlags(app, group, FLAG_PERMISSION_POLICY_FIXED to true,
- FLAG_PERMISSION_USER_SET to false, FLAG_PERMISSION_USER_FIXED to false,
- filterPermissions = listOf(perm))
+ KotlinUtils.setGroupFlags(
+ app,
+ group,
+ FLAG_PERMISSION_POLICY_FIXED to true,
+ FLAG_PERMISSION_USER_SET to false,
+ FLAG_PERMISSION_USER_FIXED to false,
+ filterPermissions = listOf(perm)
+ )
state = STATE_ALLOWED
skipGroup = true
getAutoGrantNotifier().onPermissionAutoGranted(perm)
- reportRequestResult(perm,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_GRANTED)
+ reportRequestResult(
+ perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_GRANTED
+ )
}
}
-
DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY -> {
if (group.permissions[perm]?.isPolicyFixed == false) {
- KotlinUtils.setGroupFlags(app, group, FLAG_PERMISSION_POLICY_FIXED to true,
- FLAG_PERMISSION_USER_SET to false, FLAG_PERMISSION_USER_FIXED to false,
- filterPermissions = listOf(perm))
+ KotlinUtils.setGroupFlags(
+ app,
+ group,
+ FLAG_PERMISSION_POLICY_FIXED to true,
+ FLAG_PERMISSION_USER_SET to false,
+ FLAG_PERMISSION_USER_FIXED to false,
+ filterPermissions = listOf(perm)
+ )
}
state = STATE_DENIED
skipGroup = true
- reportRequestResult(perm,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_DENIED)
+ reportRequestResult(
+ perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_DENIED
+ )
}
}
if (skipGroup && storedState == null) {
@@ -967,12 +1108,14 @@ class GrantPermissionsViewModel(
}
// If this is a legacy app, and a storage group is requested: request all storage groups
- if (!alreadyRequestedStorageGroupsIfNeeded &&
- groupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS &&
- packageInfo.targetSdkVersion <= Build.VERSION_CODES.S_V2) {
+ if (
+ !alreadyRequestedStorageGroupsIfNeeded &&
+ groupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS &&
+ packageInfo.targetSdkVersion <= Build.VERSION_CODES.S_V2
+ ) {
for (storageGroupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS) {
- val groupPerms = appPermGroupLiveDatas[storageGroupName]
- ?.value?.allPermissions?.keys?.toList()
+ val groupPerms =
+ appPermGroupLiveDatas[storageGroupName]?.value?.allPermissions?.keys?.toList()
onPermissionGrantResult(storageGroupName, groupPerms, result, true)
}
return
@@ -983,13 +1126,17 @@ class GrantPermissionsViewModel(
when (result) {
CANCELED -> {
if (foregroundGroupState != null) {
- reportRequestResult(foregroundGroupState.affectedPermissions,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_IGNORED)
+ reportRequestResult(
+ foregroundGroupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_IGNORED
+ )
foregroundGroupState.state = STATE_SKIPPED
}
if (backgroundGroupState != null) {
- reportRequestResult(backgroundGroupState.affectedPermissions,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_IGNORED)
+ reportRequestResult(
+ backgroundGroupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_IGNORED
+ )
backgroundGroupState.state = STATE_SKIPPED
}
requestInfosLiveData.update()
@@ -997,67 +1144,108 @@ class GrantPermissionsViewModel(
}
GRANTED_ALWAYS -> {
if (foregroundGroupState != null) {
- onPermissionGrantResultSingleState(foregroundGroupState,
- affectedForegroundPermissions, granted = true, isOneTime = false,
- doNotAskAgain = false)
+ onPermissionGrantResultSingleState(
+ foregroundGroupState,
+ affectedForegroundPermissions,
+ granted = true,
+ isOneTime = false,
+ doNotAskAgain = false
+ )
}
if (backgroundGroupState != null) {
- onPermissionGrantResultSingleState(backgroundGroupState,
- affectedForegroundPermissions, granted = true, isOneTime = false,
- doNotAskAgain = false)
+ onPermissionGrantResultSingleState(
+ backgroundGroupState,
+ affectedForegroundPermissions,
+ granted = true,
+ isOneTime = false,
+ doNotAskAgain = false
+ )
}
}
GRANTED_FOREGROUND_ONLY -> {
if (foregroundGroupState != null) {
- onPermissionGrantResultSingleState(foregroundGroupState,
- affectedForegroundPermissions, granted = true, isOneTime = false,
- doNotAskAgain = false)
+ onPermissionGrantResultSingleState(
+ foregroundGroupState,
+ affectedForegroundPermissions,
+ granted = true,
+ isOneTime = false,
+ doNotAskAgain = false
+ )
}
if (backgroundGroupState != null) {
- onPermissionGrantResultSingleState(backgroundGroupState,
- affectedForegroundPermissions, granted = false, isOneTime = false,
- doNotAskAgain = false)
+ onPermissionGrantResultSingleState(
+ backgroundGroupState,
+ affectedForegroundPermissions,
+ granted = false,
+ isOneTime = false,
+ doNotAskAgain = false
+ )
}
}
GRANTED_ONE_TIME -> {
if (foregroundGroupState != null) {
- onPermissionGrantResultSingleState(foregroundGroupState,
- affectedForegroundPermissions, granted = true, isOneTime = true,
- doNotAskAgain = false)
+ onPermissionGrantResultSingleState(
+ foregroundGroupState,
+ affectedForegroundPermissions,
+ granted = true,
+ isOneTime = true,
+ doNotAskAgain = false
+ )
}
if (backgroundGroupState != null) {
- onPermissionGrantResultSingleState(backgroundGroupState,
- affectedForegroundPermissions, granted = false, isOneTime = true,
- doNotAskAgain = false)
+ onPermissionGrantResultSingleState(
+ backgroundGroupState,
+ affectedForegroundPermissions,
+ granted = false,
+ isOneTime = true,
+ doNotAskAgain = false
+ )
}
}
- GRANTED_USER_SELECTED, DENIED_MORE -> {
+ GRANTED_USER_SELECTED,
+ DENIED_MORE -> {
if (foregroundGroupState != null) {
grantUserSelectedVisualGroupPermissions(foregroundGroupState)
}
}
DENIED -> {
if (foregroundGroupState != null) {
- onPermissionGrantResultSingleState(foregroundGroupState,
- affectedForegroundPermissions, granted = false, isOneTime = false,
- doNotAskAgain = false)
+ onPermissionGrantResultSingleState(
+ foregroundGroupState,
+ affectedForegroundPermissions,
+ granted = false,
+ isOneTime = false,
+ doNotAskAgain = false
+ )
}
if (backgroundGroupState != null) {
- onPermissionGrantResultSingleState(backgroundGroupState,
- affectedForegroundPermissions, granted = false, isOneTime = false,
- doNotAskAgain = false)
+ onPermissionGrantResultSingleState(
+ backgroundGroupState,
+ affectedForegroundPermissions,
+ granted = false,
+ isOneTime = false,
+ doNotAskAgain = false
+ )
}
}
DENIED_DO_NOT_ASK_AGAIN -> {
if (foregroundGroupState != null) {
- onPermissionGrantResultSingleState(foregroundGroupState,
- affectedForegroundPermissions, granted = false, isOneTime = false,
- doNotAskAgain = true)
+ onPermissionGrantResultSingleState(
+ foregroundGroupState,
+ affectedForegroundPermissions,
+ granted = false,
+ isOneTime = false,
+ doNotAskAgain = true
+ )
}
if (backgroundGroupState != null) {
- onPermissionGrantResultSingleState(backgroundGroupState,
- affectedForegroundPermissions, granted = false, isOneTime = false,
- doNotAskAgain = true)
+ onPermissionGrantResultSingleState(
+ backgroundGroupState,
+ affectedForegroundPermissions,
+ granted = false,
+ isOneTime = false,
+ doNotAskAgain = true
+ )
}
}
}
@@ -1067,32 +1255,60 @@ class GrantPermissionsViewModel(
val userSelectedPerm =
groupState.group.permissions[READ_MEDIA_VISUAL_USER_SELECTED] ?: return
if (userSelectedPerm.isImplicit) {
- val nonSelectedPerms = groupState.group.permissions.keys
- .filter { it != READ_MEDIA_VISUAL_USER_SELECTED }
+ val nonSelectedPerms =
+ groupState.group.permissions.keys.filter { it != READ_MEDIA_VISUAL_USER_SELECTED }
// If the permission is implicit, grant USER_SELECTED as user set, and all other
// permissions as one time, and without app ops.
- grantForegroundRuntimePermissions(app, groupState.group,
- listOf(READ_MEDIA_VISUAL_USER_SELECTED))
- grantForegroundRuntimePermissions(app, groupState.group,
- nonSelectedPerms, isOneTime = true, userFixed = false, withoutAppOps = true)
- val appPermGroup = AppPermissionGroup.create(app, packageName,
- groupState.group.permGroupName, groupState.group.userHandle, false)
+ grantForegroundRuntimePermissions(
+ app,
+ groupState.group,
+ listOf(READ_MEDIA_VISUAL_USER_SELECTED)
+ )
+ grantForegroundRuntimePermissions(
+ app,
+ groupState.group,
+ nonSelectedPerms,
+ isOneTime = true,
+ userFixed = false,
+ withoutAppOps = true
+ )
+ val appPermGroup =
+ AppPermissionGroup.create(
+ app,
+ packageName,
+ groupState.group.permGroupName,
+ groupState.group.userHandle,
+ false
+ )
appPermGroup.setSelfRevoked()
appPermGroup.persistChanges(false, null, nonSelectedPerms.toSet())
} else {
- val partialPerms = getPartialStorageGrantPermissionsForGroup(groupState.group).filter {
- it in groupState.affectedPermissions
- }
+ val partialPerms =
+ getPartialStorageGrantPermissionsForGroup(groupState.group).filter {
+ it in groupState.affectedPermissions
+ }
val nonSelectedPerms = groupState.affectedPermissions.filter { it !in partialPerms }
val setUserFixed = userSelectedPerm.isUserFixed || userSelectedPerm.isUserSet
- grantForegroundRuntimePermissions(app, groupState.group,
- partialPerms.toList(), userFixed = setUserFixed)
- revokeForegroundRuntimePermissions(app, groupState.group,
- userFixed = setUserFixed, oneTime = false, filterPermissions = nonSelectedPerms)
+ grantForegroundRuntimePermissions(
+ app,
+ groupState.group,
+ partialPerms.toList(),
+ userFixed = setUserFixed
+ )
+ revokeForegroundRuntimePermissions(
+ app,
+ groupState.group,
+ userFixed = setUserFixed,
+ oneTime = false,
+ filterPermissions = nonSelectedPerms
+ )
}
groupState.state = STATE_ALLOWED
- reportButtonClickResult(groupState, true,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__PHOTOS_SELECTED)
+ reportButtonClickResult(
+ groupState,
+ true,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__PHOTOS_SELECTED
+ )
}
@SuppressLint("NewApi")
@@ -1109,54 +1325,84 @@ class GrantPermissionsViewModel(
}
val result: Int
if (granted) {
- result = if (isOneTime) {
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_ONE_TIME
- } else {
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED
- }
+ result =
+ if (isOneTime) {
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_ONE_TIME
+ } else {
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED
+ }
if (groupState.isBackground) {
- grantBackgroundRuntimePermissions(app, groupState.group,
- groupState.affectedPermissions)
+ grantBackgroundRuntimePermissions(
+ app,
+ groupState.group,
+ groupState.affectedPermissions
+ )
} else {
if (affectedForegroundPermissions == null) {
- grantForegroundRuntimePermissions(app, groupState.group,
- groupState.affectedPermissions, isOneTime)
+ grantForegroundRuntimePermissions(
+ app,
+ groupState.group,
+ groupState.affectedPermissions,
+ isOneTime
+ )
// This prevents weird flag state when app targetSDK switches from S+ to R-
if (groupState.affectedPermissions.contains(ACCESS_FINE_LOCATION)) {
- KotlinUtils.setFlagsWhenLocationAccuracyChanged(
- app, groupState.group, true)
+ KotlinUtils.setFlagsWhenLocationAccuracyChanged(app, groupState.group, true)
}
} else {
- val newGroup = grantForegroundRuntimePermissions(app,
- groupState.group, affectedForegroundPermissions, isOneTime)
+ val newGroup =
+ grantForegroundRuntimePermissions(
+ app,
+ groupState.group,
+ affectedForegroundPermissions,
+ isOneTime
+ )
if (!isOneTime || newGroup.isOneTime) {
- KotlinUtils.setFlagsWhenLocationAccuracyChanged(app, newGroup,
- affectedForegroundPermissions.contains(ACCESS_FINE_LOCATION))
+ KotlinUtils.setFlagsWhenLocationAccuracyChanged(
+ app,
+ newGroup,
+ affectedForegroundPermissions.contains(ACCESS_FINE_LOCATION)
+ )
}
}
}
groupState.state = STATE_ALLOWED
} else {
if (groupState.isBackground) {
- revokeBackgroundRuntimePermissions(app, groupState.group,
- userFixed = doNotAskAgain, filterPermissions = groupState.affectedPermissions)
+ revokeBackgroundRuntimePermissions(
+ app,
+ groupState.group,
+ userFixed = doNotAskAgain,
+ filterPermissions = groupState.affectedPermissions
+ )
} else {
- if (affectedForegroundPermissions == null ||
- affectedForegroundPermissions.contains(ACCESS_COARSE_LOCATION)) {
- revokeForegroundRuntimePermissions(app, groupState.group,
+ if (
+ affectedForegroundPermissions == null ||
+ affectedForegroundPermissions.contains(ACCESS_COARSE_LOCATION)
+ ) {
+ revokeForegroundRuntimePermissions(
+ app,
+ groupState.group,
userFixed = doNotAskAgain,
- filterPermissions = groupState.affectedPermissions, oneTime = isOneTime)
+ filterPermissions = groupState.affectedPermissions,
+ oneTime = isOneTime
+ )
} else {
- revokeForegroundRuntimePermissions(app, groupState.group,
+ revokeForegroundRuntimePermissions(
+ app,
+ groupState.group,
userFixed = doNotAskAgain,
- filterPermissions = affectedForegroundPermissions, oneTime = isOneTime)
+ filterPermissions = affectedForegroundPermissions,
+ oneTime = isOneTime
+ )
}
}
- result = if (doNotAskAgain) {
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_WITH_PREJUDICE
- } else {
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED
- }
+ result =
+ if (doNotAskAgain) {
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_WITH_PREJUDICE
+ } else {
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED
+ }
groupState.state = STATE_DENIED
}
reportButtonClickResult(groupState, granted, result)
@@ -1166,8 +1412,12 @@ class GrantPermissionsViewModel(
reportRequestResult(groupState.affectedPermissions, result)
// group state has changed, reload liveData
requestInfosLiveData.update()
- PermissionDecisionStorageImpl.recordPermissionDecision(app.applicationContext,
- packageName, groupState.group.permGroupName, granted)
+ PermissionDecisionStorageImpl.recordPermissionDecision(
+ app.applicationContext,
+ packageName,
+ groupState.group.permGroupName,
+ granted
+ )
PermissionChangeStorageImpl.recordPermissionChange(packageName)
if (granted) {
startDrivingDecisionReminderServiceIfNecessary(groupState.group.permGroupName)
@@ -1183,7 +1433,10 @@ class GrantPermissionsViewModel(
return
}
DrivingDecisionReminderService.startServiceIfCurrentlyRestricted(
- Utils.getUserContext(app, user), packageName, permGroupName)
+ Utils.getUserContext(app, user),
+ packageName,
+ permGroupName
+ )
}
private fun getGroupWithPerm(
@@ -1207,12 +1460,13 @@ class GrantPermissionsViewModel(
internal var state: Int = STATE_UNKNOWN
) {
override fun toString(): String {
- val stateStr: String = when (state) {
- STATE_UNKNOWN -> "unknown"
- STATE_ALLOWED -> "granted"
- STATE_DENIED -> "denied"
- else -> "skipped"
- }
+ val stateStr: String =
+ when (state) {
+ STATE_UNKNOWN -> "unknown"
+ STATE_ALLOWED -> "granted"
+ STATE_DENIED -> "denied"
+ else -> "skipped"
+ }
return "${group.permGroupName} $isBackground $stateStr $affectedPermissions"
}
}
@@ -1231,19 +1485,30 @@ class GrantPermissionsViewModel(
*/
private fun reportRequestResult(permission: String, result: Int) {
val isImplicit = permission !in requestedPermissions
- val isPermissionRationaleShown = shouldShowPermissionRationale(
- safetyLabelInfoLiveData?.value?.safetyLabel,
- PermissionMapping.getGroupOfPlatformPermission(permission))
-
- Log.v(LOG_TAG, "Permission grant result requestId=$sessionId " +
- "callingUid=${packageInfo.uid} callingPackage=$packageName permission=$permission " +
- "isImplicit=$isImplicit result=$result " +
- "isPermissionRationaleShown=$isPermissionRationaleShown")
+ val isPermissionRationaleShown =
+ shouldShowPermissionRationale(
+ safetyLabelInfoLiveData?.value?.safetyLabel,
+ PermissionMapping.getGroupOfPlatformPermission(permission)
+ )
+
+ Log.v(
+ LOG_TAG,
+ "Permission grant result requestId=$sessionId " +
+ "callingUid=${packageInfo.uid} callingPackage=$packageName permission=$permission " +
+ "isImplicit=$isImplicit result=$result " +
+ "isPermissionRationaleShown=$isPermissionRationaleShown"
+ )
PermissionControllerStatsLog.write(
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED, sessionId,
- packageInfo.uid, packageName, permission, isImplicit, result,
- isPermissionRationaleShown)
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED,
+ sessionId,
+ packageInfo.uid,
+ packageName,
+ permission,
+ isImplicit,
+ result,
+ isPermissionRationaleShown
+ )
}
/**
@@ -1263,7 +1528,7 @@ class GrantPermissionsViewModel(
* Determine if the activity should return permission state to the caller
*
* @return Whether or not state should be returned. False only if the package is pre-M, true
- * otherwise.
+ * otherwise.
*/
fun shouldReturnPermissionState(): Boolean {
return if (packageInfoLiveData.value != null) {
@@ -1272,8 +1537,10 @@ class GrantPermissionsViewModel(
// Should not be reached, as this method shouldn't be called before data is passed to
// the activity for the first time
try {
- Utils.getUserContext(app, user).packageManager
- .getApplicationInfo(packageName, 0).targetSdkVersion >= Build.VERSION_CODES.M
+ Utils.getUserContext(app, user)
+ .packageManager
+ .getApplicationInfo(packageName, 0)
+ .targetSdkVersion >= Build.VERSION_CODES.M
} catch (e: PackageManager.NameNotFoundException) {
true
}
@@ -1286,14 +1553,16 @@ class GrantPermissionsViewModel(
permGroupsToSkip.add(HEALTH_PERMISSION_GROUP)
requestInfosLiveData.update()
}
- val healthPermissions = unfilteredAffectedPermissions.filter { permission ->
- isHealthPermission(activity, permission)
- }.toTypedArray()
- val intent: Intent = Intent(ACTION_REQUEST_HEALTH_PERMISSIONS)
- .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
- .putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES, healthPermissions)
- .putExtra(Intent.EXTRA_USER, Process.myUserHandle())
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ val healthPermissions =
+ unfilteredAffectedPermissions
+ .filter { permission -> isHealthPermission(activity, permission) }
+ .toTypedArray()
+ val intent: Intent =
+ Intent(ACTION_REQUEST_HEALTH_PERMISSIONS)
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
+ .putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES, healthPermissions)
+ .putExtra(Intent.EXTRA_USER, Process.myUserHandle())
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
activity.startActivityForResult(intent, APP_PERMISSION_REQUEST_CODE)
}
}
@@ -1309,14 +1578,23 @@ class GrantPermissionsViewModel(
activityResultCallback = Consumer { data ->
if (data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED) == null) {
// User didn't interact, count against rate limit
- val group = groupStates[groupName to false]?.group
- ?: groupStates[groupName to true]?.group ?: return@Consumer
+ val group =
+ groupStates[groupName to false]?.group
+ ?: groupStates[groupName to true]?.group ?: return@Consumer
if (group.background.isUserSet) {
- KotlinUtils.setGroupFlags(app, group, FLAG_PERMISSION_USER_FIXED to true,
- filterPermissions = group.backgroundPermNames)
+ KotlinUtils.setGroupFlags(
+ app,
+ group,
+ FLAG_PERMISSION_USER_FIXED to true,
+ filterPermissions = group.backgroundPermNames
+ )
} else {
- KotlinUtils.setGroupFlags(app, group, FLAG_PERMISSION_USER_SET to true,
- filterPermissions = group.backgroundPermNames)
+ KotlinUtils.setGroupFlags(
+ app,
+ group,
+ FLAG_PERMISSION_USER_SET to true,
+ filterPermissions = group.backgroundPermNames
+ )
}
}
@@ -1344,18 +1622,8 @@ class GrantPermissionsViewModel(
}
requestInfosLiveData.update()
}
- // A clone profile doesn't have a MediaProvider. If this user is a clone profile, open
- // the photo picker in the parent profile
- val userManager = activity.getSystemService(UserManager::class.java)!!
- val user = if (userManager.isCloneProfile) {
- userManager.getProfileParent(Process.myUserHandle()) ?: Process.myUserHandle()
- } else {
- Process.myUserHandle()
- }
- activity.startActivityForResultAsUser(Intent(MediaStore.ACTION_USER_SELECT_IMAGES_FOR_APP)
- .putExtra(Intent.EXTRA_UID, packageInfo.uid)
- .setType(KotlinUtils.getMimeTypeForPermissions(unfilteredAffectedPermissions)),
- PHOTO_PICKER_REQUEST_CODE, user)
+ openPhotoPickerForApp(activity, packageInfo.uid, unfilteredAffectedPermissions,
+ PHOTO_PICKER_REQUEST_CODE)
}
/**
@@ -1378,21 +1646,22 @@ class GrantPermissionsViewModel(
}
/**
- * Shows the Permission Rationale Dialog. For use with U+ only, otherwise no-op.
- *
- * @param activity The current activity
- * @param groupName The name of the permission group whose fragment should be opened
- */
+ * Shows the Permission Rationale Dialog. For use with U+ only, otherwise no-op.
+ *
+ * @param activity The current activity
+ * @param groupName The name of the permission group whose fragment should be opened
+ */
fun showPermissionRationaleActivity(activity: Activity, groupName: String) {
if (!SdkLevel.isAtLeastU()) {
return
}
- val intent = Intent(activity, PermissionRationaleActivity::class.java).apply {
- putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
- putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName)
- putExtra(Constants.EXTRA_SESSION_ID, sessionId)
- }
+ val intent =
+ Intent(activity, PermissionRationaleActivity::class.java).apply {
+ putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
+ putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName)
+ putExtra(Constants.EXTRA_SESSION_ID, sessionId)
+ }
activityResultCallback = Consumer { data ->
val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED)
if (returnGroupName != null) {
@@ -1406,14 +1675,17 @@ class GrantPermissionsViewModel(
}
private fun startAppPermissionFragment(activity: Activity, groupName: String) {
- val intent = Intent(Intent.ACTION_MANAGE_APP_PERMISSION)
- .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
- .putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName)
- .putExtra(Intent.EXTRA_USER, user)
- .putExtra(ManagePermissionsActivity.EXTRA_CALLER_NAME,
- GrantPermissionsActivity::class.java.name)
- .putExtra(Constants.EXTRA_SESSION_ID, sessionId)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ val intent =
+ Intent(Intent.ACTION_MANAGE_APP_PERMISSION)
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
+ .putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName)
+ .putExtra(Intent.EXTRA_USER, user)
+ .putExtra(
+ ManagePermissionsActivity.EXTRA_CALLER_NAME,
+ GrantPermissionsActivity::class.java.name
+ )
+ .putExtra(Constants.EXTRA_SESSION_ID, sessionId)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
activity.startActivityForResult(intent, APP_PERMISSION_REQUEST_CODE)
}
@@ -1429,42 +1701,58 @@ class GrantPermissionsViewModel(
when (result) {
GRANTED_ALWAYS -> {
if (foregroundGroupState != null) {
- reportRequestResult(foregroundGroupState.affectedPermissions,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_IN_SETTINGS)
+ reportRequestResult(
+ foregroundGroupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_IN_SETTINGS
+ )
}
if (backgroundGroupState != null) {
- reportRequestResult(backgroundGroupState.affectedPermissions,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_IN_SETTINGS)
+ reportRequestResult(
+ backgroundGroupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_IN_SETTINGS
+ )
}
}
GRANTED_FOREGROUND_ONLY -> {
if (foregroundGroupState != null) {
- reportRequestResult(foregroundGroupState.affectedPermissions,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_IN_SETTINGS)
+ reportRequestResult(
+ foregroundGroupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_IN_SETTINGS
+ )
}
if (backgroundGroupState != null) {
- reportRequestResult(backgroundGroupState.affectedPermissions,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_IN_SETTINGS)
+ reportRequestResult(
+ backgroundGroupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_IN_SETTINGS
+ )
}
}
DENIED -> {
if (foregroundGroupState != null) {
- reportRequestResult(foregroundGroupState.affectedPermissions,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_IN_SETTINGS)
+ reportRequestResult(
+ foregroundGroupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_IN_SETTINGS
+ )
}
if (backgroundGroupState != null) {
- reportRequestResult(backgroundGroupState.affectedPermissions,
- PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_IN_SETTINGS)
+ reportRequestResult(
+ backgroundGroupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_IN_SETTINGS
+ )
}
}
DENIED_DO_NOT_ASK_AGAIN -> {
if (foregroundGroupState != null) {
- reportRequestResult(foregroundGroupState.affectedPermissions,
- deniedPrejudiceInSettings)
+ reportRequestResult(
+ foregroundGroupState.affectedPermissions,
+ deniedPrejudiceInSettings
+ )
}
if (backgroundGroupState != null) {
- reportRequestResult(backgroundGroupState.affectedPermissions,
- deniedPrejudiceInSettings)
+ reportRequestResult(
+ backgroundGroupState.affectedPermissions,
+ deniedPrejudiceInSettings
+ )
}
}
}
@@ -1472,12 +1760,10 @@ class GrantPermissionsViewModel(
private fun isLocationAccuracyEnabledForApp(group: LightAppPermGroup): Boolean {
return isLocationAccuracyEnabled() &&
- group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.S
+ group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.S
}
- /**
- * Log all permission groups which were requested
- */
+ /** Log all permission groups which were requested */
fun logRequestedPermissionGroups() {
if (groupStates.isEmpty()) {
return
@@ -1491,7 +1777,7 @@ class GrantPermissionsViewModel(
*
* @param groupName The name of the permission group which was interacted with
* @param selectedPrecision Selected precision of the location permission - bit flags indicate
- * which locations were chosen
+ * which locations were chosen
* @param clickedButton The button that was clicked by the user
* @param presentedButtons All buttons which were shown to the user
*/
@@ -1507,29 +1793,42 @@ class GrantPermissionsViewModel(
}
if (!requestInfosLiveData.isInitialized || !packageInfoLiveData.isInitialized) {
- Log.wtf(LOG_TAG, "Logged buttons presented and clicked permissionGroupName=" +
+ Log.wtf(
+ LOG_TAG,
+ "Logged buttons presented and clicked permissionGroupName=" +
"$groupName package=$packageName presentedButtons=$presentedButtons " +
"clickedButton=$clickedButton isPermissionRationaleShown=" +
"$isPermissionRationaleShown sessionId=$sessionId, but requests were not yet" +
- "initialized", IllegalStateException())
+ "initialized",
+ IllegalStateException()
+ )
return
}
- PermissionControllerStatsLog.write(GRANT_PERMISSIONS_ACTIVITY_BUTTON_ACTIONS,
- groupName, packageInfo.uid, packageName, presentedButtons, clickedButton, sessionId,
- packageInfo.targetSdkVersion, selectedPrecision,
- isPermissionRationaleShown)
- Log.v(LOG_TAG, "Logged buttons presented and clicked permissionGroupName=" +
+ PermissionControllerStatsLog.write(
+ GRANT_PERMISSIONS_ACTIVITY_BUTTON_ACTIONS,
+ groupName,
+ packageInfo.uid,
+ packageName,
+ presentedButtons,
+ clickedButton,
+ sessionId,
+ packageInfo.targetSdkVersion,
+ selectedPrecision,
+ isPermissionRationaleShown
+ )
+ Log.v(
+ LOG_TAG,
+ "Logged buttons presented and clicked permissionGroupName=" +
"$groupName uid=${packageInfo.uid} selectedPrecision=$selectedPrecision " +
"package=$packageName presentedButtons=$presentedButtons " +
"clickedButton=$clickedButton isPermissionRationaleShown=" +
"$isPermissionRationaleShown sessionId=$sessionId " +
- "targetSdk=${packageInfo.targetSdkVersion}")
+ "targetSdk=${packageInfo.targetSdkVersion}"
+ )
}
- /**
- * Use the autoGrantNotifier to notify of auto-granted permissions.
- */
+ /** Use the autoGrantNotifier to notify of auto-granted permissions. */
fun autoGrantNotify() {
autoGrantNotifier?.notifyOfAutoGrantPermissions(true)
}
@@ -1571,8 +1870,9 @@ class GrantPermissionsViewModel(
.filter { !it.isNullOrEmpty() }
// POST_NOTIFICATIONS is actively disallowed to be declared by apps below T.
// Others we don't care as much if they were declared but not used.
- .filter { targetSdkVersion >= Build.VERSION_CODES.TIRAMISU ||
- it != POST_NOTIFICATIONS }
+ .filter {
+ targetSdkVersion >= Build.VERSION_CODES.TIRAMISU || it != POST_NOTIFICATIONS
+ }
.filterIsInstance<String>()
}
}
@@ -1593,7 +1893,13 @@ class GrantPermissionsViewModelFactory(
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
- return GrantPermissionsViewModel(app, packageName, requestedPermissions,
- sessionId, savedState) as T
+ return GrantPermissionsViewModel(
+ app,
+ packageName,
+ requestedPermissions,
+ sessionId,
+ savedState
+ )
+ as T
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManageCustomPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManageCustomPermissionsViewModel.kt
index 09866870a..bd80a88cd 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManageCustomPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManageCustomPermissionsViewModel.kt
@@ -35,12 +35,9 @@ import com.android.permissioncontroller.permission.utils.navigateSafe
*
* @param app The current application of the fragment
*/
-class ManageCustomPermissionsViewModel(
- private val app: Application
-) : AndroidViewModel(app) {
+class ManageCustomPermissionsViewModel(private val app: Application) : AndroidViewModel(app) {
- val uiDataLiveData = PermGroupsPackagesUiInfoLiveData(app,
- UsedCustomPermGroupNamesLiveData())
+ val uiDataLiveData = PermGroupsPackagesUiInfoLiveData(app, UsedCustomPermGroupNamesLiveData())
/**
* Navigate to a Permission Apps fragment
@@ -58,12 +55,10 @@ class ManageCustomPermissionsViewModel(
*
* @param app The current application of the fragment
*/
-class ManageCustomPermissionsViewModelFactory(
- private val app: Application
-) : ViewModelProvider.Factory {
+class ManageCustomPermissionsViewModelFactory(private val app: Application) :
+ ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
- @Suppress("UNCHECKED_CAST")
- return ManageCustomPermissionsViewModel(app) as T
+ @Suppress("UNCHECKED_CAST") return ManageCustomPermissionsViewModel(app) as T
}
}
@@ -72,14 +67,13 @@ class ManageCustomPermissionsViewModelFactory(
* package. This includes single-permission permission groups, as well as the Undefined permission
* group, and any other permission groups not defined by the system.
*/
-class UsedCustomPermGroupNamesLiveData :
- SmartUpdateMediatorLiveData<List<String>>() {
+class UsedCustomPermGroupNamesLiveData : SmartUpdateMediatorLiveData<List<String>>() {
init {
- addSource(PermGroupsPackagesLiveData.get(customGroups = true)) {
- value = it.keys.toList()
- }
+ addSource(PermGroupsPackagesLiveData.get(customGroups = true)) { value = it.keys.toList() }
}
- override fun onUpdate() { /* No op override */ }
+ override fun onUpdate() {
+ /* No op override */
+ }
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManagePermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManagePermissionsViewModel.kt
index 871a89aeb..f964fb9d2 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManagePermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManagePermissionsViewModel.kt
@@ -26,71 +26,71 @@ import com.android.permissioncontroller.permission.model.livedatatypes.PermGroup
/**
* A [androidx.lifecycle.ViewModel] for [ManagePermissionsFragment] and
- * [ManagePermissionsOtherFragment].
- * However, [ManagePermissionsViewModel] is designed in a way so that its owner should be an
- * [Activity][androidx.fragment.app.FragmentActivity] rather than individual
- * [Fragments][androidx.fragment.app.Fragment], and the aforementioned Fragments that manage
- * different sets of the permission groups should to share a single instance of
+ * [ManagePermissionsOtherFragment]. However, [ManagePermissionsViewModel] is designed in a way so
+ * that its owner should be an [Activity][androidx.fragment.app.FragmentActivity] rather than
+ * individual [Fragments][androidx.fragment.app.Fragment], and the aforementioned Fragments that
+ * manage different sets of the permission groups should to share a single instance of
* [ManagePermissionsViewModel].
*/
class ManagePermissionsViewModel(app: Application) : AndroidViewModel(app) {
- /**
- * [LiveData] that contains a list of all platform-defined permission groups.
- */
+ /** [LiveData] that contains a list of all platform-defined permission groups. */
val standardPermGroupsLiveData: LiveData<List<PermGroupPackagesUiInfo>> =
MediatorLiveData<List<PermGroupPackagesUiInfo>>().apply {
addSource(PermGroupsPackagesUiInfoLiveData(app, StandardPermGroupNamesLiveData)) {
- permGroups -> value = permGroups.values.filterNotNull()
+ permGroups ->
+ value = permGroups.values.filterNotNull()
}
}
/**
- * [LiveData] that contains a list of platform-defined permission groups, such
- * that at least one the permissions in the group has been requested at runtime by at least one
- * non-system application or has been pregranted to a non-system application.
+ * [LiveData] that contains a list of platform-defined permission groups, such that at least one
+ * the permissions in the group has been requested at runtime by at least one non-system
+ * application or has been pregranted to a non-system application.
+ *
* @see com.android.permissioncontroller.permission.ui.television.ManagePermissionsFragment
*/
val usedPermissionGroups: LiveData<List<PermGroupPackagesUiInfo>> =
MediatorLiveData<List<PermGroupPackagesUiInfo>>().apply {
- addSource(standardPermGroupsLiveData) {
- permGroups -> value = permGroups.filter { it.nonSystemUserSetOrPreGranted > 0 }
+ addSource(standardPermGroupsLiveData) { permGroups ->
+ value = permGroups.filter { it.nonSystemUserSetOrPreGranted > 0 }
}
}
/**
- * [LiveData] that contains a list of platform-defined permission groups, such that all
- * of the permissions in the group neither has been requested at runtime by any of the
- * non-system applications nor has been pregranted to any such application. But at least one of
- * the permissions in the group is requested by or pregranted to at least one system
- * application, other than the Shell (we do not show permission groups that are granted only to
- * the Shell, because it has all the permissions granted).
+ * [LiveData] that contains a list of platform-defined permission groups, such that all of the
+ * permissions in the group neither has been requested at runtime by any of the non-system
+ * applications nor has been pregranted to any such application. But at least one of the
+ * permissions in the group is requested by or pregranted to at least one system application,
+ * other than the Shell (we do not show permission groups that are granted only to the Shell,
+ * because it has all the permissions granted).
+ *
* @see com.android.permissioncontroller.permission.ui.television.ManagePermissionsOtherFragment
*/
val unusedPermissionGroups: LiveData<List<PermGroupPackagesUiInfo>> =
MediatorLiveData<List<PermGroupPackagesUiInfo>>().apply {
- addSource(standardPermGroupsLiveData) {
- permGroups -> value = permGroups
- .filter { it.nonSystemUserSetOrPreGranted == 0 }
- .filter { it.systemUserSetOrPreGranted > 0 }
- .filterNot { it.onlyShellPackageGranted }
+ addSource(standardPermGroupsLiveData) { permGroups ->
+ value =
+ permGroups
+ .filter { it.nonSystemUserSetOrPreGranted == 0 }
+ .filter { it.systemUserSetOrPreGranted > 0 }
+ .filterNot { it.onlyShellPackageGranted }
}
}
/**
- * [LiveData] that contains a list of the application-defined permission groups
- * (a.k.a. "custom" permissions), such that at least one of the permissions in the group has
- * been requested at runtime by or has been pregranted to at least one application (system or
- * non-system).
+ * [LiveData] that contains a list of the application-defined permission groups (a.k.a. "custom"
+ * permissions), such that at least one of the permissions in the group has been requested at
+ * runtime by or has been pregranted to at least one application (system or non-system).
+ *
* @see com.android.permissioncontroller.permission.ui.television.ManagePermissionsOtherFragment
*/
val additionalPermissionGroups: LiveData<List<PermGroupPackagesUiInfo>> =
MediatorLiveData<List<PermGroupPackagesUiInfo>>().apply {
- addSource(PermGroupsPackagesUiInfoLiveData(
- app, UsedCustomPermGroupNamesLiveData())) {
- permGroups -> value = permGroups.values
- .filterNotNull()
- .filter {
+ addSource(PermGroupsPackagesUiInfoLiveData(app, UsedCustomPermGroupNamesLiveData())) {
+ permGroups ->
+ value =
+ permGroups.values.filterNotNull().filter {
(it.nonSystemUserSetOrPreGranted > 0) or (it.systemUserSetOrPreGranted > 0)
}
}
@@ -98,16 +98,18 @@ class ManagePermissionsViewModel(app: Application) : AndroidViewModel(app) {
/**
* [LiveData] that indicates whether there any unused or additional permission groups.
+ *
* @see com.android.permissioncontroller.permission.ui.television.ManagePermissionsFragment
*/
@get:JvmName("hasUnusedOrAdditionalPermissionGroups")
val hasUnusedOrAdditionalPermissionGroups: LiveData<Boolean> =
MediatorLiveData<Boolean>().apply {
val updateValue: (Any?) -> Unit = {
- value = !unusedPermissionGroups.value.isNullOrEmpty() ||
- !additionalPermissionGroups.value.isNullOrEmpty()
+ value =
+ !unusedPermissionGroups.value.isNullOrEmpty() ||
+ !additionalPermissionGroups.value.isNullOrEmpty()
}
addSource(unusedPermissionGroups, updateValue)
addSource(additionalPermissionGroups, updateValue)
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManageStandardPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManageStandardPermissionsViewModel.kt
index e529f1cd5..b7754e66e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManageStandardPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ManageStandardPermissionsViewModel.kt
@@ -37,20 +37,16 @@ import com.android.permissioncontroller.permission.utils.navigateSafe
/**
* A ViewModel for the ManageStandardPermissionsFragment. Provides a LiveData which watches over all
* platform permission groups, and sends async updates when these groups have changes. It also
- * provides a liveData which watches the custom permission groups of the system, and provides
- * a list of group names.
+ * provides a liveData which watches the custom permission groups of the system, and provides a list
+ * of group names.
+ *
* @param app The current application of the fragment
*/
-class ManageStandardPermissionsViewModel(
- private val app: Application
-) : AndroidViewModel(app) {
+class ManageStandardPermissionsViewModel(private val app: Application) : AndroidViewModel(app) {
- val uiDataLiveData = PermGroupsPackagesUiInfoLiveData(app,
- StandardPermGroupNamesLiveData)
+ val uiDataLiveData = PermGroupsPackagesUiInfoLiveData(app, StandardPermGroupNamesLiveData)
val numCustomPermGroups = NumCustomPermGroupsWithPackagesLiveData()
- val numAutoRevoked = Transformations.map(unusedAutoRevokePackagesLiveData) {
- it?.size ?: 0
- }
+ val numAutoRevoked = Transformations.map(unusedAutoRevokePackagesLiveData) { it?.size ?: 0 }
/**
* Navigate to the Custom Permissions screen
@@ -74,8 +70,7 @@ class ManageStandardPermissionsViewModel(
Utils.navigateToNotificationSettings(fragment.context!!)
return
}
- if (Utils.isHealthPermissionUiEnabled() &&
- groupName == HEALTH_PERMISSION_GROUP) {
+ if (Utils.isHealthPermissionUiEnabled() && groupName == HEALTH_PERMISSION_GROUP) {
Utils.navigateToHealthConnectSettings(fragment.context!!)
return
}
@@ -91,15 +86,12 @@ class ManageStandardPermissionsViewModel(
* A LiveData which tracks the number of custom permission groups that are used by at least one
* package
*/
-class NumCustomPermGroupsWithPackagesLiveData() :
- SmartUpdateMediatorLiveData<Int>() {
+class NumCustomPermGroupsWithPackagesLiveData() : SmartUpdateMediatorLiveData<Int>() {
private val customPermGroupPackages = PermGroupsPackagesLiveData.get(customGroups = true)
init {
- addSource(customPermGroupPackages) {
- update()
- }
+ addSource(customPermGroupPackages) { update() }
}
override fun onUpdate() {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt
index 1b17041b6..c64fd2e6f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt
@@ -67,9 +67,9 @@ import java.util.concurrent.TimeUnit
import kotlin.math.max
/**
- * ViewModel for the PermissionAppsFragment. Has a liveData with all of the UI info for each
- * package which requests permissions in this permission group, a liveData which tracks whether or
- * not to show system apps, and a liveData tracking whether there are any system apps which request
+ * ViewModel for the PermissionAppsFragment. Has a liveData with all of the UI info for each package
+ * which requests permissions in this permission group, a liveData which tracks whether or not to
+ * show system apps, and a liveData tracking whether there are any system apps which request
* permissions in this group.
*
* @param app The current application
@@ -96,10 +96,10 @@ class PermissionAppsViewModel(
val categorizedAppsLiveData = CategorizedAppsLiveData(groupName)
@get:RequiresApi(Build.VERSION_CODES.S)
- val sensorStatusLiveData: SensorStatusLiveData by lazy(LazyThreadSafetyMode.NONE)
- @RequiresApi(Build.VERSION_CODES.S) {
- SensorStatusLiveData()
- }
+ val sensorStatusLiveData: SensorStatusLiveData by
+ lazy(LazyThreadSafetyMode.NONE) @RequiresApi(Build.VERSION_CODES.S) {
+ SensorStatusLiveData()
+ }
fun updateShowSystem(showSystem: Boolean) {
if (showSystem != state.get(SHOULD_SHOW_SYSTEM_KEY)) {
@@ -111,9 +111,7 @@ class PermissionAppsViewModel(
get() = state.get(CREATION_LOGGED_KEY) ?: false
set(value) = state.set(CREATION_LOGGED_KEY, value)
- /**
- * A LiveData that tracks the status (blocked or available) of a sensor
- */
+ /** A LiveData that tracks the status (blocked or available) of a sensor */
@RequiresApi(Build.VERSION_CODES.S)
inner class SensorStatusLiveData() : SmartUpdateMediatorLiveData<Boolean>() {
val sensorPrivacyManager = app.getSystemService(SensorPrivacyManager::class.java)!!
@@ -157,13 +155,9 @@ class PermissionAppsViewModel(
}
}
- private val listener = { _: Int, status: Boolean ->
- value = status
- }
+ private val listener = { _: Int, status: Boolean -> value = status }
- private val locListener = { status: Boolean ->
- value = !status
- }
+ private val locListener = { status: Boolean -> value = !status }
override fun onUpdate() {
// Do nothing
@@ -171,8 +165,9 @@ class PermissionAppsViewModel(
}
inner class CategorizedAppsLiveData(groupName: String) :
- MediatorLiveData<@kotlin.jvm.JvmSuppressWildcards
- Map<Category, List<Pair<String, UserHandle>>>>() {
+ MediatorLiveData<
+ @kotlin.jvm.JvmSuppressWildcards Map<Category, List<Pair<String, UserHandle>>>
+ >() {
private val packagesUiInfoLiveData = SinglePermGroupPackagesUiInfoLiveData[groupName]
init {
@@ -193,18 +188,18 @@ class PermissionAppsViewModel(
}
addSource(packagesUiInfoLiveData) {
- if (fullStorageLiveData == null || fullStorageLiveData.isInitialized)
- update()
+ if (fullStorageLiveData == null || fullStorageLiveData.isInitialized) update()
}
addSource(shouldShowSystemLiveData) {
- if (fullStorageLiveData == null || fullStorageLiveData.isInitialized)
- update()
+ if (fullStorageLiveData == null || fullStorageLiveData.isInitialized) update()
}
- if ((fullStorageLiveData == null || fullStorageLiveData.isInitialized) &&
- packagesUiInfoLiveData.isInitialized) {
- packagesWithFullFileAccess = fullStorageLiveData?.value?.filter { it.isGranted }
- ?: emptyList()
+ if (
+ (fullStorageLiveData == null || fullStorageLiveData.isInitialized) &&
+ packagesUiInfoLiveData.isInitialized
+ ) {
+ packagesWithFullFileAccess =
+ fullStorageLiveData?.value?.filter { it.isGranted } ?: emptyList()
update()
}
}
@@ -218,12 +213,14 @@ class PermissionAppsViewModel(
categoryMap[Category.ASK] = mutableListOf()
categoryMap[Category.DENIED] = mutableListOf()
- val packageMap = packagesUiInfoLiveData.value ?: run {
- if (packagesUiInfoLiveData.isInitialized) {
- value = categoryMap
- }
- return
- }
+ val packageMap =
+ packagesUiInfoLiveData.value
+ ?: run {
+ if (packagesUiInfoLiveData.isInitialized) {
+ value = categoryMap
+ }
+ return
+ }
val hasSystem = packageMap.any { it.value.isSystem && it.value.shouldShow }
if (hasSystem != state.get(HAS_SYSTEM_APPS_KEY)) {
@@ -241,22 +238,31 @@ class PermissionAppsViewModel(
continue
}
- if (uiInfo.permGrantState == PermGrantState.PERMS_ALLOWED_ALWAYS ||
- uiInfo.permGrantState == PermGrantState.PERMS_ALLOWED_FOREGROUND_ONLY) {
+ if (
+ uiInfo.permGrantState == PermGrantState.PERMS_ALLOWED_ALWAYS ||
+ uiInfo.permGrantState == PermGrantState.PERMS_ALLOWED_FOREGROUND_ONLY
+ ) {
showAlwaysAllowedString = true
}
- var category = when (uiInfo.permGrantState) {
- PermGrantState.PERMS_ALLOWED -> Category.ALLOWED
- PermGrantState.PERMS_ALLOWED_FOREGROUND_ONLY -> Category.ALLOWED_FOREGROUND
- PermGrantState.PERMS_ALLOWED_ALWAYS -> Category.ALLOWED
- PermGrantState.PERMS_DENIED -> Category.DENIED
- PermGrantState.PERMS_ASK -> Category.ASK
- }
+ var category =
+ when (uiInfo.permGrantState) {
+ PermGrantState.PERMS_ALLOWED -> Category.ALLOWED
+ PermGrantState.PERMS_ALLOWED_FOREGROUND_ONLY -> Category.ALLOWED_FOREGROUND
+ PermGrantState.PERMS_ALLOWED_ALWAYS -> Category.ALLOWED
+ PermGrantState.PERMS_DENIED -> Category.DENIED
+ PermGrantState.PERMS_ASK -> Category.ASK
+ }
- if (!SdkLevel.isAtLeastT() && groupName == Manifest.permission_group.STORAGE &&
- packagesWithFullFileAccess.any { !it.isLegacy && it.isGranted &&
- it.packageName to it.user == packageUserPair }) {
+ if (
+ !SdkLevel.isAtLeastT() &&
+ groupName == Manifest.permission_group.STORAGE &&
+ packagesWithFullFileAccess.any {
+ !it.isLegacy &&
+ it.isGranted &&
+ it.packageName to it.user == packageUserPair
+ }
+ ) {
category = Category.ALLOWED
}
categoryMap[category]!!.add(packageUserPair)
@@ -267,9 +273,9 @@ class PermissionAppsViewModel(
}
/**
- * If this is the storage permission group, some apps have full access to storage, while
- * others just have access to media files. This list contains the packages with full access.
- * To listen for changes, create and observe a FullStoragePermissionAppsLiveData
+ * If this is the storage permission group, some apps have full access to storage, while others
+ * just have access to media files. This list contains the packages with full access. To listen
+ * for changes, create and observe a FullStoragePermissionAppsLiveData
*/
private var packagesWithFullFileAccess = listOf<FullStoragePackageState>()
@@ -280,17 +286,15 @@ class PermissionAppsViewModel(
*
* @param packageName The name of the package we want to check
* @param user The name of the user whose package we want to check
- *
* @return true if the package and user has full file access
*/
fun packageHasFullStorage(packageName: String, user: UserHandle): Boolean {
- return packagesWithFullFileAccess.any {
- it.packageName == packageName && it.user == user }
+ return packagesWithFullFileAccess.any { it.packageName == packageName && it.user == user }
}
/**
- * Whether or not packages have been loaded from the system.
- * To update, need to observe the allPackageInfosLiveData.
+ * Whether or not packages have been loaded from the system. To update, need to observe the
+ * allPackageInfosLiveData.
*
* @return Whether or not all packages have been loaded
*/
@@ -313,16 +317,16 @@ class PermissionAppsViewModel(
args: Bundle
) {
val activity = fragment.activity!!
- if (LocationUtils.isLocationGroupAndProvider(
- activity, groupName, packageName)) {
+ if (LocationUtils.isLocationGroupAndProvider(activity, groupName, packageName)) {
val intent = Intent(activity, LocationProviderInterceptDialog::class.java)
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
activity.startActivityAsUser(intent, user)
return
}
- if (LocationUtils.isLocationGroupAndControllerExtraPackage(
- activity, groupName, packageName)) {
+ if (
+ LocationUtils.isLocationGroupAndControllerExtraPackage(activity, groupName, packageName)
+ ) {
// Redirect to location controller extra package settings.
LocationUtils.startLocationControllerExtraPackageSettings(activity, user)
return
@@ -332,31 +336,38 @@ class PermissionAppsViewModel(
}
fun getFilterTimeBeginMillis(): Long {
- val aggregateDataFilterBeginDays = if (is7DayToggleEnabled())
- AGGREGATE_DATA_FILTER_BEGIN_DAYS_7 else AGGREGATE_DATA_FILTER_BEGIN_DAYS_1
+ val aggregateDataFilterBeginDays =
+ if (is7DayToggleEnabled()) AGGREGATE_DATA_FILTER_BEGIN_DAYS_7
+ else AGGREGATE_DATA_FILTER_BEGIN_DAYS_1
- return max(System.currentTimeMillis() -
+ return max(
+ System.currentTimeMillis() -
TimeUnit.DAYS.toMillis(aggregateDataFilterBeginDays.toLong()),
- Instant.EPOCH.toEpochMilli())
+ Instant.EPOCH.toEpochMilli()
+ )
}
/**
* Return a mapping of user + packageName to their last access timestamps for the permission
* group.
*/
- fun extractGroupUsageLastAccessTime(appPermissionUsages: List<AppPermissionUsage>):
- MutableMap<String, Long> {
+ fun extractGroupUsageLastAccessTime(
+ appPermissionUsages: List<AppPermissionUsage>
+ ): MutableMap<String, Long> {
val accessTime: MutableMap<String, Long> = HashMap()
if (!SdkLevel.isAtLeastS()) {
return accessTime
}
- val aggregateDataFilterBeginDays = if (is7DayToggleEnabled())
- AGGREGATE_DATA_FILTER_BEGIN_DAYS_7 else AGGREGATE_DATA_FILTER_BEGIN_DAYS_1
+ val aggregateDataFilterBeginDays =
+ if (is7DayToggleEnabled()) AGGREGATE_DATA_FILTER_BEGIN_DAYS_7
+ else AGGREGATE_DATA_FILTER_BEGIN_DAYS_1
val now = System.currentTimeMillis()
- val filterTimeBeginMillis = max(
+ val filterTimeBeginMillis =
+ max(
now - TimeUnit.DAYS.toMillis(aggregateDataFilterBeginDays.toLong()),
- Instant.EPOCH.toEpochMilli())
+ Instant.EPOCH.toEpochMilli()
+ )
val numApps: Int = appPermissionUsages.size
for (appIndex in 0 until numApps) {
val appUsage: AppPermissionUsage = appPermissionUsages.get(appIndex)
@@ -380,41 +391,39 @@ class PermissionAppsViewModel(
return accessTime
}
- /**
- * Return the String preference summary based on the last access time.
- */
- fun getPreferenceSummary(res: Resources, summaryTimestamp: Triple<String, Int, String>):
- String {
+ /** Return the String preference summary based on the last access time. */
+ fun getPreferenceSummary(
+ res: Resources,
+ summaryTimestamp: Triple<String, Int, String>
+ ): String {
return when (summaryTimestamp.second) {
- Utils.LAST_24H_CONTENT_PROVIDER -> res.getString(
- R.string.app_perms_content_provider_24h)
- Utils.LAST_7D_CONTENT_PROVIDER -> res.getString(
- R.string.app_perms_content_provider_7d)
- Utils.LAST_24H_SENSOR_TODAY -> res.getString(R.string.app_perms_24h_access,
- summaryTimestamp.first)
- Utils.LAST_24H_SENSOR_YESTERDAY -> res.getString(R.string.app_perms_24h_access_yest,
- summaryTimestamp.first)
- Utils.LAST_7D_SENSOR -> res.getString(R.string.app_perms_7d_access,
- summaryTimestamp.third, summaryTimestamp.first)
+ Utils.LAST_24H_CONTENT_PROVIDER ->
+ res.getString(R.string.app_perms_content_provider_24h)
+ Utils.LAST_7D_CONTENT_PROVIDER -> res.getString(R.string.app_perms_content_provider_7d)
+ Utils.LAST_24H_SENSOR_TODAY ->
+ res.getString(R.string.app_perms_24h_access, summaryTimestamp.first)
+ Utils.LAST_24H_SENSOR_YESTERDAY ->
+ res.getString(R.string.app_perms_24h_access_yest, summaryTimestamp.first)
+ Utils.LAST_7D_SENSOR ->
+ res.getString(
+ R.string.app_perms_7d_access,
+ summaryTimestamp.third,
+ summaryTimestamp.first
+ )
else -> ""
}
}
- /**
- * Return two preferences to determine their ordering.
- */
+ /** Return two preferences to determine their ordering. */
fun comparePreference(collator: Collator, lhs: Preference, rhs: Preference): Int {
- var result: Int = collator.compare(lhs.title.toString(),
- rhs.title.toString())
+ var result: Int = collator.compare(lhs.title.toString(), rhs.title.toString())
if (result == 0) {
result = lhs.key.compareTo(rhs.key)
}
return result
}
- /**
- * Log that the fragment was created.
- */
+ /** Log that the fragment was created. */
fun logPermissionAppsFragmentCreated(
packageName: String,
user: UserHandle,
@@ -439,14 +448,30 @@ class PermissionAppsViewModel(
category = PERMISSION_APPS_FRAGMENT_VIEWED__CATEGORY__DENIED
}
}
- val uid = getPackageUid(application,
- packageName, user) ?: return
+ val uid = getPackageUid(application, packageName, user) ?: return
PermissionControllerStatsLog.write(
- PermissionControllerStatsLog.PERMISSION_APPS_FRAGMENT_VIEWED, sessionId, viewId,
- permGroupName, uid, packageName, category)
- Log.v(tag, tag + " created with sessionId=" + sessionId +
- " permissionGroupName=" + permGroupName + " appUid=" + uid +
- " packageName=" + packageName + " category=" + category)
+ PermissionControllerStatsLog.PERMISSION_APPS_FRAGMENT_VIEWED,
+ sessionId,
+ viewId,
+ permGroupName,
+ uid,
+ packageName,
+ category
+ )
+ Log.v(
+ tag,
+ tag +
+ " created with sessionId=" +
+ sessionId +
+ " permissionGroupName=" +
+ permGroupName +
+ " appUid=" +
+ uid +
+ " packageName=" +
+ packageName +
+ " category=" +
+ category
+ )
}
}
@@ -470,7 +495,6 @@ class PermissionAppsViewModelFactory(
state.set(HAS_SYSTEM_APPS_KEY, state.get<Boolean>(HAS_SYSTEM_APPS_KEY) ?: true)
state.set(SHOW_ALWAYS_ALLOWED, state.get<Boolean>(SHOW_ALWAYS_ALLOWED) ?: false)
state.set(CREATION_LOGGED_KEY, state.get<Boolean>(CREATION_LOGGED_KEY) ?: false)
- @Suppress("UNCHECKED_CAST")
- return PermissionAppsViewModel(state, app, groupName) as T
+ @Suppress("UNCHECKED_CAST") return PermissionAppsViewModel(state, app, groupName) as T
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ReviewPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ReviewPermissionsViewModel.kt
index 4e1fc1861..8613d1cae 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ReviewPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/ReviewPermissionsViewModel.kt
@@ -39,53 +39,51 @@ import com.android.settingslib.RestrictedLockUtils
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin
import java.util.stream.Collectors
-/**
- * View model for legacy {@link ReviewPermissionsFragment}.
- */
-class ReviewPermissionsViewModel(
- val app: Application,
- val packageInfo: PackageInfo
-) : ViewModel() {
+/** View model for legacy {@link ReviewPermissionsFragment}. */
+class ReviewPermissionsViewModel(val app: Application, val packageInfo: PackageInfo) : ViewModel() {
private val mUser = android.os.Process.myUserHandle()
- /**
- * Holds permission groups for a package or an empty map in case no user review is required.
- */
+ /** Holds permission groups for a package or an empty map in case no user review is required. */
val permissionGroupsLiveData =
object : SmartUpdateMediatorLiveData<Map<String, LightAppPermGroup>>() {
val packagePermsLiveData = PackagePermissionsLiveData[packageInfo.packageName, mUser]
init {
- addSource(packagePermsLiveData) {
- update()
- }
+ addSource(packagePermsLiveData) { update() }
}
val permissionGroups = mutableMapOf<String, LightAppPermGroupLiveData>()
override fun onUpdate() {
val permissionGroupsMap = packagePermsLiveData.value ?: return
- val filteredGroups = permissionGroupsMap.keys.stream()
- .filter { it -> !it.equals(NON_RUNTIME_NORMAL_PERMS) }
- .collect(Collectors.toList())
+ val filteredGroups =
+ permissionGroupsMap.keys
+ .stream()
+ .filter { it -> !it.equals(NON_RUNTIME_NORMAL_PERMS) }
+ .collect(Collectors.toList())
val getPermGroupLiveData = { permGroupName: String ->
LightAppPermGroupLiveData[packageInfo.packageName, permGroupName, mUser]
}
setSourcesToDifference(filteredGroups, permissionGroups, getPermGroupLiveData)
- if (permissionGroups.values.all { it.isInitialized } &&
- permissionGroups.values.all { !it.isStale }) {
- val permGroups: List<LightAppPermGroup?> = permissionGroups.values.map {
- it.value }
- val reviewGroups = permGroups.filterNotNull().filter {
- shouldShowPermission(it) &&
- Utils.OS_PKG == it.permGroupInfo.packageName
- }.associateBy {
- it.permGroupName
- }
- value = if (reviewGroups.any { it.value.isReviewRequired }) reviewGroups
- else emptyMap()
+ if (
+ permissionGroups.values.all { it.isInitialized } &&
+ permissionGroups.values.all { !it.isStale }
+ ) {
+ val permGroups: List<LightAppPermGroup?> =
+ permissionGroups.values.map { it.value }
+ val reviewGroups =
+ permGroups
+ .filterNotNull()
+ .filter {
+ shouldShowPermission(it) &&
+ Utils.OS_PKG == it.permGroupInfo.packageName
+ }
+ .associateBy { it.permGroupName }
+ value =
+ if (reviewGroups.any { it.value.isReviewRequired }) reviewGroups
+ else emptyMap()
}
}
}
@@ -110,15 +108,15 @@ class ReviewPermissionsViewModel(
}
/**
- * Update the summary of a permission group that has background permission.
- * This does not apply to permission groups that are fixed by policy
+ * Update the summary of a permission group that has background permission. This does not apply
+ * to permission groups that are fixed by policy
*/
- fun getSummaryForPermGroupWithBackgroundPermission(
- state: PermissionTarget
- ): PermissionSummary {
+ fun getSummaryForPermGroupWithBackgroundPermission(state: PermissionTarget): PermissionSummary {
if (state != PermissionTarget.PERMISSION_NONE) {
- if (state.and(PermissionTarget.PERMISSION_BACKGROUND)
- != PermissionTarget.PERMISSION_NONE.value) {
+ if (
+ state.and(PermissionTarget.PERMISSION_BACKGROUND) !=
+ PermissionTarget.PERMISSION_NONE.value
+ ) {
return SummaryMessage.ACCESS_ALWAYS.toPermSummary()
} else {
return SummaryMessage.ACCESS_ONLY_FOREGROUND.toPermSummary()
@@ -152,9 +150,7 @@ class ReviewPermissionsViewModel(
}
}
- /**
- * Show all individual permissions in this group in a new fragment.
- */
+ /** Show all individual permissions in this group in a new fragment. */
fun showAllPermissions(fragment: Fragment, args: Bundle) {
val navController: NavController = NavHostFragment.findNavController(fragment)
navController.navigateSafe(R.id.app_to_all_perms, args)
@@ -222,8 +218,10 @@ class ReviewPermissionsViewModel(
SummaryMessage.ENFORCED_BY_POLICY.toPermSummary()
}
} else {
- if (mState.and(PermissionTarget.PERMISSION_BACKGROUND) !=
- PermissionTarget.PERMISSION_NONE.value) {
+ if (
+ mState.and(PermissionTarget.PERMISSION_BACKGROUND) !=
+ PermissionTarget.PERMISSION_NONE.value
+ ) {
return if (hasAdmin) {
SummaryMessage.ENABLED_BY_ADMIN.toPermSummary()
} else {
@@ -242,8 +240,10 @@ class ReviewPermissionsViewModel(
} else {
// Part of the permission group can still be switched
if (permGroup.background.isPolicyFixed) {
- return if (mState.and(PermissionTarget.PERMISSION_BACKGROUND) !=
- PermissionTarget.PERMISSION_NONE.value) {
+ return if (
+ mState.and(PermissionTarget.PERMISSION_BACKGROUND) !=
+ PermissionTarget.PERMISSION_NONE.value
+ ) {
if (hasAdmin) {
SummaryMessage.ENABLED_BY_ADMIN_BACKGROUND_ONLY.toPermSummary(true)
} else {
@@ -277,11 +277,10 @@ class ReviewPermissionsViewModel(
return mGroup.foreground.isPolicyFixed && !mGroup.isGranted
}
- /**
- * Whether policy is system fixed or fully fixed or foreground disabled
- */
+ /** Whether policy is system fixed or fully fixed or foreground disabled */
fun isFixedOrForegroundDisabled(mGroup: LightAppPermGroup): Boolean {
- return mGroup.isSystemFixed || mGroup.isPolicyFullyFixed ||
+ return mGroup.isSystemFixed ||
+ mGroup.isPolicyFullyFixed ||
isForegroundDisabledByPolicy(mGroup)
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/UnusedAppsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/UnusedAppsViewModel.kt
index 3c3f347a4..868f9229f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/UnusedAppsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/UnusedAppsViewModel.kt
@@ -96,85 +96,89 @@ class UnusedAppsViewModel(private val app: Application, private val sessionId: L
private data class PackageLastUsageTime(val packageName: String, val usageTime: Long)
val unusedPackageCategoriesLiveData =
- object : SmartAsyncMediatorLiveData<Map<UnusedPeriod, List<UnusedPackageInfo>>>(
- alwaysUpdateOnActive = false
- ) {
- // Get apps usage stats from the longest interesting period (MAX_UNUSED_PERIOD_MILLIS)
- private val usageStatsLiveData = UsageStatsLiveData[MAX_UNUSED_PERIOD_MILLIS]
-
- init {
- addSource(getUnusedPackages()) {
- onUpdate()
- }
-
- addSource(AllPackageInfosLiveData) {
- onUpdate()
- }
+ object :
+ SmartAsyncMediatorLiveData<Map<UnusedPeriod, List<UnusedPackageInfo>>>(
+ alwaysUpdateOnActive = false
+ ) {
+ // Get apps usage stats from the longest interesting period (MAX_UNUSED_PERIOD_MILLIS)
+ private val usageStatsLiveData = UsageStatsLiveData[MAX_UNUSED_PERIOD_MILLIS]
- addSource(usageStatsLiveData) {
- onUpdate()
- }
- }
+ init {
+ addSource(getUnusedPackages()) { onUpdate() }
- override suspend fun loadDataAndPostValue(job: Job) {
- if (!getUnusedPackages().isInitialized ||
- !usageStatsLiveData.isInitialized || !AllPackageInfosLiveData.isInitialized
- ) {
- return
- }
+ addSource(AllPackageInfosLiveData) { onUpdate() }
- val unusedApps = getUnusedPackages().value!!
- Log.i(LOG_TAG, "Unused apps: $unusedApps")
- val categorizedApps = mutableMapOf<UnusedPeriod, MutableList<UnusedPackageInfo>>()
- for (period in UnusedPeriod.allPeriods) {
- categorizedApps[period] = mutableListOf()
+ addSource(usageStatsLiveData) { onUpdate() }
}
- // Get all packages which cannot be uninstalled.
- val systemApps = getUnusedSystemApps(AllPackageInfosLiveData.value!!, unusedApps)
- val lastUsedDataUnusedApps =
- extractUnusedAppsUsageData(usageStatsLiveData.value!!, unusedApps)
- { it: UsageStats ->
- PackageLastUsageTime(it.packageName, it.lastTimePackageUsed())
+ override suspend fun loadDataAndPostValue(job: Job) {
+ if (
+ !getUnusedPackages().isInitialized ||
+ !usageStatsLiveData.isInitialized ||
+ !AllPackageInfosLiveData.isInitialized
+ ) {
+ return
}
- val firstInstallDataUnusedApps =
- extractUnusedAppsUsageData(AllPackageInfosLiveData.value!!, unusedApps)
- { it: LightPackageInfo ->
- PackageLastUsageTime(it.packageName, it.firstInstallTime)
+
+ val unusedApps = getUnusedPackages().value!!
+ Log.i(LOG_TAG, "Unused apps: $unusedApps")
+ val categorizedApps = mutableMapOf<UnusedPeriod, MutableList<UnusedPackageInfo>>()
+ for (period in UnusedPeriod.allPeriods) {
+ categorizedApps[period] = mutableListOf()
}
- val now = System.currentTimeMillis()
- unusedApps.keys.forEach { (packageName, user) ->
- val userPackage = packageName to user
-
- // If we didn't find the stat for a package in our usageStats search, it is more than
- // 6 months old, or the app has never been opened. Then use first install date instead.
- var lastUsageTime =
- lastUsedDataUnusedApps[userPackage] ?: firstInstallDataUnusedApps[
- userPackage] ?: 0L
-
- val period = UnusedPeriod.findLongestValidPeriod(now - lastUsageTime)
- categorizedApps[period]!!.add(
- UnusedPackageInfo(
- packageName, user, systemApps.contains(userPackage),
- unusedApps[userPackage]!!
+ // Get all packages which cannot be uninstalled.
+ val systemApps = getUnusedSystemApps(AllPackageInfosLiveData.value!!, unusedApps)
+ val lastUsedDataUnusedApps =
+ extractUnusedAppsUsageData(usageStatsLiveData.value!!, unusedApps) {
+ it: UsageStats ->
+ PackageLastUsageTime(it.packageName, it.lastTimePackageUsed())
+ }
+ val firstInstallDataUnusedApps =
+ extractUnusedAppsUsageData(AllPackageInfosLiveData.value!!, unusedApps) {
+ it: LightPackageInfo ->
+ PackageLastUsageTime(it.packageName, it.firstInstallTime)
+ }
+
+ val now = System.currentTimeMillis()
+ unusedApps.keys.forEach { (packageName, user) ->
+ val userPackage = packageName to user
+
+ // If we didn't find the stat for a package in our usageStats search, it is more
+ // than
+ // 6 months old, or the app has never been opened. Then use first install date
+ // instead.
+ var lastUsageTime =
+ lastUsedDataUnusedApps[userPackage]
+ ?: firstInstallDataUnusedApps[userPackage] ?: 0L
+
+ val period = UnusedPeriod.findLongestValidPeriod(now - lastUsageTime)
+ categorizedApps[period]!!.add(
+ UnusedPackageInfo(
+ packageName,
+ user,
+ systemApps.contains(userPackage),
+ unusedApps[userPackage]!!
+ )
)
- )
- }
+ }
- postValue(categorizedApps)
+ postValue(categorizedApps)
+ }
}
- }
// Extract UserPackage information for unused system apps from source map.
private fun getUnusedSystemApps(
userPackages: Map<UserHandle, List<LightPackageInfo>>,
- unusedApps: Map<UserPackage, Set<String>>,
+ unusedApps: Map<UserPackage, Set<String>>,
): List<UserPackage> {
- return userPackages.flatMap { (userHandle, packageList) ->
- packageList.filter { (it.appFlags and ApplicationInfo.FLAG_SYSTEM) != 0 }
- .map { it.packageName to userHandle }
- }.filter { unusedApps.contains(it) }
+ return userPackages
+ .flatMap { (userHandle, packageList) ->
+ packageList
+ .filter { (it.appFlags and ApplicationInfo.FLAG_SYSTEM) != 0 }
+ .map { it.packageName to userHandle }
+ }
+ .filter { unusedApps.contains(it) }
}
/**
@@ -187,9 +191,11 @@ class UnusedAppsViewModel(private val app: Application, private val sessionId: L
unusedApps: Map<UserPackage, Set<String>>,
extractUsageData: (fullData: PackageData) -> PackageLastUsageTime,
): Map<UserPackage, Long> {
- return userPackages.flatMap { (userHandle, fullData) ->
- fullData.map { userHandle to extractUsageData(it) }
- }.associate { (handle, appData) -> (appData.packageName to handle) to appData.usageTime }
+ return userPackages
+ .flatMap { (userHandle, fullData) ->
+ fullData.map { userHandle to extractUsageData(it) }
+ }
+ .associate { (handle, appData) -> (appData.packageName to handle) to appData.usageTime }
.filterKeys { unusedApps.contains(it) }
}
@@ -215,37 +221,57 @@ class UnusedAppsViewModel(private val app: Application, private val sessionId: L
Log.i(LOG_TAG, "sessionId: $sessionId, Disabling $packageName, $user")
logAppInteraction(packageName, user, AUTO_REVOKED_APP_INTERACTION__ACTION__REMOVE)
val userContext = Utils.getUserContext(app, user)
- userContext.packageManager.setApplicationEnabledSetting(packageName,
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0)
+ userContext.packageManager.setApplicationEnabledSetting(
+ packageName,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER,
+ 0
+ )
}
private fun logAppInteraction(packageName: String, user: UserHandle, action: Int) {
GlobalScope.launch(IPC) {
// If we are logging an app interaction, then the AllPackageInfosLiveData is not stale.
- val uid = AllPackageInfosLiveData.value?.get(user)
- ?.find { info -> info.packageName == packageName }?.uid
+ val uid =
+ AllPackageInfosLiveData.value
+ ?.get(user)
+ ?.find { info -> info.packageName == packageName }
+ ?.uid
if (uid != null) {
- PermissionControllerStatsLog.write(AUTO_REVOKED_APP_INTERACTION, sessionId,
- uid, packageName, action)
+ PermissionControllerStatsLog.write(
+ AUTO_REVOKED_APP_INTERACTION,
+ sessionId,
+ uid,
+ packageName,
+ action
+ )
}
}
}
fun logAppView(packageName: String, user: UserHandle, groupName: String, isNew: Boolean) {
GlobalScope.launch(IPC) {
- val uid = AllPackageInfosLiveData.value!![user]!!.find { info ->
- info.packageName == packageName
- }?.uid
+ val uid =
+ AllPackageInfosLiveData.value!![user]!!.find { info ->
+ info.packageName == packageName
+ }
+ ?.uid
if (uid != null) {
- val bucket = if (isNew) {
- AUTO_REVOKE_FRAGMENT_APP_VIEWED__AGE__NEWER_BUCKET
- } else {
- AUTO_REVOKE_FRAGMENT_APP_VIEWED__AGE__OLDER_BUCKET
- }
- PermissionControllerStatsLog.write(AUTO_REVOKE_FRAGMENT_APP_VIEWED, sessionId,
- uid, packageName, groupName, bucket)
+ val bucket =
+ if (isNew) {
+ AUTO_REVOKE_FRAGMENT_APP_VIEWED__AGE__NEWER_BUCKET
+ } else {
+ AUTO_REVOKE_FRAGMENT_APP_VIEWED__AGE__OLDER_BUCKET
+ }
+ PermissionControllerStatsLog.write(
+ AUTO_REVOKE_FRAGMENT_APP_VIEWED,
+ sessionId,
+ uid,
+ packageName,
+ groupName,
+ bucket
+ )
}
}
}
@@ -259,7 +285,6 @@ class UnusedAppsViewModelFactory(
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
- @Suppress("UNCHECKED_CAST")
- return UnusedAppsViewModel(app, sessionId) as T
+ @Suppress("UNCHECKED_CAST") return UnusedAppsViewModel(app, sessionId) as T
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageControlPreferenceUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageControlPreferenceUtils.kt
index db79165c3..cd046ec73 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageControlPreferenceUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageControlPreferenceUtils.kt
@@ -36,11 +36,12 @@ import com.android.permissioncontroller.permission.utils.StringUtils
@RequiresApi(Build.VERSION_CODES.S)
object PermissionUsageControlPreferenceUtils {
- private val SENSOR_DATA_PERMISSIONS: List<String> = listOf(
- Manifest.permission_group.LOCATION,
- Manifest.permission_group.CAMERA,
- Manifest.permission_group.MICROPHONE
- )
+ private val SENSOR_DATA_PERMISSIONS: List<String> =
+ listOf(
+ Manifest.permission_group.LOCATION,
+ Manifest.permission_group.CAMERA,
+ Manifest.permission_group.MICROPHONE
+ )
@JvmStatic
fun initPreference(
@@ -56,19 +57,28 @@ object PermissionUsageControlPreferenceUtils {
return preference.apply {
title = permGroupLabel
icon = KotlinUtils.getPermGroupIcon(context, groupName)
- summary = StringUtils.getIcuPluralsString(context,
- R.string.permission_usage_preference_label, count)
+ summary =
+ StringUtils.getIcuPluralsString(
+ context,
+ R.string.permission_usage_preference_label,
+ count
+ )
if (count == 0) {
isEnabled = false
- val permissionUsageSummaryNotUsed = if (show7Days) {
- StringUtils.getIcuPluralsString(context,
+ val permissionUsageSummaryNotUsed =
+ if (show7Days) {
+ StringUtils.getIcuPluralsString(
+ context,
R.string.permission_usage_preference_summary_not_used_in_past_n_days,
- 7)
- } else {
- StringUtils.getIcuPluralsString(context,
+ 7
+ )
+ } else {
+ StringUtils.getIcuPluralsString(
+ context,
R.string.permission_usage_preference_summary_not_used_in_past_n_hours,
- 24)
- }
+ 24
+ )
+ }
setSummary(permissionUsageSummaryNotUsed)
} else if (SENSOR_DATA_PERMISSIONS.contains(groupName)) {
onPreferenceClickListener = OnPreferenceClickListener {
@@ -92,18 +102,19 @@ object PermissionUsageControlPreferenceUtils {
}
private fun logSensorDataTimelineViewed(groupName: String, sessionId: Long) {
- val act = when (groupName) {
- Manifest.permission_group.LOCATION -> {
- PERMISSION_USAGE_FRAGMENT_INTERACTION__ACTION__LOCATION_ACCESS_TIMELINE_VIEWED
- }
- Manifest.permission_group.CAMERA -> {
- PERMISSION_USAGE_FRAGMENT_INTERACTION__ACTION__CAMERA_ACCESS_TIMELINE_VIEWED
- }
- Manifest.permission_group.MICROPHONE -> {
- PERMISSION_USAGE_FRAGMENT_INTERACTION__ACTION__MICROPHONE_ACCESS_TIMELINE_VIEWED
+ val act =
+ when (groupName) {
+ Manifest.permission_group.LOCATION -> {
+ PERMISSION_USAGE_FRAGMENT_INTERACTION__ACTION__LOCATION_ACCESS_TIMELINE_VIEWED
+ }
+ Manifest.permission_group.CAMERA -> {
+ PERMISSION_USAGE_FRAGMENT_INTERACTION__ACTION__CAMERA_ACCESS_TIMELINE_VIEWED
+ }
+ Manifest.permission_group.MICROPHONE -> {
+ PERMISSION_USAGE_FRAGMENT_INTERACTION__ACTION__MICROPHONE_ACCESS_TIMELINE_VIEWED
+ }
+ else -> 0
}
- else -> 0
- }
PermissionControllerStatsLog.write(PERMISSION_USAGE_FRAGMENT_INTERACTION, sessionId, act)
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt
index f77bfff3b..6dba04b55 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt
@@ -28,6 +28,7 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Resources
+import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.os.UserHandle
@@ -37,7 +38,6 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.savedstate.SavedStateRegistryOwner
import com.android.modules.utils.build.SdkLevel
-import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.compat.IntentCompat
import com.android.permissioncontroller.permission.data.AppPermGroupUiInfoLiveData
@@ -54,7 +54,6 @@ import com.android.permissioncontroller.permission.model.livedatatypes.v31.Light
import com.android.permissioncontroller.permission.ui.handheld.v31.getDurationUsedStr
import com.android.permissioncontroller.permission.ui.handheld.v31.shouldShowSubattributionInPermissionsDashboard
import com.android.permissioncontroller.permission.utils.KotlinUtils
-import com.android.permissioncontroller.permission.utils.KotlinUtils.getPackageLabel
import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.Utils
import com.android.permissioncontroller.permission.utils.v31.SubattributionUtils
@@ -80,6 +79,9 @@ class PermissionUsageDetailsViewModel(
val showSystemLiveData = state.getLiveData(SHOULD_SHOW_SYSTEM_KEY, false)
val show7DaysLiveData = state.getLiveData(SHOULD_SHOW_7_DAYS_KEY, false)
+ private val packageIconCache: MutableMap<Pair<String, UserHandle>, Drawable> = mutableMapOf()
+ private val packageLabelCache: MutableMap<String, String> = mutableMapOf()
+
private val roleManager =
Utils.getSystemServiceSafe(application.applicationContext, RoleManager::class.java)
@@ -109,14 +111,19 @@ class PermissionUsageDetailsViewModel(
}
val startTime =
(System.currentTimeMillis() - showPermissionUsagesDuration).coerceAtLeast(
- Instant.EPOCH.toEpochMilli())
+ Instant.EPOCH.toEpochMilli()
+ )
return PermissionUsageDetailsUiInfo(
show7Days,
showSystem,
buildAppPermissionAccessUiInfoList(
- allLightHistoricalPackageOpsLiveData, startTime, showSystem),
- containsSystemAppUsages(allLightHistoricalPackageOpsLiveData, startTime))
+ allLightHistoricalPackageOpsLiveData,
+ startTime,
+ showSystem
+ ),
+ containsSystemAppUsages(allLightHistoricalPackageOpsLiveData, startTime)
+ )
}
/**
@@ -162,9 +169,11 @@ class PermissionUsageDetailsViewModel(
// The Telecom doesn't request microphone or camera permissions. However, telecom app may
// use these permissions and they are considered system app permissions, so we return true
// even if the AppPermGroupUiInfo is unavailable.
- if (appPermissionId.packageName == TELECOM_PACKAGE &&
- (appPermissionId.permissionGroup == Manifest.permission_group.CAMERA ||
- appPermissionId.permissionGroup == Manifest.permission_group.MICROPHONE)) {
+ if (
+ appPermissionId.packageName == TELECOM_PACKAGE &&
+ (appPermissionId.permissionGroup == Manifest.permission_group.CAMERA ||
+ appPermissionId.permissionGroup == Manifest.permission_group.MICROPHONE)
+ ) {
return true
}
return false
@@ -244,7 +253,8 @@ class PermissionUsageDetailsViewModel(
it.appPermissionId,
it.attributionLabel,
it.attributionTags,
- updatedDiscreteAccesses)
+ updatedDiscreteAccesses
+ )
}
/** Filters out data for apps and permissions that don't need to be displayed in the UI. */
@@ -268,7 +278,8 @@ class PermissionUsageDetailsViewModel(
this.appPermissionId,
Resources.ID_NULL,
attributionTags = emptyList(),
- this.discreteAccesses)
+ this.discreteAccesses
+ )
/** Groups tag-attributed accesses for the provided app and permission by attribution label. */
private fun AttributedAppPermissionDiscreteAccesses.groupAccessesByLabel(
@@ -307,7 +318,9 @@ class PermissionUsageDetailsViewModel(
appPermissionId,
label,
tags,
- discreteAccesses.sortedBy { -1 * it.accessTimeMs }))
+ discreteAccesses.sortedBy { -1 * it.accessTimeMs }
+ )
+ )
}
return appPermissionDiscreteAccessWithLabels
@@ -334,7 +347,9 @@ class PermissionUsageDetailsViewModel(
appPermAccesses.appPermissionId,
appPermAccesses.attributionLabel,
appPermAccesses.attributionTags,
- currentDiscreteAccesses.toMutableList()))
+ currentDiscreteAccesses.toMutableList()
+ )
+ )
currentDiscreteAccesses.clear()
currentDiscreteAccesses.add(discreteAccess)
} else {
@@ -348,7 +363,9 @@ class PermissionUsageDetailsViewModel(
appPermAccesses.appPermissionId,
appPermAccesses.attributionLabel,
appPermAccesses.attributionTags,
- currentDiscreteAccesses.toMutableList()))
+ currentDiscreteAccesses.toMutableList()
+ )
+ )
}
return clusters
}
@@ -384,12 +401,15 @@ class PermissionUsageDetailsViewModel(
return AppPermissionAccessUiInfo(
this.appPermissionId.userHandle,
this.appPermissionId.packageName,
+ getPackageLabel(this.appPermissionId.packageName, this.appPermissionId.userHandle),
permissionGroup,
this.discreteAccesses.last().accessTimeMs,
this.discreteAccesses.first().accessTimeMs,
summary,
showingSubAttribution,
- ArrayList(this.attributionTags))
+ ArrayList(this.attributionTags),
+ getBadgedPackageIcon(this.appPermissionId.packageName, this.appPermissionId.userHandle)
+ )
}
/** Builds a summary of the permission access. */
@@ -410,10 +430,14 @@ class PermissionUsageDetailsViewModel(
R.string.history_preference_subtext_3,
subTextStrings[0],
subTextStrings[1],
- subTextStrings[2])
+ subTextStrings[2]
+ )
2 ->
context.getString(
- R.string.history_preference_subtext_2, subTextStrings[0], subTextStrings[1])
+ R.string.history_preference_subtext_2,
+ subTextStrings[0],
+ subTextStrings[1]
+ )
1 -> subTextStrings[0]
else -> null
}
@@ -462,7 +486,6 @@ class PermissionUsageDetailsViewModel(
.firstOrNull { it.proxy?.packageName != null }
?.let {
getPackageLabel(
- PermissionControllerApplication.get(),
it.proxy!!.packageName!!,
UserHandle.getUserHandleForUid(it.proxy.uid))
}
@@ -492,13 +515,15 @@ class PermissionUsageDetailsViewModel(
/** Data used to create a preference for an app's permission usage. */
data class AppPermissionAccessUiInfo(
val userHandle: UserHandle,
- val pkgName: String,
+ val packageName: String,
+ val packageLabel: String,
val permissionGroup: String,
val accessStartTime: Long,
val accessEndTime: Long,
val summaryText: CharSequence?,
val showingAttribution: Boolean,
val attributionTags: ArrayList<String>,
+ val badgedPackageIcon: Drawable?,
)
/**
@@ -593,13 +618,17 @@ class PermissionUsageDetailsViewModel(
setSourcesToDifference(
appPermissionIds,
appPermGroupUiInfoLiveDataList,
- getAppPermGroupUiInfoLiveData) {
- update()
- }
+ getAppPermGroupUiInfoLiveData
+ ) {
+ update()
+ }
setSourcesToDifference(
- allPackages, lightPackageInfoLiveDataMap, getLightPackageInfoLiveData) {
- update()
- }
+ allPackages,
+ lightPackageInfoLiveDataMap,
+ getLightPackageInfoLiveData
+ ) {
+ update()
+ }
if (appPermGroupUiInfoLiveDataList.any { it.value.isStale }) {
return
@@ -613,6 +642,36 @@ class PermissionUsageDetailsViewModel(
}
}
+ /**
+ * Returns the icon for the provided package name and user, by first searching the cache
+ * otherwise retrieving it from the app's [android.content.pm.ApplicationInfo].
+ */
+ private fun getBadgedPackageIcon(packageName: String, userHandle: UserHandle): Drawable? {
+ val packageNameWithUser: Pair<String, UserHandle> = Pair(packageName, userHandle)
+ if (packageIconCache.containsKey(packageNameWithUser)) {
+ return requireNotNull(packageIconCache[packageNameWithUser])
+ }
+ val packageIcon = KotlinUtils.getBadgedPackageIcon(application, packageName, userHandle)
+ if (packageIcon != null) packageIconCache[packageNameWithUser] = packageIcon
+
+ return packageIcon
+ }
+
+ /**
+ * Returns the label for the provided package name, by first searching the cache otherwise
+ * retrieving it from the app's [android.content.pm.ApplicationInfo].
+ */
+ private fun getPackageLabel(packageName: String, user: UserHandle): String {
+ if (packageLabelCache.containsKey(packageName)) {
+ return requireNotNull(packageLabelCache[packageName])
+ }
+
+ val packageLabel = KotlinUtils.getPackageLabel(application, packageName, user)
+ packageLabelCache[packageName] = packageLabel
+
+ return packageLabel
+ }
+
/** Companion object for [PermissionUsageDetailsViewModel]. */
companion object {
private const val ONE_HOUR_MS = 3_600_000
@@ -629,7 +688,8 @@ class PermissionUsageDetailsViewModel(
listOf(
Manifest.permission_group.CAMERA,
Manifest.permission_group.LOCATION,
- Manifest.permission_group.MICROPHONE)
+ Manifest.permission_group.MICROPHONE
+ )
.flatMap { group -> PermissionMapping.getPlatformPermissionNamesOfGroup(group) }
.mapNotNull { permName -> AppOpsManager.permissionToOp(permName) }
.toMutableSet()
@@ -659,7 +719,8 @@ class PermissionUsageDetailsViewModel(
accessStartTime,
accessEndTime,
showingAttribution,
- attributionTags)
+ attributionTags
+ )
?: getDefaultManageAppPermissionsIntent(packageName, userHandle)
}
@@ -692,11 +753,16 @@ class PermissionUsageDetailsViewModel(
}
val resolveInfo =
context.packageManager.resolveActivity(
- intent, PackageManager.ResolveInfoFlags.of(0))
- if (resolveInfo?.activityInfo == null ||
- !Objects.equals(
- resolveInfo.activityInfo.permission,
- Manifest.permission.START_VIEW_PERMISSION_USAGE)) {
+ intent,
+ PackageManager.ResolveInfoFlags.of(0)
+ )
+ if (
+ resolveInfo?.activityInfo == null ||
+ !Objects.equals(
+ resolveInfo.activityInfo.permission,
+ Manifest.permission.START_VIEW_PERMISSION_USAGE
+ )
+ ) {
return null
}
intent.component = ComponentName(packageName, resolveInfo.activityInfo.name)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageViewModel.kt
index eeac22124..efb16ea2f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageViewModel.kt
@@ -98,7 +98,8 @@ class PermissionUsageViewModel(
showSystem,
show7Days,
mAllLightPackageOpsLiveData.containsSystemAppUsages(startTime),
- mAllLightPackageOpsLiveData.buildPermissionGroupsWithUsageCounts(startTime, showSystem))
+ mAllLightPackageOpsLiveData.buildPermissionGroupsWithUsageCounts(startTime, showSystem)
+ )
}
/** Builds a map of permission groups to the number of apps that recently accessed them. */
@@ -119,9 +120,14 @@ class PermissionUsageViewModel(
lightPackageOps.lastPermissionGroupAccessTimesMs.entries
.filterOutExemptedPermissionGroupsFromKeys()
.filterOutPermissionsNotRequestedByApp(
- lightPackageOps.packageName, lightPackageOps.userHandle)
+ lightPackageOps.packageName,
+ lightPackageOps.userHandle
+ )
.filterOutSystemAppPermissionsIfNecessary(
- showSystem, lightPackageOps.packageName, lightPackageOps.userHandle)
+ showSystem,
+ lightPackageOps.packageName,
+ lightPackageOps.userHandle
+ )
.filterAccessTimeLaterThan(startTime)
val recentlyUsedPermissions: List<String> = permGroupsToLastAccess.map { it.key }
@@ -147,10 +153,14 @@ class PermissionUsageViewModel(
.filterAccessTimeLaterThan(startTime)
.map { it.key }
.toSet()
- if (recentlyUsedPermissions
- .filterOutExemptedPermissionGroups()
- .containsSystemAppPermission(
- lightPackageOps.packageName, lightPackageOps.userHandle)) {
+ if (
+ recentlyUsedPermissions
+ .filterOutExemptedPermissionGroups()
+ .containsSystemAppPermission(
+ lightPackageOps.packageName,
+ lightPackageOps.userHandle
+ )
+ ) {
return true
}
}
@@ -186,9 +196,11 @@ class PermissionUsageViewModel(
// The Telecom doesn't request microphone or camera permissions. However, telecom app may
// use these permissions and they are considered system app permissions, so we return true
// even if the AppPermGroupUiInfo is unavailable.
- if (appPermissionId.packageName == TELECOM_PACKAGE &&
- (appPermissionId.permissionGroup == Manifest.permission_group.CAMERA ||
- appPermissionId.permissionGroup == Manifest.permission_group.MICROPHONE)) {
+ if (
+ appPermissionId.packageName == TELECOM_PACKAGE &&
+ (appPermissionId.permissionGroup == Manifest.permission_group.CAMERA ||
+ appPermissionId.permissionGroup == Manifest.permission_group.MICROPHONE)
+ ) {
return true
}
return false
@@ -312,27 +324,31 @@ class PermissionUsageViewModel(
packageWithUserHandle.first,
packageWithUserHandle.second,
permissionGroup,
- ))
+ )
+ )
}
}
setSourcesToDifference(
appPermissionIds,
appPermGroupUiInfoLiveDataList,
- getAppPermGroupUiInfoLiveData) {
- update()
- }
+ getAppPermGroupUiInfoLiveData
+ ) {
+ update()
+ }
setSourcesToDifference(
- allPackages, lightPackageInfoLiveDataMap, getLightPackageInfoLiveData) {
- update()
- }
+ allPackages,
+ lightPackageInfoLiveDataMap,
+ getLightPackageInfoLiveData
+ ) {
+ update()
+ }
if (lightPackageInfoLiveDataMap.any { it.value.isStale }) {
return
}
-
if (appPermGroupUiInfoLiveDataList.any { it.value.isStale }) {
return
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/ReviewOngoingUsageViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/ReviewOngoingUsageViewModel.kt
index 9c9a55523..2fccd7e06 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/ReviewOngoingUsageViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/ReviewOngoingUsageViewModel.kt
@@ -14,6 +14,7 @@
* limitations under the License.
*/
@file:Suppress("DEPRECATION")
+
package com.android.permissioncontroller.permission.ui.model.v31
import android.Manifest
@@ -62,16 +63,11 @@ private const val CALL_OP_USAGE_KEY = "CALL_OP_USAGE"
private const val USAGES_KEY = "USAGES_KEY"
private const val MIC_MUTED_KEY = "MIC_MUTED_KEY"
-/**
- * ViewModel for {@link ReviewOngoingUsageFragment}
- */
-class ReviewOngoingUsageViewModel(
- state: SavedStateHandle,
- extraDurationMills: Long
-) : ViewModel() {
+/** ViewModel for {@link ReviewOngoingUsageFragment} */
+class ReviewOngoingUsageViewModel(state: SavedStateHandle, extraDurationMills: Long) : ViewModel() {
/** Time of oldest usages considered */
- private val startTime = max(state.get<Long>(FIRST_OPENED_KEY)!! - extraDurationMills,
- Instant.EPOCH.toEpochMilli())
+ private val startTime =
+ max(state.get<Long>(FIRST_OPENED_KEY)!! - extraDurationMills, Instant.EPOCH.toEpochMilli())
private val SYSTEM_PKG = "android"
@@ -80,8 +76,10 @@ class ReviewOngoingUsageViewModel(
val appUsages: Map<PackageAttribution, Set<String>>,
/** Op-names of phone call accesses */
val callUsages: Collection<String>,
- /** A map of attribution, packageName and user -> list of attribution labels to show with
- * microphone*/
+ /**
+ * A map of attribution, packageName and user -> list of attribution labels to show with
+ * microphone
+ */
val shownAttributions: Map<PackageAttribution, List<CharSequence>> = emptyMap()
)
@@ -101,292 +99,355 @@ class ReviewOngoingUsageViewModel(
*
* <p>Note: This does not use a cached live-data to avoid getting stale data
*/
- private val permGroupUsages = LoadAndFreezeLifeData(state, USAGES_KEY,
- PermGroupUsageLiveData(PermissionControllerApplication.get(),
- if (shouldShowPermissionsDashboard() || shouldShowLocationIndicators()) {
- listOf(CAMERA, LOCATION, MICROPHONE)
- } else {
- listOf(CAMERA, MICROPHONE)
- }, System.currentTimeMillis() - startTime))
+ private val permGroupUsages =
+ LoadAndFreezeLifeData(
+ state,
+ USAGES_KEY,
+ PermGroupUsageLiveData(
+ PermissionControllerApplication.get(),
+ if (shouldShowPermissionsDashboard() || shouldShowLocationIndicators()) {
+ listOf(CAMERA, LOCATION, MICROPHONE)
+ } else {
+ listOf(CAMERA, MICROPHONE)
+ },
+ System.currentTimeMillis() - startTime
+ )
+ )
- /**
- * Whether the mic is muted
- */
+ /** Whether the mic is muted */
private val isMicMuted = LoadAndFreezeLifeData(state, MIC_MUTED_KEY, micMutedLiveData)
/** App runtime permission usages */
- private val appUsagesLiveData = object : SmartUpdateMediatorLiveData<Map<PackageAttribution,
- Set<String>>>() {
- private val app = PermissionControllerApplication.get()
-
- init {
- addSource(permGroupUsages) {
- update()
- }
+ private val appUsagesLiveData =
+ object : SmartUpdateMediatorLiveData<Map<PackageAttribution, Set<String>>>() {
+ private val app = PermissionControllerApplication.get()
- addSource(isMicMuted) {
- update()
- }
- }
+ init {
+ addSource(permGroupUsages) { update() }
- override fun onUpdate() {
- if (!permGroupUsages.isInitialized || !isMicMuted.isInitialized) {
- return
+ addSource(isMicMuted) { update() }
}
- if (permGroupUsages.value == null) {
- value = null
- return
- }
+ override fun onUpdate() {
+ if (!permGroupUsages.isInitialized || !isMicMuted.isInitialized) {
+ return
+ }
- // Filter out system package
- val filteredUsages = mutableMapOf<PackageAttribution, MutableSet<String>>()
- for ((permGroupName, usages) in permGroupUsages.value!!) {
- if (permGroupName == MICROPHONE && isMicMuted.value == true) {
- continue
+ if (permGroupUsages.value == null) {
+ value = null
+ return
}
- for (usage in usages) {
- if (usage.packageName != SYSTEM_PKG) {
- filteredUsages.getOrPut(getPackageAttr(usage),
- { mutableSetOf() }).add(permGroupName)
+ // Filter out system package
+ val filteredUsages = mutableMapOf<PackageAttribution, MutableSet<String>>()
+ for ((permGroupName, usages) in permGroupUsages.value!!) {
+ if (permGroupName == MICROPHONE && isMicMuted.value == true) {
+ continue
+ }
+
+ for (usage in usages) {
+ if (usage.packageName != SYSTEM_PKG) {
+ filteredUsages
+ .getOrPut(getPackageAttr(usage), { mutableSetOf() })
+ .add(permGroupName)
+ }
}
}
- }
- value = filteredUsages
- }
+ value = filteredUsages
+ }
- // TODO ntmyren: Replace this with better check if this moves beyond teamfood
- private fun isAppPredictor(usage: OpAccess): Boolean {
- return Utils.getUserContext(app, usage.user).packageManager.checkPermission(
- Manifest.permission.MANAGE_APP_PREDICTIONS, usage.packageName) ==
- PackageManager.PERMISSION_GRANTED
+ // TODO ntmyren: Replace this with better check if this moves beyond teamfood
+ private fun isAppPredictor(usage: OpAccess): Boolean {
+ return Utils.getUserContext(app, usage.user)
+ .packageManager
+ .checkPermission(
+ Manifest.permission.MANAGE_APP_PREDICTIONS,
+ usage.packageName
+ ) == PackageManager.PERMISSION_GRANTED
+ }
}
- }
/**
- * Gets all trusted proxied voice IME and voice recognition microphone uses, and get the
- * label needed to display with it, as well as information about the proxy whose label is being
- * shown, if applicable.
+ * Gets all trusted proxied voice IME and voice recognition microphone uses, and get the label
+ * needed to display with it, as well as information about the proxy whose label is being shown,
+ * if applicable.
*/
- private val trustedAttrsLiveData = object : SmartAsyncMediatorLiveData<
- Map<PackageAttribution, CharSequence>>() {
- private val VOICE_IME_SUBTYPE = "voice"
+ private val trustedAttrsLiveData =
+ object : SmartAsyncMediatorLiveData<Map<PackageAttribution, CharSequence>>() {
+ private val VOICE_IME_SUBTYPE = "voice"
- private val attributionLabelLiveDatas =
- mutableMapOf<Triple<String?, String, UserHandle>, AttributionLabelLiveData>()
+ private val attributionLabelLiveDatas =
+ mutableMapOf<Triple<String?, String, UserHandle>, AttributionLabelLiveData>()
- init {
- addSource(permGroupUsages) {
- updateAsync()
+ init {
+ addSource(permGroupUsages) { updateAsync() }
}
- }
- override suspend fun loadDataAndPostValue(job: Job) {
- if (!permGroupUsages.isInitialized) {
- return
- }
- val usages = permGroupUsages.value?.get(MICROPHONE) ?: run {
- postValue(emptyMap())
- return
- }
- val proxies = usages.mapNotNull { it.proxyAccess }
-
- val proxyLabelLiveDatas = proxies.map {
- Triple(it.attributionTag, it.packageName, it.user) }
- val toAddLabelLiveDatas = (usages.map { Triple(it.attributionTag, it.packageName,
- it.user) } + proxyLabelLiveDatas).distinct()
- val getLiveDataFun = { key: Triple<String?, String, UserHandle> ->
- AttributionLabelLiveData[key] }
- setSourcesToDifference(toAddLabelLiveDatas, attributionLabelLiveDatas, getLiveDataFun)
-
- if (attributionLabelLiveDatas.any { !it.value.isInitialized }) {
- return
- }
+ override suspend fun loadDataAndPostValue(job: Job) {
+ if (!permGroupUsages.isInitialized) {
+ return
+ }
+ val usages =
+ permGroupUsages.value?.get(MICROPHONE)
+ ?: run {
+ postValue(emptyMap())
+ return
+ }
+ val proxies = usages.mapNotNull { it.proxyAccess }
+
+ val proxyLabelLiveDatas =
+ proxies.map { Triple(it.attributionTag, it.packageName, it.user) }
+ val toAddLabelLiveDatas =
+ (usages.map { Triple(it.attributionTag, it.packageName, it.user) } +
+ proxyLabelLiveDatas)
+ .distinct()
+ val getLiveDataFun = { key: Triple<String?, String, UserHandle> ->
+ AttributionLabelLiveData[key]
+ }
+ setSourcesToDifference(
+ toAddLabelLiveDatas,
+ attributionLabelLiveDatas,
+ getLiveDataFun
+ )
+
+ if (attributionLabelLiveDatas.any { !it.value.isInitialized }) {
+ return
+ }
- val approvedAttrs = mutableMapOf<PackageAttribution, String>()
- for (user in usages.map { it.user }.distinct()) {
- val userContext = Utils.getUserContext(PermissionControllerApplication.get(), user)
-
- // TODO ntmyren: Observe changes, possibly split into separate LiveDatas
- val voiceInputs = mutableMapOf<String, CharSequence>()
- userContext.getSystemService(InputMethodManager::class.java)!!
- .enabledInputMethodList.forEach {
- for (i in 0 until it.subtypeCount) {
- if (it.getSubtypeAt(i).mode == VOICE_IME_SUBTYPE) {
- voiceInputs[it.packageName] =
- it.serviceInfo.loadSafeLabel(userContext.packageManager,
- Float.MAX_VALUE, 0)
- break
+ val approvedAttrs = mutableMapOf<PackageAttribution, String>()
+ for (user in usages.map { it.user }.distinct()) {
+ val userContext =
+ Utils.getUserContext(PermissionControllerApplication.get(), user)
+
+ // TODO ntmyren: Observe changes, possibly split into separate LiveDatas
+ val voiceInputs = mutableMapOf<String, CharSequence>()
+ userContext
+ .getSystemService(InputMethodManager::class.java)!!
+ .enabledInputMethodList
+ .forEach {
+ for (i in 0 until it.subtypeCount) {
+ if (it.getSubtypeAt(i).mode == VOICE_IME_SUBTYPE) {
+ voiceInputs[it.packageName] =
+ it.serviceInfo.loadSafeLabel(
+ userContext.packageManager,
+ Float.MAX_VALUE,
+ 0
+ )
+ break
+ }
}
}
+
+ // Get the currently selected recognizer from the secure setting.
+ val recognitionPackageName =
+ Settings.Secure.getString(
+ userContext.contentResolver,
+ // Settings.Secure.VOICE_RECOGNITION_SERVICE
+ "voice_recognition_service"
+ )
+ ?.let(ComponentName::unflattenFromString)
+ ?.packageName
+
+ val recognizers = mutableMapOf<String, CharSequence>()
+ val availableRecognizers =
+ userContext.packageManager.queryIntentServices(
+ Intent(RecognitionService.SERVICE_INTERFACE),
+ PackageManager.GET_META_DATA
+ )
+ availableRecognizers.forEach {
+ val sI = it.serviceInfo
+ if (sI.packageName == recognitionPackageName) {
+ recognizers[sI.packageName] =
+ sI.loadSafeLabel(userContext.packageManager, Float.MAX_VALUE, 0)
+ }
}
- // Get the currently selected recognizer from the secure setting.
- val recognitionPackageName = Settings.Secure.getString(userContext.contentResolver,
- // Settings.Secure.VOICE_RECOGNITION_SERVICE
- "voice_recognition_service")
- ?.let(ComponentName::unflattenFromString)?.packageName
-
- val recognizers = mutableMapOf<String, CharSequence>()
- val availableRecognizers = userContext.packageManager.queryIntentServices(
- Intent(RecognitionService.SERVICE_INTERFACE), PackageManager.GET_META_DATA)
- availableRecognizers.forEach {
- val sI = it.serviceInfo
- if (sI.packageName == recognitionPackageName) {
- recognizers[sI.packageName] = sI.loadSafeLabel(userContext.packageManager,
- Float.MAX_VALUE, 0)
+ val recognizerIntents = mutableMapOf<String, CharSequence>()
+ val availableRecognizerIntents =
+ userContext.packageManager.queryIntentActivities(
+ Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH),
+ PackageManager.GET_META_DATA
+ )
+ availableRecognizers.forEach { rI ->
+ val servicePkg = rI.serviceInfo.packageName
+ if (
+ servicePkg == recognitionPackageName &&
+ availableRecognizerIntents.any {
+ it.activityInfo.packageName == servicePkg
+ }
+ ) {
+ // If this recognizer intent is also a recognizer service, and is
+ // trusted,
+ // Then attribute to voice recognition
+ recognizerIntents[servicePkg] =
+ rI.serviceInfo.loadSafeLabel(
+ userContext.packageManager,
+ Float.MAX_VALUE,
+ 0
+ )
+ }
}
- }
- val recognizerIntents = mutableMapOf<String, CharSequence>()
- val availableRecognizerIntents = userContext.packageManager.queryIntentActivities(
- Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), PackageManager.GET_META_DATA)
- availableRecognizers.forEach { rI ->
- val servicePkg = rI.serviceInfo.packageName
- if (servicePkg == recognitionPackageName && availableRecognizerIntents.any {
- it.activityInfo.packageName == servicePkg }) {
- // If this recognizer intent is also a recognizer service, and is trusted,
- // Then attribute to voice recognition
- recognizerIntents[servicePkg] =
- rI.serviceInfo.loadSafeLabel(userContext.packageManager,
- Float.MAX_VALUE, 0)
+ // get attribution labels for voice IME, recognition intents, and recognition
+ // services
+ for (opAccess in usages) {
+ setTrustedAttrsForAccess(
+ userContext,
+ opAccess,
+ user,
+ false,
+ voiceInputs,
+ approvedAttrs
+ )
+ setTrustedAttrsForAccess(
+ userContext,
+ opAccess,
+ user,
+ false,
+ recognizerIntents,
+ approvedAttrs
+ )
+ setTrustedAttrsForAccess(
+ userContext,
+ opAccess,
+ user,
+ true,
+ recognizers,
+ approvedAttrs
+ )
}
}
+ postValue(approvedAttrs)
+ }
+
+ private fun setTrustedAttrsForAccess(
+ context: Context,
+ opAccess: OpAccess,
+ currUser: UserHandle,
+ getProxyLabel: Boolean,
+ trustedMap: Map<String, CharSequence>,
+ toSetMap: MutableMap<PackageAttribution, String>
+ ) {
+ val access =
+ if (getProxyLabel) {
+ opAccess.proxyAccess
+ } else {
+ opAccess
+ }
- // get attribution labels for voice IME, recognition intents, and recognition
- // services
- for (opAccess in usages) {
- setTrustedAttrsForAccess(userContext, opAccess, user, false, voiceInputs,
- approvedAttrs)
- setTrustedAttrsForAccess(userContext, opAccess, user, false, recognizerIntents,
- approvedAttrs)
- setTrustedAttrsForAccess(userContext, opAccess, user, true, recognizers,
- approvedAttrs)
+ if (
+ access == null || access.user != currUser || access.packageName !in trustedMap
+ ) {
+ return
}
- }
- postValue(approvedAttrs)
- }
-
- private fun setTrustedAttrsForAccess(
- context: Context,
- opAccess: OpAccess,
- currUser: UserHandle,
- getProxyLabel: Boolean,
- trustedMap: Map<String, CharSequence>,
- toSetMap: MutableMap<PackageAttribution, String>
- ) {
- val access = if (getProxyLabel) {
- opAccess.proxyAccess
- } else {
- opAccess
- }
- if (access == null || access.user != currUser || access.packageName !in trustedMap) {
- return
- }
-
- val appAttr = getPackageAttr(access)
- val packageName = access.packageName
-
- val labelResId = attributionLabelLiveDatas[Triple(access.attributionTag,
- access.packageName, access.user)]?.value ?: 0
- val label = try {
- context.createPackageContext(packageName, 0)
- .getString(labelResId)
- } catch (e: Exception) {
- return
- }
- if (trustedMap[packageName] == label) {
- toSetMap[appAttr] = label
+ val appAttr = getPackageAttr(access)
+ val packageName = access.packageName
+
+ val labelResId =
+ attributionLabelLiveDatas[
+ Triple(access.attributionTag, access.packageName, access.user)]
+ ?.value
+ ?: 0
+ val label =
+ try {
+ context.createPackageContext(packageName, 0).getString(labelResId)
+ } catch (e: Exception) {
+ return
+ }
+ if (trustedMap[packageName] == label) {
+ toSetMap[appAttr] = label
+ }
}
}
- }
/**
* Get all chains of proxy usages. A proxy chain is defined as one usage at the root, then
* further proxy usages, where the app and attribution tag of the proxy matches the previous
* usage in the chain.
*/
- private val proxyChainsLiveData = object : SmartUpdateMediatorLiveData<Set<List<OpAccess>>>() {
- init {
- addSource(permGroupUsages) {
- update()
- }
- }
- override fun onUpdate() {
- if (!permGroupUsages.isInitialized) {
- return
- }
- val usages = permGroupUsages.value?.get(MICROPHONE) ?: emptyList()
- // a map of chain start -> in progress chain
- val proxyChains = mutableMapOf<PackageAttribution, MutableList<OpAccess>>()
-
- val remainingProxyChainUsages = mutableMapOf<PackageAttribution, OpAccess>()
- for (usage in usages) {
- remainingProxyChainUsages[getPackageAttr(usage)] = usage
+ private val proxyChainsLiveData =
+ object : SmartUpdateMediatorLiveData<Set<List<OpAccess>>>() {
+ init {
+ addSource(permGroupUsages) { update() }
}
- // find all one-link chains (that is, all proxied apps whose proxy is not included in
- // the usage list)
- for (usage in usages) {
- val usageAttr = getPackageAttr(usage)
- val proxyAttr = getPackageAttr(usage.proxyAccess ?: continue)
- if (!usages.any { getPackageAttr(it) == proxyAttr }) {
- proxyChains[usageAttr] = mutableListOf(usage)
- remainingProxyChainUsages.remove(usageAttr)
+ override fun onUpdate() {
+ if (!permGroupUsages.isInitialized) {
+ return
}
- }
+ val usages = permGroupUsages.value?.get(MICROPHONE) ?: emptyList()
+ // a map of chain start -> in progress chain
+ val proxyChains = mutableMapOf<PackageAttribution, MutableList<OpAccess>>()
- // find all possible starting points for chains
- for ((usageAttr, usage) in remainingProxyChainUsages.toMap()) {
- // If this usage has a proxy, but is not a proxy, it is the start of a chain.
- // If it has no proxy, and isn't a proxy, remove it.
- if (!remainingProxyChainUsages.values.any { it.proxyAccess != null &&
- getPackageAttr(it.proxyAccess) == usageAttr }) {
- if (usage.proxyAccess != null) {
+ val remainingProxyChainUsages = mutableMapOf<PackageAttribution, OpAccess>()
+ for (usage in usages) {
+ remainingProxyChainUsages[getPackageAttr(usage)] = usage
+ }
+ // find all one-link chains (that is, all proxied apps whose proxy is not included
+ // in
+ // the usage list)
+ for (usage in usages) {
+ val usageAttr = getPackageAttr(usage)
+ val proxyAttr = getPackageAttr(usage.proxyAccess ?: continue)
+ if (!usages.any { getPackageAttr(it) == proxyAttr }) {
proxyChains[usageAttr] = mutableListOf(usage)
- } else {
remainingProxyChainUsages.remove(usageAttr)
}
}
- }
- // assemble the chains
- for ((startUsageAttr, proxyChain) in proxyChains) {
- var currentUsage = remainingProxyChainUsages[startUsageAttr] ?: continue
- while (currentUsage.proxyAccess != null) {
- val currPackageAttr = getPackageAttr(currentUsage.proxyAccess!!)
- currentUsage = remainingProxyChainUsages[currPackageAttr] ?: break
- if (proxyChain.any { it == currentUsage }) {
- // we have a cycle, and should break
- break
+ // find all possible starting points for chains
+ for ((usageAttr, usage) in remainingProxyChainUsages.toMap()) {
+ // If this usage has a proxy, but is not a proxy, it is the start of a chain.
+ // If it has no proxy, and isn't a proxy, remove it.
+ if (
+ !remainingProxyChainUsages.values.any {
+ it.proxyAccess != null && getPackageAttr(it.proxyAccess) == usageAttr
+ }
+ ) {
+ if (usage.proxyAccess != null) {
+ proxyChains[usageAttr] = mutableListOf(usage)
+ } else {
+ remainingProxyChainUsages.remove(usageAttr)
+ }
}
- proxyChain.add(currentUsage)
}
- // invert the lists, so the element without a proxy is first on the list
- proxyChain.reverse()
- }
- value = proxyChains.values.toSet()
+ // assemble the chains
+ for ((startUsageAttr, proxyChain) in proxyChains) {
+ var currentUsage = remainingProxyChainUsages[startUsageAttr] ?: continue
+ while (currentUsage.proxyAccess != null) {
+ val currPackageAttr = getPackageAttr(currentUsage.proxyAccess!!)
+ currentUsage = remainingProxyChainUsages[currPackageAttr] ?: break
+ if (proxyChain.any { it == currentUsage }) {
+ // we have a cycle, and should break
+ break
+ }
+ proxyChain.add(currentUsage)
+ }
+ // invert the lists, so the element without a proxy is first on the list
+ proxyChain.reverse()
+ }
+
+ value = proxyChains.values.toSet()
+ }
}
- }
/** Phone call usages */
private val callOpUsageLiveData =
object : SmartUpdateMediatorLiveData<Collection<String>>() {
- private val rawOps = LoadAndFreezeLifeData(state, CALL_OP_USAGE_KEY,
- OpUsageLiveData[listOf(PHONE_CALL, VIDEO_CALL),
- System.currentTimeMillis() - startTime])
+ private val rawOps =
+ LoadAndFreezeLifeData(
+ state,
+ CALL_OP_USAGE_KEY,
+ OpUsageLiveData[
+ listOf(PHONE_CALL, VIDEO_CALL), System.currentTimeMillis() - startTime]
+ )
init {
- addSource(rawOps) {
- update()
- }
+ addSource(rawOps) { update() }
- addSource(isMicMuted) {
- update()
- }
+ addSource(isMicMuted) { update() }
}
override fun onUpdate() {
@@ -394,145 +455,152 @@ class ReviewOngoingUsageViewModel(
return
}
- value = if (isMicMuted.value == true) {
- rawOps.value!!.keys.filter { it != PHONE_CALL }
- } else {
- rawOps.value!!.keys
- }
+ value =
+ if (isMicMuted.value == true) {
+ rawOps.value!!.keys.filter { it != PHONE_CALL }
+ } else {
+ rawOps.value!!.keys
+ }
}
}
/** App, system, and call usages in a single, nice, handy package */
- val usages = object : SmartAsyncMediatorLiveData<Usages>() {
- private val app = PermissionControllerApplication.get()
+ val usages =
+ object : SmartAsyncMediatorLiveData<Usages>() {
+ private val app = PermissionControllerApplication.get()
- init {
- addSource(appUsagesLiveData) {
- update()
- }
-
- addSource(callOpUsageLiveData) {
- update()
- }
-
- addSource(trustedAttrsLiveData) {
- update()
- }
+ init {
+ addSource(appUsagesLiveData) { update() }
- addSource(proxyChainsLiveData) {
- update()
- }
- }
+ addSource(callOpUsageLiveData) { update() }
- override suspend fun loadDataAndPostValue(job: Job) {
- if (job.isCancelled) {
- return
- }
+ addSource(trustedAttrsLiveData) { update() }
- if (!callOpUsageLiveData.isInitialized || !appUsagesLiveData.isInitialized ||
- !trustedAttrsLiveData.isInitialized || !proxyChainsLiveData.isInitialized) {
- return
+ addSource(proxyChainsLiveData) { update() }
}
- val callOpUsages = callOpUsageLiveData.value?.toMutableSet()
- val appUsages = appUsagesLiveData.value?.toMutableMap()
- val approvedAttrs = trustedAttrsLiveData.value?.toMutableMap() ?: mutableMapOf()
- val proxyChains = proxyChainsLiveData.value ?: emptySet()
+ override suspend fun loadDataAndPostValue(job: Job) {
+ if (job.isCancelled) {
+ return
+ }
- if (callOpUsages == null || appUsages == null) {
- postValue(null)
- return
- }
+ if (
+ !callOpUsageLiveData.isInitialized ||
+ !appUsagesLiveData.isInitialized ||
+ !trustedAttrsLiveData.isInitialized ||
+ !proxyChainsLiveData.isInitialized
+ ) {
+ return
+ }
- // If there is nothing to show the dialog should be closed, hence return a "invalid"
- // value
- if (appUsages.isEmpty() && callOpUsages.isEmpty()) {
- postValue(null)
- return
- }
+ val callOpUsages = callOpUsageLiveData.value?.toMutableSet()
+ val appUsages = appUsagesLiveData.value?.toMutableMap()
+ val approvedAttrs = trustedAttrsLiveData.value?.toMutableMap() ?: mutableMapOf()
+ val proxyChains = proxyChainsLiveData.value ?: emptySet()
- // If we are in a VOIP call (aka MODE_IN_COMMUNICATION), and have a carrier privileged
- // app using the mic, hide phone usage.
- val audioManager = app.getSystemService(AudioManager::class.java)!!
- if (callOpUsages.isNotEmpty() && audioManager.mode == MODE_IN_COMMUNICATION) {
- val telephonyManager = app.getSystemService(TelephonyManager::class.java)!!
- for ((pkg, usages) in appUsages) {
- if (telephonyManager.checkCarrierPrivilegesForPackage(pkg.packageName) ==
- CARRIER_PRIVILEGE_STATUS_HAS_ACCESS && usages.contains(MICROPHONE)) {
- callOpUsages.clear()
- continue
- }
+ if (callOpUsages == null || appUsages == null) {
+ postValue(null)
+ return
}
- }
- // Find labels for proxies, and assign them to the proper app, removing other usages
- val approvedLabels = mutableMapOf<PackageAttribution, List<CharSequence>>()
- for (chain in proxyChains) {
- // if the final link in the chain is not user sensitive, do not show the chain
- if (getPackageAttr(chain[chain.size - 1]) !in appUsages) {
- continue
+ // If there is nothing to show the dialog should be closed, hence return a "invalid"
+ // value
+ if (appUsages.isEmpty() && callOpUsages.isEmpty()) {
+ postValue(null)
+ return
}
- // if the proxy access is missing, for some reason, do not show the proxy
- if (chain.size == 1) {
- continue
+ // If we are in a VOIP call (aka MODE_IN_COMMUNICATION), and have a carrier
+ // privileged
+ // app using the mic, hide phone usage.
+ val audioManager = app.getSystemService(AudioManager::class.java)!!
+ if (callOpUsages.isNotEmpty() && audioManager.mode == MODE_IN_COMMUNICATION) {
+ val telephonyManager = app.getSystemService(TelephonyManager::class.java)!!
+ for ((pkg, usages) in appUsages) {
+ if (
+ telephonyManager.checkCarrierPrivilegesForPackage(pkg.packageName) ==
+ CARRIER_PRIVILEGE_STATUS_HAS_ACCESS && usages.contains(MICROPHONE)
+ ) {
+ callOpUsages.clear()
+ continue
+ }
+ }
}
- val labels = mutableListOf<CharSequence>()
- for ((idx, opAccess) in chain.withIndex()) {
- val appAttr = getPackageAttr(opAccess)
- // If this is the last link in the proxy chain, assign it the series of labels
- // Else, if it has a special label, add that label
- // Else, if there are no other apps in the remaining part of the chain which
- // have the same package name, add the app label
- // If it is not the last link in the chain, remove its attribution
- if (idx == chain.size - 1) {
- approvedLabels[appAttr] = labels
+ // Find labels for proxies, and assign them to the proper app, removing other usages
+ val approvedLabels = mutableMapOf<PackageAttribution, List<CharSequence>>()
+ for (chain in proxyChains) {
+ // if the final link in the chain is not user sensitive, do not show the chain
+ if (getPackageAttr(chain[chain.size - 1]) !in appUsages) {
continue
- } else if (appAttr in approvedAttrs) {
- labels.add(approvedAttrs[appAttr]!!)
- approvedAttrs.remove(appAttr)
- } else if (chain.subList(idx + 1, chain.size).all {
- it.packageName != opAccess.packageName } &&
- opAccess.packageName != SYSTEM_PKG) {
- labels.add(KotlinUtils.getPackageLabel(app, opAccess.packageName,
- opAccess.user))
}
- appUsages.remove(appAttr)
+
+ // if the proxy access is missing, for some reason, do not show the proxy
+ if (chain.size == 1) {
+ continue
+ }
+
+ val labels = mutableListOf<CharSequence>()
+ for ((idx, opAccess) in chain.withIndex()) {
+ val appAttr = getPackageAttr(opAccess)
+ // If this is the last link in the proxy chain, assign it the series of
+ // labels
+ // Else, if it has a special label, add that label
+ // Else, if there are no other apps in the remaining part of the chain which
+ // have the same package name, add the app label
+ // If it is not the last link in the chain, remove its attribution
+ if (idx == chain.size - 1) {
+ approvedLabels[appAttr] = labels
+ continue
+ } else if (appAttr in approvedAttrs) {
+ labels.add(approvedAttrs[appAttr]!!)
+ approvedAttrs.remove(appAttr)
+ } else if (
+ chain.subList(idx + 1, chain.size).all {
+ it.packageName != opAccess.packageName
+ } && opAccess.packageName != SYSTEM_PKG
+ ) {
+ labels.add(
+ KotlinUtils.getPackageLabel(
+ app,
+ opAccess.packageName,
+ opAccess.user
+ )
+ )
+ }
+ appUsages.remove(appAttr)
+ }
}
- }
- // Any remaining truested attributions must be for non-proxy usages, so add them
- for ((packageAttr, label) in approvedAttrs) {
- approvedLabels[packageAttr] = listOf(label)
- }
+ // Any remaining truested attributions must be for non-proxy usages, so add them
+ for ((packageAttr, label) in approvedAttrs) {
+ approvedLabels[packageAttr] = listOf(label)
+ }
- removeDuplicates(appUsages, approvedLabels.keys)
+ removeDuplicates(appUsages, approvedLabels.keys)
- postValue(Usages(appUsages, callOpUsages, approvedLabels))
- }
+ postValue(Usages(appUsages, callOpUsages, approvedLabels))
+ }
- /**
- * Merge any usages for the same app which don't have a special attribution
- */
- private fun removeDuplicates(
- appUsages: MutableMap<PackageAttribution, Set<String>>,
- approvedUsages: Collection<PackageAttribution>
- ) {
- // Iterate over all non-special attribution keys
- for (packageAttr in appUsages.keys.minus(approvedUsages)) {
- var groupSet = appUsages[packageAttr] ?: continue
-
- for (otherAttr in appUsages.keys.minus(approvedUsages)) {
- if (otherAttr.pkgEq(packageAttr)) {
- groupSet = groupSet.plus(appUsages[otherAttr] ?: emptySet())
- appUsages.remove(otherAttr)
+ /** Merge any usages for the same app which don't have a special attribution */
+ private fun removeDuplicates(
+ appUsages: MutableMap<PackageAttribution, Set<String>>,
+ approvedUsages: Collection<PackageAttribution>
+ ) {
+ // Iterate over all non-special attribution keys
+ for (packageAttr in appUsages.keys.minus(approvedUsages)) {
+ var groupSet = appUsages[packageAttr] ?: continue
+
+ for (otherAttr in appUsages.keys.minus(approvedUsages)) {
+ if (otherAttr.pkgEq(packageAttr)) {
+ groupSet = groupSet.plus(appUsages[otherAttr] ?: emptySet())
+ appUsages.remove(otherAttr)
+ }
}
+ appUsages[packageAttr] = groupSet
}
- appUsages[packageAttr] = groupSet
}
}
- }
private fun getPackageAttr(usage: OpAccess): PackageAttribution {
return PackageAttribution(usage.attributionTag, usage.packageName, usage.user)
@@ -552,8 +620,7 @@ class ReviewOngoingUsageViewModelFactory(
defaultArgs: Bundle
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
override fun <T : ViewModel> create(p0: String, p1: Class<T>, state: SavedStateHandle): T {
- state.set(FIRST_OPENED_KEY, state.get<Long>(FIRST_OPENED_KEY)
- ?: System.currentTimeMillis())
+ state.set(FIRST_OPENED_KEY, state.get<Long>(FIRST_OPENED_KEY) ?: System.currentTimeMillis())
@Suppress("UNCHECKED_CAST")
return ReviewOngoingUsageViewModel(state, extraDurationMillis) as T
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v33/ReviewPermissionDecisionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v33/ReviewPermissionDecisionsViewModel.kt
index 69709264b..bb3c44675 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v33/ReviewPermissionDecisionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v33/ReviewPermissionDecisionsViewModel.kt
@@ -28,7 +28,6 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.android.permissioncontroller.DumpableLog
import com.android.permissioncontroller.R
-import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.data.SmartAsyncMediatorLiveData
import com.android.permissioncontroller.permission.data.UserPackageInfosLiveData
import com.android.permissioncontroller.permission.data.v33.PermissionDecision
@@ -37,9 +36,10 @@ import com.android.permissioncontroller.permission.model.livedatatypes.LightPack
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity
import com.android.permissioncontroller.permission.ui.auto.AutoReviewPermissionDecisionsFragment
import com.android.permissioncontroller.permission.utils.KotlinUtils
+import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.StringUtils
-import kotlinx.coroutines.Job
import java.util.concurrent.TimeUnit
+import kotlinx.coroutines.Job
/** Viewmodel for [ReviewPermissionDecisionsFragment] */
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@@ -50,82 +50,94 @@ class ReviewPermissionDecisionsViewModel(val app: Application, val user: UserHan
private val recentPermissionsLiveData = RecentPermissionDecisionsLiveData()
private val userPackageInfosLiveData = UserPackageInfosLiveData[user]
- val recentPermissionDecisionsLiveData = object
- : SmartAsyncMediatorLiveData<List<PermissionDecision>>(
- alwaysUpdateOnActive = false
- ) {
+ val recentPermissionDecisionsLiveData =
+ object :
+ SmartAsyncMediatorLiveData<List<PermissionDecision>>(alwaysUpdateOnActive = false) {
- init {
- addSource(recentPermissionsLiveData) {
- onUpdate()
- }
+ init {
+ addSource(recentPermissionsLiveData) { onUpdate() }
- addSource(userPackageInfosLiveData) {
- onUpdate()
- }
- }
-
- override suspend fun loadDataAndPostValue(job: Job) {
- if (!recentPermissionsLiveData.isInitialized ||
- !userPackageInfosLiveData.isInitialized) {
- return
+ addSource(userPackageInfosLiveData) { onUpdate() }
}
- // create package info lookup map for performance
- val packageToLightPackageInfo: MutableMap<String, LightPackageInfo> = mutableMapOf()
- for (lightPackageInfo in userPackageInfosLiveData.value!!) {
- packageToLightPackageInfo[lightPackageInfo.packageName] = lightPackageInfo
- }
-
- // verify that permission state is still correct. Will also filter out any apps that
- // were uninstalled
- val decisionsToReview: MutableList<PermissionDecision> = mutableListOf()
- for (recentDecision in recentPermissionsLiveData.value!!) {
- val lightPackageInfo = packageToLightPackageInfo[recentDecision.packageName]
- if (lightPackageInfo == null) {
- DumpableLog.e(LOG_TAG, "Package $recentDecision.packageName " +
- "is no longer installed")
- continue
+ override suspend fun loadDataAndPostValue(job: Job) {
+ if (
+ !recentPermissionsLiveData.isInitialized ||
+ !userPackageInfosLiveData.isInitialized
+ ) {
+ return
}
- val grantedGroups: List<String?> = lightPackageInfo.grantedPermissions.map {
- PermissionMapping.getGroupOfPermission(
- app.packageManager.getPermissionInfo(it, /* flags= */ 0))
+
+ // create package info lookup map for performance
+ val packageToLightPackageInfo: MutableMap<String, LightPackageInfo> = mutableMapOf()
+ for (lightPackageInfo in userPackageInfosLiveData.value!!) {
+ packageToLightPackageInfo[lightPackageInfo.packageName] = lightPackageInfo
}
- val currentlyGranted = grantedGroups.contains(recentDecision.permissionGroupName)
- if (currentlyGranted && recentDecision.isGranted) {
- decisionsToReview.add(recentDecision)
- } else if (!currentlyGranted && !recentDecision.isGranted) {
- decisionsToReview.add(recentDecision)
- } else {
- // It's okay for this to happen - the state could change due to role changes,
- // app hibernation, or other non-user-driven actions.
- DumpableLog.d(LOG_TAG,
- "Permission decision grant state (${recentDecision.isGranted}) " +
- "for ${recentDecision.packageName} access to " +
- "${recentDecision.permissionGroupName} does not match current " +
- "grant state $currentlyGranted")
+
+ // verify that permission state is still correct. Will also filter out any apps that
+ // were uninstalled
+ val decisionsToReview: MutableList<PermissionDecision> = mutableListOf()
+ for (recentDecision in recentPermissionsLiveData.value!!) {
+ val lightPackageInfo = packageToLightPackageInfo[recentDecision.packageName]
+ if (lightPackageInfo == null) {
+ DumpableLog.e(
+ LOG_TAG,
+ "Package $recentDecision.packageName " + "is no longer installed"
+ )
+ continue
+ }
+ val grantedGroups: List<String?> =
+ lightPackageInfo.grantedPermissions.map {
+ PermissionMapping.getGroupOfPermission(
+ app.packageManager.getPermissionInfo(it, /* flags= */ 0)
+ )
+ }
+ val currentlyGranted =
+ grantedGroups.contains(recentDecision.permissionGroupName)
+ if (currentlyGranted && recentDecision.isGranted) {
+ decisionsToReview.add(recentDecision)
+ } else if (!currentlyGranted && !recentDecision.isGranted) {
+ decisionsToReview.add(recentDecision)
+ } else {
+ // It's okay for this to happen - the state could change due to role
+ // changes,
+ // app hibernation, or other non-user-driven actions.
+ DumpableLog.d(
+ LOG_TAG,
+ "Permission decision grant state (${recentDecision.isGranted}) " +
+ "for ${recentDecision.packageName} access to " +
+ "${recentDecision.permissionGroupName} does not match current " +
+ "grant state $currentlyGranted"
+ )
+ }
}
- }
- postValue(decisionsToReview)
+ postValue(decisionsToReview)
+ }
}
- }
fun getAppIcon(packageName: String): Drawable? {
return KotlinUtils.getBadgedPackageIcon(app, packageName, user)
}
fun createPreferenceTitle(permissionDecision: PermissionDecision): String {
- val packageLabel = BidiFormatter.getInstance().unicodeWrap(
- KotlinUtils.getPackageLabel(app, permissionDecision.packageName, user))
- val permissionGroupLabel = KotlinUtils.getPermGroupLabel(app,
- permissionDecision.permissionGroupName).toString()
+ val packageLabel =
+ BidiFormatter.getInstance()
+ .unicodeWrap(KotlinUtils.getPackageLabel(app, permissionDecision.packageName, user))
+ val permissionGroupLabel =
+ KotlinUtils.getPermGroupLabel(app, permissionDecision.permissionGroupName).toString()
return if (permissionDecision.isGranted) {
- app.getString(R.string.granted_permission_decision, packageLabel,
- UCharacter.toLowerCase(permissionGroupLabel))
+ app.getString(
+ R.string.granted_permission_decision,
+ packageLabel,
+ UCharacter.toLowerCase(permissionGroupLabel)
+ )
} else {
- app.getString(R.string.denied_permission_decision, packageLabel,
- UCharacter.toLowerCase(permissionGroupLabel))
+ app.getString(
+ R.string.denied_permission_decision,
+ packageLabel,
+ UCharacter.toLowerCase(permissionGroupLabel)
+ )
}
}
@@ -134,8 +146,10 @@ class ReviewPermissionDecisionsViewModel(val app: Application, val user: UserHan
putExtra(Intent.EXTRA_PACKAGE_NAME, permissionDecision.packageName)
putExtra(Intent.EXTRA_PERMISSION_NAME, permissionDecision.permissionGroupName)
putExtra(Intent.EXTRA_USER, user)
- putExtra(ManagePermissionsActivity.EXTRA_CALLER_NAME,
- AutoReviewPermissionDecisionsFragment::class.java.name)
+ putExtra(
+ ManagePermissionsActivity.EXTRA_CALLER_NAME,
+ AutoReviewPermissionDecisionsFragment::class.java.name
+ )
}
}
@@ -146,15 +160,12 @@ class ReviewPermissionDecisionsViewModel(val app: Application, val user: UserHan
}
}
-/**
- * Factory for a [ReviewPermissionDecisionsViewModel]
- */
+/** Factory for a [ReviewPermissionDecisionsViewModel] */
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
class ReviewPermissionDecisionsViewModelFactory(val app: Application, val user: UserHandle) :
ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
- @Suppress("UNCHECKED_CAST")
- return ReviewPermissionDecisionsViewModel(app, user) as T
+ @Suppress("UNCHECKED_CAST") return ReviewPermissionDecisionsViewModel(app, user) as T
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt
index 304dc3db4..7bc0e1e1f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v34/PermissionRationaleViewModel.kt
@@ -32,14 +32,14 @@ import androidx.lifecycle.ViewModelProvider
import com.android.permissioncontroller.Constants
import com.android.permissioncontroller.PermissionControllerStatsLog
import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED
-import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED__BUTTON_PRESSED__INSTALL_SOURCE
import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED__BUTTON_PRESSED__HELP_CENTER
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED__BUTTON_PRESSED__INSTALL_SOURCE
import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED__BUTTON_PRESSED__PERMISSION_SETTINGS
import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_RATIONALE_DIALOG_VIEWED
import com.android.permissioncontroller.R
-import com.android.permissioncontroller.permission.data.v34.SafetyLabelInfoLiveData
import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData
import com.android.permissioncontroller.permission.data.get
+import com.android.permissioncontroller.permission.data.v34.SafetyLabelInfoLiveData
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_INTERACTED
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_RESULT
@@ -75,8 +75,8 @@ class PermissionRationaleViewModel(
/**
* Should be invoked by base activity when a valid onActivityResult is received
*
- * @param data [Intent] which may contain result data from a started Activity
- * (various data can be attached to Intent "extras")
+ * @param data [Intent] which may contain result data from a started Activity (various data
+ * can be attached to Intent "extras")
* @return {@code true} if Activity should finish after processing this result
*/
fun shouldFinishActivityForResult(data: Intent?): Boolean
@@ -88,12 +88,12 @@ class PermissionRationaleViewModel(
* should be shown with it.
*/
data class PermissionRationaleInfo(
- val groupName: String,
- val isPreloadedApp: Boolean,
- val installSourcePackageName: String?,
- val installSourceLabel: String?,
- val purposeSet: Set<Int>
- )
+ val groupName: String,
+ val isPreloadedApp: Boolean,
+ val installSourcePackageName: String?,
+ val installSourceLabel: String?,
+ val purposeSet: Set<Int>
+ )
/** A [LiveData] which holds the currently pending PermissionRationaleInfo */
val permissionRationaleInfoLiveData =
@@ -126,8 +126,11 @@ class PermissionRationaleViewModel(
KotlinUtils.getPackageLabel(app, it, Process.myUserHandle())
}
- val purposes = SafetyLabelUtils.getSafetyLabelSharingPurposesForGroup(
- safetyLabelInfo.safetyLabel, permissionGroupName)
+ val purposes =
+ SafetyLabelUtils.getSafetyLabelSharingPurposesForGroup(
+ safetyLabelInfo.safetyLabel,
+ permissionGroupName
+ )
if (value == null) {
logPermissionRationaleDialogViewed(purposes)
}
@@ -137,7 +140,8 @@ class PermissionRationaleViewModel(
safetyLabelInfo.installSourceInfo.isPreloadedApp,
installSourcePackageName,
installSourceLabel,
- purposes)
+ purposes
+ )
}
}
@@ -147,7 +151,8 @@ class PermissionRationaleViewModel(
fun sendToAppStore(context: Context, installSourcePackageName: String) {
logPermissionRationaleDialogActionReported(
- PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED__BUTTON_PRESSED__INSTALL_SOURCE)
+ PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED__BUTTON_PRESSED__INSTALL_SOURCE
+ )
val storeIntent = getAppStoreIntent(context, installSourcePackageName, packageName)
context.startActivity(storeIntent)
}
@@ -162,14 +167,17 @@ class PermissionRationaleViewModel(
if (activityResultCallback != null) {
return
}
- activityResultCallback = object : ActivityResultCallback {
- override fun shouldFinishActivityForResult(data: Intent?): Boolean {
- val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED)
- return (returnGroupName != null) && data.hasExtra(EXTRA_RESULT_PERMISSION_RESULT)
+ activityResultCallback =
+ object : ActivityResultCallback {
+ override fun shouldFinishActivityForResult(data: Intent?): Boolean {
+ val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED)
+ return (returnGroupName != null) &&
+ data.hasExtra(EXTRA_RESULT_PERMISSION_RESULT)
+ }
}
- }
logPermissionRationaleDialogActionReported(
- PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED__BUTTON_PRESSED__PERMISSION_SETTINGS)
+ PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED__BUTTON_PRESSED__PERMISSION_SETTINGS
+ )
startAppPermissionFragment(activity, groupName)
}
@@ -192,11 +200,13 @@ class PermissionRationaleViewModel(
// Add in some extra locale query parameters
val fullUri =
HelpUtils.uriWithAddedParameters(activity, Uri.parse(getHelpCenterUrlString(activity)))
- val intent = Intent(Intent.ACTION_VIEW, fullUri).apply {
- setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
- }
+ val intent =
+ Intent(Intent.ACTION_VIEW, fullUri).apply {
+ setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+ }
logPermissionRationaleDialogActionReported(
- PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED__BUTTON_PRESSED__HELP_CENTER)
+ PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED__BUTTON_PRESSED__HELP_CENTER
+ )
try {
activity.startActivity(intent)
} catch (e: ActivityNotFoundException) {
@@ -206,14 +216,17 @@ class PermissionRationaleViewModel(
}
private fun startAppPermissionFragment(activity: Activity, groupName: String) {
- val intent = Intent(Intent.ACTION_MANAGE_APP_PERMISSION)
- .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
- .putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName)
- .putExtra(Intent.EXTRA_USER, user)
- .putExtra(ManagePermissionsActivity.EXTRA_CALLER_NAME,
- PermissionRationaleActivity::class.java.name)
- .putExtra(Constants.EXTRA_SESSION_ID, sessionId)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ val intent =
+ Intent(Intent.ACTION_MANAGE_APP_PERMISSION)
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
+ .putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName)
+ .putExtra(Intent.EXTRA_USER, user)
+ .putExtra(
+ ManagePermissionsActivity.EXTRA_CALLER_NAME,
+ PermissionRationaleActivity::class.java.name
+ )
+ .putExtra(Constants.EXTRA_SESSION_ID, sessionId)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
activity.startActivityForResult(intent, APP_PERMISSION_REQUEST_CODE)
}
@@ -225,14 +238,24 @@ class PermissionRationaleViewModel(
purposes.forEach { purposeInt ->
purposesPresented = purposesPresented or 1.shl(purposeInt)
}
- PermissionControllerStatsLog.write(PERMISSION_RATIONALE_DIALOG_VIEWED, sessionId, uid,
- permissionGroupName, purposesPresented)
+ PermissionControllerStatsLog.write(
+ PERMISSION_RATIONALE_DIALOG_VIEWED,
+ sessionId,
+ uid,
+ permissionGroupName,
+ purposesPresented
+ )
}
fun logPermissionRationaleDialogActionReported(buttonPressed: Int) {
val uid = KotlinUtils.getPackageUid(app, packageName, user) ?: return
- PermissionControllerStatsLog.write(PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED, sessionId,
- uid, permissionGroupName, buttonPressed)
+ PermissionControllerStatsLog.write(
+ PERMISSION_RATIONALE_DIALOG_ACTION_REPORTED,
+ sessionId,
+ uid,
+ permissionGroupName,
+ buttonPressed
+ )
}
private fun getHelpCenterUrlString(context: Context): String? {
@@ -257,7 +280,12 @@ class PermissionRationaleViewModelFactory(
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
return PermissionRationaleViewModel(
- app, packageName, permissionGroupName, sessionId, savedState)
+ app,
+ packageName,
+ permissionGroupName,
+ sessionId,
+ savedState
+ )
as T
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java
index e2df47009..399a694d0 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java
@@ -289,7 +289,7 @@ public class AppPermissionFragment extends SettingsWithHeader
});
mAllowAlwaysButton.setOnPreferenceClickListener((v) -> {
if (mIsStorageGroup) {
- showConfirmDialog(ChangeRequest.GRANT_All_FILE_ACCESS,
+ showConfirmDialog(ChangeRequest.GRANT_ALL_FILE_ACCESS,
R.string.special_file_access_dialog, -1, false);
} else {
mViewModel.requestChange(false, this, this, ChangeRequest.GRANT_BOTH,
@@ -464,7 +464,7 @@ public class AppPermissionFragment extends SettingsWithHeader
public Dialog onCreateDialog(Bundle savedInstanceState) {
AppPermissionFragment fragment = (AppPermissionFragment) getTargetFragment();
boolean isGrantFileAccess = getArguments().getSerializable(CHANGE_REQUEST)
- == ChangeRequest.GRANT_All_FILE_ACCESS;
+ == ChangeRequest.GRANT_ALL_FILE_ACCESS;
int positiveButtonStringResId = R.string.grant_dialog_button_deny_anyway;
if (isGrantFileAccess) {
positiveButtonStringResId = R.string.grant_dialog_button_allow;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/television/TvUnusedAppsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/television/TvUnusedAppsFragment.kt
index 07e2ab08f..6797f5dff 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/television/TvUnusedAppsFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/television/TvUnusedAppsFragment.kt
@@ -27,16 +27,14 @@ import com.android.permissioncontroller.hibernation.isHibernationEnabled
import com.android.permissioncontroller.permission.ui.UnusedAppsFragment
import com.android.permissioncontroller.permission.ui.UnusedAppsFragment.Companion.INFO_MSG_CATEGORY
-/**
- * TV wrapper, with customizations, around [UnusedAppsFragment].
- */
-class TvUnusedAppsFragment : SettingsWithHeader(),
- UnusedAppsFragment.Parent<TvUnusedAppsPreference> {
+/** TV wrapper, with customizations, around [UnusedAppsFragment]. */
+class TvUnusedAppsFragment :
+ SettingsWithHeader(), UnusedAppsFragment.Parent<TvUnusedAppsPreference> {
companion object {
private const val UNUSED_PREFERENCE_KEY = "unused_pref_row_key"
- /** Create a new instance of this fragment. */
+ /** Create a new instance of this fragment. */
@JvmStatic
fun newInstance(): TvUnusedAppsFragment {
return TvUnusedAppsFragment()
@@ -50,15 +48,12 @@ class TvUnusedAppsFragment : SettingsWithHeader(),
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (savedInstanceState == null) {
- val fragment:
- UnusedAppsFragment<TvUnusedAppsFragment, TvUnusedAppsPreference> =
+ val fragment: UnusedAppsFragment<TvUnusedAppsFragment, TvUnusedAppsPreference> =
UnusedAppsFragment.newInstance()
fragment.arguments = arguments
// child fragment does not have its own UI - it will add to the preferences of this
// parent fragment
- childFragmentManager.beginTransaction()
- .add(fragment, null)
- .commit()
+ childFragmentManager.beginTransaction().add(fragment, null).commit()
}
}
@@ -67,8 +62,7 @@ class TvUnusedAppsFragment : SettingsWithHeader(),
if (isHibernationEnabled()) {
preference.summary = getString(R.string.unused_apps_page_tv_summary)
} else {
- preference.summary =
- getString(R.string.auto_revoked_apps_page_summary)
+ preference.summary = getString(R.string.auto_revoked_apps_page_summary)
}
preference.setIcon(R.drawable.ic_info_outline)
preference.isSelectable = false
@@ -93,9 +87,9 @@ class TvUnusedAppsFragment : SettingsWithHeader(),
override fun setEmptyState(empty: Boolean) {
val infoMsgCategory =
- preferenceScreen.findPreference<PreferenceCategory>(INFO_MSG_CATEGORY)!!
+ preferenceScreen.findPreference<PreferenceCategory>(INFO_MSG_CATEGORY)!!
val noUnusedAppsPreference: Preference? =
- infoMsgCategory.findPreference<Preference>(UNUSED_PREFERENCE_KEY)
+ infoMsgCategory.findPreference<Preference>(UNUSED_PREFERENCE_KEY)
if (empty && noUnusedAppsPreference == null) {
infoMsgCategory.addPreference(createNoUnusedAppsPreference())
} else if (noUnusedAppsPreference != null) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/television/TvUnusedAppsPreference.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/television/TvUnusedAppsPreference.kt
index 905aa30d1..bc29e928f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/television/TvUnusedAppsPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/television/TvUnusedAppsPreference.kt
@@ -16,10 +16,10 @@
package com.android.permissioncontroller.permission.ui.television
-import androidx.preference.Preference
import android.app.Application
import android.content.Context
import android.os.UserHandle
+import androidx.preference.Preference
import com.android.permissioncontroller.permission.ui.RemovablePref
import com.android.permissioncontroller.permission.utils.KotlinUtils
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/v33/AdvancedConfirmDialogArgs.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/v33/AdvancedConfirmDialogArgs.kt
index b841f3aeb..a2505312d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/v33/AdvancedConfirmDialogArgs.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/v33/AdvancedConfirmDialogArgs.kt
@@ -28,8 +28,7 @@ data class AdvancedConfirmDialogArgs(
@StringRes val messageId: Int,
@StringRes val negativeButtonTextId: Int,
@StringRes val positiveButtonTextId: Int,
-
val changeRequest: AppPermissionViewModel.ChangeRequest? = null,
val setOneTime: Boolean? = null,
val buttonClicked: Int? = null
-) \ No newline at end of file
+)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/v33/widget/SafetyProtectionSectionView.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/v33/widget/SafetyProtectionSectionView.kt
index daea1c198..9f91f3c18 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/v33/widget/SafetyProtectionSectionView.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/v33/widget/SafetyProtectionSectionView.kt
@@ -49,11 +49,12 @@ class SafetyProtectionSectionView : LinearLayout {
init {
gravity = Gravity.CENTER
orientation = HORIZONTAL
- visibility = if (KotlinUtils.shouldShowSafetyProtectionResources(context)) {
- View.VISIBLE
- } else {
- View.GONE
- }
+ visibility =
+ if (KotlinUtils.shouldShowSafetyProtectionResources(context)) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
}
override fun onFinishInflate() {
@@ -62,8 +63,9 @@ class SafetyProtectionSectionView : LinearLayout {
LayoutInflater.from(context).inflate(R.layout.safety_protection_section, this)
val safetyProtectionDisplayTextView =
requireViewById<TextView>(R.id.safety_protection_display_text)
- safetyProtectionDisplayTextView.setText(Html.fromHtml(
- context.getString(android.R.string.safety_protection_display_text), 0))
+ safetyProtectionDisplayTextView.setText(
+ Html.fromHtml(context.getString(android.R.string.safety_protection_display_text), 0)
+ )
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/v34/PermissionRationaleViewHandler.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/v34/PermissionRationaleViewHandler.kt
index 0b7537136..02f5e9d41 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/v34/PermissionRationaleViewHandler.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/v34/PermissionRationaleViewHandler.kt
@@ -38,8 +38,8 @@ interface PermissionRationaleViewHandler {
}
/**
- * Listener interface for getting notified when the user responds to a permission rationale
- * user action.
+ * Listener interface for getting notified when the user responds to a permission rationale user
+ * action.
*/
interface ResultListener {
fun onPermissionRationaleResult(groupName: String?, @Result result: Int)
@@ -60,7 +60,7 @@ interface PermissionRationaleViewHandler {
* @param groupName the name of the permission group
* @param title the title for the dialog
* @param dataSharingSourceMessage the data sharing source data usage comes from message to
- * display the user
+ * display the user
* @param purposeTitle the data usage purposes title to display the user
* @param purposeMessage the data usage purposes message to display the user
* @param learnMoreMessage the more info about safety labels message to display the user
@@ -91,9 +91,7 @@ interface PermissionRationaleViewHandler {
/** Gives a chance for handling the back key. */
fun onBackPressed()
- /**
- * Handles cancel event for the permission rationale dialog.
- */
+ /** Handles cancel event for the permission rationale dialog. */
fun onCancelled() {}
/**
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/AndroidUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/AndroidUtils.kt
index 6a6623da7..a5f78aa53 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/AndroidUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/AndroidUtils.kt
@@ -26,19 +26,19 @@ import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.os.Looper
import android.os.UserHandle
-import kotlinx.coroutines.asCoroutineDispatcher
import java.util.concurrent.Executors
+import kotlinx.coroutines.asCoroutineDispatcher
-/**
- * Gets an [Application] instance from a regular [Context]
- */
-val Context.application: Application get() = when (this) {
- is Application -> this
- is Activity -> application
- is Service -> application
- is ContextWrapper -> baseContext.application
- else -> applicationContext as Application
-}
+/** Gets an [Application] instance from a regular [Context] */
+val Context.application: Application
+ get() =
+ when (this) {
+ is Application -> this
+ is Activity -> application
+ is Service -> application
+ is ContextWrapper -> baseContext.application
+ else -> applicationContext as Application
+ }
/**
* The number of threads in the IPC thread pool. Set to the maximum number of binder threads allowed
@@ -46,21 +46,16 @@ val Context.application: Application get() = when (this) {
*/
const val IPC_THREAD_POOL_COUNT = 8
-/**
- * A coroutine dispatcher with a fixed thread pool size, to be used for background tasks
- */
+/** A coroutine dispatcher with a fixed thread pool size, to be used for background tasks */
val IPC = Executors.newFixedThreadPool(IPC_THREAD_POOL_COUNT).asCoroutineDispatcher()
-/**
- * Assert that an operation is running on main thread
- */
-fun ensureMainThread() = check(Looper.myLooper() == Looper.getMainLooper()) {
- "Only meant to be used on the main thread"
-}
+/** Assert that an operation is running on main thread */
+fun ensureMainThread() =
+ check(Looper.myLooper() == Looper.getMainLooper()) {
+ "Only meant to be used on the main thread"
+ }
-/**
- * A more readable version of [PackageManager.updatePermissionFlags]
- */
+/** A more readable version of [PackageManager.updatePermissionFlags] */
fun PackageManager.updatePermissionFlags(
permissionName: String,
packageName: String,
@@ -68,18 +63,14 @@ fun PackageManager.updatePermissionFlags(
vararg flags: Pair<Int, Boolean>
) {
val mask = flags.fold(0, { mask, (flag, _) -> mask or flag })
- val value = flags.fold(0,
- { mask2, (flag, flagValue) -> if (flagValue) mask2 or flag else mask2 })
+ val value =
+ flags.fold(0, { mask2, (flag, flagValue) -> if (flagValue) mask2 or flag else mask2 })
updatePermissionFlags(permissionName, packageName, mask, value, user)
}
-/**
- * Gets a [ComponentInfo] from a [ResolveInfo]
- */
+/** Gets a [ComponentInfo] from a [ResolveInfo] */
val ResolveInfo.componentInfo: ComponentInfo
get() {
return (activityInfo as ComponentInfo?)
- ?: serviceInfo
- ?: providerInfo
- ?: throw IllegalStateException("Missing ComponentInfo!")
- } \ No newline at end of file
+ ?: serviceInfo ?: providerInfo ?: throw IllegalStateException("Missing ComponentInfo!")
+ }
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/DebugUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/DebugUtils.kt
index cf8a69b40..96d634ded 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/DebugUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/DebugUtils.kt
@@ -25,24 +25,21 @@ import java.util.Collections.reverse
*/
fun shortStackTrace() = permissionsStackTrace().toShortString()
-/**
- * [StackTraceElement]s of only the permission-related frames
- */
-fun permissionsStackTrace() = stackTraceWithin("com.android.permissioncontroller")
- .dropLastWhile { it.className.contains(".DebugUtils") }
+/** [StackTraceElement]s of only the permission-related frames */
+fun permissionsStackTrace() =
+ stackTraceWithin("com.android.permissioncontroller").dropLastWhile {
+ it.className.contains(".DebugUtils")
+ }
/**
* [StackTraceElement]s of only frames who's [full class name][StackTraceElement.getClassName]
* starts with [pkgPrefix]
*/
-fun stackTraceWithin(pkgPrefix: String) = Thread
- .currentThread()
- .stackTrace
- .dropWhile {
- !it.className.startsWith(pkgPrefix)
- }.takeWhile {
- it.className.startsWith(pkgPrefix)
- }
+fun stackTraceWithin(pkgPrefix: String) =
+ Thread.currentThread()
+ .stackTrace
+ .dropWhile { !it.className.startsWith(pkgPrefix) }
+ .takeWhile { it.className.startsWith(pkgPrefix) }
/**
* Renders a stack trace slice to a short-ish single-line string.
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
index 358f86f4b..f2aa0ae66 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
@@ -25,6 +25,7 @@ import android.Manifest.permission.POST_NOTIFICATIONS
import android.Manifest.permission.READ_MEDIA_IMAGES
import android.Manifest.permission.READ_MEDIA_VIDEO
import android.Manifest.permission_group.NOTIFICATIONS
+import android.app.Activity
import android.app.ActivityManager
import android.app.AppOpsManager
import android.app.AppOpsManager.MODE_ALLOWED
@@ -59,8 +60,10 @@ import android.health.connect.HealthConnectManager
import android.os.Build
import android.os.Bundle
import android.os.UserHandle
+import android.os.UserManager
import android.permission.PermissionManager
import android.provider.DeviceConfig
+import android.provider.MediaStore
import android.provider.Settings
import android.safetylabel.SafetyLabelConstants.PERMISSION_RATIONALE_ENABLED
import android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED
@@ -297,17 +300,14 @@ object KotlinUtils {
)
}
- /**
- * Whether the Photo Picker Prompt is supported by the device
- *
- */
+ /** Whether the Photo Picker Prompt is supported by the device */
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
fun isPhotoPickerPromptSupported(): Boolean {
val app = PermissionControllerApplication.get()
return SdkLevel.isAtLeastU() &&
- !DeviceUtils.isAuto(app) &&
- !DeviceUtils.isTelevision(app) &&
- !DeviceUtils.isWear(app)
+ !DeviceUtils.isAuto(app) &&
+ !DeviceUtils.isTelevision(app) &&
+ !DeviceUtils.isWear(app)
}
/*
@@ -650,6 +650,28 @@ object KotlinUtils {
}
}
+ fun openPhotoPickerForApp(
+ activity: Activity,
+ uid: Int,
+ requestedPermissions: List<String>,
+ requestCode: Int
+ ) {
+ // A clone profile doesn't have a MediaProvider. If the app's user is a clone profile, open
+ // the photo picker in the parent profile
+ val appUser = UserHandle.getUserHandleForUid(uid)
+ val userManager =
+ activity.createContextAsUser(appUser, 0).getSystemService(UserManager::class.java)!!
+ val user = if (userManager.isCloneProfile) {
+ userManager.getProfileParent(appUser) ?: appUser
+ } else {
+ appUser
+ }
+ val pickerIntent = Intent(MediaStore.ACTION_USER_SELECT_IMAGES_FOR_APP)
+ .putExtra(Intent.EXTRA_UID, uid)
+ .setType(getMimeTypeForPermissions(requestedPermissions))
+ activity.startActivityForResultAsUser(pickerIntent, requestCode, user)
+ }
+
/** Return a specific MIME type, if a set of permissions is associated with one */
fun getMimeTypeForPermissions(permissions: List<String>): String? {
if (permissions.contains(READ_MEDIA_IMAGES) && !permissions.contains(READ_MEDIA_VIDEO)) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
index 32d3a5325..840a033c3 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
@@ -23,10 +23,9 @@ import android.content.pm.PackageManager
import android.content.pm.PermissionInfo
import android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP
import android.util.Log
-
import com.android.modules.utils.build.SdkLevel
-import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
import com.android.permission.safetylabel.DataCategoryConstants
+import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
/**
* This file contains the canonical mapping of permission to permission group, used in the
@@ -36,15 +35,16 @@ object PermissionMapping {
private val LOG_TAG = "PermissionMapping"
- private val PERMISSION_GROUPS_TO_DATA_CATEGORIES: Map<String, List<String>> = mapOf(
- Manifest.permission_group.LOCATION to listOf(DataCategoryConstants.CATEGORY_LOCATION))
+ private val PERMISSION_GROUPS_TO_DATA_CATEGORIES: Map<String, List<String>> =
+ mapOf(Manifest.permission_group.LOCATION to listOf(DataCategoryConstants.CATEGORY_LOCATION))
@JvmField
val SENSOR_DATA_PERMISSIONS: List<String> =
listOf(
Manifest.permission_group.LOCATION,
Manifest.permission_group.CAMERA,
- Manifest.permission_group.MICROPHONE)
+ Manifest.permission_group.MICROPHONE
+ )
@JvmField
val STORAGE_SUPERGROUP_PERMISSIONS: List<String> =
@@ -53,7 +53,8 @@ object PermissionMapping {
listOf(
Manifest.permission_group.STORAGE,
Manifest.permission_group.READ_MEDIA_AURAL,
- Manifest.permission_group.READ_MEDIA_VISUAL)
+ Manifest.permission_group.READ_MEDIA_VISUAL
+ )
val PARTIAL_MEDIA_PERMISSIONS: MutableSet<String> = mutableSetOf()
@@ -68,7 +69,6 @@ object PermissionMapping {
private val HEALTH_PERMISSIONS_SET: MutableSet<String> = mutableSetOf()
-
init {
PLATFORM_PERMISSIONS[Manifest.permission.READ_CONTACTS] = Manifest.permission_group.CONTACTS
PLATFORM_PERMISSIONS[Manifest.permission.WRITE_CONTACTS] =
@@ -202,7 +202,6 @@ object PermissionMapping {
* platform permission.
*
* @param permission the permission to resolve
- *
* @return The group the permission belongs to
*/
@JvmStatic
@@ -214,7 +213,6 @@ object PermissionMapping {
* Get name of the permission group a permission belongs to.
*
* @param permission the [info][PermissionInfo] of the permission to resolve
- *
* @return The group the permission belongs to
*/
@JvmStatic
@@ -230,9 +228,8 @@ object PermissionMapping {
* Get the names for all platform permissions belonging to a group.
*
* @param group the group
- *
* @return The permission names or an empty list if the group does not have platform runtime
- * permissions
+ * permissions
*/
@JvmStatic
fun getPlatformPermissionNamesOfGroup(group: String): List<String> {
@@ -245,19 +242,19 @@ object PermissionMapping {
*
* @param pm Package manager to use to resolve permission infos
* @param group the group
- *
* @return The infos for platform permissions belonging to the group or an empty list if the
- * group does not have platform runtime permissions
+ * group does not have platform runtime permissions
*/
@JvmStatic
fun getPlatformPermissionsOfGroup(pm: PackageManager, group: String): List<PermissionInfo> {
val permInfos = mutableListOf<PermissionInfo>()
for (permName in PLATFORM_PERMISSION_GROUPS[group] ?: emptyList()) {
- val permInfo: PermissionInfo = try {
+ val permInfo: PermissionInfo =
+ try {
pm.getPermissionInfo(permName, 0)
- } catch (e: PackageManager.NameNotFoundException) {
- throw IllegalStateException("$permName not defined by platform", e)
- }
+ } catch (e: PackageManager.NameNotFoundException) {
+ throw IllegalStateException("$permName not defined by platform", e)
+ }
permInfos.add(permInfo)
}
return permInfos
@@ -300,6 +297,7 @@ object PermissionMapping {
/**
* Whether the permission group supports one-time
+ *
* @param permissionGroup The permission group to check
* @return `true` iff the group supports one-time
*/
@@ -308,9 +306,7 @@ object PermissionMapping {
return ONE_TIME_PERMISSION_GROUPS.contains(permissionGroup)
}
- /**
- * Adds health permissions as platform permissions.
- */
+ /** Adds health permissions as platform permissions. */
@JvmStatic
fun addHealthPermissionsToPlatform(permissions: Set<String>) {
if (permissions.isEmpty()) {
@@ -338,8 +334,9 @@ object PermissionMapping {
return emptySet()
}
- val appSupportsPickerPrompt = group
- .permissions[Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED]?.isImplicit == false
+ val appSupportsPickerPrompt =
+ group.permissions[Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED]?.isImplicit ==
+ false
return if (appSupportsPickerPrompt) {
PARTIAL_MEDIA_PERMISSIONS
@@ -348,9 +345,7 @@ object PermissionMapping {
}
}
- /**
- * Returns true if the given permission is a health platform permission.
- */
+ /** Returns true if the given permission is a health platform permission. */
@JvmStatic
fun isHealthPermission(permissionName: String): Boolean {
return HEALTH_PERMISSIONS_SET.contains(permissionName)
@@ -386,8 +381,8 @@ object PermissionMapping {
/**
* Get the SafetyLabel categories pertaining to a specified permission group.
*
- * @return The categories, or an empty list if the group does not have a supported mapping
- * to safety label category
+ * @return The categories, or an empty list if the group does not have a supported mapping to
+ * safety label category
*/
fun getDataCategoriesForPermissionGroup(permissionGroupName: String): List<String> {
return if (isSafetyLabelAwarePermissionGroup(permissionGroupName)) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/SystemTimeSource.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/SystemTimeSource.kt
index dc05ededc..116c498be 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/SystemTimeSource.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/SystemTimeSource.kt
@@ -18,9 +18,7 @@ package com.android.permissioncontroller.permission.utils
import android.os.SystemClock
-/**
- * Time source that uses the system time.
- */
+/** Time source that uses the system time. */
class SystemTimeSource : TimeSource {
override fun currentTimeMillis(): Long {
@@ -30,4 +28,4 @@ class SystemTimeSource : TimeSource {
override fun elapsedRealtime(): Long {
return SystemClock.elapsedRealtime()
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/TimeSource.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/TimeSource.kt
index 00b93f405..29883e1f3 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/TimeSource.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/TimeSource.kt
@@ -16,18 +16,12 @@
package com.android.permissioncontroller.permission.utils
-/**
- * Interface for system time components.
- */
+/** Interface for system time components. */
interface TimeSource {
- /**
- * Returns the current time in milliseconds.
- */
+ /** Returns the current time in milliseconds. */
fun currentTimeMillis(): Long
- /**
- * Returns milliseconds since boot, including time spent in sleep.
- */
+ /** Returns milliseconds since boot, including time spent in sleep. */
fun elapsedRealtime(): Long
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/UserSensitiveFlagsUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/UserSensitiveFlagsUtils.kt
index 3cd9891ee..50cacf876 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/UserSensitiveFlagsUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/UserSensitiveFlagsUtils.kt
@@ -25,9 +25,9 @@ import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.permission.data.UserSensitivityLiveData
import com.android.permissioncontroller.permission.model.livedatatypes.UidSensitivityState
import com.android.permissioncontroller.permission.utils.Utils.FLAGS_ALWAYS_USER_SENSITIVE
+import java.lang.IllegalStateException
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
-import java.lang.IllegalStateException
private const val LOG_TAG = "UserSensitiveFlagsUtils"
@@ -35,10 +35,9 @@ private const val LOG_TAG = "UserSensitiveFlagsUtils"
* Update the [PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED] and
* [PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED] for all apps of this user.
*
- * @see UserSensitivityLiveData.loadDataAndPostValue
- *
* @param user The user for whom packages will be updated
* @param callback A callback which will be executed when finished
+ * @see UserSensitivityLiveData.loadDataAndPostValue
*/
fun updateUserSensitiveForUser(user: UserHandle, callback: Runnable) {
GlobalScope.launch(IPC) {
@@ -47,7 +46,8 @@ fun updateUserSensitiveForUser(user: UserHandle, callback: Runnable) {
if (uidUserSensitivity == null) {
callback.run()
throw IllegalStateException(
- "All uids sensitivity liveData should not be null if initialized")
+ "All uids sensitivity liveData should not be null if initialized"
+ )
}
updateUserSensitiveForUidsInternal(uidUserSensitivity, user, callback)
}
@@ -62,28 +62,38 @@ private fun updateUserSensitiveForUidsInternal(
val pm = userContext.packageManager
for ((uid, uidState) in uidsUserSensitivity) {
- for (pkg in uidState.packages) {
- for (perm in pkg.requestedPermissions) {
- var flags = uidState.permStates[perm] ?: continue
+ for (pkg in uidState.packages) {
+ for (perm in pkg.requestedPermissions) {
+ var flags = uidState.permStates[perm] ?: continue
- try {
- val oldFlags = pm.getPermissionFlags(perm, pkg.packageName, user) and
+ try {
+ val oldFlags =
+ pm.getPermissionFlags(perm, pkg.packageName, user) and
FLAGS_ALWAYS_USER_SENSITIVE
- if (flags != oldFlags) {
- pm.updatePermissionFlags(perm, pkg.packageName,
- FLAGS_ALWAYS_USER_SENSITIVE, flags, user)
- }
- } catch (e: IllegalArgumentException) {
- if (e.message?.startsWith("Unknown permission: ") == false) {
- Log.e(LOG_TAG, "Unexpected exception while updating flags for " +
- "${pkg.packageName} (uid $uid) permission $perm", e)
- } else {
- // Unknown permission - ignore
- }
+ if (flags != oldFlags) {
+ pm.updatePermissionFlags(
+ perm,
+ pkg.packageName,
+ FLAGS_ALWAYS_USER_SENSITIVE,
+ flags,
+ user
+ )
+ }
+ } catch (e: IllegalArgumentException) {
+ if (e.message?.startsWith("Unknown permission: ") == false) {
+ Log.e(
+ LOG_TAG,
+ "Unexpected exception while updating flags for " +
+ "${pkg.packageName} (uid $uid) permission $perm",
+ e
+ )
+ } else {
+ // Unknown permission - ignore
}
}
}
}
+ }
callback?.run()
}
@@ -98,8 +108,11 @@ fun updateUserSensitiveForUid(uid: Int, callback: Runnable? = null) {
GlobalScope.launch(IPC) {
val uidSensitivityState = UserSensitivityLiveData[uid].getInitializedValue()
if (uidSensitivityState != null) {
- updateUserSensitiveForUidsInternal(uidSensitivityState,
- UserHandle.getUserHandleForUid(uid), callback)
+ updateUserSensitiveForUidsInternal(
+ uidSensitivityState,
+ UserHandle.getUserHandleForUid(uid),
+ callback
+ )
} else {
Log.e(LOG_TAG, "No packages associated with uid $uid, not updating flags")
callback?.run()
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt
index 5dbe203f9..9fd8ab916 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt
@@ -32,8 +32,8 @@ object SafetyLabelUtils {
groupName: String
): Set<Int> {
val purposeSet = mutableSetOf<Int>()
- val categoriesForPermission = PermissionMapping
- .getDataCategoriesForPermissionGroup(groupName)
+ val categoriesForPermission =
+ PermissionMapping.getDataCategoriesForPermissionGroup(groupName)
categoriesForPermission.forEach categoryLoop@{ category ->
val dataCategory: DataCategory? = safetyLabel.dataLabel.dataShared[category]
if (dataCategory == null) {
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySettingsUtil.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySettingsUtil.kt
index 59dbf635d..f9079c41b 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySettingsUtil.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySettingsUtil.kt
@@ -32,24 +32,28 @@ object AccessibilitySettingsUtil {
private val LOG_TAG = AccessibilitySettingsUtil::class.java.simpleName
private val lock = Mutex()
- /**
- * Changes an accessibility component's state.
- */
+ /** Changes an accessibility component's state. */
suspend fun disableAccessibilityService(context: Context, serviceToBeDisabled: ComponentName) {
lock.withLock {
val settingsEnabledA11yServices = getEnabledServicesFromSettings(context)
- if (settingsEnabledA11yServices.isEmpty() ||
- !settingsEnabledA11yServices.contains(serviceToBeDisabled)
+ if (
+ settingsEnabledA11yServices.isEmpty() ||
+ !settingsEnabledA11yServices.contains(serviceToBeDisabled)
) {
- Log.w(LOG_TAG, "${serviceToBeDisabled.toShortString()} is already disabled " +
- "or not installed.")
+ Log.w(
+ LOG_TAG,
+ "${serviceToBeDisabled.toShortString()} is already disabled " +
+ "or not installed."
+ )
return
}
settingsEnabledA11yServices.remove(serviceToBeDisabled)
- val updatedEnabledServices = settingsEnabledA11yServices.map { it.flattenToString() }
- .joinToString(separator = ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR.toString())
+ val updatedEnabledServices =
+ settingsEnabledA11yServices
+ .map { it.flattenToString() }
+ .joinToString(separator = ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR.toString())
Settings.Secure.putString(
context.contentResolver,
@@ -59,27 +63,24 @@ object AccessibilitySettingsUtil {
}
}
- /**
- * @return the mutable set of enabled accessibility services.
- */
+ /** @return the mutable set of enabled accessibility services. */
fun getEnabledServicesFromSettings(context: Context): MutableSet<ComponentName> {
- val enabledServicesSetting = Settings.Secure.getString(
- context.contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
- )
+ val enabledServicesSetting =
+ Settings.Secure.getString(
+ context.contentResolver,
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
+ )
val enabledServices = mutableSetOf<ComponentName>()
if (TextUtils.isEmpty(enabledServicesSetting)) {
return enabledServices
}
- val colonSplitter: TextUtils.StringSplitter = TextUtils.SimpleStringSplitter(
- ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR
- )
+ val colonSplitter: TextUtils.StringSplitter =
+ TextUtils.SimpleStringSplitter(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR)
colonSplitter.setString(enabledServicesSetting)
for (componentNameString in colonSplitter) {
- val enabledService = ComponentName.unflattenFromString(
- componentNameString
- )
+ val enabledService = ComponentName.unflattenFromString(componentNameString)
if (enabledService != null) {
enabledServices.add(enabledService)
} else {
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt
index 33acd8285..5f29e87fa 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt
@@ -80,8 +80,7 @@ import kotlinx.coroutines.sync.withLock
const val PROPERTY_SC_ACCESSIBILITY_SOURCE_ENABLED = "sc_accessibility_source_enabled"
const val PROPERTY_SC_ACCESSIBILITY_LISTENER_ENABLED = "sc_accessibility_listener_enabled"
const val SC_ACCESSIBILITY_SOURCE_ID = "AndroidAccessibility"
-const val SC_ACCESSIBILITY_REMOVE_ACCESS_ACTION_ID =
- "revoke_accessibility_app_access"
+const val SC_ACCESSIBILITY_REMOVE_ACCESS_ACTION_ID = "revoke_accessibility_app_access"
private const val DEBUG = false
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
@@ -97,9 +96,7 @@ fun isAccessibilitySourceEnabled(): Boolean {
)
}
-/**
- * cts test needs to disable the listener.
- */
+/** cts test needs to disable the listener. */
fun isAccessibilityListenerEnabled(): Boolean {
return DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_PRIVACY,
@@ -110,24 +107,21 @@ fun isAccessibilityListenerEnabled(): Boolean {
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private fun isSafetyCenterEnabled(context: Context): Boolean {
- return getSystemServiceSafe(context, SafetyCenterManager::class.java)
- .isSafetyCenterEnabled
+ return getSystemServiceSafe(context, SafetyCenterManager::class.java).isSafetyCenterEnabled
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
-class AccessibilitySourceService(
- val context: Context,
- val random: Random = Random()
-) : PrivacySource {
+class AccessibilitySourceService(val context: Context, val random: Random = Random()) :
+ PrivacySource {
private val parentUserContext = Utils.getParentUserContext(context)
private val packageManager = parentUserContext.packageManager
- private val sharedPrefs: SharedPreferences = parentUserContext.getSharedPreferences(
- ACCESSIBILITY_PREFERENCES_FILE, Context.MODE_PRIVATE)
- private val notificationsManager = getSystemServiceSafe(parentUserContext,
- NotificationManager::class.java)
- private val safetyCenterManager = getSystemServiceSafe(parentUserContext,
- SafetyCenterManager::class.java)
+ private val sharedPrefs: SharedPreferences =
+ parentUserContext.getSharedPreferences(ACCESSIBILITY_PREFERENCES_FILE, Context.MODE_PRIVATE)
+ private val notificationsManager =
+ getSystemServiceSafe(parentUserContext, NotificationManager::class.java)
+ private val safetyCenterManager =
+ getSystemServiceSafe(parentUserContext, SafetyCenterManager::class.java)
@WorkerThread
internal suspend fun processAccessibilityJob(
@@ -157,15 +151,15 @@ class AccessibilitySourceService(
val lastShownNotification =
sharedPrefs.getLong(KEY_LAST_ACCESSIBILITY_NOTIFICATION_SHOWN, 0)
- val showNotification = ((System.currentTimeMillis() - lastShownNotification) >
- getNotificationsIntervalMillis()) && getCurrentNotification() == null
+ val showNotification =
+ ((System.currentTimeMillis() - lastShownNotification) >
+ getNotificationsIntervalMillis()) && getCurrentNotification() == null
if (showNotification) {
val alreadyNotifiedServices = getNotifiedServices()
- val toBeNotifiedServices = a11yServiceList.filter {
- !alreadyNotifiedServices.contains(it.id)
- }
+ val toBeNotifiedServices =
+ a11yServiceList.filter { !alreadyNotifiedServices.contains(it.id) }
if (toBeNotifiedServices.isNotEmpty()) {
if (DEBUG) {
@@ -194,9 +188,7 @@ class AccessibilitySourceService(
}
}
- /**
- * sends a notification for a given accessibility package
- */
+ /** sends a notification for a given accessibility package */
private suspend fun sendNotification(
serviceToBeNotified: AccessibilityServiceInfo,
sessionId: Long
@@ -214,13 +206,13 @@ class AccessibilitySourceService(
identifier = componentName.flattenToString()
}
- val title = parentUserContext.getString(
- R.string.accessibility_access_reminder_notification_title
- )
- val summary = parentUserContext.getString(
- R.string.accessibility_access_reminder_notification_content,
- pkgLabel
- )
+ val title =
+ parentUserContext.getString(R.string.accessibility_access_reminder_notification_title)
+ val summary =
+ parentUserContext.getString(
+ R.string.accessibility_access_reminder_notification_content,
+ pkgLabel
+ )
val (appLabel, smallIcon, color) =
KotlinUtils.getSafetyCenterNotificationResources(parentUserContext)
@@ -236,8 +228,11 @@ class AccessibilitySourceService(
.setAutoCancel(true)
.setDeleteIntent(
PendingIntent.getBroadcast(
- parentUserContext, 0, notificationDeleteIntent,
- PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_UPDATE_CURRENT or
+ parentUserContext,
+ 0,
+ notificationDeleteIntent,
+ PendingIntent.FLAG_ONE_SHOT or
+ PendingIntent.FLAG_UPDATE_CURRENT or
PendingIntent.FLAG_IMMUTABLE
)
)
@@ -256,10 +251,10 @@ class AccessibilitySourceService(
)
sharedPrefsLock.withLock {
- sharedPrefs.edit().putLong(
- KEY_LAST_ACCESSIBILITY_NOTIFICATION_SHOWN,
- System.currentTimeMillis()
- ).apply()
+ sharedPrefs
+ .edit()
+ .putLong(KEY_LAST_ACCESSIBILITY_NOTIFICATION_SHOWN, System.currentTimeMillis())
+ .apply()
}
markServiceAsNotified(ComponentName.unflattenFromString(serviceToBeNotified.id)!!)
@@ -277,11 +272,12 @@ class AccessibilitySourceService(
/** Create the channel for a11y notifications */
private fun createPermissionReminderChannel() {
- val permissionReminderChannel = NotificationChannel(
- Constants.PERMISSION_REMINDER_CHANNEL_ID,
- context.getString(R.string.permission_reminders),
- NotificationManager.IMPORTANCE_LOW
- )
+ val permissionReminderChannel =
+ NotificationChannel(
+ Constants.PERMISSION_REMINDER_CHANNEL_ID,
+ context.getString(R.string.permission_reminders),
+ NotificationManager.IMPORTANCE_LOW
+ )
notificationsManager.createNotificationChannel(permissionReminderChannel)
}
@@ -298,32 +294,37 @@ class AccessibilitySourceService(
val pkgLabel = a11yService.resolveInfo.loadLabel(packageManager).toString()
val uid = a11yService.resolveInfo.serviceInfo.applicationInfo.uid
- val removeAccessPendingIntent = getRemoveAccessPendingIntent(
- context,
- componentName,
- safetySourceIssueId,
- uid,
- sessionId
- )
+ val removeAccessPendingIntent =
+ getRemoveAccessPendingIntent(
+ context,
+ componentName,
+ safetySourceIssueId,
+ uid,
+ sessionId
+ )
- val removeAccessAction = SafetySourceIssue.Action.Builder(
- SC_ACCESSIBILITY_REMOVE_ACCESS_ACTION_ID,
- parentUserContext.getString(R.string.accessibility_remove_access_button_label),
- removeAccessPendingIntent
- )
- .setWillResolve(true)
- .setSuccessMessage(parentUserContext.getString(
- R.string.accessibility_remove_access_success_label))
- .build()
+ val removeAccessAction =
+ SafetySourceIssue.Action.Builder(
+ SC_ACCESSIBILITY_REMOVE_ACCESS_ACTION_ID,
+ parentUserContext.getString(R.string.accessibility_remove_access_button_label),
+ removeAccessPendingIntent
+ )
+ .setWillResolve(true)
+ .setSuccessMessage(
+ parentUserContext.getString(R.string.accessibility_remove_access_success_label)
+ )
+ .build()
val accessibilityActivityPendingIntent =
getAccessibilityActivityPendingIntent(context, uid, sessionId)
- val accessibilityActivityAction = SafetySourceIssue.Action.Builder(
- SC_ACCESSIBILITY_SHOW_ACCESSIBILITY_ACTIVITY_ACTION_ID,
- parentUserContext.getString(R.string.accessibility_show_all_apps_button_label),
- accessibilityActivityPendingIntent
- ).build()
+ val accessibilityActivityAction =
+ SafetySourceIssue.Action.Builder(
+ SC_ACCESSIBILITY_SHOW_ACCESSIBILITY_ACTIVITY_ACTION_ID,
+ parentUserContext.getString(R.string.accessibility_show_all_apps_button_label),
+ accessibilityActivityPendingIntent
+ )
+ .build()
val warningCardDismissIntent =
Intent(parentUserContext, AccessibilityWarningCardDismissalReceiver::class.java).apply {
@@ -334,15 +335,19 @@ class AccessibilitySourceService(
putExtra(Intent.EXTRA_UID, uid)
}
- val warningCardDismissPendingIntent = PendingIntent.getBroadcast(
- parentUserContext, 0, warningCardDismissIntent,
- PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_UPDATE_CURRENT or
- PendingIntent.FLAG_IMMUTABLE
- )
- val title = parentUserContext.getString(
- R.string.accessibility_access_reminder_notification_title)
- val summary = parentUserContext.getString(
- R.string.accessibility_access_warning_card_content)
+ val warningCardDismissPendingIntent =
+ PendingIntent.getBroadcast(
+ parentUserContext,
+ 0,
+ warningCardDismissIntent,
+ PendingIntent.FLAG_ONE_SHOT or
+ PendingIntent.FLAG_UPDATE_CURRENT or
+ PendingIntent.FLAG_IMMUTABLE
+ )
+ val title =
+ parentUserContext.getString(R.string.accessibility_access_reminder_notification_title)
+ val summary =
+ parentUserContext.getString(R.string.accessibility_access_warning_card_content)
return SafetySourceIssue.Builder(
safetySourceIssueId,
@@ -359,9 +364,7 @@ class AccessibilitySourceService(
.build()
}
- /**
- * @return pending intent for remove access button on the warning card.
- */
+ /** @return pending intent for remove access button on the warning card. */
private fun getRemoveAccessPendingIntent(
context: Context,
serviceComponentName: ComponentName,
@@ -387,9 +390,7 @@ class AccessibilitySourceService(
)
}
- /**
- * @return pending intent for redirecting user to the accessibility page
- */
+ /** @return pending intent for redirecting user to the accessibility page */
private fun getAccessibilityActivityPendingIntent(
context: Context,
uid: Int,
@@ -412,9 +413,7 @@ class AccessibilitySourceService(
)
}
- /**
- * @return pending intent to redirect the user to safety center on notification click
- */
+ /** @return pending intent to redirect the user to safety center on notification click */
private fun getSafetyCenterActivityIntent(
context: Context,
uid: Int,
@@ -478,9 +477,7 @@ class AccessibilitySourceService(
sendIssuesToSafetyCenter(enabledServices, safetyEvent)
}
- /**
- * If [.cancel] throw an [InterruptedException].
- */
+ /** If [.cancel] throw an [InterruptedException]. */
@Throws(InterruptedException::class)
private fun interruptJobIfCanceled(cancel: BooleanSupplier?) {
if (cancel != null && cancel.asBoolean) {
@@ -488,26 +485,28 @@ class AccessibilitySourceService(
}
}
- private val accessibilityManager = getSystemServiceSafe(parentUserContext,
- AccessibilityManager::class.java)
+ private val accessibilityManager =
+ getSystemServiceSafe(parentUserContext, AccessibilityManager::class.java)
- /**
- * @return enabled 3rd party accessibility services.
- */
+ /** @return enabled 3rd party accessibility services. */
fun getEnabledAccessibilityServices(): List<AccessibilityServiceInfo> {
- val installedServices = accessibilityManager.getInstalledAccessibilityServiceList()
- .associateBy { ComponentName.unflattenFromString(it.id) }
- val enabledServices = AccessibilitySettingsUtil.getEnabledServicesFromSettings(context)
- .map {
+ val installedServices =
+ accessibilityManager.getInstalledAccessibilityServiceList().associateBy {
+ ComponentName.unflattenFromString(it.id)
+ }
+ val enabledServices =
+ AccessibilitySettingsUtil.getEnabledServicesFromSettings(context).map {
if (installedServices[it] == null) {
- Log.e(LOG_TAG, "enabled accessibility service ($it) not found in installed" +
- "services: ${installedServices.keys}")
+ Log.e(
+ LOG_TAG,
+ "enabled accessibility service ($it) not found in installed" +
+ "services: ${installedServices.keys}"
+ )
}
installedServices[it]
}
- return enabledServices.filterNotNull()
- .filter { !it.isAccessibilityTool }
+ return enabledServices.filterNotNull().filter { !it.isAccessibilityTool }
}
/**
@@ -523,13 +522,14 @@ class AccessibilitySourceService(
internal suspend fun removeFromNotifiedServices(a11Service: ComponentName) {
sharedPrefsLock.withLock {
val notifiedServices = getNotifiedServices()
- val filteredServices = notifiedServices.filter {
- it != a11Service.flattenToShortString()
- }.toSet()
+ val filteredServices =
+ notifiedServices.filter { it != a11Service.flattenToShortString() }.toSet()
if (filteredServices.size < notifiedServices.size) {
- sharedPrefs.edit().putStringSet(KEY_ALREADY_NOTIFIED_SERVICES, filteredServices)
- .apply()
+ sharedPrefs
+ .edit()
+ .putStringSet(KEY_ALREADY_NOTIFIED_SERVICES, filteredServices)
+ .apply()
}
}
}
@@ -538,7 +538,9 @@ class AccessibilitySourceService(
sharedPrefsLock.withLock {
val alreadyNotifiedServices = getNotifiedServices()
alreadyNotifiedServices.add(a11Service.flattenToShortString())
- sharedPrefs.edit().putStringSet(KEY_ALREADY_NOTIFIED_SERVICES, alreadyNotifiedServices)
+ sharedPrefs
+ .edit()
+ .putStringSet(KEY_ALREADY_NOTIFIED_SERVICES, alreadyNotifiedServices)
.apply()
}
}
@@ -548,7 +550,9 @@ class AccessibilitySourceService(
val alreadyNotifiedServices = getNotifiedServices()
val services = alreadyNotifiedServices.filter { enabledA11yServices.contains(it) }
if (services.size < alreadyNotifiedServices.size) {
- sharedPrefs.edit().putStringSet(KEY_ALREADY_NOTIFIED_SERVICES, services.toSet())
+ sharedPrefs
+ .edit()
+ .putStringSet(KEY_ALREADY_NOTIFIED_SERVICES, services.toSet())
.apply()
}
}
@@ -563,17 +567,13 @@ class AccessibilitySourceService(
return sharedPrefs
}
- /**
- * Remove notification when safety center feature is turned off
- */
+ /** Remove notification when safety center feature is turned off */
private fun removeAccessibilityNotification() {
val notification: StatusBarNotification = getCurrentNotification() ?: return
cancelNotification(notification.tag)
}
- /**
- * Remove notification (if needed) when an accessibility event occur.
- */
+ /** Remove notification (if needed) when an accessibility event occur. */
fun removeAccessibilityNotification(a11yEnabledComponents: Set<String>) {
val notification = getCurrentNotification() ?: return
if (a11yEnabledComponents.contains(notification.tag)) {
@@ -582,9 +582,7 @@ class AccessibilitySourceService(
cancelNotification(notification.tag)
}
- /**
- * Remove notification when a package is uninstalled.
- */
+ /** Remove notification when a package is uninstalled. */
private fun removeAccessibilityNotification(pkg: String) {
val notification = getCurrentNotification() ?: return
val component = ComponentName.unflattenFromString(notification.tag)
@@ -594,9 +592,7 @@ class AccessibilitySourceService(
cancelNotification(notification.tag)
}
- /**
- * Remove notification for a component, when warning card is dismissed.
- */
+ /** Remove notification for a component, when warning card is dismissed. */
fun removeAccessibilityNotification(component: ComponentName) {
val notification = getCurrentNotification() ?: return
if (component.flattenToShortString() == notification.tag) {
@@ -612,17 +608,19 @@ class AccessibilitySourceService(
internal suspend fun removePackageState(pkg: String) {
sharedPrefsLock.withLock {
removeAccessibilityNotification(pkg)
- val notifiedServices = getNotifiedServices().mapNotNull {
- ComponentName.unflattenFromString(it)
- }
-
- val filteredServices = notifiedServices.filterNot { it.packageName == pkg }
- .map { it.flattenToShortString() }.toSet()
+ val notifiedServices =
+ getNotifiedServices().mapNotNull { ComponentName.unflattenFromString(it) }
+
+ val filteredServices =
+ notifiedServices
+ .filterNot { it.packageName == pkg }
+ .map { it.flattenToShortString() }
+ .toSet()
if (filteredServices.size < notifiedServices.size) {
- sharedPrefs.edit().putStringSet(
- KEY_ALREADY_NOTIFIED_SERVICES,
- filteredServices
- ).apply()
+ sharedPrefs
+ .edit()
+ .putStringSet(KEY_ALREADY_NOTIFIED_SERVICES, filteredServices)
+ .apply()
}
}
}
@@ -640,8 +638,8 @@ class AccessibilitySourceService(
"sc_accessibility_job_interval_millis"
private val DEFAULT_SC_ACCESSIBILITY_JOB_INTERVAL_MILLIS = TimeUnit.DAYS.toMillis(1)
- private val sourceStateChanged = SafetyEvent.Builder(
- SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
+ private val sourceStateChanged =
+ SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
/** lock for processing a job */
internal val lock = Mutex()
@@ -667,7 +665,6 @@ class AccessibilitySourceService(
/**
* Flexibility of the periodic check.
*
- *
* 10% of [.getPeriodicCheckIntervalMillis]
*
* @return The flexibility of the periodic check in milliseconds
@@ -679,7 +676,6 @@ class AccessibilitySourceService(
/**
* Minimum time in between showing two notifications.
*
- *
* This is just small enough so that the periodic check can always show a notification.
*
* @return The minimum time in milliseconds
@@ -716,8 +712,9 @@ class AccessibilityPackageResetHandler : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
- if (action != Intent.ACTION_PACKAGE_DATA_CLEARED &&
- action != Intent.ACTION_PACKAGE_FULLY_REMOVED
+ if (
+ action != Intent.ACTION_PACKAGE_DATA_CLEARED &&
+ action != Intent.ACTION_PACKAGE_FULLY_REMOVED
) {
return
}
@@ -732,9 +729,7 @@ class AccessibilityPackageResetHandler : BroadcastReceiver() {
if (DEBUG) {
Log.v(LOG_TAG, "package reset event occurred for ${data.schemeSpecificPart}")
}
- AccessibilitySourceService(context).run {
- removePackageState(data.schemeSpecificPart)
- }
+ AccessibilitySourceService(context).run { removePackageState(data.schemeSpecificPart) }
}
}
}
@@ -762,9 +757,7 @@ class AccessibilityNotificationDeleteHandler : BroadcastReceiver() {
}
}
-/**
- * Handler for Remove access action (warning cards) in safety center dashboard
- */
+/** Handler for Remove access action (warning cards) in safety center dashboard */
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
class AccessibilityRemoveAccessHandler : BroadcastReceiver() {
private val LOG_TAG = AccessibilityRemoveAccessHandler::class.java.simpleName
@@ -783,27 +776,27 @@ class AccessibilityRemoveAccessHandler : BroadcastReceiver() {
AccessibilitySourceService.lock.withLock {
val accessibilityService = AccessibilitySourceService(context)
var a11yEnabledServices = accessibilityService.getEnabledAccessibilityServices()
- val builder = try {
- AccessibilitySettingsUtil.disableAccessibilityService(context, a11yService)
- accessibilityService.removeFromNotifiedServices(a11yService)
- a11yEnabledServices = a11yEnabledServices.filter {
- it.id != a11yService.flattenToShortString()
+ val builder =
+ try {
+ AccessibilitySettingsUtil.disableAccessibilityService(context, a11yService)
+ accessibilityService.removeFromNotifiedServices(a11yService)
+ a11yEnabledServices =
+ a11yEnabledServices.filter {
+ it.id != a11yService.flattenToShortString()
+ }
+ SafetyEvent.Builder(
+ SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
+ )
+ } catch (ex: Exception) {
+ Log.w(LOG_TAG, "error occurred in disabling a11y service.", ex)
+ SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
}
- SafetyEvent.Builder(
- SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
- )
- } catch (ex: Exception) {
- Log.w(LOG_TAG, "error occurred in disabling a11y service.", ex)
- SafetyEvent.Builder(
- SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
- )
- }
- val safetySourceIssueId = intent.getStringExtra(
- EXTRA_SAFETY_SOURCE_ISSUE_ID
- )
- val safetyEvent = builder.setSafetySourceIssueId(safetySourceIssueId)
- .setSafetySourceIssueActionId(SC_ACCESSIBILITY_REMOVE_ACCESS_ACTION_ID)
- .build()
+ val safetySourceIssueId = intent.getStringExtra(EXTRA_SAFETY_SOURCE_ISSUE_ID)
+ val safetyEvent =
+ builder
+ .setSafetySourceIssueId(safetySourceIssueId)
+ .setSafetySourceIssueActionId(SC_ACCESSIBILITY_REMOVE_ACCESS_ACTION_ID)
+ .build()
accessibilityService.sendIssuesToSafetyCenter(a11yEnabledServices, safetyEvent)
}
if (DEBUG) {
@@ -820,9 +813,7 @@ class AccessibilityRemoveAccessHandler : BroadcastReceiver() {
}
}
-/**
- * Handler for accessibility warning cards dismissal in safety center dashboard
- */
+/** Handler for accessibility warning cards dismissal in safety center dashboard */
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
class AccessibilityWarningCardDismissalReceiver : BroadcastReceiver() {
private val LOG_TAG = AccessibilityWarningCardDismissalReceiver::class.java.simpleName
@@ -857,8 +848,8 @@ class AccessibilityWarningCardDismissalReceiver : BroadcastReceiver() {
}
/**
- * Schedules periodic job to send notifications for third part accessibility services,
- * the job also sends this data to Safety Center.
+ * Schedules periodic job to send notifications for third part accessibility services, the job also
+ * sends this data to Safety Center.
*/
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
class AccessibilityOnBootReceiver : BroadcastReceiver() {
@@ -876,15 +867,16 @@ class AccessibilityOnBootReceiver : BroadcastReceiver() {
val jobScheduler = getSystemServiceSafe(context, JobScheduler::class.java)
if (jobScheduler.getPendingJob(Constants.PERIODIC_ACCESSIBILITY_CHECK_JOB_ID) == null) {
- val jobInfo = JobInfo.Builder(
- Constants.PERIODIC_ACCESSIBILITY_CHECK_JOB_ID,
- ComponentName(context, AccessibilityJobService::class.java)
- )
- .setPeriodic(
- AccessibilitySourceService.getJobsIntervalMillis(),
- AccessibilitySourceService.getFlexJobsIntervalMillis()
- )
- .build()
+ val jobInfo =
+ JobInfo.Builder(
+ Constants.PERIODIC_ACCESSIBILITY_CHECK_JOB_ID,
+ ComponentName(context, AccessibilityJobService::class.java)
+ )
+ .setPeriodic(
+ AccessibilitySourceService.getJobsIntervalMillis(),
+ AccessibilitySourceService.getFlexJobsIntervalMillis()
+ )
+ .build()
val status = jobScheduler.schedule(jobInfo)
if (status != JobScheduler.RESULT_SUCCESS) {
@@ -901,8 +893,7 @@ class AccessibilityJobService : JobService() {
private var mSourceService: AccessibilitySourceService? = null
private val mLock = Object()
- @GuardedBy("mLock")
- private var mCurrentJob: Job? = null
+ @GuardedBy("mLock") private var mCurrentJob: Job? = null
override fun onCreate() {
super.onCreate()
@@ -917,24 +908,28 @@ class AccessibilityJobService : JobService() {
Log.v(LOG_TAG, "Accessibility privacy source job already running")
return false
}
- if (!isAccessibilitySourceEnabled() ||
- !isSafetyCenterEnabled(this@AccessibilityJobService)) {
+ if (
+ !isAccessibilitySourceEnabled() ||
+ !isSafetyCenterEnabled(this@AccessibilityJobService)
+ ) {
Log.v(LOG_TAG, "either privacy source or safety center is not enabled")
jobFinished(params, false)
mCurrentJob = null
return false
}
val coroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
- mCurrentJob = coroutineScope.launch(Dispatchers.Default) {
- mSourceService?.processAccessibilityJob(
- params,
- this@AccessibilityJobService,
- BooleanSupplier {
- val job = mCurrentJob
- return@BooleanSupplier job?.isCancelled ?: false
- }
- ) ?: jobFinished(params, false)
- }
+ mCurrentJob =
+ coroutineScope.launch(Dispatchers.Default) {
+ mSourceService?.processAccessibilityJob(
+ params,
+ this@AccessibilityJobService,
+ BooleanSupplier {
+ val job = mCurrentJob
+ return@BooleanSupplier job?.isCancelled ?: false
+ }
+ )
+ ?: jobFinished(params, false)
+ }
}
return true
}
@@ -942,20 +937,19 @@ class AccessibilityJobService : JobService() {
override fun onStopJob(params: JobParameters?): Boolean {
var job: Job?
synchronized(mLock) {
- job = if (mCurrentJob == null) {
- return false
- } else {
- mCurrentJob
- }
+ job =
+ if (mCurrentJob == null) {
+ return false
+ } else {
+ mCurrentJob
+ }
}
job?.cancel()
return false
}
fun clearJob() {
- synchronized(mLock) {
- mCurrentJob = null
- }
+ synchronized(mLock) { mCurrentJob = null }
}
}
@@ -971,8 +965,9 @@ class SafetyCenterAccessibilityListener(val context: Context) :
return
}
- if (!isAccessibilitySourceEnabled() || !isSafetyCenterEnabled(context) ||
- isProfile(context)) {
+ if (
+ !isAccessibilitySourceEnabled() || !isSafetyCenterEnabled(context) || isProfile(context)
+ ) {
Log.v(LOG_TAG, "accessibility event occurred, safety center feature not enabled.")
return
}
@@ -986,9 +981,13 @@ class SafetyCenterAccessibilityListener(val context: Context) :
val a11ySourceService = AccessibilitySourceService(context)
val a11yEnabledServices = a11ySourceService.getEnabledAccessibilityServices()
a11ySourceService.sendIssuesToSafetyCenter(a11yEnabledServices)
- val enabledComponents = a11yEnabledServices.map { a11yService ->
- ComponentName.unflattenFromString(a11yService.id)!!.flattenToShortString()
- }.toSet()
+ val enabledComponents =
+ a11yEnabledServices
+ .map { a11yService ->
+ ComponentName.unflattenFromString(a11yService.id)!!
+ .flattenToShortString()
+ }
+ .toSet()
a11ySourceService.removeAccessibilityNotification(enabledComponents)
a11ySourceService.updateServiceAsNotified(enabledComponents)
}
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/AutoRevokePrivacySource.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/AutoRevokePrivacySource.kt
index 0660955ff..93bb376ba 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/AutoRevokePrivacySource.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/AutoRevokePrivacySource.kt
@@ -25,9 +25,7 @@ import com.android.permissioncontroller.hibernation.cancelUnusedAppsNotification
import com.android.permissioncontroller.hibernation.rescanAndPushDataToSafetyCenter
import java.util.Random
-/**
- * Privacy source for auto-revoked permissions.
- */
+/** Privacy source for auto-revoked permissions. */
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
class AutoRevokePrivacySource : PrivacySource {
override val shouldProcessProfileRequest: Boolean = false
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/LocationAccessPrivacySource.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/LocationAccessPrivacySource.kt
index df35048e5..97d1f3ebf 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/LocationAccessPrivacySource.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/LocationAccessPrivacySource.kt
@@ -20,7 +20,6 @@ import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.annotation.RequiresApi
-
import com.android.permissioncontroller.permission.service.LocationAccessCheck
import com.android.permissioncontroller.privacysources.SafetyCenterReceiver.RefreshEvent
@@ -40,4 +39,4 @@ class LocationAccessPrivacySource : PrivacySource {
val safetyRefreshEvent = getSafetyCenterEvent(refreshEvent, intent)
LocationAccessCheck(context, null).rescanAndPushSafetyCenterData(safetyRefreshEvent, null)
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerCheck.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerCheck.kt
index 91a043a6a..4d5adfcc0 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerCheck.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerCheck.kt
@@ -109,7 +109,10 @@ private val DEFAULT_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS = DAYS.toMillis(
private fun isNotificationListenerCheckFlagEnabled(): Boolean {
// TODO: b/249789657 Set default to true after policy exemption + impact analysis
return DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PRIVACY, PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED, false)
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED,
+ false
+ )
}
/**
@@ -123,7 +126,8 @@ private fun getPeriodicCheckIntervalMillis(): Long {
return DeviceConfig.getLong(
DeviceConfig.NAMESPACE_PRIVACY,
PROPERTY_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS,
- DEFAULT_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS)
+ DEFAULT_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS
+ )
}
/**
@@ -178,8 +182,8 @@ private fun getSafetySourceIssueIdFromComponentName(componentName: ComponentName
* <p>We rate limit the number of notification we show and only ever show one notification at a
* time.
*
- * <p>As there are many cases why a notification should not been shown, we always schedule a {@link
- * #addNotificationListenerNotificationIfNeeded check} which then might add a notification.
+ * <p>As there are many cases why a notification should not been shown, we always schedule a
+ * {@link #addNotificationListenerNotificationIfNeeded check} which then might add a notification.
*
* @param context Used to resolve managers
* @param shouldCancel If supplied, can be used to interrupt long-running operations
@@ -199,10 +203,11 @@ internal class NotificationListenerCheckInternal(
@VisibleForTesting
val exemptPackagesDelegate = lazy {
getExemptedPackages(
- getSystemServiceSafe(parentUserContext, RoleManager::class.java), parentUserContext)
+ getSystemServiceSafe(parentUserContext, RoleManager::class.java),
+ parentUserContext
+ )
}
- @VisibleForTesting
- val exemptPackages: Set<String> by exemptPackagesDelegate
+ @VisibleForTesting val exemptPackages: Set<String> by exemptPackagesDelegate
companion object {
@VisibleForTesting const val NLS_PREFERENCE_FILE = "nls_preference"
@@ -231,7 +236,8 @@ internal class NotificationListenerCheckInternal(
SYSTEM_AUDIO_INTELLIGENCE,
SYSTEM_NOTIFICATION_INTELLIGENCE,
SYSTEM_TEXT_INTELLIGENCE,
- SYSTEM_VISUAL_INTELLIGENCE)
+ SYSTEM_VISUAL_INTELLIGENCE
+ )
/** Lock required for all public methods */
private val nlsLock = Mutex()
@@ -286,7 +292,8 @@ internal class NotificationListenerCheckInternal(
TAG,
"Found ${enabledComponents.size} enabled notification listeners. " +
"${notifiedComponents.size} already notified. ${unNotifiedComponents.size} " +
- "unnotified, sessionId = $sessionId")
+ "unnotified, sessionId = $sessionId"
+ )
}
throwInterruptedExceptionIfTaskIsCanceled()
@@ -318,7 +325,8 @@ internal class NotificationListenerCheckInternal(
TAG,
"enabledNotificationListeners=$enabledNotificationListeners\n" +
"enabledNotificationListenersExcludingExemptPackages=" +
- "$enabledNotificationListenersExcludingExemptPackages")
+ "$enabledNotificationListenersExcludingExemptPackages"
+ )
}
throwInterruptedExceptionIfTaskIsCanceled()
@@ -421,13 +429,16 @@ internal class NotificationListenerCheckInternal(
val componentsInternal = components.toMutableList()
// Don't show too many notification within certain timespan
- if (currentTimeMillis() - getLastNotificationShownTimeMillis() <
- getInBetweenNotificationsMillis()) {
+ if (
+ currentTimeMillis() - getLastNotificationShownTimeMillis() <
+ getInBetweenNotificationsMillis()
+ ) {
if (DEBUG) {
Log.v(
TAG,
"Notification not posted, within " +
- "$DEFAULT_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS ms")
+ "$DEFAULT_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS ms"
+ )
}
return
}
@@ -458,7 +469,8 @@ internal class NotificationListenerCheckInternal(
if (DEBUG) {
Log.v(
TAG,
- "Attempting to get PackageInfo for " + componentToNotifyFor.packageName)
+ "Attempting to get PackageInfo for " + componentToNotifyFor.packageName
+ )
}
pkgInfo =
Utils.getPackageInfoForComponentName(parentUserContext, componentToNotifyFor)
@@ -483,7 +495,8 @@ internal class NotificationListenerCheckInternal(
NotificationChannel(
Constants.PERMISSION_REMINDER_CHANNEL_ID,
parentUserContext.getString(R.string.permission_reminders),
- NotificationManager.IMPORTANCE_LOW)
+ NotificationManager.IMPORTANCE_LOW
+ )
val notificationManager =
getSystemServiceSafe(parentUserContext, NotificationManager::class.java)
@@ -503,8 +516,7 @@ internal class NotificationListenerCheckInternal(
pkg: PackageInfo,
sessionId: Long
) {
- val pkgLabel =
- Utils.getApplicationLabel(parentUserContext, pkg.applicationInfo)
+ val pkgLabel = Utils.getApplicationLabel(parentUserContext, pkg.applicationInfo)
val uid = pkg.applicationInfo.uid
val deletePendingIntent =
@@ -516,7 +528,9 @@ internal class NotificationListenerCheckInternal(
parentUserContext.getString(R.string.notification_listener_reminder_notification_title)
val text =
parentUserContext.getString(
- R.string.notification_listener_reminder_notification_content, pkgLabel)
+ R.string.notification_listener_reminder_notification_content,
+ pkgLabel
+ )
val (appLabel, smallIcon, color) =
KotlinUtils.getSafetyCenterNotificationResources(parentUserContext)
@@ -543,13 +557,17 @@ internal class NotificationListenerCheckInternal(
val notificationManager =
getSystemServiceSafe(parentUserContext, NotificationManager::class.java)
notificationManager.notify(
- componentName.flattenToString(), NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID, b.build())
+ componentName.flattenToString(),
+ NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID,
+ b.build()
+ )
if (DEBUG) {
Log.v(
TAG,
"Notification listener check notification shown with component=" +
- "${componentName.flattenToString()}, uid=$uid, sessionId=$sessionId")
+ "${componentName.flattenToString()}, uid=$uid, sessionId=$sessionId"
+ )
}
PermissionControllerStatsLog.write(
@@ -557,7 +575,8 @@ internal class NotificationListenerCheckInternal(
PRIVACY_SIGNAL_NOTIFICATION_INTERACTION__PRIVACY_SOURCE__NOTIFICATION_LISTENER,
uid,
PRIVACY_SIGNAL_NOTIFICATION_INTERACTION__ACTION__NOTIFICATION_SHOWN,
- sessionId)
+ sessionId
+ )
updateLastShownNotificationTime()
}
@@ -571,7 +590,8 @@ internal class NotificationListenerCheckInternal(
val intent =
Intent(
parentUserContext,
- NotificationListenerCheckNotificationDeleteHandler::class.java)
+ NotificationListenerCheckNotificationDeleteHandler::class.java
+ )
.apply {
putExtra(EXTRA_COMPONENT_NAME, componentName)
putExtra(Constants.EXTRA_SESSION_ID, sessionId)
@@ -580,7 +600,11 @@ internal class NotificationListenerCheckInternal(
identifier = componentName.flattenToString()
}
return PendingIntent.getBroadcast(
- context, 0, intent, FLAG_ONE_SHOT or FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
+ context,
+ 0,
+ intent,
+ FLAG_ONE_SHOT or FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
+ )
}
/** @return [PendingIntent] to safety center */
@@ -595,7 +619,8 @@ internal class NotificationListenerCheckInternal(
putExtra(EXTRA_SAFETY_SOURCE_ID, SC_NLS_SOURCE_ID)
putExtra(
EXTRA_SAFETY_SOURCE_ISSUE_ID,
- getSafetySourceIssueIdFromComponentName(componentName))
+ getSafetySourceIssueIdFromComponentName(componentName)
+ )
putExtra(EXTRA_COMPONENT_NAME, componentName)
putExtra(Constants.EXTRA_SESSION_ID, sessionId)
putExtra(Intent.EXTRA_UID, uid)
@@ -603,7 +628,11 @@ internal class NotificationListenerCheckInternal(
identifier = componentName.flattenToString()
}
return PendingIntent.getActivity(
- context, 0, intent, FLAG_ONE_SHOT or FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
+ context,
+ 0,
+ intent,
+ FLAG_ONE_SHOT or FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
+ )
}
/**
@@ -684,7 +713,7 @@ internal class NotificationListenerCheckInternal(
/**
* @param componentName enabled [NotificationListenerService]
* @return safety source issue, shown as the warning card in safety center. Null if unable to
- * create safety source issue
+ * create safety source issue
*/
@VisibleForTesting
fun createSafetySourceIssue(componentName: ComponentName, sessionId: Long): SafetySourceIssue? {
@@ -703,30 +732,45 @@ internal class NotificationListenerCheckInternal(
val disableNlsPendingIntent =
getDisableNlsPendingIntent(
- parentUserContext, safetySourceIssueId, componentName, uid, sessionId)
+ parentUserContext,
+ safetySourceIssueId,
+ componentName,
+ uid,
+ sessionId
+ )
val disableNlsAction =
SafetySourceIssue.Action.Builder(
SC_NLS_DISABLE_ACTION_ID,
parentUserContext.getString(
- R.string.notification_listener_remove_access_button_label),
- disableNlsPendingIntent)
+ R.string.notification_listener_remove_access_button_label
+ ),
+ disableNlsPendingIntent
+ )
.setWillResolve(true)
.setSuccessMessage(
parentUserContext.getString(
- R.string.notification_listener_remove_access_success_label))
+ R.string.notification_listener_remove_access_success_label
+ )
+ )
.build()
val notificationListenerDetailSettingsPendingIntent =
getNotificationListenerDetailSettingsPendingIntent(
- parentUserContext, componentName, uid, sessionId)
+ parentUserContext,
+ componentName,
+ uid,
+ sessionId
+ )
val showNotificationListenerSettingsAction =
SafetySourceIssue.Action.Builder(
SC_SHOW_NLS_SETTINGS_ACTION_ID,
parentUserContext.getString(
- R.string.notification_listener_review_app_button_label),
- notificationListenerDetailSettingsPendingIntent)
+ R.string.notification_listener_review_app_button_label
+ ),
+ notificationListenerDetailSettingsPendingIntent
+ )
.build()
val actionCardDismissPendingIntent =
@@ -742,7 +786,8 @@ internal class NotificationListenerCheckInternal(
title,
summary,
SafetySourceData.SEVERITY_LEVEL_INFORMATION,
- SC_NLS_ISSUE_TYPE_ID)
+ SC_NLS_ISSUE_TYPE_ID
+ )
.setSubtitle(pkgLabel)
.addAction(disableNlsAction)
.addAction(showNotificationListenerSettingsAction)
@@ -784,7 +829,9 @@ internal class NotificationListenerCheckInternal(
flags = FLAG_ACTIVITY_NEW_TASK
identifier = componentName.flattenToString()
putExtra(
- EXTRA_NOTIFICATION_LISTENER_COMPONENT_NAME, componentName.flattenToString())
+ EXTRA_NOTIFICATION_LISTENER_COMPONENT_NAME,
+ componentName.flattenToString()
+ )
putExtra(Constants.EXTRA_SESSION_ID, sessionId)
putExtra(Intent.EXTRA_UID, uid)
putExtra(Constants.EXTRA_IS_FROM_SLICE, true)
@@ -843,14 +890,14 @@ class NotificationListenerCheckJobService : JobService() {
val job = addNotificationListenerNotificationIfNeededJob
return@BooleanSupplier job?.isCancelled ?: false
}
- })
+ }
+ )
}
/**
* Starts an asynchronous check if a notification listener notification should be shown.
*
* @param params Not used other than for interacting with job scheduling
- *
* @return `false` if another check is already running, or if SDK Check fails (below T)
*/
override fun onStartJob(params: JobParameters): Boolean {
@@ -869,7 +916,9 @@ class NotificationListenerCheckJobService : JobService() {
GlobalScope.launch(Default) {
notificationListenerCheckInternal
?.getEnabledNotificationListenersAndNotifyIfNeeded(
- params, this@NotificationListenerCheckJobService)
+ params,
+ this@NotificationListenerCheckJobService
+ )
?: jobFinished(params, true)
}
}
@@ -880,7 +929,6 @@ class NotificationListenerCheckJobService : JobService() {
* Abort the check if still running.
*
* @param params ignored
- *
* @return false
*/
override fun onStopJob(params: JobParameters): Boolean {
@@ -922,13 +970,16 @@ class SetupPeriodicNotificationListenerCheck : BroadcastReceiver() {
val job =
JobInfo.Builder(
PERIODIC_NOTIFICATION_LISTENER_CHECK_JOB_ID,
- ComponentName(context, NotificationListenerCheckJobService::class.java))
+ ComponentName(context, NotificationListenerCheckJobService::class.java)
+ )
.setPeriodic(getPeriodicCheckIntervalMillis(), getFlexForPeriodicCheckMillis())
.build()
val scheduleResult = jobScheduler.schedule(job)
if (scheduleResult != JobScheduler.RESULT_SUCCESS) {
Log.e(
- TAG, "Could not schedule periodic notification listener check $scheduleResult")
+ TAG,
+ "Could not schedule periodic notification listener check $scheduleResult"
+ )
} else if (DEBUG) {
Log.i(TAG, "Scheduled periodic notification listener check")
}
@@ -957,14 +1008,16 @@ class NotificationListenerCheckNotificationDeleteHandler : BroadcastReceiver() {
Log.v(
TAG,
"Notification listener check notification declined with component=" +
- "${componentName.flattenToString()} , uid=$uid, sessionId=$sessionId")
+ "${componentName.flattenToString()} , uid=$uid, sessionId=$sessionId"
+ )
}
PermissionControllerStatsLog.write(
PRIVACY_SIGNAL_NOTIFICATION_INTERACTION,
PRIVACY_SIGNAL_NOTIFICATION_INTERACTION__PRIVACY_SOURCE__NOTIFICATION_LISTENER,
uid,
PRIVACY_SIGNAL_NOTIFICATION_INTERACTION__ACTION__DISMISSED,
- sessionId)
+ sessionId
+ )
}
}
@@ -984,7 +1037,8 @@ class DisableNotificationListenerComponentHandler : BroadcastReceiver() {
Log.v(
TAG,
"DisableComponentHandler: disabling $componentName," +
- "uid=$uid, sessionId=$sessionId")
+ "uid=$uid, sessionId=$sessionId"
+ )
}
val safetyEventBuilder =
@@ -993,7 +1047,10 @@ class DisableNotificationListenerComponentHandler : BroadcastReceiver() {
getSystemServiceSafe(context, NotificationManager::class.java)
disallowNlsLock.withLock {
notificationManager.setNotificationListenerAccessGranted(
- componentName, /* granted= */ false, /* userSet= */ true)
+ componentName,
+ /* granted= */ false,
+ /* userSet= */ true
+ )
}
SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED)
@@ -1019,7 +1076,8 @@ class DisableNotificationListenerComponentHandler : BroadcastReceiver() {
PRIVACY_SIGNAL_ISSUE_CARD_INTERACTION__PRIVACY_SOURCE__NOTIFICATION_LISTENER,
uid,
PRIVACY_SIGNAL_ISSUE_CARD_INTERACTION__ACTION__CLICKED_CTA1,
- sessionId)
+ sessionId
+ )
}
}
@@ -1044,7 +1102,8 @@ class NotificationListenerActionCardDismissalReceiver : BroadcastReceiver() {
Log.v(
TAG,
"ActionCardDismissalReceiver: $componentName dismissed," +
- "uid=$uid, sessionId=$sessionId")
+ "uid=$uid, sessionId=$sessionId"
+ )
}
NotificationListenerCheckInternal(context, null).run {
removeNotificationsForComponent(componentName)
@@ -1056,7 +1115,8 @@ class NotificationListenerActionCardDismissalReceiver : BroadcastReceiver() {
PRIVACY_SIGNAL_ISSUE_CARD_INTERACTION__PRIVACY_SOURCE__NOTIFICATION_LISTENER,
uid,
PRIVACY_SIGNAL_ISSUE_CARD_INTERACTION__ACTION__CARD_DISMISSED,
- sessionId)
+ sessionId
+ )
}
}
@@ -1068,8 +1128,10 @@ class NotificationListenerActionCardDismissalReceiver : BroadcastReceiver() {
class NotificationListenerPackageResetHandler : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
- if (action != Intent.ACTION_PACKAGE_DATA_CLEARED &&
- action != Intent.ACTION_PACKAGE_FULLY_REMOVED) {
+ if (
+ action != Intent.ACTION_PACKAGE_DATA_CLEARED &&
+ action != Intent.ACTION_PACKAGE_FULLY_REMOVED
+ ) {
return
}
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySourceData.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySourceData.kt
index f5903dfc2..4abd7129c 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySourceData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySourceData.kt
@@ -23,4 +23,4 @@ interface PrivacySourceData {
interface Creator<T> {
fun fromStorageData(data: String): T
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySourceStorageRepository.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySourceStorageRepository.kt
index 1eee90e31..621a7219d 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySourceStorageRepository.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySourceStorageRepository.kt
@@ -21,4 +21,4 @@ interface PrivacySourceStorageRepository {
fun persistData(dataList: List<PrivacySourceData>)
fun <T> readData(creator: PrivacySourceData.Creator<T>): List<T>
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/TextStorageRepository.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/TextStorageRepository.kt
index 8a8711bb6..a2e5b1376 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/TextStorageRepository.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/TextStorageRepository.kt
@@ -40,14 +40,16 @@ class TextStorageRepository(private val file: File) : PrivacySourceStorageReposi
override fun <T> readData(creator: PrivacySourceData.Creator<T>): List<T> {
try {
BufferedReader(FileReader(file)).useLines { lines ->
- return lines.mapNotNull {
- try {
- creator.fromStorageData(it)
- } catch (ex: Exception) {
- Log.e(LOG_TAG, "corrupted data : $it in file ${file.absolutePath}", ex)
- null
+ return lines
+ .mapNotNull {
+ try {
+ creator.fromStorageData(it)
+ } catch (ex: Exception) {
+ Log.e(LOG_TAG, "corrupted data : $it in file ${file.absolutePath}", ex)
+ null
+ }
}
- }.toList()
+ .toList()
}
} catch (ignored: FileNotFoundException) {
Log.e(LOG_TAG, "Could not find file ${file.absolutePath}")
@@ -66,4 +68,4 @@ class TextStorageRepository(private val file: File) : PrivacySourceStorageReposi
}
}
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/WorkPolicyInfo.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/WorkPolicyInfo.kt
index 2ab6d37f0..bf9f92398 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/WorkPolicyInfo.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/WorkPolicyInfo.kt
@@ -74,7 +74,10 @@ class WorkPolicyInfo(private val workPolicyUtils: WorkPolicyUtils) : PrivacySour
val safetySourceData: SafetySourceData? = createSafetySourceDataForWorkPolicy(context)
safetyCenterManager.setSafetySourceData(
- WORK_POLICY_INFO_SOURCE_ID, safetySourceData, safetyEvent)
+ WORK_POLICY_INFO_SOURCE_ID,
+ safetySourceData,
+ safetyEvent
+ )
}
private fun createSafetySourceDataForWorkPolicy(context: Context): SafetySourceData? {
@@ -84,16 +87,25 @@ class WorkPolicyInfo(private val workPolicyUtils: WorkPolicyUtils) : PrivacySour
when {
deviceOwnerIntent != null -> {
PendingIntent.getActivity(
- context, 0, deviceOwnerIntent, PendingIntent.FLAG_IMMUTABLE)
+ context,
+ 0,
+ deviceOwnerIntent,
+ PendingIntent.FLAG_IMMUTABLE
+ )
}
profileOwnerIntent != null -> {
val managedProfileContext =
context.createPackageContextAsUser(
context.packageName,
0,
- UserHandle.of(workPolicyUtils.managedProfileUserId))
+ UserHandle.of(workPolicyUtils.managedProfileUserId)
+ )
PendingIntent.getActivity(
- managedProfileContext, 0, profileOwnerIntent, PendingIntent.FLAG_IMMUTABLE)
+ managedProfileContext,
+ 0,
+ profileOwnerIntent,
+ PendingIntent.FLAG_IMMUTABLE
+ )
}
else -> null
}
@@ -102,10 +114,17 @@ class WorkPolicyInfo(private val workPolicyUtils: WorkPolicyUtils) : PrivacySour
val safetySourceStatus: SafetySourceStatus =
SafetySourceStatus.Builder(
Utils.getEnterpriseString(
- context, WORK_POLICY_TITLE, R.string.work_policy_title),
+ context,
+ WORK_POLICY_TITLE,
+ R.string.work_policy_title
+ ),
Utils.getEnterpriseString(
- context, WORK_POLICY_SUMMARY, R.string.work_policy_summary),
- SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED)
+ context,
+ WORK_POLICY_SUMMARY,
+ R.string.work_policy_summary
+ ),
+ SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
+ )
.setPendingIntent(pendingIntent)
.build()
@@ -120,7 +139,8 @@ class WorkPolicyInfo(private val workPolicyUtils: WorkPolicyUtils) : PrivacySour
RefreshEvent.EVENT_REFRESH_REQUESTED -> {
val refreshBroadcastId =
intent.getStringExtra(
- SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID)
+ SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
+ )
SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
.setRefreshBroadcastId(refreshBroadcastId)
.build()
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/v34/AppDataSharingUpdatesPrivacySource.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/v34/AppDataSharingUpdatesPrivacySource.kt
index 8bedc3979..ec86a49a4 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/v34/AppDataSharingUpdatesPrivacySource.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/v34/AppDataSharingUpdatesPrivacySource.kt
@@ -71,13 +71,16 @@ class AppDataSharingUpdatesPrivacySource : PrivacySource {
SafetySourceStatus.Builder(
context.getString(R.string.data_sharing_updates_title),
context.getString(R.string.data_sharing_updates_summary),
- SEVERITY_LEVEL_INFORMATION)
+ SEVERITY_LEVEL_INFORMATION
+ )
.setPendingIntent(
PendingIntent.getActivity(
context,
/* requestCode= */ 0,
Intent(ACTION_REVIEW_APP_DATA_SHARING_UPDATES),
- FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE))
+ FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
+ )
+ )
.build(),
)
.build()
@@ -88,7 +91,8 @@ class AppDataSharingUpdatesPrivacySource : PrivacySource {
safetyCenterManager.setSafetySourceData(
APP_DATA_SHARING_UPDATES_SOURCE_ID,
safetySourceData,
- createSafetyEventForDataSharingUpdates(refreshEvent, intent))
+ createSafetyEventForDataSharingUpdates(refreshEvent, intent)
+ )
}
private fun createSafetyEventForDataSharingUpdates(
@@ -99,7 +103,8 @@ class AppDataSharingUpdatesPrivacySource : PrivacySource {
EVENT_REFRESH_REQUESTED -> {
val refreshBroadcastId =
intent.getStringExtra(
- SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID)
+ SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
+ )
SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
.setRefreshBroadcastId(refreshBroadcastId)
.build()
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/CollapsableGroupCardHelper.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/CollapsableGroupCardHelper.kt
index cdc5cc1f3..20ac4c7a5 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/CollapsableGroupCardHelper.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/CollapsableGroupCardHelper.kt
@@ -27,7 +27,7 @@ internal class CollapsableGroupCardHelper {
private companion object {
private const val EXPANDED_ENTRY_GROUPS_SAVED_INSTANCE_STATE_KEY =
- "expanded_entry_groups_saved_instance_state_key"
+ "expanded_entry_groups_saved_instance_state_key"
}
fun restoreState(state: Bundle?) {
@@ -39,8 +39,8 @@ internal class CollapsableGroupCardHelper {
fun saveState(outState: Bundle) {
outState.putCharSequenceArray(
- EXPANDED_ENTRY_GROUPS_SAVED_INSTANCE_STATE_KEY,
- expandedGroups.toTypedArray()
+ EXPANDED_ENTRY_GROUPS_SAVED_INSTANCE_STATE_KEY,
+ expandedGroups.toTypedArray()
)
}
@@ -52,6 +52,5 @@ internal class CollapsableGroupCardHelper {
expandedGroups.add(groupId)
}
- fun isGroupExpanded(groupId: CharSequence): Boolean =
- expandedGroups.contains(groupId)
+ fun isGroupExpanded(groupId: CharSequence): Boolean = expandedGroups.contains(groupId)
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ComparablePreference.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ComparablePreference.kt
index 1950a0976..d5c7c3738 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ComparablePreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ComparablePreference.kt
@@ -17,14 +17,15 @@ package com.android.permissioncontroller.safetycenter.ui
import androidx.preference.Preference
-/** Allows comparison with a [Preference] to determine if it has been changed.
+/**
+ * Allows comparison with a [Preference] to determine if it has been changed.
*
* @see SafetyPreferenceComparisonCallback
*/
internal interface ComparablePreference {
- /** Returns true if given Preference represents an item of the same kind. */
+ /** Returns true if given Preference represents an item of the same kind. */
fun isSameItem(preference: Preference): Boolean
- /** Returns true if given Preference contains the same data. */
+ /** Returns true if given Preference contains the same data. */
fun hasSameContents(preference: Preference): Boolean
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ComparablePreferenceCategory.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ComparablePreferenceCategory.kt
index 55d27dbb3..7a9d164cf 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ComparablePreferenceCategory.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ComparablePreferenceCategory.kt
@@ -25,13 +25,13 @@ import androidx.preference.PreferenceCategory
import com.android.permissioncontroller.R
/** A {@link PreferenceCategory} that implements {@link ComparablePreference} interface. */
-internal class ComparablePreferenceCategory @JvmOverloads constructor(
+internal class ComparablePreferenceCategory
+@JvmOverloads
+constructor(
context: Context,
attrs: AttributeSet? = null,
- defStyleAttr: Int = getAttr(
- context,
- R.attr.preferenceCategoryStyle,
- android.R.attr.preferenceCategoryStyle),
+ defStyleAttr: Int =
+ getAttr(context, R.attr.preferenceCategoryStyle, android.R.attr.preferenceCategoryStyle),
defStyleRes: Int = 0
) : PreferenceCategory(context, attrs, defStyleAttr, defStyleRes), ComparablePreference {
@@ -47,8 +47,8 @@ internal class ComparablePreferenceCategory @JvmOverloads constructor(
}
override fun isSameItem(preference: Preference): Boolean =
- preference is ComparablePreferenceCategory && TextUtils.equals(key, preference.key)
+ preference is ComparablePreferenceCategory && TextUtils.equals(key, preference.key)
override fun hasSameContents(preference: Preference): Boolean =
- preference is ComparablePreferenceCategory && TextUtils.equals(title, preference.title)
+ preference is ComparablePreferenceCategory && TextUtils.equals(title, preference.title)
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EntriesTopPaddingPreference.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EntriesTopPaddingPreference.kt
new file mode 100644
index 000000000..077ccfa2d
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EntriesTopPaddingPreference.kt
@@ -0,0 +1,13 @@
+package com.android.permissioncontroller.safetycenter.ui
+
+import android.content.Context
+import android.util.AttributeSet
+import androidx.preference.Preference
+import com.android.permissioncontroller.R
+
+class EntriesTopPaddingPreference(context: Context, attrs: AttributeSet) :
+ Preference(context, attrs) {
+ init {
+ layoutResource = R.layout.preference_entries_top_padding
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EqualWidthContainer.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EqualWidthContainer.kt
index 6f56874eb..1bdc0dc39 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EqualWidthContainer.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EqualWidthContainer.kt
@@ -43,7 +43,8 @@ class EqualWidthContainer @JvmOverloads constructor(context: Context, attrs: Att
nonSpaceItems.forEach {
it.measure(
MeasureSpec.makeMeasureSpec(neededWidthPerNonSpaceItem, EXACTLY),
- MeasureSpec.makeMeasureSpec(it.measuredHeight, EXACTLY))
+ MeasureSpec.makeMeasureSpec(it.measuredHeight, EXACTLY)
+ )
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/InteractionLogger.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/InteractionLogger.kt
index 58bec87b8..51f550944 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/InteractionLogger.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/InteractionLogger.kt
@@ -43,10 +43,7 @@ import java.math.BigInteger
import java.security.MessageDigest
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
-class InteractionLogger
-private constructor(
- private val noLogSourceIds: Set<String?>
-) {
+class InteractionLogger private constructor(private val noLogSourceIds: Set<String?>) {
var sessionId: Long = Constants.INVALID_SESSION_ID
var viewType: ViewType = ViewType.UNKNOWN
var navigationSource: NavigationSource = NavigationSource.UNKNOWN
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/MoreIssuesCardAnimator.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/MoreIssuesCardAnimator.kt
index 55293f775..9121c76c2 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/MoreIssuesCardAnimator.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/MoreIssuesCardAnimator.kt
@@ -46,16 +46,19 @@ class MoreIssuesCardAnimator {
super.onAnimationEnd(drawable)
statusIcon.setImageResource(endSeverityLevelResId)
}
- })
+ }
+ )
setStatusIconDrawable.start()
}
}
fun cancelStatusAnimation(statusIcon: ImageView) {
val statusDrawable: Drawable? = statusIcon.drawable
- if (statusDrawable != null &&
- statusDrawable is AnimatedVectorDrawable &&
- statusDrawable.isRunning) {
+ if (
+ statusDrawable != null &&
+ statusDrawable is AnimatedVectorDrawable &&
+ statusDrawable.isRunning
+ ) {
statusDrawable.clearAnimationCallbacks()
statusDrawable.stop()
}
@@ -106,7 +109,10 @@ class MoreIssuesCardAnimator {
Log.e(
MoreIssuesCardPreference.TAG,
String.format(
- "Unexpected SafetyCenterIssue.IssueSeverityLevel: %d", endSeverityLevel))
+ "Unexpected SafetyCenterIssue.IssueSeverityLevel: %d",
+ endSeverityLevel
+ )
+ )
R.drawable.ic_safety_null_state
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ParsedSafetyCenterIntent.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ParsedSafetyCenterIntent.kt
index 6bf4b52e8..377c8d5f5 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ParsedSafetyCenterIntent.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/ParsedSafetyCenterIntent.kt
@@ -41,7 +41,10 @@ data class ParsedSafetyCenterIntent(
getParcelableExtra(EXTRA_SAFETY_SOURCE_USER_HANDLE, UserHandle::class.java)
val safetyCenterIssueKey: SafetyCenterIssueKey? =
createSafetyCenterIssueKey(
- safetySourceId, safetySourceIssueId, safetySourceUserHandle)
+ safetySourceId,
+ safetySourceIssueId,
+ safetySourceUserHandle
+ )
// Check if we've navigated from QS or if focusing on single issue and issues should be
// expanded
@@ -56,8 +59,8 @@ data class ParsedSafetyCenterIntent(
*
* @param safetySourceId source ID for a {@link SafetySourceIssue}
* @param safetySourceIssueId an issue ID for a {@link SafetySourceIssue}
- * @param safetySourceUserHandle the specific a {@link android.os.UserHandle} associated with
- * issue
+ * @param safetySourceUserHandle the specific a {@link android.os.UserHandle} associated
+ * with issue
*/
private fun createSafetyCenterIssueKey(
safetySourceId: String?,
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PositionInCardList.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PositionInCardList.kt
index 01e8f8d15..b1c48befd 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PositionInCardList.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PositionInCardList.kt
@@ -51,10 +51,12 @@ internal enum class PositionInCardList(val backgroundDrawableResId: Int) {
fun getTopMargin(context: Context): Int =
when (this) {
- CARD_START, CARD_START_END, CARD_START_LIST_END ->
- context.resources.getDimensionPixelSize(R.dimen.sc_card_margin)
- LIST_START, LIST_START_CARD_END, LIST_START_END ->
- context.resources.getDimensionPixelSize(R.dimen.sc_list_margin_top)
+ CARD_START,
+ CARD_START_END,
+ CARD_START_LIST_END -> context.resources.getDimensionPixelSize(R.dimen.sc_card_margin)
+ LIST_START,
+ LIST_START_CARD_END,
+ LIST_START_END -> context.resources.getDimensionPixelSize(R.dimen.sc_list_margin_top)
else -> 0
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PrivacySubpageFragment.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PrivacySubpageFragment.kt
index 54ba9560f..9fb17ce03 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PrivacySubpageFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PrivacySubpageFragment.kt
@@ -114,7 +114,8 @@ class PrivacySubpageFragment : SafetyCenterFragment() {
subpageIssues,
subpageDismissedIssues,
uiData.resolvedIssues,
- requireActivity().getTaskId())
+ requireActivity().getTaskId()
+ )
}
private fun updateSafetyCenterEntries(entryGroup: SafetyCenterEntryGroup) {
@@ -130,9 +131,13 @@ class PrivacySubpageFragment : SafetyCenterFragment() {
SafetySubpageEntryPreference(
requireContext(),
PendingIntentSender.getTaskIdForEntry(
- entryId, sameTaskSourceIds, requireActivity()),
+ entryId,
+ sameTaskSourceIds,
+ requireActivity()
+ ),
entry,
- safetyCenterViewModel)
+ safetyCenterViewModel
+ )
if (sourceId == "AndroidPrivacyControls") {
// No action required here because the privacy controls are rendered separately
@@ -149,7 +154,11 @@ class PrivacySubpageFragment : SafetyCenterFragment() {
fun setSwitchPreference(prefType: Pref) {
val switchPreference: ClickableDisabledSwitchPreference? = findPreference(prefType.key)
switchPreference?.setupState(
- prefStates[prefType], prefType, privacyControlsViewModel, this)
+ prefStates[prefType],
+ prefType,
+ privacyControlsViewModel,
+ this
+ )
}
setSwitchPreference(Pref.MIC)
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java
index 57462c20e..f6d653c99 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java
@@ -117,6 +117,7 @@ public final class SafetyCenterDashboardFragment extends SafetyCenterFragment {
mIssuesGroup = getPreferenceScreen().findPreference(ISSUES_GROUP_KEY);
mEntriesGroup = getPreferenceScreen().findPreference(ENTRIES_GROUP_KEY);
mStaticEntriesGroup = getPreferenceScreen().findPreference(STATIC_ENTRIES_GROUP_KEY);
+
if (mIsQuickSettingsFragment) {
getPreferenceScreen().removePreference(mEntriesGroup);
mEntriesGroup = null;
@@ -142,6 +143,7 @@ public final class SafetyCenterDashboardFragment extends SafetyCenterFragment {
}
return recyclerView;
}
+
// Set the default divider line between preferences to be transparent
@Override
public void setDivider(Drawable divider) {
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterTouchTarget.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterTouchTarget.kt
index 0e368291e..01d23241f 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterTouchTarget.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterTouchTarget.kt
@@ -28,6 +28,7 @@ import androidx.annotation.RequiresApi
object SafetyCenterTouchTarget {
/**
* Resizes the touch target of views by delegating to the parent component.
+ *
* @param view component that will be expanded
* @param minTouchTargetSizeResource required minimum touch target size
*/
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java
index 0b8706a38..ad19d9a22 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java
@@ -27,6 +27,7 @@ import android.os.Looper;
import android.safetycenter.SafetyCenterStatus;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
@@ -49,6 +50,8 @@ import java.util.Objects;
@RequiresApi(TIRAMISU)
public class SafetyStatusPreference extends Preference implements ComparablePreference {
+ private static final String TAG = "SafetyStatusPreference";
+
@Nullable private StatusUiData mStatus;
@Nullable private SafetyCenterViewModel mViewModel;
@@ -72,6 +75,7 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
+ Log.d(TAG, String.format("onBindViewHolder called for status %s", mStatus));
if (mStatus == null) {
return;
@@ -334,7 +338,12 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
}
void setData(StatusUiData statusUiData) {
+ if (Objects.equals(mStatus, statusUiData)) {
+ return;
+ }
+
mStatus = statusUiData;
+ Log.d(TAG, String.format("setData called for status %s", mStatus));
safeNotifyChanged();
}
@@ -349,7 +358,14 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
// Calling notifyChanged while recyclerview is scrolling or computing layout will result in an
// IllegalStateException. Post to handler to wait for UI to settle.
private void safeNotifyChanged() {
- new Handler(Looper.getMainLooper()).post(this::notifyChanged);
+ new Handler(Looper.getMainLooper())
+ .post(
+ () -> {
+ Log.d(
+ TAG,
+ String.format("Calling notifyChanged for status %s", mStatus));
+ notifyChanged();
+ });
}
@Override
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SpacerPreference.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SpacerPreference.kt
index bb09783be..a5356962a 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SpacerPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SpacerPreference.kt
@@ -62,21 +62,24 @@ internal class SpacerPreference(context: Context, attrs: AttributeSet) :
// we should ensure we won't add multiple listeners to the same view,
// and Preferences API does not allow to do cleanups when onViewRecycled,
// so we are keeping a track of the added listener attaching it as a tag to the View
- val listener: View.OnLayoutChangeListener = spacer.tag as? View.OnLayoutChangeListener
- ?: object : View.OnLayoutChangeListener {
- override fun onLayoutChange(
- v: View?,
- left: Int,
- top: Int,
- right: Int,
- bottom: Int,
- oldLeft: Int,
- oldTop: Int,
- oldRight: Int,
- oldBottom: Int
- ) {
- adjustHeight(spacer)
- }}.also { spacer.tag = it }
+ val listener: View.OnLayoutChangeListener =
+ spacer.tag as? View.OnLayoutChangeListener
+ ?: object : View.OnLayoutChangeListener {
+ override fun onLayoutChange(
+ v: View?,
+ left: Int,
+ top: Int,
+ right: Int,
+ bottom: Int,
+ oldLeft: Int,
+ oldTop: Int,
+ oldRight: Int,
+ oldBottom: Int
+ ) {
+ adjustHeight(spacer)
+ }
+ }
+ .also { spacer.tag = it }
spacer.removeOnLayoutChangeListener(listener)
spacer.addOnLayoutChangeListener(listener)
@@ -96,12 +99,13 @@ internal class SpacerPreference(context: Context, attrs: AttributeSet) :
// differently due to the auto-scroll to highlight a specific item,
// and in this case we need to wait the content parent to be measured
if (contentParent.height == 0) {
- val globalLayoutObserver = object : ViewTreeObserver.OnGlobalLayoutListener {
- override fun onGlobalLayout() {
- contentParent.viewTreeObserver.removeOnGlobalLayoutListener(this)
- adjustHeight(spacer)
+ val globalLayoutObserver =
+ object : ViewTreeObserver.OnGlobalLayoutListener {
+ override fun onGlobalLayout() {
+ contentParent.viewTreeObserver.removeOnGlobalLayoutListener(this)
+ adjustHeight(spacer)
+ }
}
- }
contentParent.viewTreeObserver.addOnGlobalLayoutListener(globalLayoutObserver)
return
}
@@ -110,13 +114,14 @@ internal class SpacerPreference(context: Context, attrs: AttributeSet) :
maxKnownToolbarHeight = max(maxKnownToolbarHeight, collapsingToolbar.height)
val contentHeight = spacer.top + maxKnownToolbarHeight
- val desiredSpacerHeight = if (contentHeight > contentParent.height) {
- // making it 0 height will remove if from recyclerview
- 1
- } else {
- // to unlock the scrolling we need spacer to go slightly beyond the screen
- contentParent.height - contentHeight + 1
- }
+ val desiredSpacerHeight =
+ if (contentHeight > contentParent.height) {
+ // making it 0 height will remove if from recyclerview
+ 1
+ } else {
+ // to unlock the scrolling we need spacer to go slightly beyond the screen
+ contentParent.height - contentHeight + 1
+ }
val layoutParams = spacer.layoutParams
if (layoutParams.height != desiredSpacerHeight) {
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StatusAnimationResolver.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StatusAnimationResolver.kt
index 55288564c..8409ca75d 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StatusAnimationResolver.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StatusAnimationResolver.kt
@@ -129,21 +129,24 @@ object StatusAnimationResolver {
@JvmStatic
fun getStatusChangeAnimation(fromSeverity: Int, toSeverity: Int): Int =
- if (fromSeverity == toSeverity &&
- fromSeverity != SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK) {
+ if (
+ fromSeverity == toSeverity &&
+ fromSeverity != SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK
+ ) {
0
- } else when (fromSeverity) {
- SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK ->
- R.drawable.safety_status_info_to_info_anim
- SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_RECOMMENDATION ->
- R.drawable.safety_status_recommend_to_info_anim
- SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING -> {
- if (toSeverity == SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK) {
- R.drawable.safety_status_warn_to_info_anim
- } else {
- R.drawable.safety_status_warn_to_recommend_anim
+ } else
+ when (fromSeverity) {
+ SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK ->
+ R.drawable.safety_status_info_to_info_anim
+ SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_RECOMMENDATION ->
+ R.drawable.safety_status_recommend_to_info_anim
+ SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING -> {
+ if (toSeverity == SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK) {
+ R.drawable.safety_status_warn_to_info_anim
+ } else {
+ R.drawable.safety_status_warn_to_recommend_anim
+ }
}
+ else -> 0
}
- else -> 0
- }
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/TextFadeAnimator.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/TextFadeAnimator.kt
index a98fcf2ad..656c3800a 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/TextFadeAnimator.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/TextFadeAnimator.kt
@@ -78,7 +78,8 @@ constructor(targetIds: List<Int>, changeDuration: Duration = DEFAULT_TEXT_CHANGE
super.onTransitionEnd(transition)
fadeTextIn(textChanges, parentViewGroup, onFinish)
}
- })
+ }
+ )
parentViewGroup.post {
TransitionManager.beginDelayedTransition(parentViewGroup, fadeOutTransition)
for ((textView, _) in textChanges) {
@@ -101,7 +102,8 @@ constructor(targetIds: List<Int>, changeDuration: Duration = DEFAULT_TEXT_CHANGE
super.onTransitionEnd(transition)
onFinish?.run()
}
- })
+ }
+ )
parent.post {
TransitionManager.beginDelayedTransition(parent, fadeInTransition)
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterQsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterQsViewModel.kt
index 73c7da99f..b1ac62874 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterQsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterQsViewModel.kt
@@ -83,7 +83,10 @@ class SafetyCenterQsViewModel(
val userHandle = UserHandle.getUserHandleForUid(permGroupUsage.uid)
val lightAppPermissionGroupUsageKey =
LightAppPermissionGroupUsageKey(
- packageName, permissionGroupName, userHandle)
+ packageName,
+ permissionGroupName,
+ userHandle
+ )
val appPermGroupLiveData: LightAppPermGroupLiveData =
LightAppPermGroupLiveData[
Triple(packageName, permissionGroupName, userHandle)]
@@ -110,7 +113,8 @@ class SafetyCenterQsViewModel(
LightAppPermissionGroupUsageKey(
usage.packageName,
usage.permissionGroupName,
- UserHandle.getUserHandleForUid(usage.uid))]
+ UserHandle.getUserHandleForUid(usage.uid)
+ )]
?: return false
return group.supportsRuntimePerms &&
!group.hasInstallToRuntimeSplit &&
@@ -125,7 +129,8 @@ class SafetyCenterQsViewModel(
LightAppPermissionGroupUsageKey(
usage.packageName,
usage.permissionGroupName,
- UserHandle.getUserHandleForUid(usage.uid))]
+ UserHandle.getUserHandleForUid(usage.uid)
+ )]
?: return
KotlinUtils.revokeForegroundRuntimePermissions(app, group)
@@ -177,13 +182,16 @@ class SafetyCenterQsViewModel(
getSensorState(
Sensors.CAMERA,
UserManager.DISALLOW_CAMERA_TOGGLE,
- configCameraToggleEnabled),
+ configCameraToggleEnabled
+ ),
MICROPHONE to
getSensorState(
Sensors.MICROPHONE,
UserManager.DISALLOW_MICROPHONE_TOGGLE,
- configMicToggleEnabled),
- LOCATION to SensorState(true, locationEnabled, locationEnforcedAdmin))
+ configMicToggleEnabled
+ ),
+ LOCATION to SensorState(true, locationEnabled, locationEnforcedAdmin)
+ )
}
@Suppress("OVERRIDE_DEPRECATION")
@@ -221,13 +229,14 @@ class SafetyCenterQsViewModel(
return SensorState(
sensorConfigEnabled && sensorPrivacyManager.supportsSensorToggle(sensor),
!sensorPrivacyManager.isSensorPrivacyEnabled(TOGGLE_TYPE_SOFTWARE, sensor),
- getEnforcedAdmin(restriction))
+ getEnforcedAdmin(restriction)
+ )
}
private fun getEnforcedAdmin(restriction: String) =
- if (userManager
- .getUserRestrictionSources(restriction, Process.myUserHandle())
- .isNotEmpty()) {
+ if (
+ userManager.getUserRestrictionSources(restriction, Process.myUserHandle()).isNotEmpty()
+ ) {
RestrictedLockUtils.getProfileOrDeviceOwner(app, Process.myUserHandle())
} else {
null
@@ -250,10 +259,12 @@ class SafetyCenterQsViewModel(
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val resolveInfo: ResolveInfo? =
context.packageManager.resolveActivity(intent, PackageManager.ResolveInfoFlags.of(0))
- if (resolveInfo != null &&
- resolveInfo.activityInfo != null &&
- resolveInfo.activityInfo.permission ==
- android.Manifest.permission.START_VIEW_PERMISSION_USAGE) {
+ if (
+ resolveInfo != null &&
+ resolveInfo.activityInfo != null &&
+ resolveInfo.activityInfo.permission ==
+ android.Manifest.permission.START_VIEW_PERMISSION_USAGE
+ ) {
intent.component = ComponentName(usage.packageName, resolveInfo.activityInfo.name)
return intent
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryGroupView.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryGroupView.kt
index 7e4223298..b00b7f765 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryGroupView.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryGroupView.kt
@@ -51,7 +51,6 @@ constructor(
) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
private companion object {
- val TAG = SafetyEntryGroupView::class.java.simpleName
const val EXPAND_COLLAPSE_ANIMATION_DURATION_MS = 183L
}
@@ -107,8 +106,15 @@ constructor(
val params = layoutParams as MarginLayoutParams
if (params.topMargin != topMargin) {
params.topMargin = topMargin
- layoutParams = params
}
+
+ if (isLastCard) {
+ params.bottomMargin = context.resources.getDimensionPixelSize(R.dimen.sc_spacing_large)
+ } else {
+ params.bottomMargin = 0
+ }
+
+ layoutParams = params
}
private fun showGroupDetails(group: SafetyCenterEntryGroup) {
diff --git a/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistory.kt b/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistory.kt
index 26f327e96..69e696695 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistory.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistory.kt
@@ -59,7 +59,8 @@ data class AppsSafetyLabelHistory(val appSafetyLabelHistories: List<AppSafetyLab
.toMutableList()
.apply { add(safetyLabel) }
.sortedBy { it.receivedAt }
- .takeLast(maxToPersist))
+ .takeLast(maxToPersist)
+ )
}
/** Data class representing the information about an app. */
@@ -90,7 +91,8 @@ data class AppsSafetyLabelHistory(val appSafetyLabelHistories: List<AppSafetyLab
SafetyLabel(
AppInfo(packageName),
receivedAt,
- DataLabel.extractLocationSharingDataLabel(appMetadataSafetyLabel.dataLabel))
+ DataLabel.extractLocationSharingDataLabel(appMetadataSafetyLabel.dataLabel)
+ )
}
}
@@ -113,7 +115,8 @@ data class AppsSafetyLabelHistory(val appSafetyLabelHistories: List<AppSafetyLab
.filter { it.key == DataCategoryConstants.CATEGORY_LOCATION }
.mapValues { categoryEntry ->
DataCategory.fromAppMetadataDataCategory(categoryEntry.value)
- })
+ }
+ )
}
}
@@ -134,7 +137,8 @@ data class AppsSafetyLabelHistory(val appSafetyLabelHistories: List<AppSafetyLab
DataCategory(
appMetadataDataCategory.dataTypes.values.any {
it.purposeSet.contains(PURPOSE_ADVERTISING)
- })
+ }
+ )
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistoryPersistence.kt b/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistoryPersistence.kt
index 9bb7e819f..ce6233fdf 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistoryPersistence.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistoryPersistence.kt
@@ -90,10 +90,14 @@ object AppsSafetyLabelHistoryPersistence {
Log.e(LOG_TAG, "File not found: $file")
} catch (e: IOException) {
Log.e(
- LOG_TAG, "Failed to read file: $file, encountered exception ${e.localizedMessage}")
+ LOG_TAG,
+ "Failed to read file: $file, encountered exception ${e.localizedMessage}"
+ )
} catch (e: XmlPullParserException) {
Log.e(
- LOG_TAG, "Failed to parse file: $file, encountered exception ${e.localizedMessage}")
+ LOG_TAG,
+ "Failed to parse file: $file, encountered exception ${e.localizedMessage}"
+ )
}
return AppsSafetyLabelHistoryFileContent(appsSafetyLabelHistory = null, INITIAL_VERSION)
@@ -133,13 +137,15 @@ object AppsSafetyLabelHistoryPersistence {
AppsSafetyLabelHistory(
currentHistories.toMutableList().apply {
add(AppSafetyLabelHistory(appInfo, listOf(safetyLabel)))
- })
+ }
+ )
} else {
AppsSafetyLabelHistory(
currentHistories.map {
if (it.appInfo != appInfo) it
else it.addSafetyLabelIfChanged(safetyLabel)
- })
+ }
+ )
}
write(file, updatedAppsSafetyLabelHistory)
@@ -231,7 +237,9 @@ object AppsSafetyLabelHistoryPersistence {
// to startTime. The aim is retain one safety label prior to start time to
// be used as the "before" safety label when determining updates.
AppSafetyLabelHistory(
- appHistory.appInfo, history.subList(last, history.size))
+ appHistory.appInfo,
+ history.subList(last, history.size)
+ )
}
}
@@ -265,7 +273,10 @@ object AppsSafetyLabelHistoryPersistence {
listeners.forEach { it.onSafetyLabelHistoryChanged() }
} catch (e: Exception) {
Log.i(
- LOG_TAG, "Failed to write to $file. Previous version of file will be restored.", e)
+ LOG_TAG,
+ "Failed to write to $file. Previous version of file will be restored.",
+ e
+ )
atomicFile.failWrite(outputStream)
} finally {
try {
@@ -284,10 +295,12 @@ object AppsSafetyLabelHistoryPersistence {
return currentAppsSafetyLabelHistory.appSafetyLabelHistories.mapNotNull {
val before = it.getSafetyLabelAt(startTime)
val after = it.getLatestSafetyLabel()
- if (before == null ||
- after == null ||
- before == after ||
- before.receivedAt.isAfter(after.receivedAt))
+ if (
+ before == null ||
+ after == null ||
+ before == after ||
+ before.receivedAt.isAfter(after.receivedAt)
+ )
null
else AppSafetyLabelDiff(before, after)
}
@@ -332,7 +345,8 @@ object AppsSafetyLabelHistoryPersistence {
else ->
throw IllegalArgumentException(
"Unexpected attribute ${getAttributeName(i)} in tag" +
- " $TAG_APPS_SAFETY_LABEL_HISTORY")
+ " $TAG_APPS_SAFETY_LABEL_HISTORY"
+ )
}
}
if (version == null) {
@@ -350,7 +364,9 @@ object AppsSafetyLabelHistoryPersistence {
next()
return AppsSafetyLabelHistoryFileContent(
- AppsSafetyLabelHistory(appSafetyLabelHistories), version)
+ AppsSafetyLabelHistory(appSafetyLabelHistories),
+ version
+ )
}
private fun XmlPullParser.parseAppSafetyLabelHistory(): AppSafetyLabelHistory {
@@ -379,7 +395,8 @@ object AppsSafetyLabelHistoryPersistence {
ATTRIBUTE_RECEIVED_AT -> receivedAt = parseInstant(getAttributeValue(i))
else ->
throw IllegalArgumentException(
- "Unexpected attribute ${getAttributeName(i)} in tag $TAG_SAFETY_LABEL")
+ "Unexpected attribute ${getAttributeName(i)} in tag $TAG_SAFETY_LABEL"
+ )
}
}
if (receivedAt == null) {
@@ -432,7 +449,8 @@ object AppsSafetyLabelHistoryPersistence {
ATTRIBUTE_CONTAINS_ADS -> hasAds = getAttributeValue(i).toBoolean()
else ->
throw IllegalArgumentException(
- "Unexpected attribute ${getAttributeName(i)} in tag $TAG_DATA_SHARED_ENTRY")
+ "Unexpected attribute ${getAttributeName(i)} in tag $TAG_DATA_SHARED_ENTRY"
+ )
}
}
if (category == null) {
@@ -440,7 +458,8 @@ object AppsSafetyLabelHistoryPersistence {
}
if (hasAds == null) {
throw IllegalArgumentException(
- "Missing $ATTRIBUTE_CONTAINS_ADS in $TAG_DATA_SHARED_ENTRY")
+ "Missing $ATTRIBUTE_CONTAINS_ADS in $TAG_DATA_SHARED_ENTRY"
+ )
}
nextTag()
@@ -458,7 +477,8 @@ object AppsSafetyLabelHistoryPersistence {
ATTRIBUTE_PACKAGE_NAME -> packageName = getAttributeValue(i)
else ->
throw IllegalArgumentException(
- "Unexpected attribute ${getAttributeName(i)} in tag $TAG_APP_INFO")
+ "Unexpected attribute ${getAttributeName(i)} in tag $TAG_APP_INFO"
+ )
}
}
if (packageName == null) {
@@ -540,7 +560,8 @@ object AppsSafetyLabelHistoryPersistence {
attribute(
null,
ATTRIBUTE_CONTAINS_ADS,
- dataSharedEntry.value.containsAdvertisingPurpose.toString())
+ dataSharedEntry.value.containsAdvertisingPurpose.toString()
+ )
endTag(null, TAG_DATA_SHARED_ENTRY)
}
@@ -592,7 +613,10 @@ object AppsSafetyLabelHistoryPersistence {
*/
private fun getMaxSafetyLabelsToPersist() =
DeviceConfig.getInt(
- DeviceConfig.NAMESPACE_PRIVACY, PROPERTY_MAX_SAFETY_LABELS_PERSISTED_PER_APP, 20)
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_MAX_SAFETY_LABELS_PERSISTED_PER_APP,
+ 20
+ )
/** An interface to listen to changes to persisted safety labels. */
interface ChangeListener {
diff --git a/PermissionController/src/com/android/permissioncontroller/safetylabel/SafetyLabelChangedBroadcastReceiver.kt b/PermissionController/src/com/android/permissioncontroller/safetylabel/SafetyLabelChangedBroadcastReceiver.kt
index 99f4adb02..0a7375642 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetylabel/SafetyLabelChangedBroadcastReceiver.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetylabel/SafetyLabelChangedBroadcastReceiver.kt
@@ -56,8 +56,10 @@ class SafetyLabelChangedBroadcastReceiver : BroadcastReceiver() {
}
val packageChangeEvent = getPackageChangeEvent(intent)
- if (!(packageChangeEvent == PackageChangeEvent.NEW_INSTALL ||
- packageChangeEvent == PackageChangeEvent.UPDATE)) {
+ if (
+ !(packageChangeEvent == PackageChangeEvent.NEW_INSTALL ||
+ packageChangeEvent == PackageChangeEvent.UPDATE)
+ ) {
return
}
@@ -74,7 +76,8 @@ class SafetyLabelChangedBroadcastReceiver : BroadcastReceiver() {
"received broadcast packageName: $packageName, current user: $currentUser," +
" packageChangeEvent: $packageChangeEvent, intent user:" +
" ${intent.getParcelableExtra(Intent.EXTRA_USER, UserHandle::class.java)
- ?: currentUser}")
+ ?: currentUser}"
+ )
}
val userManager = Utils.getSystemServiceSafe(context, UserManager::class.java)
if (userManager.isProfile) {
@@ -127,7 +130,8 @@ class SafetyLabelChangedBroadcastReceiver : BroadcastReceiver() {
Log.i(
TAG,
"writeSafetyLabel called for packageName: $packageName, currentUser:" +
- " ${Process.myUserHandle()}")
+ " ${Process.myUserHandle()}"
+ )
}
// Get the context for the user in which the app is installed.
@@ -155,7 +159,10 @@ class SafetyLabelChangedBroadcastReceiver : BroadcastReceiver() {
val safetyLabelForPersistence: SafetyLabelForPersistence =
AppsSafetyLabelHistory.SafetyLabel.extractLocationSharingSafetyLabel(
- packageName, Instant.ofEpochMilli(receivedAtMs), safetyLabel)
+ packageName,
+ Instant.ofEpochMilli(receivedAtMs),
+ safetyLabel
+ )
val historyFile = AppsSafetyLabelHistoryPersistence.getSafetyLabelHistoryFile(context)
AppsSafetyLabelHistoryPersistence.recordSafetyLabel(safetyLabelForPersistence, historyFile)
@@ -212,12 +219,14 @@ class SafetyLabelChangedBroadcastReceiver : BroadcastReceiver() {
Log.i(
TAG,
"Forwarding intent from current user: $currentUser to profile parent" +
- " $profileParent")
+ " $profileParent"
+ )
context.sendBroadcastAsUser(
Intent(intent)
.setAction(ACTION_PACKAGE_ADDED_PERMISSIONCONTROLLER_FORWARDED)
.putExtra(Intent.EXTRA_USER, currentUser),
- profileParent)
+ profileParent
+ )
}
/** Types of package change events. */
diff --git a/PermissionController/tests/inprocess/AppThatUsesCameraPermission/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt b/PermissionController/tests/inprocess/AppThatUsesCameraPermission/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt
index 2a4900ce4..58f0a8968 100644
--- a/PermissionController/tests/inprocess/AppThatUsesCameraPermission/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt
+++ b/PermissionController/tests/inprocess/AppThatUsesCameraPermission/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt
@@ -18,5 +18,4 @@ package com.android.permissioncontroller.tests.appthatrequestpermission
import android.app.Activity
-class DummyActivity : Activity() {
-} \ No newline at end of file
+class DummyActivity : Activity() {}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/GetPermissionGroupInfoTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/GetPermissionGroupInfoTest.kt
index 1dd13be2a..b20e99c38 100644
--- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/GetPermissionGroupInfoTest.kt
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/GetPermissionGroupInfoTest.kt
@@ -22,9 +22,9 @@ import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.google.common.truth.Truth.assertThat
-import org.junit.Test
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
+import org.junit.Test
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
class GetPermissionGroupInfoTest {
@@ -43,8 +43,8 @@ class GetPermissionGroupInfoTest {
latch.countDown()
}
latch.await(timeoutMs, TimeUnit.MILLISECONDS)
- assertThat(returnedPerms).isEqualTo(
- PermissionMapping.getPlatformPermissionNamesOfGroup(group))
+ assertThat(returnedPerms)
+ .isEqualTo(PermissionMapping.getPlatformPermissionNamesOfGroup(group))
}
}
@@ -61,8 +61,8 @@ class GetPermissionGroupInfoTest {
latch.countDown()
}
latch.await(timeoutMs, TimeUnit.MILLISECONDS)
- assertThat(permGroup).isEqualTo(
- PermissionMapping.getGroupOfPlatformPermission(permName))
+ assertThat(permGroup)
+ .isEqualTo(PermissionMapping.getGroupOfPlatformPermission(permName))
}
}
}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveDataTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveDataTest.kt
index 24ea039a1..01a3525c2 100644
--- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveDataTest.kt
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveDataTest.kt
@@ -29,7 +29,7 @@ import org.junit.Before
import org.junit.Test
private const val APK =
- "/data/local/tmp/permissioncontroller/tests/inprocess/AppThatUsesCameraPermission.apk"
+ "/data/local/tmp/permissioncontroller/tests/inprocess/AppThatUsesCameraPermission.apk"
private const val PKG = "com.android.permissioncontroller.tests.appthatrequestpermission"
class AttributionLabelLiveDataTest {
@@ -43,8 +43,8 @@ class AttributionLabelLiveDataTest {
@Test
fun getValidTag() {
AttributionLabelLiveData["testTag", PKG, myUserHandle()].withLoadedValue {
- assertThat(context.packageManager.getResourcesForApplication(PKG)
- .getString(it!!)).isEqualTo("Test Attribution Label")
+ assertThat(context.packageManager.getResourcesForApplication(PKG).getString(it!!))
+ .isEqualTo("Test Attribution Label")
}
}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/DataUtils.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/DataUtils.kt
index 519a7ef64..b34c151c3 100644
--- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/DataUtils.kt
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/DataUtils.kt
@@ -23,11 +23,12 @@ import java.util.concurrent.CompletableFuture
fun <T> SmartUpdateMediatorLiveData<T>.withLoadedValue(block: (T?) -> Unit) {
val v = CompletableFuture<T?>()
- val observer = Observer<T?> {
- if (isInitialized) {
- v.complete(it)
+ val observer =
+ Observer<T?> {
+ if (isInitialized) {
+ v.complete(it)
+ }
}
- }
Handler(Looper.getMainLooper()).post { observeForever(observer) }
try {
@@ -35,4 +36,4 @@ fun <T> SmartUpdateMediatorLiveData<T>.withLoadedValue(block: (T?) -> Unit) {
} finally {
Handler(Looper.getMainLooper()).post { removeObserver(observer) }
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt
index 305dcdfb7..708d4222f 100644
--- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt
@@ -23,8 +23,7 @@ import org.junit.Test
class ArrayUtilsTest {
@Test
fun appendString_appendToNull_returnsArrayWithString() {
- assertThat(ArrayUtils.appendString(null, TEST_STRING))
- .isEqualTo(arrayOf(TEST_STRING))
+ assertThat(ArrayUtils.appendString(null, TEST_STRING)).isEqualTo(arrayOf(TEST_STRING))
}
@Test
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt
index 8f54da579..37aa8d988 100644
--- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt
@@ -34,18 +34,16 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFailsWith
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mockito.argThat
import org.mockito.Mockito.mock
-import kotlin.test.assertFailsWith
import org.mockito.Mockito.`when` as whenever
-/**
- * Unit tests for [KotlinUtils].
- */
+/** Unit tests for [KotlinUtils]. */
@RunWith(AndroidJUnit4::class)
class KotlinUtilsTest {
private val targetContext = InstrumentationRegistry.getInstrumentation().targetContext
@@ -85,19 +83,25 @@ class KotlinUtilsTest {
whenever(mockContext.packageManager).thenReturn(mockPackageManager)
val installerIntent = Intent(ACTION_SHOW_APP_INFO).setPackage(installerPackage)
whenever(
- mockPackageManager.resolveActivity(
- argThat { intent -> intent.filterEquals(installerIntent) }, /* flags= */ anyInt()))
- .thenReturn(ResolveInfo().apply {
- activityInfo = ActivityInfo().apply {
- packageName = installerPackage
- name = installerActivity
+ mockPackageManager.resolveActivity(
+ argThat { intent -> intent.filterEquals(installerIntent) },
+ /* flags= */ anyInt()
+ )
+ )
+ .thenReturn(
+ ResolveInfo().apply {
+ activityInfo =
+ ActivityInfo().apply {
+ packageName = installerPackage
+ name = installerActivity
+ }
}
- })
+ )
val intent = KotlinUtils.getAppStoreIntent(mockContext, installerPackage, appPackage)
assertThat(intent).isNotNull()
- with (intent!!) {
+ with(intent!!) {
assertThat(action).isEqualTo(ACTION_SHOW_APP_INFO)
assertThat(component?.packageName).isEqualTo(installerPackage)
assertThat(component?.className).isEqualTo(installerActivity)
@@ -110,14 +114,16 @@ class KotlinUtilsTest {
val mockContext = mock(Context::class.java)
val mockPackageManager = mock(PackageManager::class.java)
whenever(mockContext.packageManager).thenReturn(mockPackageManager)
- whenever(
- mockPackageManager.resolveActivity(any(), /* flags= */ anyInt()))
- .thenReturn(ResolveInfo().apply {
- activityInfo = ActivityInfo().apply {
- packageName = ""
- name = ""
+ whenever(mockPackageManager.resolveActivity(any(), /* flags= */ anyInt()))
+ .thenReturn(
+ ResolveInfo().apply {
+ activityInfo =
+ ActivityInfo().apply {
+ packageName = ""
+ name = ""
+ }
}
- })
+ )
val intent = KotlinUtils.getAppStoreIntent(mockContext, "com.installer", appPackage)
@@ -149,7 +155,8 @@ class KotlinUtilsTest {
@Test
fun getMimeTypeForPermissions_bothReadMediaPermissions_returnsNull() {
assertThat(
- KotlinUtils.getMimeTypeForPermissions(listOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO)))
+ KotlinUtils.getMimeTypeForPermissions(listOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO))
+ )
.isNull()
}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt
index 64a13df60..4d942f815 100644
--- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt
@@ -29,31 +29,41 @@ import org.junit.runner.RunWith
class PermissionMappingTest {
@Test
fun testGetPlatformPermissionGroupForOp_healthPermissionGroup() {
- assertThat(PermissionMapping.getPlatformPermissionGroupForOp(
- AppOpsManager.OPSTR_READ_WRITE_HEALTH_DATA
- )).isEqualTo(HealthPermissions.HEALTH_PERMISSION_GROUP)
+ assertThat(
+ PermissionMapping.getPlatformPermissionGroupForOp(
+ AppOpsManager.OPSTR_READ_WRITE_HEALTH_DATA
+ )
+ )
+ .isEqualTo(HealthPermissions.HEALTH_PERMISSION_GROUP)
}
@Test
fun testGetPlatformPermissionGroupForOp_microphone() {
- assertThat(PermissionMapping.getPlatformPermissionGroupForOp(
- AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE
- )).isEqualTo(Manifest.permission_group.MICROPHONE)
+ assertThat(
+ PermissionMapping.getPlatformPermissionGroupForOp(
+ AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE
+ )
+ )
+ .isEqualTo(Manifest.permission_group.MICROPHONE)
}
@Test
fun testGetPlatformPermissionGroupForOp_camera() {
assertThat(
- PermissionMapping.getPlatformPermissionGroupForOp(AppOpsManager.OPSTR_PHONE_CALL_CAMERA)
- ).isEqualTo(Manifest.permission_group.CAMERA)
+ PermissionMapping.getPlatformPermissionGroupForOp(
+ AppOpsManager.OPSTR_PHONE_CALL_CAMERA
+ )
+ )
+ .isEqualTo(Manifest.permission_group.CAMERA)
}
@Test
fun testGetPlatformPermissionGroupForOp_readContacts() {
assertThat(
- PermissionMapping.getPlatformPermissionGroupForOp(AppOpsManager.OPSTR_READ_CONTACTS)
- ).isEqualTo(
- PermissionMapping.getGroupOfPlatformPermission(Manifest.permission.READ_CONTACTS)
- )
+ PermissionMapping.getPlatformPermissionGroupForOp(AppOpsManager.OPSTR_READ_CONTACTS)
+ )
+ .isEqualTo(
+ PermissionMapping.getGroupOfPlatformPermission(Manifest.permission.READ_CONTACTS)
+ )
}
}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt
index 15218024e..11bcca356 100644
--- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt
@@ -45,9 +45,9 @@ import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.utils.Utils
import com.android.permissioncontroller.privacysources.WorkPolicyInfo
import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFailsWith
import org.junit.Ignore
import org.junit.Test
-import kotlin.test.assertFailsWith
class UtilsTest {
private val context = InstrumentationRegistry.getInstrumentation().targetContext as Context
@@ -110,8 +110,14 @@ class UtilsTest {
@Test
@Ignore("b/277782895")
fun getEnterpriseString() {
- assertThat(Utils.getEnterpriseString(context, WorkPolicyInfo.WORK_POLICY_TITLE,
- R.string.work_policy_title)).isInstanceOf(String::class.java)
+ assertThat(
+ Utils.getEnterpriseString(
+ context,
+ WorkPolicyInfo.WORK_POLICY_TITLE,
+ R.string.work_policy_title
+ )
+ )
+ .isInstanceOf(String::class.java)
}
@Test
@@ -148,12 +154,26 @@ class UtilsTest {
@Test
fun getPermissionGroupDescriptionString_validPermissionGroup() {
- val permissionGroupNames = listOf(ACTIVITY_RECOGNITION, CALENDAR, CALL_LOG,
- CAMERA, CONTACTS, LOCATION, MICROPHONE, NEARBY_DEVICES, PHONE, READ_MEDIA_AURAL,
- READ_MEDIA_VISUAL, SENSORS, SMS, STORAGE)
+ val permissionGroupNames =
+ listOf(
+ ACTIVITY_RECOGNITION,
+ CALENDAR,
+ CALL_LOG,
+ CAMERA,
+ CONTACTS,
+ LOCATION,
+ MICROPHONE,
+ NEARBY_DEVICES,
+ PHONE,
+ READ_MEDIA_AURAL,
+ READ_MEDIA_VISUAL,
+ SENSORS,
+ SMS,
+ STORAGE
+ )
for (permissionGroupName in permissionGroupNames) {
assertThat(Utils.getPermissionGroupDescriptionString(context, permissionGroupName, ""))
- .isNotNull()
+ .isNotNull()
}
}
@@ -167,8 +187,12 @@ class UtilsTest {
@Test
fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsToday() {
- val result = Utils.getPermissionLastAccessSummaryTimestamp(System.currentTimeMillis(),
- context, LOCATION)
+ val result =
+ Utils.getPermissionLastAccessSummaryTimestamp(
+ System.currentTimeMillis(),
+ context,
+ LOCATION
+ )
assertThat(result.first).isNotEmpty()
assertThat(result.second).isEqualTo(Utils.LAST_24H_SENSOR_TODAY)
assertThat(result.third).isNotEmpty()
@@ -176,8 +200,12 @@ class UtilsTest {
@Test
fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsYesterday() {
- val result = Utils.getPermissionLastAccessSummaryTimestamp(
- System.currentTimeMillis() - 24 * 60 * 60 * 1000, context, LOCATION)
+ val result =
+ Utils.getPermissionLastAccessSummaryTimestamp(
+ System.currentTimeMillis() - 24 * 60 * 60 * 1000,
+ context,
+ LOCATION
+ )
assertThat(result.first).isNotEmpty()
assertThat(result.second).isEqualTo(Utils.LAST_24H_SENSOR_YESTERDAY)
assertThat(result.third).isNotEmpty()
@@ -185,8 +213,12 @@ class UtilsTest {
@Test
fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsLast7Days() {
- val result = Utils.getPermissionLastAccessSummaryTimestamp(
- System.currentTimeMillis() - 5 * 24 * 60 * 60 * 1000, context, LOCATION)
+ val result =
+ Utils.getPermissionLastAccessSummaryTimestamp(
+ System.currentTimeMillis() - 5 * 24 * 60 * 60 * 1000,
+ context,
+ LOCATION
+ )
assertThat(result.first).isNotEmpty()
assertThat(result.second).isEqualTo(Utils.LAST_7D_SENSOR)
assertThat(result.third).isNotEmpty()
@@ -194,8 +226,12 @@ class UtilsTest {
@Test
fun getPermissionLastAccessSummaryTimestamp_nonSensorDataPermission_lastAccessSummaryTimestampIsLast24Hrs() {
- val result = Utils.getPermissionLastAccessSummaryTimestamp(
- System.currentTimeMillis(), context, STORAGE)
+ val result =
+ Utils.getPermissionLastAccessSummaryTimestamp(
+ System.currentTimeMillis(),
+ context,
+ STORAGE
+ )
assertThat(result.first).isNotEmpty()
assertThat(result.second).isEqualTo(Utils.LAST_24H_CONTENT_PROVIDER)
assertThat(result.third).isNotEmpty()
@@ -203,8 +239,12 @@ class UtilsTest {
@Test
fun getPermissionLastAccessSummaryTimestamp_nonSensorDataPermission_lastAccessSummaryTimestampIs7Days() {
- val result = Utils.getPermissionLastAccessSummaryTimestamp(
- System.currentTimeMillis() - 5 * 60 * 60 * 24 * 1000, context, STORAGE)
+ val result =
+ Utils.getPermissionLastAccessSummaryTimestamp(
+ System.currentTimeMillis() - 5 * 60 * 60 * 24 * 1000,
+ context,
+ STORAGE
+ )
assertThat(result.first).isNotEmpty()
assertThat(result.second).isEqualTo(Utils.LAST_7D_CONTENT_PROVIDER)
assertThat(result.third).isNotEmpty()
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/hibernation/HibernationControllerTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/hibernation/HibernationControllerTest.kt
index e4cc110f0..c09b2e53c 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/hibernation/HibernationControllerTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/hibernation/HibernationControllerTest.kt
@@ -49,9 +49,7 @@ import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-/**
- * Unit tests for [HibernationController].
- */
+/** Unit tests for [HibernationController]. */
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
class HibernationControllerTest {
@@ -68,12 +66,9 @@ class HibernationControllerTest {
private var mockitoSession: MockitoSession? = null
- @Mock
- lateinit var context: Context
- @Mock
- lateinit var appHibernationManager: AppHibernationManager
- @Mock
- lateinit var usageStatsManager: UsageStatsManager
+ @Mock lateinit var context: Context
+ @Mock lateinit var appHibernationManager: AppHibernationManager
+ @Mock lateinit var usageStatsManager: UsageStatsManager
lateinit var filesDir: File
@@ -82,8 +77,11 @@ class HibernationControllerTest {
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- mockitoSession = mockitoSession().mockStatic(PermissionControllerApplication::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
whenever(PermissionControllerApplication.get()).thenReturn(application)
filesDir = InstrumentationRegistry.getInstrumentation().getTargetContext().getCacheDir()
whenever(application.filesDir).thenReturn(filesDir)
@@ -92,8 +90,8 @@ class HibernationControllerTest {
doReturn(appHibernationManager).`when`(context).getSystemService(APP_HIBERNATION_SERVICE)
doReturn(usageStatsManager).`when`(context).getSystemService(USAGE_STATS_SERVICE)
- hibernationController = HibernationController(
- context, TEST_UNUSED_THRESHOLD, true /* targetsPreS */)
+ hibernationController =
+ HibernationController(context, TEST_UNUSED_THRESHOLD, true /* targetsPreS */)
}
@After
@@ -123,8 +121,8 @@ class HibernationControllerTest {
// GIVEN an app that is globally unused (i.e. unused at a package level)
val userPackages = listOf(makePackageInfo(PACKAGE_NAME_1), makePackageInfo(PACKAGE_NAME_2))
val map = mapOf(UserHandle.of(USER_ID) to userPackages)
- whenever(usageStatsManager.getLastTimeAnyComponentUsed(PACKAGE_NAME_1)).thenReturn(
- System.currentTimeMillis() - (TEST_UNUSED_THRESHOLD + TEST_MOCK_DELAY))
+ whenever(usageStatsManager.getLastTimeAnyComponentUsed(PACKAGE_NAME_1))
+ .thenReturn(System.currentTimeMillis() - (TEST_UNUSED_THRESHOLD + TEST_MOCK_DELAY))
// WHEN the controller hibernates the apps
hibernationController.hibernateApps(map)
@@ -138,8 +136,8 @@ class HibernationControllerTest {
// GIVEN an app that has been used globally (i.e. used at a package level)
val userPackages = listOf(makePackageInfo(PACKAGE_NAME_1), makePackageInfo(PACKAGE_NAME_2))
val map = mapOf(UserHandle.of(USER_ID) to userPackages)
- whenever(usageStatsManager.getLastTimeAnyComponentUsed(PACKAGE_NAME_1)).thenReturn(
- System.currentTimeMillis() - (TEST_UNUSED_THRESHOLD - TEST_MOCK_DELAY))
+ whenever(usageStatsManager.getLastTimeAnyComponentUsed(PACKAGE_NAME_1))
+ .thenReturn(System.currentTimeMillis() - (TEST_UNUSED_THRESHOLD - TEST_MOCK_DELAY))
// WHEN the controller hibernates the apps
hibernationController.hibernateApps(map)
@@ -162,6 +160,7 @@ class HibernationControllerTest {
0 /* firstInstallTime */,
0 /* lastUpdateTime */,
false /* areAttributionsUserVisible */,
- emptyMap() /* attributionTagsToLabels */)
+ emptyMap() /* attributionTagsToLabels */
+ )
}
}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/hibernation/HibernationPolicyTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/hibernation/HibernationPolicyTest.kt
index fadd35f82..d85cb40b0 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/hibernation/HibernationPolicyTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/hibernation/HibernationPolicyTest.kt
@@ -53,9 +53,7 @@ import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-/**
- * Unit tests for [HibernationPolicy].
- */
+/** Unit tests for [HibernationPolicy]. */
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
class HibernationPolicyTest {
@@ -77,10 +75,12 @@ class HibernationPolicyTest {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(DeviceConfig::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(DeviceConfig::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
`when`(PermissionControllerApplication.get()).thenReturn(application)
realContext = ApplicationProvider.getApplicationContext()
@@ -109,12 +109,14 @@ class HibernationPolicyTest {
fun onReceive_shouldInitializeAndAdjustStartTimeOfUnusedAppTracking() {
receiver.onReceive(context, Intent(Intent.ACTION_BOOT_COMPLETED))
val startTimeOfUnusedAppTracking =
- sharedPreferences.getLong(PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING,
- SNAPSHOT_UNINITIALIZED)
+ sharedPreferences.getLong(
+ PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING,
+ SNAPSHOT_UNINITIALIZED
+ )
val systemTimeSnapshot =
- sharedPreferences.getLong(PREF_KEY_BOOT_TIME_SNAPSHOT, SNAPSHOT_UNINITIALIZED)
- val realtimeSnapshot = sharedPreferences.getLong(PREF_KEY_ELAPSED_REALTIME_SNAPSHOT,
- SNAPSHOT_UNINITIALIZED)
+ sharedPreferences.getLong(PREF_KEY_BOOT_TIME_SNAPSHOT, SNAPSHOT_UNINITIALIZED)
+ val realtimeSnapshot =
+ sharedPreferences.getLong(PREF_KEY_ELAPSED_REALTIME_SNAPSHOT, SNAPSHOT_UNINITIALIZED)
val currentTimeMillis = System.currentTimeMillis()
val currentRealTime = SystemClock.elapsedRealtime()
assertThat(startTimeOfUnusedAppTracking).isNotEqualTo(SNAPSHOT_UNINITIALIZED)
@@ -134,30 +136,28 @@ class HibernationPolicyTest {
@Test
fun getStartTimeOfUnusedAppTracking_shouldReturnExpectedValue() {
assertThat(getStartTimeOfUnusedAppTracking(sharedPreferences))
- .isNotEqualTo(SNAPSHOT_UNINITIALIZED)
+ .isNotEqualTo(SNAPSHOT_UNINITIALIZED)
receiver.onReceive(context, Intent(Intent.ACTION_BOOT_COMPLETED))
- val systemTimeSnapshot = sharedPreferences.getLong(PREF_KEY_BOOT_TIME_SNAPSHOT,
- SNAPSHOT_UNINITIALIZED)
+ val systemTimeSnapshot =
+ sharedPreferences.getLong(PREF_KEY_BOOT_TIME_SNAPSHOT, SNAPSHOT_UNINITIALIZED)
sharedPreferences
- .edit()
- .putLong(PREF_KEY_BOOT_TIME_SNAPSHOT, systemTimeSnapshot - ONE_DAY_MS)
- .apply()
+ .edit()
+ .putLong(PREF_KEY_BOOT_TIME_SNAPSHOT, systemTimeSnapshot - ONE_DAY_MS)
+ .apply()
assertThat(getStartTimeOfUnusedAppTracking(sharedPreferences))
- .isNotEqualTo(systemTimeSnapshot)
+ .isNotEqualTo(systemTimeSnapshot)
}
- private fun assertAdjustedTime(
- systemTimeSnapshot: Long,
- realtimeSnapshot: Long
- ) {
+ private fun assertAdjustedTime(systemTimeSnapshot: Long, realtimeSnapshot: Long) {
val newStartTimeOfUnusedAppTracking =
- sharedPreferences.getLong(PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING,
- SNAPSHOT_UNINITIALIZED)
+ sharedPreferences.getLong(
+ PREF_KEY_START_TIME_OF_UNUSED_APP_TRACKING,
+ SNAPSHOT_UNINITIALIZED
+ )
val newSystemTimeSnapshot =
- sharedPreferences.getLong(PREF_KEY_BOOT_TIME_SNAPSHOT, SNAPSHOT_UNINITIALIZED)
+ sharedPreferences.getLong(PREF_KEY_BOOT_TIME_SNAPSHOT, SNAPSHOT_UNINITIALIZED)
val newRealtimeSnapshot =
- sharedPreferences.getLong(PREF_KEY_ELAPSED_REALTIME_SNAPSHOT,
- SNAPSHOT_UNINITIALIZED)
+ sharedPreferences.getLong(PREF_KEY_ELAPSED_REALTIME_SNAPSHOT, SNAPSHOT_UNINITIALIZED)
assertThat(newStartTimeOfUnusedAppTracking).isNotEqualTo(SNAPSHOT_UNINITIALIZED)
assertThat(newSystemTimeSnapshot).isNotEqualTo(SNAPSHOT_UNINITIALIZED)
assertThat(newSystemTimeSnapshot).isGreaterThan(systemTimeSnapshot)
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/data/FakeEventStorage.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/data/FakeEventStorage.kt
index de43bd2d5..057af89d1 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/data/FakeEventStorage.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/data/FakeEventStorage.kt
@@ -19,9 +19,7 @@ package com.android.permissioncontroller.tests.mocking.permission.data
import com.android.permissioncontroller.permission.data.PermissionEvent
import com.android.permissioncontroller.permission.service.PermissionEventStorage
-/**
- * Fake event storage class used for tests
- */
+/** Fake event storage class used for tests */
class FakeEventStorage<T : PermissionEvent> : PermissionEventStorage<T> {
val events: MutableList<T> = mutableListOf()
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/data/v33/RecentPermissionDecisionsLiveDataTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/data/v33/RecentPermissionDecisionsLiveDataTest.kt
index 43d599871..b6d63ecb0 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/data/v33/RecentPermissionDecisionsLiveDataTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/data/v33/RecentPermissionDecisionsLiveDataTest.kt
@@ -28,19 +28,17 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@RunWith(AndroidJUnit4::class)
class RecentPermissionDecisionsLiveDataTest {
- @Mock
- lateinit var job: Job
+ @Mock lateinit var job: Job
- @Mock
- lateinit var recentDecision: PermissionDecision
+ @Mock lateinit var recentDecision: PermissionDecision
private val recentPermissionDecisionStorage = FakeEventStorage<PermissionDecision>()
@@ -49,11 +47,9 @@ class RecentPermissionDecisionsLiveDataTest {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- runBlocking {
- recentPermissionDecisionStorage.storeEvent(recentDecision)
- }
- recentPermissionDecisionsLiveData = spy(RecentPermissionDecisionsLiveData(
- recentPermissionDecisionStorage))
+ runBlocking { recentPermissionDecisionStorage.storeEvent(recentDecision) }
+ recentPermissionDecisionsLiveData =
+ spy(RecentPermissionDecisionsLiveData(recentPermissionDecisionStorage))
}
@Test
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/BasePermissionEventStorageTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/BasePermissionEventStorageTest.kt
index 41a60101d..534342144 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/BasePermissionEventStorageTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/BasePermissionEventStorageTest.kt
@@ -27,6 +27,11 @@ import com.android.permissioncontroller.Constants
import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.permission.service.BasePermissionEventStorage
import com.google.common.truth.Truth.assertThat
+import java.io.File
+import java.io.InputStream
+import java.io.OutputStream
+import java.util.Date
+import java.util.concurrent.TimeUnit
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Before
@@ -34,16 +39,11 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.any
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-import java.io.File
-import java.io.InputStream
-import java.io.OutputStream
-import java.util.Date
-import java.util.concurrent.TimeUnit
@RunWith(AndroidJUnit4::class)
class BasePermissionEventStorageTest {
@@ -66,11 +66,9 @@ class BasePermissionEventStorageTest {
private val parkingEvent = TestPermissionEvent("package.test.parking", jan22020)
private val podcastEvent = TestPermissionEvent("package.test.podcast", jan22020)
- @Mock
- lateinit var jobScheduler: JobScheduler
+ @Mock lateinit var jobScheduler: JobScheduler
- @Mock
- lateinit var existingJob: JobInfo
+ @Mock lateinit var existingJob: JobInfo
private lateinit var context: Context
private lateinit var storage: BasePermissionEventStorage<TestPermissionEvent>
@@ -80,10 +78,12 @@ class BasePermissionEventStorageTest {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(DeviceConfig::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(DeviceConfig::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
`when`(PermissionControllerApplication.get()).thenReturn(application)
context = ApplicationProvider.getApplicationContext()
filesDir = context.cacheDir
@@ -107,9 +107,7 @@ class BasePermissionEventStorageTest {
@Test
fun loadEvents_noData_returnsEmptyList() {
init()
- runBlocking {
- assertThat(storage.loadEvents()).isEmpty()
- }
+ runBlocking { assertThat(storage.loadEvents()).isEmpty() }
}
@Test
@@ -130,8 +128,7 @@ class BasePermissionEventStorageTest {
storage.storeEvent(parkingEvent)
storage.storeEvent(podcastEvent)
assertThat(storage.loadEvents())
- .containsExactly(musicEvent, mapEvent, parkingEvent,
- podcastEvent)
+ .containsExactly(musicEvent, mapEvent, parkingEvent, podcastEvent)
}
}
@@ -181,10 +178,10 @@ class BasePermissionEventStorageTest {
fun removeOldData_removesOnlyOldData() {
init()
val todayEvent = parkingEvent.copy(eventTime = System.currentTimeMillis())
- val sixDaysAgoEvent = podcastEvent.copy(
- eventTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(6))
- val eightDaysAgoEvent = parkingEvent.copy(
- eventTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(8))
+ val sixDaysAgoEvent =
+ podcastEvent.copy(eventTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(6))
+ val eightDaysAgoEvent =
+ parkingEvent.copy(eventTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(8))
runBlocking {
storage.storeEvent(eightDaysAgoEvent)
storage.storeEvent(sixDaysAgoEvent)
@@ -202,11 +199,10 @@ class BasePermissionEventStorageTest {
storage.storeEvent(musicEvent)
storage.updateEventsBySystemTimeDelta(TimeUnit.DAYS.toMillis(1))
- assertThat(storage.loadEvents()).containsExactly(
- musicEvent.copy(
- eventTime = musicEvent.eventTime + TimeUnit.DAYS.toMillis(1)
+ assertThat(storage.loadEvents())
+ .containsExactly(
+ musicEvent.copy(eventTime = musicEvent.eventTime + TimeUnit.DAYS.toMillis(1))
)
- )
}
}
@@ -217,18 +213,15 @@ class BasePermissionEventStorageTest {
storage.storeEvent(musicEvent)
storage.updateEventsBySystemTimeDelta(-TimeUnit.DAYS.toMillis(1))
- assertThat(storage.loadEvents()).containsExactly(
- musicEvent.copy(
- eventTime = musicEvent.eventTime - TimeUnit.DAYS.toMillis(1)
+ assertThat(storage.loadEvents())
+ .containsExactly(
+ musicEvent.copy(eventTime = musicEvent.eventTime - TimeUnit.DAYS.toMillis(1))
)
- )
}
}
- private class TestPermissionEventStorage(
- context: Context,
- jobScheduler: JobScheduler
- ) : BasePermissionEventStorage<TestPermissionEvent>(context, jobScheduler) {
+ private class TestPermissionEventStorage(context: Context, jobScheduler: JobScheduler) :
+ BasePermissionEventStorage<TestPermissionEvent>(context, jobScheduler) {
lateinit var fakeDiskStore: List<TestPermissionEvent>
override fun serialize(stream: OutputStream, events: List<TestPermissionEvent>) {
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionChangeStorageImplTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionChangeStorageImplTest.kt
index 761fff18b..21855c124 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionChangeStorageImplTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionChangeStorageImplTest.kt
@@ -28,6 +28,10 @@ import com.android.permissioncontroller.permission.data.PermissionChange
import com.android.permissioncontroller.permission.service.PermissionChangeStorageImpl
import com.android.permissioncontroller.permission.utils.Utils
import com.google.common.truth.Truth.assertThat
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.io.File
+import java.util.Date
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Before
@@ -39,10 +43,6 @@ import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-import java.io.ByteArrayInputStream
-import java.io.ByteArrayOutputStream
-import java.io.File
-import java.util.Date
@RunWith(AndroidJUnit4::class)
class PermissionChangeStorageImplTest {
@@ -57,8 +57,7 @@ class PermissionChangeStorageImplTest {
private val mapChange = PermissionChange(MAP_PACKAGE_NAME, jan12020)
- @Mock
- lateinit var jobScheduler: JobScheduler
+ @Mock lateinit var jobScheduler: JobScheduler
private lateinit var context: Context
private lateinit var storage: PermissionChangeStorageImpl
@@ -68,10 +67,12 @@ class PermissionChangeStorageImplTest {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(DeviceConfig::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(DeviceConfig::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
Mockito.`when`(PermissionControllerApplication.get()).thenReturn(application)
context = ApplicationProvider.getApplicationContext()
filesDir = context.cacheDir
@@ -101,8 +102,7 @@ class PermissionChangeStorageImplTest {
@Test
fun serialize_roundsTimeDownToDate() {
- val laterInTheDayGrant = mapChange.copy(
- eventTime = (mapChange.eventTime + FIVE_HOURS_MS))
+ val laterInTheDayGrant = mapChange.copy(eventTime = (mapChange.eventTime + FIVE_HOURS_MS))
val outStream = ByteArrayOutputStream()
storage.serialize(outStream, listOf(laterInTheDayGrant))
@@ -113,9 +113,12 @@ class PermissionChangeStorageImplTest {
@Test
fun serialize_exactTimeDataCanBeParsed() {
Mockito.`when`(
- DeviceConfig.getBoolean(ArgumentMatchers.eq(DeviceConfig.NAMESPACE_PERMISSIONS),
- ArgumentMatchers.eq(Utils.PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME),
- ArgumentMatchers.anyBoolean()))
+ DeviceConfig.getBoolean(
+ ArgumentMatchers.eq(DeviceConfig.NAMESPACE_PERMISSIONS),
+ ArgumentMatchers.eq(Utils.PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME),
+ ArgumentMatchers.anyBoolean()
+ )
+ )
.thenReturn(true)
val outStream = ByteArrayOutputStream()
@@ -131,9 +134,12 @@ class PermissionChangeStorageImplTest {
storage.serialize(outStream, listOf(mapChange))
Mockito.`when`(
- DeviceConfig.getBoolean(ArgumentMatchers.eq(DeviceConfig.NAMESPACE_PERMISSIONS),
- ArgumentMatchers.eq(Utils.PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME),
- ArgumentMatchers.anyBoolean()))
+ DeviceConfig.getBoolean(
+ ArgumentMatchers.eq(DeviceConfig.NAMESPACE_PERMISSIONS),
+ ArgumentMatchers.eq(Utils.PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME),
+ ArgumentMatchers.anyBoolean()
+ )
+ )
.thenReturn(true)
val inStream = ByteArrayInputStream(outStream.toByteArray())
@@ -143,20 +149,25 @@ class PermissionChangeStorageImplTest {
@Test
fun serialize_afterStoresExactTimeChangedToFalse_roundsTimeDownToDate() {
Mockito.`when`(
- DeviceConfig.getBoolean(ArgumentMatchers.eq(DeviceConfig.NAMESPACE_PERMISSIONS),
- ArgumentMatchers.eq(Utils.PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME),
- ArgumentMatchers.anyBoolean()))
+ DeviceConfig.getBoolean(
+ ArgumentMatchers.eq(DeviceConfig.NAMESPACE_PERMISSIONS),
+ ArgumentMatchers.eq(Utils.PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME),
+ ArgumentMatchers.anyBoolean()
+ )
+ )
.thenReturn(true)
- val laterInTheDayEvent = mapChange.copy(
- eventTime = (mapChange.eventTime + FIVE_HOURS_MS))
+ val laterInTheDayEvent = mapChange.copy(eventTime = (mapChange.eventTime + FIVE_HOURS_MS))
val outStream = ByteArrayOutputStream()
storage.serialize(outStream, listOf(laterInTheDayEvent))
Mockito.`when`(
- DeviceConfig.getBoolean(ArgumentMatchers.eq(DeviceConfig.NAMESPACE_PERMISSIONS),
- ArgumentMatchers.eq(Utils.PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME),
- ArgumentMatchers.anyBoolean()))
+ DeviceConfig.getBoolean(
+ ArgumentMatchers.eq(DeviceConfig.NAMESPACE_PERMISSIONS),
+ ArgumentMatchers.eq(Utils.PROPERTY_PERMISSION_CHANGES_STORE_EXACT_TIME),
+ ArgumentMatchers.anyBoolean()
+ )
+ )
.thenReturn(false)
val inStream = ByteArrayInputStream(outStream.toByteArray())
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionEventCleanupJobServiceTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionEventCleanupJobServiceTest.kt
index b60fea123..2f95d467d 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionEventCleanupJobServiceTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionEventCleanupJobServiceTest.kt
@@ -28,6 +28,7 @@ import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.permission.service.PermissionEventCleanupJobService
import com.android.permissioncontroller.permission.service.PermissionEventCleanupJobService.Companion.DEFAULT_CLEAR_OLD_EVENTS_CHECK_FREQUENCY
import com.android.permissioncontroller.permission.utils.Utils
+import java.io.File
import org.junit.After
import org.junit.Before
import org.junit.Test
@@ -38,7 +39,6 @@ import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-import java.io.File
@RunWith(AndroidJUnit4::class)
class PermissionEventCleanupJobServiceTest {
@@ -47,10 +47,8 @@ class PermissionEventCleanupJobServiceTest {
val application = Mockito.mock(PermissionControllerApplication::class.java)
}
- @Mock
- lateinit var jobScheduler: JobScheduler
- @Mock
- lateinit var existingJob: JobInfo
+ @Mock lateinit var jobScheduler: JobScheduler
+ @Mock lateinit var existingJob: JobInfo
private lateinit var context: Context
private lateinit var mockitoSession: MockitoSession
@@ -59,19 +57,24 @@ class PermissionEventCleanupJobServiceTest {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(DeviceConfig::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(DeviceConfig::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
Mockito.`when`(PermissionControllerApplication.get()).thenReturn(application)
context = ApplicationProvider.getApplicationContext()
filesDir = context.cacheDir
Mockito.`when`(application.filesDir).thenReturn(filesDir)
Mockito.`when`(jobScheduler.schedule(Mockito.any())).thenReturn(JobScheduler.RESULT_SUCCESS)
Mockito.`when`(
- DeviceConfig.getLong(eq(DeviceConfig.NAMESPACE_PERMISSIONS),
- eq(Utils.PROPERTY_PERMISSION_EVENTS_CHECK_OLD_FREQUENCY_MILLIS),
- eq(DEFAULT_CLEAR_OLD_EVENTS_CHECK_FREQUENCY)))
+ DeviceConfig.getLong(
+ eq(DeviceConfig.NAMESPACE_PERMISSIONS),
+ eq(Utils.PROPERTY_PERMISSION_EVENTS_CHECK_OLD_FREQUENCY_MILLIS),
+ eq(DEFAULT_CLEAR_OLD_EVENTS_CHECK_FREQUENCY)
+ )
+ )
.thenReturn(DEFAULT_CLEAR_OLD_EVENTS_CHECK_FREQUENCY)
}
@@ -93,8 +96,8 @@ class PermissionEventCleanupJobServiceTest {
@Test
fun init_existingJob_doesNotScheduleNewJob() {
- Mockito.`when`(existingJob.intervalMillis).thenReturn(
- DEFAULT_CLEAR_OLD_EVENTS_CHECK_FREQUENCY)
+ Mockito.`when`(existingJob.intervalMillis)
+ .thenReturn(DEFAULT_CLEAR_OLD_EVENTS_CHECK_FREQUENCY)
Mockito.`when`(jobScheduler.getPendingJob(Constants.OLD_PERMISSION_EVENT_CLEANUP_JOB_ID))
.thenReturn(existingJob)
PermissionEventCleanupJobService.scheduleOldDataCleanupIfNecessary(context, jobScheduler)
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionStorageTimeChangeReceiverTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionStorageTimeChangeReceiverTest.kt
index cf5d92fe3..2ae4b0585 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionStorageTimeChangeReceiverTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PermissionStorageTimeChangeReceiverTest.kt
@@ -34,6 +34,8 @@ import com.android.permissioncontroller.permission.service.PermissionStorageTime
import com.android.permissioncontroller.permission.service.PermissionStorageTimeChangeReceiver.Companion.PREF_KEY_SYSTEM_TIME_SNAPSHOT
import com.android.permissioncontroller.permission.service.PermissionStorageTimeChangeReceiver.Companion.SNAPSHOT_UNINITIALIZED
import com.android.permissioncontroller.permission.utils.TimeSource
+import java.io.File
+import java.util.concurrent.TimeUnit
import org.junit.After
import org.junit.Before
import org.junit.Test
@@ -43,17 +45,15 @@ import org.mockito.ArgumentMatchers.anyLong
import org.mockito.ArgumentMatchers.anyString
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-import java.io.File
-import java.util.concurrent.TimeUnit
@RunWith(AndroidJUnit4::class)
class PermissionStorageTimeChangeReceiverTest {
@@ -62,20 +62,15 @@ class PermissionStorageTimeChangeReceiverTest {
val application = mock(PermissionControllerApplication::class.java)
}
- @Mock
- lateinit var context: Context
+ @Mock lateinit var context: Context
- @Mock
- lateinit var sharedPreferences: SharedPreferences
+ @Mock lateinit var sharedPreferences: SharedPreferences
- @Mock
- lateinit var editor: SharedPreferences.Editor
+ @Mock lateinit var editor: SharedPreferences.Editor
- @Mock
- lateinit var packageManager: PackageManager
+ @Mock lateinit var packageManager: PackageManager
- @Mock
- lateinit var permissionEventStorage: PermissionEventStorage<out PermissionEvent>
+ @Mock lateinit var permissionEventStorage: PermissionEventStorage<out PermissionEvent>
private val fakeTimeSource = FakeTimeSource()
private lateinit var mockitoSession: MockitoSession
@@ -85,25 +80,27 @@ class PermissionStorageTimeChangeReceiverTest {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(DeviceConfig::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(DeviceConfig::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
`when`(PermissionControllerApplication.get()).thenReturn(application)
`when`(context.getSharedPreferences(anyString(), anyInt())).thenReturn(sharedPreferences)
`when`(sharedPreferences.edit()).thenReturn(editor)
val context: Context = ApplicationProvider.getApplicationContext()
filesDir = context.cacheDir
`when`(application.filesDir).thenReturn(filesDir)
- `when`(DeviceConfig.getProperty(eq(DeviceConfig.NAMESPACE_PERMISSIONS),
- anyString())).thenReturn(null)
+ `when`(DeviceConfig.getProperty(eq(DeviceConfig.NAMESPACE_PERMISSIONS), anyString()))
+ .thenReturn(null)
`when`(sharedPreferences.getLong(eq(PREF_KEY_SYSTEM_TIME_SNAPSHOT), anyLong()))
.thenReturn(SNAPSHOT_UNINITIALIZED)
`when`(sharedPreferences.getLong(eq(PREF_KEY_ELAPSED_REALTIME_SNAPSHOT), anyLong()))
.thenReturn(SNAPSHOT_UNINITIALIZED)
- receiver = spy(PermissionStorageTimeChangeReceiver(listOf(permissionEventStorage),
- fakeTimeSource))
+ receiver =
+ spy(PermissionStorageTimeChangeReceiver(listOf(permissionEventStorage), fakeTimeSource))
}
@After
@@ -123,8 +120,8 @@ class PermissionStorageTimeChangeReceiverTest {
@Test
fun onReceive_timeSetReceived_beforeBootCompleted_doesNothing() {
- fakeTimeSource.currentTimeMillis = fakeTimeSource.currentTimeMillis +
- TimeUnit.DAYS.toMillis(2)
+ fakeTimeSource.currentTimeMillis =
+ fakeTimeSource.currentTimeMillis + TimeUnit.DAYS.toMillis(2)
receiver.onReceive(context, Intent(Intent.ACTION_TIME_CHANGED))
verify(receiver, never()).onTimeChanged(anyLong())
@@ -143,8 +140,8 @@ class PermissionStorageTimeChangeReceiverTest {
fun onReceive_timeDiffBelowMinimum_doesNothing() {
mockBootCompletedSnapshot()
- fakeTimeSource.currentTimeMillis = fakeTimeSource.currentTimeMillis -
- TimeUnit.SECONDS.toMillis(30)
+ fakeTimeSource.currentTimeMillis =
+ fakeTimeSource.currentTimeMillis - TimeUnit.SECONDS.toMillis(30)
receiver.onReceive(context, Intent(Intent.ACTION_TIME_CHANGED))
verify(receiver, never()).onTimeChanged(anyLong())
@@ -155,10 +152,9 @@ class PermissionStorageTimeChangeReceiverTest {
mockBootCompletedSnapshot()
// in 3 days the time is set to one day from now (effectively set back by 2 days)
- fakeTimeSource.currentTimeMillis = fakeTimeSource.currentTimeMillis +
- TimeUnit.DAYS.toMillis(1)
- fakeTimeSource.elapsedRealtime = fakeTimeSource.elapsedRealtime +
- TimeUnit.DAYS.toMillis(3)
+ fakeTimeSource.currentTimeMillis =
+ fakeTimeSource.currentTimeMillis + TimeUnit.DAYS.toMillis(1)
+ fakeTimeSource.elapsedRealtime = fakeTimeSource.elapsedRealtime + TimeUnit.DAYS.toMillis(3)
receiver.onReceive(context, Intent(Intent.ACTION_TIME_CHANGED))
verify(receiver).onTimeChanged(-TimeUnit.DAYS.toMillis(2))
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PersistedStoragePackageUninstalledReceiverTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PersistedStoragePackageUninstalledReceiverTest.kt
index 2cefaab67..baa848960 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PersistedStoragePackageUninstalledReceiverTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/PersistedStoragePackageUninstalledReceiverTest.kt
@@ -29,6 +29,8 @@ import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.permission.service.PersistedStoragePackageUninstalledReceiver
import com.android.permissioncontroller.tests.mocking.permission.data.FakeEventStorage
import com.google.common.truth.Truth.assertThat
+import java.io.File
+import java.util.Date
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import org.junit.After
@@ -37,14 +39,12 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.spy
import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-import java.io.File
-import java.util.Date
@RunWith(AndroidJUnit4::class)
class PersistedStoragePackageUninstalledReceiverTest {
@@ -55,14 +55,11 @@ class PersistedStoragePackageUninstalledReceiverTest {
private val musicEvent = TestPermissionEvent("package.test.music", Date(2020, 0, 1).time)
- @Mock
- lateinit var context: Context
+ @Mock lateinit var context: Context
- @Mock
- lateinit var packageManager: PackageManager
+ @Mock lateinit var packageManager: PackageManager
- @Mock
- lateinit var jobScheduler: JobScheduler
+ @Mock lateinit var jobScheduler: JobScheduler
private lateinit var mockitoSession: MockitoSession
private lateinit var filesDir: File
@@ -72,17 +69,24 @@ class PersistedStoragePackageUninstalledReceiverTest {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(PermissionControllerApplication::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
`when`(PermissionControllerApplication.get()).thenReturn(application)
val context: Context = ApplicationProvider.getApplicationContext()
filesDir = context.cacheDir
`when`(application.filesDir).thenReturn(filesDir)
permissionEventStorage = spy(FakeEventStorage())
- receiver = spy(PersistedStoragePackageUninstalledReceiver(
- listOf(permissionEventStorage), Dispatchers.Main.immediate))
+ receiver =
+ spy(
+ PersistedStoragePackageUninstalledReceiver(
+ listOf(permissionEventStorage),
+ Dispatchers.Main.immediate
+ )
+ )
}
@After
@@ -112,8 +116,6 @@ class PersistedStoragePackageUninstalledReceiverTest {
receiver.onReceive(context, intent)
- runBlocking {
- assertThat(permissionEventStorage.loadEvents().isEmpty())
- }
+ runBlocking { assertThat(permissionEventStorage.loadEvents().isEmpty()) }
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/RuntimePermissionsUpgradeControllerTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/RuntimePermissionsUpgradeControllerTest.kt
index 86aab9b60..d4522241b 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/RuntimePermissionsUpgradeControllerTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/RuntimePermissionsUpgradeControllerTest.kt
@@ -83,8 +83,7 @@ class RuntimePermissionsUpgradeControllerTest {
init {
whenever(application.applicationContext).thenReturn(application)
- whenever(application.createContextAsUser(any(), anyInt())).thenReturn(
- application)
+ whenever(application.createContextAsUser(any(), anyInt())).thenReturn(application)
whenever(application.registerComponentCallbacks(any())).thenAnswer {
val dataRepository = it.arguments[0] as ComponentCallbacks2
@@ -95,34 +94,31 @@ class RuntimePermissionsUpgradeControllerTest {
}
/** Latest permission database version known in this test */
- private val LATEST_VERSION = if (SdkLevel.isAtLeastT()) {
- 10
- } else {
- 9
- }
+ private val LATEST_VERSION =
+ if (SdkLevel.isAtLeastT()) {
+ 10
+ } else {
+ 9
+ }
/** Use a unique test package name for each test */
private val TEST_PKG_NAME: String
- get() = Thread.currentThread().stackTrace
- .filter { it.className == this::class.java.name }[1].methodName
+ get() =
+ Thread.currentThread()
+ .stackTrace
+ .filter { it.className == this::class.java.name }[1]
+ .methodName
/** Mockito session of this test */
private var mockitoSession: MockitoSession? = null
- @Mock
- lateinit var packageManager: PackageManager
- @Mock
- lateinit var permissionManager: PermissionManager
- @Mock
- lateinit var activityManager: ActivityManager
- @Mock
- lateinit var appOpsManager: AppOpsManager
- @Mock
- lateinit var locationManager: LocationManager
- @Mock
- lateinit var userManager: UserManager
- @Mock
- lateinit var jobScheduler: JobScheduler
+ @Mock lateinit var packageManager: PackageManager
+ @Mock lateinit var permissionManager: PermissionManager
+ @Mock lateinit var activityManager: ActivityManager
+ @Mock lateinit var appOpsManager: AppOpsManager
+ @Mock lateinit var locationManager: LocationManager
+ @Mock lateinit var userManager: UserManager
+ @Mock lateinit var jobScheduler: JobScheduler
/**
* Set up {@link #packageManager} as if the passed packages are installed.
@@ -131,24 +127,28 @@ class RuntimePermissionsUpgradeControllerTest {
*/
private fun setPackages(vararg pkgs: Package) {
val mockPackageInfo = { pkgs: List<Package>, flags: Long ->
- pkgs.filter { pkg ->
- (flags and MATCH_FACTORY_ONLY.toLong()) == 0L || pkg.isPreinstalled
- }.map { pkg ->
- PackageInfo().apply {
- packageName = pkg.name
- requestedPermissions = pkg.permissions.map { it.name }.toTypedArray()
- requestedPermissionsFlags = pkg.permissions.map {
- if (it.isGranted) {
- REQUESTED_PERMISSION_GRANTED
- } else {
- 0
- }
- }.toIntArray()
- applicationInfo = ApplicationInfo().apply {
- targetSdkVersion = pkg.targetSdkVersion
+ pkgs
+ .filter { pkg ->
+ (flags and MATCH_FACTORY_ONLY.toLong()) == 0L || pkg.isPreinstalled
+ }
+ .map { pkg ->
+ PackageInfo().apply {
+ packageName = pkg.name
+ requestedPermissions = pkg.permissions.map { it.name }.toTypedArray()
+ requestedPermissionsFlags =
+ pkg.permissions
+ .map {
+ if (it.isGranted) {
+ REQUESTED_PERMISSION_GRANTED
+ } else {
+ 0
+ }
+ }
+ .toIntArray()
+ applicationInfo =
+ ApplicationInfo().apply { targetSdkVersion = pkg.targetSdkVersion }
}
}
- }
}
whenever(packageManager.getInstalledPackagesAsUser(anyInt(), anyInt())).thenAnswer {
@@ -159,22 +159,22 @@ class RuntimePermissionsUpgradeControllerTest {
if (SdkLevel.isAtLeastT()) {
whenever(
- packageManager.getInstalledPackagesAsUser(
- any(PackageManager.PackageInfoFlags::class.java),
- anyInt()
+ packageManager.getInstalledPackagesAsUser(
+ any(PackageManager.PackageInfoFlags::class.java),
+ anyInt()
+ )
)
- ).thenAnswer {
- val flags = it.arguments[0] as PackageManager.PackageInfoFlags
+ .thenAnswer {
+ val flags = it.arguments[0] as PackageManager.PackageInfoFlags
- mockPackageInfo(pkgs.toList(), flags.value)
- }
+ mockPackageInfo(pkgs.toList(), flags.value)
+ }
}
whenever(packageManager.getPackageInfo(anyString(), anyInt())).thenAnswer {
val packageName = it.arguments[0] as String
- packageManager.getInstalledPackagesAsUser(0, 0)
- .find { it.packageName == packageName }
+ packageManager.getInstalledPackagesAsUser(0, 0).find { it.packageName == packageName }
?: throw PackageManager.NameNotFoundException()
}
@@ -182,8 +182,12 @@ class RuntimePermissionsUpgradeControllerTest {
val permissionName = it.arguments[0] as String
val packageName = it.arguments[1] as String
- pkgs.find { it.name == packageName }?.permissions
- ?.find { it.name == permissionName }?.flags ?: 0
+ pkgs
+ .find { it.name == packageName }
+ ?.permissions
+ ?.find { it.name == permissionName }
+ ?.flags
+ ?: 0
}
}
@@ -195,37 +199,43 @@ class RuntimePermissionsUpgradeControllerTest {
fun initSystem() {
initMocks(this)
- mockitoSession = mockitoSession().mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(Settings.Secure::class.java).strictness(LENIENT).startMocking()
+ mockitoSession =
+ mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(Settings.Secure::class.java)
+ .strictness(LENIENT)
+ .startMocking()
whenever(PermissionControllerApplication.get()).thenReturn(application)
- whenever(application.getSystemService(PermissionManager::class.java)).thenReturn(
- permissionManager)
- whenever(application.getSystemService(ActivityManager::class.java)).thenReturn(
- activityManager)
+ whenever(application.getSystemService(PermissionManager::class.java))
+ .thenReturn(permissionManager)
+ whenever(application.getSystemService(ActivityManager::class.java))
+ .thenReturn(activityManager)
whenever(application.getSystemService(AppOpsManager::class.java)).thenReturn(appOpsManager)
- whenever(application.getSystemService(LocationManager::class.java)).thenReturn(
- locationManager)
- whenever(application.getSystemService(UserManager::class.java)).thenReturn(
- userManager)
- whenever(application.getSystemService(JobScheduler::class.java)).thenReturn(
- jobScheduler)
+ whenever(application.getSystemService(LocationManager::class.java))
+ .thenReturn(locationManager)
+ whenever(application.getSystemService(UserManager::class.java)).thenReturn(userManager)
+ whenever(application.getSystemService(JobScheduler::class.java)).thenReturn(jobScheduler)
whenever(application.packageManager).thenReturn(packageManager)
whenever(packageManager.getPermissionInfo(any(), anyInt())).thenAnswer {
val permissionName = it.arguments[0] as String
- InstrumentationRegistry.getInstrumentation().getTargetContext().packageManager
- .getPermissionInfo(permissionName, 0)
+ InstrumentationRegistry.getInstrumentation()
+ .getTargetContext()
+ .packageManager
+ .getPermissionInfo(permissionName, 0)
}
whenever(packageManager.getPermissionGroupInfo(any(), anyInt())).thenAnswer {
val groupName = it.arguments[0] as String
- InstrumentationRegistry.getInstrumentation().getTargetContext().packageManager
- .getPermissionGroupInfo(groupName, 0)
+ InstrumentationRegistry.getInstrumentation()
+ .getTargetContext()
+ .packageManager
+ .getPermissionGroupInfo(groupName, 0)
}
// We cannot use thenReturn(mutableListOf()) because that would return the same instance.
@@ -234,15 +244,14 @@ class RuntimePermissionsUpgradeControllerTest {
}
}
- /**
- * Call {@link RuntimePermissionsUpgradeController#upgradeIfNeeded) and wait until finished.
- */
+ /** Call {@link RuntimePermissionsUpgradeController#upgradeIfNeeded) and wait until finished. */
private fun upgradeIfNeeded() {
val completionCallback = CompletableFuture<Unit>()
runWithShellPermissionIdentity {
- RuntimePermissionsUpgradeController.upgradeIfNeeded(application, Runnable {
- completionCallback.complete(Unit)
- })
+ RuntimePermissionsUpgradeController.upgradeIfNeeded(
+ application,
+ Runnable { completionCallback.complete(Unit) }
+ )
completionCallback.join()
}
}
@@ -253,37 +262,37 @@ class RuntimePermissionsUpgradeControllerTest {
private fun verifyWhitelisted(packageName: String, vararg permissionNames: String) {
for (permissionName in permissionNames) {
- verify(packageManager, timeout(100)).addWhitelistedRestrictedPermission(
- packageName, permissionName, FLAG_PERMISSION_WHITELIST_UPGRADE)
+ verify(packageManager, timeout(100))
+ .addWhitelistedRestrictedPermission(
+ packageName,
+ permissionName,
+ FLAG_PERMISSION_WHITELIST_UPGRADE
+ )
}
}
private fun verifyNotWhitelisted(packageName: String, vararg permissionNames: String) {
for (permissionName in permissionNames) {
- verify(packageManager, never()).addWhitelistedRestrictedPermission(eq(packageName),
- eq(permissionName), anyInt())
+ verify(packageManager, never())
+ .addWhitelistedRestrictedPermission(eq(packageName), eq(permissionName), anyInt())
}
}
private fun verifyGranted(packageName: String, permissionName: String) {
- verify(packageManager, timeout(100)).grantRuntimePermission(eq(packageName),
- eq(permissionName), any())
+ verify(packageManager, timeout(100))
+ .grantRuntimePermission(eq(packageName), eq(permissionName), any())
}
private fun verifyNotGranted(packageName: String, permissionName: String) {
- verify(packageManager, never()).grantRuntimePermission(eq(packageName),
- eq(permissionName), any())
+ verify(packageManager, never())
+ .grantRuntimePermission(eq(packageName), eq(permissionName), any())
}
@Test
fun restrictedPermissionsOfPreinstalledPackagesGetWhiteListed() {
setInitialDatabaseVersion(LATEST_VERSION)
- setPackages(
- PreinstalledPackage(TEST_PKG_NAME,
- Permission(SEND_SMS)
- )
- )
+ setPackages(PreinstalledPackage(TEST_PKG_NAME, Permission(SEND_SMS)))
upgradeIfNeeded()
@@ -294,11 +303,7 @@ class RuntimePermissionsUpgradeControllerTest {
fun nonRestrictedPermissionsOfPreinstalledPackagesDoNotGetWhiteListed() {
setInitialDatabaseVersion(LATEST_VERSION)
- setPackages(
- PreinstalledPackage(TEST_PKG_NAME,
- Permission(ACCESS_FINE_LOCATION)
- )
- )
+ setPackages(PreinstalledPackage(TEST_PKG_NAME, Permission(ACCESS_FINE_LOCATION)))
upgradeIfNeeded()
@@ -308,11 +313,7 @@ class RuntimePermissionsUpgradeControllerTest {
@Test
fun restrictedPermissionsOfNonPreinstalledPackagesDoNotGetWhiteListed() {
setInitialDatabaseVersion(LATEST_VERSION)
- setPackages(
- Package(TEST_PKG_NAME,
- Permission(SEND_SMS)
- )
- )
+ setPackages(Package(TEST_PKG_NAME, Permission(SEND_SMS)))
upgradeIfNeeded()
@@ -322,12 +323,7 @@ class RuntimePermissionsUpgradeControllerTest {
@Test
fun smsAndCallLogGetsWhitelistedWhenInitialVersionIs0() {
setInitialDatabaseVersion(0)
- setPackages(
- Package(TEST_PKG_NAME,
- Permission(SEND_SMS),
- Permission(READ_CALL_LOG)
- )
- )
+ setPackages(Package(TEST_PKG_NAME, Permission(SEND_SMS), Permission(READ_CALL_LOG)))
upgradeIfNeeded()
@@ -338,12 +334,7 @@ class RuntimePermissionsUpgradeControllerTest {
@Test
fun smsAndCallLogGDoesNotGetWhitelistedWhenInitialVersionIs1() {
setInitialDatabaseVersion(1)
- setPackages(
- Package(TEST_PKG_NAME,
- Permission(SEND_SMS),
- Permission(READ_CALL_LOG)
- )
- )
+ setPackages(Package(TEST_PKG_NAME, Permission(SEND_SMS), Permission(READ_CALL_LOG)))
upgradeIfNeeded()
@@ -354,11 +345,7 @@ class RuntimePermissionsUpgradeControllerTest {
@Test
fun backgroundLocationGetsWhitelistedWhenInitialVersionIs3() {
setInitialDatabaseVersion(3)
- setPackages(
- Package(TEST_PKG_NAME,
- Permission(ACCESS_BACKGROUND_LOCATION)
- )
- )
+ setPackages(Package(TEST_PKG_NAME, Permission(ACCESS_BACKGROUND_LOCATION)))
upgradeIfNeeded()
@@ -368,11 +355,7 @@ class RuntimePermissionsUpgradeControllerTest {
@Test
fun backgroundLocationGetsWhitelistedWhenInitialVersionIs4() {
setInitialDatabaseVersion(4)
- setPackages(
- Package(TEST_PKG_NAME,
- Permission(ACCESS_BACKGROUND_LOCATION)
- )
- )
+ setPackages(Package(TEST_PKG_NAME, Permission(ACCESS_BACKGROUND_LOCATION)))
upgradeIfNeeded()
@@ -382,11 +365,7 @@ class RuntimePermissionsUpgradeControllerTest {
@Test
fun storageGetsWhitelistedWhenInitialVersionIs5() {
setInitialDatabaseVersion(5)
- setPackages(
- Package(TEST_PKG_NAME,
- Permission(READ_EXTERNAL_STORAGE)
- )
- )
+ setPackages(Package(TEST_PKG_NAME, Permission(READ_EXTERNAL_STORAGE)))
upgradeIfNeeded()
@@ -396,11 +375,7 @@ class RuntimePermissionsUpgradeControllerTest {
@Test
fun storageGetsWhitelistedWhenInitialVersionIs6() {
setInitialDatabaseVersion(6)
- setPackages(
- Package(TEST_PKG_NAME,
- Permission(READ_EXTERNAL_STORAGE)
- )
- )
+ setPackages(Package(TEST_PKG_NAME, Permission(READ_EXTERNAL_STORAGE)))
upgradeIfNeeded()
@@ -411,7 +386,8 @@ class RuntimePermissionsUpgradeControllerTest {
fun locationGetsExpandedWhenUpgradingFromP() {
setInitialDatabaseVersion(-1)
setPackages(
- Package(TEST_PKG_NAME,
+ Package(
+ TEST_PKG_NAME,
Permission(ACCESS_FINE_LOCATION, isGranted = true),
Permission(ACCESS_BACKGROUND_LOCATION)
)
@@ -426,7 +402,8 @@ class RuntimePermissionsUpgradeControllerTest {
fun locationDoesNotGetExpandedWhenNotUpgradingFromP() {
setInitialDatabaseVersion(0)
setPackages(
- Package(TEST_PKG_NAME,
+ Package(
+ TEST_PKG_NAME,
Permission(ACCESS_FINE_LOCATION, isGranted = true),
Permission(ACCESS_BACKGROUND_LOCATION)
)
@@ -441,7 +418,8 @@ class RuntimePermissionsUpgradeControllerTest {
fun locationDoesNotGetExpandedWhenUpgradingFromPWhenForegroundPermissionIsDenied() {
setInitialDatabaseVersion(-1)
setPackages(
- Package(TEST_PKG_NAME,
+ Package(
+ TEST_PKG_NAME,
Permission(ACCESS_FINE_LOCATION),
Permission(ACCESS_BACKGROUND_LOCATION)
)
@@ -456,9 +434,13 @@ class RuntimePermissionsUpgradeControllerTest {
fun storageGetsExpandedWhenVersionIs7() {
setInitialDatabaseVersion(7)
setPackages(
- Package(TEST_PKG_NAME,
- Permission(READ_EXTERNAL_STORAGE, isGranted = true,
- flags = FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT),
+ Package(
+ TEST_PKG_NAME,
+ Permission(
+ READ_EXTERNAL_STORAGE,
+ isGranted = true,
+ flags = FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT
+ ),
Permission(ACCESS_MEDIA_LOCATION)
)
)
@@ -472,9 +454,13 @@ class RuntimePermissionsUpgradeControllerTest {
fun storageDoesNotGetExpandedWhenVersionIs8() {
setInitialDatabaseVersion(8)
setPackages(
- Package(TEST_PKG_NAME,
- Permission(READ_EXTERNAL_STORAGE, isGranted = true,
- flags = FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT),
+ Package(
+ TEST_PKG_NAME,
+ Permission(
+ READ_EXTERNAL_STORAGE,
+ isGranted = true,
+ flags = FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT
+ ),
Permission(ACCESS_MEDIA_LOCATION)
)
)
@@ -488,9 +474,12 @@ class RuntimePermissionsUpgradeControllerTest {
fun storageDoesNotGetExpandedWhenDenied() {
setInitialDatabaseVersion(7)
setPackages(
- Package(TEST_PKG_NAME,
- Permission(READ_EXTERNAL_STORAGE,
- flags = FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT),
+ Package(
+ TEST_PKG_NAME,
+ Permission(
+ READ_EXTERNAL_STORAGE,
+ flags = FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT
+ ),
Permission(ACCESS_MEDIA_LOCATION)
)
)
@@ -504,9 +493,13 @@ class RuntimePermissionsUpgradeControllerTest {
fun storageDoesNotGetExpandedWhenNewUser() {
setInitialDatabaseVersion(0)
setPackages(
- Package(TEST_PKG_NAME,
- Permission(READ_EXTERNAL_STORAGE, isGranted = true,
- flags = FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT),
+ Package(
+ TEST_PKG_NAME,
+ Permission(
+ READ_EXTERNAL_STORAGE,
+ isGranted = true,
+ flags = FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT
+ ),
Permission(ACCESS_MEDIA_LOCATION)
)
)
@@ -527,13 +520,23 @@ class RuntimePermissionsUpgradeControllerTest {
whenever(packageManager.isDeviceUpgrading).thenReturn(true)
setInitialDatabaseVersion(9)
setPackages(
- Package(TEST_PKG_NAME,
- Permission(READ_EXTERNAL_STORAGE, isGranted = true,
- flags = FLAG_PERMISSION_USER_SET),
- Permission(WRITE_EXTERNAL_STORAGE, isGranted = true,
- flags = FLAG_PERMISSION_USER_SET),
- Permission(ACCESS_MEDIA_LOCATION, isGranted = true,
- flags = FLAG_PERMISSION_USER_SET),
+ Package(
+ TEST_PKG_NAME,
+ Permission(
+ READ_EXTERNAL_STORAGE,
+ isGranted = true,
+ flags = FLAG_PERMISSION_USER_SET
+ ),
+ Permission(
+ WRITE_EXTERNAL_STORAGE,
+ isGranted = true,
+ flags = FLAG_PERMISSION_USER_SET
+ ),
+ Permission(
+ ACCESS_MEDIA_LOCATION,
+ isGranted = true,
+ flags = FLAG_PERMISSION_USER_SET
+ ),
Permission(READ_MEDIA_AUDIO, isGranted = false),
Permission(READ_MEDIA_VIDEO, isGranted = false),
Permission(READ_MEDIA_IMAGES, isGranted = false),
@@ -554,7 +557,8 @@ class RuntimePermissionsUpgradeControllerTest {
whenever(packageManager.isDeviceUpgrading).thenReturn(true)
setInitialDatabaseVersion(10)
setPackages(
- Package(TEST_PKG_NAME,
+ Package(
+ TEST_PKG_NAME,
Permission(READ_MEDIA_VIDEO, isGranted = true, flags = FLAG_PERMISSION_USER_SET),
Permission(READ_MEDIA_IMAGES, isGranted = true, flags = FLAG_PERMISSION_USER_SET),
Permission(READ_MEDIA_VISUAL_USER_SELECTED, isGranted = false),
@@ -573,7 +577,8 @@ class RuntimePermissionsUpgradeControllerTest {
whenever(packageManager.isDeviceUpgrading).thenReturn(false)
setInitialDatabaseVersion(10)
setPackages(
- Package(TEST_PKG_NAME,
+ Package(
+ TEST_PKG_NAME,
Permission(READ_MEDIA_VIDEO, isGranted = true, flags = FLAG_PERMISSION_USER_SET),
Permission(READ_MEDIA_IMAGES, isGranted = true, flags = FLAG_PERMISSION_USER_SET),
Permission(READ_MEDIA_VISUAL_USER_SELECTED, isGranted = false),
@@ -592,7 +597,8 @@ class RuntimePermissionsUpgradeControllerTest {
whenever(packageManager.isDeviceUpgrading).thenReturn(false)
setInitialDatabaseVersion(10)
setPackages(
- Package(TEST_PKG_NAME,
+ Package(
+ TEST_PKG_NAME,
Permission(READ_MEDIA_VIDEO, isGranted = false, flags = FLAG_PERMISSION_USER_SET),
Permission(READ_MEDIA_IMAGES, isGranted = false, flags = FLAG_PERMISSION_USER_SET),
Permission(READ_MEDIA_VISUAL_USER_SELECTED, isGranted = false),
@@ -633,12 +639,9 @@ class RuntimePermissionsUpgradeControllerTest {
) : this(name, permission.toList(), isPreinstalled, targetSdkVersion)
}
- private class PreinstalledPackage(
- name: String,
- permissions: List<Permission> = emptyList()
- ) : Package(name, permissions, true) {
- constructor(name: String, vararg permission: Permission) :
- this(name, permission.toList())
+ private class PreinstalledPackage(name: String, permissions: List<Permission> = emptyList()) :
+ Package(name, permissions, true) {
+ constructor(name: String, vararg permission: Permission) : this(name, permission.toList())
}
private fun <R> runWithShellPermissionIdentity(block: () -> R): R {
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/v33/PermissionDecisionStorageImplTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/v33/PermissionDecisionStorageImplTest.kt
index de8e3f5ef..fbbc07837 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/v33/PermissionDecisionStorageImplTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/v33/PermissionDecisionStorageImplTest.kt
@@ -27,6 +27,10 @@ import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.permission.data.v33.PermissionDecision
import com.android.permissioncontroller.permission.service.v33.PermissionDecisionStorageImpl
import com.google.common.truth.Truth.assertThat
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.io.File
+import java.util.Date
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Before
@@ -37,10 +41,6 @@ import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-import java.io.ByteArrayInputStream
-import java.io.ByteArrayOutputStream
-import java.io.File
-import java.util.Date
@RunWith(AndroidJUnit4::class)
class PermissionDecisionStorageImplTest {
@@ -53,13 +53,12 @@ class PermissionDecisionStorageImplTest {
private val jan12020 = Date(2020, 0, 1).time
- private val mapLocationGrant = PermissionDecision(
- MAP_PACKAGE_NAME, jan12020, "location", /* isGranted */ true)
- private val parkingLocationGrant = PermissionDecision(
- "package.test.parking", jan12020, "location", /* isGranted */ false)
+ private val mapLocationGrant =
+ PermissionDecision(MAP_PACKAGE_NAME, jan12020, "location", /* isGranted */ true)
+ private val parkingLocationGrant =
+ PermissionDecision("package.test.parking", jan12020, "location", /* isGranted */ false)
- @Mock
- lateinit var jobScheduler: JobScheduler
+ @Mock lateinit var jobScheduler: JobScheduler
private lateinit var context: Context
private lateinit var storage: PermissionDecisionStorageImpl
@@ -69,10 +68,12 @@ class PermissionDecisionStorageImplTest {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(DeviceConfig::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(DeviceConfig::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
Mockito.`when`(PermissionControllerApplication.get()).thenReturn(application)
context = ApplicationProvider.getApplicationContext()
filesDir = context.cacheDir
@@ -102,8 +103,8 @@ class PermissionDecisionStorageImplTest {
@Test
fun serialize_roundsTimeDownToDate() {
- val laterInTheDayGrant = mapLocationGrant.copy(
- eventTime = (mapLocationGrant.eventTime + FIVE_HOURS_MS))
+ val laterInTheDayGrant =
+ mapLocationGrant.copy(eventTime = (mapLocationGrant.eventTime + FIVE_HOURS_MS))
val outStream = ByteArrayOutputStream()
storage.serialize(outStream, listOf(laterInTheDayGrant))
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/handheld/v31/DashboardUtilsTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/handheld/v31/DashboardUtilsTest.kt
index 776e0719c..136162040 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/handheld/v31/DashboardUtilsTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/handheld/v31/DashboardUtilsTest.kt
@@ -21,189 +21,123 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.permissioncontroller.permission.ui.handheld.v31.getDurationUsedStr
import com.android.permissioncontroller.permission.ui.handheld.v31.getTimeDiffStr
import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.TimeUnit
import org.junit.Test
import org.junit.runner.RunWith
-import java.util.concurrent.TimeUnit
-/**
- * A suite of unit tests to test the permission dashboard utils.
- */
+/** A suite of unit tests to test the permission dashboard utils. */
@RunWith(AndroidJUnit4::class)
class DashboardUtilsTest {
@Test
fun getTimeDiffStr_durationSecondsOne() {
val duration: Long = TimeUnit.SECONDS.toMillis(1L)
- assertThat(
- getTimeDiffStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("1 second")
+ assertThat(getTimeDiffStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("1 second")
}
@Test
fun getTimeDiffStr_durationSecondsOther() {
val duration: Long = TimeUnit.SECONDS.toMillis(59L)
- assertThat(
- getTimeDiffStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("59 seconds")
+ assertThat(getTimeDiffStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("59 seconds")
}
@Test
fun getTimeDiffStr_durationMinutesOne() {
val duration: Long = TimeUnit.MINUTES.toMillis(1L)
- assertThat(
- getTimeDiffStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("1 minute")
+ assertThat(getTimeDiffStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("1 minute")
}
@Test
fun getTimeDiffStr_durationMinutesOther() {
val duration: Long = TimeUnit.MINUTES.toMillis(59L)
- assertThat(
- getTimeDiffStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("59 minutes")
+ assertThat(getTimeDiffStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("59 minutes")
}
@Test
fun getTimeDiffStr_durationHoursOne() {
val duration: Long = TimeUnit.HOURS.toMillis(1L)
- assertThat(
- getTimeDiffStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("1 hour")
+ assertThat(getTimeDiffStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("1 hour")
}
@Test
fun getTimeDiffStr_durationHoursOther() {
val duration: Long = TimeUnit.HOURS.toMillis(23L)
- assertThat(
- getTimeDiffStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("23 hours")
+ assertThat(getTimeDiffStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("23 hours")
}
@Test
fun getTimeDiffStr_durationDaysOne() {
val duration: Long = TimeUnit.DAYS.toMillis(1L)
- assertThat(
- getTimeDiffStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("1 day")
+ assertThat(getTimeDiffStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("1 day")
}
@Test
fun getTimeDiffStr_durationDaysOther() {
val duration: Long = TimeUnit.DAYS.toMillis(2L)
- assertThat(
- getTimeDiffStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("2 days")
+ assertThat(getTimeDiffStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("2 days")
}
@Test
fun getDurationUsedStr_durationSecondsOne() {
val duration: Long = TimeUnit.SECONDS.toMillis(1L)
- assertThat(
- getDurationUsedStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("1 sec")
+ assertThat(getDurationUsedStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("1 sec")
}
@Test
fun getDurationUsedStr_durationSecondsOther() {
val duration: Long = TimeUnit.SECONDS.toMillis(59L)
- assertThat(
- getDurationUsedStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("59 secs")
+ assertThat(getDurationUsedStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("59 secs")
}
@Test
fun getDurationUsedStr_durationMinutesOne() {
val duration: Long = TimeUnit.MINUTES.toMillis(1L)
- assertThat(
- getDurationUsedStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("1 min")
+ assertThat(getDurationUsedStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("1 min")
}
@Test
fun getDurationUsedStr_durationMinutesOther() {
val duration: Long = TimeUnit.MINUTES.toMillis(59L)
- assertThat(
- getDurationUsedStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("59 mins")
+ assertThat(getDurationUsedStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("59 mins")
}
@Test
fun getDurationUsedStr_durationHoursOne() {
val duration: Long = TimeUnit.HOURS.toMillis(1L)
- assertThat(
- getDurationUsedStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("1 hour")
+ assertThat(getDurationUsedStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("1 hour")
}
@Test
fun getDurationUsedStr_durationHoursOther() {
val duration: Long = TimeUnit.HOURS.toMillis(23L)
- assertThat(
- getDurationUsedStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("23 hours")
+ assertThat(getDurationUsedStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("23 hours")
}
@Test
fun getDurationUsedStr_durationDaysOne() {
val duration: Long = TimeUnit.DAYS.toMillis(1L)
- assertThat(
- getDurationUsedStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("1 day")
+ assertThat(getDurationUsedStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("1 day")
}
@Test
fun getDurationUsedStr_durationDaysOther() {
val duration: Long = TimeUnit.DAYS.toMillis(2L)
- assertThat(
- getDurationUsedStr(
- ApplicationProvider.getApplicationContext(),
- duration
- )
- ).isEqualTo("2 days")
- }
-} \ No newline at end of file
+ assertThat(getDurationUsedStr(ApplicationProvider.getApplicationContext(), duration))
+ .isEqualTo("2 days")
+ }
+}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/model/ReviewPermissionsViewModelTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/model/ReviewPermissionsViewModelTest.kt
index 0f4216066..899a026c4 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/model/ReviewPermissionsViewModelTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/model/ReviewPermissionsViewModelTest.kt
@@ -47,26 +47,18 @@ import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-/**
- * Unit tests for [ReviewPermissionsViewModel]
- */
+/** Unit tests for [ReviewPermissionsViewModel] */
@RunWith(AndroidJUnit4::class)
class ReviewPermissionsViewModelTest {
private val testPackageName = "test.package"
- @Mock
- private lateinit var application: PermissionControllerApplication
- @Mock
- private lateinit var permGroup: LightAppPermGroup
- @Mock
- private lateinit var foregroundSubGroup: LightAppPermGroup.AppPermSubGroup
- @Mock
- private lateinit var backgroundSubGroup: LightAppPermGroup.AppPermSubGroup
- @Mock
- private lateinit var admin: RestrictedLockUtils.EnforcedAdmin
- @Mock
- private lateinit var packageManager: PackageManager
+ @Mock private lateinit var application: PermissionControllerApplication
+ @Mock private lateinit var permGroup: LightAppPermGroup
+ @Mock private lateinit var foregroundSubGroup: LightAppPermGroup.AppPermSubGroup
+ @Mock private lateinit var backgroundSubGroup: LightAppPermGroup.AppPermSubGroup
+ @Mock private lateinit var admin: RestrictedLockUtils.EnforcedAdmin
+ @Mock private lateinit var packageManager: PackageManager
private lateinit var mockitoSession: MockitoSession
private lateinit var context: Context
@@ -76,10 +68,12 @@ class ReviewPermissionsViewModelTest {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(Utils::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(Utils::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
context = ApplicationProvider.getApplicationContext()
val userHandle: UserHandle = android.os.Process.myUserHandle()
@@ -114,9 +108,9 @@ class ReviewPermissionsViewModelTest {
val summary = model.getSummaryForIndividuallyControlledPermGroup(permGroup)
assertEquals(
- ReviewPermissionsViewModel.PermissionSummary(
- SummaryMessage.REVOKED_COUNT, false, 1
- ), summary)
+ ReviewPermissionsViewModel.PermissionSummary(SummaryMessage.REVOKED_COUNT, false, 1),
+ summary
+ )
}
@Test
@@ -124,48 +118,78 @@ class ReviewPermissionsViewModelTest {
whenever(permGroup.isGranted).thenReturn(true)
whenever(foregroundSubGroup.isPolicyFixed).thenReturn(true)
- val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_FOREGROUND,
- permGroup, context)
+ val summary =
+ model.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_FOREGROUND,
+ permGroup,
+ context
+ )
assertEquals(SummaryMessage.ENABLED_BY_POLICY_FOREGROUND_ONLY.toPermSummary(), summary)
val spyViewModel = spy(model)
doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
- val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
- PERMISSION_FOREGROUND, permGroup, context)
- assertEquals(SummaryMessage.ENABLED_BY_ADMIN_FOREGROUND_ONLY.toPermSummary(true),
- summaryAdmin)
+ val summaryAdmin =
+ spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_FOREGROUND,
+ permGroup,
+ context
+ )
+ assertEquals(
+ SummaryMessage.ENABLED_BY_ADMIN_FOREGROUND_ONLY.toPermSummary(true),
+ summaryAdmin
+ )
}
@Test
fun getSummary_backgroundFixedPolicy_foregroundRequested() {
whenever(backgroundSubGroup.isPolicyFixed).thenReturn(true)
- val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_FOREGROUND,
- permGroup, context)
+ val summary =
+ model.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_FOREGROUND,
+ permGroup,
+ context
+ )
assertEquals(SummaryMessage.DISABLED_BY_POLICY_BACKGROUND_ONLY.toPermSummary(), summary)
val spyViewModel = spy(model)
doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
- val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
- PERMISSION_FOREGROUND, permGroup, context)
- assertEquals(SummaryMessage.DISABLED_BY_ADMIN_BACKGROUND_ONLY.toPermSummary(true),
- summaryAdmin)
+ val summaryAdmin =
+ spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_FOREGROUND,
+ permGroup,
+ context
+ )
+ assertEquals(
+ SummaryMessage.DISABLED_BY_ADMIN_BACKGROUND_ONLY.toPermSummary(true),
+ summaryAdmin
+ )
}
@Test
fun getSummary_backgroundFixedPolicy() {
whenever(backgroundSubGroup.isPolicyFixed).thenReturn(true)
- val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BACKGROUND,
- permGroup, context)
+ val summary =
+ model.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_BACKGROUND,
+ permGroup,
+ context
+ )
assertEquals(SummaryMessage.ENABLED_BY_POLICY_BACKGROUND_ONLY.toPermSummary(), summary)
val spyViewModel = spy(model)
doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
- val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
- PERMISSION_BACKGROUND, permGroup, context)
- assertEquals(SummaryMessage.ENABLED_BY_ADMIN_BACKGROUND_ONLY.toPermSummary(true),
- summaryAdmin)
+ val summaryAdmin =
+ spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_BACKGROUND,
+ permGroup,
+ context
+ )
+ assertEquals(
+ SummaryMessage.ENABLED_BY_ADMIN_BACKGROUND_ONLY.toPermSummary(true),
+ summaryAdmin
+ )
}
@Test
@@ -173,14 +197,22 @@ class ReviewPermissionsViewModelTest {
whenever(permGroup.isPolicyFullyFixed).thenReturn(true)
whenever(permGroup.hasBackgroundGroup).thenReturn(true)
- val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_FOREGROUND,
- permGroup, context)
+ val summary =
+ model.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_FOREGROUND,
+ permGroup,
+ context
+ )
assertEquals(SummaryMessage.ENABLED_BY_POLICY_BACKGROUND_ONLY.toPermSummary(), summary)
val spyViewModel = spy(model)
doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
- val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
- PERMISSION_FOREGROUND, permGroup, context)
+ val summaryAdmin =
+ spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_FOREGROUND,
+ permGroup,
+ context
+ )
assertEquals(SummaryMessage.ENABLED_BY_ADMIN_FOREGROUND_ONLY.toPermSummary(), summaryAdmin)
}
@@ -189,14 +221,22 @@ class ReviewPermissionsViewModelTest {
whenever(permGroup.isPolicyFullyFixed).thenReturn(true)
whenever(permGroup.hasBackgroundGroup).thenReturn(true)
- val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BACKGROUND,
- permGroup, context)
+ val summary =
+ model.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_BACKGROUND,
+ permGroup,
+ context
+ )
assertEquals(SummaryMessage.ENFORCED_BY_POLICY.toPermSummary(), summary)
val spyViewModel = spy(model)
doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
- val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
- PERMISSION_BACKGROUND, permGroup, context)
+ val summaryAdmin =
+ spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_BACKGROUND,
+ permGroup,
+ context
+ )
assertEquals(SummaryMessage.ENABLED_BY_ADMIN.toPermSummary(), summaryAdmin)
}
@@ -204,14 +244,18 @@ class ReviewPermissionsViewModelTest {
fun getSummary_fullyFixedPolicy_hasNoBackgroundGroup() {
whenever(permGroup.isPolicyFullyFixed).thenReturn(true)
- val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH,
- permGroup, context)
+ val summary =
+ model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH, permGroup, context)
assertEquals(SummaryMessage.ENFORCED_BY_POLICY.toPermSummary(), summary)
val spyViewModel = spy(model)
doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
- val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH,
- permGroup, context)
+ val summaryAdmin =
+ spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_BOTH,
+ permGroup,
+ context
+ )
assertEquals(SummaryMessage.ENABLED_BY_ADMIN.toPermSummary(), summaryAdmin)
}
@@ -220,14 +264,18 @@ class ReviewPermissionsViewModelTest {
whenever(foregroundSubGroup.isPolicyFixed).thenReturn(true)
whenever(permGroup.isGranted).thenReturn(false)
- val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH,
- permGroup, context)
+ val summary =
+ model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH, permGroup, context)
assertEquals(SummaryMessage.ENFORCED_BY_POLICY.toPermSummary(), summary)
val spyViewModel = spy(model)
doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
- val adminSummary = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH,
- permGroup, context)
+ val adminSummary =
+ spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_BOTH,
+ permGroup,
+ context
+ )
assertEquals(SummaryMessage.DISABLED_BY_ADMIN.toPermSummary(), adminSummary)
}
@@ -235,8 +283,8 @@ class ReviewPermissionsViewModelTest {
fun getSummary_systemFixedPolicy() {
whenever(permGroup.isSystemFixed).thenReturn(true)
- val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH,
- permGroup, context)
+ val summary =
+ model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH, permGroup, context)
assertEquals(SummaryMessage.ENABLED_SYSTEM_FIXED.toPermSummary(), summary)
}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt
index be6518b23..fba7e4a75 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt
@@ -64,7 +64,8 @@ import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
-private const val PERMISSION_CONTROLLER_CHANGED_FLAG_MASK = FLAG_PERMISSION_USER_SET or
+private const val PERMISSION_CONTROLLER_CHANGED_FLAG_MASK =
+ FLAG_PERMISSION_USER_SET or
FLAG_PERMISSION_USER_FIXED or
FLAG_PERMISSION_ONE_TIME or
FLAG_PERMISSION_REVOKED_COMPAT or
@@ -101,8 +102,7 @@ class GrantRevokeTests {
}
}
- @Mock
- val app: Application = mock(Application::class.java)
+ @Mock val app: Application = mock(Application::class.java)
/**
* Create a mock Application object, with a mock packageManager, AppOpsManager, and
@@ -119,11 +119,11 @@ class GrantRevokeTests {
.thenReturn(-1)
`when`(app.getSystemService(AppOpsManager::class.java)).thenReturn(aom)
- `when`(app.getSystemService(ActivityManager::class.java)).thenReturn(
- mock(ActivityManager::class.java))
+ `when`(app.getSystemService(ActivityManager::class.java))
+ .thenReturn(mock(ActivityManager::class.java))
- `when`(app.getSystemService(PermissionManager::class.java)).thenReturn(
- mock(PermissionManager::class.java))
+ `when`(app.getSystemService(PermissionManager::class.java))
+ .thenReturn(mock(PermissionManager::class.java))
}
/**
@@ -142,19 +142,34 @@ class GrantRevokeTests {
val permFlags = mutableListOf<Int>()
for ((permName, isGranted) in perms) {
permNames.add(permName)
- permFlags.add(if (isGranted) {
- PERMISSION_GRANTED
- } else {
- PERMISSION_DENIED
- })
+ permFlags.add(
+ if (isGranted) {
+ PERMISSION_GRANTED
+ } else {
+ PERMISSION_DENIED
+ }
+ )
}
- return LightPackageInfo(TEST_PACKAGE_NAME, listOf(), permNames, permFlags, TEST_UID,
- if (isPreMApp) {
- Build.VERSION_CODES.LOLLIPOP
- } else {
- Build.VERSION_CODES.R
- }, isInstantApp, isInstantApp, 0, 0L, 0L, false, emptyMap())
+ return LightPackageInfo(
+ TEST_PACKAGE_NAME,
+ listOf(),
+ permNames,
+ permFlags,
+ TEST_UID,
+ if (isPreMApp) {
+ Build.VERSION_CODES.LOLLIPOP
+ } else {
+ Build.VERSION_CODES.R
+ },
+ isInstantApp,
+ isInstantApp,
+ 0,
+ 0L,
+ 0L,
+ false,
+ emptyMap()
+ )
}
/**
@@ -163,13 +178,13 @@ class GrantRevokeTests {
* @param pkg Package requesting the permission
* @param permName The name of the permission
* @param granted Whether the permission is granted (should be false if the permission is compat
- * revoked)
+ * revoked)
* @param backgroundPerm The name of this permission's background permission, if there is one
* @param foregroundPerms The names of this permission's foreground permissions, if there are
- * any
+ * any
* @param flags The system permission flags of this permission
* @param permInfoProtectionFlags The flags that the PermissionInfo object has (accessed by
- * PermissionInfo.getProtectionFlags)
+ * PermissionInfo.getProtectionFlags)
*/
private fun createMockPerm(
pkgInfo: LightPackageInfo,
@@ -179,11 +194,24 @@ class GrantRevokeTests {
flags: Int = NO_FLAGS,
permInfoProtectionFlags: Int = 0
): LightPermission {
- val permInfo = LightPermInfo(permName, TEST_PACKAGE_NAME, PERM_GROUP_NAME, backgroundPerm,
- PermissionInfo.PROTECTION_DANGEROUS, permInfoProtectionFlags, 0)
- return LightPermission(pkgInfo, permInfo,
- pkgInfo.requestedPermissionsFlags[pkgInfo.requestedPermissions.indexOf(permName)]
- == PERMISSION_GRANTED, flags, foregroundPerms)
+ val permInfo =
+ LightPermInfo(
+ permName,
+ TEST_PACKAGE_NAME,
+ PERM_GROUP_NAME,
+ backgroundPerm,
+ PermissionInfo.PROTECTION_DANGEROUS,
+ permInfoProtectionFlags,
+ 0
+ )
+ return LightPermission(
+ pkgInfo,
+ permInfo,
+ pkgInfo.requestedPermissionsFlags[pkgInfo.requestedPermissions.indexOf(permName)] ==
+ PERMISSION_GRANTED,
+ flags,
+ foregroundPerms
+ )
}
/**
@@ -201,12 +229,11 @@ class GrantRevokeTests {
}
/**
- * Create a list of strings which usefully states which flags are set in a group of flags.
- * Only checks for flags relevant to granting and revoking (so, for instance, policy fixed is
- * not checked).
+ * Create a list of strings which usefully states which flags are set in a group of flags. Only
+ * checks for flags relevant to granting and revoking (so, for instance, policy fixed is not
+ * checked).
*
* @param flags The flags to check
- *
* @return a list of strings, representing which flags have been set
*/
private fun flagsToString(flags: Int): List<String> {
@@ -251,28 +278,32 @@ class GrantRevokeTests {
val flags = state.second
assertWithMessage("permission $permName grant state incorrect")
- .that(perms[permName]?.isGrantedIncludingAppOp).isEqualTo(granted)
+ .that(perms[permName]?.isGrantedIncludingAppOp)
+ .isEqualTo(granted)
val actualFlags = perms[permName]!!.flags
- assertWithMessage("permission $permName flags incorrect, expected" +
- "${flagsToString(flags)}; got ${flagsToString(actualFlags)}")
- .that(perms[permName]?.flags).isEqualTo(flags)
+ assertWithMessage(
+ "permission $permName flags incorrect, expected" +
+ "${flagsToString(flags)}; got ${flagsToString(actualFlags)}"
+ )
+ .that(perms[permName]?.flags)
+ .isEqualTo(flags)
}
}
/**
- * Verify that permission state was propagated to the system. Verify that grant or revoke
- * were called, if applicable, or verify they weren't. Verify that we have set flags
- * correctly, if applicable, or verify flags were not set.
+ * Verify that permission state was propagated to the system. Verify that grant or revoke were
+ * called, if applicable, or verify they weren't. Verify that we have set flags correctly, if
+ * applicable, or verify flags were not set.
*
* @param permName The name of the permission to verify
* @param expectPermChange Whether or not a permission grant or revoke was expected. If false,
- * verify neither grant nor revoke were called
- * @param expectPermGranted If a permission change was expected, verify that the permission
- * was set to granted (if true) or revoked (if false)
+ * verify neither grant nor revoke were called
+ * @param expectPermGranted If a permission change was expected, verify that the permission was
+ * set to granted (if true) or revoked (if false)
* @param expectedFlags The flags that the system should have set the permission to have
- * @param originalFlags The flags the permission originally had. Used to ensure the correct
- * flag mask was used
+ * @param originalFlags The flags the permission originally had. Used to ensure the correct flag
+ * mask was used
*/
private fun verifyPermissionState(
permName: String,
@@ -294,11 +325,23 @@ class GrantRevokeTests {
}
if (expectedFlags != originalFlags) {
- verify(pm).updatePermissionFlags(permName, TEST_PACKAGE_NAME,
- PERMISSION_CONTROLLER_CHANGED_FLAG_MASK, expectedFlags, TEST_USER)
+ verify(pm)
+ .updatePermissionFlags(
+ permName,
+ TEST_PACKAGE_NAME,
+ PERMISSION_CONTROLLER_CHANGED_FLAG_MASK,
+ expectedFlags,
+ TEST_USER
+ )
} else {
- verify(pm, never()).updatePermissionFlags(eq(permName), eq(TEST_PACKAGE_NAME), anyInt(),
- anyInt(), eq(TEST_USER))
+ verify(pm, never())
+ .updatePermissionFlags(
+ eq(permName),
+ eq(TEST_PACKAGE_NAME),
+ anyInt(),
+ anyInt(),
+ eq(TEST_USER)
+ )
}
}
@@ -308,7 +351,7 @@ class GrantRevokeTests {
*
* @param appOpName The name of the app op to check
* @param expectAppOpSet Whether an app op change was expected. If false, verify setUidMode was
- * not called
+ * not called
* @param expectedMode If a change was expected, the mode the app op should be set to
*/
private fun verifyAppOpState(
@@ -353,8 +396,12 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = true, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = true,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
verifyAppKillState(shouldBeKilled = false)
@@ -379,17 +426,28 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = true, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = true,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
- verifyPermissionState(permName = FG_PERM_2_NAME, expectPermChange = true,
- expectPermGranted = true, expectedFlags = newFlags)
- verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = true,
- expectedMode = MODE_FOREGROUND)
+ verifyPermissionState(
+ permName = FG_PERM_2_NAME,
+ expectPermChange = true,
+ expectPermGranted = true,
+ expectedFlags = newFlags
+ )
+ verifyAppOpState(
+ appOpName = OP_2_NAME,
+ expectAppOpSet = true,
+ expectedMode = MODE_FOREGROUND
+ )
verifyAppKillState(shouldBeKilled = false)
- val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags),
- FG_PERM_2_NAME to (true to newFlags))
+ val expectedState =
+ mutableMapOf(FG_PERM_NAME to (true to newFlags), FG_PERM_2_NAME to (true to newFlags))
assertGroupPermState(newGroup, expectedState)
}
@@ -408,8 +466,12 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME_NO_APP_OP, expectPermChange = true,
- expectPermGranted = true, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME_NO_APP_OP,
+ expectPermChange = true,
+ expectPermGranted = true,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
verifyAppKillState(shouldBeKilled = false)
@@ -434,14 +496,18 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.grantBackgroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = true,
- expectPermGranted = true, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = BG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = true,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
verifyAppKillState(shouldBeKilled = false)
- val expectedState = mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS),
- BG_PERM_NAME to (true to newFlags))
+ val expectedState =
+ mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS), BG_PERM_NAME to (true to newFlags))
assertGroupPermState(newGroup, expectedState)
}
@@ -462,26 +528,34 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = true, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = true,
+ expectedFlags = newFlags
+ )
verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = false)
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
verifyAppKillState(shouldBeKilled = false)
- val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags),
- BG_PERM_NAME to (false to NO_FLAGS))
+ val expectedState =
+ mutableMapOf(FG_PERM_NAME to (true to newFlags), BG_PERM_NAME to (false to NO_FLAGS))
assertGroupPermState(newGroup, expectedState)
resetMockAppState()
val newGroup2 = KotlinUtils.grantBackgroundRuntimePermissions(app, newGroup)
- verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = true,
- expectPermGranted = true, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = BG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = true,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
verifyAppKillState(shouldBeKilled = false)
- val expectedState2 = mutableMapOf(FG_PERM_NAME to (true to newFlags),
- BG_PERM_NAME to (true to newFlags))
+ val expectedState2 =
+ mutableMapOf(FG_PERM_NAME to (true to newFlags), BG_PERM_NAME to (true to newFlags))
assertGroupPermState(newGroup2, expectedState2)
}
@@ -495,20 +569,28 @@ class GrantRevokeTests {
val pkg = createMockPackage(mapOf(FG_PERM_NAME to false, BG_PERM_NAME to false))
val perms = mutableMapOf<String, LightPermission>()
val origBgFlags = FLAG_PERMISSION_AUTO_REVOKED
- perms[FG_PERM_NAME] = createMockPerm(
- pkg, FG_PERM_NAME, BG_PERM_NAME, null, FLAG_PERMISSION_AUTO_REVOKED)
- perms[BG_PERM_NAME] = createMockPerm(
- pkg, BG_PERM_NAME, null, listOf(FG_PERM_NAME), origBgFlags)
+ perms[FG_PERM_NAME] =
+ createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME, null, FLAG_PERMISSION_AUTO_REVOKED)
+ perms[BG_PERM_NAME] =
+ createMockPerm(pkg, BG_PERM_NAME, null, listOf(FG_PERM_NAME), origBgFlags)
val group = createMockGroup(pkg, perms)
resetMockAppState()
KotlinUtils.grantForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = true, expectedFlags = newFlags)
- verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = false,
- expectedFlags = NO_FLAGS, originalFlags = origBgFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = true,
+ expectedFlags = newFlags
+ )
+ verifyPermissionState(
+ permName = BG_PERM_NAME,
+ expectPermChange = false,
+ expectedFlags = NO_FLAGS,
+ originalFlags = origBgFlags
+ )
}
/**
@@ -528,16 +610,24 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = true, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = true,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
- verifyPermissionState(permName = FG_PERM_2_NAME, expectPermChange = false,
- expectedFlags = permFlags, originalFlags = permFlags)
+ verifyPermissionState(
+ permName = FG_PERM_2_NAME,
+ expectPermChange = false,
+ expectedFlags = permFlags,
+ originalFlags = permFlags
+ )
verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
verifyAppKillState(shouldBeKilled = false)
- val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags),
- FG_PERM_2_NAME to (false to permFlags))
+ val expectedState =
+ mutableMapOf(FG_PERM_NAME to (true to newFlags), FG_PERM_2_NAME to (false to permFlags))
assertGroupPermState(newGroup, expectedState)
}
@@ -558,25 +648,33 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = true, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = true,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
verifyAppKillState(shouldBeKilled = false)
- var expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags),
- BG_PERM_NAME to (false to permFlags))
+ var expectedState =
+ mutableMapOf(FG_PERM_NAME to (true to newFlags), BG_PERM_NAME to (false to permFlags))
assertGroupPermState(newGroup, expectedState)
resetMockAppState()
val newGroup2 = KotlinUtils.grantBackgroundRuntimePermissions(app, newGroup)
- verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = false,
- expectedFlags = permFlags, originalFlags = permFlags)
+ verifyPermissionState(
+ permName = BG_PERM_NAME,
+ expectPermChange = false,
+ expectedFlags = permFlags,
+ originalFlags = permFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
verifyAppKillState(shouldBeKilled = false)
- expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags),
- BG_PERM_NAME to (false to permFlags))
+ expectedState =
+ mutableMapOf(FG_PERM_NAME to (true to newFlags), BG_PERM_NAME to (false to permFlags))
assertGroupPermState(newGroup2, expectedState)
}
@@ -596,8 +694,12 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
- expectedFlags = newFlags, originalFlags = oldFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = false,
+ expectedFlags = newFlags,
+ originalFlags = oldFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
verifyAppKillState(shouldBeKilled = false)
@@ -620,8 +722,12 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
- expectedFlags = newFlags, originalFlags = oldFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = false,
+ expectedFlags = newFlags,
+ originalFlags = oldFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
verifyAppKillState(shouldBeKilled = true)
@@ -643,8 +749,12 @@ class GrantRevokeTests {
resetMockAppState()
val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
- expectedFlags = flags, originalFlags = flags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = false,
+ expectedFlags = flags,
+ originalFlags = flags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
verifyAppKillState(shouldBeKilled = false)
@@ -652,9 +762,7 @@ class GrantRevokeTests {
assertGroupPermState(newGroup, expectedState)
}
- /**
- * Test that an instant app cannot have regular (non-instant) permission granted.
- */
+ /** Test that an instant app cannot have regular (non-instant) permission granted. */
@Test
fun cantGrantInstantAppStandardPermTest() {
val pkg = createMockPackage(mapOf(FG_PERM_NAME to false), isInstantApp = true)
@@ -680,8 +788,12 @@ class GrantRevokeTests {
fun cantGrantPreRuntimeAppWithRuntimeOnlyPermTest() {
val pkg = createMockPackage(mapOf(FG_PERM_NAME to false), isPreMApp = true)
val perms = mutableMapOf<String, LightPermission>()
- perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME,
- permInfoProtectionFlags = PROTECTION_FLAG_RUNTIME_ONLY)
+ perms[FG_PERM_NAME] =
+ createMockPerm(
+ pkg,
+ FG_PERM_NAME,
+ permInfoProtectionFlags = PROTECTION_FLAG_RUNTIME_ONLY
+ )
val group = createMockGroup(pkg, perms)
resetMockAppState()
@@ -695,23 +807,25 @@ class GrantRevokeTests {
assertGroupPermState(newGroup, expectedState)
}
- /**
- * Test that an instant package can have an instant permission granted.
- */
+ /** Test that an instant package can have an instant permission granted. */
@Test
fun grantInstantAppInstantPermTest() {
val pkg = createMockPackage(mapOf(FG_PERM_NAME to false), isInstantApp = true)
val perms = mutableMapOf<String, LightPermission>()
- perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME,
- permInfoProtectionFlags = PROTECTION_FLAG_INSTANT)
+ perms[FG_PERM_NAME] =
+ createMockPerm(pkg, FG_PERM_NAME, permInfoProtectionFlags = PROTECTION_FLAG_INSTANT)
val group = createMockGroup(pkg, perms)
resetMockAppState()
val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = true, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = true,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
verifyAppKillState(shouldBeKilled = false)
@@ -719,9 +833,7 @@ class GrantRevokeTests {
assertGroupPermState(newGroup, expectedState)
}
- /**
- * Test that granting a permission clears the user fixed and review required flags.
- */
+ /** Test that granting a permission clears the user fixed and review required flags. */
@Test
fun grantClearsUserFixedAndReviewRequired() {
val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
@@ -733,8 +845,12 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
- expectedFlags = newFlags, originalFlags = oldFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = false,
+ expectedFlags = newFlags,
+ originalFlags = oldFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
verifyAppKillState(shouldBeKilled = false)
@@ -742,9 +858,7 @@ class GrantRevokeTests {
assertGroupPermState(newGroup, expectedState)
}
- /**
- * Test revoking one foreground permission. The permission and app op should be revoked.
- */
+ /** Test revoking one foreground permission. The permission and app op should be revoked. */
@Test
fun revokeOnePermTest() {
val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
@@ -756,8 +870,12 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
verifyAppKillState(shouldBeKilled = false)
@@ -765,9 +883,7 @@ class GrantRevokeTests {
assertGroupPermState(newGroup, expectedState)
}
- /**
- * Test revoking two foreground permissions. Both permissions and app ops should be revoked.
- */
+ /** Test revoking two foreground permissions. Both permissions and app ops should be revoked. */
@Test
fun revokeTwoPermTest() {
val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, FG_PERM_2_NAME to true))
@@ -780,16 +896,24 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
- verifyPermissionState(permName = FG_PERM_2_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_2_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
verifyAppKillState(shouldBeKilled = false)
- val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags),
- FG_PERM_2_NAME to (false to newFlags))
+ val expectedState =
+ mutableMapOf(FG_PERM_NAME to (false to newFlags), FG_PERM_2_NAME to (false to newFlags))
assertGroupPermState(newGroup, expectedState)
}
@@ -807,8 +931,12 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME_NO_APP_OP, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME_NO_APP_OP,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
verifyAppKillState(shouldBeKilled = false)
@@ -834,13 +962,17 @@ class GrantRevokeTests {
val newFlags = FLAG_PERMISSION_USER_SET
verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
- verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = BG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
verifyAppKillState(shouldBeKilled = false)
- val expectedState = mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS),
- BG_PERM_NAME to (false to newFlags))
+ val expectedState =
+ mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS), BG_PERM_NAME to (false to newFlags))
assertGroupPermState(newGroup, expectedState)
}
@@ -861,24 +993,32 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, group, true)
val newFlags = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED
- verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = BG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
verifyAppKillState(shouldBeKilled = false)
- val expectedState = mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS),
- BG_PERM_NAME to (false to newFlags))
+ val expectedState =
+ mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS), BG_PERM_NAME to (false to newFlags))
assertGroupPermState(newGroup, expectedState)
resetMockAppState()
val newGroup2 = KotlinUtils.revokeForegroundRuntimePermissions(app, newGroup, true)
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
verifyAppKillState(shouldBeKilled = false)
- val expectedState2 = mutableMapOf(FG_PERM_NAME to (false to newFlags),
- BG_PERM_NAME to (false to newFlags))
+ val expectedState2 =
+ mutableMapOf(FG_PERM_NAME to (false to newFlags), BG_PERM_NAME to (false to newFlags))
assertGroupPermState(newGroup2, expectedState2)
}
@@ -899,15 +1039,19 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags
+ )
verifyPermissionState(permName = FG_PERM_2_NAME, expectPermChange = false)
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
verifyAppKillState(shouldBeKilled = false)
- val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags),
- FG_PERM_2_NAME to (true to permFlags))
+ val expectedState =
+ mutableMapOf(FG_PERM_NAME to (false to newFlags), FG_PERM_2_NAME to (true to permFlags))
assertGroupPermState(newGroup, expectedState)
}
@@ -928,13 +1072,17 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
verifyAppKillState(shouldBeKilled = false)
- var expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags),
- BG_PERM_NAME to (true to permFlags))
+ var expectedState =
+ mutableMapOf(FG_PERM_NAME to (false to newFlags), BG_PERM_NAME to (true to permFlags))
assertGroupPermState(newGroup, expectedState)
resetMockAppState()
@@ -944,14 +1092,14 @@ class GrantRevokeTests {
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
verifyAppKillState(shouldBeKilled = false)
- expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags),
- BG_PERM_NAME to (true to permFlags))
+ expectedState =
+ mutableMapOf(FG_PERM_NAME to (false to newFlags), BG_PERM_NAME to (true to permFlags))
assertGroupPermState(newGroup2, expectedState)
}
/**
- * Test revoking a one time granted permission. The permission should be revoked, but no
- * longer be one time.
+ * Test revoking a one time granted permission. The permission should be revoked, but no longer
+ * be one time.
*/
@Test
fun revokeOneTimeTest() {
@@ -965,8 +1113,13 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags, originalFlags = oldFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags,
+ originalFlags = oldFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
verifyAppKillState(shouldBeKilled = false)
@@ -975,8 +1128,8 @@ class GrantRevokeTests {
}
/**
- * Test compat revoking (permission granted, app op denied) permission. The app op
- * should be revoked, while the permission remains granted. The app should also be killed.
+ * Test compat revoking (permission granted, app op denied) permission. The app op should be
+ * revoked, while the permission remains granted. The app should also be killed.
*/
@Test
fun revokePreMAppTest() {
@@ -989,8 +1142,11 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_REVOKED_COMPAT
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
- expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = false,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
verifyAppKillState(shouldBeKilled = true)
@@ -1036,8 +1192,12 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group, true)
val newFlags = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
verifyAppKillState(shouldBeKilled = false)
@@ -1062,8 +1222,13 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags, originalFlags = oldFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags,
+ originalFlags = oldFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
verifyAppKillState(shouldBeKilled = false)
@@ -1087,8 +1252,13 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group, true)
val newFlags = oldFlags or FLAG_PERMISSION_USER_FIXED
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
- expectPermGranted = false, expectedFlags = newFlags, originalFlags = oldFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = true,
+ expectPermGranted = false,
+ expectedFlags = newFlags,
+ originalFlags = oldFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
verifyAppKillState(shouldBeKilled = false)
@@ -1097,8 +1267,8 @@ class GrantRevokeTests {
}
/**
- * Test revoking an already revoked permission, while changing its user fixed state from true
- * to false. The user fixed should update, but the state should stay the same otherwise.
+ * Test revoking an already revoked permission, while changing its user fixed state from true to
+ * false. The user fixed should update, but the state should stay the same otherwise.
*/
@Test
fun changeUserFixedTest() {
@@ -1112,8 +1282,12 @@ class GrantRevokeTests {
val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
val newFlags = FLAG_PERMISSION_USER_SET
- verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
- expectedFlags = newFlags, originalFlags = oldFlags)
+ verifyPermissionState(
+ permName = FG_PERM_NAME,
+ expectPermChange = false,
+ expectedFlags = newFlags,
+ originalFlags = oldFlags
+ )
verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
verifyAppKillState(shouldBeKilled = false)
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/StringUtilsTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/StringUtilsTest.kt
index 178f5d56b..02308f750 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/StringUtilsTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/StringUtilsTest.kt
@@ -16,62 +16,64 @@
package com.android.permissioncontroller.tests.mocking.permission.utils
-import com.android.permissioncontroller.R
-import com.android.permissioncontroller.permission.utils.StringUtils
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.utils.StringUtils
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * A suite of unit tests to test the permission dashboard utils.
- */
+/** A suite of unit tests to test the permission dashboard utils. */
@RunWith(AndroidJUnit4::class)
class StringUtilsTest {
@Test
fun getIcuPluralsString_one_noArguments() {
assertThat(
- StringUtils.getIcuPluralsString(
- ApplicationProvider.getApplicationContext(),
- R.string.test_icu_plural,
- 1
+ StringUtils.getIcuPluralsString(
+ ApplicationProvider.getApplicationContext(),
+ R.string.test_icu_plural,
+ 1
+ )
)
- ).isEqualTo("1 test")
+ .isEqualTo("1 test")
}
@Test
fun getIcuPluralsString_other_noArguments() {
assertThat(
- StringUtils.getIcuPluralsString(
- ApplicationProvider.getApplicationContext(),
- R.string.test_icu_plural,
- 2
+ StringUtils.getIcuPluralsString(
+ ApplicationProvider.getApplicationContext(),
+ R.string.test_icu_plural,
+ 2
+ )
)
- ).isEqualTo("2 tests")
+ .isEqualTo("2 tests")
}
@Test
fun getIcuPluralsString_one_additionalArguments() {
assertThat(
- StringUtils.getIcuPluralsString(
- ApplicationProvider.getApplicationContext(),
- R.string.test_icu_plural_with_argument,
- 1,
- "with argument"
+ StringUtils.getIcuPluralsString(
+ ApplicationProvider.getApplicationContext(),
+ R.string.test_icu_plural_with_argument,
+ 1,
+ "with argument"
+ )
)
- ).isEqualTo("1 test with argument")
+ .isEqualTo("1 test with argument")
}
@Test
fun getIcuPluralsString_other_additionalArguments() {
assertThat(
- StringUtils.getIcuPluralsString(
- ApplicationProvider.getApplicationContext(),
- R.string.test_icu_plural_with_argument,
- 2,
- "with argument"
+ StringUtils.getIcuPluralsString(
+ ApplicationProvider.getApplicationContext(),
+ R.string.test_icu_plural_with_argument,
+ 2,
+ "with argument"
+ )
)
- ).isEqualTo("2 tests with argument")
+ .isEqualTo("2 tests with argument")
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/AccessibilitySourceServiceTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/AccessibilitySourceServiceTest.kt
index 2fcf4a24d..f794ab0d3 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/AccessibilitySourceServiceTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/AccessibilitySourceServiceTest.kt
@@ -33,8 +33,8 @@ import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Before
-import org.junit.runner.RunWith
import org.junit.Test
+import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
@@ -53,8 +53,7 @@ import org.mockito.quality.Strictness
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
class AccessibilitySourceServiceTest {
- @Mock
- lateinit var jobService: AccessibilityJobService
+ @Mock lateinit var jobService: AccessibilityJobService
private lateinit var context: Context
private lateinit var mockitoSession: MockitoSession
private lateinit var accessibilitySourceService: AccessibilitySourceService
@@ -66,9 +65,11 @@ class AccessibilitySourceServiceTest {
MockitoAnnotations.initMocks(this)
context = ApplicationProvider.getApplicationContext()
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(DeviceConfig::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(DeviceConfig::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
accessibilitySourceService = runWithShellPermissionIdentity {
AccessibilitySourceService(context)
@@ -91,10 +92,9 @@ class AccessibilitySourceServiceTest {
runWithShellPermissionIdentity {
runBlocking {
- accessibilitySourceService.processAccessibilityJob(
- jobParameters,
- jobService
- ) { shouldCancel }
+ accessibilitySourceService.processAccessibilityJob(jobParameters, jobService) {
+ shouldCancel
+ }
}
}
verify(jobService).jobFinished(jobParameters, true)
@@ -103,9 +103,7 @@ class AccessibilitySourceServiceTest {
@Test
fun markServiceAsNotified() {
val a11yService = ComponentName("com.test.package", "AccessibilityService")
- runBlocking {
- accessibilitySourceService.markServiceAsNotified(a11yService)
- }
+ runBlocking { accessibilitySourceService.markServiceAsNotified(a11yService) }
val storedServices = getNotifiedServices()
assertThat(storedServices.size).isEqualTo(1)
@@ -143,9 +141,7 @@ class AccessibilitySourceServiceTest {
val allServices = listOf(a11yService, a11yService2, a11yService3)
val notifiedServices = runBlocking {
- allServices.forEach {
- accessibilitySourceService.markServiceAsNotified(it)
- }
+ allServices.forEach { accessibilitySourceService.markServiceAsNotified(it) }
accessibilitySourceService.removeFromNotifiedServices(a11yService2)
getNotifiedServices()
}
@@ -164,9 +160,7 @@ class AccessibilitySourceServiceTest {
val testComponents = listOf(testComponent, testComponent2, testComponent3)
val notifiedServices = runBlocking {
- testComponents.forEach {
- accessibilitySourceService.markServiceAsNotified(it)
- }
+ testComponents.forEach { accessibilitySourceService.markServiceAsNotified(it) }
accessibilitySourceService.removePackageState(testComponent.packageName)
getNotifiedServices()
}
@@ -182,9 +176,7 @@ class AccessibilitySourceServiceTest {
val testComponents = listOf(testComponent, testComponent2)
val notifiedServices = runBlocking {
- testComponents.forEach {
- accessibilitySourceService.markServiceAsNotified(it)
- }
+ testComponents.forEach { accessibilitySourceService.markServiceAsNotified(it) }
accessibilitySourceService.removePackageState(testComponent.packageName)
getNotifiedServices()
}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/AppDataSharingUpdatesPrivacySourceTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/AppDataSharingUpdatesPrivacySourceTest.kt
index b1b5694ff..d09b5093f 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/AppDataSharingUpdatesPrivacySourceTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/AppDataSharingUpdatesPrivacySourceTest.kt
@@ -82,7 +82,10 @@ class AppDataSharingUpdatesPrivacySourceTest {
.startMocking()
whenever(
Utils.getSystemServiceSafe(
- any(ContextWrapper::class.java), eq(SafetyCenterManager::class.java)))
+ any(ContextWrapper::class.java),
+ eq(SafetyCenterManager::class.java)
+ )
+ )
.thenReturn(mockSafetyCenterManager)
appDataSharingUpdatesPrivacySource = AppDataSharingUpdatesPrivacySource()
@@ -116,7 +119,10 @@ class AppDataSharingUpdatesPrivacySourceTest {
.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_ID)
appDataSharingUpdatesPrivacySource.rescanAndPushSafetyCenterData(
- context, refreshIntent, EVENT_REFRESH_REQUESTED)
+ context,
+ refreshIntent,
+ EVENT_REFRESH_REQUESTED
+ )
val expectedSafetySourceData: SafetySourceData =
SafetySourceData.Builder()
@@ -124,14 +130,18 @@ class AppDataSharingUpdatesPrivacySourceTest {
SafetySourceStatus.Builder(
DATA_SHARING_UPDATES_TITLE,
DATA_SHARING_UPDATES_SUMMARY,
- SafetySourceData.SEVERITY_LEVEL_INFORMATION)
+ SafetySourceData.SEVERITY_LEVEL_INFORMATION
+ )
.setPendingIntent(
PendingIntent.getActivity(
context,
/* requestCode= */ 0,
Intent(ACTION_REVIEW_APP_DATA_SHARING_UPDATES),
- FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE))
- .build())
+ FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
+ )
+ )
+ .build()
+ )
.build()
val expectedSafetyEvent =
SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
@@ -139,7 +149,10 @@ class AppDataSharingUpdatesPrivacySourceTest {
.build()
verify(mockSafetyCenterManager)
.setSafetySourceData(
- APP_DATA_SHARING_UPDATES_SOURCE_ID, expectedSafetySourceData, expectedSafetyEvent)
+ APP_DATA_SHARING_UPDATES_SOURCE_ID,
+ expectedSafetySourceData,
+ expectedSafetyEvent
+ )
}
@Test
@@ -148,7 +161,10 @@ class AppDataSharingUpdatesPrivacySourceTest {
val bootCompleteIntent = Intent(ACTION_BOOT_COMPLETED)
appDataSharingUpdatesPrivacySource.rescanAndPushSafetyCenterData(
- context, bootCompleteIntent, EVENT_DEVICE_REBOOTED)
+ context,
+ bootCompleteIntent,
+ EVENT_DEVICE_REBOOTED
+ )
val expectedSafetyEvent = SafetyEvent.Builder(SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build()
verify(mockSafetyCenterManager)
@@ -163,7 +179,10 @@ class AppDataSharingUpdatesPrivacySourceTest {
.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_ID)
appDataSharingUpdatesPrivacySource.rescanAndPushSafetyCenterData(
- context, refreshIntent, EVENT_REFRESH_REQUESTED)
+ context,
+ refreshIntent,
+ EVENT_REFRESH_REQUESTED
+ )
val expectedSafetyEvent =
SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
@@ -190,7 +209,9 @@ class AppDataSharingUpdatesPrivacySourceTest {
DeviceConfig.getBoolean(
eq(NAMESPACE_PRIVACY),
eq(SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED),
- anyBoolean()))
+ anyBoolean()
+ )
+ )
.thenReturn(enabled)
}
}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerCheckInternalTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerCheckInternalTest.kt
index 6f1d2c5c9..bc00d3bc8 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerCheckInternalTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerCheckInternalTest.kt
@@ -95,7 +95,9 @@ class NotificationListenerCheckInternalTest {
// Setup Safety Center
doReturn(mockSafetyCenterManager).`when` {
Utils.getSystemServiceSafe(
- any(ContextWrapper::class.java), eq(SafetyCenterManager::class.java))
+ any(ContextWrapper::class.java),
+ eq(SafetyCenterManager::class.java)
+ )
}
notificationListenerCheck = runWithShellPermissionIdentity {
@@ -121,7 +123,9 @@ class NotificationListenerCheckInternalTest {
runWithShellPermissionIdentity {
runBlocking {
notificationListenerCheck.getEnabledNotificationListenersAndNotifyIfNeeded(
- jobParameters, mockNotificationListenerCheckJobService)
+ jobParameters,
+ mockNotificationListenerCheckJobService
+ )
}
}
@@ -135,7 +139,9 @@ class NotificationListenerCheckInternalTest {
runWithShellPermissionIdentity {
runBlocking {
notificationListenerCheck.getEnabledNotificationListenersAndNotifyIfNeeded(
- jobParameters, mockNotificationListenerCheckJobService)
+ jobParameters,
+ mockNotificationListenerCheckJobService
+ )
}
}
@@ -149,7 +155,9 @@ class NotificationListenerCheckInternalTest {
runWithShellPermissionIdentity {
runBlocking {
notificationListenerCheck.getEnabledNotificationListenersAndNotifyIfNeeded(
- jobParameters, mockNotificationListenerCheckJobService)
+ jobParameters,
+ mockNotificationListenerCheckJobService
+ )
}
}
@@ -157,7 +165,8 @@ class NotificationListenerCheckInternalTest {
.setSafetySourceData(
eq(SC_NLS_SOURCE_ID),
any(SafetySourceData::class.java),
- any(SafetyEvent::class.java))
+ any(SafetyEvent::class.java)
+ )
}
@Test
@@ -185,7 +194,8 @@ class NotificationListenerCheckInternalTest {
val updatedNlsComponents = runWithShellPermissionIdentity {
runBlocking {
notificationListenerCheck.removeDisabledComponentsFromNotifiedComponents(
- updatedEnabledComponents)
+ updatedEnabledComponents
+ )
getNotifiedComponents()
}
}
@@ -445,7 +455,9 @@ class NotificationListenerCheckInternalTest {
val testAppLabel = "TestApp Label"
doReturn(PackageInfo().apply { applicationInfo = ApplicationInfo() }).`when` {
Utils.getPackageInfoForComponentName(
- any(Context::class.java), any(ComponentName::class.java))
+ any(Context::class.java),
+ any(ComponentName::class.java)
+ )
}
doReturn(testAppLabel).`when` {
Utils.getApplicationLabel(any(Context::class.java), any(ApplicationInfo::class.java))
@@ -453,7 +465,8 @@ class NotificationListenerCheckInternalTest {
val safetySourceIssue =
Preconditions.checkNotNull(
- notificationListenerCheck.createSafetySourceIssue(testComponent, 0))
+ notificationListenerCheck.createSafetySourceIssue(testComponent, 0)
+ )
val expectedId = "notification_listener_${testComponent.flattenToString()}"
val expectedTitle =
@@ -470,21 +483,28 @@ class NotificationListenerCheckInternalTest {
}
val expectedDismissPendingIntent =
PendingIntent.getBroadcast(
- context, 0, expectedDismissIntent, PendingIntent.FLAG_IMMUTABLE)
+ context,
+ 0,
+ expectedDismissIntent,
+ PendingIntent.FLAG_IMMUTABLE
+ )
val expectedAction1 =
SafetySourceIssue.Action.Builder(
SC_NLS_DISABLE_ACTION_ID,
context.getString(R.string.notification_listener_remove_access_button_label),
- getDisableNlsPendingIntent(context, expectedId, testComponent))
+ getDisableNlsPendingIntent(context, expectedId, testComponent)
+ )
.setWillResolve(true)
.setSuccessMessage(
- context.getString(R.string.notification_listener_remove_access_success_label))
+ context.getString(R.string.notification_listener_remove_access_success_label)
+ )
.build()
val expectedAction2 =
SafetySourceIssue.Action.Builder(
NotificationListenerCheckInternal.SC_SHOW_NLS_SETTINGS_ACTION_ID,
context.getString(R.string.notification_listener_review_app_button_label),
- getNotificationListenerSettingsPendingIntent(context, testComponent))
+ getNotificationListenerSettingsPendingIntent(context, testComponent)
+ )
.build()
assertThat(safetySourceIssue.id).isEqualTo(expectedId)
@@ -501,9 +521,7 @@ class NotificationListenerCheckInternalTest {
@Test
fun exemptPackagesNotInitializedUntilUsed() {
assertThat(notificationListenerCheck.exemptPackagesDelegate.isInitialized()).isFalse()
- runWithShellPermissionIdentity {
- notificationListenerCheck.exemptPackages
- }
+ runWithShellPermissionIdentity { notificationListenerCheck.exemptPackages }
assertThat(notificationListenerCheck.exemptPackagesDelegate.isInitialized()).isTrue()
}
@@ -542,7 +560,8 @@ class NotificationListenerCheckInternalTest {
identifier = componentName.flattenToString()
putExtra(
Settings.EXTRA_NOTIFICATION_LISTENER_COMPONENT_NAME,
- componentName.flattenToString())
+ componentName.flattenToString()
+ )
}
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerPregrantsTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerPregrantsTest.kt
index d8d4b3866..55419ca3d 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerPregrantsTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerPregrantsTest.kt
@@ -47,9 +47,11 @@ class NotificationListenerPregrantsTest {
MockitoAnnotations.initMocks(this)
context = ApplicationProvider.getApplicationContext()
- mockitoSession = ExtendedMockito.mockitoSession()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
.mockStatic(Utils::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ .strictness(Strictness.LENIENT)
+ .startMocking()
notificationListenerPregrants = NotificationListenerPregrants(context)
}
@@ -71,4 +73,4 @@ class NotificationListenerPregrantsTest {
notificationListenerPregrants.pregrantedPackages
assertTrue(notificationListenerPregrants.pregrantedPackagesDelegate.isInitialized())
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerPrivacySourceTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerPrivacySourceTest.kt
index 9c1edb795..30f0880e1 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerPrivacySourceTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/NotificationListenerPrivacySourceTest.kt
@@ -37,10 +37,10 @@ import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.permissioncontroller.Constants.NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID
-import com.android.permissioncontroller.permission.utils.Utils
import com.android.permissioncontroller.PermissionControllerApplication
-import com.android.permissioncontroller.privacysources.NotificationListenerPrivacySource
+import com.android.permissioncontroller.permission.utils.Utils
import com.android.permissioncontroller.privacysources.NotificationListenerCheckInternal
+import com.android.permissioncontroller.privacysources.NotificationListenerPrivacySource
import com.android.permissioncontroller.privacysources.PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED
import com.android.permissioncontroller.privacysources.SC_NLS_SOURCE_ID
import com.android.permissioncontroller.privacysources.SafetyCenterReceiver
@@ -53,27 +53,23 @@ import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyString
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
-import org.mockito.MockitoAnnotations
-import org.mockito.MockitoSession
-import org.mockito.quality.Strictness
import org.mockito.Mockito.never
-import org.mockito.Mockito.`when` as whenever
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+import org.mockito.MockitoSession
+import org.mockito.quality.Strictness
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
class NotificationListenerPrivacySourceTest {
private lateinit var mockitoSession: MockitoSession
- @Mock
- lateinit var mockSafetyCenterManager: SafetyCenterManager
- @Mock
- lateinit var mockNotificationManager: NotificationManager
- @Mock
- lateinit var mockRoleManager: RoleManager
- @Mock
- lateinit var mockUserManager: UserManager
+ @Mock lateinit var mockSafetyCenterManager: SafetyCenterManager
+ @Mock lateinit var mockNotificationManager: NotificationManager
+ @Mock lateinit var mockRoleManager: RoleManager
+ @Mock lateinit var mockUserManager: UserManager
private lateinit var context: Context
private lateinit var notificationListenerCheck: NotificationListenerCheckInternal
@@ -92,66 +88,89 @@ class NotificationListenerPrivacySourceTest {
MockitoAnnotations.initMocks(this)
context = ApplicationProvider.getApplicationContext()
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(DeviceConfig::class.java)
- .mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(Utils::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(DeviceConfig::class.java)
+ .mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(Utils::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
// Setup default flagging
setNotificationListenerCheckEnabled(true)
// Setup contexts
- whenever(Utils.getParentUserContext(any(ContextWrapper::class.java)))
- .thenReturn(context)
+ whenever(Utils.getParentUserContext(any(ContextWrapper::class.java))).thenReturn(context)
// Setup package manager and mocked NLS packages
val packageInfo1 = getPackageInfo()
val packageInfo2 = getPackageInfo()
- whenever(Utils.getPackageInfoForComponentName(
- any(ContextWrapper::class.java),
- eq(testComponent1)))
+ whenever(
+ Utils.getPackageInfoForComponentName(
+ any(ContextWrapper::class.java),
+ eq(testComponent1)
+ )
+ )
.thenReturn(packageInfo1)
- whenever(Utils.getPackageInfoForComponentName(
- any(ContextWrapper::class.java),
- eq(testComponent2)))
+ whenever(
+ Utils.getPackageInfoForComponentName(
+ any(ContextWrapper::class.java),
+ eq(testComponent2)
+ )
+ )
.thenReturn(packageInfo2)
- whenever(Utils.getApplicationLabel(
- any(ContextWrapper::class.java),
- eq(packageInfo1.applicationInfo)))
+ whenever(
+ Utils.getApplicationLabel(
+ any(ContextWrapper::class.java),
+ eq(packageInfo1.applicationInfo)
+ )
+ )
.thenReturn(testComponent1.className)
- whenever(Utils.getApplicationLabel(
- any(ContextWrapper::class.java),
- eq(packageInfo2.applicationInfo)))
+ whenever(
+ Utils.getApplicationLabel(
+ any(ContextWrapper::class.java),
+ eq(packageInfo2.applicationInfo)
+ )
+ )
.thenReturn(testComponent2.className)
// Setup UserManager and User
- whenever(Utils.getSystemServiceSafe(
- any(ContextWrapper::class.java),
- eq(UserManager::class.java)))
+ whenever(
+ Utils.getSystemServiceSafe(
+ any(ContextWrapper::class.java),
+ eq(UserManager::class.java)
+ )
+ )
.thenReturn(mockUserManager)
- whenever(mockUserManager.getProfileParent(any(UserHandle::class.java)))
- .thenReturn(null)
+ whenever(mockUserManager.getProfileParent(any(UserHandle::class.java))).thenReturn(null)
// Setup Notification Manager
- whenever(Utils.getSystemServiceSafe(
- any(ContextWrapper::class.java),
- eq(NotificationManager::class.java)))
+ whenever(
+ Utils.getSystemServiceSafe(
+ any(ContextWrapper::class.java),
+ eq(NotificationManager::class.java)
+ )
+ )
.thenReturn(mockNotificationManager)
whenever(mockNotificationManager.enabledNotificationListeners)
.thenReturn(listOf(testComponent1, testComponent2))
- whenever(Utils.getSystemServiceSafe(
- any(ContextWrapper::class.java),
- eq(RoleManager::class.java)))
+ whenever(
+ Utils.getSystemServiceSafe(
+ any(ContextWrapper::class.java),
+ eq(RoleManager::class.java)
+ )
+ )
.thenReturn(mockRoleManager)
- whenever(mockRoleManager.getRoleHolders(anyString()))
- .thenReturn(emptyList())
+ whenever(mockRoleManager.getRoleHolders(anyString())).thenReturn(emptyList())
// Setup Safety Center
- whenever(Utils.getSystemServiceSafe(
- any(ContextWrapper::class.java),
- eq(SafetyCenterManager::class.java)))
+ whenever(
+ Utils.getSystemServiceSafe(
+ any(ContextWrapper::class.java),
+ eq(SafetyCenterManager::class.java)
+ )
+ )
.thenReturn(mockSafetyCenterManager)
// Init NotificationListenerCheckInternal, used to quickly create expected SafetySourceData
@@ -167,24 +186,21 @@ class NotificationListenerPrivacySourceTest {
@Test
fun safetyCenterEnabledChanged_removesNotifications() {
- runWithShellPermissionIdentity {
- privacySource.safetyCenterEnabledChanged(context, false)
- }
+ runWithShellPermissionIdentity { privacySource.safetyCenterEnabledChanged(context, false) }
verify(mockNotificationManager).cancel(NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID)
}
@Test
fun safetyCenterEnabledChanged_doesNotUpdateSafetyCenterData() {
- runWithShellPermissionIdentity {
- privacySource.safetyCenterEnabledChanged(context, false)
- }
+ runWithShellPermissionIdentity { privacySource.safetyCenterEnabledChanged(context, false) }
verify(mockSafetyCenterManager, never())
.setSafetySourceData(
eq(SC_NLS_SOURCE_ID),
any(SafetySourceData::class.java),
- any(SafetyEvent::class.java))
+ any(SafetyEvent::class.java)
+ )
}
@Test
@@ -209,18 +225,17 @@ class NotificationListenerPrivacySourceTest {
SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build()
verify(mockSafetyCenterManager)
- .setSafetySourceData(
- SC_NLS_SOURCE_ID,
- expectedSafetySourceData,
- expectedSafetyEvent
- )
+ .setSafetySourceData(SC_NLS_SOURCE_ID, expectedSafetySourceData, expectedSafetyEvent)
}
@Test
fun rescanAndPushSafetyCenterData_updatesSafetyCenterEventRefresh() {
- val intent = Intent(SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES)
- .putExtra(SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID,
- SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID)
+ val intent =
+ Intent(SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES)
+ .putExtra(
+ SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID,
+ SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
+ )
privacySource.rescanAndPushSafetyCenterData(
context,
intent,
@@ -237,11 +252,7 @@ class NotificationListenerPrivacySourceTest {
.build()
verify(mockSafetyCenterManager)
- .setSafetySourceData(
- SC_NLS_SOURCE_ID,
- expectedSafetySourceData,
- expectedSafetyEvent
- )
+ .setSafetySourceData(SC_NLS_SOURCE_ID, expectedSafetySourceData, expectedSafetyEvent)
}
@Test
@@ -257,16 +268,11 @@ class NotificationListenerPrivacySourceTest {
SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
verify(mockSafetyCenterManager)
- .setSafetySourceData(
- SC_NLS_SOURCE_ID,
- expectedSafetySourceData,
- expectedSafetyEvent
- )
+ .setSafetySourceData(SC_NLS_SOURCE_ID, expectedSafetySourceData, expectedSafetyEvent)
}
@Test
- fun rescanAndPushSafetyCenterData_notificationListenerCheckDisabled_noSafetyCenterInteractions
- () {
+ fun rescanAndPushSafetyCenterData_notificationListenerCheckDisabled_noSafetyCenterInteractions() {
setNotificationListenerCheckEnabled(false)
privacySource.rescanAndPushSafetyCenterData(
@@ -280,18 +286,17 @@ class NotificationListenerPrivacySourceTest {
private fun setNotificationListenerCheckEnabled(enabled: Boolean) {
whenever(
- DeviceConfig.getBoolean(
- eq(DeviceConfig.NAMESPACE_PRIVACY),
- eq(PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED),
- anyBoolean()
+ DeviceConfig.getBoolean(
+ eq(DeviceConfig.NAMESPACE_PRIVACY),
+ eq(PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED),
+ anyBoolean()
+ )
)
- ).thenReturn(enabled)
+ .thenReturn(enabled)
}
private fun getPackageInfo(): PackageInfo {
- return PackageInfo().apply {
- applicationInfo = ApplicationInfo()
- }
+ return PackageInfo().apply { applicationInfo = ApplicationInfo() }
}
private fun createExpectedSafetyCenterData(): SafetySourceData {
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/SafetyCenterReceiverTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/SafetyCenterReceiverTest.kt
index b4b1abd96..6a45ac7c4 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/SafetyCenterReceiverTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/SafetyCenterReceiverTest.kt
@@ -38,7 +38,6 @@ import com.android.permissioncontroller.privacysources.PrivacySource
import com.android.permissioncontroller.privacysources.SafetyCenterReceiver
import com.android.permissioncontroller.privacysources.SafetyCenterReceiver.RefreshEvent.EVENT_DEVICE_REBOOTED
import com.android.permissioncontroller.privacysources.SafetyCenterReceiver.RefreshEvent.EVENT_REFRESH_REQUESTED
-import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
@@ -48,7 +47,6 @@ import kotlinx.coroutines.test.runBlockingTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
-import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers
@@ -56,16 +54,14 @@ import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito
-import org.mockito.Mockito.`when` as whenever
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-/**
- * Unit tests for [SafetyCenterReceiver]
- */
+/** Unit tests for [SafetyCenterReceiver] */
@ExperimentalCoroutinesApi
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
@@ -80,48 +76,50 @@ class SafetyCenterReceiverTest {
private val testCoroutineDispatcher = TestCoroutineDispatcher()
- @Mock
- lateinit var mockSafetyCenterManager: SafetyCenterManager
- @Mock
- lateinit var mockPackageManager: PackageManager
- @Mock
- lateinit var mockPrivacySource: PrivacySource
- @Mock
- lateinit var mockPrivacySource2: PrivacySource
- @Mock
- lateinit var mockUserManager: UserManager
+ @Mock lateinit var mockSafetyCenterManager: SafetyCenterManager
+ @Mock lateinit var mockPackageManager: PackageManager
+ @Mock lateinit var mockPrivacySource: PrivacySource
+ @Mock lateinit var mockPrivacySource2: PrivacySource
+ @Mock lateinit var mockUserManager: UserManager
private lateinit var mockitoSession: MockitoSession
private lateinit var safetyCenterReceiver: SafetyCenterReceiver
- private fun privacySourceMap(context: Context) = mapOf(
- TEST_PRIVACY_SOURCE_ID to mockPrivacySource,
- TEST_PRIVACY_SOURCE_ID_2 to mockPrivacySource2
- )
+ private fun privacySourceMap(context: Context) =
+ mapOf(
+ TEST_PRIVACY_SOURCE_ID to mockPrivacySource,
+ TEST_PRIVACY_SOURCE_ID_2 to mockPrivacySource2
+ )
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(DeviceConfig::class.java)
- .mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(Utils::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(DeviceConfig::class.java)
+ .mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(Utils::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
whenever(PermissionControllerApplication.get()).thenReturn(application)
whenever(application.applicationContext).thenReturn(application)
whenever(application.packageManager).thenReturn(mockPackageManager)
whenever(mockSafetyCenterManager.isSafetyCenterEnabled).thenReturn(true)
whenever(
- Utils.getSystemServiceSafe(
- any(ContextWrapper::class.java), eq(UserManager::class.java)
- ))
+ Utils.getSystemServiceSafe(
+ any(ContextWrapper::class.java),
+ eq(UserManager::class.java)
+ )
+ )
.thenReturn(mockUserManager)
whenever(
- Utils.getSystemServiceSafe(
- any(ContextWrapper::class.java), eq(SafetyCenterManager::class.java)
- ))
+ Utils.getSystemServiceSafe(
+ any(ContextWrapper::class.java),
+ eq(SafetyCenterManager::class.java)
+ )
+ )
.thenReturn(mockSafetyCenterManager)
whenever(mockUserManager.isProfile).thenReturn(false)
@@ -140,12 +138,13 @@ class SafetyCenterReceiverTest {
private fun mockQSTileSettingsFlag() {
whenever(
- DeviceConfig.getInt(
- eq(DeviceConfig.NAMESPACE_PRIVACY),
- eq(SafetyCenterQsTileService.QS_TILE_COMPONENT_SETTING_FLAGS),
- ArgumentMatchers.anyInt()
+ DeviceConfig.getInt(
+ eq(DeviceConfig.NAMESPACE_PRIVACY),
+ eq(SafetyCenterQsTileService.QS_TILE_COMPONENT_SETTING_FLAGS),
+ ArgumentMatchers.anyInt()
+ )
)
- ).thenReturn(PackageManager.DONT_KILL_APP)
+ .thenReturn(PackageManager.DONT_KILL_APP)
}
@Test
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/TextStorageRepositoryTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/TextStorageRepositoryTest.kt
index 15b9168ad..6c824122c 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/TextStorageRepositoryTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/TextStorageRepositoryTest.kt
@@ -25,6 +25,9 @@ import androidx.test.filters.SdkSuppress
import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.permissioncontroller.privacysources.PrivacySourceData
import com.android.permissioncontroller.privacysources.TextStorageRepository
+import java.io.BufferedWriter
+import java.io.File
+import java.io.FileWriter
import org.junit.After
import org.junit.Assert
import org.junit.Before
@@ -33,9 +36,6 @@ import org.junit.runner.RunWith
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-import java.io.BufferedWriter
-import java.io.File
-import java.io.FileWriter
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
@@ -50,9 +50,11 @@ class TextStorageRepositoryTest {
MockitoAnnotations.initMocks(this)
context = ApplicationProvider.getApplicationContext()
- mockitoSession = ExtendedMockito.mockitoSession()
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
.mockStatic(DeviceConfig::class.java)
- .strictness(Strictness.LENIENT).startMocking()
+ .strictness(Strictness.LENIENT)
+ .startMocking()
dataFile = context.getFileStreamPath("testFile")
}
@@ -83,10 +85,12 @@ class TextStorageRepositoryTest {
@Test
fun testWrite_MultipleEntries() {
val storageRepository = TextStorageRepository(dataFile)
- val components = listOf(TestPrivacySourceComponent("a", 100),
+ val components =
+ listOf(
+ TestPrivacySourceComponent("a", 100),
TestPrivacySourceComponent("b", 200),
TestPrivacySourceComponent("c", 300)
- )
+ )
storageRepository.persistData(components)
val dataList = storageRepository.readData(creator)
Assert.assertEquals(3, dataList.size)
@@ -95,10 +99,12 @@ class TextStorageRepositoryTest {
@Test
fun testRead_Ignore_CorruptedEntries() {
val storageRepository = TextStorageRepository(dataFile)
- val components = listOf(TestPrivacySourceComponent("a", 100),
- TestPrivacySourceComponent("b", 200),
- TestPrivacySourceComponent("c", 300)
- )
+ val components =
+ listOf(
+ TestPrivacySourceComponent("a", 100),
+ TestPrivacySourceComponent("b", 200),
+ TestPrivacySourceComponent("c", 300)
+ )
storageRepository.persistData(components)
appendCorruptedData(dataFile, "not_enough_parts")
appendCorruptedData(dataFile, "not_enough_parts")
@@ -110,9 +116,8 @@ class TextStorageRepositoryTest {
@Test
fun testRead_Ignore_NumberFormatError() {
val storageRepository = TextStorageRepository(dataFile)
- val components = listOf(TestPrivacySourceComponent("a", 100),
- TestPrivacySourceComponent("b", 200)
- )
+ val components =
+ listOf(TestPrivacySourceComponent("a", 100), TestPrivacySourceComponent("b", 200))
storageRepository.persistData(components)
appendCorruptedData(dataFile, "com.example.TestService hundred")
appendCorruptedData(dataFile, "com.example.TestService1 abc")
@@ -128,19 +133,18 @@ class TextStorageRepositoryTest {
}
}
- private val creator = object : PrivacySourceData.Creator<TestPrivacySourceComponent> {
- override fun fromStorageData(data: String): TestPrivacySourceComponent {
- val lineComponents = data.split(" ")
- return TestPrivacySourceComponent(lineComponents[0], lineComponents[1].toInt())
+ private val creator =
+ object : PrivacySourceData.Creator<TestPrivacySourceComponent> {
+ override fun fromStorageData(data: String): TestPrivacySourceComponent {
+ val lineComponents = data.split(" ")
+ return TestPrivacySourceComponent(lineComponents[0], lineComponents[1].toInt())
+ }
}
- }
}
-class TestPrivacySourceComponent(
- private val name: String,
- private val timestamp: Int
-) : PrivacySourceData {
+class TestPrivacySourceComponent(private val name: String, private val timestamp: Int) :
+ PrivacySourceData {
override fun toStorageData(): String {
return "$name $timestamp"
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/WorkPolicyInfoTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/WorkPolicyInfoTest.kt
index 3e86d58b0..bbbf0e86a 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/WorkPolicyInfoTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/privacysources/WorkPolicyInfoTest.kt
@@ -85,24 +85,34 @@ class WorkPolicyInfoTest {
val application = Mockito.mock(PermissionControllerApplication::class.java)
whenever(
Utils.getSystemServiceSafe(
- any(ContextWrapper::class.java), eq(UserManager::class.java)))
+ any(ContextWrapper::class.java),
+ eq(UserManager::class.java)
+ )
+ )
.thenReturn(mockUserManager)
whenever(
Utils.getSystemServiceSafe(
- any(ContextWrapper::class.java), eq(SafetyCenterManager::class.java)))
+ any(ContextWrapper::class.java),
+ eq(SafetyCenterManager::class.java)
+ )
+ )
.thenReturn(mockSafetyCenterManager)
whenever(mockUserManager.isProfile).thenReturn(false)
whenever(
Utils.getEnterpriseString(
any(ContextWrapper::class.java),
eq(WorkPolicyInfo.WORK_POLICY_TITLE),
- anyInt()))
+ anyInt()
+ )
+ )
.thenReturn(WORK_POLICY_TITLE)
whenever(
Utils.getEnterpriseString(
any(ContextWrapper::class.java),
eq(WorkPolicyInfo.WORK_POLICY_SUMMARY),
- anyInt()))
+ anyInt()
+ )
+ )
.thenReturn(WORK_POLICY_SUMMARY)
whenever(PermissionControllerApplication.get()).thenReturn(application)
@@ -121,7 +131,8 @@ class WorkPolicyInfoTest {
Intent(Intent.ACTION_BOOT_COMPLETED)
.putExtra(
SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID,
- SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID)
+ SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
+ )
whenever(mockWorkPolicyUtils.workPolicyInfoIntentDO).thenReturn(intent)
whenever(mockWorkPolicyUtils.workPolicyInfoIntentPO).thenReturn(null)
@@ -134,7 +145,8 @@ class WorkPolicyInfoTest {
SafetySourceStatus.Builder(
WORK_POLICY_TITLE,
WORK_POLICY_SUMMARY,
- SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED)
+ SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
+ )
.setPendingIntent(pendingIntent)
.build()
val expectedSafetySourceData: SafetySourceData =
@@ -146,7 +158,8 @@ class WorkPolicyInfoTest {
.setSafetySourceData(
WorkPolicyInfo.WORK_POLICY_INFO_SOURCE_ID,
expectedSafetySourceData,
- expectedSafetyEvent)
+ expectedSafetyEvent
+ )
}
@Test
@@ -170,7 +183,8 @@ class WorkPolicyInfoTest {
.setSafetySourceData(
WorkPolicyInfo.WORK_POLICY_INFO_SOURCE_ID,
expectedSafetySourceData,
- expectedSafetyEvent)
+ expectedSafetyEvent
+ )
}
@Test
@@ -189,7 +203,10 @@ class WorkPolicyInfoTest {
whenever(mockWorkPolicyUtils.workPolicyInfoIntentPO).thenReturn(null)
workPolicyInfo.rescanAndPushSafetyCenterData(
- context, intent, RefreshEvent.EVENT_DEVICE_REBOOTED)
+ context,
+ intent,
+ RefreshEvent.EVENT_DEVICE_REBOOTED
+ )
val pendingIntent =
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
@@ -197,7 +214,8 @@ class WorkPolicyInfoTest {
SafetySourceStatus.Builder(
WORK_POLICY_TITLE,
WORK_POLICY_SUMMARY,
- SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED)
+ SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
+ )
.setPendingIntent(pendingIntent)
.build()
@@ -210,7 +228,8 @@ class WorkPolicyInfoTest {
.setSafetySourceData(
WorkPolicyInfo.WORK_POLICY_INFO_SOURCE_ID,
expectedSafetySourceData,
- expectedSafetyEvent)
+ expectedSafetyEvent
+ )
}
@Test
@@ -219,13 +238,17 @@ class WorkPolicyInfoTest {
Intent(Intent.ACTION_BOOT_COMPLETED)
.putExtra(
SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID,
- SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID)
+ SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
+ )
whenever(mockWorkPolicyUtils.workPolicyInfoIntentDO).thenReturn(intent)
whenever(mockWorkPolicyUtils.workPolicyInfoIntentPO).thenReturn(null)
workPolicyInfo.rescanAndPushSafetyCenterData(
- context, intent, RefreshEvent.EVENT_REFRESH_REQUESTED)
+ context,
+ intent,
+ RefreshEvent.EVENT_REFRESH_REQUESTED
+ )
val pendingIntent =
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
@@ -233,7 +256,8 @@ class WorkPolicyInfoTest {
SafetySourceStatus.Builder(
WORK_POLICY_TITLE,
WORK_POLICY_SUMMARY,
- SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED)
+ SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
+ )
.setPendingIntent(pendingIntent)
.build()
@@ -251,7 +275,8 @@ class WorkPolicyInfoTest {
.setSafetySourceData(
WorkPolicyInfo.WORK_POLICY_INFO_SOURCE_ID,
expectedSafetySourceData,
- expectedSafetyEvent)
+ expectedSafetyEvent
+ )
}
@Test
@@ -270,7 +295,8 @@ class WorkPolicyInfoTest {
SafetySourceStatus.Builder(
WORK_POLICY_TITLE,
WORK_POLICY_SUMMARY,
- SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED)
+ SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
+ )
.setPendingIntent(pendingIntent)
.build()
@@ -283,7 +309,8 @@ class WorkPolicyInfoTest {
.setSafetySourceData(
WorkPolicyInfo.WORK_POLICY_INFO_SOURCE_ID,
expectedSafetySourceData,
- expectedSafetyEvent)
+ expectedSafetyEvent
+ )
}
@Test
@@ -302,6 +329,7 @@ class WorkPolicyInfoTest {
.setSafetySourceData(
WorkPolicyInfo.WORK_POLICY_INFO_SOURCE_ID,
expectedSafetySourceData,
- expectedSafetyEvent)
+ expectedSafetyEvent
+ )
}
}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/StatusUiDataTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/StatusUiDataTest.kt
index d963fd535..2b9f6b8d2 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/StatusUiDataTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/StatusUiDataTest.kt
@@ -72,8 +72,8 @@ class StatusUiDataTest {
assertThat(StatusUiData(STATUS).originalSummary).isEqualTo(STATUS.summary)
assertThat(StatusUiData(ANOTHER_STATUS).originalSummary).isEqualTo(ANOTHER_STATUS.summary)
assertThat(
- StatusUiData(SafetyCenterData(STATUS, listOf(), listOf(), listOf()))
- .originalSummary)
+ StatusUiData(SafetyCenterData(STATUS, listOf(), listOf(), listOf())).originalSummary
+ )
.isEqualTo(STATUS.summary)
}
@@ -83,7 +83,8 @@ class StatusUiDataTest {
assertThat(StatusUiData(ANOTHER_STATUS).severityLevel)
.isEqualTo(ANOTHER_STATUS.severityLevel)
assertThat(
- StatusUiData(SafetyCenterData(STATUS, listOf(), listOf(), listOf())).severityLevel)
+ StatusUiData(SafetyCenterData(STATUS, listOf(), listOf(), listOf())).severityLevel
+ )
.isEqualTo(STATUS.severityLevel)
}
@@ -114,7 +115,9 @@ class StatusUiDataTest {
mockContext.getString(
R.string.safety_status_preference_title_and_summary_content_description,
STATUS.title,
- STATUS.summary))
+ STATUS.summary
+ )
+ )
.thenReturn(expectedContentDescription)
val actualContentDescription = StatusUiData(STATUS).getContentDescription(mockContext)
@@ -163,14 +166,16 @@ class StatusUiDataTest {
@Test
fun isRefreshInProgress_dataFetch_isTrue() {
assertThat(
- uiDataForRefreshStatus(REFRESH_STATUS_DATA_FETCH_IN_PROGRESS).isRefreshInProgress)
+ uiDataForRefreshStatus(REFRESH_STATUS_DATA_FETCH_IN_PROGRESS).isRefreshInProgress
+ )
.isTrue()
}
@Test
fun isRefreshInProgress_fullRescan_isTrue() {
assertThat(
- uiDataForRefreshStatus(REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS).isRefreshInProgress)
+ uiDataForRefreshStatus(REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS).isRefreshInProgress
+ )
.isTrue()
}
@@ -185,8 +190,10 @@ class StatusUiDataTest {
StatusUiData(
statusForSeverity(OVERALL_SEVERITY_LEVEL_OK),
hasIssues = false,
- hasPendingActions = false)
- .shouldShowRescanButton())
+ hasPendingActions = false
+ )
+ .shouldShowRescanButton()
+ )
.isTrue()
}
@@ -196,8 +203,10 @@ class StatusUiDataTest {
StatusUiData(
statusForSeverity(OVERALL_SEVERITY_LEVEL_UNKNOWN),
hasIssues = false,
- hasPendingActions = false)
- .shouldShowRescanButton())
+ hasPendingActions = false
+ )
+ .shouldShowRescanButton()
+ )
.isTrue()
}
@@ -207,8 +216,10 @@ class StatusUiDataTest {
StatusUiData(
statusForSeverity(OVERALL_SEVERITY_LEVEL_OK),
hasIssues = true,
- hasPendingActions = false)
- .shouldShowRescanButton())
+ hasPendingActions = false
+ )
+ .shouldShowRescanButton()
+ )
.isFalse()
}
@@ -218,8 +229,10 @@ class StatusUiDataTest {
StatusUiData(
statusForSeverity(OVERALL_SEVERITY_LEVEL_OK),
hasIssues = false,
- hasPendingActions = true)
- .shouldShowRescanButton())
+ hasPendingActions = true
+ )
+ .shouldShowRescanButton()
+ )
.isFalse()
}
@@ -227,13 +240,17 @@ class StatusUiDataTest {
fun shouldShowRescanButton_severityNotOkOrUnknown_isFalse() {
for (severity in
listOf(
- OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING, OVERALL_SEVERITY_LEVEL_RECOMMENDATION)) {
+ OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING,
+ OVERALL_SEVERITY_LEVEL_RECOMMENDATION
+ )) {
assertThat(
StatusUiData(
statusForSeverity(severity),
hasIssues = false,
- hasPendingActions = false)
- .shouldShowRescanButton())
+ hasPendingActions = false
+ )
+ .shouldShowRescanButton()
+ )
.isFalse()
}
}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryPersistenceTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryPersistenceTest.kt
index 10221f6fa..ff91677b8 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryPersistenceTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryPersistenceTest.kt
@@ -113,7 +113,9 @@ class AppsSafetyLabelHistoryPersistenceTest {
val appsSafetyLabelHistory =
AppsSafetyLabelHistory(
listOf(
- AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_2), listOf(SAFETY_LABEL_PKG_2_V2))))
+ AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_2), listOf(SAFETY_LABEL_PKG_2_V2))
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
assertThat(AppsSafetyLabelHistoryPersistence.read(dataFile).appsSafetyLabelHistory)
@@ -128,7 +130,10 @@ class AppsSafetyLabelHistoryPersistenceTest {
AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1)),
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
- listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2))))
+ listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2)
+ )
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
assertThat(AppsSafetyLabelHistoryPersistence.read(dataFile).appsSafetyLabelHistory)
@@ -145,7 +150,9 @@ class AppsSafetyLabelHistoryPersistenceTest {
val appsSafetyLabelHistory =
AppsSafetyLabelHistory(
listOf(
- AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_2), listOf(SAFETY_LABEL_PKG_2_V2))))
+ AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_2), listOf(SAFETY_LABEL_PKG_2_V2))
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
assertThat(AppsSafetyLabelHistoryPersistence.read(dataFile).version).isEqualTo(0)
@@ -156,9 +163,13 @@ class AppsSafetyLabelHistoryPersistenceTest {
val appsSafetyLabelHistory =
AppsSafetyLabelHistory(
listOf(
- AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_2), listOf(SAFETY_LABEL_PKG_2_V2))))
+ AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_2), listOf(SAFETY_LABEL_PKG_2_V2))
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(
- dataFile, AppsSafetyLabelHistoryFileContent(appsSafetyLabelHistory, 5))
+ dataFile,
+ AppsSafetyLabelHistoryFileContent(appsSafetyLabelHistory, 5)
+ )
assertThat(AppsSafetyLabelHistoryPersistence.read(dataFile).version).isEqualTo(5)
}
@@ -174,7 +185,12 @@ class AppsSafetyLabelHistoryPersistenceTest {
AppsSafetyLabelHistory(
listOf(
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1)))))
+ AppInfo(PACKAGE_NAME_1),
+ listOf(SAFETY_LABEL_PKG_1_V1)
+ )
+ )
+ )
+ )
}
@Test
@@ -182,7 +198,9 @@ class AppsSafetyLabelHistoryPersistenceTest {
val appsSafetyLabelHistory =
AppsSafetyLabelHistory(
listOf(
- AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1))))
+ AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1))
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
AppsSafetyLabelHistoryPersistence.recordSafetyLabel(SAFETY_LABEL_PKG_2_V1, dataFile)
@@ -192,9 +210,16 @@ class AppsSafetyLabelHistoryPersistenceTest {
AppsSafetyLabelHistory(
listOf(
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1)),
+ AppInfo(PACKAGE_NAME_1),
+ listOf(SAFETY_LABEL_PKG_1_V1)
+ ),
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_2), listOf(SAFETY_LABEL_PKG_2_V1)))))
+ AppInfo(PACKAGE_NAME_2),
+ listOf(SAFETY_LABEL_PKG_2_V1)
+ )
+ )
+ )
+ )
}
@Test
@@ -205,7 +230,10 @@ class AppsSafetyLabelHistoryPersistenceTest {
AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1)),
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
- listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2))))
+ listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2)
+ )
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
AppsSafetyLabelHistoryPersistence.recordSafetyLabel(SAFETY_LABEL_PKG_2_V3, dataFile)
@@ -215,13 +243,20 @@ class AppsSafetyLabelHistoryPersistenceTest {
AppsSafetyLabelHistory(
listOf(
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1)),
+ AppInfo(PACKAGE_NAME_1),
+ listOf(SAFETY_LABEL_PKG_1_V1)
+ ),
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
listOf(
SAFETY_LABEL_PKG_2_V1,
SAFETY_LABEL_PKG_2_V2,
- SAFETY_LABEL_PKG_2_V3)))))
+ SAFETY_LABEL_PKG_2_V3
+ )
+ )
+ )
+ )
+ )
}
@Test
@@ -238,7 +273,11 @@ class AppsSafetyLabelHistoryPersistenceTest {
listOf(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
- listOf(SAFETY_LABEL_PKG_2_V2, SAFETY_LABEL_PKG_2_V3)))))
+ listOf(SAFETY_LABEL_PKG_2_V2, SAFETY_LABEL_PKG_2_V3)
+ )
+ )
+ )
+ )
}
@Test
@@ -249,7 +288,10 @@ class AppsSafetyLabelHistoryPersistenceTest {
AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V2)),
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
- listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2))))
+ listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2)
+ )
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
AppsSafetyLabelHistoryPersistence.recordSafetyLabel(SAFETY_LABEL_PKG_1_V3, dataFile)
@@ -264,7 +306,9 @@ class AppsSafetyLabelHistoryPersistenceTest {
AppsSafetyLabelHistory(
listOf(
AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1)),
- AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_2), listOf(SAFETY_LABEL_PKG_2_V1))))
+ AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_2), listOf(SAFETY_LABEL_PKG_2_V1))
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
AppsSafetyLabelHistoryPersistence.recordSafetyLabels(
@@ -272,8 +316,10 @@ class AppsSafetyLabelHistoryPersistenceTest {
SAFETY_LABEL_PKG_1_V2,
SAFETY_LABEL_PKG_2_V2,
SAFETY_LABEL_PKG_2_V3,
- SAFETY_LABEL_PKG_3_V1),
- dataFile)
+ SAFETY_LABEL_PKG_3_V1
+ ),
+ dataFile
+ )
assertThat(AppsSafetyLabelHistoryPersistence.read(dataFile).appsSafetyLabelHistory)
.isEqualTo(
@@ -281,16 +327,23 @@ class AppsSafetyLabelHistoryPersistenceTest {
listOf(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_1),
- listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2)),
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2)
+ ),
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
listOf(
SAFETY_LABEL_PKG_2_V1,
SAFETY_LABEL_PKG_2_V2,
- SAFETY_LABEL_PKG_2_V3)),
+ SAFETY_LABEL_PKG_2_V3
+ )
+ ),
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_3), listOf(SAFETY_LABEL_PKG_3_V1)),
- )))
+ AppInfo(PACKAGE_NAME_3),
+ listOf(SAFETY_LABEL_PKG_3_V1)
+ ),
+ )
+ )
+ )
}
@Test
@@ -308,7 +361,9 @@ class AppsSafetyLabelHistoryPersistenceTest {
val appsSafetyLabelHistory =
AppsSafetyLabelHistory(
listOf(
- AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1))))
+ AppSafetyLabelHistory(AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1))
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
val safetyLabelDiffs: List<AppSafetyLabelDiff> =
@@ -324,7 +379,10 @@ class AppsSafetyLabelHistoryPersistenceTest {
listOf(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_1),
- listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2))))
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2)
+ )
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
val safetyLabelDiffs: List<AppSafetyLabelDiff> =
@@ -340,7 +398,10 @@ class AppsSafetyLabelHistoryPersistenceTest {
listOf(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
- listOf(SAFETY_LABEL_PKG_2_V2, SAFETY_LABEL_PKG_2_V3))))
+ listOf(SAFETY_LABEL_PKG_2_V2, SAFETY_LABEL_PKG_2_V3)
+ )
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
val safetyLabelDiffs: List<AppSafetyLabelDiff> =
@@ -357,11 +418,14 @@ class AppsSafetyLabelHistoryPersistenceTest {
listOf(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_1),
- listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2)),
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2)
+ ),
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
- listOf(
- SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2, SAFETY_LABEL_PKG_2_V3))))
+ listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2, SAFETY_LABEL_PKG_2_V3)
+ )
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
val safetyLabelDiffs =
@@ -371,7 +435,9 @@ class AppsSafetyLabelHistoryPersistenceTest {
.isEqualTo(
listOf(
AppSafetyLabelDiff(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2),
- AppSafetyLabelDiff(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V3)))
+ AppSafetyLabelDiff(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V3)
+ )
+ )
}
@Test
@@ -389,11 +455,14 @@ class AppsSafetyLabelHistoryPersistenceTest {
listOf(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_1),
- listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2)),
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2)
+ ),
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
- listOf(
- SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2, SAFETY_LABEL_PKG_2_V3))))
+ listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2, SAFETY_LABEL_PKG_2_V3)
+ )
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
val lastUpdatedTimes =
@@ -403,7 +472,9 @@ class AppsSafetyLabelHistoryPersistenceTest {
.isEqualTo(
mapOf(
AppInfo(PACKAGE_NAME_1) to DATE_2022_10_14,
- AppInfo(PACKAGE_NAME_2) to DATE_2022_12_30))
+ AppInfo(PACKAGE_NAME_2) to DATE_2022_12_30
+ )
+ )
}
@Test
@@ -413,14 +484,20 @@ class AppsSafetyLabelHistoryPersistenceTest {
listOf(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_1),
- listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2)),
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2)
+ ),
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
- listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2))))
+ listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2)
+ )
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
AppsSafetyLabelHistoryPersistence.deleteSafetyLabelsForApps(
- setOf(AppInfo(PACKAGE_NAME_2)), dataFile)
+ setOf(AppInfo(PACKAGE_NAME_2)),
+ dataFile
+ )
assertThat(AppsSafetyLabelHistoryPersistence.read(dataFile).appsSafetyLabelHistory)
.isEqualTo(
@@ -428,7 +505,11 @@ class AppsSafetyLabelHistoryPersistenceTest {
listOf(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_1),
- listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2)))))
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2)
+ )
+ )
+ )
+ )
}
@Test
@@ -438,11 +519,14 @@ class AppsSafetyLabelHistoryPersistenceTest {
listOf(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_1),
- listOf(
- SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3)),
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3)
+ ),
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
- listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2))))
+ listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2)
+ )
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
AppsSafetyLabelHistoryPersistence.deleteSafetyLabelsOlderThan(DATE_2022_12_30, dataFile)
@@ -452,9 +536,16 @@ class AppsSafetyLabelHistoryPersistenceTest {
AppsSafetyLabelHistory(
listOf(
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V3)),
+ AppInfo(PACKAGE_NAME_1),
+ listOf(SAFETY_LABEL_PKG_1_V3)
+ ),
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_2), listOf(SAFETY_LABEL_PKG_2_V2)))))
+ AppInfo(PACKAGE_NAME_2),
+ listOf(SAFETY_LABEL_PKG_2_V2)
+ )
+ )
+ )
+ )
}
@Test
@@ -464,11 +555,14 @@ class AppsSafetyLabelHistoryPersistenceTest {
listOf(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_1),
- listOf(
- SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3)),
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3)
+ ),
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
- listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2))))
+ listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2)
+ )
+ )
+ )
AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory)
AppsSafetyLabelHistoryPersistence.deleteSafetyLabelsOlderThan(DATE_2022_10_14, dataFile)
@@ -479,10 +573,15 @@ class AppsSafetyLabelHistoryPersistenceTest {
listOf(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_1),
- listOf(SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3)),
+ listOf(SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3)
+ ),
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_2),
- listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2)))))
+ listOf(SAFETY_LABEL_PKG_2_V1, SAFETY_LABEL_PKG_2_V2)
+ )
+ )
+ )
+ )
}
@Test
@@ -531,7 +630,9 @@ class AppsSafetyLabelHistoryPersistenceTest {
DeviceConfig.getInt(
eq(NAMESPACE_PRIVACY),
eq(PROPERTY_MAX_SAFETY_LABELS_PERSISTED_PER_APP),
- anyInt()))
+ anyInt()
+ )
+ )
.thenReturn(max)
}
}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryTest.kt
index dedb0b1cd..74eba4e4c 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryTest.kt
@@ -49,7 +49,9 @@ class AppsSafetyLabelHistoryTest {
fun createAppSafetyLabelHistory_requiresAllSafetyLabelsHaveSameApp() {
Assert.assertThrows(IllegalArgumentException::class.java) {
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_2_V1))
+ AppInfo(PACKAGE_NAME_1),
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_2_V1)
+ )
}
}
@@ -57,7 +59,9 @@ class AppsSafetyLabelHistoryTest {
fun createAppSafetyLabelHistory_requiresOrderedByReceivedAt() {
Assert.assertThrows(IllegalArgumentException::class.java) {
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V1))
+ AppInfo(PACKAGE_NAME_1),
+ listOf(SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V1)
+ )
}
}
@@ -65,7 +69,9 @@ class AppsSafetyLabelHistoryTest {
fun withSafetyLabel_forDifferentApp_throwsIllegalArgumentException() {
val appSafetyLabelHistory =
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V3))
+ AppInfo(PACKAGE_NAME_1),
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V3)
+ )
Assert.assertThrows(IllegalArgumentException::class.java) {
appSafetyLabelHistory.withSafetyLabel(SAFETY_LABEL_PKG_2_V1, 20)
@@ -76,25 +82,34 @@ class AppsSafetyLabelHistoryTest {
fun withSafetyLabel_returnsOrderdSafetyLabels() {
val appSafetyLabelHistory =
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V3))
+ AppInfo(PACKAGE_NAME_1),
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V3)
+ )
assertThat(appSafetyLabelHistory.withSafetyLabel(SAFETY_LABEL_PKG_1_V2, 20))
.isEqualTo(
AppSafetyLabelHistory(
AppInfo(PACKAGE_NAME_1),
- listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3)))
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3)
+ )
+ )
}
@Test
fun withSafetyLabel_dropsOldLabelsWhenMaxPersisted() {
val appSafetyLabelHistory =
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V3))
+ AppInfo(PACKAGE_NAME_1),
+ listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V3)
+ )
assertThat(appSafetyLabelHistory.withSafetyLabel(SAFETY_LABEL_PKG_1_V2, 2))
.isEqualTo(
AppSafetyLabelHistory(
- AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3)))
+ AppInfo(PACKAGE_NAME_1),
+ listOf(SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3)
+ )
+ )
}
@Test
@@ -105,7 +120,10 @@ class AppsSafetyLabelHistoryTest {
val safetyLabelForPersistence =
SafetyLabel.extractLocationSharingSafetyLabel(
- PACKAGE_NAME_1, DATE_2022_09_01, appMetadataSafetyLabel)
+ PACKAGE_NAME_1,
+ DATE_2022_09_01,
+ appMetadataSafetyLabel
+ )
assertThat(safetyLabelForPersistence)
.isEqualTo(SafetyLabel(AppInfo(PACKAGE_NAME_1), DATE_2022_09_01, DataLabel(mapOf())))
@@ -119,14 +137,19 @@ class AppsSafetyLabelHistoryTest {
val safetyLabelForPersistence =
SafetyLabel.extractLocationSharingSafetyLabel(
- PACKAGE_NAME_1, DATE_2022_10_10, appMetadataSafetyLabel)
+ PACKAGE_NAME_1,
+ DATE_2022_10_10,
+ appMetadataSafetyLabel
+ )
assertThat(safetyLabelForPersistence)
.isEqualTo(
SafetyLabel(
AppInfo(PACKAGE_NAME_1),
DATE_2022_10_10,
- DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(false)))))
+ DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(false)))
+ )
+ )
}
@Test
@@ -137,14 +160,19 @@ class AppsSafetyLabelHistoryTest {
val safetyLabelForPersistence =
SafetyLabel.extractLocationSharingSafetyLabel(
- PACKAGE_NAME_2, DATE_2022_10_10, appMetadataSafetyLabel)
+ PACKAGE_NAME_2,
+ DATE_2022_10_10,
+ appMetadataSafetyLabel
+ )
assertThat(safetyLabelForPersistence)
.isEqualTo(
SafetyLabel(
AppInfo(PACKAGE_NAME_2),
DATE_2022_10_10,
- DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true)))))
+ DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true)))
+ )
+ )
}
@Test
@@ -155,7 +183,10 @@ class AppsSafetyLabelHistoryTest {
val safetyLabelForPersistence =
SafetyLabel.extractLocationSharingSafetyLabel(
- PACKAGE_NAME_2, DATE_2022_10_10, appMetadataSafetyLabel)
+ PACKAGE_NAME_2,
+ DATE_2022_10_10,
+ appMetadataSafetyLabel
+ )
assertThat(safetyLabelForPersistence)
.isEqualTo(SafetyLabel(AppInfo(PACKAGE_NAME_2), DATE_2022_10_10, DataLabel(mapOf())))
@@ -170,14 +201,19 @@ class AppsSafetyLabelHistoryTest {
val safetyLabelForPersistence =
SafetyLabel.extractLocationSharingSafetyLabel(
- PACKAGE_NAME_2, DATE_2022_10_10, appMetadataSafetyLabel)
+ PACKAGE_NAME_2,
+ DATE_2022_10_10,
+ appMetadataSafetyLabel
+ )
assertThat(safetyLabelForPersistence)
.isEqualTo(
SafetyLabel(
AppInfo(PACKAGE_NAME_2),
DATE_2022_10_10,
- DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true)))))
+ DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true)))
+ )
+ )
}
/** Companion object for [AppsSafetyLabelHistoryTest]. */
@@ -211,8 +247,10 @@ class AppsSafetyLabelHistoryTest {
PersistableBundle().apply {
putIntArray(
PURPOSES_KEY,
- listOf(PURPOSE_FRAUD_PREVENTION_SECURITY).toIntArray())
- })
+ listOf(PURPOSE_FRAUD_PREVENTION_SECURITY).toIntArray()
+ )
+ }
+ )
}
return PersistableBundle().apply {
@@ -227,7 +265,8 @@ class AppsSafetyLabelHistoryTest {
APPROX_LOCATION,
PersistableBundle().apply {
putIntArray(PURPOSES_KEY, listOf(PURPOSE_ADVERTISING).toIntArray())
- })
+ }
+ )
}
return PersistableBundle().apply {
@@ -242,7 +281,8 @@ class AppsSafetyLabelHistoryTest {
FINANCIAL_PURCHASE_HISTORY,
PersistableBundle().apply {
putIntArray(PURPOSES_KEY, listOf(PURPOSE_ADVERTISING).toIntArray())
- })
+ }
+ )
}
return PersistableBundle().apply {
@@ -257,7 +297,8 @@ class AppsSafetyLabelHistoryTest {
APPROX_LOCATION,
PersistableBundle().apply {
putIntArray(PURPOSES_KEY, listOf(PURPOSE_ADVERTISING).toIntArray())
- })
+ }
+ )
}
val financeBundle =
PersistableBundle().apply {
@@ -265,7 +306,8 @@ class AppsSafetyLabelHistoryTest {
FINANCIAL_PURCHASE_HISTORY,
PersistableBundle().apply {
putIntArray(PURPOSES_KEY, listOf(PURPOSE_ADVERTISING).toIntArray())
- })
+ }
+ )
}
return PersistableBundle().apply {
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/SafetyLabelChangesJobServiceTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/SafetyLabelChangesJobServiceTest.kt
index f6395f8ea..4d206a2f4 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/SafetyLabelChangesJobServiceTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/SafetyLabelChangesJobServiceTest.kt
@@ -138,8 +138,8 @@ class SafetyLabelChangesJobServiceTest {
val captor = ArgumentCaptor.forClass(JobInfo::class.java)
verify(mockJobScheduler, times(2)).schedule(captor.capture())
val capturedJobIds = captor.getAllValues()
- assertThat(capturedJobIds[0].id).isEqualTo(
- Constants.SAFETY_LABEL_CHANGES_DETECT_UPDATES_JOB_ID)
+ assertThat(capturedJobIds[0].id)
+ .isEqualTo(Constants.SAFETY_LABEL_CHANGES_DETECT_UPDATES_JOB_ID)
assertThat(capturedJobIds[1].id)
.isEqualTo(Constants.SAFETY_LABEL_CHANGES_PERIODIC_NOTIFICATION_JOB_ID)
}
@@ -155,7 +155,9 @@ class SafetyLabelChangesJobServiceTest {
DeviceConfig.getBoolean(
eq(DeviceConfig.NAMESPACE_PRIVACY),
eq(SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED),
- anyBoolean()))
+ anyBoolean()
+ )
+ )
.thenReturn(flagValue)
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/TestSafetyLabels.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/TestSafetyLabels.kt
index 19c5adddd..45b57662d 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/TestSafetyLabels.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/TestSafetyLabels.kt
@@ -42,21 +42,24 @@ object TestSafetyLabels {
SafetyLabel(
AppInfo(PACKAGE_NAME_1),
DATE_2022_09_01,
- DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true))))
+ DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true)))
+ )
/** A Safety label for [PACKAGE_NAME_1]. */
val SAFETY_LABEL_PKG_1_V2: SafetyLabel =
SafetyLabel(
AppInfo(PACKAGE_NAME_1),
DATE_2022_10_14,
- DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(false))))
+ DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(false)))
+ )
/** A Safety label for [PACKAGE_NAME_1]. */
val SAFETY_LABEL_PKG_1_V3: SafetyLabel =
SafetyLabel(
AppInfo(PACKAGE_NAME_1),
DATE_2022_12_10,
- DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(false))))
+ DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(false)))
+ )
/** A Safety label for [PACKAGE_NAME_2]. */
val SAFETY_LABEL_PKG_2_V1: SafetyLabel =
@@ -66,7 +69,10 @@ object TestSafetyLabels {
DataLabel(
mapOf(
LOCATION_CATEGORY to DataCategory(true),
- FINANCIAL_CATEGORY to DataCategory(false))))
+ FINANCIAL_CATEGORY to DataCategory(false)
+ )
+ )
+ )
/** A Safety label for [PACKAGE_NAME_2]. */
val SAFETY_LABEL_PKG_2_V2: SafetyLabel =
@@ -77,12 +83,14 @@ object TestSafetyLabels {
SafetyLabel(
AppInfo(PACKAGE_NAME_2),
DATE_2022_12_30,
- DataLabel(mapOf(FINANCIAL_CATEGORY to DataCategory(true))))
+ DataLabel(mapOf(FINANCIAL_CATEGORY to DataCategory(true)))
+ )
/** A Safety label for [PACKAGE_NAME_3]. */
val SAFETY_LABEL_PKG_3_V1: SafetyLabel =
SafetyLabel(
AppInfo(PACKAGE_NAME_3),
DATE_2022_10_10,
- DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true))))
+ DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true)))
+ )
}
diff --git a/PermissionController/tests/outofprocess/src/com/android/permissioncontroller/tests/outofprocess/DumpTest.kt b/PermissionController/tests/outofprocess/src/com/android/permissioncontroller/tests/outofprocess/DumpTest.kt
index 4963a4683..707d7678d 100644
--- a/PermissionController/tests/outofprocess/src/com/android/permissioncontroller/tests/outofprocess/DumpTest.kt
+++ b/PermissionController/tests/outofprocess/src/com/android/permissioncontroller/tests/outofprocess/DumpTest.kt
@@ -23,11 +23,11 @@ import androidx.test.platform.app.InstrumentationRegistry
import com.android.permissioncontroller.PermissionControllerProto.PermissionControllerDumpProto
import com.google.common.truth.Truth.assertThat
import com.google.protobuf.InvalidProtocolBufferException
+import java.nio.charset.StandardCharsets.UTF_8
import org.junit.Assert.fail
import org.junit.Assume.assumeTrue
import org.junit.Test
import org.junit.runner.RunWith
-import java.nio.charset.StandardCharsets.UTF_8
@RunWith(AndroidJUnit4::class)
class DumpTest {
@@ -36,8 +36,8 @@ class DumpTest {
private val instrumentation = InstrumentationRegistry.getInstrumentation()
private fun getDump(): PermissionControllerDumpProto {
- val dumpFile = instrumentation.getUiAutomation()
- .executeShellCommand("dumpsys permissionmgr --proto")
+ val dumpFile =
+ instrumentation.getUiAutomation().executeShellCommand("dumpsys permissionmgr --proto")
val dump = AutoCloseInputStream(dumpFile).readBytes()
try {
@@ -66,6 +66,6 @@ class DumpTest {
assumeTrue(dump.autoRevoke.usersList.isNotEmpty())
assertThat(dump.autoRevoke.usersList[myUserId()].packagesList.map { it.packageName })
- .contains(OS_PKG)
+ .contains(OS_PKG)
}
}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionGroupPreferenceUtils.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionGroupPreferenceUtils.kt
index 175b7a701..8e1d6a831 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionGroupPreferenceUtils.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionGroupPreferenceUtils.kt
@@ -26,31 +26,33 @@ private const val SUMMARY_TEXT = "apps allowed"
* Read the {@link UsageCount} of the group of the permission from the Ui.
*
* @param groupLabel label fo the group the count should be read for
- *
* @return usage counts for the group of the permission
*/
fun getUsageCountsFromUi(groupLabel: CharSequence): UsageCount {
waitFindObject(By.text(groupLabel.toString()))
return getEventually {
- val summaryText = waitFindObject(By.hasChild(By.text(groupLabel.toString()))
- .hasChild(By.textContains(SUMMARY_TEXT))).findObject(By.textContains(SUMMARY_TEXT)).text
+ val summaryText =
+ waitFindObject(
+ By.hasChild(By.text(groupLabel.toString()))
+ .hasChild(By.textContains(SUMMARY_TEXT))
+ )
+ .findObject(By.textContains(SUMMARY_TEXT))
+ .text
// Matches two numbers out of the summary line, i.e. "...3...12..." -> "3", "12"
- val groups = Regex("^[^\\d]*(\\d+)[^\\d]*(\\d+)[^\\d]*\$")
- .find(summaryText)?.groupValues
- ?: throw Exception("No usage counts found")
+ val groups =
+ Regex("^[^\\d]*(\\d+)[^\\d]*(\\d+)[^\\d]*\$").find(summaryText)?.groupValues
+ ?: throw Exception("No usage counts found")
UsageCount(groups[1].toInt(), groups[2].toInt())
}
}
-/**
- * Usage counts as read via {@link #getUsageCountsFromUi}.
- */
+/** Usage counts as read via {@link #getUsageCountsFromUi}. */
data class UsageCount(
/** Number of apps with permission granted */
val granted: Int,
/** Number of apps that request permissions */
val total: Int
-) \ No newline at end of file
+)
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionHub2Test.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionHub2Test.kt
index 6f143d2db..0b1269a2f 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionHub2Test.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionHub2Test.kt
@@ -35,9 +35,7 @@ import com.google.common.truth.Truth.assertThat
import org.junit.AfterClass
import org.junit.BeforeClass
-/**
- * Super class with utilities for testing permission hub 2 code
- */
+/** Super class with utilities for testing permission hub 2 code */
open class PermissionHub2Test {
private val APP = "com.android.permissioncontroller.tests.appthatrequestpermission"
@@ -54,13 +52,18 @@ open class PermissionHub2Test {
fun enablePermissionHub2() {
runWithShellPermissionIdentity {
- wasPermissionHubEnabled = DeviceConfig.getBoolean(NAMESPACE_PRIVACY,
- PROPERTY_PERMISSIONS_HUB_2_ENABLED, false)
+ wasPermissionHubEnabled =
+ DeviceConfig.getBoolean(
+ NAMESPACE_PRIVACY,
+ PROPERTY_PERMISSIONS_HUB_2_ENABLED,
+ false
+ )
}
if (!wasPermissionHubEnabled) {
runShellCommand(
- "device_config put privacy $PROPERTY_PERMISSIONS_HUB_2_ENABLED true")
+ "device_config put privacy $PROPERTY_PERMISSIONS_HUB_2_ENABLED true"
+ )
}
}
@@ -69,34 +72,43 @@ open class PermissionHub2Test {
fun disablePermissionHub2() {
if (!wasPermissionHubEnabled) {
runShellCommand(
- "device_config put privacy $PROPERTY_PERMISSIONS_HUB_2_ENABLED false")
+ "device_config put privacy $PROPERTY_PERMISSIONS_HUB_2_ENABLED false"
+ )
}
}
}
- /**
- * Make {@value #APP} access the camera
- */
+ /** Make {@value #APP} access the camera */
protected fun accessCamera() {
// App needs to be in foreground to be able to access camera
context.startActivity(
- Intent().setComponent(ComponentName.createRelative(APP, ".DummyActivity"))
- .setFlags(FLAG_ACTIVITY_NEW_TASK))
+ Intent()
+ .setComponent(ComponentName.createRelative(APP, ".DummyActivity"))
+ .setFlags(FLAG_ACTIVITY_NEW_TASK)
+ )
runWithShellPermissionIdentity {
eventually {
assertThat(
- context.packageManager.getPermissionFlags(CAMERA, APP, myUserHandle()) and
- FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED
- ).isNotEqualTo(0)
+ context.packageManager.getPermissionFlags(CAMERA, APP, myUserHandle()) and
+ FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED
+ )
+ .isNotEqualTo(0)
}
eventually {
assertThat(
- context.getSystemService(AppOpsManager::class.java).startOp(
- OPSTR_CAMERA, context.packageManager.getPackageUid(APP, 0), APP, null, null
+ context
+ .getSystemService(AppOpsManager::class.java)
+ .startOp(
+ OPSTR_CAMERA,
+ context.packageManager.getPackageUid(APP, 0),
+ APP,
+ null,
+ null
+ )
)
- ).isEqualTo(MODE_ALLOWED)
+ .isEqualTo(MODE_ALLOWED)
}
}
}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/UiUtils.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/UiUtils.kt
index 25aa79632..fa741d3eb 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/UiUtils.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/UiUtils.kt
@@ -16,12 +16,10 @@
package com.android.permissioncontroller.permissionui
-import androidx.test.uiautomator.UiDevice
import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
-/**
- * Wake up screen
- */
+/** Wake up screen */
fun wakeUpScreen() {
val uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@@ -29,9 +27,7 @@ fun wakeUpScreen() {
uiDevice.executeShellCommand("wm dismiss-keyguard")
}
-/**
- * Press the home button
- */
+/** Press the home button */
fun pressHome() {
val uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
uiDevice.pressHome()
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AllAppPermissionsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AllAppPermissionsFragmentTest.kt
index d5f574327..b460493ff 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AllAppPermissionsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AllAppPermissionsFragmentTest.kt
@@ -19,8 +19,8 @@ package com.android.permissioncontroller.permissionui.ui
import android.content.Intent
import android.permission.cts.PermissionUtils.install
import android.permission.cts.PermissionUtils.uninstallApp
-import androidx.test.uiautomator.By
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.uiautomator.By
import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject
@@ -37,11 +37,9 @@ private const val MORE_OPTIONS = "More options"
private const val ALL_PERMISSIONS = "All permissions"
/**
- * Simple tests for {@link AllAppPermissionsFragment}
- * Currently, does NOT run on TV.
- * TODO(b/178576541): Adapt and run on TV.
- * Run with:
- * atest AllAppPermissionsFragmentTest
+ * Simple tests for {@link AllAppPermissionsFragment} Currently, does NOT run on TV.
+ *
+ * TODO(b/178576541): Adapt and run on TV. Run with: atest AllAppPermissionsFragmentTest
*/
@RunWith(AndroidJUnit4::class)
class AllAppPermissionsFragmentTest : BasePermissionUiTest() {
@@ -62,8 +60,7 @@ class AllAppPermissionsFragmentTest : BasePermissionUiTest() {
private val TIMEOUT_SHORT = 500L
- @Before
- fun assumeNotTelevision() = assumeFalse(isTelevision)
+ @Before fun assumeNotTelevision() = assumeFalse(isTelevision)
@Before
fun wakeScreenUp() {
@@ -76,12 +73,13 @@ class AllAppPermissionsFragmentTest : BasePermissionUiTest() {
install(PERMISSION_USER_APK)
runWithShellPermissionIdentity {
- instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS)
- .apply {
+ instrumentationContext.startActivity(
+ Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
putExtra(Intent.EXTRA_PACKAGE_NAME, USER_PKG)
- })
+ }
+ )
}
waitFindObject(By.descContains(MORE_OPTIONS)).click()
@@ -98,30 +96,22 @@ class AllAppPermissionsFragmentTest : BasePermissionUiTest() {
waitFindObject(By.text(PERM_LABEL))
install(TWO_PERMISSION_USER_APK)
- eventually {
- waitFindObject(By.text(SECOND_PERM_LABEL))
- }
+ eventually { waitFindObject(By.text(SECOND_PERM_LABEL)) }
}
@Test
fun permissionsAreRemovedWhenAppIsUpdated() {
install(TWO_PERMISSION_USER_APK)
- eventually {
- waitFindObject(By.text(SECOND_PERM_LABEL))
- }
+ eventually { waitFindObject(By.text(SECOND_PERM_LABEL)) }
install(PERMISSION_USER_APK)
- eventually {
- assertNull(waitFindObjectOrNull(By.text(SECOND_PERM_LABEL), TIMEOUT_SHORT))
- }
+ eventually { assertNull(waitFindObjectOrNull(By.text(SECOND_PERM_LABEL), TIMEOUT_SHORT)) }
}
@Test
fun activityIsClosedWhenUserIsUninstalled() {
uninstallApp(USER_PKG)
- eventually {
- assertNull(waitFindObjectOrNull(By.text(ALL_PERMISSIONS), TIMEOUT_SHORT))
- }
+ eventually { assertNull(waitFindObjectOrNull(By.text(ALL_PERMISSIONS), TIMEOUT_SHORT)) }
}
@After
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AppPermissionFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AppPermissionFragmentTest.kt
index 7b058d004..b4893dc83 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AppPermissionFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AppPermissionFragmentTest.kt
@@ -21,8 +21,8 @@ import android.os.UserHandle
import android.os.UserHandle.myUserId
import android.permission.cts.PermissionUtils.install
import android.permission.cts.PermissionUtils.uninstallApp
-import androidx.test.uiautomator.By
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.uiautomator.By
import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull
@@ -37,11 +37,9 @@ import org.junit.runner.RunWith
private const val APP_PERMISSIONS = "App permissions"
/**
- * Simple tests for {@link AppPermissionFragment}
- * Currently, does NOT run on TV.
- * TODO(b/178576541): Adapt and run on TV.
- * Run with:
- * atest AppPermissionFragmentTest
+ * Simple tests for {@link AppPermissionFragment} Currently, does NOT run on TV.
+ *
+ * TODO(b/178576541): Adapt and run on TV. Run with: atest AppPermissionFragmentTest
*/
@RunWith(AndroidJUnit4::class)
class AppPermissionFragmentTest : BasePermissionUiTest() {
@@ -56,8 +54,7 @@ class AppPermissionFragmentTest : BasePermissionUiTest() {
private val PERM = "com.android.permissioncontroller.tests.A"
- @Before
- fun assumeNotTelevision() = assumeFalse(isTelevision)
+ @Before fun assumeNotTelevision() = assumeFalse(isTelevision)
@Before
fun wakeScreenUp() {
@@ -73,31 +70,29 @@ class AppPermissionFragmentTest : BasePermissionUiTest() {
@Before
fun startManagePermissionAppsActivity() {
runWithShellPermissionIdentity {
- instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_APP_PERMISSION).apply {
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- putExtra(Intent.EXTRA_PACKAGE_NAME, USER_PKG)
- putExtra(Intent.EXTRA_PERMISSION_NAME, PERM)
- putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, PERM)
- putExtra(Intent.EXTRA_USER, UserHandle.of(myUserId()))
- putExtra("com.android.permissioncontroller.extra.CALLER_NAME", "")
- })
+ instrumentationContext.startActivity(
+ Intent(Intent.ACTION_MANAGE_APP_PERMISSION).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ putExtra(Intent.EXTRA_PACKAGE_NAME, USER_PKG)
+ putExtra(Intent.EXTRA_PERMISSION_NAME, PERM)
+ putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, PERM)
+ putExtra(Intent.EXTRA_USER, UserHandle.of(myUserId()))
+ putExtra("com.android.permissioncontroller.extra.CALLER_NAME", "")
+ }
+ )
}
}
@Test
fun activityIsClosedWhenUserIsUninstalled() {
uninstallApp(USER_PKG)
- eventually {
- assertNull(waitFindObjectOrNull(By.text(APP_PERMISSIONS)))
- }
+ eventually { assertNull(waitFindObjectOrNull(By.text(APP_PERMISSIONS))) }
}
@Test
fun activityIsClosedWhenDefinerIsUninstalled() {
uninstallApp(DEFINER_PKG)
- eventually {
- assertNull(waitFindObjectOrNull(By.text(APP_PERMISSIONS)))
- }
+ eventually { assertNull(waitFindObjectOrNull(By.text(APP_PERMISSIONS))) }
}
@After
@@ -105,4 +100,4 @@ class AppPermissionFragmentTest : BasePermissionUiTest() {
uninstallApp(DEFINER_PKG)
uninstallApp(USER_PKG)
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/BasePermissionUiTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/BasePermissionUiTest.kt
index 7d2c644c5..2cb7e7a5c 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/BasePermissionUiTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/BasePermissionUiTest.kt
@@ -29,11 +29,11 @@ abstract class BasePermissionUiTest {
protected val instrumentationContext = instrumentation.context!!
protected val targetContext = instrumentation.targetContext!!
private val packageManager = instrumentationContext.packageManager!!
- protected val isTelevision = packageManager.run {
- hasSystemFeature(PackageManager.FEATURE_LEANBACK) ||
- hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)
- }
+ protected val isTelevision =
+ packageManager.run {
+ hasSystemFeature(PackageManager.FEATURE_LEANBACK) ||
+ hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)
+ }
- @Rule
- fun disableAnimationsRule() = DisableAnimationRule()
-} \ No newline at end of file
+ @Rule fun disableAnimationsRule() = DisableAnimationRule()
+}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/CustomPermissionAppsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/CustomPermissionAppsFragmentTest.kt
index 988cbca73..fb1214d70 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/CustomPermissionAppsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/CustomPermissionAppsFragmentTest.kt
@@ -17,8 +17,8 @@
package com.android.permissioncontroller.permissionui.ui
import android.permission.cts.PermissionUtils.uninstallApp
-import androidx.test.uiautomator.By
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.uiautomator.By
import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull
import org.junit.Assert.assertNull
@@ -32,24 +32,24 @@ private const val PERMISSION_APPS_DESCRIPTION = "Apps with this permission"
* Simple tests for {@link PermissionAppsFragment} when showing custom permission
*
* Currently, does NOT run on TV (same as the other tests that extend [PermissionAppsFragmentTest]).
+ *
* TODO(b/178576541): Adapt and run on TV.
*/
@RunWith(AndroidJUnit4::class)
-class CustomPermissionAppsFragmentTest : PermissionAppsFragmentTest(
- "/data/local/tmp/permissioncontroller/tests/permissionui" +
- "/PermissionUiUseAdditionalPermissionApp.apk",
- "com.android.permissioncontroller.tests.appthatrequestpermission",
- "com.android.permissioncontroller.tests.A",
- "/data/local/tmp/permissioncontroller/tests/permissionui" +
- "/PermissionUiDefineAdditionalPermissionApp.apk",
- "com.android.permissioncontroller.tests.appthatdefinespermission"
-) {
+class CustomPermissionAppsFragmentTest :
+ PermissionAppsFragmentTest(
+ "/data/local/tmp/permissioncontroller/tests/permissionui" +
+ "/PermissionUiUseAdditionalPermissionApp.apk",
+ "com.android.permissioncontroller.tests.appthatrequestpermission",
+ "com.android.permissioncontroller.tests.A",
+ "/data/local/tmp/permissioncontroller/tests/permissionui" +
+ "/PermissionUiDefineAdditionalPermissionApp.apk",
+ "com.android.permissioncontroller.tests.appthatdefinespermission"
+ ) {
@Ignore("b/155112992")
@Test
fun fragmentIsClosedWhenPermissionIsRemoved() {
uninstallApp(definerApk!!)
- eventually {
- assertNull(waitFindObjectOrNull(By.text(PERMISSION_APPS_DESCRIPTION)))
- }
+ eventually { assertNull(waitFindObjectOrNull(By.text(PERMISSION_APPS_DESCRIPTION))) }
}
}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAllAppPermissionFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAllAppPermissionFragmentTest.kt
index c7a33e857..2bf39aab3 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAllAppPermissionFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAllAppPermissionFragmentTest.kt
@@ -34,17 +34,15 @@ import org.junit.Test
import org.junit.runner.RunWith
/**
- * Simple tests for {@link AllAppPermissionsFragment} for Health Connect behaviors
- * Currently, does NOT run on TV.
- * TODO(b/178576541): Adapt and run on TV.
- * Run with:
- * atest HealthConnectAllAppPermissionFragmentTest
+ * Simple tests for {@link AllAppPermissionsFragment} for Health Connect behaviors Currently, does
+ * NOT run on TV.
+ *
+ * TODO(b/178576541): Adapt and run on TV. Run with: atest HealthConnectAllAppPermissionFragmentTest
*/
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
class HealthConnectAllAppPermissionFragmentTest : BasePermissionUiTest() {
- @Before
- fun assumeNotTelevision() = assumeFalse(isTelevision)
+ @Before fun assumeNotTelevision() = assumeFalse(isTelevision)
@Before
fun wakeScreenUp() {
@@ -76,10 +74,18 @@ class HealthConnectAllAppPermissionFragmentTest : BasePermissionUiTest() {
eventually {
assertNull(waitFindObjectOrNull(By.text(HEALTH_CONNECT_LABEL), TIMEOUT_SHORT))
- assertNull(waitFindObjectOrNull(
- By.text(HEALTH_CONNECT_PERMISSION_READ_FLOORS_CLIMBED_LABEL), TIMEOUT_SHORT))
- assertNull(waitFindObjectOrNull(
- By.text(HEALTH_CONNECT_PERMISSION_READ_STEPS_LABEL), TIMEOUT_SHORT))
+ assertNull(
+ waitFindObjectOrNull(
+ By.text(HEALTH_CONNECT_PERMISSION_READ_FLOORS_CLIMBED_LABEL),
+ TIMEOUT_SHORT
+ )
+ )
+ assertNull(
+ waitFindObjectOrNull(
+ By.text(HEALTH_CONNECT_PERMISSION_READ_STEPS_LABEL),
+ TIMEOUT_SHORT
+ )
+ )
}
}
@@ -105,12 +111,13 @@ class HealthConnectAllAppPermissionFragmentTest : BasePermissionUiTest() {
private fun startManageAppPermissionsActivity() {
runWithShellPermissionIdentity {
- instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS)
- .apply {
+ instrumentationContext.startActivity(
+ Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
putExtra(Intent.EXTRA_PACKAGE_NAME, PERM_USER_PACKAGE)
- })
+ }
+ )
}
waitFindObject(By.descContains(MORE_OPTIONS)).click()
@@ -124,12 +131,11 @@ class HealthConnectAllAppPermissionFragmentTest : BasePermissionUiTest() {
"android.permission.health.READ_FLOORS_CLIMBED"
private const val HEALTH_CONNECT_PERMISSION_READ_FLOORS_CLIMBED_LABEL =
"Read floors climbed"
- private const val HEALTH_CONNECT_PERMISSION_READ_STEPS_LABEL =
- "Read steps"
+ private const val HEALTH_CONNECT_PERMISSION_READ_STEPS_LABEL = "Read steps"
private const val MORE_OPTIONS = "More options"
private const val ALL_PERMISSIONS = "All permissions"
private val TIMEOUT_SHORT = 500L
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAppPermissionFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAppPermissionFragmentTest.kt
index 4f3e281cd..640354e56 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAppPermissionFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAppPermissionFragmentTest.kt
@@ -34,17 +34,15 @@ import org.junit.Test
import org.junit.runner.RunWith
/**
- * Simple tests for {@link AppPermissionsFragment} for Health Connect behaviors
- * Currently, does NOT run on TV.
- * TODO(b/178576541): Adapt and run on TV.
- * Run with:
- * atest HealthConnectAppPermissionFragmentTest
+ * Simple tests for {@link AppPermissionsFragment} for Health Connect behaviors Currently, does NOT
+ * run on TV.
+ *
+ * TODO(b/178576541): Adapt and run on TV. Run with: atest HealthConnectAppPermissionFragmentTest
*/
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
class HealthConnectAppPermissionFragmentTest : BasePermissionUiTest() {
- @Before
- fun assumeNotTelevision() = assumeFalse(isTelevision)
+ @Before fun assumeNotTelevision() = assumeFalse(isTelevision)
@Before
fun wakeScreenUp() {
@@ -61,9 +59,7 @@ class HealthConnectAppPermissionFragmentTest : BasePermissionUiTest() {
startManageAppPermissionsActivity()
- eventually {
- waitFindObject(By.text(HEALTH_CONNECT_LABEL))
- }
+ eventually { waitFindObject(By.text(HEALTH_CONNECT_LABEL)) }
}
@Test
@@ -85,19 +81,18 @@ class HealthConnectAppPermissionFragmentTest : BasePermissionUiTest() {
startManageAppPermissionsActivity()
- eventually {
- waitFindObject(By.text(HEALTH_CONNECT_LABEL))
- }
+ eventually { waitFindObject(By.text(HEALTH_CONNECT_LABEL)) }
}
private fun startManageAppPermissionsActivity() {
runWithShellPermissionIdentity {
- instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS)
- .apply {
+ instrumentationContext.startActivity(
+ Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
putExtra(Intent.EXTRA_PACKAGE_NAME, PERM_USER_PACKAGE)
- })
+ }
+ )
}
}
@@ -109,4 +104,4 @@ class HealthConnectAppPermissionFragmentTest : BasePermissionUiTest() {
private val TIMEOUT_SHORT = 500L
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/LocationPermissionAppsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/LocationPermissionAppsFragmentTest.kt
index 3b48d7235..c1cfd30af 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/LocationPermissionAppsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/LocationPermissionAppsFragmentTest.kt
@@ -24,11 +24,13 @@ import org.junit.runner.RunWith
* Simple tests for {@link PermissionAppsFragment} when showing location permission
*
* Currently, does NOT run on TV (same as the other tests that extend [PermissionAppsFragmentTest]).
+ *
* TODO(b/178576541): Adapt and run on TV.
*/
@RunWith(AndroidJUnit4::class)
-class LocationPermissionAppsFragmentTest : PermissionAppsFragmentTest(
- "/data/local/tmp/permissioncontroller/tests/permissionui/AppThatRequestsLocation.apk",
- "android.permission.cts.appthatrequestpermission",
- ACCESS_COARSE_LOCATION
-)
+class LocationPermissionAppsFragmentTest :
+ PermissionAppsFragmentTest(
+ "/data/local/tmp/permissioncontroller/tests/permissionui/AppThatRequestsLocation.apk",
+ "android.permission.cts.appthatrequestpermission",
+ ACCESS_COARSE_LOCATION
+ )
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/PermissionAppsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/PermissionAppsFragmentTest.kt
index a5453d9e7..14c77776c 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/PermissionAppsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/PermissionAppsFragmentTest.kt
@@ -37,6 +37,7 @@ import org.junit.Test
* <p>Leave abstract to prevent the test runner from trying to run it
*
* Currently, none of the tests that extend [PermissionAppsFragmentTest] run on TV.
+ *
* TODO(b/178576541): Adapt and run on TV.
*/
abstract class PermissionAppsFragmentTest(
@@ -47,8 +48,7 @@ abstract class PermissionAppsFragmentTest(
val definerPkg: String? = null
) : BasePermissionUiTest() {
- @Before
- fun assumeNotTelevision() = assumeFalse(isTelevision)
+ @Before fun assumeNotTelevision() = assumeFalse(isTelevision)
@Before
fun wakeScreenUp() {
@@ -65,11 +65,12 @@ abstract class PermissionAppsFragmentTest(
@Before
fun startManagePermissionAppsActivity() {
runWithShellPermissionIdentity {
- instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_PERMISSION_APPS)
- .apply {
+ instrumentationContext.startActivity(
+ Intent(Intent.ACTION_MANAGE_PERMISSION_APPS).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra(Intent.EXTRA_PERMISSION_NAME, perm)
- })
+ }
+ )
}
}
@@ -78,9 +79,7 @@ abstract class PermissionAppsFragmentTest(
assertNull(waitFindObjectOrNull(By.text(userPkg)))
install(userApk)
- eventually {
- waitFindObject(By.text(userPkg))
- }
+ eventually { waitFindObject(By.text(userPkg)) }
}
// TODO(b/280652042) Slow tests aren't good
@@ -89,14 +88,10 @@ abstract class PermissionAppsFragmentTest(
assertNull(waitFindObjectOrNull(By.text(userPkg)))
install(userApk)
- eventually {
- waitFindObject(By.text(userPkg))
- }
+ eventually { waitFindObject(By.text(userPkg)) }
uninstallApp(userPkg)
- eventually {
- assertNull(waitFindObjectOrNull(By.text(userPkg)))
- }
+ eventually { assertNull(waitFindObjectOrNull(By.text(userPkg))) }
}
@After
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/StoragePermissionAppsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/StoragePermissionAppsFragmentTest.kt
index ada143613..5046bea85 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/StoragePermissionAppsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/StoragePermissionAppsFragmentTest.kt
@@ -24,12 +24,14 @@ import org.junit.runner.RunWith
* Simple tests for {@link PermissionAppsFragment} when showing location permission
*
* Currently, does NOT run on TV (same as the other tests that extend [PermissionAppsFragmentTest]).
+ *
* TODO(b/178576541): Adapt and run on TV.
*/
@RunWith(AndroidJUnit4::class)
-class StoragePermissionAppsFragmentTest : PermissionAppsFragmentTest(
- "/data/local/tmp/permissioncontroller/tests/permissionui" +
- "/PermissionUiUseStoragePermissionApp.apk",
- "com.android.permissioncontroller.tests.appthatrequestpermission",
- READ_EXTERNAL_STORAGE
-)
+class StoragePermissionAppsFragmentTest :
+ PermissionAppsFragmentTest(
+ "/data/local/tmp/permissioncontroller/tests/permissionui" +
+ "/PermissionUiUseStoragePermissionApp.apk",
+ "com.android.permissioncontroller.tests.appthatrequestpermission",
+ READ_EXTERNAL_STORAGE
+ )
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/TestAppUtils.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/TestAppUtils.kt
index 523ce6dc0..e715b03e3 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/TestAppUtils.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/TestAppUtils.kt
@@ -38,8 +38,7 @@ private const val ADDITIONAL_PERM_DEFINER_APK =
// All 4 of the AppThatUses_X_Permission(s) applications share the same package name.
private const val PERM_DEFINER_PACKAGE =
"com.android.permissioncontroller.tests.appthatdefinespermission"
-const val PERM_USER_PACKAGE =
- "com.android.permissioncontroller.tests.appthatrequestpermission"
+const val PERM_USER_PACKAGE = "com.android.permissioncontroller.tests.appthatrequestpermission"
const val CAMERA_TEST_APP_LABEL = "CameraRequestApp"
@@ -52,12 +51,18 @@ const val TEST_APP_DEFINED_PERMISSION_B_LABEL = "Permission B"
const val TEST_APP_DEFINED_PERMISSION_C_LABEL = "Permission C"
fun installTestAppThatRequestsLocation() = install(LOCATION_PERM_USER_APK)
+
fun installTestAppThatUsesCameraPermission() = install(CAMERA_PERM_USER_APK)
+
fun installTestAppThatUsesHealthConnectPermission() = install(HEALTH_CONNECT_PERMISSION_USER_APK)
+
fun installInvalidTestAppThatUsesHealthConnectPermission() =
install(INVALID_HEALTH_CONNECT_PERMISSION_USER_APK)
+
fun installTestAppThatUsesAdditionalPermission() = install(ADDITIONAL_PERM_USER_APK)
+
fun installTestAppThatUsesTwoAdditionalPermissions() = install(TWO_ADDITIONAL_PERM_USER_APK)
+
fun installTestAppThatDefinesAdditionalPermissions() = install(ADDITIONAL_PERM_DEFINER_APK)
fun uninstallTestApps() {
@@ -65,4 +70,4 @@ fun uninstallTestApps() {
uninstallApp(PERM_DEFINER_PACKAGE)
}
-fun grantTestAppPermission(permission: String) = grantPermission(PERM_USER_PACKAGE, permission) \ No newline at end of file
+fun grantTestAppPermission(permission: String) = grantPermission(PERM_USER_PACKAGE, permission)
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/BaseHandheldPermissionUiTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/BaseHandheldPermissionUiTest.kt
index 66e254155..7f005e489 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/BaseHandheldPermissionUiTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/BaseHandheldPermissionUiTest.kt
@@ -21,6 +21,5 @@ import org.junit.Assume.assumeFalse
import org.junit.Before
abstract class BaseHandheldPermissionUiTest : BasePermissionUiTest() {
- @Before
- fun assumeNotTelevision() = assumeFalse(isTelevision)
-} \ No newline at end of file
+ @Before fun assumeNotTelevision() = assumeFalse(isTelevision)
+}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageCustomPermissionsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageCustomPermissionsFragmentTest.kt
index c41dacc96..4f2360aaa 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageCustomPermissionsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageCustomPermissionsFragmentTest.kt
@@ -21,8 +21,8 @@ import android.permission.cts.PermissionUtils.grantPermission
import android.permission.cts.PermissionUtils.install
import android.permission.cts.PermissionUtils.revokePermission
import android.permission.cts.PermissionUtils.uninstallApp
-import androidx.test.uiautomator.By
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.uiautomator.By
import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject
@@ -34,9 +34,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Simple tests for {@link ManageCustomPermissionsFragment}
- */
+/** Simple tests for {@link ManageCustomPermissionsFragment} */
@RunWith(AndroidJUnit4::class)
class ManageCustomPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
private val ONE_PERMISSION_DEFINER_APK =
@@ -57,9 +55,11 @@ class ManageCustomPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
wakeUpScreen()
runWithShellPermissionIdentity {
- instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply {
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- })
+ instrumentationContext.startActivity(
+ Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ )
}
}
@@ -88,14 +88,10 @@ class ManageCustomPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
val original = getUsageCountsFromUi(PERM_LABEL)
grantPermission(USER_PKG, PERM)
- eventually {
- assertThat(getUsageCountsFromUi(PERM_LABEL)).isNotEqualTo(original)
- }
+ eventually { assertThat(getUsageCountsFromUi(PERM_LABEL)).isNotEqualTo(original) }
revokePermission(USER_PKG, PERM)
- eventually {
- assertThat(getUsageCountsFromUi(PERM_LABEL)).isEqualTo(original)
- }
+ eventually { assertThat(getUsageCountsFromUi(PERM_LABEL)).isEqualTo(original) }
}
@After
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageStandardPermissionsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageStandardPermissionsFragmentTest.kt
index 5d0fae9a1..0181903aa 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageStandardPermissionsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageStandardPermissionsFragmentTest.kt
@@ -22,8 +22,8 @@ import android.permission.cts.PermissionUtils.grantPermission
import android.permission.cts.PermissionUtils.install
import android.permission.cts.PermissionUtils.revokePermission
import android.permission.cts.PermissionUtils.uninstallApp
-import androidx.test.uiautomator.By
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.uiautomator.By
import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.SystemUtil.getEventually
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
@@ -36,9 +36,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Simple tests for {@link ManageStandardPermissionsFragment}
- */
+/** Simple tests for {@link ManageStandardPermissionsFragment} */
@RunWith(AndroidJUnit4::class)
class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
private val LOCATION_USER_APK =
@@ -68,14 +66,15 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
waitFindObjectOrNull(By.textContains(ADDITIONAL_PERMISSIONS_LABEL)) ?: return 0
// Sometimes the entire preference disappears while it's searching for the app count
// (during uninstalling). Hence also return the count as 0 if count doesn't exist
- val additionalPermissionsSummary = waitFindObjectOrNull(
- By.textContains(ADDITIONAL_PERMISSIONS_SUMMARY)) ?: return 0
+ val additionalPermissionsSummary =
+ waitFindObjectOrNull(By.textContains(ADDITIONAL_PERMISSIONS_SUMMARY)) ?: return 0
val additionalPermissionsSummaryText = additionalPermissionsSummary.getText()
// Matches a single number out of the summary line, i.e. "...3..." -> "3"
return getEventually {
Regex("^[^\\d]*(\\d+)[^\\d]*\$")
- .find(additionalPermissionsSummaryText)!!.groupValues[1]
+ .find(additionalPermissionsSummaryText)!!
+ .groupValues[1]
.toInt()
}
}
@@ -85,9 +84,11 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
wakeUpScreen()
runWithShellPermissionIdentity {
- instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply {
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- })
+ instrumentationContext.startActivity(
+ Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ )
}
reuninstallApp(LOCATION_USER_APK, LOCATION_USER_PKG)
@@ -114,15 +115,11 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
val original = getUsageCountsFromUi(locationGroupLabel)
install(LOCATION_USER_APK)
- eventually {
- assertThat(getUsageCountsFromUi(locationGroupLabel)).isNotEqualTo(original)
- }
+ eventually { assertThat(getUsageCountsFromUi(locationGroupLabel)).isNotEqualTo(original) }
uninstallApp(LOCATION_USER_PKG)
reuninstallApp(LOCATION_USER_APK, LOCATION_USER_PKG)
- eventually {
- assertThat(getUsageCountsFromUi(locationGroupLabel)).isEqualTo(original)
- }
+ eventually { assertThat(getUsageCountsFromUi(locationGroupLabel)).isEqualTo(original) }
}
@Test
@@ -131,8 +128,7 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
install(LOCATION_USER_APK)
eventually {
- assertThat(getUsageCountsFromUi(locationGroupLabel).total)
- .isEqualTo(original.total + 1)
+ assertThat(getUsageCountsFromUi(locationGroupLabel).total).isEqualTo(original.total + 1)
}
grantPermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION)
@@ -149,16 +145,14 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
install(LOCATION_USER_APK)
grantPermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION)
eventually {
- assertThat(getUsageCountsFromUi(locationGroupLabel).total)
- .isNotEqualTo(original.total)
+ assertThat(getUsageCountsFromUi(locationGroupLabel).total).isNotEqualTo(original.total)
assertThat(getUsageCountsFromUi(locationGroupLabel).granted)
.isNotEqualTo(original.granted)
}
revokePermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION)
eventually {
- assertThat(getUsageCountsFromUi(locationGroupLabel).granted)
- .isEqualTo(original.granted)
+ assertThat(getUsageCountsFromUi(locationGroupLabel).granted).isEqualTo(original.granted)
}
}
@@ -169,8 +163,7 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
install(ADDITIONAL_DEFINER_APK)
install(ADDITIONAL_USER_APK)
eventually {
- assertThat(getAdditionalPermissionCount())
- .isEqualTo(additionalPermissionBefore + 1)
+ assertThat(getAdditionalPermissionCount()).isEqualTo(additionalPermissionBefore + 1)
}
}
@@ -181,8 +174,7 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
install(ADDITIONAL_DEFINER_APK)
install(ADDITIONAL_USER_APK)
eventually {
- assertThat(getAdditionalPermissionCount())
- .isNotEqualTo(additionalPermissionBefore)
+ assertThat(getAdditionalPermissionCount()).isNotEqualTo(additionalPermissionBefore)
}
uninstallApp(ADDITIONAL_USER_PKG)
@@ -198,8 +190,7 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
install(ADDITIONAL_DEFINER_APK)
install(ADDITIONAL_USER_APK)
eventually {
- assertThat(getAdditionalPermissionCount())
- .isNotEqualTo(additionalPermissionBefore)
+ assertThat(getAdditionalPermissionCount()).isNotEqualTo(additionalPermissionBefore)
}
uninstallApp(ADDITIONAL_DEFINER_PKG)
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ReviewOngoingUsageFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ReviewOngoingUsageFragmentTest.kt
index ec9971cb4..dc654047d 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ReviewOngoingUsageFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ReviewOngoingUsageFragmentTest.kt
@@ -30,9 +30,7 @@ import org.junit.After
import org.junit.Before
import org.junit.Test
-/**
- * Simple tests for {@link ReviewOngoingUsageFragment}
- */
+/** Simple tests for {@link ReviewOngoingUsageFragment} */
class ReviewOngoingUsageFragmentTest : PermissionHub2Test() {
@Before
@@ -46,14 +44,15 @@ class ReviewOngoingUsageFragmentTest : PermissionHub2Test() {
@Test
fun cameraAccessShouldBeShown() {
runWithShellPermissionIdentity {
- context.startActivity(Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE).apply {
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- })
+ context.startActivity(
+ Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ )
}
waitFindObject(By.textContains(CAMERA_TEST_APP_LABEL)).click()
}
- @After
- fun cleanUp() = uninstallTestApps()
-} \ No newline at end of file
+ @After fun cleanUp() = uninstallTestApps()
+}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/v31/PermissionUsageFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/v31/PermissionUsageFragmentTest.kt
index 45cc52649..6286b1131 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/v31/PermissionUsageFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/v31/PermissionUsageFragmentTest.kt
@@ -29,8 +29,8 @@ import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject
import com.android.permissioncontroller.permissionui.PermissionHub2Test
-import com.android.permissioncontroller.permissionui.wakeUpScreen
import com.android.permissioncontroller.permissionui.pressHome
+import com.android.permissioncontroller.permissionui.wakeUpScreen
import org.junit.After
import org.junit.Before
import org.junit.Test
@@ -61,8 +61,7 @@ class PermissionUsageFragmentTest : PermissionHub2Test() {
runWithShellPermissionIdentity {
context.startActivity(
- Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE)
- .apply {
+ Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/ManagePermissionsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/ManagePermissionsFragmentTest.kt
index f3171c7d5..9794d787d 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/ManagePermissionsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/ManagePermissionsFragmentTest.kt
@@ -27,42 +27,49 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Run with:
- * atest ManagePermissionsFragmentTest
- */
+/** Run with: atest ManagePermissionsFragmentTest */
@RunWith(AndroidJUnit4::class)
class ManagePermissionsFragmentTest : TelevisionUiBaseTest() {
- @Before
- fun launch() = launchPermissionController()
+ @Before fun launch() = launchPermissionController()
@Test
fun test_bodySensors_permissionGroup_isNotShown() {
- assertFalse("Found \"Body sensors\" permission",
- uiDevice.hasElementWithTitle(bodySensorsPermissionLabel))
+ assertFalse(
+ "Found \"Body sensors\" permission",
+ uiDevice.hasElementWithTitle(bodySensorsPermissionLabel)
+ )
}
@Test
fun test_camera_permissionGroup_isShown_whenUsed() {
// Make sure Camera permission group is not shown at first.
- assertFalse("Found \"Camera\" permission",
- uiDevice.hasElementWithTitle(cameraPermissionLabel))
+ assertFalse(
+ "Found \"Camera\" permission",
+ uiDevice.hasElementWithTitle(cameraPermissionLabel)
+ )
// Install app that uses Camera permission...
installTestAppThatUsesCameraPermission()
// ... grant the permission ...
grantTestAppPermission(CAMERA)
// ... make sure now the Camera permission is shown.
- assertTrue("Could not find \"Camera\" permission",
- uiDevice.focusOnElementWithTitle(cameraPermissionLabel))
+ assertTrue(
+ "Could not find \"Camera\" permission",
+ uiDevice.focusOnElementWithTitle(cameraPermissionLabel)
+ )
}
@Test
fun test_otherPermissions_Button_isShown() {
uiDevice.navigateToTheBottom()
- assertEquals("The last item should be the \"Other permissions\" button",
- otherPermissionsLabel, uiDevice.focusedElementTitle)
- assertTrue("\"Other permissions\" button should be clickable",
- uiDevice.focusedElement.isClickable)
+ assertEquals(
+ "The last item should be the \"Other permissions\" button",
+ otherPermissionsLabel,
+ uiDevice.focusedElementTitle
+ )
+ assertTrue(
+ "\"Other permissions\" button should be clickable",
+ uiDevice.focusedElement.isClickable
+ )
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/ManagePermissionsOtherFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/ManagePermissionsOtherFragmentTest.kt
index f7cf27c72..2d338906b 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/ManagePermissionsOtherFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/ManagePermissionsOtherFragmentTest.kt
@@ -29,10 +29,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Run with:
- * atest ManagePermissionsOtherFragmentTest
- */
+/** Run with: atest ManagePermissionsOtherFragmentTest */
@RunWith(AndroidJUnit4::class)
class ManagePermissionsOtherFragmentTest : TelevisionUiBaseTest() {
@@ -45,20 +42,27 @@ class ManagePermissionsOtherFragmentTest : TelevisionUiBaseTest() {
uiDevice.waitForIdle()
// Making sure are on the "Other permission" page now.
// For this we can check the Fragment's title.
- assertEquals("\"Other permissions\" didn't open",
- otherPermissionsLabel, uiDevice.fragmentDecorTitle)
+ assertEquals(
+ "\"Other permissions\" didn't open",
+ otherPermissionsLabel,
+ uiDevice.fragmentDecorTitle
+ )
}
@Test
fun bodySensors_permissionGroup_isNotShown() {
- assertFalse("Found \"Body sensors\" permission",
- uiDevice.focusOnElementWithTitle(bodySensorsPermissionLabel))
+ assertFalse(
+ "Found \"Body sensors\" permission",
+ uiDevice.focusOnElementWithTitle(bodySensorsPermissionLabel)
+ )
}
@Test
fun additionalPermissions_section_isNotShown_ifAllUnused() {
- assertFalse("\"Additional permissions\" section is shown",
- uiDevice.hasElementWithTitle(additionalPermissionsLabel))
+ assertFalse(
+ "\"Additional permissions\" section is shown",
+ uiDevice.hasElementWithTitle(additionalPermissionsLabel)
+ )
}
@Test
@@ -72,10 +76,14 @@ class ManagePermissionsOtherFragmentTest : TelevisionUiBaseTest() {
grantTestAppPermission(TEST_APP_DEFINED_PERMISSION_A)
// Make sure the "Additional permissions" section is now shown...
- assertTrue("\"Additional permissions\" section should be shown",
- uiDevice.hasElementWithTitle(additionalPermissionsLabel))
+ assertTrue(
+ "\"Additional permissions\" section should be shown",
+ uiDevice.hasElementWithTitle(additionalPermissionsLabel)
+ )
// ... and that we now have "Permission A" row.
- assertTrue("Could not find \"Permission A\" row",
- uiDevice.focusOnElementWithTitle(TEST_APP_DEFINED_PERMISSION_A_LABEL))
+ assertTrue(
+ "Could not find \"Permission A\" row",
+ uiDevice.focusOnElementWithTitle(TEST_APP_DEFINED_PERMISSION_A_LABEL)
+ )
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/TelevisionUiBaseTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/TelevisionUiBaseTest.kt
index c289afa6e..f56544660 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/TelevisionUiBaseTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/TelevisionUiBaseTest.kt
@@ -30,8 +30,7 @@ abstract class TelevisionUiBaseTest : BasePermissionUiTest() {
val otherPermissionsLabel = "Other permissions"
val additionalPermissionsLabel = "Additional permissions"
- @Before
- fun assumeTelevision() = assumeTrue(isTelevision)
+ @Before fun assumeTelevision() = assumeTrue(isTelevision)
@Before
fun wakeUpAndGoToHomeScreen() {
@@ -39,16 +38,17 @@ abstract class TelevisionUiBaseTest : BasePermissionUiTest() {
uiDevice.pressHome()
}
- @After
- fun cleanUp() = uninstallTestApps()
+ @After fun cleanUp() = uninstallTestApps()
protected fun launchPermissionController() {
SystemUtil.runWithShellPermissionIdentity {
- instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply {
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- })
+ instrumentationContext.startActivity(
+ Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ )
}
uiDevice.waitForIdle()
}
-} \ No newline at end of file
+}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/TelevisionUtils.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/TelevisionUtils.kt
index b221eae70..8caac313e 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/TelevisionUtils.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/television/TelevisionUtils.kt
@@ -34,17 +34,20 @@ val UiDevice.fragmentDecorTitle: String?
get() = wait(Until.findObject(SELECTOR_RES_ID_PC_DECOR_TITLE), WAIT_DELAY)?.text
val UiDevice.focusedElement: UiObject2
- get() = wait(Until.findObject(SELECTOR_FOCUSED), WAIT_DELAY)
- ?: error("Focused item is not found")
+ get() =
+ wait(Until.findObject(SELECTOR_FOCUSED), WAIT_DELAY) ?: error("Focused item is not found")
private val UiObject2.titleElement: UiObject2
- get() = wait(Until.findObject(SELECTOR_RES_ID_ANDROID_TITLE), WAIT_DELAY)
- ?: error("Could not retrieve title")
+ get() =
+ wait(Until.findObject(SELECTOR_RES_ID_ANDROID_TITLE), WAIT_DELAY)
+ ?: error("Could not retrieve title")
val UiDevice.focusedElementTitle: String?
get() {
repeat(RETRIES) {
- try { return focusedElement.titleElement.text } catch (e: StaleObjectException) {}
+ try {
+ return focusedElement.titleElement.text
+ } catch (e: StaleObjectException) {}
}
error("Could not get title text")
}
@@ -63,13 +66,13 @@ fun UiDevice.navigateToTheTop() {
while (navigateUp()) {}
}
-fun UiDevice.focusOnElementWithTitle(title: CharSequence): Boolean =
- checkAllItemsIfNeeded { focusedElementTitle == title }
+fun UiDevice.focusOnElementWithTitle(title: CharSequence): Boolean = checkAllItemsIfNeeded {
+ focusedElementTitle == title
+}
-fun UiDevice.hasElementWithTitle(title: CharSequence): Boolean =
- checkAllItemsIfNeeded {
- hasObject(By.copy(SELECTOR_RES_ID_ANDROID_TITLE).text(title.toString()))
- }
+fun UiDevice.hasElementWithTitle(title: CharSequence): Boolean = checkAllItemsIfNeeded {
+ hasObject(By.copy(SELECTOR_RES_ID_ANDROID_TITLE).text(title.toString()))
+}
private fun UiDevice.checkAllItemsIfNeeded(predicate: () -> Boolean): Boolean {
// Let's do one quick check first, right where we are. If it does not work - we'll do the walk.
@@ -93,4 +96,4 @@ private fun UiDevice.navigate(action: () -> Unit): Boolean {
waitForIdle()
return prevFocusedTitle != focusedElementTitle
-} \ No newline at end of file
+}
diff --git a/SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresTiramisuByDefault.java b/SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresTiramisuByDefault.java
deleted file mode 100644
index 6e1f4c3b7..000000000
--- a/SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresTiramisuByDefault.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.safetycenter.annotations;
-
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
-import static java.lang.annotation.ElementType.PACKAGE;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import androidx.annotation.RequiresApi;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import javax.annotation.meta.TypeQualifierDefault;
-
-/**
- * Specifies that all types are {@code RequiresApi(TIRAMISU)} within the annotated package, unless
- * tagged another {@code @RequiresApi} annotation.
- */
-@Retention(CLASS)
-@Target(PACKAGE)
-@TypeQualifierDefault({TYPE})
-@RequiresApi(TIRAMISU)
-public @interface RequiresTiramisuByDefault {}
diff --git a/SafetyCenter/Resources/res/values-da/strings.xml b/SafetyCenter/Resources/res/values-da/strings.xml
index 16df659b8..59d275320 100644
--- a/SafetyCenter/Resources/res/values-da/strings.xml
+++ b/SafetyCenter/Resources/res/values-da/strings.xml
@@ -24,7 +24,7 @@
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"Der er ingen oplysninger endnu"</string>
<string name="lock_screen_search_terms" msgid="2678486357779794826">"Enhedslås, skærmlås, låseskærm, adgangskode, pinkode, mønster"</string>
<string name="biometrics_title" msgid="5859504610285212938">"Biometri"</string>
- <string name="biometrics_search_terms" msgid="6040319118762671981">"Fingeraftryk, finger, tilføj fingeraftryk, ansigtslås, ansigt"</string>
+ <string name="biometrics_search_terms" msgid="6040319118762671981">"Fingeraftryk, finger, tilføj fingeraftryk, ansigtsoplåsning, ansigt"</string>
<string name="privacy_sources_title" msgid="4061110826457365957">"Privatliv"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Kontrolpanel, tilladelser, styringselementer"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Privatlivspanel"</string>
diff --git a/SafetyCenter/Resources/res/values-eu-v34/strings.xml b/SafetyCenter/Resources/res/values-eu-v34/strings.xml
index dae0daaab..20f2cfbaf 100644
--- a/SafetyCenter/Resources/res/values-eu-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-eu-v34/strings.xml
@@ -22,8 +22,8 @@
<string name="privacy_sources_summary" msgid="4083646673569677049">"Baimenak, panela eta ezarpenak"</string>
<string name="health_connect_title" msgid="8318152190040327804">"Health Connect"</string>
<string name="health_connect_search_terms" msgid="4998970586245680829">"Osasuna, Health Connect"</string>
- <string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Kokapen-datuak partekatzeko moduaren inguruko berritasunak"</string>
- <string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"datuak, datuak partekatzea, datuak partekatzeko moduaren inguruko berritasunak, kokapen-datuak partekatzeko moduaren inguruko berritasunak, partekatzea"</string>
+ <string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Kokapen-datuak partekatzeko aukeraren berritasunak"</string>
+ <string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"datuak, datuak partekatzeko aukera, datuak partekatzeko aukeraren berritasunak, kokapen-datuak partekatzeko aukeraren berritasunak, partekatzea"</string>
<string name="advanced_title" msgid="6259362998269627310">"Beste ezarpen batzuk"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Segurtasun eta pribatutasun gehiago"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Betetze automatikoa, jakinarazpenak eta abar"</string>
diff --git a/SafetyCenter/Resources/res/values-it/strings.xml b/SafetyCenter/Resources/res/values-it/strings.xml
index b3ff1668c..02f431a9a 100644
--- a/SafetyCenter/Resources/res/values-it/strings.xml
+++ b/SafetyCenter/Resources/res/values-it/strings.xml
@@ -24,7 +24,7 @@
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"Ancora nessuna informazione"</string>
<string name="lock_screen_search_terms" msgid="2678486357779794826">"Blocco dispositivo, Blocco schermo, Schermata di blocco, Password, PIN, Sequenza"</string>
<string name="biometrics_title" msgid="5859504610285212938">"Dati biometrici"</string>
- <string name="biometrics_search_terms" msgid="6040319118762671981">"Impronta, Dito, Aggiungi impronta, Sblocco con il volto, Volto"</string>
+ <string name="biometrics_search_terms" msgid="6040319118762671981">"Impronta, Dito, Aggiungi impronta, Sblocco con il Volto, Volto"</string>
<string name="privacy_sources_title" msgid="4061110826457365957">"Privacy"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Dashboard, autorizzazioni, impostazioni"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Dashboard della privacy"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ca/strings.xml b/SafetyCenter/Resources/shared_res/values-ca/strings.xml
index a2d8b0f35..640a723c1 100644
--- a/SafetyCenter/Resources/shared_res/values-ca/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ca/strings.xml
@@ -26,7 +26,7 @@
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Revisa la configuració"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Comprova la llista d\'opcions de configuració"</string>
<string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"El dispositiu pot estar en perill"</string>
- <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"El dispositiu està en perill"</string>
+ <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"Dispositiu en perill"</string>
<string name="overall_severity_level_data_recommendation_title" msgid="1424269714861655302">"Les dades poden estar en perill"</string>
<string name="overall_severity_level_critical_data_warning_title" msgid="1012704126634698604">"Les dades estan en perill"</string>
<string name="overall_severity_level_passwords_recommendation_title" msgid="8625105570296877719">"Contrasenyes en perill (antigues)"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ja/strings.xml b/SafetyCenter/Resources/shared_res/values-ja/strings.xml
index 393ca271c..c6d76eb2c 100644
--- a/SafetyCenter/Resources/shared_res/values-ja/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ja/strings.xml
@@ -37,7 +37,7 @@
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"リスクが検出されました"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"アカウントが危険にさらされています"</string>
<string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"アカウントが危険です"</string>
- <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{アラートを確認する}other{アラートを確認する}}"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{アラートを確認してください}other{アラートを確認してください}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"ページを開けませんでした"</string>
<string name="resolving_action_error" msgid="371968886143262375">"アラートを解決できませんでした"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{設定を確認できませんでした}other{設定を確認できませんでした}}"</string>
diff --git a/apex_manifest.json b/apex_manifest.json
index 44d557cd5..99141267d 100644
--- a/apex_manifest.json
+++ b/apex_manifest.json
@@ -3,5 +3,5 @@
// Placeholder module version to be replaced during build.
// Do not change!
- "version": 341110000
+ "version": 341310000
}
diff --git a/framework-s/java/android/app/role/RoleManager.java b/framework-s/java/android/app/role/RoleManager.java
index de697f801..5b927084d 100644
--- a/framework-s/java/android/app/role/RoleManager.java
+++ b/framework-s/java/android/app/role/RoleManager.java
@@ -527,8 +527,8 @@ public final class RoleManager {
public void setDefaultApplication(@NonNull String roleName, @Nullable String packageName,
@ManageHoldersFlags int flags, @CallbackExecutor @NonNull Executor executor,
@NonNull Consumer<Boolean> callback) {
+ // Prior to Android V some devices might require the "packageName" to be non-null.
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
Objects.requireNonNull(executor, "executor cannot be null");
Objects.requireNonNull(callback, "callback cannot be null");
try {
diff --git a/framework-s/java/android/safetycenter/SafetySourceIssue.java b/framework-s/java/android/safetycenter/SafetySourceIssue.java
index de75aa298..b6e291fe3 100644
--- a/framework-s/java/android/safetycenter/SafetySourceIssue.java
+++ b/framework-s/java/android/safetycenter/SafetySourceIssue.java
@@ -956,6 +956,8 @@ public final class SafetySourceIssue implements Parcelable {
mConfirmationDialogDetails = action.mConfirmationDialogDetails;
}
+ // TODO(b/303443020): Add setters for id, label, and pendingIntent
+
/**
* Sets whether the action will resolve the safety issue. Defaults to {@code false}.
*
diff --git a/ktfmt_includes.txt b/ktfmt_includes.txt
index 40d8f07d9..5917fc714 100644
--- a/ktfmt_includes.txt
+++ b/ktfmt_includes.txt
@@ -1,2 +1,3 @@
+SafetyCenter
++PermissionController
+tests
diff --git a/service/java/com/android/safetycenter/PendingIntentFactory.java b/service/java/com/android/safetycenter/PendingIntentFactory.java
index b52365c38..c4e9decd2 100644
--- a/service/java/com/android/safetycenter/PendingIntentFactory.java
+++ b/service/java/com/android/safetycenter/PendingIntentFactory.java
@@ -22,6 +22,7 @@ import android.annotation.UserIdInt;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.ResolveInfoFlags;
import android.content.pm.ResolveInfo;
@@ -60,9 +61,9 @@ public final class PendingIntentFactory {
* Creates or retrieves a {@link PendingIntent} that will start a new {@code Activity} matching
* the given {@code intentAction}.
*
- * <p>If the given {@code intentAction} resolves for the given {@code packageName}, the {@link
- * PendingIntent} will explicitly target the {@code packageName}. If the {@code intentAction}
- * resolves elsewhere, the {@link PendingIntent} will be implicit.
+ * <p>If the given {@code intentAction} resolves, the {@link PendingIntent} will use an implicit
+ * {@link Intent}. Otherwise, the {@link PendingIntent} will explicitly target the {@code
+ * packageName} if it resolves.
*
* <p>The {@code PendingIntent} is associated with a specific source given by {@code sourceId}.
*
@@ -70,7 +71,7 @@ public final class PendingIntentFactory {
* is no valid target for the given {@code intentAction}.
*/
@Nullable
- PendingIntent getPendingIntent(
+ public PendingIntent getPendingIntent(
String sourceId,
@Nullable String intentAction,
String packageName,
@@ -113,26 +114,25 @@ public final class PendingIntentFactory {
intent.setIdentifier("with_settings_homepage_extra");
}
+ if (intentResolvesToActivity(packageContext, intent)) {
+ return intent;
+ }
+
// If the intent resolves for the package provided, then we make the assumption that it is
// the desired app and make the intent explicit. This is to workaround implicit internal
// intents that may not be exported which will stop working on Android U+.
- // This assumes that the source or the caller has the highest priority to resolve the intent
- // action.
Intent explicitIntent = new Intent(intent).setPackage(packageContext.getPackageName());
- if (intentResolves(packageContext, explicitIntent)) {
+ if (intentResolvesToActivity(packageContext, explicitIntent)) {
return explicitIntent;
}
- if (intentResolves(packageContext, intent)) {
- return intent;
- }
-
// resolveActivity does not return any activity when the work profile is in quiet mode, even
// though it opens the quiet mode dialog and/or the original intent would otherwise resolve
// when quiet mode is turned off. So, we assume that the explicit intent will always resolve
// to this dialog. This heuristic is preferable on U+ as it has a higher chance of resolving
// once the work profile is enabled considering the implicit internal intent restriction.
if (isQuietModeEnabled) {
+ // TODO(b/266538628): Find a way to fix this, this heuristic isn't ideal.
return explicitIntent;
}
@@ -147,8 +147,20 @@ public final class PendingIntentFactory {
.contains(sourceId);
}
- private static boolean intentResolves(Context packageContext, Intent intent) {
- return resolveActivity(packageContext, intent) != null;
+ private static boolean intentResolvesToActivity(Context packageContext, Intent intent) {
+ ResolveInfo resolveInfo = resolveActivity(packageContext, intent);
+ if (resolveInfo == null) {
+ return false;
+ }
+ ActivityInfo activityInfo = resolveInfo.activityInfo;
+ if (activityInfo == null) {
+ return false;
+ }
+ boolean intentIsImplicit = intent.getPackage() == null && intent.getComponent() == null;
+ if (intentIsImplicit) {
+ return activityInfo.exported;
+ }
+ return true;
}
@Nullable
diff --git a/service/java/com/android/safetycenter/SafetyCenterFlags.java b/service/java/com/android/safetycenter/SafetyCenterFlags.java
index 821987ce9..67c4d25d6 100644
--- a/service/java/com/android/safetycenter/SafetyCenterFlags.java
+++ b/service/java/com/android/safetycenter/SafetyCenterFlags.java
@@ -32,6 +32,9 @@ import com.android.safetycenter.resources.SafetyCenterResourcesApk;
import java.io.PrintWriter;
import java.time.Duration;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
/**
* A class to access the Safety Center {@link DeviceConfig} flags.
@@ -102,6 +105,9 @@ public final class SafetyCenterFlags {
private static final String PROPERTY_TEMP_HIDDEN_ISSUE_RESURFACE_DELAY_MILLIS =
"safety_center_temp_hidden_issue_resurface_delay_millis";
+ private static final String PROPERTY_ACTIONS_TO_OVERRIDE_WITH_DEFAULT_INTENT =
+ "safety_center_actions_to_override_with_default_intent";
+
private static final Duration RESOLVING_ACTION_TIMEOUT_DEFAULT_DURATION =
Duration.ofSeconds(10);
@@ -127,6 +133,8 @@ public final class SafetyCenterFlags {
private static volatile String sRefreshOnPageOpenSourcesDefault = "AndroidBiometrics";
+ private static volatile String sActionsToOverrideWithDefaultIntentDefault = "";
+
static void init(SafetyCenterResourcesApk safetyCenterResourcesApk) {
String untrackedSourcesDefault =
safetyCenterResourcesApk.getOptionalStringByName("config_defaultUntrackedSources");
@@ -151,6 +159,12 @@ public final class SafetyCenterFlags {
if (refreshOnPageOpenSourcesDefault != null) {
sRefreshOnPageOpenSourcesDefault = refreshOnPageOpenSourcesDefault;
}
+ String actionsToOverrideWithDefaultIntentDefault =
+ safetyCenterResourcesApk.getOptionalStringByName(
+ "config_defaultActionsToOverrideWithDefaultIntent");
+ if (actionsToOverrideWithDefaultIntentDefault != null) {
+ sActionsToOverrideWithDefaultIntentDefault = actionsToOverrideWithDefaultIntentDefault;
+ }
}
private static final Duration TEMP_HIDDEN_ISSUE_RESURFACE_DELAY_DEFAULT_DURATION =
@@ -395,6 +409,17 @@ public final class SafetyCenterFlags {
return getString(PROPERTY_RESURFACE_ISSUE_DELAYS_MILLIS, RESURFACE_ISSUE_DELAYS_DEFAULT);
}
+ /**
+ * Returns a comma-delimited list of colon-delimited pairs of SourceId:ActionId. The action IDs
+ * listed by this flag should have their {@code PendingIntent}s overridden with the source's
+ * default intent drawn from Safety Center's config file, if available.
+ */
+ private static String getActionsToOverrideWithDefaultIntent() {
+ return getString(
+ PROPERTY_ACTIONS_TO_OVERRIDE_WITH_DEFAULT_INTENT,
+ sActionsToOverrideWithDefaultIntentDefault);
+ }
+
/** Returns a duration after which a temporarily hidden issue will resurface. */
public static Duration getTemporarilyHiddenIssueResurfaceDelay() {
return getDuration(
@@ -408,19 +433,10 @@ public final class SafetyCenterFlags {
*/
public static boolean isIssueCategoryAllowedForSource(
@SafetySourceIssue.IssueCategory int issueCategory, String safetySourceId) {
- String issueCategoryAllowlists = getIssueCategoryAllowlists();
- String allowlistString =
- getStringValueFromStringMapping(issueCategoryAllowlists, issueCategory);
- if (allowlistString == null) {
- return true;
- }
- String[] allowlistArray = allowlistString.split("\\|");
- for (int i = 0; i < allowlistArray.length; i++) {
- if (allowlistArray[i].equals(safetySourceId)) {
- return true;
- }
- }
- return false;
+ List<String> allowlist =
+ getStringListValueFromStringMapping(
+ getIssueCategoryAllowlists(), Integer.toString(issueCategory));
+ return allowlist.isEmpty() || allowlist.contains(safetySourceId);
}
/** Returns a set of package certificates allowlisted for the given package name. */
@@ -452,6 +468,16 @@ public final class SafetyCenterFlags {
}
/**
+ * Returns a list of action IDs that should be overridden with the source's default intent drawn
+ * from the config for a given source.
+ */
+ public static List<String> getActionsToOverrideWithDefaultIntentForSource(
+ String safetySourceId) {
+ return getStringListValueFromStringMapping(
+ getActionsToOverrideWithDefaultIntent(), safetySourceId);
+ }
+
+ /**
* Returns whether to show subpages in the Safety Center UI for Android-U instead of the
* expand-and-collapse list implementation.
*/
@@ -515,15 +541,15 @@ public final class SafetyCenterFlags {
* pairs of integers and longs.
*/
@Nullable
- private static Long getLongValueFromStringMapping(String config, int key) {
- String valueString = getStringValueFromStringMapping(config, key);
+ private static Long getLongValueFromStringMapping(String mapping, int key) {
+ String valueString = getStringValueFromStringMapping(mapping, key);
if (valueString == null) {
return null;
}
try {
return Long.parseLong(valueString);
} catch (NumberFormatException e) {
- Log.w(TAG, "Badly formatted string config: " + config, e);
+ Log.w(TAG, "Badly formatted string mapping: " + mapping, e);
return null;
}
}
@@ -533,8 +559,8 @@ public final class SafetyCenterFlags {
* of integers and strings.
*/
@Nullable
- private static String getStringValueFromStringMapping(String config, int key) {
- return getStringValueFromStringMapping(config, Integer.toString(key));
+ private static String getStringValueFromStringMapping(String mapping, int key) {
+ return getStringValueFromStringMapping(mapping, Integer.toString(key));
}
/**
@@ -542,15 +568,15 @@ public final class SafetyCenterFlags {
* string pairs.
*/
@Nullable
- private static String getStringValueFromStringMapping(String config, String key) {
- if (config.isEmpty()) {
+ private static String getStringValueFromStringMapping(String mapping, String key) {
+ if (mapping.isEmpty()) {
return null;
}
- String[] pairsList = config.split(",");
+ String[] pairsList = mapping.split(",");
for (int i = 0; i < pairsList.length; i++) {
String[] pair = pairsList[i].split(":", -1 /* allow trailing empty strings */);
if (pair.length != 2) {
- Log.w(TAG, "Badly formatted string config: " + config);
+ Log.w(TAG, "Badly formatted string mapping: " + mapping);
continue;
}
if (pair[0].equals(key)) {
@@ -560,5 +586,14 @@ public final class SafetyCenterFlags {
return null;
}
+ private static List<String> getStringListValueFromStringMapping(String mapping, String key) {
+ String value = getStringValueFromStringMapping(mapping, key);
+ if (value == null) {
+ return Collections.emptyList();
+ }
+
+ return Arrays.asList(value.split("\\|"));
+ }
+
private SafetyCenterFlags() {}
}
diff --git a/service/java/com/android/safetycenter/SafetyCenterService.java b/service/java/com/android/safetycenter/SafetyCenterService.java
index 578997355..1c72e7118 100644
--- a/service/java/com/android/safetycenter/SafetyCenterService.java
+++ b/service/java/com/android/safetycenter/SafetyCenterService.java
@@ -76,9 +76,9 @@ import com.android.modules.utils.BackgroundThread;
import com.android.modules.utils.build.SdkLevel;
import com.android.permission.util.ForegroundThread;
import com.android.permission.util.UserUtils;
-import com.android.safetycenter.data.AndroidLockScreenFix;
import com.android.safetycenter.data.SafetyCenterDataManager;
import com.android.safetycenter.data.SafetyEventFix;
+import com.android.safetycenter.data.SafetySourceDataFix;
import com.android.safetycenter.internaldata.SafetyCenterIds;
import com.android.safetycenter.internaldata.SafetyCenterIssueActionId;
import com.android.safetycenter.internaldata.SafetyCenterIssueId;
@@ -120,6 +120,8 @@ public final class SafetyCenterService extends SystemService {
@GuardedBy("mApiLock")
private final SafetyCenterRefreshTracker mSafetyCenterRefreshTracker;
+ private final SafetySourceDataFix mSafetySourceDataFix;
+
@GuardedBy("mApiLock")
private final SafetyCenterDataManager mSafetyCenterDataManager;
@@ -151,6 +153,10 @@ public final class SafetyCenterService extends SystemService {
mSafetyCenterResourcesApk = new SafetyCenterResourcesApk(context);
mSafetyCenterConfigReader = new SafetyCenterConfigReader(mSafetyCenterResourcesApk);
mSafetyCenterRefreshTracker = new SafetyCenterRefreshTracker(context);
+ PendingIntentFactory pendingIntentFactory =
+ new PendingIntentFactory(context, mSafetyCenterResourcesApk);
+ mSafetySourceDataFix =
+ new SafetySourceDataFix(context, pendingIntentFactory, mSafetyCenterConfigReader);
mSafetyCenterDataManager =
new SafetyCenterDataManager(
context, mSafetyCenterConfigReader, mSafetyCenterRefreshTracker, mApiLock);
@@ -160,7 +166,7 @@ public final class SafetyCenterService extends SystemService {
mSafetyCenterResourcesApk,
mSafetyCenterConfigReader,
mSafetyCenterRefreshTracker,
- new PendingIntentFactory(context, mSafetyCenterResourcesApk),
+ pendingIntentFactory,
mSafetyCenterDataManager);
mSafetyCenterListeners = new SafetyCenterListeners(mSafetyCenterDataFactory);
mNotificationChannels = new SafetyCenterNotificationChannels(mSafetyCenterResourcesApk);
@@ -310,8 +316,8 @@ public final class SafetyCenterService extends SystemService {
UserProfileGroup userProfileGroup = UserProfileGroup.fromUser(getContext(), userId);
synchronized (mApiLock) {
safetySourceData =
- AndroidLockScreenFix.maybeOverrideSafetySourceData(
- getContext(), safetySourceId, safetySourceData);
+ mSafetySourceDataFix.maybeOverrideSafetySourceData(
+ safetySourceId, safetySourceData, packageName, userId);
safetyEvent =
SafetyEventFix.maybeOverrideSafetyEvent(
mSafetyCenterDataManager,
diff --git a/service/java/com/android/safetycenter/data/AndroidLockScreenFix.java b/service/java/com/android/safetycenter/data/AndroidLockScreenFix.java
index e46ba2f4d..53043c0f8 100644
--- a/service/java/com/android/safetycenter/data/AndroidLockScreenFix.java
+++ b/service/java/com/android/safetycenter/data/AndroidLockScreenFix.java
@@ -27,8 +27,6 @@ import android.safetycenter.SafetySourceIssue;
import android.safetycenter.SafetySourceStatus;
import android.util.Log;
-import androidx.annotation.Nullable;
-
import com.android.modules.utils.build.SdkLevel;
import com.android.safetycenter.PendingIntentFactory;
import com.android.safetycenter.SafetyCenterFlags;
@@ -38,10 +36,8 @@ import java.util.List;
/**
* A class to work around an issue with the {@code AndroidLockScreen} safety source, by potentially
* overriding its {@link SafetySourceData}.
- *
- * @hide
*/
-public final class AndroidLockScreenFix {
+final class AndroidLockScreenFix {
private static final String TAG = "AndroidLockScreenFix";
@@ -55,9 +51,22 @@ public final class AndroidLockScreenFix {
private AndroidLockScreenFix() {}
+ static boolean shouldApplyFix(String sourceId) {
+ if (SdkLevel.isAtLeastU()) {
+ // No need to override on U+ as the issue has been fixed in a T QPR release.
+ // As such, U+ fields for the SafetySourceData are not taken into account in the methods
+ // below.
+ return false;
+ }
+ if (!ANDROID_LOCK_SCREEN_SOURCE_ID.equals(sourceId)) {
+ return false;
+ }
+ return SafetyCenterFlags.getReplaceLockScreenIconAction();
+ }
+
/**
- * Potentially overrides the {@link SafetySourceData} of the {@code AndroidLockScreen} source by
- * replacing its {@link PendingIntent}s.
+ * Overrides the {@link SafetySourceData} of the {@code AndroidLockScreen} source by replacing
+ * its {@link PendingIntent}s.
*
* <p>This is done because of a bug in the Settings app where the {@link PendingIntent}s created
* end up referencing either the {@link SafetyCenterEntry#getPendingIntent()} or the {@link
@@ -70,67 +79,45 @@ public final class AndroidLockScreenFix {
* different request codes for the different {@link PendingIntent}s to ensure new instances are
* created (the key does take into account the request code).
*/
- @Nullable
- public static SafetySourceData maybeOverrideSafetySourceData(
- Context context, String sourceId, @Nullable SafetySourceData safetySourceData) {
- if (safetySourceData == null) {
- return null;
- }
- if (SdkLevel.isAtLeastU()) {
- // No need to override on U+ as the issue has been fixed in a T QPR release.
- // As such, U+ fields for the SafetySourceData are not taken into account in the methods
- // below.
- return safetySourceData;
- }
- if (!ANDROID_LOCK_SCREEN_SOURCE_ID.equals(sourceId)) {
- return safetySourceData;
- }
- if (!SafetyCenterFlags.getReplaceLockScreenIconAction()) {
- return safetySourceData;
- }
- return overrideTiramisuSafetySourceData(context, safetySourceData);
- }
+ static SafetySourceData applyFix(Context context, SafetySourceData data) {
+ SafetySourceData.Builder overriddenData =
+ SafetySourceDataOverrides.copyDataToBuilderWithoutIssues(data);
- private static SafetySourceData overrideTiramisuSafetySourceData(
- Context context, SafetySourceData safetySourceData) {
- SafetySourceData.Builder overriddenSafetySourceData = new SafetySourceData.Builder();
- SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
- if (safetySourceStatus != null) {
- overriddenSafetySourceData.setStatus(
- overrideTiramisuSafetySourceStatus(context, safetySourceStatus));
+ SafetySourceStatus originalStatus = data.getStatus();
+ if (originalStatus != null) {
+ overriddenData.setStatus(overrideTiramisuSafetySourceStatus(context, originalStatus));
}
- List<SafetySourceIssue> safetySourceIssues = safetySourceData.getIssues();
- for (int i = 0; i < safetySourceIssues.size(); i++) {
- SafetySourceIssue safetySourceIssue = safetySourceIssues.get(i);
- overriddenSafetySourceData.addIssue(
- overrideTiramisuSafetySourceIssue(context, safetySourceIssue));
+
+ List<SafetySourceIssue> issues = data.getIssues();
+ for (int i = 0; i < issues.size(); i++) {
+ overriddenData.addIssue(overrideTiramisuIssue(context, issues.get(i)));
}
- return overriddenSafetySourceData.build();
+
+ return overriddenData.build();
}
private static SafetySourceStatus overrideTiramisuSafetySourceStatus(
- Context context, SafetySourceStatus safetySourceStatus) {
- SafetySourceStatus.Builder overriddenSafetySourceStatus =
- new SafetySourceStatus.Builder(
- safetySourceStatus.getTitle(),
- safetySourceStatus.getSummary(),
- safetySourceStatus.getSeverityLevel())
- .setPendingIntent(
- overridePendingIntent(
- context,
- safetySourceStatus.getPendingIntent(),
- /* isIconAction= */ false))
- .setEnabled(safetySourceStatus.isEnabled());
- SafetySourceStatus.IconAction iconAction = safetySourceStatus.getIconAction();
+ Context context, SafetySourceStatus status) {
+ SafetySourceStatus.Builder overriddenStatus =
+ SafetySourceDataOverrides.copyStatusToBuilder(status);
+
+ PendingIntent originalPendingIntent = status.getPendingIntent();
+ if (originalPendingIntent != null) {
+ overriddenStatus.setPendingIntent(
+ overridePendingIntent(
+ context, originalPendingIntent, /* isIconAction= */ false));
+ }
+
+ SafetySourceStatus.IconAction iconAction = status.getIconAction();
if (iconAction != null) {
- overriddenSafetySourceStatus.setIconAction(
- overrideTiramisuSafetySourceStatusIconAction(
- context, safetySourceStatus.getIconAction()));
+ overriddenStatus.setIconAction(
+ overrideTiramisuIconAction(context, status.getIconAction()));
}
- return overriddenSafetySourceStatus.build();
+
+ return overriddenStatus.build();
}
- private static SafetySourceStatus.IconAction overrideTiramisuSafetySourceStatusIconAction(
+ private static SafetySourceStatus.IconAction overrideTiramisuIconAction(
Context context, SafetySourceStatus.IconAction iconAction) {
return new SafetySourceStatus.IconAction(
iconAction.getIconType(),
@@ -138,45 +125,30 @@ public final class AndroidLockScreenFix {
context, iconAction.getPendingIntent(), /* isIconAction= */ true));
}
- private static SafetySourceIssue overrideTiramisuSafetySourceIssue(
- Context context, SafetySourceIssue safetySourceIssue) {
- SafetySourceIssue.Builder overriddenSafetySourceIssue =
- new SafetySourceIssue.Builder(
- safetySourceIssue.getId(),
- safetySourceIssue.getTitle(),
- safetySourceIssue.getSummary(),
- safetySourceIssue.getSeverityLevel(),
- safetySourceIssue.getIssueTypeId())
- .setSubtitle(safetySourceIssue.getSubtitle())
- .setIssueCategory(safetySourceIssue.getIssueCategory())
- .setOnDismissPendingIntent(safetySourceIssue.getOnDismissPendingIntent());
- List<SafetySourceIssue.Action> actions = safetySourceIssue.getActions();
+ private static SafetySourceIssue overrideTiramisuIssue(
+ Context context, SafetySourceIssue issue) {
+ SafetySourceIssue.Builder overriddenIssue =
+ SafetySourceDataOverrides.copyIssueToBuilderWithoutActions(issue);
+
+ List<SafetySourceIssue.Action> actions = issue.getActions();
for (int i = 0; i < actions.size(); i++) {
SafetySourceIssue.Action action = actions.get(i);
- overriddenSafetySourceIssue.addAction(
- overrideTiramisuSafetySourceIssueAction(context, action));
+ overriddenIssue.addAction(overrideTiramisuIssueAction(context, action));
}
- return overriddenSafetySourceIssue.build();
+
+ return overriddenIssue.build();
}
- private static SafetySourceIssue.Action overrideTiramisuSafetySourceIssueAction(
+ private static SafetySourceIssue.Action overrideTiramisuIssueAction(
Context context, SafetySourceIssue.Action action) {
- return new SafetySourceIssue.Action.Builder(
- action.getId(),
- action.getLabel(),
- overridePendingIntent(
- context, action.getPendingIntent(), /* isIconAction= */ false))
- .setWillResolve(action.willResolve())
- .setSuccessMessage(action.getSuccessMessage())
- .build();
+ PendingIntent pendingIntent =
+ overridePendingIntent(
+ context, action.getPendingIntent(), /* isIconAction= */ false);
+ return SafetySourceDataOverrides.overrideActionPendingIntent(action, pendingIntent);
}
- @Nullable
private static PendingIntent overridePendingIntent(
- Context context, @Nullable PendingIntent pendingIntent, boolean isIconAction) {
- if (pendingIntent == null) {
- return null;
- }
+ Context context, PendingIntent pendingIntent, boolean isIconAction) {
String settingsPackageName = pendingIntent.getCreatorPackage();
int userId = pendingIntent.getCreatorUserHandle().getIdentifier();
Context settingsPackageContext =
diff --git a/service/java/com/android/safetycenter/data/DefaultActionOverrideFix.java b/service/java/com/android/safetycenter/data/DefaultActionOverrideFix.java
new file mode 100644
index 000000000..9ca188670
--- /dev/null
+++ b/service/java/com/android/safetycenter/data/DefaultActionOverrideFix.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.data;
+
+import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+
+import android.annotation.UserIdInt;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.safetycenter.SafetySourceData;
+import android.safetycenter.SafetySourceIssue;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+
+import com.android.modules.utils.build.SdkLevel;
+import com.android.permission.util.UserUtils;
+import com.android.safetycenter.PendingIntentFactory;
+import com.android.safetycenter.SafetyCenterConfigReader;
+import com.android.safetycenter.SafetyCenterFlags;
+
+import java.util.List;
+
+/**
+ * Replaces {@link SafetySourceIssue.Action}s with the corresponding source's default intent drawn
+ * from the Safety Center config.
+ *
+ * <p>Actions to be replaced are controlled by the {@code
+ * safety_center_actions_to_override_with_default_intent} DeviceConfig flag.
+ *
+ * <p>This is done to support cases where we allow OEMs to override intents in the config, but
+ * sources are unaware of and unable to access those overrides when providing issues and
+ * notifications. We use the default intent when sources provide a null pending intent in their
+ * status. This fix allows us to implement a similar behavior for actions, without changing the
+ * non-null requirement on their pending intent fields.
+ */
+final class DefaultActionOverrideFix {
+
+ private final Context mContext;
+ private final PendingIntentFactory mPendingIntentFactory;
+ private final SafetyCenterConfigReader mSafetyCenterConfigReader;
+
+ DefaultActionOverrideFix(
+ Context context,
+ PendingIntentFactory pendingIntentFactory,
+ SafetyCenterConfigReader safetyCenterConfigReader) {
+ mContext = context;
+ mPendingIntentFactory = pendingIntentFactory;
+ mSafetyCenterConfigReader = safetyCenterConfigReader;
+ }
+
+ static boolean shouldApplyFix(String sourceId) {
+ List<String> actionsToOverride =
+ SafetyCenterFlags.getActionsToOverrideWithDefaultIntentForSource(sourceId);
+ return !actionsToOverride.isEmpty();
+ }
+
+ SafetySourceData applyFix(
+ String sourceId,
+ SafetySourceData safetySourceData,
+ String packageName,
+ @UserIdInt int userId) {
+ if (safetySourceData.getIssues().isEmpty()) {
+ return safetySourceData;
+ }
+
+ PendingIntent defaultIntentForSource =
+ getDefaultIntentForSource(sourceId, packageName, userId);
+ if (defaultIntentForSource == null) {
+ // If there's no default intent, we can't override any actions with it.
+ return safetySourceData;
+ }
+
+ List<String> actionsToOverride =
+ SafetyCenterFlags.getActionsToOverrideWithDefaultIntentForSource(sourceId);
+ if (actionsToOverride.isEmpty()) {
+ // This shouldn't happen if shouldApplyFix is called first, but we check for good
+ // measure.
+ return safetySourceData;
+ }
+
+ SafetySourceData.Builder overriddenSafetySourceData =
+ SafetySourceDataOverrides.copyDataToBuilderWithoutIssues(safetySourceData);
+ List<SafetySourceIssue> issues = safetySourceData.getIssues();
+ for (int i = 0; i < issues.size(); i++) {
+ overriddenSafetySourceData.addIssue(
+ maybeOverrideActionsWithDefaultIntent(
+ issues.get(i), actionsToOverride, defaultIntentForSource));
+ }
+
+ return overriddenSafetySourceData.build();
+ }
+
+ @Nullable
+ private PendingIntent getDefaultIntentForSource(
+ String sourceId, String packageName, @UserIdInt int userId) {
+ SafetyCenterConfigReader.ExternalSafetySource externalSafetySource =
+ mSafetyCenterConfigReader.getExternalSafetySource(sourceId, packageName);
+ if (externalSafetySource == null) {
+ return null;
+ }
+
+ boolean isQuietModeEnabled =
+ UserUtils.isManagedProfile(userId, mContext)
+ && !UserUtils.isProfileRunning(userId, mContext);
+
+ return mPendingIntentFactory.getPendingIntent(
+ sourceId,
+ externalSafetySource.getSafetySource().getIntentAction(),
+ packageName,
+ userId,
+ isQuietModeEnabled);
+ }
+
+ private SafetySourceIssue maybeOverrideActionsWithDefaultIntent(
+ SafetySourceIssue issue, List<String> actionsToOverride, PendingIntent defaultIntent) {
+ SafetySourceIssue.Builder overriddenIssue =
+ SafetySourceDataOverrides.copyIssueToBuilderWithoutActions(issue);
+
+ List<SafetySourceIssue.Action> actions = issue.getActions();
+ for (int i = 0; i < actions.size(); i++) {
+ overriddenIssue.addAction(
+ maybeOverrideAction(actions.get(i), actionsToOverride, defaultIntent));
+ }
+
+ if (SdkLevel.isAtLeastU()) {
+ overriddenIssue.setCustomNotification(
+ maybeOverrideNotification(
+ issue.getCustomNotification(), actionsToOverride, defaultIntent));
+ }
+
+ return overriddenIssue.build();
+ }
+
+ @RequiresApi(UPSIDE_DOWN_CAKE)
+ @Nullable
+ private static SafetySourceIssue.Notification maybeOverrideNotification(
+ @Nullable SafetySourceIssue.Notification notification,
+ List<String> actionsToOverride,
+ PendingIntent defaultIntent) {
+ if (notification == null) {
+ return null;
+ }
+
+ SafetySourceIssue.Notification.Builder overriddenNotification =
+ new SafetySourceIssue.Notification.Builder(notification).clearActions();
+
+ List<SafetySourceIssue.Action> actions = notification.getActions();
+ for (int i = 0; i < actions.size(); i++) {
+ overriddenNotification.addAction(
+ maybeOverrideAction(actions.get(i), actionsToOverride, defaultIntent));
+ }
+
+ return overriddenNotification.build();
+ }
+
+ private static SafetySourceIssue.Action maybeOverrideAction(
+ SafetySourceIssue.Action action,
+ List<String> actionsToOverride,
+ PendingIntent defaultIntent) {
+ if (actionsToOverride.contains(action.getId())) {
+ return SafetySourceDataOverrides.overrideActionPendingIntent(action, defaultIntent);
+ }
+ return action;
+ }
+}
diff --git a/service/java/com/android/safetycenter/data/SafetySourceDataFix.java b/service/java/com/android/safetycenter/data/SafetySourceDataFix.java
new file mode 100644
index 000000000..a34f3b03b
--- /dev/null
+++ b/service/java/com/android/safetycenter/data/SafetySourceDataFix.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.data;
+
+import android.annotation.UserIdInt;
+import android.content.Context;
+import android.safetycenter.SafetySourceData;
+
+import androidx.annotation.Nullable;
+
+import com.android.safetycenter.PendingIntentFactory;
+import com.android.safetycenter.SafetyCenterConfigReader;
+
+/**
+ * Applies various workarounds and fixes to {@link SafetySourceData} as it's received.
+ *
+ * @hide
+ */
+public final class SafetySourceDataFix {
+
+ private final DefaultActionOverrideFix mDefaultActionOverrideFix;
+ private Context mContext;
+
+ public SafetySourceDataFix(
+ Context context,
+ PendingIntentFactory pendingIntentFactory,
+ SafetyCenterConfigReader safetyCenterConfigReader) {
+ mContext = context;
+ mDefaultActionOverrideFix =
+ new DefaultActionOverrideFix(
+ context, pendingIntentFactory, safetyCenterConfigReader);
+ }
+
+ /**
+ * Potentially overrides the {@link SafetySourceData}.
+ *
+ * <p>Should be called when the data is received from a source and before it's stored by Safety
+ * Center.
+ */
+ @Nullable
+ public SafetySourceData maybeOverrideSafetySourceData(
+ String sourceId,
+ @Nullable SafetySourceData safetySourceData,
+ String packageName,
+ @UserIdInt int userId) {
+ if (safetySourceData == null) {
+ return null;
+ }
+
+ if (AndroidLockScreenFix.shouldApplyFix(sourceId)) {
+ safetySourceData = AndroidLockScreenFix.applyFix(mContext, safetySourceData);
+ }
+
+ if (DefaultActionOverrideFix.shouldApplyFix(sourceId)) {
+ safetySourceData =
+ mDefaultActionOverrideFix.applyFix(
+ sourceId, safetySourceData, packageName, userId);
+ }
+
+ return safetySourceData;
+ }
+}
diff --git a/service/java/com/android/safetycenter/data/SafetySourceDataOverrides.java b/service/java/com/android/safetycenter/data/SafetySourceDataOverrides.java
new file mode 100644
index 000000000..b292ae6cb
--- /dev/null
+++ b/service/java/com/android/safetycenter/data/SafetySourceDataOverrides.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.data;
+
+import android.app.PendingIntent;
+import android.safetycenter.SafetySourceData;
+import android.safetycenter.SafetySourceIssue;
+import android.safetycenter.SafetySourceStatus;
+
+import com.android.modules.utils.build.SdkLevel;
+
+final class SafetySourceDataOverrides {
+ private SafetySourceDataOverrides() {}
+
+ static SafetySourceData.Builder copyDataToBuilderWithoutIssues(SafetySourceData data) {
+ if (SdkLevel.isAtLeastU()) {
+ return new SafetySourceData.Builder(data).clearIssues();
+ }
+
+ // Copy T-only fields
+ return new SafetySourceData.Builder().setStatus(data.getStatus());
+ }
+
+ static SafetySourceStatus.Builder copyStatusToBuilder(SafetySourceStatus status) {
+ if (SdkLevel.isAtLeastU()) {
+ return new SafetySourceStatus.Builder(status);
+ }
+
+ // Copy T-only fields
+ return new SafetySourceStatus.Builder(
+ status.getTitle(), status.getSummary(), status.getSeverityLevel())
+ .setPendingIntent(status.getPendingIntent())
+ .setEnabled(status.isEnabled())
+ .setIconAction(status.getIconAction());
+ }
+
+ static SafetySourceIssue.Builder copyIssueToBuilderWithoutActions(SafetySourceIssue issue) {
+ if (SdkLevel.isAtLeastU()) {
+ return new SafetySourceIssue.Builder(issue).clearActions();
+ }
+
+ // Copy T-only fields
+ return new SafetySourceIssue.Builder(
+ issue.getId(),
+ issue.getTitle(),
+ issue.getSummary(),
+ issue.getSeverityLevel(),
+ issue.getIssueTypeId())
+ .setIssueCategory(issue.getIssueCategory())
+ .setSubtitle(issue.getSubtitle())
+ .setOnDismissPendingIntent(issue.getOnDismissPendingIntent());
+ }
+
+ /**
+ * Returns an new {@link SafetySourceIssue.Action} object, replacing its {@link PendingIntent}
+ * with the one supplied.
+ */
+ static SafetySourceIssue.Action overrideActionPendingIntent(
+ SafetySourceIssue.Action action, PendingIntent pendingIntent) {
+ // TODO(b/303443020): Add setter for pendingIntent so this method can use the copy builder.
+ return new SafetySourceIssue.Action.Builder(
+ action.getId(), action.getLabel(), pendingIntent)
+ .setWillResolve(action.willResolve())
+ .setSuccessMessage(action.getSuccessMessage())
+ .build();
+ }
+}
diff --git a/service/java/com/android/safetycenter/data/package-info.java b/service/java/com/android/safetycenter/data/package-info.java
index e82755370..a125b3176 100644
--- a/service/java/com/android/safetycenter/data/package-info.java
+++ b/service/java/com/android/safetycenter/data/package-info.java
@@ -14,8 +14,11 @@
* limitations under the License.
*/
@NonNullByDefault
-@RequiresTiramisuByDefault
+@RequiresApi(TIRAMISU)
package com.android.safetycenter.data;
+import static android.os.Build.VERSION_CODES.TIRAMISU;
+
+import android.annotation.RequiresApi;
+
import com.android.safetycenter.annotations.NonNullByDefault;
-import com.android.safetycenter.annotations.RequiresTiramisuByDefault;
diff --git a/service/java/com/android/safetycenter/logging/package-info.java b/service/java/com/android/safetycenter/logging/package-info.java
index 47575f2d9..79e504ebd 100644
--- a/service/java/com/android/safetycenter/logging/package-info.java
+++ b/service/java/com/android/safetycenter/logging/package-info.java
@@ -14,8 +14,11 @@
* limitations under the License.
*/
@NonNullByDefault
-@RequiresTiramisuByDefault
+@RequiresApi(TIRAMISU)
package com.android.safetycenter.logging;
+import static android.os.Build.VERSION_CODES.TIRAMISU;
+
+import android.annotation.RequiresApi;
+
import com.android.safetycenter.annotations.NonNullByDefault;
-import com.android.safetycenter.annotations.RequiresTiramisuByDefault;
diff --git a/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationFactory.java b/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationFactory.java
index 0624bad82..84001f249 100644
--- a/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationFactory.java
+++ b/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationFactory.java
@@ -84,6 +84,10 @@ final class SafetyCenterNotificationFactory {
SafetySourceIssue issue,
SafetySourceIssue.Action action,
@UserIdInt int userId) {
+ if (action.getSuccessMessage() == null) {
+ return null;
+ }
+
String channelId = mNotificationChannels.getCreatedChannelId(notificationManager, issue);
if (channelId == null) {
return null;
diff --git a/service/java/com/android/safetycenter/notifications/package-info.java b/service/java/com/android/safetycenter/notifications/package-info.java
index e16c06d58..83d886fe1 100644
--- a/service/java/com/android/safetycenter/notifications/package-info.java
+++ b/service/java/com/android/safetycenter/notifications/package-info.java
@@ -14,8 +14,11 @@
* limitations under the License.
*/
@NonNullByDefault
-@RequiresTiramisuByDefault
+@RequiresApi(TIRAMISU)
package com.android.safetycenter.notifications;
+import static android.os.Build.VERSION_CODES.TIRAMISU;
+
+import android.annotation.RequiresApi;
+
import com.android.safetycenter.annotations.NonNullByDefault;
-import com.android.safetycenter.annotations.RequiresTiramisuByDefault;
diff --git a/service/java/com/android/safetycenter/package-info.java b/service/java/com/android/safetycenter/package-info.java
index 72774d21e..57142c658 100644
--- a/service/java/com/android/safetycenter/package-info.java
+++ b/service/java/com/android/safetycenter/package-info.java
@@ -14,8 +14,11 @@
* limitations under the License.
*/
@NonNullByDefault
-@RequiresTiramisuByDefault
+@RequiresApi(TIRAMISU)
package com.android.safetycenter;
+import static android.os.Build.VERSION_CODES.TIRAMISU;
+
+import android.annotation.RequiresApi;
+
import com.android.safetycenter.annotations.NonNullByDefault;
-import com.android.safetycenter.annotations.RequiresTiramisuByDefault;
diff --git a/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt b/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt
index 9534b597a..acbc5cfc0 100644
--- a/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt
+++ b/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt
@@ -20,7 +20,6 @@ import android.Manifest.permission.INTERACT_ACROSS_USERS
import android.Manifest.permission.INTERACT_ACROSS_USERS_FULL
import android.app.PendingIntent
import android.content.Context
-import android.content.Intent
import android.os.UserHandle
import android.safetycenter.SafetyCenterData
import android.safetycenter.SafetyCenterEntry
@@ -60,7 +59,6 @@ import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.get
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.setSafetySourceDataWithPermission
import com.android.safetycenter.testing.SafetyCenterFlags
import com.android.safetycenter.testing.SafetyCenterTestConfigs
-import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.ACTION_TEST_ACTIVITY
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.DYNAMIC_BAREBONE_ID
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.DYNAMIC_DISABLED_ID
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.DYNAMIC_GROUP_ID
@@ -244,69 +242,67 @@ class SafetyCenterMultiUsersTest {
private val staticAllOptional =
safetyCenterTestData.safetyCenterEntryDefaultStaticBuilder(STATIC_ALL_OPTIONAL_ID).build()
- private fun staticAllOptionalForWorkBuilder(inQuietMode: Boolean = false) =
- safetyCenterTestData
- .safetyCenterEntryDefaultStaticBuilder(
- STATIC_ALL_OPTIONAL_ID,
- userId = deviceState.workProfile().id(),
- title = "Paste"
- )
- .setPendingIntent(
- createTestActivityRedirectPendingIntentForUser(
- deviceState.workProfile().userHandle(),
- inQuietMode
+ private val staticAllOptionalForWorkBuilder
+ get() =
+ safetyCenterTestData
+ .safetyCenterEntryDefaultStaticBuilder(
+ STATIC_ALL_OPTIONAL_ID,
+ userId = deviceState.workProfile().id(),
+ title = "Paste"
+ )
+ .setPendingIntent(
+ createTestActivityRedirectPendingIntentForUser(
+ deviceState.workProfile().userHandle(),
+ explicit = false
+ )
)
- )
private val staticAllOptionalForWork
- get() = staticAllOptionalForWorkBuilder().build()
+ get() = staticAllOptionalForWorkBuilder.build()
private val staticAllOptionalForWorkPaused
get() =
- staticAllOptionalForWorkBuilder(inQuietMode = true)
+ staticAllOptionalForWorkBuilder
.setSummary(safetyCenterResourcesApk.getStringByName("work_profile_paused"))
.setEnabled(false)
.build()
- private val staticEntry: SafetyCenterStaticEntry
- get() =
- SafetyCenterStaticEntry.Builder("OK")
- .setSummary("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
- .build()
+ private fun createStaticEntry(explicit: Boolean = true): SafetyCenterStaticEntry =
+ SafetyCenterStaticEntry.Builder("OK")
+ .setSummary("OK")
+ .setPendingIntent(
+ safetySourceTestData.createTestActivityRedirectPendingIntent(explicit)
+ )
+ .build()
private val staticEntryUpdated: SafetyCenterStaticEntry
get() =
SafetyCenterStaticEntry.Builder("Unspecified title")
.setSummary("Unspecified summary")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(safetySourceTestData.createTestActivityRedirectPendingIntent())
.build()
- private fun staticEntryForWorkBuilder(
- title: CharSequence = "Paste",
- inQuietMode: Boolean = false
- ) =
+ private fun staticEntryForWorkBuilder(title: CharSequence = "Paste", explicit: Boolean = true) =
SafetyCenterStaticEntry.Builder(title)
.setSummary("OK")
.setPendingIntent(
createTestActivityRedirectPendingIntentForUser(
deviceState.workProfile().userHandle(),
- inQuietMode
+ explicit
)
)
- private val staticEntryForWork: SafetyCenterStaticEntry
- get() = staticEntryForWorkBuilder().build()
+ private fun createStaticEntryForWork(explicit: Boolean = true): SafetyCenterStaticEntry =
+ staticEntryForWorkBuilder(explicit = explicit).build()
- private val staticEntryForWorkPaused: SafetyCenterStaticEntry
- get() =
- staticEntryForWorkBuilder(inQuietMode = true)
- .setSummary(safetyCenterResourcesApk.getStringByName("work_profile_paused"))
- .build()
+ private fun createStaticEntryForWorkPaused(): SafetyCenterStaticEntry =
+ staticEntryForWorkBuilder(explicit = false)
+ .setSummary(safetyCenterResourcesApk.getStringByName("work_profile_paused"))
+ .build()
- private val staticEntryForWorkPausedUpdated
+ private val staticEntryForWorkPausedUpdated: SafetyCenterStaticEntry
get() =
- staticEntryForWorkBuilder(title = "Unspecified title for Work", inQuietMode = true)
+ staticEntryForWorkBuilder(title = "Unspecified title for Work")
.setSummary(safetyCenterResourcesApk.getStringByName("work_profile_paused"))
.build()
@@ -314,7 +310,7 @@ class SafetyCenterMultiUsersTest {
get() =
SafetyCenterStaticEntry.Builder("Unspecified title for Work")
.setSummary("Unspecified summary")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(safetySourceTestData.createTestActivityRedirectPendingIntent())
.build()
private val safetyCenterDataForAdditionalUser
@@ -543,7 +539,12 @@ class SafetyCenterMultiUsersTest {
.build()
)
),
- listOf(SafetyCenterStaticEntryGroup("OK", listOf(staticEntry, staticEntry)))
+ listOf(
+ SafetyCenterStaticEntryGroup(
+ "OK",
+ listOf(createStaticEntry(), createStaticEntry(explicit = false))
+ )
+ )
)
assertThat(apiSafetyCenterData.withoutExtras()).isEqualTo(safetyCenterDataFromComplexConfig)
}
@@ -589,7 +590,12 @@ class SafetyCenterMultiUsersTest {
listOf(
SafetyCenterStaticEntryGroup(
"OK",
- listOf(staticEntry, staticEntryForWork, staticEntry, staticEntryForWork)
+ listOf(
+ createStaticEntry(),
+ createStaticEntryForWork(),
+ createStaticEntry(explicit = false),
+ createStaticEntryForWork(explicit = false)
+ )
)
)
)
@@ -639,9 +645,9 @@ class SafetyCenterMultiUsersTest {
"OK",
listOf(
staticEntryUpdated,
- staticEntryForWork,
- staticEntry,
- staticEntryForWork
+ createStaticEntryForWork(),
+ createStaticEntry(explicit = false),
+ createStaticEntryForWork(explicit = false)
)
)
)
@@ -749,8 +755,8 @@ class SafetyCenterMultiUsersTest {
listOf(
staticEntryUpdated,
staticEntryForWorkUpdated,
- staticEntry,
- staticEntryForWork
+ createStaticEntry(explicit = false),
+ createStaticEntryForWork(explicit = false)
)
)
)
@@ -809,8 +815,8 @@ class SafetyCenterMultiUsersTest {
listOf(
staticEntryUpdated,
staticEntryForWorkPausedUpdated,
- staticEntry,
- staticEntryForWorkPaused
+ createStaticEntry(explicit = false),
+ createStaticEntryForWorkPaused()
)
)
)
@@ -1228,13 +1234,12 @@ class SafetyCenterMultiUsersTest {
private fun createTestActivityRedirectPendingIntentForUser(
user: UserHandle,
- inQuietMode: Boolean = false
+ explicit: Boolean = true
): PendingIntent {
return callWithShellPermissionIdentity(INTERACT_ACROSS_USERS) {
SafetySourceTestData.createRedirectPendingIntent(
getContextForUser(user),
- Intent(ACTION_TEST_ACTIVITY),
- inQuietMode
+ SafetySourceTestData.createTestActivityIntent(getContextForUser(user), explicit)
)
}
}
diff --git a/tests/functional/safetycenter/safetycenteractivity/src/android/safetycenter/functional/ui/SafetyCenterActivityTest.kt b/tests/functional/safetycenter/safetycenteractivity/src/android/safetycenter/functional/ui/SafetyCenterActivityTest.kt
index 8bb27929d..73f435615 100644
--- a/tests/functional/safetycenter/safetycenteractivity/src/android/safetycenter/functional/ui/SafetyCenterActivityTest.kt
+++ b/tests/functional/safetycenter/safetycenteractivity/src/android/safetycenter/functional/ui/SafetyCenterActivityTest.kt
@@ -1124,7 +1124,7 @@ class SafetyCenterActivityTest {
}
@Test
- fun moreIssuesCard_twoIssuesAlreadyShown_expandAdditionalIssueCards() {
+ fun moreIssuesCard_withThreeIssues_showsTopIssuesAndMoreIssuesCard() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
safetyCenterTestHelper.setData(
SOURCE_ID_1,
@@ -1144,14 +1144,31 @@ class SafetyCenterActivityTest {
waitSourceIssueDisplayed(safetySourceTestData.recommendationGeneralIssue)
waitAllTextDisplayed(MORE_ISSUES_LABEL)
waitSourceIssueNotDisplayed(safetySourceTestData.informationIssue)
+ }
+ }
+
+ @Test
+ fun moreIssuesCard_twoIssuesAlreadyShown_expandAdditionalIssueCards() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
+ safetyCenterTestHelper.setData(
+ SOURCE_ID_1,
+ safetySourceTestData.criticalWithResolvingGeneralIssue
+ )
+ safetyCenterTestHelper.setData(
+ SOURCE_ID_2,
+ safetySourceTestData.recommendationWithGeneralIssue
+ )
+ safetyCenterTestHelper.setData(SOURCE_ID_3, safetySourceTestData.informationWithIssue)
+
+ val bundle = Bundle()
+ bundle.putString(EXTRA_SAFETY_SOURCE_ID, SOURCE_ID_2)
+ bundle.putString(EXTRA_SAFETY_SOURCE_ISSUE_ID, RECOMMENDATION_ISSUE_ID)
+ context.launchSafetyCenterActivity(bundle) {
+ waitSourceIssueNotDisplayed(safetySourceTestData.informationIssue)
clickMoreIssuesCard()
- waitExpandedIssuesDisplayed(
- safetySourceTestData.criticalResolvingGeneralIssue,
- safetySourceTestData.recommendationGeneralIssue,
- safetySourceTestData.informationIssue
- )
+ waitSourceIssueDisplayed(safetySourceTestData.informationIssue)
}
}
@@ -1435,7 +1452,7 @@ class SafetyCenterActivityTest {
@Test
fun startStaticEntryActivity_withConfigToBeSettingsActivity_trueExtraInBundle() {
- safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleStaticSettingsSource)
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleStaticSettingsSourceConfig)
context.launchSafetyCenterActivity {
waitDisplayed(By.text("OK")) { it.click() }
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt
index e2a7802b3..d90fbcd1e 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt
+++ b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt
@@ -16,7 +16,6 @@
package android.safetycenter.functional
-import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION_CODES.TIRAMISU
@@ -62,7 +61,6 @@ import android.safetycenter.config.SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
-import com.android.compatibility.common.preconditions.ScreenLockHelper
import com.android.compatibility.common.util.SystemUtil
import com.android.modules.utils.build.SdkLevel
import com.android.safetycenter.internaldata.SafetyCenterBundles
@@ -81,6 +79,7 @@ import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.ref
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.reportSafetySourceErrorWithPermission
import com.android.safetycenter.testing.SafetyCenterFlags
import com.android.safetycenter.testing.SafetyCenterTestConfigs
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.ACTION_TEST_ACTIVITY
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.ACTION_TEST_ACTIVITY_EXPORTED
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.ANDROID_LOCK_SCREEN_SOURCES_GROUP_ID
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.DYNAMIC_ALL_OPTIONAL_ID
@@ -137,7 +136,6 @@ import java.time.Duration
import kotlin.test.assertFailsWith
import kotlinx.coroutines.TimeoutCancellationException
import org.junit.Assume.assumeFalse
-import org.junit.Assume.assumeTrue
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -332,7 +330,9 @@ class SafetyCenterManagerTest {
.setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNSPECIFIED)
.setSummary("OK")
.setPendingIntent(
- safetySourceTestData.testActivityRedirectPendingIntent
+ safetySourceTestData.createTestActivityRedirectPendingIntent(
+ explicit = false
+ )
)
.setSeverityUnspecifiedIconType(
SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON
@@ -352,11 +352,19 @@ class SafetyCenterManagerTest {
"OK",
listOf(
SafetyCenterStaticEntry.Builder("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(
+ safetySourceTestData.createTestActivityRedirectPendingIntent(
+ explicit = false
+ )
+ )
.build(),
SafetyCenterStaticEntry.Builder("OK")
.setSummary("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(
+ safetySourceTestData.createTestActivityRedirectPendingIntent(
+ explicit = false
+ )
+ )
.build()
)
)
@@ -368,11 +376,17 @@ class SafetyCenterManagerTest {
listOf(
SafetyCenterStaticEntry.Builder("OK")
.setSummary("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(
+ safetySourceTestData.createTestActivityRedirectPendingIntent()
+ )
.build(),
SafetyCenterStaticEntry.Builder("OK")
.setSummary("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(
+ safetySourceTestData.createTestActivityRedirectPendingIntent(
+ explicit = false
+ )
+ )
.build()
)
)
@@ -385,11 +399,17 @@ class SafetyCenterManagerTest {
listOf(
SafetyCenterStaticEntry.Builder("Unspecified title")
.setSummary("Unspecified summary")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(
+ safetySourceTestData.createTestActivityRedirectPendingIntent()
+ )
.build(),
SafetyCenterStaticEntry.Builder("OK")
.setSummary("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(
+ safetySourceTestData.createTestActivityRedirectPendingIntent(
+ explicit = false
+ )
+ )
.build()
)
)
@@ -457,7 +477,7 @@ class SafetyCenterManagerTest {
.safetyCenterEntryOkBuilder(SINGLE_SOURCE_ID)
.setIconAction(
ICON_ACTION_TYPE_INFO,
- safetySourceTestData.testActivityRedirectPendingIntent
+ safetySourceTestData.createTestActivityRedirectPendingIntent()
)
.build()
)
@@ -974,28 +994,105 @@ class SafetyCenterManagerTest {
}
@Test
+ fun getSafetyCenterData_withoutDataExplicitIntentConfig_defaultEntryHasExplicitIntent() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+
+ val apiSafetyCenterData = safetyCenterManager.getSafetyCenterDataWithPermission()
+
+ val expectedExplicitPendingIntent =
+ SafetySourceTestData.createRedirectPendingIntent(
+ context,
+ Intent(ACTION_TEST_ACTIVITY).setPackage(context.packageName)
+ )
+ val defaultEntryPendingIntent =
+ apiSafetyCenterData.entriesOrGroups.firstOrNull()?.entry?.pendingIntent
+ val defaultEntryIntentFilterEqualsToExplicitIntent =
+ callWithShellPermissionIdentity("android.permission.GET_INTENT_SENDER_INTENT") {
+ expectedExplicitPendingIntent.intentFilterEquals(defaultEntryPendingIntent)
+ }
+ assertThat(defaultEntryIntentFilterEqualsToExplicitIntent).isTrue()
+ }
+
+ @Test
fun getSafetyCenterData_withoutDataImplicitIntentConfig_defaultEntryHasImplicitIntent() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.implicitIntentSingleSourceConfig)
val apiSafetyCenterData = safetyCenterManager.getSafetyCenterDataWithPermission()
- val implicitPendingIntentCreatedByCts =
- PendingIntent.getActivity(
+ val expectedImplicitPendingIntent =
+ SafetySourceTestData.createRedirectPendingIntent(
context,
- 0 /* requestCode */,
- Intent(ACTION_TEST_ACTIVITY_EXPORTED),
- PendingIntent.FLAG_IMMUTABLE
+ Intent(ACTION_TEST_ACTIVITY_EXPORTED)
)
val defaultEntryPendingIntent =
apiSafetyCenterData.entriesOrGroups.firstOrNull()?.entry?.pendingIntent
val defaultEntryIntentFilterEqualsToImplicitIntent =
callWithShellPermissionIdentity("android.permission.GET_INTENT_SENDER_INTENT") {
- implicitPendingIntentCreatedByCts.intentFilterEquals(defaultEntryPendingIntent)
+ expectedImplicitPendingIntent.intentFilterEquals(defaultEntryPendingIntent)
}
assertThat(defaultEntryIntentFilterEqualsToImplicitIntent).isTrue()
}
@Test
+ fun getSafetyCenterData_withStaticImplicitResolving_implicitStaticEntry() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.staticSourcesConfig)
+
+ val apiSafetyCenterData = safetyCenterManager.getSafetyCenterDataWithPermission()
+
+ val expectedImplicitPendingIntent =
+ SafetySourceTestData.createRedirectPendingIntent(
+ context,
+ Intent(ACTION_TEST_ACTIVITY_EXPORTED)
+ )
+ val staticEntryPendingIntent =
+ apiSafetyCenterData.staticEntryGroups
+ .firstOrNull()
+ ?.staticEntries
+ ?.firstOrNull()
+ ?.pendingIntent
+ val staticEntryIntentFilterEqualsToImplicitIntent =
+ callWithShellPermissionIdentity("android.permission.GET_INTENT_SENDER_INTENT") {
+ expectedImplicitPendingIntent.intentFilterEquals(staticEntryPendingIntent)
+ }
+ assertThat(staticEntryIntentFilterEqualsToImplicitIntent).isTrue()
+ }
+
+ @Test
+ fun getSafetyCenterData_withStaticImplicitNotExported_explicitStaticEntryUsingCallerPackage() {
+ safetyCenterTestHelper.setConfig(
+ safetyCenterTestConfigs.singleStaticImplicitIntentNotExportedConfig
+ )
+
+ val apiSafetyCenterData = safetyCenterManager.getSafetyCenterDataWithPermission()
+
+ val expectedExplicitPendingIntent =
+ SafetySourceTestData.createRedirectPendingIntent(
+ context,
+ Intent(ACTION_TEST_ACTIVITY).setPackage(context.packageName)
+ )
+ val staticEntryPendingIntent =
+ apiSafetyCenterData.staticEntryGroups
+ .firstOrNull()
+ ?.staticEntries
+ ?.firstOrNull()
+ ?.pendingIntent
+ val staticEntryIntentFilterEqualsToExplicitIntent =
+ callWithShellPermissionIdentity("android.permission.GET_INTENT_SENDER_INTENT") {
+ expectedExplicitPendingIntent.intentFilterEquals(staticEntryPendingIntent)
+ }
+ assertThat(staticEntryIntentFilterEqualsToExplicitIntent).isTrue()
+ }
+
+ @Test
+ fun getSafetyCenterData_withStaticNotResolving_noStaticEntry() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleStaticInvalidIntentConfig)
+
+ val apiSafetyCenterData = safetyCenterManager.getSafetyCenterDataWithPermission()
+
+ assertThat(apiSafetyCenterData.staticEntryGroups).isEmpty()
+ }
+
+ @Test
fun getSafetyCenterData_withComplexConfigWithoutDataProvided_returnsDataFromConfig() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.complexConfig)
@@ -3635,46 +3732,6 @@ class SafetyCenterManagerTest {
}
@Test
- fun lockScreenSource_withoutReplaceLockScreenIconActionFlag_doesntReplace() {
- // Must have a screen lock for the icon action to be set
- assumeTrue(ScreenLockHelper.isDeviceSecure(context))
- safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.settingsLockScreenSourceConfig)
- val listener = safetyCenterTestHelper.addListener()
- SafetyCenterFlags.replaceLockScreenIconAction = false
-
- safetyCenterManager.refreshSafetySourcesWithPermission(REFRESH_REASON_PAGE_OPEN)
- // Skip loading data.
- listener.receiveSafetyCenterData()
-
- val lockScreenSafetyCenterData = listener.receiveSafetyCenterData()
- val lockScreenEntry = lockScreenSafetyCenterData.entriesOrGroups.first().entry!!
- val entryPendingIntent = lockScreenEntry.pendingIntent!!
- val iconActionPendingIntent = lockScreenEntry.iconAction!!.pendingIntent
- // This test passes for now but will eventually start failing once we introduce the fix in
- // the Settings app. This will warn if the assumption is failed rather than fail, at which
- // point we can remove this test (and potentially even this magnificent hack).
- assumeTrue(iconActionPendingIntent == entryPendingIntent)
- }
-
- @Test
- fun lockScreenSource_withReplaceLockScreenIconActionFlag_replaces() {
- // Must have a screen lock for the icon action to be set
- assumeTrue(ScreenLockHelper.isDeviceSecure(context))
- safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.settingsLockScreenSourceConfig)
- val listener = safetyCenterTestHelper.addListener()
-
- safetyCenterManager.refreshSafetySourcesWithPermission(REFRESH_REASON_PAGE_OPEN)
- // Skip loading data.
- listener.receiveSafetyCenterData()
-
- val lockScreenSafetyCenterData = listener.receiveSafetyCenterData()
- val lockScreenEntry = lockScreenSafetyCenterData.entriesOrGroups.first().entry!!
- val entryPendingIntent = lockScreenEntry.pendingIntent!!
- val iconActionPendingIntent = lockScreenEntry.iconAction!!.pendingIntent
- assertThat(iconActionPendingIntent).isNotEqualTo(entryPendingIntent)
- }
-
- @Test
fun beforeAnyDataSet_noLastUpdatedTimestamps() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterNotificationTest.kt b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterNotificationTest.kt
index a97b24bb8..9c9e9b009 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterNotificationTest.kt
+++ b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterNotificationTest.kt
@@ -28,6 +28,7 @@ import android.safetycenter.SafetyCenterStatus
import android.safetycenter.SafetyEvent
import android.safetycenter.SafetySourceErrorDetails
import android.safetycenter.SafetySourceIssue
+import android.service.notification.StatusBarNotification
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
@@ -295,8 +296,8 @@ class SafetyCenterNotificationTest {
@Test
fun setSafetySourceData_issueWithTwoActions_notificationWithTwoActions() {
- val intent1 = safetySourceTestData.testActivityRedirectPendingIntent(identifier = "1")
- val intent2 = safetySourceTestData.testActivityRedirectPendingIntent(identifier = "2")
+ val intent1 = safetySourceTestData.createTestActivityRedirectPendingIntent(identifier = "1")
+ val intent2 = safetySourceTestData.createTestActivityRedirectPendingIntent(identifier = "2")
val data =
safetySourceTestData
@@ -360,8 +361,8 @@ class SafetyCenterNotificationTest {
@Test
@SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_withCustomNotification_usesCustomValues() {
- val intent1 = safetySourceTestData.testActivityRedirectPendingIntent(identifier = "1")
- val intent2 = safetySourceTestData.testActivityRedirectPendingIntent(identifier = "2")
+ val intent1 = safetySourceTestData.createTestActivityRedirectPendingIntent(identifier = "1")
+ val intent2 = safetySourceTestData.createTestActivityRedirectPendingIntent(identifier = "2")
val notification =
SafetySourceIssue.Notification.Builder("Custom title", "Custom text")
@@ -383,7 +384,7 @@ class SafetyCenterNotificationTest {
SafetySourceIssue.Action.Builder(
"default_action",
"Default action",
- safetySourceTestData.testActivityRedirectPendingIntent
+ safetySourceTestData.createTestActivityRedirectPendingIntent()
)
.build()
)
@@ -421,7 +422,7 @@ class SafetyCenterNotificationTest {
SafetySourceIssue.Action.Builder(
"default_action",
"Default action",
- safetySourceTestData.testActivityRedirectPendingIntent
+ safetySourceTestData.createTestActivityRedirectPendingIntent()
)
.build()
)
@@ -474,7 +475,7 @@ class SafetyCenterNotificationTest {
SafetySourceIssue.Action.Builder(
"new_action",
"New action",
- safetySourceTestData.testActivityRedirectPendingIntent(
+ safetySourceTestData.createTestActivityRedirectPendingIntent(
identifier = "new_action"
)
)
@@ -900,13 +901,7 @@ class SafetyCenterNotificationTest {
sendActionPendingIntentAndWaitWithPermission(action)
- TestNotificationListener.waitForSingleNotificationMatching(
- NotificationCharacteristics(
- "Issue solved",
- "",
- actions = emptyList(),
- )
- )
+ TestNotificationListener.waitForSuccessNotification("Issue solved")
}
@Test
@@ -924,16 +919,10 @@ class SafetyCenterNotificationTest {
Response.SetData(safetySourceTestData.information)
)
sendActionPendingIntentAndWaitWithPermission(action)
- val issueSolvedNotificationWithChannel =
- TestNotificationListener.waitForSingleNotificationMatching(
- NotificationCharacteristics(
- "Issue solved",
- "",
- actions = emptyList(),
- )
- )
- assertThat(issueSolvedNotificationWithChannel.hasAutoCancel()).isTrue()
+ TestNotificationListener.waitForSuccessNotification("Issue solved") {
+ assertThat(it.hasAutoCancel()).isTrue()
+ }
}
// TODO(b/284271124): Decide what to do with existing notifications when flag flipped off
@@ -979,13 +968,7 @@ class SafetyCenterNotificationTest {
sendActionPendingIntentAndWaitWithPermission(action)
- TestNotificationListener.waitForSingleNotificationMatching(
- NotificationCharacteristics(
- "Issue solved",
- "",
- actions = emptyList(),
- )
- )
+ TestNotificationListener.waitForSuccessNotification("Issue solved")
}
@Test
@@ -1046,13 +1029,7 @@ class SafetyCenterNotificationTest {
sendActionPendingIntentAndWaitWithPermission(action)
- TestNotificationListener.waitForSingleNotificationMatching(
- NotificationCharacteristics(
- "Solved via notification action :)",
- "",
- actions = emptyList(),
- )
- )
+ TestNotificationListener.waitForSuccessNotification("Solved via notification action :)")
}
@Test
@@ -1120,7 +1097,7 @@ class SafetyCenterNotificationTest {
safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.informationWithIssue)
val notificationWithChannel = TestNotificationListener.waitForSingleNotification()
- assertThat(notificationWithChannel.hasAutoCancel()).isTrue()
+ assertThat(notificationWithChannel.statusBarNotification.hasAutoCancel()).isTrue()
}
@Test
@@ -1131,7 +1108,7 @@ class SafetyCenterNotificationTest {
)
val notificationWithChannel = TestNotificationListener.waitForSingleNotification()
- assertThat(notificationWithChannel.hasAutoCancel()).isFalse()
+ assertThat(notificationWithChannel.statusBarNotification.hasAutoCancel()).isFalse()
}
private companion object {
@@ -1156,9 +1133,8 @@ class SafetyCenterNotificationTest {
sourceIds.map { "$it/$ISSUE_TYPE_ID" }.toSet()
}
- fun StatusBarNotificationWithChannel.hasAutoCancel(): Boolean {
- val autoCancelMask =
- statusBarNotification.notification.flags and Notification.FLAG_AUTO_CANCEL
+ fun StatusBarNotification.hasAutoCancel(): Boolean {
+ val autoCancelMask = notification.flags and Notification.FLAG_AUTO_CANCEL
return autoCancelMask != 0
}
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetySourceDataFixesTest.kt b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetySourceDataFixesTest.kt
new file mode 100644
index 000000000..4ba293eb9
--- /dev/null
+++ b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetySourceDataFixesTest.kt
@@ -0,0 +1,298 @@
+package android.safetycenter.functional
+
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+import android.safetycenter.SafetyCenterManager
+import android.safetycenter.SafetySourceData
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_INFORMATION
+import android.safetycenter.SafetySourceIssue
+import android.safetycenter.SafetySourceStatus
+import androidx.annotation.RequiresApi
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import com.android.compatibility.common.preconditions.ScreenLockHelper
+import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.getSafetySourceDataWithPermission
+import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.refreshSafetySourcesWithPermission
+import com.android.safetycenter.testing.SafetyCenterFlags
+import com.android.safetycenter.testing.SafetyCenterTestConfigs
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_1
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_2
+import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
+import com.android.safetycenter.testing.SafetySourceTestData
+import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assume.assumeTrue
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Functional tests for "fixes" applied to Safety Source data received by [SafetyCenterManager]. */
+@RunWith(AndroidJUnit4::class)
+class SafetySourceDataFixesTest {
+
+ private val context: Context = ApplicationProvider.getApplicationContext()
+ private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
+ private val safetySourceTestData = SafetySourceTestData(context)
+ private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
+ private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
+
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+
+ @Test
+ fun lockScreenSource_withoutReplaceLockScreenIconActionFlag_doesntReplace() {
+ // Must have a screen lock for the icon action to be set
+ assumeTrue(ScreenLockHelper.isDeviceSecure(context))
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.settingsLockScreenSourceConfig)
+ val listener = safetyCenterTestHelper.addListener()
+ SafetyCenterFlags.replaceLockScreenIconAction = false
+
+ safetyCenterManager.refreshSafetySourcesWithPermission(
+ SafetyCenterManager.REFRESH_REASON_PAGE_OPEN
+ )
+ // Skip loading data.
+ listener.receiveSafetyCenterData()
+
+ val lockScreenSafetyCenterData = listener.receiveSafetyCenterData()
+ val lockScreenEntry = lockScreenSafetyCenterData.entriesOrGroups.first().entry!!
+ val entryPendingIntent = lockScreenEntry.pendingIntent!!
+ val iconActionPendingIntent = lockScreenEntry.iconAction!!.pendingIntent
+ // This test passes for now but will eventually start failing once we introduce the fix in
+ // the Settings app. This will warn if the assumption is failed rather than fail, at which
+ // point we can remove this test (and potentially even this magnificent hack).
+ assumeTrue(iconActionPendingIntent == entryPendingIntent)
+ }
+
+ @Test
+ fun lockScreenSource_withReplaceLockScreenIconActionFlag_replaces() {
+ // Must have a screen lock for the icon action to be set
+ assumeTrue(ScreenLockHelper.isDeviceSecure(context))
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.settingsLockScreenSourceConfig)
+ val listener = safetyCenterTestHelper.addListener()
+
+ safetyCenterManager.refreshSafetySourcesWithPermission(
+ SafetyCenterManager.REFRESH_REASON_PAGE_OPEN
+ )
+ // Skip loading data.
+ listener.receiveSafetyCenterData()
+
+ val lockScreenSafetyCenterData = listener.receiveSafetyCenterData()
+ val lockScreenEntry = lockScreenSafetyCenterData.entriesOrGroups.first().entry!!
+ val entryPendingIntent = lockScreenEntry.pendingIntent!!
+ val iconActionPendingIntent = lockScreenEntry.iconAction!!.pendingIntent
+ assertThat(iconActionPendingIntent).isNotEqualTo(entryPendingIntent)
+ }
+
+ @Test
+ fun defaultActionOverride_issue_overridesMatchingActions() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ val targetActionId = "TargetActionId"
+ SafetyCenterFlags.actionsToOverrideWithDefaultIntent =
+ mapOf(SINGLE_SOURCE_ID to setOf(targetActionId, "AdditionalActionId"))
+
+ val originalPendingIntent = pendingIntent(Intent("blah.wrong.INTENT"))
+ val dataWithActionToOverride =
+ sourceDataBuilder()
+ .addIssue(
+ issueBuilder()
+ .clearActions()
+ .addAction(
+ safetySourceTestData.action(
+ id = targetActionId,
+ pendingIntent = originalPendingIntent
+ )
+ )
+ .build()
+ )
+ .build()
+
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, dataWithActionToOverride)
+
+ val overriddenPendingIntent =
+ safetyCenterManager
+ .getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)!!
+ .issues[0]
+ .actions[0]
+ .pendingIntent
+ val expectedPendingIntent =
+ pendingIntent(
+ Intent(SafetyCenterTestConfigs.ACTION_TEST_ACTIVITY).setPackage(context.packageName)
+ )
+ assertThat(intentsFilterEqual(overriddenPendingIntent, expectedPendingIntent)).isTrue()
+ }
+ @Test
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
+ fun defaultActionOverride_notification_overridesMatchingActions() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ val targetActionId = "TargetActionId"
+ SafetyCenterFlags.actionsToOverrideWithDefaultIntent =
+ mapOf(SINGLE_SOURCE_ID to setOf(targetActionId, "AdditionalActionId"))
+
+ val originalPendingIntent = pendingIntent(Intent("blah.wrong.INTENT"))
+ val dataWithNotificationActionToOverride =
+ sourceDataBuilder()
+ .addIssue(
+ issueBuilder()
+ .setCustomNotification(
+ notification(
+ safetySourceTestData.action(
+ id = targetActionId,
+ pendingIntent = originalPendingIntent
+ )
+ )
+ )
+ .build()
+ )
+ .build()
+
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, dataWithNotificationActionToOverride)
+
+ val overriddenPendingIntent =
+ safetyCenterManager
+ .getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)!!
+ .issues[0]
+ .customNotification!!
+ .actions[0]
+ .pendingIntent
+ val expectedPendingIntent =
+ pendingIntent(
+ Intent(SafetyCenterTestConfigs.ACTION_TEST_ACTIVITY).setPackage(context.packageName)
+ )
+ assertThat(intentsFilterEqual(overriddenPendingIntent, expectedPendingIntent)).isTrue()
+ }
+
+ @Test
+ fun defaultActionOverride_sameActionIdDifferentSource_doesNotOverride() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
+ val targetActionId = "TargetActionId"
+ SafetyCenterFlags.actionsToOverrideWithDefaultIntent =
+ mapOf(SOURCE_ID_1 to setOf(targetActionId, "AdditionalActionId"))
+
+ val originalPendingIntent = pendingIntent(Intent("blah.wrong.INTENT"))
+ val dataWithoutActionToOverride =
+ sourceDataBuilder()
+ .addIssue(
+ issueBuilder()
+ .clearActions()
+ .addAction(
+ safetySourceTestData.action(
+ id = targetActionId,
+ pendingIntent = originalPendingIntent
+ )
+ )
+ .build()
+ )
+ .build()
+
+ safetyCenterTestHelper.setData(
+ SOURCE_ID_2, // Different source ID
+ dataWithoutActionToOverride
+ )
+
+ val actualPendingIntent =
+ safetyCenterManager
+ .getSafetySourceDataWithPermission(SOURCE_ID_2)!!
+ .issues[0]
+ .actions[0]
+ .pendingIntent
+ assertThat(intentsFilterEqual(actualPendingIntent, originalPendingIntent)).isTrue()
+ }
+
+ @Test
+ fun defaultActionOverride_sameSourceDifferentActionId_doesNotOverride() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
+ SafetyCenterFlags.actionsToOverrideWithDefaultIntent =
+ mapOf(SOURCE_ID_1 to setOf("TargetActionId"))
+
+ val originalPendingIntent = pendingIntent(Intent("blah.wrong.INTENT"))
+ val dataWithoutActionToOverride =
+ sourceDataBuilder()
+ .addIssue(
+ issueBuilder()
+ .clearActions()
+ .addAction(
+ safetySourceTestData.action(
+ id = "DifferentActionId",
+ pendingIntent = originalPendingIntent
+ )
+ )
+ .build()
+ )
+ .build()
+
+ safetyCenterTestHelper.setData(SOURCE_ID_1, dataWithoutActionToOverride)
+
+ val actualPendingIntent =
+ safetyCenterManager
+ .getSafetySourceDataWithPermission(SOURCE_ID_1)!!
+ .issues[0]
+ .actions[0]
+ .pendingIntent
+ assertThat(intentsFilterEqual(actualPendingIntent, originalPendingIntent)).isTrue()
+ }
+
+ @Test
+ fun defaultActionOverride_noDefaultIntent_doesNotOverride() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceInvalidIntentConfig)
+ val targetActionId = "TargetActionId"
+ SafetyCenterFlags.actionsToOverrideWithDefaultIntent =
+ mapOf(SINGLE_SOURCE_ID to setOf(targetActionId, "AdditionalActionId"))
+
+ val originalPendingIntent = pendingIntent(Intent("blah.wrong.INTENT"))
+ val dataWithActionToOverride =
+ sourceDataBuilder()
+ .addIssue(
+ issueBuilder()
+ .clearActions()
+ .addAction(
+ safetySourceTestData.action(
+ id = targetActionId,
+ pendingIntent = originalPendingIntent
+ )
+ )
+ .build()
+ )
+ .build()
+
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, dataWithActionToOverride)
+
+ val actualPendingIntent =
+ safetyCenterManager
+ .getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)!!
+ .issues[0]
+ .actions[0]
+ .pendingIntent
+ assertThat(intentsFilterEqual(actualPendingIntent, originalPendingIntent)).isTrue()
+ }
+
+ private fun issueBuilder() = safetySourceTestData.defaultInformationIssueBuilder()
+
+ private fun pendingIntent(intent: Intent) =
+ PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
+
+ companion object {
+ private fun sourceDataBuilder() =
+ SafetySourceData.Builder()
+ .setStatus(
+ SafetySourceStatus.Builder("OK", "Blah", SEVERITY_LEVEL_INFORMATION).build()
+ )
+
+ @RequiresApi(UPSIDE_DOWN_CAKE)
+ private fun notification(action: SafetySourceIssue.Action) =
+ SafetySourceIssue.Notification.Builder("Blah", "Bleh").addAction(action).build()
+
+ private fun intentsFilterEqual(
+ actualPendingIntent: PendingIntent,
+ expectedPendingIntent: PendingIntent?
+ ) =
+ callWithShellPermissionIdentity("android.permission.GET_INTENT_SENDER_INTENT") {
+ actualPendingIntent.intentFilterEquals(expectedPendingIntent)
+ }
+ }
+}
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterStatusCardTest.kt b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterStatusCardTest.kt
index 5655b935b..f76a52256 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterStatusCardTest.kt
+++ b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterStatusCardTest.kt
@@ -17,6 +17,8 @@
package android.safetycenter.functional.ui
import android.content.Context
+import android.os.Build
+import android.safetycenter.SafetySourceData
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.uiautomator.By
@@ -105,6 +107,7 @@ class SafetyCenterStatusCardTest {
@Test
fun withInformationAndNoIssues_hasRescanButton() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ preSetDataOnT(SINGLE_SOURCE_ID, safetySourceTestData.information)
SafetySourceReceiver.setResponse(
Request.Refresh(SINGLE_SOURCE_ID),
Response.SetData(safetySourceTestData.information)
@@ -122,6 +125,7 @@ class SafetyCenterStatusCardTest {
@Test
fun withInformationAndNoIssues_hasContentDescriptions() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ preSetDataOnT(SINGLE_SOURCE_ID, safetySourceTestData.information)
SafetySourceReceiver.setResponse(
Request.Refresh(SINGLE_SOURCE_ID),
Response.SetData(safetySourceTestData.information)
@@ -136,6 +140,7 @@ class SafetyCenterStatusCardTest {
@Test
fun withInformationIssue_doesNotHaveRescanButton() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ preSetDataOnT(SINGLE_SOURCE_ID, safetySourceTestData.informationWithIssue)
SafetySourceReceiver.setResponse(
Request.Refresh(SINGLE_SOURCE_ID),
Response.SetData(safetySourceTestData.informationWithIssue)
@@ -153,6 +158,10 @@ class SafetyCenterStatusCardTest {
@Test
fun withRecommendationIssue_doesNotHaveRescanButton() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(
+ SINGLE_SOURCE_ID,
+ safetySourceTestData.recommendationWithGeneralIssue
+ )
SafetySourceReceiver.setResponse(
Request.Refresh(SINGLE_SOURCE_ID),
Response.SetData(safetySourceTestData.recommendationWithGeneralIssue)
@@ -172,6 +181,10 @@ class SafetyCenterStatusCardTest {
@Test
fun withCriticalWarningIssue_doesNotHaveRescanButton() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(
+ SINGLE_SOURCE_ID,
+ safetySourceTestData.criticalWithResolvingGeneralIssue
+ )
SafetySourceReceiver.setResponse(
Request.Refresh(SINGLE_SOURCE_ID),
Response.SetData(safetySourceTestData.criticalWithResolvingGeneralIssue)
@@ -191,6 +204,7 @@ class SafetyCenterStatusCardTest {
@Test
fun withKnownStatus_displaysScanningOnRescan() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ preSetDataOnT(SINGLE_SOURCE_ID, safetySourceTestData.information)
SafetySourceReceiver.setResponse(
Request.Refresh(SINGLE_SOURCE_ID),
Response.SetData(safetySourceTestData.information)
@@ -214,6 +228,7 @@ class SafetyCenterStatusCardTest {
@Test
fun rescan_updatesDataAfterScanCompletes() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ preSetDataOnT(SINGLE_SOURCE_ID, safetySourceTestData.information)
SafetySourceReceiver.setResponse(
Request.Refresh(SINGLE_SOURCE_ID),
Response.SetData(safetySourceTestData.information)
@@ -239,4 +254,14 @@ class SafetyCenterStatusCardTest {
)
}
}
+
+ /**
+ * Sets the given data for the given source ID if this test is running on T builds. This is a
+ * mitigation for b/301234118 which seems to only fail consistently on T.
+ */
+ private fun preSetDataOnT(sourceId: String, safetySourceData: SafetySourceData) {
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
+ safetyCenterTestHelper.setData(sourceId, safetySourceData)
+ }
+ }
}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt
index 714565d62..912ea44ad 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt
@@ -203,6 +203,18 @@ object SafetyCenterFlags {
)
/**
+ * Flag containing a map (a comma separated list of colon separated pairs) where the key is a
+ * Safety Source ID and the value is a vertical-bar-delimited list of Action IDs that should
+ * have their PendingIntent replaced with the source's default PendingIntent.
+ */
+ private val actionsToOverrideWithDefaultIntentFlag =
+ Flag(
+ "safety_center_actions_to_override_with_default_intent",
+ defaultValue = emptyMap(),
+ MapParser(StringParser(), SetParser(StringParser(), delimiter = "|"))
+ )
+
+ /**
* Flag that represents a comma delimited list of IDs of sources that should only be refreshed
* when Safety Center is on screen. We will refresh these sources only on page open and when the
* scan button is clicked.
@@ -303,6 +315,7 @@ object SafetyCenterFlags {
resurfaceIssueMaxCountsFlag,
resurfaceIssueDelaysFlag,
issueCategoryAllowlistsFlag,
+ actionsToOverrideWithDefaultIntentFlag,
allowedAdditionalPackageCertsFlag,
backgroundRefreshDeniedSourcesFlag,
allowStatsdLoggingFlag,
@@ -358,6 +371,10 @@ object SafetyCenterFlags {
/** A property that allows getting and setting the [issueCategoryAllowlistsFlag]. */
var issueCategoryAllowlists: Map<Int, Set<String>> by issueCategoryAllowlistsFlag
+ /** A property that allows getting and setting the [actionsToOverrideWithDefaultIntentFlag]. */
+ var actionsToOverrideWithDefaultIntent: Map<String, Set<String>> by
+ actionsToOverrideWithDefaultIntentFlag
+
var allowedAdditionalPackageCerts: Map<String, Set<String>> by allowedAdditionalPackageCertsFlag
/** A property that allows getting and setting the [backgroundRefreshDeniedSourcesFlag]. */
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt
index de4cf7094..fea9b45cc 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt
@@ -64,7 +64,9 @@ class SafetyCenterTestConfigs(private val context: Context) {
*/
val singleSourceInvalidIntentConfig =
singleSourceConfig(
- dynamicSafetySourceBuilder(SINGLE_SOURCE_ID).setIntentAction("stub").build()
+ dynamicSafetySourceBuilder(SINGLE_SOURCE_ID)
+ .setIntentAction(INTENT_ACTION_NOT_RESOLVING)
+ .build()
)
/**
@@ -348,7 +350,9 @@ class SafetyCenterTestConfigs(private val context: Context) {
.addSafetySourcesGroup(
safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_1)
.addSafetySource(
- dynamicSafetySourceBuilder(SOURCE_ID_1).setIntentAction("stub").build()
+ dynamicSafetySourceBuilder(SOURCE_ID_1)
+ .setIntentAction(INTENT_ACTION_NOT_RESOLVING)
+ .build()
)
.addSafetySource(dynamicSafetySource(SOURCE_ID_2))
.build()
@@ -373,9 +377,7 @@ class SafetyCenterTestConfigs(private val context: Context) {
* Source group provided by [staticSourcesConfig] containing a single source [staticSource1].
*/
val staticSourceGroup1 =
- SafetySourcesGroup.Builder()
- .setId("test_static_sources_group_id_1")
- .setTitleResId(android.R.string.paste)
+ staticSafetySourcesGroupBuilder("test_static_sources_group_id_1")
.addSafetySource(staticSource1)
.build()
@@ -383,8 +385,7 @@ class SafetyCenterTestConfigs(private val context: Context) {
* Source group provided by [staticSourcesConfig] containing a single source [staticSource2].
*/
val staticSourceGroup2 =
- SafetySourcesGroup.Builder()
- .setId("test_static_sources_group_id_2")
+ staticSafetySourcesGroupBuilder("test_static_sources_group_id_2")
.setTitleResId(android.R.string.copy)
.addSafetySource(staticSource2)
.build()
@@ -402,7 +403,44 @@ class SafetyCenterTestConfigs(private val context: Context) {
* The particular source ID is configured in the same way as sources hosted by the Settings app,
* to launch as if it is part of the Settings app UI.
*/
- val singleStaticSettingsSource = singleSourceConfig(staticSafetySource("TestSource"))
+ val singleStaticSettingsSourceConfig =
+ SafetyCenterConfig.Builder()
+ .addSafetySourcesGroup(
+ staticSafetySourcesGroupBuilder("single_static_source_group")
+ .addSafetySource(staticSafetySource("TestSource"))
+ .build()
+ )
+ .build()
+
+ /** A [SafetyCenterConfig] with a single static source and an intent that doesn't resolve */
+ val singleStaticInvalidIntentConfig =
+ SafetyCenterConfig.Builder()
+ .addSafetySourcesGroup(
+ staticSafetySourcesGroupBuilder("single_static_source_group")
+ .addSafetySource(
+ staticSafetySourceBuilder(SINGLE_SOURCE_ID)
+ .setIntentAction(INTENT_ACTION_NOT_RESOLVING)
+ .build()
+ )
+ .build()
+ )
+ .build()
+
+ /**
+ * A [SafetyCenterConfig] with a single static source and an implicit intent that isn't exported
+ */
+ val singleStaticImplicitIntentNotExportedConfig =
+ SafetyCenterConfig.Builder()
+ .addSafetySourcesGroup(
+ staticSafetySourcesGroupBuilder("single_static_source_group")
+ .addSafetySource(
+ staticSafetySourceBuilder(SINGLE_SOURCE_ID)
+ .setIntentAction(ACTION_TEST_ACTIVITY)
+ .build()
+ )
+ .build()
+ )
+ .build()
/** [SafetyCenterConfig] used in tests for Your Work Policy Info source. */
val workPolicyInfoConfig =
@@ -750,7 +788,7 @@ class SafetyCenterTestConfigs(private val context: Context) {
.setId(id)
.setTitleResId(android.R.string.ok)
.setSummaryResId(android.R.string.ok)
- .setIntentAction(ACTION_TEST_ACTIVITY)
+ .setIntentAction(ACTION_TEST_ACTIVITY_EXPORTED)
.setProfile(SafetySource.PROFILE_PRIMARY)
private fun staticAllProfileSafetySourceBuilder(id: String) =
@@ -780,6 +818,9 @@ class SafetyCenterTestConfigs(private val context: Context) {
.setTitleResId(android.R.string.ok)
.setSummaryResId(android.R.string.ok)
+ private fun staticSafetySourcesGroupBuilder(id: String) =
+ SafetySourcesGroup.Builder().setId(id).setTitleResId(android.R.string.paste)
+
fun singleSourceConfig(safetySource: SafetySource) =
SafetyCenterConfig.Builder()
.addSafetySourcesGroup(
@@ -1033,5 +1074,7 @@ class SafetyCenterTestConfigs(private val context: Context) {
* [privacySubpageWithoutDataSourcesConfig], to replicate the privacy sources group.
*/
const val ANDROID_PRIVACY_SOURCES_GROUP_ID = "AndroidPrivacySources"
+
+ private const val INTENT_ACTION_NOT_RESOLVING = "there.is.no.way.this.resolves"
}
}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestData.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestData.kt
index 31e9855ae..289bc32a8 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestData.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestData.kt
@@ -164,7 +164,8 @@ class SafetyCenterTestData(context: Context) {
sourceId: String,
userId: Int = UserHandle.myUserId(),
title: CharSequence = "OK",
- pendingIntent: PendingIntent? = safetySourceTestData.testActivityRedirectPendingIntent
+ pendingIntent: PendingIntent? =
+ safetySourceTestData.createTestActivityRedirectPendingIntent()
) =
SafetyCenterEntry.Builder(entryId(sourceId, userId), title)
.setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNKNOWN)
@@ -181,7 +182,8 @@ class SafetyCenterTestData(context: Context) {
sourceId: String,
userId: Int = UserHandle.myUserId(),
title: CharSequence = "OK",
- pendingIntent: PendingIntent? = safetySourceTestData.testActivityRedirectPendingIntent
+ pendingIntent: PendingIntent? =
+ safetySourceTestData.createTestActivityRedirectPendingIntent()
) = safetyCenterEntryDefaultBuilder(sourceId, userId, title, pendingIntent).build()
/**
@@ -197,7 +199,9 @@ class SafetyCenterTestData(context: Context) {
SafetyCenterEntry.Builder(entryId(sourceId, userId), title)
.setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNSPECIFIED)
.setSummary("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(
+ safetySourceTestData.createTestActivityRedirectPendingIntent(explicit = false)
+ )
.setSeverityUnspecifiedIconType(SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON)
/**
@@ -214,7 +218,8 @@ class SafetyCenterTestData(context: Context) {
*/
fun safetyCenterEntryUnspecified(
sourceId: String,
- pendingIntent: PendingIntent? = safetySourceTestData.testActivityRedirectPendingIntent
+ pendingIntent: PendingIntent? =
+ safetySourceTestData.createTestActivityRedirectPendingIntent()
) =
SafetyCenterEntry.Builder(entryId(sourceId), "Unspecified title")
.setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNSPECIFIED)
@@ -237,7 +242,7 @@ class SafetyCenterTestData(context: Context) {
SafetyCenterEntry.Builder(entryId(sourceId, userId), title)
.setSeverityLevel(ENTRY_SEVERITY_LEVEL_OK)
.setSummary("Ok summary")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(safetySourceTestData.createTestActivityRedirectPendingIntent())
.setSeverityUnspecifiedIconType(SEVERITY_UNSPECIFIED_ICON_TYPE_NO_RECOMMENDATION)
/**
@@ -262,7 +267,7 @@ class SafetyCenterTestData(context: Context) {
SafetyCenterEntry.Builder(entryId(sourceId), "Recommendation title")
.setSeverityLevel(ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
.setSummary(summary)
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(safetySourceTestData.createTestActivityRedirectPendingIntent())
.setSeverityUnspecifiedIconType(SEVERITY_UNSPECIFIED_ICON_TYPE_NO_RECOMMENDATION)
.build()
@@ -274,7 +279,7 @@ class SafetyCenterTestData(context: Context) {
SafetyCenterEntry.Builder(entryId(sourceId), "Critical title")
.setSeverityLevel(ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING)
.setSummary("Critical summary")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .setPendingIntent(safetySourceTestData.createTestActivityRedirectPendingIntent())
.setSeverityUnspecifiedIconType(SEVERITY_UNSPECIFIED_ICON_TYPE_NO_RECOMMENDATION)
.build()
@@ -305,7 +310,7 @@ class SafetyCenterTestData(context: Context) {
userId
),
"Review",
- safetySourceTestData.testActivityRedirectPendingIntent
+ safetySourceTestData.createTestActivityRedirectPendingIntent()
)
.build()
)
@@ -345,7 +350,7 @@ class SafetyCenterTestData(context: Context) {
userId
),
"See issue",
- safetySourceTestData.testActivityRedirectPendingIntent
+ safetySourceTestData.createTestActivityRedirectPendingIntent()
)
.apply {
if (confirmationDialog && SdkLevel.isAtLeastU()) {
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt
index 0dda827ee..2c4f856bb 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt
@@ -20,7 +20,6 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_RECEIVER_FOREGROUND
-import android.content.pm.PackageManager.ResolveInfoFlags
import android.os.Build.VERSION_CODES.TIRAMISU
import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.safetycenter.SafetyEvent
@@ -39,13 +38,13 @@ import android.safetycenter.SafetySourceStatus.IconAction.ICON_TYPE_INFO
import androidx.annotation.RequiresApi
import com.android.modules.utils.build.SdkLevel
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.ACTION_TEST_ACTIVITY
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.ACTION_TEST_ACTIVITY_EXPORTED
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
import com.android.safetycenter.testing.SafetySourceIntentHandler.Companion.ACTION_DISMISS_ISSUE
import com.android.safetycenter.testing.SafetySourceIntentHandler.Companion.ACTION_RESOLVE_ACTION
import com.android.safetycenter.testing.SafetySourceIntentHandler.Companion.EXTRA_SOURCE_ID
import com.android.safetycenter.testing.SafetySourceIntentHandler.Companion.EXTRA_SOURCE_ISSUE_ACTION_ID
import com.android.safetycenter.testing.SafetySourceIntentHandler.Companion.EXTRA_SOURCE_ISSUE_ID
-import java.lang.IllegalStateException
import kotlin.math.max
/**
@@ -55,16 +54,21 @@ import kotlin.math.max
@RequiresApi(TIRAMISU)
class SafetySourceTestData(private val context: Context) {
- /** A [PendingIntent] that redirects to the [TestActivity] page. */
- val testActivityRedirectPendingIntent =
- createRedirectPendingIntent(context, Intent(ACTION_TEST_ACTIVITY))
-
/**
- * A [PendingIntent] that redirects to the [TestActivity] page, the [Intent] is constructed with
- * the given [identifier].
+ * A [PendingIntent] that redirects to the [TestActivity] page.
+ *
+ * @param explicit whether the returned [PendingIntent] should use an explicit [Intent] (default
+ * [true])
+ * @param identifier the [Intent] identifier (default [null])
*/
- fun testActivityRedirectPendingIntent(identifier: String? = null) =
- createRedirectPendingIntent(context, Intent(ACTION_TEST_ACTIVITY).setIdentifier(identifier))
+ fun createTestActivityRedirectPendingIntent(
+ explicit: Boolean = true,
+ identifier: String? = null
+ ) =
+ createRedirectPendingIntent(
+ context,
+ createTestActivityIntent(context, explicit).setIdentifier(identifier)
+ )
/** A [SafetySourceData] with a [SEVERITY_LEVEL_UNSPECIFIED] [SafetySourceStatus]. */
val unspecified =
@@ -93,7 +97,7 @@ class SafetySourceTestData(private val context: Context) {
SEVERITY_LEVEL_UNSPECIFIED
)
.setEnabled(false)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
.build()
@@ -110,14 +114,14 @@ class SafetySourceTestData(private val context: Context) {
summary: String = "Information issue summary"
) =
SafetySourceIssue.Builder(id, title, summary, SEVERITY_LEVEL_INFORMATION, ISSUE_TYPE_ID)
- .addAction(
- Action.Builder(
- INFORMATION_ISSUE_ACTION_ID,
- "Review",
- testActivityRedirectPendingIntent
- )
- .build()
- )
+ .addAction(action())
+
+ /** Creates an action with some defaults set. */
+ fun action(
+ id: String = INFORMATION_ISSUE_ACTION_ID,
+ label: String = "Review",
+ pendingIntent: PendingIntent = createTestActivityRedirectPendingIntent()
+ ) = Action.Builder(id, label, pendingIntent).build()
/**
* A [SafetySourceIssue] with a [SEVERITY_LEVEL_INFORMATION] and a redirecting [Action]. With
@@ -132,14 +136,7 @@ class SafetySourceTestData(private val context: Context) {
ISSUE_TYPE_ID
)
.setSubtitle("Information issue subtitle")
- .addAction(
- Action.Builder(
- INFORMATION_ISSUE_ACTION_ID,
- "Review",
- testActivityRedirectPendingIntent
- )
- .build()
- )
+ .addAction(action())
.build()
/**
@@ -154,7 +151,7 @@ class SafetySourceTestData(private val context: Context) {
"Unspecified summary",
SEVERITY_LEVEL_UNSPECIFIED
)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
.addIssue(informationIssue)
@@ -172,7 +169,7 @@ class SafetySourceTestData(private val context: Context) {
"Unspecified summary",
SEVERITY_LEVEL_UNSPECIFIED
)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
.addIssue(informationIssue)
@@ -183,7 +180,7 @@ class SafetySourceTestData(private val context: Context) {
SafetySourceData.Builder()
.setStatus(
SafetySourceStatus.Builder("Ok title", "Ok summary", SEVERITY_LEVEL_INFORMATION)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
.build()
@@ -209,8 +206,10 @@ class SafetySourceTestData(private val context: Context) {
SafetySourceData.Builder()
.setStatus(
SafetySourceStatus.Builder("Ok title", "Ok summary", SEVERITY_LEVEL_INFORMATION)
- .setPendingIntent(testActivityRedirectPendingIntent)
- .setIconAction(IconAction(ICON_TYPE_INFO, testActivityRedirectPendingIntent))
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
+ .setIconAction(
+ IconAction(ICON_TYPE_INFO, createTestActivityRedirectPendingIntent())
+ )
.build()
)
.build()
@@ -223,8 +222,10 @@ class SafetySourceTestData(private val context: Context) {
SafetySourceData.Builder()
.setStatus(
SafetySourceStatus.Builder("Ok title", "Ok summary", SEVERITY_LEVEL_INFORMATION)
- .setPendingIntent(testActivityRedirectPendingIntent)
- .setIconAction(IconAction(ICON_TYPE_GEAR, testActivityRedirectPendingIntent))
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
+ .setIconAction(
+ IconAction(ICON_TYPE_GEAR, createTestActivityRedirectPendingIntent())
+ )
.build()
)
.build()
@@ -237,7 +238,7 @@ class SafetySourceTestData(private val context: Context) {
SafetySourceData.Builder()
.setStatus(
SafetySourceStatus.Builder("Ok title", "Ok summary", SEVERITY_LEVEL_INFORMATION)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
.addIssue(informationIssue)
@@ -253,7 +254,7 @@ class SafetySourceTestData(private val context: Context) {
SafetySourceData.Builder()
.setStatus(
SafetySourceStatus.Builder("Ok title", "Ok summary", SEVERITY_LEVEL_INFORMATION)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
.addIssue(
@@ -275,7 +276,7 @@ class SafetySourceTestData(private val context: Context) {
"Ok summary",
SEVERITY_LEVEL_INFORMATION
)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
.addIssue(informationIssue)
@@ -289,7 +290,7 @@ class SafetySourceTestData(private val context: Context) {
SafetySourceData.Builder()
.setStatus(
SafetySourceStatus.Builder("Ok title", "Ok summary", SEVERITY_LEVEL_INFORMATION)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
.addIssue(informationIssueWithSubtitle)
@@ -315,7 +316,7 @@ class SafetySourceTestData(private val context: Context) {
Action.Builder(
RECOMMENDATION_ISSUE_ACTION_ID,
"See issue",
- testActivityRedirectPendingIntent
+ createTestActivityRedirectPendingIntent()
)
.apply {
if (confirmationDialog && SdkLevel.isAtLeastU()) {
@@ -383,7 +384,7 @@ class SafetySourceTestData(private val context: Context) {
"Recommendation summary",
SEVERITY_LEVEL_RECOMMENDATION
)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
@@ -467,7 +468,11 @@ class SafetySourceTestData(private val context: Context) {
/** An action that redirects to [TestActivity] */
val testActivityRedirectAction =
- Action.Builder(CRITICAL_ISSUE_ACTION_ID, "Redirect", testActivityRedirectPendingIntent)
+ Action.Builder(
+ CRITICAL_ISSUE_ACTION_ID,
+ "Redirect",
+ createTestActivityRedirectPendingIntent()
+ )
.build()
/** A resolving Critical [Action] that declares a success message */
@@ -505,7 +510,7 @@ class SafetySourceTestData(private val context: Context) {
Action.Builder(
CRITICAL_ISSUE_ACTION_ID,
"Go solve issue",
- testActivityRedirectPendingIntent
+ createTestActivityRedirectPendingIntent()
)
.build()
)
@@ -584,7 +589,7 @@ class SafetySourceTestData(private val context: Context) {
"Critical summary",
SEVERITY_LEVEL_CRITICAL_WARNING
)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
@@ -698,7 +703,7 @@ class SafetySourceTestData(private val context: Context) {
"Critical summary",
SEVERITY_LEVEL_CRITICAL_WARNING
)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
.addIssue(criticalResolvingIssueWithSuccessMessage)
@@ -723,7 +728,7 @@ class SafetySourceTestData(private val context: Context) {
"Critical summary 2",
SEVERITY_LEVEL_CRITICAL_WARNING
)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
.addIssue(criticalRedirectingIssue)
@@ -742,7 +747,7 @@ class SafetySourceTestData(private val context: Context) {
SafetySourceData.Builder()
.setStatus(
SafetySourceStatus.Builder(entryTitle, entrySummary, severityLevel)
- .setPendingIntent(testActivityRedirectPendingIntent)
+ .setPendingIntent(createTestActivityRedirectPendingIntent())
.build()
)
.apply {
@@ -759,7 +764,7 @@ class SafetySourceTestData(private val context: Context) {
Action.Builder(
"action_id",
"Action",
- testActivityRedirectPendingIntent
+ createTestActivityRedirectPendingIntent()
)
.build()
)
@@ -824,41 +829,28 @@ class SafetySourceTestData(private val context: Context) {
return builder.build()
}
- /** Returns a [PendingIntent] that redirects to [intent]. */
- fun createRedirectPendingIntent(
- context: Context,
- intent: Intent,
- inQuietMode: Boolean = false
- ): PendingIntent {
- val explicitIntent = Intent(intent).setPackage(context.packageName)
- val redirectIntent =
- if (intentResolves(context, explicitIntent)) {
- explicitIntent
- } else if (intentResolves(context, intent)) {
- // We have seen some flakiness where implicit intents find multiple receivers
- // and the ResolveActivity pops up. A test cannot handle this, so crash. Most
- // likely the cause is other test's APKs being left hanging around by flaky
- // test infrastructure.
- val intentWithFlag = Intent(intent)
- intentWithFlag.flags =
- intentWithFlag.flags or Intent.FLAG_ACTIVITY_REQUIRE_DEFAULT
- intentWithFlag
- } else if (inQuietMode) {
- explicitIntent
- } else {
- throw IllegalStateException("Intent doesn't resolve")
- }
+ /** Returns an [Intent] that redirects to the [TestActivity] page. */
+ fun createTestActivityIntent(context: Context, explicit: Boolean = true): Intent =
+ if (explicit) {
+ Intent(ACTION_TEST_ACTIVITY).setPackage(context.packageName)
+ } else {
+ val intent = Intent(ACTION_TEST_ACTIVITY_EXPORTED)
+ // We have seen some flakiness where implicit intents find multiple receivers
+ // and the ResolveActivity pops up. A test cannot handle this, so crash. Most
+ // likely the cause is other test's APKs being left hanging around by flaky
+ // test infrastructure.
+ intent.flags = intent.flags or Intent.FLAG_ACTIVITY_REQUIRE_DEFAULT
+ intent
+ }
+
+ /** Returns a [PendingIntent] that redirects to the given [Intent]. */
+ fun createRedirectPendingIntent(context: Context, intent: Intent): PendingIntent {
return PendingIntent.getActivity(
context,
0 /* requestCode */,
- redirectIntent,
+ intent,
PendingIntent.FLAG_IMMUTABLE
)
}
-
- private fun intentResolves(context: Context, intent: Intent): Boolean =
- context.packageManager
- .queryIntentActivities(intent, ResolveInfoFlags.of(0))
- .isNotEmpty()
}
}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/TestNotificationListener.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/TestNotificationListener.kt
index db714fa97..2b2342d7a 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/TestNotificationListener.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/TestNotificationListener.kt
@@ -166,6 +166,32 @@ class TestNotificationListener : NotificationListenerService() {
}
/**
+ * Waits for a success notification with the given [successMessage] after resolving an
+ * issue.
+ *
+ * Additional assertions can be made on the [StatusBarNotification] using [onNotification].
+ */
+ fun waitForSuccessNotification(
+ successMessage: String,
+ onNotification: (StatusBarNotification) -> Unit = {}
+ ) {
+ val successNotificationWithChannel =
+ waitForSingleNotificationMatching(
+ NotificationCharacteristics(
+ successMessage,
+ "",
+ actions = emptyList(),
+ )
+ )
+ val statusBarNotification = successNotificationWithChannel.statusBarNotification
+ onNotification(statusBarNotification)
+ // Cancel the notification directly to speed up the tests as it's only auto-cancelled
+ // after 10 seconds, and the teardown waits for all notifications to be cancelled to
+ // avoid having unrelated notifications leaking between test cases.
+ cancelAndWait(statusBarNotification.key, waitForIssueCache = false)
+ }
+
+ /**
* Blocks for [TIMEOUT_SHORT], or throw an [AssertionError] if any notification is posted or
* removed before then.
*/
@@ -277,18 +303,20 @@ class TestNotificationListener : NotificationListenerService() {
/**
* Cancels a specific notification and then waits for it to be removed by the notification
* manager and marked as dismissed in Safety Center, or throws if it has not been removed
- * within [timeout].
+ * within [TIMEOUT_LONG].
*/
- fun cancelAndWait(key: String, timeout: Duration = TIMEOUT_LONG) {
+ fun cancelAndWait(key: String, waitForIssueCache: Boolean = true) {
getInstanceOrThrow().cancelNotification(key)
waitForNotificationsToSatisfy(
- timeout = timeout,
+ timeout = TIMEOUT_LONG,
description = "no notification with the key $key"
) { notifications ->
notifications.none { it.statusBarNotification.key == key }
}
- waitForIssueCacheToContainAnyDismissedNotification()
+ if (waitForIssueCache) {
+ waitForIssueCacheToContainAnyDismissedNotification()
+ }
}
private fun waitForIssueCacheToContainAnyDismissedNotification() {