Loading src/com/android/packageinstaller/permission/data/AppPermissionGroupLiveData.kt +9 −12 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ class AppPermissionGroupLiveData( ) : MediatorLiveData<AppPermissionGroup?>(), DataRepository.InactiveTimekeeper { private val context = app.applicationContext private val context = PackageInfoRepository.getUserContext(app, user) private lateinit var appOpsLiveData: AppOpsLiveData private val packageInfoLiveData = PackageInfoRepository.getPackageInfoLiveData(app, packageName, user) Loading @@ -52,15 +52,10 @@ class AppPermissionGroupLiveData( * as source, and generate value. */ init { if (packageInfoLiveData.value == null || groupLiveData.value == null) { value = null } else { if (packageInfoLiveData.value != null && groupLiveData.value != null) { appOpsLiveData = AppOpsLiveData(app, packageName, permissionGroupName, user) /** * Since the AppPermissionGroup only keeps a reference to the AppOpManager, it is not * immediately affected by app op changes. Regenerate the AppPermissionGroup */ addSource(appOpsLiveData) { addSource(packageInfoLiveData) { generateNewPermissionGroup() } Loading @@ -68,7 +63,11 @@ class AppPermissionGroupLiveData( generateNewPermissionGroup() } addSource(packageInfoLiveData) { /** * Since the AppPermissionGroup only keeps a reference to the AppOpManager, it is not * immediately affected by app op changes. Regenerate the AppPermissionGroup */ addSource(appOpsLiveData) { generateNewPermissionGroup() } Loading @@ -91,8 +90,6 @@ class AppPermissionGroupLiveData( removeSource(packageInfoLiveData) value = null } else { // TODO: AppPermissionGroup.grantRuntimePermission silently updates the values. // Is this desired behavior? value = AppPermissionGroup.create(context, packageInfo, groupInfo, permissionInfos, false) } Loading src/com/android/packageinstaller/permission/data/PackageInfoLiveData.kt +76 −8 Original line number Diff line number Diff line Loading @@ -17,10 +17,10 @@ package com.android.packageinstaller.permission.data import android.app.Application import android.content.Context import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.os.UserHandle import android.util.Log import androidx.lifecycle.LiveData /** Loading @@ -39,8 +39,15 @@ class PackageInfoLiveData( PermissionListenerMultiplexer.PermissionChangeCallback, DataRepository.InactiveTimekeeper { private val context: Context = app.applicationContext private var uid = context.packageManager.getPackageUid(packageName, 0) private val LOG_TAG = PackageInfoLiveData::class.java.simpleName private var context = PackageInfoRepository.getUserContext(app, user) private var uid: Int? = null /** * The currently registered UID on which this LiveData is listening for permission changes */ private var registeredUid: Int? = null override var timeWentInactive: Long? = null Loading @@ -65,12 +72,64 @@ class PackageInfoLiveData( */ private fun generatePackageData() { try { uid = context.packageManager.getPackageUid(packageName, 0) this.value = context.packageManager.getPackageInfo(packageName, val packageInfo = context.packageManager.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS) if (relevantPackageInfoFieldsEqual(packageInfo, super.getValue())) { return } uid = packageInfo.applicationInfo.uid value = packageInfo return } catch (e: PackageManager.NameNotFoundException) { this.value = null Log.w(LOG_TAG, "Package \"$packageName\" not found") if (super.getValue() != null) { value = null } } return } private fun relevantPackageInfoFieldsEqual( newPkg: PackageInfo?, oldPkg: PackageInfo? ): Boolean { if (oldPkg == null && newPkg == null) { return true } if (oldPkg == null || newPkg == null) { return false } if (oldPkg.packageName != newPkg.packageName || oldPkg.applicationInfo.uid != newPkg.applicationInfo.uid) { return false } val oldPerms = oldPkg.requestedPermissions val newPerms = newPkg.requestedPermissions if (oldPerms != null) { if (!oldPerms.contentEquals(newPerms)) { return false } } else { if (newPerms != null) { return false } } val oldFlags = oldPkg.requestedPermissionsFlags val newFlags = newPkg.requestedPermissionsFlags if (oldFlags != null) { if (!oldFlags.contentEquals(newFlags)) { return false } } else { if (newFlags == null) { return false } } return true } override fun onPermissionChange() { Loading @@ -82,7 +141,12 @@ class PackageInfoLiveData( PackageInfoRepository.getPackageBroadcastReceiver(app) .addChangeCallback(packageName, this) PackageInfoRepository.permissionListenerMultiplexer?.addCallback(uid, this) generatePackageData() value?.applicationInfo?.uid?.let { newUid -> uid = newUid registeredUid = newUid PackageInfoRepository.permissionListenerMultiplexer?.addCallback(newUid, this) } } override fun onInactive() { Loading @@ -91,6 +155,10 @@ class PackageInfoLiveData( timeWentInactive = System.nanoTime() PackageInfoRepository.getPackageBroadcastReceiver(app) .removeChangeCallback(packageName, this) PackageInfoRepository.permissionListenerMultiplexer?.removeCallback(uid, this) registeredUid?.let { regUid -> PackageInfoRepository.permissionListenerMultiplexer ?.removeCallback(regUid, this) registeredUid = null } } } No newline at end of file src/com/android/packageinstaller/permission/data/PackageInfoRepository.kt +11 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.packageinstaller.permission.data import android.app.Application import android.content.Context import android.os.UserHandle /** Loading @@ -26,6 +27,7 @@ import android.os.UserHandle object PackageInfoRepository : DataRepository<Pair<String, UserHandle>, PackageInfoLiveData>() { private var broadcastReceiver: PackageBroadcastReceiver? = null private val userContexts = mutableMapOf<UserHandle, Context>() /** * Gets the PackageBroadcastReceiver, instantiating it if need be. Loading @@ -34,6 +36,7 @@ object PackageInfoRepository : DataRepository<Pair<String, UserHandle>, PackageI * * @return The cached or newly created PackageBroadcastReceiver */ @JvmStatic fun getPackageBroadcastReceiver(app: Application): PackageBroadcastReceiver { if (broadcastReceiver == null) { broadcastReceiver = PackageBroadcastReceiver(app) Loading @@ -57,6 +60,7 @@ object PackageInfoRepository : DataRepository<Pair<String, UserHandle>, PackageI * * @return The cached or newly created PackageInfoLiveData */ @JvmStatic fun getPackageInfoLiveData(app: Application, packageName: String, user: UserHandle): PackageInfoLiveData { if (permissionListenerMultiplexer == null) { Loading @@ -66,6 +70,13 @@ object PackageInfoRepository : DataRepository<Pair<String, UserHandle>, PackageI return getDataObject(app, packageName to user) } @JvmStatic fun getUserContext(app: Application, user: UserHandle): Context { return userContexts.getOrPut(user) { app.applicationContext.createPackageContextAsUser(app.packageName, 0, user) } } override fun newValue(app: Application, key: Pair<String, UserHandle>): PackageInfoLiveData { return PackageInfoLiveData(app, key.first, key.second) } Loading src/com/android/packageinstaller/permission/data/PermissionGroupLiveData.kt +12 −9 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import androidx.lifecycle.MediatorLiveData import com.android.packageinstaller.permission.data.PackageInfoRepository.getPackageInfoLiveData import com.android.packageinstaller.permission.data.PackageInfoRepository.getPackageBroadcastReceiver import com.android.packageinstaller.permission.utils.Utils import com.android.packageinstaller.permission.utils.Utils.OS_PKG /** * LiveData for a Permission Group. Contains GroupInfo and a list of PermissionInfos Loading Loading @@ -100,8 +101,13 @@ class PermissionGroupLiveData( } removePackagePermissions(packageInfo.packageName) val permissions = if (packageInfo.packageName == OS_PKG) { Utils.getPermissionInfosForGroup(context.packageManager, groupName) } else { packageInfo.permissions.toList() } var hasPackagePermissions = false for (newPermission in packageInfo.permissions) { for (newPermission in permissions) { if (Utils.getGroupOfPermission(newPermission) == groupInfo.name) { permissionInfos[newPermission.name] = newPermission hasPackagePermissions = true Loading Loading @@ -199,11 +205,11 @@ class PermissionGroupLiveData( return } var permInfos = mutableListOf<PermissionInfo>() when (groupInfo) { is PermissionGroupInfo -> { try { val permInfos = Utils.getPermissionInfosForGroup(context.packageManager, groupName) permInfos = Utils.getPermissionInfosForGroup(context.packageManager, groupName) for (permInfo in permInfos) { permissionInfos[permInfo.name] = permInfo } Loading @@ -223,12 +229,9 @@ class PermissionGroupLiveData( addPackageLiveData(groupInfo.packageName, getPackageInfoLiveData(app, groupInfo.packageName, user)) for ((_, permissionInfo) in permissionInfos) { val pkgName = permissionInfo.packageName if (!liveDatas.contains(pkgName)) { addPackageLiveData(pkgName, getPackageInfoLiveData(app, pkgName, user)) } for (permInfo in permInfos) { addPackageLiveData(permInfo.packageName, getPackageInfoLiveData(app, permInfo.packageName, user)) } } Loading Loading
src/com/android/packageinstaller/permission/data/AppPermissionGroupLiveData.kt +9 −12 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ class AppPermissionGroupLiveData( ) : MediatorLiveData<AppPermissionGroup?>(), DataRepository.InactiveTimekeeper { private val context = app.applicationContext private val context = PackageInfoRepository.getUserContext(app, user) private lateinit var appOpsLiveData: AppOpsLiveData private val packageInfoLiveData = PackageInfoRepository.getPackageInfoLiveData(app, packageName, user) Loading @@ -52,15 +52,10 @@ class AppPermissionGroupLiveData( * as source, and generate value. */ init { if (packageInfoLiveData.value == null || groupLiveData.value == null) { value = null } else { if (packageInfoLiveData.value != null && groupLiveData.value != null) { appOpsLiveData = AppOpsLiveData(app, packageName, permissionGroupName, user) /** * Since the AppPermissionGroup only keeps a reference to the AppOpManager, it is not * immediately affected by app op changes. Regenerate the AppPermissionGroup */ addSource(appOpsLiveData) { addSource(packageInfoLiveData) { generateNewPermissionGroup() } Loading @@ -68,7 +63,11 @@ class AppPermissionGroupLiveData( generateNewPermissionGroup() } addSource(packageInfoLiveData) { /** * Since the AppPermissionGroup only keeps a reference to the AppOpManager, it is not * immediately affected by app op changes. Regenerate the AppPermissionGroup */ addSource(appOpsLiveData) { generateNewPermissionGroup() } Loading @@ -91,8 +90,6 @@ class AppPermissionGroupLiveData( removeSource(packageInfoLiveData) value = null } else { // TODO: AppPermissionGroup.grantRuntimePermission silently updates the values. // Is this desired behavior? value = AppPermissionGroup.create(context, packageInfo, groupInfo, permissionInfos, false) } Loading
src/com/android/packageinstaller/permission/data/PackageInfoLiveData.kt +76 −8 Original line number Diff line number Diff line Loading @@ -17,10 +17,10 @@ package com.android.packageinstaller.permission.data import android.app.Application import android.content.Context import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.os.UserHandle import android.util.Log import androidx.lifecycle.LiveData /** Loading @@ -39,8 +39,15 @@ class PackageInfoLiveData( PermissionListenerMultiplexer.PermissionChangeCallback, DataRepository.InactiveTimekeeper { private val context: Context = app.applicationContext private var uid = context.packageManager.getPackageUid(packageName, 0) private val LOG_TAG = PackageInfoLiveData::class.java.simpleName private var context = PackageInfoRepository.getUserContext(app, user) private var uid: Int? = null /** * The currently registered UID on which this LiveData is listening for permission changes */ private var registeredUid: Int? = null override var timeWentInactive: Long? = null Loading @@ -65,12 +72,64 @@ class PackageInfoLiveData( */ private fun generatePackageData() { try { uid = context.packageManager.getPackageUid(packageName, 0) this.value = context.packageManager.getPackageInfo(packageName, val packageInfo = context.packageManager.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS) if (relevantPackageInfoFieldsEqual(packageInfo, super.getValue())) { return } uid = packageInfo.applicationInfo.uid value = packageInfo return } catch (e: PackageManager.NameNotFoundException) { this.value = null Log.w(LOG_TAG, "Package \"$packageName\" not found") if (super.getValue() != null) { value = null } } return } private fun relevantPackageInfoFieldsEqual( newPkg: PackageInfo?, oldPkg: PackageInfo? ): Boolean { if (oldPkg == null && newPkg == null) { return true } if (oldPkg == null || newPkg == null) { return false } if (oldPkg.packageName != newPkg.packageName || oldPkg.applicationInfo.uid != newPkg.applicationInfo.uid) { return false } val oldPerms = oldPkg.requestedPermissions val newPerms = newPkg.requestedPermissions if (oldPerms != null) { if (!oldPerms.contentEquals(newPerms)) { return false } } else { if (newPerms != null) { return false } } val oldFlags = oldPkg.requestedPermissionsFlags val newFlags = newPkg.requestedPermissionsFlags if (oldFlags != null) { if (!oldFlags.contentEquals(newFlags)) { return false } } else { if (newFlags == null) { return false } } return true } override fun onPermissionChange() { Loading @@ -82,7 +141,12 @@ class PackageInfoLiveData( PackageInfoRepository.getPackageBroadcastReceiver(app) .addChangeCallback(packageName, this) PackageInfoRepository.permissionListenerMultiplexer?.addCallback(uid, this) generatePackageData() value?.applicationInfo?.uid?.let { newUid -> uid = newUid registeredUid = newUid PackageInfoRepository.permissionListenerMultiplexer?.addCallback(newUid, this) } } override fun onInactive() { Loading @@ -91,6 +155,10 @@ class PackageInfoLiveData( timeWentInactive = System.nanoTime() PackageInfoRepository.getPackageBroadcastReceiver(app) .removeChangeCallback(packageName, this) PackageInfoRepository.permissionListenerMultiplexer?.removeCallback(uid, this) registeredUid?.let { regUid -> PackageInfoRepository.permissionListenerMultiplexer ?.removeCallback(regUid, this) registeredUid = null } } } No newline at end of file
src/com/android/packageinstaller/permission/data/PackageInfoRepository.kt +11 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.packageinstaller.permission.data import android.app.Application import android.content.Context import android.os.UserHandle /** Loading @@ -26,6 +27,7 @@ import android.os.UserHandle object PackageInfoRepository : DataRepository<Pair<String, UserHandle>, PackageInfoLiveData>() { private var broadcastReceiver: PackageBroadcastReceiver? = null private val userContexts = mutableMapOf<UserHandle, Context>() /** * Gets the PackageBroadcastReceiver, instantiating it if need be. Loading @@ -34,6 +36,7 @@ object PackageInfoRepository : DataRepository<Pair<String, UserHandle>, PackageI * * @return The cached or newly created PackageBroadcastReceiver */ @JvmStatic fun getPackageBroadcastReceiver(app: Application): PackageBroadcastReceiver { if (broadcastReceiver == null) { broadcastReceiver = PackageBroadcastReceiver(app) Loading @@ -57,6 +60,7 @@ object PackageInfoRepository : DataRepository<Pair<String, UserHandle>, PackageI * * @return The cached or newly created PackageInfoLiveData */ @JvmStatic fun getPackageInfoLiveData(app: Application, packageName: String, user: UserHandle): PackageInfoLiveData { if (permissionListenerMultiplexer == null) { Loading @@ -66,6 +70,13 @@ object PackageInfoRepository : DataRepository<Pair<String, UserHandle>, PackageI return getDataObject(app, packageName to user) } @JvmStatic fun getUserContext(app: Application, user: UserHandle): Context { return userContexts.getOrPut(user) { app.applicationContext.createPackageContextAsUser(app.packageName, 0, user) } } override fun newValue(app: Application, key: Pair<String, UserHandle>): PackageInfoLiveData { return PackageInfoLiveData(app, key.first, key.second) } Loading
src/com/android/packageinstaller/permission/data/PermissionGroupLiveData.kt +12 −9 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import androidx.lifecycle.MediatorLiveData import com.android.packageinstaller.permission.data.PackageInfoRepository.getPackageInfoLiveData import com.android.packageinstaller.permission.data.PackageInfoRepository.getPackageBroadcastReceiver import com.android.packageinstaller.permission.utils.Utils import com.android.packageinstaller.permission.utils.Utils.OS_PKG /** * LiveData for a Permission Group. Contains GroupInfo and a list of PermissionInfos Loading Loading @@ -100,8 +101,13 @@ class PermissionGroupLiveData( } removePackagePermissions(packageInfo.packageName) val permissions = if (packageInfo.packageName == OS_PKG) { Utils.getPermissionInfosForGroup(context.packageManager, groupName) } else { packageInfo.permissions.toList() } var hasPackagePermissions = false for (newPermission in packageInfo.permissions) { for (newPermission in permissions) { if (Utils.getGroupOfPermission(newPermission) == groupInfo.name) { permissionInfos[newPermission.name] = newPermission hasPackagePermissions = true Loading Loading @@ -199,11 +205,11 @@ class PermissionGroupLiveData( return } var permInfos = mutableListOf<PermissionInfo>() when (groupInfo) { is PermissionGroupInfo -> { try { val permInfos = Utils.getPermissionInfosForGroup(context.packageManager, groupName) permInfos = Utils.getPermissionInfosForGroup(context.packageManager, groupName) for (permInfo in permInfos) { permissionInfos[permInfo.name] = permInfo } Loading @@ -223,12 +229,9 @@ class PermissionGroupLiveData( addPackageLiveData(groupInfo.packageName, getPackageInfoLiveData(app, groupInfo.packageName, user)) for ((_, permissionInfo) in permissionInfos) { val pkgName = permissionInfo.packageName if (!liveDatas.contains(pkgName)) { addPackageLiveData(pkgName, getPackageInfoLiveData(app, pkgName, user)) } for (permInfo in permInfos) { addPackageLiveData(permInfo.packageName, getPackageInfoLiveData(app, permInfo.packageName, user)) } } Loading