1 /* <lambda>null2 * 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 android.util.Log 24 import com.android.permissioncontroller.PermissionControllerApplication 25 import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo 26 import kotlinx.coroutines.Job 27 28 /** 29 * A LiveData which tracks all of the packageinfos installed for a given user. 30 * 31 * @param app The current application 32 * @param user The user whose packages are desired 33 */ 34 class UserPackageInfosLiveData private constructor( 35 private val app: Application, 36 private val user: UserHandle 37 ) : SmartAsyncMediatorLiveData<@kotlin.jvm.JvmSuppressWildcards List<LightPackageInfo>>(), 38 PackageBroadcastReceiver.PackageBroadcastListener, 39 PermissionListenerMultiplexer.PermissionChangeCallback { 40 41 /** 42 * Whether or not the permissions in this liveData are out of date 43 */ 44 var permChangeStale = false 45 46 override fun onPackageUpdate(packageName: String) { 47 updateAsync() 48 } 49 50 // TODO ntmyren: replace with correctly updating 51 override fun onPermissionChange() { 52 permChangeStale = true 53 for (packageInfo in value ?: emptyList()) { 54 PermissionListenerMultiplexer.removeCallback(packageInfo.uid, this) 55 } 56 } 57 58 override fun setValue(newValue: List<LightPackageInfo>?) { 59 if (newValue != value) { 60 for (packageInfo in value ?: emptyList()) { 61 PermissionListenerMultiplexer.removeCallback(packageInfo.uid, this) 62 } 63 for (packageInfo in newValue ?: emptyList()) { 64 PermissionListenerMultiplexer.addCallback(packageInfo.uid, this) 65 } 66 } 67 super.setValue(newValue) 68 permChangeStale = false 69 } 70 71 /** 72 * Get all of the packages in the system, organized by user. 73 */ 74 override suspend fun loadDataAndPostValue(job: Job) { 75 if (job.isCancelled) { 76 return 77 } 78 // TODO ntmyren: remove once b/154796729 is fixed 79 Log.i("UserPackageInfos", "updating UserPackageInfosLiveData for user " + 80 "${user.identifier}") 81 val packageInfos = app.applicationContext.packageManager 82 .getInstalledPackagesAsUser(GET_PERMISSIONS or MATCH_ALL, user.identifier) 83 84 postValue(packageInfos.map { packageInfo -> LightPackageInfo(packageInfo) }) 85 } 86 87 override fun onActive() { 88 super.onActive() 89 90 PackageBroadcastReceiver.addAllCallback(this) 91 92 for (packageInfo in value ?: emptyList()) { 93 PermissionListenerMultiplexer.addCallback(packageInfo.uid, this) 94 } 95 96 updateAsync() 97 } 98 99 override fun onInactive() { 100 super.onInactive() 101 102 for (packageInfo in value ?: emptyList()) { 103 PermissionListenerMultiplexer.removeCallback(packageInfo.uid, this) 104 } 105 106 PackageBroadcastReceiver.removeAllCallback(this) 107 } 108 109 /** 110 * Repository for UserPackageInfosLiveDatas. 111 * <p> Key value is a UserHandle, value is its corresponding LiveData. 112 */ 113 companion object : DataRepository<UserHandle, UserPackageInfosLiveData>() { 114 override fun newValue(key: UserHandle): UserPackageInfosLiveData { 115 return UserPackageInfosLiveData(PermissionControllerApplication.get(), key) 116 } 117 } 118 }