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 java.lang.IllegalStateException
29 import kotlinx.coroutines.GlobalScope
30 import kotlinx.coroutines.launch
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 * @param user The user for whom packages will be updated
39 * @param callback A callback which will be executed when finished
40 * @see UserSensitivityLiveData.loadDataAndPostValue
41 */
updateUserSensitiveForUsernull42 fun updateUserSensitiveForUser(user: UserHandle, callback: Runnable) {
43 GlobalScope.launch(IPC) {
44 // a map of <uid, uid state>
45 val uidUserSensitivity = UserSensitivityLiveData[user].getInitializedValue()
46 if (uidUserSensitivity == null) {
47 callback.run()
48 throw IllegalStateException(
49 "All uids sensitivity liveData should not be null if initialized"
50 )
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 =
71 pm.getPermissionFlags(perm, pkg.packageName, user) and
72 FLAGS_ALWAYS_USER_SENSITIVE
73 if (flags != oldFlags) {
74 pm.updatePermissionFlags(
75 perm,
76 pkg.packageName,
77 FLAGS_ALWAYS_USER_SENSITIVE,
78 flags,
79 user
80 )
81 }
82 } catch (e: IllegalArgumentException) {
83 if (e.message?.startsWith("Unknown permission: ") == false) {
84 Log.e(
85 LOG_TAG,
86 "Unexpected exception while updating flags for " +
87 "${pkg.packageName} (uid $uid) permission $perm",
88 e
89 )
90 } else {
91 // Unknown permission - ignore
92 }
93 }
94 }
95 }
96 }
97 callback?.run()
98 }
99
100 /**
101 * [updateUserSensitiveForUser] for a single [uid]
102 *
103 * @param uid The uid to be updated
104 * @param callback A callback which will be executed when finished
105 */
106 @JvmOverloads
updateUserSensitiveForUidnull107 fun updateUserSensitiveForUid(uid: Int, callback: Runnable? = null) {
108 GlobalScope.launch(IPC) {
109 val uidSensitivityState = UserSensitivityLiveData[uid].getInitializedValue()
110 if (uidSensitivityState != null) {
111 updateUserSensitiveForUidsInternal(
112 uidSensitivityState,
113 UserHandle.getUserHandleForUid(uid),
114 callback
115 )
116 } else {
117 Log.e(LOG_TAG, "No packages associated with uid $uid, not updating flags")
118 callback?.run()
119 }
120 }
121 }
122