1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.permissioncontroller.permission.data 18 19 import android.app.Application 20 import android.content.pm.PackageManager.GET_PERMISSIONS 21 import android.content.pm.PackageManager.MATCH_ALL 22 import android.os.UserHandle 23 import com.android.permissioncontroller.PermissionControllerApplication 24 import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo 25 import kotlinx.coroutines.Job 26 27 /** 28 * A LiveData which tracks all of the packageinfos installed for a given user. 29 * 30 * @param app The current application 31 * @param user The user whose packages are desired 32 */ 33 class UserPackageInfosLiveData private constructor( 34 private val app: Application, 35 private val user: UserHandle 36 ) : SmartAsyncMediatorLiveData<@kotlin.jvm.JvmSuppressWildcards List<LightPackageInfo>>(), 37 PackageBroadcastReceiver.PackageBroadcastListener, 38 PermissionListenerMultiplexer.PermissionChangeCallback { 39 40 /** 41 * Whether or not the permissions in this liveData are out of date 42 */ 43 var permChangeStale = false 44 45 override fun onPackageUpdate(packageName: String) { 46 updateAsync() 47 } 48 49 // TODO ntmyren: replace with correctly updating 50 override fun onPermissionChange() { 51 permChangeStale = true 52 for (packageInfo in value ?: emptyList()) { 53 PermissionListenerMultiplexer.removeCallback(packageInfo.uid, this) 54 } 55 } 56 57 override fun setValue(newValue: List<LightPackageInfo>?) { 58 if (newValue != value) { 59 for (packageInfo in value ?: emptyList()) { 60 PermissionListenerMultiplexer.removeCallback(packageInfo.uid, this) 61 } 62 for (packageInfo in newValue ?: emptyList()) { 63 PermissionListenerMultiplexer.addCallback(packageInfo.uid, this) 64 } 65 } 66 super.setValue(newValue) 67 permChangeStale = false 68 } 69 70 /** 71 * Get all of the packages in the system, organized by user. 72 */ 73 override suspend fun loadDataAndPostValue(job: Job) { 74 if (job.isCancelled) { 75 return 76 } 77 val packageInfos = app.applicationContext.packageManager 78 .getInstalledPackagesAsUser(GET_PERMISSIONS or MATCH_ALL, user.identifier) 79 80 postValue(packageInfos.map { packageInfo -> LightPackageInfo(packageInfo) }) 81 } 82 83 override fun onActive() { 84 super.onActive() 85 86 PackageBroadcastReceiver.addAllCallback(this) 87 88 for (packageInfo in value ?: emptyList()) { 89 PermissionListenerMultiplexer.addCallback(packageInfo.uid, this) 90 } 91 } 92 93 override fun onInactive() { 94 super.onInactive() 95 96 for (packageInfo in value ?: emptyList()) { 97 PermissionListenerMultiplexer.removeCallback(packageInfo.uid, this) 98 } 99 100 PackageBroadcastReceiver.removeAllCallback(this) 101 } 102 103 /** 104 * Repository for UserPackageInfosLiveDatas. 105 * <p> Key value is a UserHandle, value is its corresponding LiveData. 106 */ 107 companion object : DataRepository<UserHandle, UserPackageInfosLiveData>() { 108 override fun newValue(key: UserHandle): UserPackageInfosLiveData { 109 return UserPackageInfosLiveData(PermissionControllerApplication.get(), key) 110 } 111 } 112 }