Loading src/com/android/permissioncontroller/permission/data/ServiceLiveData.kt 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.permissioncontroller.permission.data import android.app.Application import android.content.Intent import android.content.pm.PackageManager import android.os.UserHandle import com.android.permissioncontroller.DumpableLog import com.android.permissioncontroller.PermissionControllerApplication import com.android.permissioncontroller.permission.utils.Utils.getUserContext import kotlinx.coroutines.Job /** * A LiveData which tracks services for a certain type * * @param app The current application * @param serviceInterface The name of interface the service implements * @param permission The permission required for the service * @param user The user the services should be determined for */ class ServiceLiveData( private val app: Application, val serviceInterface: String, private val permission: String, private val user: UserHandle ) : SmartAsyncMediatorLiveData<Set<String>>(), PackageBroadcastReceiver.PackageBroadcastListener { private val DEBUG = false override fun onPackageUpdate(packageName: String) { updateAsync() } override suspend fun loadDataAndPostValue(job: Job) { if (job.isCancelled) { return } val packageNames = getUserContext(app, user).packageManager .queryIntentServices( Intent(serviceInterface), PackageManager.GET_SERVICES or PackageManager.GET_META_DATA) .mapNotNull { resolveInfo -> if (resolveInfo?.serviceInfo?.permission != permission) { return@mapNotNull null } resolveInfo?.serviceInfo?.packageName }.toSet() if (DEBUG) { DumpableLog.i(LOG_TAG, "Detected ${serviceInterface.substringAfterLast(".")}s: $packageNames") } postValue(packageNames) } override fun onActive() { super.onActive() PackageBroadcastReceiver.addAllCallback(this) updateAsync() } override fun onInactive() { super.onInactive() PackageBroadcastReceiver.addAllCallback(this) } /** * Repository for 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>() { override fun newValue(key: Triple<String, String, UserHandle>): ServiceLiveData { return ServiceLiveData(PermissionControllerApplication.get(), key.first, key.second, key.third) } } } No newline at end of file src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt +134 −83 Original line number Diff line number Diff line Loading @@ -47,8 +47,6 @@ import android.content.Intent import android.content.SharedPreferences import android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET import android.content.pm.PackageManager.GET_META_DATA import android.content.pm.PackageManager.GET_SERVICES import android.content.pm.PackageManager.PERMISSION_GRANTED import android.net.NetworkScoreManager import android.os.Bundle Loading Loading @@ -84,11 +82,14 @@ import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_ import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.data.AllPackageInfosLiveData import com.android.permissioncontroller.permission.data.AppOpLiveData import com.android.permissioncontroller.permission.data.DataRepositoryForPackage import com.android.permissioncontroller.permission.data.LightAppPermGroupLiveData import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData import com.android.permissioncontroller.permission.data.ServiceLiveData import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData import com.android.permissioncontroller.permission.data.UnusedAutoRevokedPackagesLiveData import com.android.permissioncontroller.permission.data.UsageStatsLiveData import com.android.permissioncontroller.permission.data.UsersLiveData import com.android.permissioncontroller.permission.data.get import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo Loading Loading @@ -285,61 +286,9 @@ private suspend fun revokePermissionsOnUnusedApps( } // Exempt important system-bound services val keyboardPackages = packagesWithService(context, InputMethod.SERVICE_INTERFACE, Manifest.permission.BIND_INPUT_METHOD) val notificationListenerPackages = packagesWithService(context, NotificationListenerService.SERVICE_INTERFACE, Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE) val accessibilityPackages = packagesWithService(context, AccessibilityService.SERVICE_INTERFACE, Manifest.permission.BIND_ACCESSIBILITY_SERVICE) val liveWallpaperPackages = packagesWithService(context, WallpaperService.SERVICE_INTERFACE, Manifest.permission.BIND_WALLPAPER) val voiceInteractionServicePackages = packagesWithService(context, VoiceInteractionService.SERVICE_INTERFACE, Manifest.permission.BIND_VOICE_INTERACTION) val attentionServicePackages = packagesWithService(context, AttentionService.SERVICE_INTERFACE, Manifest.permission.BIND_ATTENTION_SERVICE) val textClassifierPackages = packagesWithService(context, TextClassifierService.SERVICE_INTERFACE, Manifest.permission.BIND_TEXTCLASSIFIER_SERVICE) val printServicePackages = packagesWithService(context, PrintService.SERVICE_INTERFACE, Manifest.permission.BIND_PRINT_SERVICE) val dreamServicePackages = packagesWithService(context, DreamService.SERVICE_INTERFACE, Manifest.permission.BIND_DREAM_SERVICE) val networkScorerPackages = packagesWithService(context, NetworkScoreManager.ACTION_RECOMMEND_NETWORKS, Manifest.permission.BIND_NETWORK_RECOMMENDATION_SERVICE) val autofillPackages = packagesWithService(context, AutofillService.SERVICE_INTERFACE, Manifest.permission.BIND_AUTOFILL_SERVICE) val augmentedAutofillPackages = packagesWithService(context, AugmentedAutofillService.SERVICE_INTERFACE, Manifest.permission.BIND_AUGMENTED_AUTOFILL_SERVICE) val deviceAdminPackages = packagesWithService(context, DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE, Manifest.permission.BIND_DEVICE_ADMIN) val exemptServicePackages = mutableSetOf<String>().apply { addAll(keyboardPackages) addAll(notificationListenerPackages) addAll(accessibilityPackages) addAll(liveWallpaperPackages) addAll(voiceInteractionServicePackages) addAll(attentionServicePackages) addAll(textClassifierPackages) addAll(printServicePackages) addAll(dreamServicePackages) addAll(networkScorerPackages) addAll(autofillPackages) addAll(augmentedAutofillPackages) addAll(deviceAdminPackages) } // TODO: Support more than the current user val exemptServicePackages = ExemptServicesLiveData[myUserHandle()] .getInitializedValue(staleOk = true).keys val revokedApps = mutableListOf<Pair<String, UserHandle>>() for ((user, userApps) in unusedApps) { Loading Loading @@ -441,28 +390,6 @@ private suspend fun revokePermissionsOnUnusedApps( return revokedApps } private fun packagesWithService( context: Context, serviceInterface: String, permission: String ): List<String> { val packageNames = context.packageManager .queryIntentServices( Intent(serviceInterface), GET_SERVICES or GET_META_DATA) .mapNotNull { resolveInfo -> if (resolveInfo?.serviceInfo?.permission != permission) { return@mapNotNull null } resolveInfo?.serviceInfo?.packageName } if (DEBUG) { DumpableLog.i(LOG_TAG, "Detected ${serviceInterface.substringAfterLast(".")}s: $packageNames") } return packageNames } private fun List<UsageStats>.lastTimeVisible(pkgName: String) = find { it.packageName == pkgName }?.lastTimeVisible ?: 0L Loading Loading @@ -636,6 +563,97 @@ class AutoRevokeService : JobService() { } } /** * Packages using exempt services for the current user (package-name -> list<service-interfaces> * implemented by the package) */ private class ExemptServicesLiveData(val user: UserHandle) : SmartUpdateMediatorLiveData<Map<String, List<String>>>() { private val serviceLiveDatas = listOf( ServiceLiveData[InputMethod.SERVICE_INTERFACE, Manifest.permission.BIND_INPUT_METHOD, user], ServiceLiveData[ NotificationListenerService.SERVICE_INTERFACE, Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE, user], ServiceLiveData[ AccessibilityService.SERVICE_INTERFACE, Manifest.permission.BIND_ACCESSIBILITY_SERVICE, user], ServiceLiveData[ WallpaperService.SERVICE_INTERFACE, Manifest.permission.BIND_WALLPAPER, user], ServiceLiveData[ VoiceInteractionService.SERVICE_INTERFACE, Manifest.permission.BIND_VOICE_INTERACTION, user], ServiceLiveData[ AttentionService.SERVICE_INTERFACE, Manifest.permission.BIND_ATTENTION_SERVICE, user], ServiceLiveData[ TextClassifierService.SERVICE_INTERFACE, Manifest.permission.BIND_TEXTCLASSIFIER_SERVICE, user], ServiceLiveData[ PrintService.SERVICE_INTERFACE, Manifest.permission.BIND_PRINT_SERVICE, user], ServiceLiveData[ DreamService.SERVICE_INTERFACE, Manifest.permission.BIND_DREAM_SERVICE, user], ServiceLiveData[ NetworkScoreManager.ACTION_RECOMMEND_NETWORKS, Manifest.permission.BIND_NETWORK_RECOMMENDATION_SERVICE, user], ServiceLiveData[ AutofillService.SERVICE_INTERFACE, Manifest.permission.BIND_AUTOFILL_SERVICE, user], ServiceLiveData[ AugmentedAutofillService.SERVICE_INTERFACE, Manifest.permission.BIND_AUGMENTED_AUTOFILL_SERVICE, user], ServiceLiveData[ DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE, Manifest.permission.BIND_DEVICE_ADMIN, user] ) init { serviceLiveDatas.forEach { addSource(it) { updateIfActive() } } } override fun onUpdate() { if (serviceLiveDatas.all { it.isInitialized }) { val pksToServices = mutableMapOf<String, MutableList<String>>() serviceLiveDatas.forEach { serviceLD -> serviceLD.value!!.forEach { packageName -> pksToServices.getOrPut(packageName, { mutableListOf() }) .add(serviceLD.serviceInterface) } } value = pksToServices } } /** * Repository for ExemptServiceLiveData * * <p> Key value is user */ companion object : DataRepositoryForPackage<UserHandle, ExemptServicesLiveData>() { override fun newValue(key: UserHandle): ExemptServicesLiveData { return ExemptServicesLiveData(key) } } } private data class TeamfoodSettings( val enabledForPreRApps: Boolean, val unusedThresholdMs: Long, Loading Loading @@ -724,6 +742,7 @@ private class AutoRevokeDumpLiveData(context: Context) : val packageName: String, val firstInstallTime: Long, val lastTimeVisible: Long?, val implementedServices: List<String>, val groups: List<AutoRevokeDumpGroupData> ) { fun dump(): PackageProto { Loading @@ -734,6 +753,8 @@ private class AutoRevokeDumpLiveData(context: Context) : lastTimeVisible?.let { dump.lastTimeVisible = lastTimeVisible } implementedServices.forEach { dump.addImplementedServices(it) } groups.forEach { dump.addGroups(it.dump()) } return dump.build() Loading Loading @@ -763,6 +784,12 @@ private class AutoRevokeDumpLiveData(context: Context) : } } /** All users */ private val users = UsersLiveData /** Exempt services for each user: user -> services */ private var services: MutableMap<UserHandle, ExemptServicesLiveData>? = null /** Usage stats: user -> list<usages> */ private val usages = UsageStatsLiveData[ getUnusedThresholdMs(context), Loading Loading @@ -798,6 +825,13 @@ private class AutoRevokeDumpLiveData(context: Context) : updateIfActive() } addSource(users) { services?.values?.forEach { removeSource(it) } services = null updateIfActive() } addSource(usages) { updateIfActive() } Loading @@ -818,7 +852,21 @@ private class AutoRevokeDumpLiveData(context: Context) : } isUpdating = true // Step 1, packages is loaded, nothing else // services step 1, users is loaded, nothing else if (users.isInitialized && services == null) { services = mutableMapOf() for (user in users.value!!) { val newServices = ExemptServicesLiveData[user] services!![user] = newServices addSource(newServices) { updateIfActive() } } } // pkgPermGroupNames step 1, packages is loaded, nothing else if (packages.isInitialized && pkgPermGroupNames == null) { pkgPermGroupNames = mutableMapOf() Loading @@ -837,7 +885,8 @@ private class AutoRevokeDumpLiveData(context: Context) : } } // Step 2, packages and pkgPermGroupNames are loaded, but pkgPermGroups are not loaded yet // pkgPermGroupNames step 2, packages and pkgPermGroupNames are loaded, but pkgPermGroups // are not loaded yet if (packages.isInitialized && pkgPermGroupNames != null) { for ((user, userPkgs) in packages.value!!) { for (pkg in userPkgs) { Loading @@ -863,11 +912,12 @@ private class AutoRevokeDumpLiveData(context: Context) : } } // Step 3, everything is loaded, generate data // Final step, everything is loaded, generate data if (packages.isInitialized && usages.isInitialized && revokedPermGroupNames.isInitialized && pkgPermGroupNames?.values?.all { it.isInitialized } == true && pkgPermGroupNames?.size == pkgPermGroups.size && pkgPermGroups.values.all { it?.values?.all { it.isInitialized } == true }) { pkgPermGroups.values.all { it?.values?.all { it.isInitialized } == true } && services?.values?.all { it.isInitialized } == true) { val users = mutableListOf<AutoRevokeDumpUserData>() for ((user, userPkgs) in packages.value!!) { Loading Loading @@ -898,6 +948,7 @@ private class AutoRevokeDumpLiveData(context: Context) : pkg.firstInstallTime, usages.value!![user] ?.find { it.packageName == pkg.packageName }?.lastTimeVisible, services!![user]?.value!![pkg.packageName] ?: emptyList(), groups)) } Loading src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.proto +1 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ message PackageProto { optional int64 last_time_visible = 4; optional int64 first_install_time = 5; repeated PermissionGroupProto groups = 6; repeated string implemented_services = 7; } message PermissionGroupProto { Loading Loading
src/com/android/permissioncontroller/permission/data/ServiceLiveData.kt 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.permissioncontroller.permission.data import android.app.Application import android.content.Intent import android.content.pm.PackageManager import android.os.UserHandle import com.android.permissioncontroller.DumpableLog import com.android.permissioncontroller.PermissionControllerApplication import com.android.permissioncontroller.permission.utils.Utils.getUserContext import kotlinx.coroutines.Job /** * A LiveData which tracks services for a certain type * * @param app The current application * @param serviceInterface The name of interface the service implements * @param permission The permission required for the service * @param user The user the services should be determined for */ class ServiceLiveData( private val app: Application, val serviceInterface: String, private val permission: String, private val user: UserHandle ) : SmartAsyncMediatorLiveData<Set<String>>(), PackageBroadcastReceiver.PackageBroadcastListener { private val DEBUG = false override fun onPackageUpdate(packageName: String) { updateAsync() } override suspend fun loadDataAndPostValue(job: Job) { if (job.isCancelled) { return } val packageNames = getUserContext(app, user).packageManager .queryIntentServices( Intent(serviceInterface), PackageManager.GET_SERVICES or PackageManager.GET_META_DATA) .mapNotNull { resolveInfo -> if (resolveInfo?.serviceInfo?.permission != permission) { return@mapNotNull null } resolveInfo?.serviceInfo?.packageName }.toSet() if (DEBUG) { DumpableLog.i(LOG_TAG, "Detected ${serviceInterface.substringAfterLast(".")}s: $packageNames") } postValue(packageNames) } override fun onActive() { super.onActive() PackageBroadcastReceiver.addAllCallback(this) updateAsync() } override fun onInactive() { super.onInactive() PackageBroadcastReceiver.addAllCallback(this) } /** * Repository for 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>() { override fun newValue(key: Triple<String, String, UserHandle>): ServiceLiveData { return ServiceLiveData(PermissionControllerApplication.get(), key.first, key.second, key.third) } } } No newline at end of file
src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt +134 −83 Original line number Diff line number Diff line Loading @@ -47,8 +47,6 @@ import android.content.Intent import android.content.SharedPreferences import android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET import android.content.pm.PackageManager.GET_META_DATA import android.content.pm.PackageManager.GET_SERVICES import android.content.pm.PackageManager.PERMISSION_GRANTED import android.net.NetworkScoreManager import android.os.Bundle Loading Loading @@ -84,11 +82,14 @@ import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_ import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.data.AllPackageInfosLiveData import com.android.permissioncontroller.permission.data.AppOpLiveData import com.android.permissioncontroller.permission.data.DataRepositoryForPackage import com.android.permissioncontroller.permission.data.LightAppPermGroupLiveData import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData import com.android.permissioncontroller.permission.data.ServiceLiveData import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData import com.android.permissioncontroller.permission.data.UnusedAutoRevokedPackagesLiveData import com.android.permissioncontroller.permission.data.UsageStatsLiveData import com.android.permissioncontroller.permission.data.UsersLiveData import com.android.permissioncontroller.permission.data.get import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo Loading Loading @@ -285,61 +286,9 @@ private suspend fun revokePermissionsOnUnusedApps( } // Exempt important system-bound services val keyboardPackages = packagesWithService(context, InputMethod.SERVICE_INTERFACE, Manifest.permission.BIND_INPUT_METHOD) val notificationListenerPackages = packagesWithService(context, NotificationListenerService.SERVICE_INTERFACE, Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE) val accessibilityPackages = packagesWithService(context, AccessibilityService.SERVICE_INTERFACE, Manifest.permission.BIND_ACCESSIBILITY_SERVICE) val liveWallpaperPackages = packagesWithService(context, WallpaperService.SERVICE_INTERFACE, Manifest.permission.BIND_WALLPAPER) val voiceInteractionServicePackages = packagesWithService(context, VoiceInteractionService.SERVICE_INTERFACE, Manifest.permission.BIND_VOICE_INTERACTION) val attentionServicePackages = packagesWithService(context, AttentionService.SERVICE_INTERFACE, Manifest.permission.BIND_ATTENTION_SERVICE) val textClassifierPackages = packagesWithService(context, TextClassifierService.SERVICE_INTERFACE, Manifest.permission.BIND_TEXTCLASSIFIER_SERVICE) val printServicePackages = packagesWithService(context, PrintService.SERVICE_INTERFACE, Manifest.permission.BIND_PRINT_SERVICE) val dreamServicePackages = packagesWithService(context, DreamService.SERVICE_INTERFACE, Manifest.permission.BIND_DREAM_SERVICE) val networkScorerPackages = packagesWithService(context, NetworkScoreManager.ACTION_RECOMMEND_NETWORKS, Manifest.permission.BIND_NETWORK_RECOMMENDATION_SERVICE) val autofillPackages = packagesWithService(context, AutofillService.SERVICE_INTERFACE, Manifest.permission.BIND_AUTOFILL_SERVICE) val augmentedAutofillPackages = packagesWithService(context, AugmentedAutofillService.SERVICE_INTERFACE, Manifest.permission.BIND_AUGMENTED_AUTOFILL_SERVICE) val deviceAdminPackages = packagesWithService(context, DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE, Manifest.permission.BIND_DEVICE_ADMIN) val exemptServicePackages = mutableSetOf<String>().apply { addAll(keyboardPackages) addAll(notificationListenerPackages) addAll(accessibilityPackages) addAll(liveWallpaperPackages) addAll(voiceInteractionServicePackages) addAll(attentionServicePackages) addAll(textClassifierPackages) addAll(printServicePackages) addAll(dreamServicePackages) addAll(networkScorerPackages) addAll(autofillPackages) addAll(augmentedAutofillPackages) addAll(deviceAdminPackages) } // TODO: Support more than the current user val exemptServicePackages = ExemptServicesLiveData[myUserHandle()] .getInitializedValue(staleOk = true).keys val revokedApps = mutableListOf<Pair<String, UserHandle>>() for ((user, userApps) in unusedApps) { Loading Loading @@ -441,28 +390,6 @@ private suspend fun revokePermissionsOnUnusedApps( return revokedApps } private fun packagesWithService( context: Context, serviceInterface: String, permission: String ): List<String> { val packageNames = context.packageManager .queryIntentServices( Intent(serviceInterface), GET_SERVICES or GET_META_DATA) .mapNotNull { resolveInfo -> if (resolveInfo?.serviceInfo?.permission != permission) { return@mapNotNull null } resolveInfo?.serviceInfo?.packageName } if (DEBUG) { DumpableLog.i(LOG_TAG, "Detected ${serviceInterface.substringAfterLast(".")}s: $packageNames") } return packageNames } private fun List<UsageStats>.lastTimeVisible(pkgName: String) = find { it.packageName == pkgName }?.lastTimeVisible ?: 0L Loading Loading @@ -636,6 +563,97 @@ class AutoRevokeService : JobService() { } } /** * Packages using exempt services for the current user (package-name -> list<service-interfaces> * implemented by the package) */ private class ExemptServicesLiveData(val user: UserHandle) : SmartUpdateMediatorLiveData<Map<String, List<String>>>() { private val serviceLiveDatas = listOf( ServiceLiveData[InputMethod.SERVICE_INTERFACE, Manifest.permission.BIND_INPUT_METHOD, user], ServiceLiveData[ NotificationListenerService.SERVICE_INTERFACE, Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE, user], ServiceLiveData[ AccessibilityService.SERVICE_INTERFACE, Manifest.permission.BIND_ACCESSIBILITY_SERVICE, user], ServiceLiveData[ WallpaperService.SERVICE_INTERFACE, Manifest.permission.BIND_WALLPAPER, user], ServiceLiveData[ VoiceInteractionService.SERVICE_INTERFACE, Manifest.permission.BIND_VOICE_INTERACTION, user], ServiceLiveData[ AttentionService.SERVICE_INTERFACE, Manifest.permission.BIND_ATTENTION_SERVICE, user], ServiceLiveData[ TextClassifierService.SERVICE_INTERFACE, Manifest.permission.BIND_TEXTCLASSIFIER_SERVICE, user], ServiceLiveData[ PrintService.SERVICE_INTERFACE, Manifest.permission.BIND_PRINT_SERVICE, user], ServiceLiveData[ DreamService.SERVICE_INTERFACE, Manifest.permission.BIND_DREAM_SERVICE, user], ServiceLiveData[ NetworkScoreManager.ACTION_RECOMMEND_NETWORKS, Manifest.permission.BIND_NETWORK_RECOMMENDATION_SERVICE, user], ServiceLiveData[ AutofillService.SERVICE_INTERFACE, Manifest.permission.BIND_AUTOFILL_SERVICE, user], ServiceLiveData[ AugmentedAutofillService.SERVICE_INTERFACE, Manifest.permission.BIND_AUGMENTED_AUTOFILL_SERVICE, user], ServiceLiveData[ DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE, Manifest.permission.BIND_DEVICE_ADMIN, user] ) init { serviceLiveDatas.forEach { addSource(it) { updateIfActive() } } } override fun onUpdate() { if (serviceLiveDatas.all { it.isInitialized }) { val pksToServices = mutableMapOf<String, MutableList<String>>() serviceLiveDatas.forEach { serviceLD -> serviceLD.value!!.forEach { packageName -> pksToServices.getOrPut(packageName, { mutableListOf() }) .add(serviceLD.serviceInterface) } } value = pksToServices } } /** * Repository for ExemptServiceLiveData * * <p> Key value is user */ companion object : DataRepositoryForPackage<UserHandle, ExemptServicesLiveData>() { override fun newValue(key: UserHandle): ExemptServicesLiveData { return ExemptServicesLiveData(key) } } } private data class TeamfoodSettings( val enabledForPreRApps: Boolean, val unusedThresholdMs: Long, Loading Loading @@ -724,6 +742,7 @@ private class AutoRevokeDumpLiveData(context: Context) : val packageName: String, val firstInstallTime: Long, val lastTimeVisible: Long?, val implementedServices: List<String>, val groups: List<AutoRevokeDumpGroupData> ) { fun dump(): PackageProto { Loading @@ -734,6 +753,8 @@ private class AutoRevokeDumpLiveData(context: Context) : lastTimeVisible?.let { dump.lastTimeVisible = lastTimeVisible } implementedServices.forEach { dump.addImplementedServices(it) } groups.forEach { dump.addGroups(it.dump()) } return dump.build() Loading Loading @@ -763,6 +784,12 @@ private class AutoRevokeDumpLiveData(context: Context) : } } /** All users */ private val users = UsersLiveData /** Exempt services for each user: user -> services */ private var services: MutableMap<UserHandle, ExemptServicesLiveData>? = null /** Usage stats: user -> list<usages> */ private val usages = UsageStatsLiveData[ getUnusedThresholdMs(context), Loading Loading @@ -798,6 +825,13 @@ private class AutoRevokeDumpLiveData(context: Context) : updateIfActive() } addSource(users) { services?.values?.forEach { removeSource(it) } services = null updateIfActive() } addSource(usages) { updateIfActive() } Loading @@ -818,7 +852,21 @@ private class AutoRevokeDumpLiveData(context: Context) : } isUpdating = true // Step 1, packages is loaded, nothing else // services step 1, users is loaded, nothing else if (users.isInitialized && services == null) { services = mutableMapOf() for (user in users.value!!) { val newServices = ExemptServicesLiveData[user] services!![user] = newServices addSource(newServices) { updateIfActive() } } } // pkgPermGroupNames step 1, packages is loaded, nothing else if (packages.isInitialized && pkgPermGroupNames == null) { pkgPermGroupNames = mutableMapOf() Loading @@ -837,7 +885,8 @@ private class AutoRevokeDumpLiveData(context: Context) : } } // Step 2, packages and pkgPermGroupNames are loaded, but pkgPermGroups are not loaded yet // pkgPermGroupNames step 2, packages and pkgPermGroupNames are loaded, but pkgPermGroups // are not loaded yet if (packages.isInitialized && pkgPermGroupNames != null) { for ((user, userPkgs) in packages.value!!) { for (pkg in userPkgs) { Loading @@ -863,11 +912,12 @@ private class AutoRevokeDumpLiveData(context: Context) : } } // Step 3, everything is loaded, generate data // Final step, everything is loaded, generate data if (packages.isInitialized && usages.isInitialized && revokedPermGroupNames.isInitialized && pkgPermGroupNames?.values?.all { it.isInitialized } == true && pkgPermGroupNames?.size == pkgPermGroups.size && pkgPermGroups.values.all { it?.values?.all { it.isInitialized } == true }) { pkgPermGroups.values.all { it?.values?.all { it.isInitialized } == true } && services?.values?.all { it.isInitialized } == true) { val users = mutableListOf<AutoRevokeDumpUserData>() for ((user, userPkgs) in packages.value!!) { Loading Loading @@ -898,6 +948,7 @@ private class AutoRevokeDumpLiveData(context: Context) : pkg.firstInstallTime, usages.value!![user] ?.find { it.packageName == pkg.packageName }?.lastTimeVisible, services!![user]?.value!![pkg.packageName] ?: emptyList(), groups)) } Loading
src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.proto +1 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ message PackageProto { optional int64 last_time_visible = 4; optional int64 first_install_time = 5; repeated PermissionGroupProto groups = 6; repeated string implemented_services = 7; } message PermissionGroupProto { Loading