1 /* 2 * 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 @file:JvmName("UserSensitiveFlagsUtils") 18 19 package com.android.permissioncontroller.permission.utils 20 21 import android.content.pm.PackageManager 22 import android.os.UserHandle 23 import android.util.Log 24 import com.android.permissioncontroller.PermissionControllerApplication 25 import com.android.permissioncontroller.permission.data.UserSensitivityLiveData 26 import com.android.permissioncontroller.permission.model.livedatatypes.UidSensitivityState 27 import com.android.permissioncontroller.permission.utils.Utils.FLAGS_ALWAYS_USER_SENSITIVE 28 import kotlinx.coroutines.GlobalScope 29 import kotlinx.coroutines.launch 30 import java.lang.IllegalStateException 31 32 private const val LOG_TAG = "UserSensitiveFlagsUtils" 33 34 /** 35 * Update the [PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED] and 36 * [PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED] for all apps of this user. 37 * 38 * @see UserSensitivityLiveData.loadDataAndPostValue 39 * 40 * @param user The user for whom packages will be updated 41 * @param callback A callback which will be executed when finished 42 */ 43 fun updateUserSensitiveForUser(user: UserHandle, callback: Runnable) { 44 GlobalScope.launch(IPC) { 45 // a map of <uid, uid state> 46 val uidUserSensitivity = UserSensitivityLiveData[user].getInitializedValue() 47 if (uidUserSensitivity == null) { 48 callback.run() 49 throw IllegalStateException( 50 "All uids sensitivity liveData should not be null if initialized") 51 } 52 updateUserSensitiveForUidsInternal(uidUserSensitivity, user, callback) 53 } 54 } 55 56 private fun updateUserSensitiveForUidsInternal( 57 uidsUserSensitivity: Map<Int, UidSensitivityState>, 58 user: UserHandle, 59 callback: Runnable? 60 ) { 61 val userContext = Utils.getUserContext(PermissionControllerApplication.get(), user) 62 val pm = userContext.packageManager 63 64 for ((uid, uidState) in uidsUserSensitivity) { 65 for (pkg in uidState.packages) { 66 for (perm in pkg.requestedPermissions) { 67 var flags = uidState.permStates[perm] ?: continue 68 69 try { 70 val oldFlags = pm.getPermissionFlags(perm, pkg.packageName, user) and 71 FLAGS_ALWAYS_USER_SENSITIVE 72 if (flags != oldFlags) { 73 pm.updatePermissionFlags(perm, pkg.packageName, 74 FLAGS_ALWAYS_USER_SENSITIVE, flags, user) 75 } 76 } catch (e: IllegalArgumentException) { 77 if (e.message?.startsWith("Unknown permission: ") == false) { 78 Log.e(LOG_TAG, "Unexpected exception while updating flags for " + 79 "${pkg.packageName} (uid $uid) permission $perm", e) 80 } else { 81 // Unknown permission - ignore 82 } 83 } 84 } 85 } 86 } 87 callback?.run() 88 } 89 90 /** 91 * [updateUserSensitiveForUser] for a single [uid] 92 * 93 * @param uid The uid to be updated 94 * @param callback A callback which will be executed when finished 95 */ 96 @JvmOverloads 97 fun updateUserSensitiveForUid(uid: Int, callback: Runnable? = null) { 98 GlobalScope.launch(IPC) { 99 val uidSensitivityState = UserSensitivityLiveData[uid].getInitializedValue() 100 if (uidSensitivityState != null) { 101 updateUserSensitiveForUidsInternal(uidSensitivityState, 102 UserHandle.getUserHandleForUid(uid), callback) 103 } else { 104 Log.e(LOG_TAG, "No packages associated with uid $uid, not updating flags") 105 callback?.run() 106 } 107 } 108 } 109