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