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