summaryrefslogtreecommitdiff
path: root/PermissionController/src/com/android
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-02 22:45:31 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-02 22:45:31 +0000
commit0200d6fbca83dca25736cdef8fa67f4c55552ae0 (patch)
treed4c2bbf2e2847a3569ebe3a3119ac5d6586eec16 /PermissionController/src/com/android
parentec92dfe7d68b2aec544825ebe61c45df98cae6b7 (diff)
parent17440e9d4d86da90a850ad04dbc41cb59d30cdec (diff)
downloadPermission-0200d6fbca83dca25736cdef8fa67f4c55552ae0.tar.gz
Snap for 11041982 from 17440e9d4d86da90a850ad04dbc41cb59d30cdec to mainline-uwb-releaseaml_uwb_341310300aml_uwb_341310030android14-mainline-uwb-release
Change-Id: If31740c980b44eae1671d1a80e4f088e8f9ef7e4
Diffstat (limited to 'PermissionController/src/com/android')
-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
184 files changed, 6948 insertions, 5398 deletions
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. */