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 */
updateUserSensitiveForUsernull43 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
updateUserSensitiveForUidsInternalnull56 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
updateUserSensitiveForUidnull97 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