• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }