• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.v34
18 
19 import android.app.Application
20 import android.content.Context
21 import android.content.pm.PackageManager
22 import android.os.Process
23 import android.os.UserHandle
24 import android.util.Log
25 import com.android.permission.safetylabel.SafetyLabel
26 import com.android.permissioncontroller.PermissionControllerApplication
27 import com.android.permissioncontroller.permission.data.DataRepositoryForPackage
28 import com.android.permissioncontroller.permission.data.PackageBroadcastReceiver
29 import com.android.permissioncontroller.permission.data.SmartAsyncMediatorLiveData
30 import com.android.permissioncontroller.permission.data.get
31 import com.android.permissioncontroller.permission.model.livedatatypes.v34.SafetyLabelInfo
32 import com.android.permissioncontroller.permission.utils.v34.SafetyLabelUtils
33 import kotlinx.coroutines.Job
34 
35 /**
36  * [SafetyLabelInfo] [LiveData] for the specified package
37  *
38  * @param app current Application
39  * @param packageName name of the package to get SafetyLabel information for
40  * @param user The user of the package
41  */
42 class SafetyLabelInfoLiveData
43 private constructor(
44     private val app: Application,
45     private val packageName: String,
46     private val user: UserHandle
47 ) :
48     SmartAsyncMediatorLiveData<SafetyLabelInfo>(),
49     PackageBroadcastReceiver.PackageBroadcastListener {
50 
51     private val lightInstallSourceInfoLiveData = LightInstallSourceInfoLiveData[packageName, user]
52 
53     init {
<lambda>null54         addSource(lightInstallSourceInfoLiveData) { update() }
55 
56         update()
57     }
58 
onActivenull59     override fun onActive() {
60         super.onActive()
61         PackageBroadcastReceiver.addChangeCallback(packageName, this)
62     }
63 
onInactivenull64     override fun onInactive() {
65         super.onInactive()
66         PackageBroadcastReceiver.removeChangeCallback(packageName, this)
67     }
68 
69     /**
70      * Callback from the PackageBroadcastReceiver
71      *
72      * @param packageName the name of the package which was updated.
73      */
onPackageUpdatenull74     override fun onPackageUpdate(packageName: String) {
75         update()
76     }
77 
loadDataAndPostValuenull78     override suspend fun loadDataAndPostValue(job: Job) {
79         if (job.isCancelled) {
80             return
81         }
82 
83         if (lightInstallSourceInfoLiveData.isStale) {
84             return
85         }
86 
87         val lightInstallSourceInfo = lightInstallSourceInfoLiveData.value
88         if (lightInstallSourceInfo?.supportsSafetyLabel != true) {
89             postValue(SafetyLabelInfo.UNAVAILABLE)
90             return
91         }
92 
93         val userContext =
94             if (user == Process.myUserHandle()) {
95                 app
96             } else {
97                 app.createContextAsUser(user, /* flags= */ 0)
98             }
99 
100         // Asl in Apk (V+) is not supported by permissions
101         if (!SafetyLabelUtils.isAppMetadataSourceSupported(userContext, packageName)) {
102             postValue(SafetyLabelInfo.UNAVAILABLE)
103             return
104         }
105 
106         val safetyLabelInfo: SafetyLabelInfo =
107             try {
108                 val safetyLabel: SafetyLabel? = getSafetyLabel(userContext, packageName)
109                 if (safetyLabel != null) {
110                     SafetyLabelInfo(safetyLabel, lightInstallSourceInfo)
111                 } else {
112                     SafetyLabelInfo.UNAVAILABLE
113                 }
114             } catch (e: PackageManager.NameNotFoundException) {
115                 Log.w(LOG_TAG, "SafetyLabel for $packageName not found")
116                 invalidateSingle(packageName to user)
117                 SafetyLabelInfo.UNAVAILABLE
118             }
119         postValue(safetyLabelInfo)
120     }
121 
122     /** Returns the [SafetyLabel] for the given package and user. */
123     @Throws(PackageManager.NameNotFoundException::class)
getSafetyLabelnull124     private fun getSafetyLabel(userContext: Context, packageName: String): SafetyLabel? {
125         return SafetyLabel.getSafetyLabelFromMetadata(
126             userContext.packageManager.getAppMetadata(packageName)
127         )
128     }
129 
130     companion object :
131         DataRepositoryForPackage<Pair<String, UserHandle>, SafetyLabelInfoLiveData>() {
132         private val LOG_TAG = SafetyLabelInfoLiveData::class.java.simpleName
133 
newValuenull134         override fun newValue(key: Pair<String, UserHandle>): SafetyLabelInfoLiveData {
135             return SafetyLabelInfoLiveData(
136                 PermissionControllerApplication.get(),
137                 key.first,
138                 key.second
139             )
140         }
141     }
142 }
143