blob: 4f0b689996f2a43e9723cf1584096671b4559f6a [file] [log] [blame]
Todd Kennedy0eb97382017-10-03 16:57:22 -07001/*
2 * Copyright (C) 2017 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
17package com.android.server.pm.permission;
18
Todd Kennedyc971a452019-07-08 16:04:52 -070019import static android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY;
Todd Kennedy0eb97382017-10-03 16:57:22 -070020import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
21import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
Eugene Susla922cd082020-03-11 12:38:17 -070022import static android.app.AppOpsManager.MODE_ALLOWED;
23import static android.app.AppOpsManager.MODE_IGNORED;
Eugene Susla49b84c32020-03-23 15:19:29 -070024import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISALLOWED;
25import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISCOURAGED;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070026import static android.content.pm.PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT;
27import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -070028import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
Hai Zhang253fa2b2020-06-02 14:07:23 -070029import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
Evan Seversonf21a09a2020-03-19 10:54:51 -070030import static android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -070031import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
Nate Myrenc92df182020-06-23 16:31:39 -070032import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
33import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
34import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
Todd Kennedy3bc94722017-10-10 09:55:53 -070035import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
Hai Zhang50a5a9b2019-09-19 13:57:45 -070036import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -070037import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
38import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
39import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
40import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070041import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER;
42import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM;
43import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE;
Philip P. Moltmannba742062019-04-08 13:22:44 -070044import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS_ALL;
Todd Kennedyc5b0e862019-07-16 09:47:58 -070045import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
Hongwei Wangf391b552018-04-06 13:52:46 -070046import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
Todd Kennedyc971a452019-07-08 16:04:52 -070047import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED;
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -070048import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED;
Hongwei Wangf391b552018-04-06 13:52:46 -070049
Philip P. Moltmannbd278012020-03-10 14:46:27 -070050import static com.android.server.pm.ApexManager.MATCH_ACTIVE_PACKAGE;
Todd Kennedyc29b11a2017-10-23 15:55:59 -070051import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
52import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
53import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS;
54import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
55import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
Philip P. Moltmann48456672019-01-20 13:14:03 -080056import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_FAILURE;
57
58import static java.util.concurrent.TimeUnit.SECONDS;
Todd Kennedy0eb97382017-10-03 16:57:22 -070059
60import android.Manifest;
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -070061import android.annotation.IntDef;
Todd Kennedy0eb97382017-10-03 16:57:22 -070062import android.annotation.NonNull;
63import android.annotation.Nullable;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -070064import android.annotation.UserIdInt;
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -070065import android.app.ActivityManager;
Eugene Susla922cd082020-03-11 12:38:17 -070066import android.app.AppOpsManager;
Eugene Suslad516bee2019-05-01 09:48:43 -070067import android.app.ApplicationPackageManager;
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -070068import android.app.IActivityManager;
wayneyang8126b1f2020-01-09 14:10:31 +080069import android.app.admin.DeviceAdminInfo;
Michael Groover56a84b22020-03-04 20:41:36 -080070import android.app.admin.DevicePolicyManager;
wayneyang8126b1f2020-01-09 14:10:31 +080071import android.app.admin.DevicePolicyManagerInternal;
Evan Severson50a77742020-01-06 10:38:19 -080072import android.compat.annotation.ChangeId;
73import android.compat.annotation.EnabledAfter;
Todd Kennedy0eb97382017-10-03 16:57:22 -070074import android.content.Context;
kholoud mohamed79a89f02020-01-15 15:30:07 +000075import android.content.PermissionChecker;
Hongming Jinbc4d0102019-08-16 14:28:30 -070076import android.content.pm.ApplicationInfo;
Todd Kennedy0eb97382017-10-03 16:57:22 -070077import android.content.pm.PackageManager;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -070078import android.content.pm.PackageManager.PermissionGroupInfoFlags;
79import android.content.pm.PackageManager.PermissionInfoFlags;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070080import android.content.pm.PackageManager.PermissionWhitelistFlags;
Todd Kennedy0eb97382017-10-03 16:57:22 -070081import android.content.pm.PackageManagerInternal;
82import android.content.pm.PackageParser;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -070083import android.content.pm.ParceledListSlice;
Todd Kennedy460f28c2017-10-06 13:46:22 -070084import android.content.pm.PermissionGroupInfo;
Todd Kennedy0eb97382017-10-03 16:57:22 -070085import android.content.pm.PermissionInfo;
Winsonf00c7552020-01-28 12:52:01 -080086import android.content.pm.parsing.component.ParsedPermission;
87import android.content.pm.parsing.component.ParsedPermissionGroup;
Anthony Hughde787d42019-08-22 15:35:48 -070088import android.content.pm.permission.SplitPermissionInfoParcelable;
Philip P. Moltmann8cff8b92017-10-25 14:32:41 -070089import android.metrics.LogMaker;
Todd Kennedy0eb97382017-10-03 16:57:22 -070090import android.os.Binder;
91import android.os.Build;
92import android.os.Handler;
93import android.os.HandlerThread;
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -070094import android.os.Looper;
95import android.os.Message;
Todd Kennedy0eb97382017-10-03 16:57:22 -070096import android.os.Process;
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -070097import android.os.RemoteCallbackList;
98import android.os.RemoteException;
Todd Kennedy8f135982019-07-02 07:35:15 -070099import android.os.ServiceManager;
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700100import android.os.Trace;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700101import android.os.UserHandle;
102import android.os.UserManager;
103import android.os.UserManagerInternal;
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700104import android.os.storage.StorageManager;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700105import android.os.storage.StorageManagerInternal;
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -0700106import android.permission.IOnPermissionsChangeListener;
Todd Kennedy8f135982019-07-02 07:35:15 -0700107import android.permission.IPermissionManager;
Philip P. Moltmann48456672019-01-20 13:14:03 -0800108import android.permission.PermissionControllerManager;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -0700109import android.permission.PermissionManager;
Philip P. Moltmann48456672019-01-20 13:14:03 -0800110import android.permission.PermissionManagerInternal;
Todd Kennedyca1ea172019-07-03 15:02:28 -0700111import android.permission.PermissionManagerInternal.CheckPermissionDelegate;
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700112import android.permission.PermissionManagerInternal.OnRuntimePermissionStateChangedListener;
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700113import android.text.TextUtils;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700114import android.util.ArrayMap;
115import android.util.ArraySet;
Eugene Suslad516bee2019-05-01 09:48:43 -0700116import android.util.DebugUtils;
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -0700117import android.util.EventLog;
Todd Kennedyc971a452019-07-08 16:04:52 -0700118import android.util.IntArray;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700119import android.util.Log;
120import android.util.Slog;
Todd Kennedy3bc94722017-10-10 09:55:53 -0700121import android.util.SparseArray;
Philip P. Moltmann48456672019-01-20 13:14:03 -0800122import android.util.SparseBooleanArray;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700123
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700124import com.android.internal.annotations.GuardedBy;
Michael Groover56a84b22020-03-04 20:41:36 -0800125import com.android.internal.annotations.VisibleForTesting;
Evan Severson50a77742020-01-06 10:38:19 -0800126import com.android.internal.compat.IPlatformCompat;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700127import com.android.internal.logging.MetricsLogger;
128import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700129import com.android.internal.os.RoSystemProperties;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700130import com.android.internal.util.ArrayUtils;
Philip P. Moltmann58c52d42020-05-18 12:06:13 -0700131import com.android.internal.util.DumpUtils;
Todd Kennedyc971a452019-07-08 16:04:52 -0700132import com.android.internal.util.IntPair;
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -0700133import com.android.internal.util.Preconditions;
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700134import com.android.internal.util.function.pooled.PooledLambda;
135import com.android.server.FgThread;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700136import com.android.server.LocalServices;
137import com.android.server.ServiceThread;
138import com.android.server.SystemConfig;
139import com.android.server.Watchdog;
Philip P. Moltmannbd278012020-03-10 14:46:27 -0700140import com.android.server.pm.ApexManager;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700141import com.android.server.pm.PackageManagerServiceUtils;
142import com.android.server.pm.PackageSetting;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700143import com.android.server.pm.SharedUserSetting;
Todd Kennedy3bc94722017-10-10 09:55:53 -0700144import com.android.server.pm.UserManagerService;
Winson5e0a1d52020-01-24 12:00:33 -0800145import com.android.server.pm.parsing.PackageInfoUtils;
Winsonf00c7552020-01-28 12:52:01 -0800146import com.android.server.pm.parsing.pkg.AndroidPackage;
Todd Kennedy583378d2019-07-12 06:50:30 -0700147import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultBrowserProvider;
148import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultDialerProvider;
149import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultHomeProvider;
Philip P. Moltmann48456672019-01-20 13:14:03 -0800150import com.android.server.pm.permission.PermissionManagerServiceInternal.PermissionCallback;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700151import com.android.server.pm.permission.PermissionsState.PermissionState;
Svet Ganov3c499ea2019-07-26 17:45:56 -0700152import com.android.server.policy.PermissionPolicyInternal;
Philip P. Moltmann8625cdd2019-05-30 08:27:19 -0700153import com.android.server.policy.SoftRestrictedPermissionPolicy;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700154
155import libcore.util.EmptyArray;
156
Philip P. Moltmann5ab27fc2020-05-06 17:10:59 -0700157import java.io.FileDescriptor;
158import java.io.PrintWriter;
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -0700159import java.lang.annotation.Retention;
160import java.lang.annotation.RetentionPolicy;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700161import java.util.ArrayList;
Hai Zhang4c0d15b2020-05-18 16:06:58 -0700162import java.util.Collection;
Hongwei Wangf391b552018-04-06 13:52:46 -0700163import java.util.HashMap;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700164import java.util.Iterator;
165import java.util.List;
Hongwei Wangf391b552018-04-06 13:52:46 -0700166import java.util.Map;
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700167import java.util.Objects;
Todd Kennedyc8423932017-10-05 08:58:36 -0700168import java.util.Set;
Philip P. Moltmann48456672019-01-20 13:14:03 -0800169import java.util.concurrent.CompletableFuture;
170import java.util.concurrent.ExecutionException;
171import java.util.concurrent.TimeUnit;
172import java.util.concurrent.TimeoutException;
Todd Kennedy230c0a72019-07-03 13:06:35 -0700173import java.util.function.Consumer;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700174
175/**
176 * Manages all permissions and handles permissions related tasks.
177 */
Todd Kennedy8f135982019-07-02 07:35:15 -0700178public class PermissionManagerService extends IPermissionManager.Stub {
Todd Kennedy0eb97382017-10-03 16:57:22 -0700179 private static final String TAG = "PackageManager";
180
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700181 /** Permission grant: not grant the permission. */
182 private static final int GRANT_DENIED = 1;
183 /** Permission grant: grant the permission as an install permission. */
184 private static final int GRANT_INSTALL = 2;
185 /** Permission grant: grant the permission as a runtime one. */
186 private static final int GRANT_RUNTIME = 3;
187 /** Permission grant: grant as runtime a permission that was granted as an install time one. */
188 private static final int GRANT_UPGRADE = 4;
189
Philip P. Moltmann48456672019-01-20 13:14:03 -0800190 private static final long BACKUP_TIMEOUT_MILLIS = SECONDS.toMillis(60);
191
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700192 /** Cap the size of permission trees that 3rd party apps can define; in characters of text */
193 private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768;
194 /** Empty array to avoid allocations */
195 private static final int[] EMPTY_INT_ARRAY = new int[0];
Todd Kennedy0eb97382017-10-03 16:57:22 -0700196
Philip P. Moltmann319c4ee2019-02-25 09:21:23 -0800197 /**
198 * When these flags are set, the system should not automatically modify the permission grant
199 * state.
200 */
201 private static final int BLOCKING_PERMISSION_FLAGS = FLAG_PERMISSION_SYSTEM_FIXED
202 | FLAG_PERMISSION_POLICY_FIXED
203 | FLAG_PERMISSION_GRANTED_BY_DEFAULT;
204
205 /** Permission flags set by the user */
206 private static final int USER_PERMISSION_FLAGS = FLAG_PERMISSION_USER_SET
207 | FLAG_PERMISSION_USER_FIXED;
208
Hongwei Wangf391b552018-04-06 13:52:46 -0700209 /** If the permission of the value is granted, so is the key */
210 private static final Map<String, String> FULLER_PERMISSION_MAP = new HashMap<>();
211
212 static {
213 FULLER_PERMISSION_MAP.put(Manifest.permission.ACCESS_COARSE_LOCATION,
214 Manifest.permission.ACCESS_FINE_LOCATION);
215 FULLER_PERMISSION_MAP.put(Manifest.permission.INTERACT_ACROSS_USERS,
216 Manifest.permission.INTERACT_ACROSS_USERS_FULL);
217 }
218
Todd Kennedy0eb97382017-10-03 16:57:22 -0700219 /** Lock to protect internal data access */
220 private final Object mLock;
221
222 /** Internal connection to the package manager */
223 private final PackageManagerInternal mPackageManagerInt;
224
225 /** Internal connection to the user manager */
226 private final UserManagerInternal mUserManagerInt;
227
Philip P. Moltmann48456672019-01-20 13:14:03 -0800228 /** Permission controller: User space permission management */
229 private PermissionControllerManager mPermissionControllerManager;
230
Evan Seversonb252d8b2019-11-20 08:41:33 -0800231 /** Map of OneTimePermissionUserManagers keyed by userId */
232 private final SparseArray<OneTimePermissionUserManager> mOneTimePermissionUserManagers =
233 new SparseArray<>();
234
Todd Kennedy0eb97382017-10-03 16:57:22 -0700235 /** Default permission policy to provide proper behaviour out-of-the-box */
236 private final DefaultPermissionGrantPolicy mDefaultPermissionGrantPolicy;
237
Eugene Susla922cd082020-03-11 12:38:17 -0700238 /** App ops manager */
239 private final AppOpsManager mAppOpsManager;
240
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700241 /**
242 * Built-in permissions. Read from system configuration files. Mapping is from
243 * UID to permission name.
244 */
Todd Kennedy3bc94722017-10-10 09:55:53 -0700245 private final SparseArray<ArraySet<String>> mSystemPermissions;
Todd Kennedy3bc94722017-10-10 09:55:53 -0700246
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700247 /** Built-in group IDs given to all packages. Read from system configuration files. */
248 private final int[] mGlobalGids;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700249
250 private final HandlerThread mHandlerThread;
251 private final Handler mHandler;
252 private final Context mContext;
Philip P. Moltmann8cff8b92017-10-25 14:32:41 -0700253 private final MetricsLogger mMetricsLogger = new MetricsLogger();
Evan Severson50a77742020-01-06 10:38:19 -0800254 private final IPlatformCompat mPlatformCompat = IPlatformCompat.Stub.asInterface(
255 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
Todd Kennedy0eb97382017-10-03 16:57:22 -0700256
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700257 /** Internal storage for permissions and related settings */
258 @GuardedBy("mLock")
259 private final PermissionSettings mSettings;
260
Michael Groover56a84b22020-03-04 20:41:36 -0800261 /** Injector that can be used to facilitate testing. */
262 private final Injector mInjector;
263
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700264 @GuardedBy("mLock")
265 private ArraySet<String> mPrivappPermissionsViolations;
266
267 @GuardedBy("mLock")
268 private boolean mSystemReady;
269
Svet Ganov3c499ea2019-07-26 17:45:56 -0700270 @GuardedBy("mLock")
271 private PermissionPolicyInternal mPermissionPolicyInternal;
272
Philip P. Moltmanne1b277a2018-11-01 16:22:50 -0700273 /**
274 * For each foreground/background permission the mapping:
275 * Background permission -> foreground permissions
276 */
277 @GuardedBy("mLock")
278 private ArrayMap<String, List<String>> mBackgroundPermissions;
279
Philip P. Moltmann48456672019-01-20 13:14:03 -0800280 /**
281 * A permission backup might contain apps that are not installed. In this case we delay the
282 * restoration until the app is installed.
283 *
284 * <p>This array ({@code userId -> noDelayedBackupLeft}) is {@code true} for all the users where
285 * there is <u>no more</u> delayed backup left.
286 */
287 @GuardedBy("mLock")
288 private final SparseBooleanArray mHasNoDelayedPermBackup = new SparseBooleanArray();
289
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700290 /** Listeners for permission state (granting and flags) changes */
291 @GuardedBy("mLock")
292 final private ArrayList<OnRuntimePermissionStateChangedListener>
293 mRuntimePermissionStateChangedListeners = new ArrayList<>();
294
Todd Kennedyca1ea172019-07-03 15:02:28 -0700295 @GuardedBy("mLock")
296 private CheckPermissionDelegate mCheckPermissionDelegate;
297
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -0700298 @GuardedBy("mLock")
299 private final OnPermissionChangeListeners mOnPermissionChangeListeners;
300
Todd Kennedy583378d2019-07-12 06:50:30 -0700301 @GuardedBy("mLock")
302 private DefaultBrowserProvider mDefaultBrowserProvider;
303
304 @GuardedBy("mLock")
305 private DefaultDialerProvider mDefaultDialerProvider;
306
307 @GuardedBy("mLock")
308 private DefaultHomeProvider mDefaultHomeProvider;
309
Todd Kennedy230c0a72019-07-03 13:06:35 -0700310 // TODO: Take a look at the methods defined in the callback.
311 // The callback was initially created to support the split between permission
312 // manager and the package manager. However, it's started to be used for other
313 // purposes. It may make sense to keep as an abstraction, but, the methods
314 // necessary to be overridden may be different than what was initially needed
315 // for the split.
316 private PermissionCallback mDefaultPermissionCallback = new PermissionCallback() {
317 @Override
318 public void onGidsChanged(int appId, int userId) {
Todd Kennedyc971a452019-07-08 16:04:52 -0700319 mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED));
Todd Kennedy230c0a72019-07-03 13:06:35 -0700320 }
321 @Override
322 public void onPermissionGranted(int uid, int userId) {
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -0700323 mOnPermissionChangeListeners.onPermissionsChanged(uid);
324
325 // Not critical; if this is lost, the application has to request again.
326 mPackageManagerInt.writeSettings(true);
Todd Kennedy230c0a72019-07-03 13:06:35 -0700327 }
328 @Override
329 public void onInstallPermissionGranted() {
330 mPackageManagerInt.writeSettings(true);
331 }
332 @Override
Evan Seversonaacd48b2020-06-22 16:45:03 -0700333 public void onPermissionRevoked(int uid, int userId, String reason) {
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -0700334 mOnPermissionChangeListeners.onPermissionsChanged(uid);
335
336 // Critical; after this call the application should never have the permission
337 mPackageManagerInt.writeSettings(false);
338 final int appId = UserHandle.getAppId(uid);
Evan Seversonaacd48b2020-06-22 16:45:03 -0700339 if (reason == null) {
340 mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED));
341 } else {
342 mHandler.post(() -> killUid(appId, userId, reason));
343 }
Todd Kennedy230c0a72019-07-03 13:06:35 -0700344 }
345 @Override
346 public void onInstallPermissionRevoked() {
347 mPackageManagerInt.writeSettings(true);
348 }
349 @Override
350 public void onPermissionUpdated(int[] userIds, boolean sync) {
351 mPackageManagerInt.writePermissionSettings(userIds, !sync);
352 }
353 @Override
354 public void onInstallPermissionUpdated() {
355 mPackageManagerInt.writeSettings(true);
356 }
357 @Override
358 public void onPermissionRemoved() {
359 mPackageManagerInt.writeSettings(false);
360 }
361 public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
362 int uid) {
363 onPermissionUpdated(updatedUserIds, sync);
Nate Myren3fb13a12019-12-11 12:30:39 -0800364 for (int i = 0; i < updatedUserIds.length; i++) {
365 int userUid = UserHandle.getUid(updatedUserIds[i], UserHandle.getAppId(uid));
366 mOnPermissionChangeListeners.onPermissionsChanged(userUid);
367 }
Todd Kennedy230c0a72019-07-03 13:06:35 -0700368 }
369 public void onInstallPermissionUpdatedNotifyListener(int uid) {
370 onInstallPermissionUpdated();
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -0700371 mOnPermissionChangeListeners.onPermissionsChanged(uid);
Todd Kennedy230c0a72019-07-03 13:06:35 -0700372 }
373 };
374
Todd Kennedy0eb97382017-10-03 16:57:22 -0700375 PermissionManagerService(Context context,
Todd Kennedy0eb97382017-10-03 16:57:22 -0700376 @NonNull Object externalLock) {
Michael Groover56a84b22020-03-04 20:41:36 -0800377 this(context, externalLock, new Injector(context));
378 }
379
380 @VisibleForTesting
381 PermissionManagerService(Context context, @NonNull Object externalLock,
382 @NonNull Injector injector) {
383 mInjector = injector;
Daniel Colascionea46b7b32020-01-24 13:30:25 -0800384 // The package info cache is the cache for package and permission information.
Michael Groover56a84b22020-03-04 20:41:36 -0800385 mInjector.invalidatePackageInfoCache();
386 mInjector.disablePermissionCache();
387 mInjector.disablePackageNamePermissionCache();
Daniel Colascionea46b7b32020-01-24 13:30:25 -0800388
Todd Kennedy0eb97382017-10-03 16:57:22 -0700389 mContext = context;
390 mLock = externalLock;
391 mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
392 mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700393 mSettings = new PermissionSettings(mLock);
Eugene Susla922cd082020-03-11 12:38:17 -0700394 mAppOpsManager = context.getSystemService(AppOpsManager.class);
Todd Kennedy0eb97382017-10-03 16:57:22 -0700395
396 mHandlerThread = new ServiceThread(TAG,
397 Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
398 mHandlerThread.start();
399 mHandler = new Handler(mHandlerThread.getLooper());
400 Watchdog.getInstance().addThread(mHandler);
401
402 mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(
Philip P. Moltmannbe11ab62020-05-01 00:11:09 -0700403 context, mHandlerThread.getLooper());
Todd Kennedy3bc94722017-10-10 09:55:53 -0700404 SystemConfig systemConfig = SystemConfig.getInstance();
405 mSystemPermissions = systemConfig.getSystemPermissions();
406 mGlobalGids = systemConfig.getGlobalGids();
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -0700407 mOnPermissionChangeListeners = new OnPermissionChangeListeners(FgThread.get().getLooper());
Todd Kennedy0eb97382017-10-03 16:57:22 -0700408
409 // propagate permission configuration
410 final ArrayMap<String, SystemConfig.PermissionEntry> permConfig =
411 SystemConfig.getInstance().getPermissions();
412 synchronized (mLock) {
413 for (int i=0; i<permConfig.size(); i++) {
414 final SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
415 BasePermission bp = mSettings.getPermissionLocked(perm.name);
416 if (bp == null) {
417 bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
418 mSettings.putPermissionLocked(perm.name, bp);
419 }
420 if (perm.gids != null) {
421 bp.setGids(perm.gids, perm.perUser);
422 }
423 }
424 }
425
Philip P. Moltmann48456672019-01-20 13:14:03 -0800426 PermissionManagerServiceInternalImpl localService =
427 new PermissionManagerServiceInternalImpl();
428 LocalServices.addService(PermissionManagerServiceInternal.class, localService);
429 LocalServices.addService(PermissionManagerInternal.class, localService);
Todd Kennedy0eb97382017-10-03 16:57:22 -0700430 }
431
Philip P. Moltmann5ab27fc2020-05-06 17:10:59 -0700432 @Override
433 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Philip P. Moltmann58c52d42020-05-18 12:06:13 -0700434 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
435 return;
436 }
437
Philip P. Moltmann1a446782020-05-07 22:51:38 -0700438 mContext.getSystemService(PermissionControllerManager.class).dump(fd, args);
Philip P. Moltmann5ab27fc2020-05-06 17:10:59 -0700439 }
440
Todd Kennedy0eb97382017-10-03 16:57:22 -0700441 /**
442 * Creates and returns an initialized, internal service for use by other components.
443 * <p>
444 * The object returned is identical to the one returned by the LocalServices class using:
Philip P. Moltmann48456672019-01-20 13:14:03 -0800445 * {@code LocalServices.getService(PermissionManagerServiceInternal.class);}
Todd Kennedy0eb97382017-10-03 16:57:22 -0700446 * <p>
447 * NOTE: The external lock is temporary and should be removed. This needs to be a
448 * lock created by the permission manager itself.
449 */
Philip P. Moltmann48456672019-01-20 13:14:03 -0800450 public static PermissionManagerServiceInternal create(Context context,
Todd Kennedy0eb97382017-10-03 16:57:22 -0700451 @NonNull Object externalLock) {
Philip P. Moltmann48456672019-01-20 13:14:03 -0800452 final PermissionManagerServiceInternal permMgrInt =
453 LocalServices.getService(PermissionManagerServiceInternal.class);
Todd Kennedy0eb97382017-10-03 16:57:22 -0700454 if (permMgrInt != null) {
455 return permMgrInt;
456 }
Todd Kennedy8f135982019-07-02 07:35:15 -0700457 PermissionManagerService permissionService =
458 (PermissionManagerService) ServiceManager.getService("permissionmgr");
459 if (permissionService == null) {
460 permissionService =
461 new PermissionManagerService(context, externalLock);
462 ServiceManager.addService("permissionmgr", permissionService);
463 }
Philip P. Moltmann48456672019-01-20 13:14:03 -0800464 return LocalServices.getService(PermissionManagerServiceInternal.class);
Todd Kennedy0eb97382017-10-03 16:57:22 -0700465 }
466
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -0700467 /**
468 * This method should typically only be used when granting or revoking
469 * permissions, since the app may immediately restart after this call.
470 * <p>
471 * If you're doing surgery on app code/data, use {@link PackageFreezer} to
472 * guard your work against the app being relaunched.
473 */
474 public static void killUid(int appId, int userId, String reason) {
475 final long identity = Binder.clearCallingIdentity();
476 try {
477 IActivityManager am = ActivityManager.getService();
478 if (am != null) {
479 try {
Evan Seversonaacd48b2020-06-22 16:45:03 -0700480 am.killUidForPermissionChange(appId, userId, reason);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -0700481 } catch (RemoteException e) {
482 /* ignore - same process */
483 }
484 }
485 } finally {
486 Binder.restoreCallingIdentity(identity);
487 }
488 }
489
Winson14ff7172019-10-23 10:42:27 -0700490 @Nullable
491 BasePermission getPermission(String permName) {
Todd Kennedy0eb97382017-10-03 16:57:22 -0700492 synchronized (mLock) {
493 return mSettings.getPermissionLocked(permName);
494 }
495 }
496
Todd Kennedy8f135982019-07-02 07:35:15 -0700497 @Override
498 public String[] getAppOpPermissionPackages(String permName) {
499 return getAppOpPermissionPackagesInternal(permName, getCallingUid());
500 }
501
502 private String[] getAppOpPermissionPackagesInternal(String permName, int callingUid) {
503 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
504 return null;
505 }
506 synchronized (mLock) {
507 final ArraySet<String> pkgs = mSettings.mAppOpPermissionPackages.get(permName);
508 if (pkgs == null) {
509 return null;
510 }
511 return pkgs.toArray(new String[pkgs.size()]);
512 }
513 }
514
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700515 @Override
516 @NonNull
517 public ParceledListSlice<PermissionGroupInfo> getAllPermissionGroups(
518 @PermissionGroupInfoFlags int flags) {
519 final int callingUid = getCallingUid();
520 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
521 return ParceledListSlice.emptyList();
522 }
523 synchronized (mLock) {
524 final int n = mSettings.mPermissionGroups.size();
Winson14ff7172019-10-23 10:42:27 -0700525 final ArrayList<PermissionGroupInfo> out = new ArrayList<>(n);
526 for (ParsedPermissionGroup pg : mSettings.mPermissionGroups.values()) {
527 out.add(PackageInfoUtils.generatePermissionGroupInfo(pg, flags));
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700528 }
529 return new ParceledListSlice<>(out);
530 }
531 }
532
533
534 @Override
535 @Nullable
536 public PermissionGroupInfo getPermissionGroupInfo(String groupName,
537 @PermissionGroupInfoFlags int flags) {
538 final int callingUid = getCallingUid();
539 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
540 return null;
541 }
542 synchronized (mLock) {
Winson14ff7172019-10-23 10:42:27 -0700543 return PackageInfoUtils.generatePermissionGroupInfo(
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700544 mSettings.mPermissionGroups.get(groupName), flags);
545 }
546 }
547
548
549 @Override
550 @Nullable
551 public PermissionInfo getPermissionInfo(String permName, String packageName,
552 @PermissionInfoFlags int flags) {
553 final int callingUid = getCallingUid();
554 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
555 return null;
556 }
557 synchronized (mLock) {
558 final BasePermission bp = mSettings.getPermissionLocked(permName);
559 if (bp == null) {
560 return null;
561 }
562 final int adjustedProtectionLevel = adjustPermissionProtectionFlagsLocked(
563 bp.getProtectionLevel(), packageName, callingUid);
564 return bp.generatePermissionInfo(adjustedProtectionLevel, flags);
565 }
566 }
567
568 @Override
569 @Nullable
570 public ParceledListSlice<PermissionInfo> queryPermissionsByGroup(String groupName,
571 @PermissionInfoFlags int flags) {
572 final int callingUid = getCallingUid();
573 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
574 return null;
575 }
576 synchronized (mLock) {
577 if (groupName != null && !mSettings.mPermissionGroups.containsKey(groupName)) {
578 return null;
579 }
580 final ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
581 for (BasePermission bp : mSettings.mPermissions.values()) {
582 final PermissionInfo pi = bp.generatePermissionInfo(groupName, flags);
583 if (pi != null) {
584 out.add(pi);
585 }
586 }
587 return new ParceledListSlice<>(out);
588 }
589 }
590
Todd Kennedy6ffc5a62019-07-03 09:35:31 -0700591 @Override
592 public boolean addPermission(PermissionInfo info, boolean async) {
593 final int callingUid = getCallingUid();
594 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
595 throw new SecurityException("Instant apps can't add permissions");
596 }
597 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
598 throw new SecurityException("Label must be specified in permission");
599 }
600 final BasePermission tree = mSettings.enforcePermissionTree(info.name, callingUid);
601 final boolean added;
602 final boolean changed;
603 synchronized (mLock) {
604 BasePermission bp = mSettings.getPermissionLocked(info.name);
605 added = bp == null;
606 int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
607 if (added) {
608 enforcePermissionCapLocked(info, tree);
609 bp = new BasePermission(info.name, tree.getSourcePackageName(),
610 BasePermission.TYPE_DYNAMIC);
611 } else if (!bp.isDynamic()) {
612 throw new SecurityException("Not allowed to modify non-dynamic permission "
613 + info.name);
614 }
615 changed = bp.addToTree(fixedLevel, info, tree);
616 if (added) {
617 mSettings.putPermissionLocked(info.name, bp);
618 }
619 }
620 if (changed) {
621 mPackageManagerInt.writeSettings(async);
622 }
623 return added;
624 }
625
626 @Override
627 public void removePermission(String permName) {
628 final int callingUid = getCallingUid();
629 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
630 throw new SecurityException("Instant applications don't have access to this method");
631 }
632 final BasePermission tree = mSettings.enforcePermissionTree(permName, callingUid);
633 synchronized (mLock) {
634 final BasePermission bp = mSettings.getPermissionLocked(permName);
635 if (bp == null) {
636 return;
637 }
638 if (bp.isDynamic()) {
639 // TODO: switch this back to SecurityException
640 Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
641 + permName);
642 }
643 mSettings.removePermissionLocked(permName);
644 mPackageManagerInt.writeSettings(false);
645 }
646 }
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700647
Todd Kennedy230c0a72019-07-03 13:06:35 -0700648 @Override
649 public int getPermissionFlags(String permName, String packageName, int userId) {
650 final int callingUid = getCallingUid();
651 return getPermissionFlagsInternal(permName, packageName, callingUid, userId);
652 }
653
654 private int getPermissionFlagsInternal(
655 String permName, String packageName, int callingUid, int userId) {
656 if (!mUserManagerInt.exists(userId)) {
657 return 0;
658 }
659
660 enforceGrantRevokeGetRuntimePermissionPermissions("getPermissionFlags");
661 enforceCrossUserPermission(callingUid, userId,
662 true, // requireFullPermission
663 false, // checkShell
664 false, // requirePermissionWhenSameUser
665 "getPermissionFlags");
666
Winson14ff7172019-10-23 10:42:27 -0700667 final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
668 if (pkg == null) {
669 return 0;
670 }
671 final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
672 pkg.getPackageName());
673 if (ps == null) {
Todd Kennedy230c0a72019-07-03 13:06:35 -0700674 return 0;
675 }
676 synchronized (mLock) {
677 if (mSettings.getPermissionLocked(permName) == null) {
678 return 0;
679 }
680 }
681 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
682 return 0;
683 }
Todd Kennedy230c0a72019-07-03 13:06:35 -0700684 PermissionsState permissionsState = ps.getPermissionsState();
685 return permissionsState.getPermissionFlags(permName, userId);
686 }
687
688 @Override
689 public void updatePermissionFlags(String permName, String packageName, int flagMask,
690 int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
691 final int callingUid = getCallingUid();
692 boolean overridePolicy = false;
693
694 if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
695 long callingIdentity = Binder.clearCallingIdentity();
696 try {
697 if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0) {
698 if (checkAdjustPolicyFlagPermission) {
699 mContext.enforceCallingOrSelfPermission(
700 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
701 "Need " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
702 + " to change policy flags");
Hai Zhang053c3a22019-08-23 15:08:03 -0700703 } else if (mPackageManagerInt.getUidTargetSdkVersion(callingUid)
Todd Kennedy230c0a72019-07-03 13:06:35 -0700704 >= Build.VERSION_CODES.Q) {
705 throw new IllegalArgumentException(
706 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY + " needs "
707 + " to be checked for packages targeting "
708 + Build.VERSION_CODES.Q + " or later when changing policy "
709 + "flags");
710 }
711 overridePolicy = true;
712 }
713 } finally {
714 Binder.restoreCallingIdentity(callingIdentity);
715 }
716 }
717
718 updatePermissionFlagsInternal(
719 permName, packageName, flagMask, flagValues, callingUid, userId,
720 overridePolicy, mDefaultPermissionCallback);
721 }
722
723 private void updatePermissionFlagsInternal(String permName, String packageName, int flagMask,
724 int flagValues, int callingUid, int userId, boolean overridePolicy,
725 PermissionCallback callback) {
Eugene Suslacb923e32019-08-20 16:48:55 -0700726 if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES
Todd Kennedy230c0a72019-07-03 13:06:35 -0700727 && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
Eugene Suslacb923e32019-08-20 16:48:55 -0700728 Log.i(TAG, "System is updating flags for " + packageName + " "
Todd Kennedy230c0a72019-07-03 13:06:35 -0700729 + permName + " for user " + userId + " "
730 + DebugUtils.flagsToString(
731 PackageManager.class, "FLAG_PERMISSION_", flagMask)
732 + " := "
733 + DebugUtils.flagsToString(
734 PackageManager.class, "FLAG_PERMISSION_", flagValues)
735 + " on behalf of uid " + callingUid
736 + " " + mPackageManagerInt.getNameForUid(callingUid),
737 new RuntimeException());
738 }
739
740 if (!mUserManagerInt.exists(userId)) {
741 return;
742 }
743
744 enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
745
746 enforceCrossUserPermission(callingUid, userId,
747 true, // requireFullPermission
748 true, // checkShell
749 false, // requirePermissionWhenSameUser
750 "updatePermissionFlags");
751
752 if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0 && !overridePolicy) {
753 throw new SecurityException("updatePermissionFlags requires "
754 + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
755 }
756
757 // Only the system can change these flags and nothing else.
758 if (callingUid != Process.SYSTEM_UID) {
759 flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
760 flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
761 flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
762 flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
763 flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
Nate Myrenc92df182020-06-23 16:31:39 -0700764 flagValues &= ~FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
765 flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
766 flagValues &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
Todd Kennedy230c0a72019-07-03 13:06:35 -0700767 flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
768 }
769
Winson14ff7172019-10-23 10:42:27 -0700770 final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
771 final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
772 packageName);
773 if (pkg == null || ps == null) {
Todd Kennedy230c0a72019-07-03 13:06:35 -0700774 Log.e(TAG, "Unknown package: " + packageName);
775 return;
776 }
777 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
778 throw new IllegalArgumentException("Unknown package: " + packageName);
779 }
780
781 final BasePermission bp;
782 synchronized (mLock) {
783 bp = mSettings.getPermissionLocked(permName);
784 }
785 if (bp == null) {
786 throw new IllegalArgumentException("Unknown permission: " + permName);
787 }
788
Todd Kennedy230c0a72019-07-03 13:06:35 -0700789 final PermissionsState permissionsState = ps.getPermissionsState();
790 final boolean hadState =
791 permissionsState.getRuntimePermissionState(permName, userId) != null;
792 final boolean permissionUpdated =
793 permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
794 if (permissionUpdated && bp.isRuntime()) {
795 notifyRuntimePermissionStateChanged(packageName, userId);
796 }
797 if (permissionUpdated && callback != null) {
798 // Install and runtime permissions are stored in different places,
799 // so figure out what permission changed and persist the change.
800 if (permissionsState.getInstallPermissionState(permName) != null) {
Nate Myren3fb13a12019-12-11 12:30:39 -0800801 int userUid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid()));
802 callback.onInstallPermissionUpdatedNotifyListener(userUid);
Todd Kennedy230c0a72019-07-03 13:06:35 -0700803 } else if (permissionsState.getRuntimePermissionState(permName, userId) != null
804 || hadState) {
Winson14ff7172019-10-23 10:42:27 -0700805 callback.onPermissionUpdatedNotifyListener(new int[]{userId}, false,
806 pkg.getUid());
Todd Kennedy230c0a72019-07-03 13:06:35 -0700807 }
808 }
809 }
810
811 /**
812 * Update the permission flags for all packages and runtime permissions of a user in order
813 * to allow device or profile owner to remove POLICY_FIXED.
814 */
815 @Override
816 public void updatePermissionFlagsForAllApps(int flagMask, int flagValues,
817 final int userId) {
818 final int callingUid = getCallingUid();
819 if (!mUserManagerInt.exists(userId)) {
820 return;
821 }
822
823 enforceGrantRevokeRuntimePermissionPermissions(
824 "updatePermissionFlagsForAllApps");
825 enforceCrossUserPermission(callingUid, userId,
826 true, // requireFullPermission
827 true, // checkShell
828 false, // requirePermissionWhenSameUser
829 "updatePermissionFlagsForAllApps");
830
831 // Only the system can change system fixed flags.
832 final int effectiveFlagMask = (callingUid != Process.SYSTEM_UID)
833 ? flagMask : flagMask & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
834 final int effectiveFlagValues = (callingUid != Process.SYSTEM_UID)
835 ? flagValues : flagValues & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
836
837 final boolean[] changed = new boolean[1];
Winson14ff7172019-10-23 10:42:27 -0700838 mPackageManagerInt.forEachPackage(pkg -> {
839 final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
840 pkg.getPackageName());
841 if (ps == null) {
842 return;
Todd Kennedy230c0a72019-07-03 13:06:35 -0700843 }
Winson14ff7172019-10-23 10:42:27 -0700844 final PermissionsState permissionsState = ps.getPermissionsState();
845 changed[0] |= permissionsState.updatePermissionFlagsForAllPermissions(
846 userId, effectiveFlagMask, effectiveFlagValues);
847 mOnPermissionChangeListeners.onPermissionsChanged(pkg.getUid());
Todd Kennedy230c0a72019-07-03 13:06:35 -0700848 });
849
850 if (changed[0]) {
851 mPackageManagerInt.writePermissionSettings(new int[] { userId }, true);
852 }
853 }
854
Todd Kennedyca1ea172019-07-03 15:02:28 -0700855 @Override
856 public int checkPermission(String permName, String pkgName, int userId) {
Daulet Zhanguzin82adfcb2020-01-02 17:31:40 +0000857 // Not using Objects.requireNonNull() here for compatibility reasons.
Hai Zhang3b049a52019-08-16 15:37:46 -0700858 if (permName == null || pkgName == null) {
859 return PackageManager.PERMISSION_DENIED;
860 }
861 if (!mUserManagerInt.exists(userId)) {
862 return PackageManager.PERMISSION_DENIED;
863 }
864
Todd Kennedyca1ea172019-07-03 15:02:28 -0700865 final CheckPermissionDelegate checkPermissionDelegate;
866 synchronized (mLock) {
Todd Kennedyca1ea172019-07-03 15:02:28 -0700867 checkPermissionDelegate = mCheckPermissionDelegate;
868 }
Hai Zhang61b4d352019-10-07 13:45:26 -0700869 if (checkPermissionDelegate == null) {
870 return checkPermissionImpl(permName, pkgName, userId);
871 }
Todd Kennedyca1ea172019-07-03 15:02:28 -0700872 return checkPermissionDelegate.checkPermission(permName, pkgName, userId,
Hai Zhang61b4d352019-10-07 13:45:26 -0700873 this::checkPermissionImpl);
Todd Kennedyca1ea172019-07-03 15:02:28 -0700874 }
875
Hai Zhang4fef76a2019-09-28 00:03:50 +0000876 private int checkPermissionImpl(String permName, String pkgName, int userId) {
Winson655a5b92019-10-23 10:49:32 -0700877 final AndroidPackage pkg = mPackageManagerInt.getPackage(pkgName);
Hai Zhang3b049a52019-08-16 15:37:46 -0700878 if (pkg == null) {
Todd Kennedy0eb97382017-10-03 16:57:22 -0700879 return PackageManager.PERMISSION_DENIED;
880 }
Hai Zhang4fef76a2019-09-28 00:03:50 +0000881 return checkPermissionInternal(pkg, true, permName, userId);
Hai Zhang3b049a52019-08-16 15:37:46 -0700882 }
883
Winson655a5b92019-10-23 10:49:32 -0700884 private int checkPermissionInternal(@NonNull AndroidPackage pkg, boolean isPackageExplicit,
Hai Zhang4fef76a2019-09-28 00:03:50 +0000885 @NonNull String permissionName, @UserIdInt int userId) {
Hai Zhang3b049a52019-08-16 15:37:46 -0700886 final int callingUid = getCallingUid();
Winson14ff7172019-10-23 10:42:27 -0700887 if (isPackageExplicit || pkg.getSharedUserId() == null) {
Patrick Baumann97b9b532018-04-11 14:51:30 +0000888 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
Hai Zhang4fef76a2019-09-28 00:03:50 +0000889 return PackageManager.PERMISSION_DENIED;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700890 }
Hai Zhang3b049a52019-08-16 15:37:46 -0700891 } else {
892 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
Hai Zhang4fef76a2019-09-28 00:03:50 +0000893 return PackageManager.PERMISSION_DENIED;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700894 }
895 }
Hai Zhang3b049a52019-08-16 15:37:46 -0700896
Winson14ff7172019-10-23 10:42:27 -0700897 final int uid = UserHandle.getUid(userId, pkg.getUid());
898 final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
899 pkg.getPackageName());
Hai Zhang3b049a52019-08-16 15:37:46 -0700900 if (ps == null) {
Hai Zhang4fef76a2019-09-28 00:03:50 +0000901 return PackageManager.PERMISSION_DENIED;
Hai Zhang3b049a52019-08-16 15:37:46 -0700902 }
903 final PermissionsState permissionsState = ps.getPermissionsState();
904
Hai Zhang4fef76a2019-09-28 00:03:50 +0000905 if (checkSinglePermissionInternal(uid, permissionsState, permissionName)) {
906 return PackageManager.PERMISSION_GRANTED;
Hai Zhang3b049a52019-08-16 15:37:46 -0700907 }
908
909 final String fullerPermissionName = FULLER_PERMISSION_MAP.get(permissionName);
Hai Zhang4fef76a2019-09-28 00:03:50 +0000910 if (fullerPermissionName != null
911 && checkSinglePermissionInternal(uid, permissionsState, fullerPermissionName)) {
912 return PackageManager.PERMISSION_GRANTED;
Hai Zhang3b049a52019-08-16 15:37:46 -0700913 }
914
Hai Zhang4fef76a2019-09-28 00:03:50 +0000915 return PackageManager.PERMISSION_DENIED;
Todd Kennedy0eb97382017-10-03 16:57:22 -0700916 }
917
Hai Zhang3b049a52019-08-16 15:37:46 -0700918 private boolean checkSinglePermissionInternal(int uid,
Hai Zhang4fef76a2019-09-28 00:03:50 +0000919 @NonNull PermissionsState permissionsState, @NonNull String permissionName) {
Hai Zhang61b4d352019-10-07 13:45:26 -0700920 if (!permissionsState.hasPermission(permissionName, UserHandle.getUserId(uid))) {
Hai Zhang3b049a52019-08-16 15:37:46 -0700921 return false;
922 }
923
924 if (mPackageManagerInt.getInstantAppPackageName(uid) != null) {
925 return mSettings.isPermissionInstant(permissionName);
926 }
927
928 return true;
929 }
930
Todd Kennedyca1ea172019-07-03 15:02:28 -0700931 @Override
932 public int checkUidPermission(String permName, int uid) {
Daulet Zhanguzin82adfcb2020-01-02 17:31:40 +0000933 // Not using Objects.requireNonNull() here for compatibility reasons.
Hai Zhang3b049a52019-08-16 15:37:46 -0700934 if (permName == null) {
935 return PackageManager.PERMISSION_DENIED;
936 }
937 final int userId = UserHandle.getUserId(uid);
938 if (!mUserManagerInt.exists(userId)) {
939 return PackageManager.PERMISSION_DENIED;
940 }
941
Todd Kennedyca1ea172019-07-03 15:02:28 -0700942 final CheckPermissionDelegate checkPermissionDelegate;
943 synchronized (mLock) {
Todd Kennedyca1ea172019-07-03 15:02:28 -0700944 checkPermissionDelegate = mCheckPermissionDelegate;
945 }
Hai Zhang61b4d352019-10-07 13:45:26 -0700946 if (checkPermissionDelegate == null) {
947 return checkUidPermissionImpl(permName, uid);
948 }
Todd Kennedyca1ea172019-07-03 15:02:28 -0700949 return checkPermissionDelegate.checkUidPermission(permName, uid,
Hai Zhang61b4d352019-10-07 13:45:26 -0700950 this::checkUidPermissionImpl);
Todd Kennedyca1ea172019-07-03 15:02:28 -0700951 }
952
Hai Zhang4fef76a2019-09-28 00:03:50 +0000953 private int checkUidPermissionImpl(String permName, int uid) {
Winson655a5b92019-10-23 10:49:32 -0700954 final AndroidPackage pkg = mPackageManagerInt.getPackage(uid);
Hai Zhang4fef76a2019-09-28 00:03:50 +0000955 return checkUidPermissionInternal(pkg, uid, permName);
Todd Kennedyca1ea172019-07-03 15:02:28 -0700956 }
957
958 /**
959 * Checks whether or not the given package has been granted the specified
960 * permission. If the given package is {@code null}, we instead check the
961 * system permissions for the given UID.
962 *
963 * @see SystemConfig#getSystemPermissions()
964 */
Winson655a5b92019-10-23 10:49:32 -0700965 private int checkUidPermissionInternal(@Nullable AndroidPackage pkg, int uid,
Hai Zhang4fef76a2019-09-28 00:03:50 +0000966 @NonNull String permissionName) {
Hai Zhang3b049a52019-08-16 15:37:46 -0700967 if (pkg != null) {
968 final int userId = UserHandle.getUserId(uid);
Hai Zhang4fef76a2019-09-28 00:03:50 +0000969 return checkPermissionInternal(pkg, false, permissionName, userId);
Todd Kennedy3bc94722017-10-10 09:55:53 -0700970 }
971
Hai Zhang3b049a52019-08-16 15:37:46 -0700972 if (checkSingleUidPermissionInternal(uid, permissionName)) {
Hai Zhang4fef76a2019-09-28 00:03:50 +0000973 return PackageManager.PERMISSION_GRANTED;
Todd Kennedy3bc94722017-10-10 09:55:53 -0700974 }
Hai Zhang3b049a52019-08-16 15:37:46 -0700975
976 final String fullerPermissionName = FULLER_PERMISSION_MAP.get(permissionName);
977 if (fullerPermissionName != null
978 && checkSingleUidPermissionInternal(uid, fullerPermissionName)) {
Hai Zhang4fef76a2019-09-28 00:03:50 +0000979 return PackageManager.PERMISSION_GRANTED;
Hai Zhang3b049a52019-08-16 15:37:46 -0700980 }
981
Hai Zhang4fef76a2019-09-28 00:03:50 +0000982 return PackageManager.PERMISSION_DENIED;
Todd Kennedy3bc94722017-10-10 09:55:53 -0700983 }
984
Hai Zhang3b049a52019-08-16 15:37:46 -0700985 private boolean checkSingleUidPermissionInternal(int uid, @NonNull String permissionName) {
986 synchronized (mLock) {
987 ArraySet<String> permissions = mSystemPermissions.get(uid);
988 return permissions != null && permissions.contains(permissionName);
989 }
990 }
991
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -0700992 @Override
Michael Groover56a84b22020-03-04 20:41:36 -0800993 public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message,
994 @Nullable String callingFeatureId, int pid, int uid) {
995 // If the check is being requested by an app then only allow the app to query its own
996 // access status.
997 int callingUid = mInjector.getCallingUid();
998 int callingPid = mInjector.getCallingPid();
999 if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID && (callingUid != uid
1000 || callingPid != pid)) {
1001 String response = String.format(
1002 "Calling uid %d, pid %d cannot check device identifier access for package %s "
1003 + "(uid=%d, pid=%d)",
1004 callingUid, callingPid, packageName, uid, pid);
1005 Log.w(TAG, response);
1006 throw new SecurityException(response);
1007 }
1008 // Allow system and root access to the device identifiers.
1009 final int appId = UserHandle.getAppId(uid);
1010 if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) {
1011 return PackageManager.PERMISSION_GRANTED;
1012 }
1013 // Allow access to packages that have the READ_PRIVILEGED_PHONE_STATE permission.
1014 if (mInjector.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid,
1015 uid) == PackageManager.PERMISSION_GRANTED) {
1016 return PackageManager.PERMISSION_GRANTED;
1017 }
1018 // If the calling package is not null then perform the appop and device / profile owner
1019 // check.
1020 if (packageName != null) {
1021 // Allow access to a package that has been granted the READ_DEVICE_IDENTIFIERS appop.
1022 long token = mInjector.clearCallingIdentity();
1023 AppOpsManager appOpsManager = (AppOpsManager) mInjector.getSystemService(
1024 Context.APP_OPS_SERVICE);
1025 try {
1026 if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid,
1027 packageName, callingFeatureId, message) == AppOpsManager.MODE_ALLOWED) {
1028 return PackageManager.PERMISSION_GRANTED;
1029 }
1030 } finally {
1031 mInjector.restoreCallingIdentity(token);
1032 }
1033 // Check if the calling packages meets the device / profile owner requirements for
1034 // identifier access.
1035 DevicePolicyManager devicePolicyManager =
1036 (DevicePolicyManager) mInjector.getSystemService(Context.DEVICE_POLICY_SERVICE);
1037 if (devicePolicyManager != null && devicePolicyManager.hasDeviceIdentifierAccess(
1038 packageName, pid, uid)) {
1039 return PackageManager.PERMISSION_GRANTED;
1040 }
1041 }
1042 return PackageManager.PERMISSION_DENIED;
1043 }
1044
1045 @Override
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001046 public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
1047 mContext.enforceCallingOrSelfPermission(
1048 Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS,
1049 "addOnPermissionsChangeListener");
1050
1051 synchronized (mLock) {
1052 mOnPermissionChangeListeners.addListenerLocked(listener);
1053 }
1054 }
1055
1056 @Override
1057 public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
1058 if (mPackageManagerInt.getInstantAppPackageName(Binder.getCallingUid()) != null) {
1059 throw new SecurityException("Instant applications don't have access to this method");
1060 }
1061 synchronized (mLock) {
1062 mOnPermissionChangeListeners.removeListenerLocked(listener);
1063 }
1064 }
1065
1066 @Override
1067 @Nullable public List<String> getWhitelistedRestrictedPermissions(@NonNull String packageName,
1068 @PermissionWhitelistFlags int flags, @UserIdInt int userId) {
Daulet Zhanguzin82adfcb2020-01-02 17:31:40 +00001069 Objects.requireNonNull(packageName);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001070 Preconditions.checkFlagsArgument(flags,
1071 PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
1072 | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
1073 | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
1074 Preconditions.checkArgumentNonNegative(userId, null);
1075
1076 if (UserHandle.getCallingUserId() != userId) {
1077 mContext.enforceCallingOrSelfPermission(
1078 android.Manifest.permission.INTERACT_ACROSS_USERS,
1079 "getWhitelistedRestrictedPermissions for user " + userId);
1080 }
1081
Winson14ff7172019-10-23 10:42:27 -07001082 final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001083 if (pkg == null) {
1084 return null;
1085 }
1086
1087 final int callingUid = Binder.getCallingUid();
1088 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, UserHandle.getCallingUserId())) {
1089 return null;
1090 }
1091 final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
1092 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
1093 == PackageManager.PERMISSION_GRANTED;
1094 final boolean isCallerInstallerOnRecord =
1095 mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
1096
1097 if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
1098 && !isCallerPrivileged) {
1099 throw new SecurityException("Querying system whitelist requires "
1100 + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1101 }
1102
1103 if ((flags & (PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
1104 | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)) != 0) {
1105 if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
1106 throw new SecurityException("Querying upgrade or installer whitelist"
1107 + " requires being installer on record or "
1108 + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1109 }
1110 }
1111
1112 final long identity = Binder.clearCallingIdentity();
1113 try {
1114 final PermissionsState permissionsState =
Winson14ff7172019-10-23 10:42:27 -07001115 PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001116 if (permissionsState == null) {
1117 return null;
1118 }
1119
1120 int queryFlags = 0;
1121 if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0) {
Nate Myrenc92df182020-06-23 16:31:39 -07001122 queryFlags |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001123 }
1124 if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
Nate Myrenc92df182020-06-23 16:31:39 -07001125 queryFlags |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001126 }
1127 if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
Nate Myrenc92df182020-06-23 16:31:39 -07001128 queryFlags |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001129 }
1130
1131 ArrayList<String> whitelistedPermissions = null;
1132
Winson14ff7172019-10-23 10:42:27 -07001133 final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions());
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001134 for (int i = 0; i < permissionCount; i++) {
Winson14ff7172019-10-23 10:42:27 -07001135 final String permissionName = pkg.getRequestedPermissions().get(i);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001136 final int currentFlags =
1137 permissionsState.getPermissionFlags(permissionName, userId);
1138 if ((currentFlags & queryFlags) != 0) {
1139 if (whitelistedPermissions == null) {
1140 whitelistedPermissions = new ArrayList<>();
1141 }
1142 whitelistedPermissions.add(permissionName);
1143 }
1144 }
1145
1146 return whitelistedPermissions;
1147 } finally {
1148 Binder.restoreCallingIdentity(identity);
1149 }
1150 }
1151
1152 @Override
1153 public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
1154 @NonNull String permName, @PermissionWhitelistFlags int flags,
1155 @UserIdInt int userId) {
1156 // Other argument checks are done in get/setWhitelistedRestrictedPermissions
Daulet Zhanguzin82adfcb2020-01-02 17:31:40 +00001157 Objects.requireNonNull(permName);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001158
1159 if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
1160 return false;
1161 }
1162
1163 List<String> permissions =
1164 getWhitelistedRestrictedPermissions(packageName, flags, userId);
1165 if (permissions == null) {
1166 permissions = new ArrayList<>(1);
1167 }
1168 if (permissions.indexOf(permName) < 0) {
1169 permissions.add(permName);
1170 return setWhitelistedRestrictedPermissionsInternal(packageName, permissions,
1171 flags, userId);
1172 }
1173 return false;
1174 }
1175
1176 private boolean checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(
1177 @NonNull String permName) {
1178 synchronized (mLock) {
1179 final BasePermission bp = mSettings.getPermissionLocked(permName);
1180 if (bp == null) {
1181 Slog.w(TAG, "No such permissions: " + permName);
1182 return false;
1183 }
1184 if (bp.isHardOrSoftRestricted() && bp.isImmutablyRestricted()
1185 && mContext.checkCallingOrSelfPermission(
1186 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
1187 != PackageManager.PERMISSION_GRANTED) {
1188 throw new SecurityException("Cannot modify whitelisting of an immutably "
1189 + "restricted permission: " + permName);
1190 }
1191 return true;
1192 }
1193 }
1194
1195 @Override
1196 public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
1197 @NonNull String permName, @PermissionWhitelistFlags int flags,
1198 @UserIdInt int userId) {
1199 // Other argument checks are done in get/setWhitelistedRestrictedPermissions
Daulet Zhanguzin82adfcb2020-01-02 17:31:40 +00001200 Objects.requireNonNull(permName);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001201
1202 if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
1203 return false;
1204 }
1205
1206 final List<String> permissions =
1207 getWhitelistedRestrictedPermissions(packageName, flags, userId);
1208 if (permissions != null && permissions.remove(permName)) {
1209 return setWhitelistedRestrictedPermissionsInternal(packageName, permissions,
1210 flags, userId);
1211 }
1212 return false;
1213 }
1214
1215 private boolean setWhitelistedRestrictedPermissionsInternal(@NonNull String packageName,
1216 @Nullable List<String> permissions, @PermissionWhitelistFlags int flags,
1217 @UserIdInt int userId) {
Daulet Zhanguzin82adfcb2020-01-02 17:31:40 +00001218 Objects.requireNonNull(packageName);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001219 Preconditions.checkFlagsArgument(flags,
1220 PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
1221 | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
1222 | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
1223 Preconditions.checkArgument(Integer.bitCount(flags) == 1);
1224 Preconditions.checkArgumentNonNegative(userId, null);
1225
1226 if (UserHandle.getCallingUserId() != userId) {
1227 mContext.enforceCallingOrSelfPermission(
1228 Manifest.permission.INTERACT_ACROSS_USERS,
1229 "setWhitelistedRestrictedPermissions for user " + userId);
1230 }
1231
Winson14ff7172019-10-23 10:42:27 -07001232 final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001233 if (pkg == null) {
1234 return false;
1235 }
1236
1237 final int callingUid = Binder.getCallingUid();
1238 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, UserHandle.getCallingUserId())) {
1239 return false;
1240 }
1241
1242 final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
1243 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
1244 == PackageManager.PERMISSION_GRANTED;
1245 final boolean isCallerInstallerOnRecord =
1246 mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
1247
1248 if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
1249 && !isCallerPrivileged) {
1250 throw new SecurityException("Modifying system whitelist requires "
1251 + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1252 }
1253
1254 if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
1255 if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
1256 throw new SecurityException("Modifying upgrade whitelist requires"
1257 + " being installer on record or "
1258 + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1259 }
1260 final List<String> whitelistedPermissions =
Winson14ff7172019-10-23 10:42:27 -07001261 getWhitelistedRestrictedPermissions(pkg.getPackageName(), flags, userId);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001262 if (permissions == null || permissions.isEmpty()) {
1263 if (whitelistedPermissions == null || whitelistedPermissions.isEmpty()) {
1264 return true;
1265 }
1266 } else {
1267 // Only the system can add and remove while the installer can only remove.
1268 final int permissionCount = permissions.size();
1269 for (int i = 0; i < permissionCount; i++) {
1270 if ((whitelistedPermissions == null
1271 || !whitelistedPermissions.contains(permissions.get(i)))
1272 && !isCallerPrivileged) {
1273 throw new SecurityException("Adding to upgrade whitelist requires"
1274 + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1275 }
1276 }
1277 }
1278
1279 if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
1280 if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
1281 throw new SecurityException("Modifying installer whitelist requires"
1282 + " being installer on record or "
1283 + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1284 }
1285 }
1286 }
1287
1288 final long identity = Binder.clearCallingIdentity();
1289 try {
Nate Myrenc92df182020-06-23 16:31:39 -07001290 setWhitelistedRestrictedPermissionsForUsers(pkg, new int[]{ userId }, permissions,
1291 Process.myUid(), flags, mDefaultPermissionCallback);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07001292 } finally {
1293 Binder.restoreCallingIdentity(identity);
1294 }
1295
1296 return true;
1297 }
1298
Todd Kennedyc971a452019-07-08 16:04:52 -07001299 @Override
Eugene Susla922cd082020-03-11 12:38:17 -07001300 public boolean setAutoRevokeWhitelisted(
1301 @NonNull String packageName, boolean whitelisted, int userId) {
1302 Objects.requireNonNull(packageName);
1303
1304 final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
1305 final int callingUid = Binder.getCallingUid();
Eugene Susla64c88c02020-05-07 15:31:23 -07001306 final int packageUid = UserHandle.getUid(userId, pkg.getUid());
Eugene Susla922cd082020-03-11 12:38:17 -07001307
1308 if (!checkAutoRevokeAccess(pkg, callingUid)) {
1309 return false;
1310 }
1311
1312 if (mAppOpsManager
1313 .checkOpNoThrow(AppOpsManager.OP_AUTO_REVOKE_MANAGED_BY_INSTALLER,
Eugene Susla64c88c02020-05-07 15:31:23 -07001314 packageUid, packageName)
Eugene Susla922cd082020-03-11 12:38:17 -07001315 != MODE_ALLOWED) {
1316 // Whitelist user set - don't override
1317 return false;
1318 }
1319
1320 final long identity = Binder.clearCallingIdentity();
1321 try {
1322 mAppOpsManager.setMode(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
Eugene Susla64c88c02020-05-07 15:31:23 -07001323 packageUid, packageName,
Eugene Susla922cd082020-03-11 12:38:17 -07001324 whitelisted ? MODE_IGNORED : MODE_ALLOWED);
1325 } finally {
1326 Binder.restoreCallingIdentity(identity);
1327 }
1328 return true;
1329 }
1330
1331 private boolean checkAutoRevokeAccess(AndroidPackage pkg, int callingUid) {
1332 if (pkg == null) {
1333 return false;
1334 }
1335
1336 final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
1337 Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS)
1338 == PackageManager.PERMISSION_GRANTED;
1339 final boolean isCallerInstallerOnRecord =
1340 mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
1341
1342 if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
1343 throw new SecurityException("Caller must either hold "
1344 + Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS
1345 + " or be the installer on record");
1346 }
1347 return true;
1348 }
1349
1350 @Override
1351 public boolean isAutoRevokeWhitelisted(@NonNull String packageName, int userId) {
1352 Objects.requireNonNull(packageName);
1353
1354 final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
1355 final int callingUid = Binder.getCallingUid();
Eugene Susla64c88c02020-05-07 15:31:23 -07001356 final int packageUid = UserHandle.getUid(userId, pkg.getUid());
Eugene Susla922cd082020-03-11 12:38:17 -07001357
1358 if (!checkAutoRevokeAccess(pkg, callingUid)) {
1359 return false;
1360 }
1361
1362 final long identity = Binder.clearCallingIdentity();
1363 try {
1364 return mAppOpsManager.checkOpNoThrow(
Eugene Susla64c88c02020-05-07 15:31:23 -07001365 AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageUid, packageName)
Eugene Susla922cd082020-03-11 12:38:17 -07001366 == MODE_IGNORED;
1367 } finally {
1368 Binder.restoreCallingIdentity(identity);
1369 }
1370 }
1371
1372 @Override
Todd Kennedyc971a452019-07-08 16:04:52 -07001373 public void grantRuntimePermission(String packageName, String permName, final int userId) {
1374 final int callingUid = Binder.getCallingUid();
1375 final boolean overridePolicy =
1376 checkUidPermission(ADJUST_RUNTIME_PERMISSIONS_POLICY, callingUid)
1377 == PackageManager.PERMISSION_GRANTED;
1378
1379 grantRuntimePermissionInternal(permName, packageName, overridePolicy,
1380 callingUid, userId, mDefaultPermissionCallback);
1381 }
1382
1383 // TODO swap permission name and package name
1384 private void grantRuntimePermissionInternal(String permName, String packageName,
1385 boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) {
1386 if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
1387 && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
Eugene Suslacb923e32019-08-20 16:48:55 -07001388 Log.i(TAG, "System is granting " + packageName + " "
Todd Kennedyc971a452019-07-08 16:04:52 -07001389 + permName + " for user " + userId + " on behalf of uid " + callingUid
1390 + " " + mPackageManagerInt.getNameForUid(callingUid),
1391 new RuntimeException());
1392 }
1393 if (!mUserManagerInt.exists(userId)) {
1394 Log.e(TAG, "No such user:" + userId);
1395 return;
1396 }
1397
1398 mContext.enforceCallingOrSelfPermission(
1399 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
1400 "grantRuntimePermission");
1401
1402 enforceCrossUserPermission(callingUid, userId,
1403 true, // requireFullPermission
1404 true, // checkShell
1405 false, // requirePermissionWhenSameUser
1406 "grantRuntimePermission");
1407
Winson14ff7172019-10-23 10:42:27 -07001408 final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
1409 final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
1410 packageName);
1411 if (pkg == null || ps == null) {
Hai Zhangb94491c2019-07-31 14:07:17 -07001412 Log.e(TAG, "Unknown package: " + packageName);
1413 return;
Todd Kennedyc971a452019-07-08 16:04:52 -07001414 }
1415 final BasePermission bp;
1416 synchronized (mLock) {
1417 bp = mSettings.getPermissionLocked(permName);
1418 }
1419 if (bp == null) {
1420 throw new IllegalArgumentException("Unknown permission: " + permName);
1421 }
1422 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
1423 throw new IllegalArgumentException("Unknown package: " + packageName);
1424 }
1425
Winson14ff7172019-10-23 10:42:27 -07001426 bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, ps);
Todd Kennedyc971a452019-07-08 16:04:52 -07001427
1428 // If a permission review is required for legacy apps we represent
1429 // their permissions as always granted runtime ones since we need
1430 // to keep the review required permission flag per user while an
1431 // install permission's state is shared across all users.
Winson14ff7172019-10-23 10:42:27 -07001432 if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M
Todd Kennedyc971a452019-07-08 16:04:52 -07001433 && bp.isRuntime()) {
1434 return;
1435 }
1436
Winson14ff7172019-10-23 10:42:27 -07001437 final int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid()));
Todd Kennedyc971a452019-07-08 16:04:52 -07001438
Todd Kennedyc971a452019-07-08 16:04:52 -07001439 final PermissionsState permissionsState = ps.getPermissionsState();
1440
1441 final int flags = permissionsState.getPermissionFlags(permName, userId);
1442 if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
1443 Log.e(TAG, "Cannot grant system fixed permission "
1444 + permName + " for package " + packageName);
1445 return;
1446 }
1447 if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
1448 Log.e(TAG, "Cannot grant policy fixed permission "
1449 + permName + " for package " + packageName);
1450 return;
1451 }
1452
1453 if (bp.isHardRestricted()
1454 && (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
1455 Log.e(TAG, "Cannot grant hard restricted non-exempt permission "
1456 + permName + " for package " + packageName);
1457 return;
1458 }
1459
1460 if (bp.isSoftRestricted() && !SoftRestrictedPermissionPolicy.forPermission(mContext,
Winson33eacc62020-01-24 12:02:58 -08001461 pkg.toAppInfoWithoutState(), pkg, UserHandle.of(userId), permName)
Winson6571c8a2019-10-23 17:00:42 -07001462 .mayGrantPermission()) {
Todd Kennedyc971a452019-07-08 16:04:52 -07001463 Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
1464 + packageName);
1465 return;
1466 }
1467
1468 if (bp.isDevelopment()) {
1469 // Development permissions must be handled specially, since they are not
1470 // normal runtime permissions. For now they apply to all users.
1471 if (permissionsState.grantInstallPermission(bp)
1472 != PERMISSION_OPERATION_FAILURE) {
1473 if (callback != null) {
1474 callback.onInstallPermissionGranted();
1475 }
1476 }
1477 return;
1478 }
1479
1480 if (ps.getInstantApp(userId) && !bp.isInstant()) {
1481 throw new SecurityException("Cannot grant non-ephemeral permission"
1482 + permName + " for package " + packageName);
1483 }
1484
Winson14ff7172019-10-23 10:42:27 -07001485 if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) {
Todd Kennedyc971a452019-07-08 16:04:52 -07001486 Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
1487 return;
1488 }
1489
1490 final int result = permissionsState.grantRuntimePermission(bp, userId);
1491 switch (result) {
1492 case PERMISSION_OPERATION_FAILURE: {
1493 return;
1494 }
1495
1496 case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
1497 if (callback != null) {
Winson14ff7172019-10-23 10:42:27 -07001498 callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
Todd Kennedyc971a452019-07-08 16:04:52 -07001499 }
1500 }
1501 break;
1502 }
1503
1504 if (bp.isRuntime()) {
1505 logPermission(MetricsEvent.ACTION_PERMISSION_GRANTED, permName, packageName);
1506 }
1507
1508 if (callback != null) {
1509 callback.onPermissionGranted(uid, userId);
1510 }
1511
1512 if (bp.isRuntime()) {
1513 notifyRuntimePermissionStateChanged(packageName, userId);
1514 }
1515
1516 // Only need to do this if user is initialized. Otherwise it's a new user
1517 // and there are no processes running as the user yet and there's no need
1518 // to make an expensive call to remount processes for the changed permissions.
1519 if (READ_EXTERNAL_STORAGE.equals(permName)
1520 || WRITE_EXTERNAL_STORAGE.equals(permName)) {
1521 final long token = Binder.clearCallingIdentity();
1522 try {
1523 if (mUserManagerInt.isUserInitialized(userId)) {
1524 StorageManagerInternal storageManagerInternal = LocalServices.getService(
1525 StorageManagerInternal.class);
1526 storageManagerInternal.onExternalStoragePolicyChanged(uid, packageName);
1527 }
1528 } finally {
1529 Binder.restoreCallingIdentity(token);
1530 }
1531 }
1532
1533 }
1534
1535 @Override
Evan Seversonaacd48b2020-06-22 16:45:03 -07001536 public void revokeRuntimePermission(String packageName, String permName, int userId,
1537 String reason) {
Todd Kennedyc971a452019-07-08 16:04:52 -07001538 final int callingUid = Binder.getCallingUid();
1539 final boolean overridePolicy =
1540 checkUidPermission(ADJUST_RUNTIME_PERMISSIONS_POLICY, callingUid)
1541 == PackageManager.PERMISSION_GRANTED;
1542
1543 revokeRuntimePermissionInternal(permName, packageName, overridePolicy, callingUid, userId,
Evan Seversonaacd48b2020-06-22 16:45:03 -07001544 reason, mDefaultPermissionCallback);
Todd Kennedyc971a452019-07-08 16:04:52 -07001545 }
1546
1547 // TODO swap permission name and package name
1548 private void revokeRuntimePermissionInternal(String permName, String packageName,
Evan Seversonaacd48b2020-06-22 16:45:03 -07001549 boolean overridePolicy, int callingUid, final int userId, String reason,
1550 PermissionCallback callback) {
Eugene Suslacb923e32019-08-20 16:48:55 -07001551 if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES
Todd Kennedyc971a452019-07-08 16:04:52 -07001552 && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
Eugene Suslacb923e32019-08-20 16:48:55 -07001553 Log.i(TAG, "System is revoking " + packageName + " "
Todd Kennedyc971a452019-07-08 16:04:52 -07001554 + permName + " for user " + userId + " on behalf of uid " + callingUid
1555 + " " + mPackageManagerInt.getNameForUid(callingUid),
1556 new RuntimeException());
1557 }
1558 if (!mUserManagerInt.exists(userId)) {
1559 Log.e(TAG, "No such user:" + userId);
1560 return;
1561 }
1562
1563 mContext.enforceCallingOrSelfPermission(
1564 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
1565 "revokeRuntimePermission");
1566
1567 enforceCrossUserPermission(callingUid, userId,
1568 true, // requireFullPermission
1569 true, // checkShell
1570 false, // requirePermissionWhenSameUser
1571 "revokeRuntimePermission");
1572
Winson14ff7172019-10-23 10:42:27 -07001573 final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
1574 final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
1575 packageName);
1576 if (pkg == null || ps == null) {
Hai Zhangb94491c2019-07-31 14:07:17 -07001577 Log.e(TAG, "Unknown package: " + packageName);
1578 return;
Todd Kennedyc971a452019-07-08 16:04:52 -07001579 }
1580 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
1581 throw new IllegalArgumentException("Unknown package: " + packageName);
1582 }
1583 final BasePermission bp = mSettings.getPermissionLocked(permName);
1584 if (bp == null) {
1585 throw new IllegalArgumentException("Unknown permission: " + permName);
1586 }
1587
Winson14ff7172019-10-23 10:42:27 -07001588 bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, ps);
Todd Kennedyc971a452019-07-08 16:04:52 -07001589
1590 // If a permission review is required for legacy apps we represent
1591 // their permissions as always granted runtime ones since we need
1592 // to keep the review required permission flag per user while an
1593 // install permission's state is shared across all users.
Winson14ff7172019-10-23 10:42:27 -07001594 if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M
Todd Kennedyc971a452019-07-08 16:04:52 -07001595 && bp.isRuntime()) {
1596 return;
1597 }
1598
Todd Kennedyc971a452019-07-08 16:04:52 -07001599 final PermissionsState permissionsState = ps.getPermissionsState();
1600
1601 final int flags = permissionsState.getPermissionFlags(permName, userId);
1602 // Only the system may revoke SYSTEM_FIXED permissions.
1603 if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
1604 && UserHandle.getCallingAppId() != Process.SYSTEM_UID) {
1605 throw new SecurityException("Non-System UID cannot revoke system fixed permission "
1606 + permName + " for package " + packageName);
1607 }
1608 if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
1609 throw new SecurityException("Cannot revoke policy fixed permission "
1610 + permName + " for package " + packageName);
1611 }
1612
1613 if (bp.isDevelopment()) {
1614 // Development permissions must be handled specially, since they are not
1615 // normal runtime permissions. For now they apply to all users.
1616 if (permissionsState.revokeInstallPermission(bp)
1617 != PERMISSION_OPERATION_FAILURE) {
1618 if (callback != null) {
1619 mDefaultPermissionCallback.onInstallPermissionRevoked();
1620 }
1621 }
1622 return;
1623 }
1624
1625 // Permission is already revoked, no need to do anything.
1626 if (!permissionsState.hasRuntimePermission(permName, userId)) {
1627 return;
1628 }
1629
1630 if (permissionsState.revokeRuntimePermission(bp, userId)
1631 == PERMISSION_OPERATION_FAILURE) {
1632 return;
1633 }
1634
1635 if (bp.isRuntime()) {
1636 logPermission(MetricsEvent.ACTION_PERMISSION_REVOKED, permName, packageName);
1637 }
1638
1639 if (callback != null) {
Nate Myren8f6a9092019-08-27 15:50:03 -07001640 callback.onPermissionRevoked(UserHandle.getUid(userId,
Evan Seversonaacd48b2020-06-22 16:45:03 -07001641 UserHandle.getAppId(pkg.getUid())), userId, reason);
Todd Kennedyc971a452019-07-08 16:04:52 -07001642 }
1643
1644 if (bp.isRuntime()) {
1645 notifyRuntimePermissionStateChanged(packageName, userId);
1646 }
1647 }
1648
1649 @Override
1650 public void resetRuntimePermissions() {
1651 mContext.enforceCallingOrSelfPermission(
1652 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
1653 "revokeRuntimePermission");
1654
1655 final int callingUid = Binder.getCallingUid();
1656 if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
1657 mContext.enforceCallingOrSelfPermission(
1658 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1659 "resetRuntimePermissions");
1660 }
1661
1662 updateAllPermissions(
1663 StorageManager.UUID_PRIVATE_INTERNAL, false, mDefaultPermissionCallback);
1664 for (final int userId : UserManagerService.getInstance().getUserIds()) {
1665 mPackageManagerInt.forEachPackage(
Winson14ff7172019-10-23 10:42:27 -07001666 (AndroidPackage pkg) -> resetRuntimePermissionsInternal(pkg, userId));
Todd Kennedyc971a452019-07-08 16:04:52 -07001667 }
1668 }
1669
1670 /**
1671 * Reverts user permission state changes (permissions and flags).
1672 *
Hai Zhang4ffebb72019-07-18 14:50:58 -07001673 * @param pkg The package for which to reset.
Todd Kennedyc971a452019-07-08 16:04:52 -07001674 * @param userId The device user for which to do a reset.
1675 */
Patrick Baumann865fd3a2019-07-26 14:53:02 -07001676 @GuardedBy("mLock")
Winson14ff7172019-10-23 10:42:27 -07001677 private void resetRuntimePermissionsInternal(final AndroidPackage pkg,
Todd Kennedyc971a452019-07-08 16:04:52 -07001678 final int userId) {
Winson14ff7172019-10-23 10:42:27 -07001679 final String packageName = pkg.getPackageName();
Todd Kennedyc971a452019-07-08 16:04:52 -07001680
1681 // These are flags that can change base on user actions.
1682 final int userSettableMask = FLAG_PERMISSION_USER_SET
1683 | FLAG_PERMISSION_USER_FIXED
Hai Zhang50a5a9b2019-09-19 13:57:45 -07001684 | FLAG_PERMISSION_REVOKED_COMPAT
Evan Seversonf21a09a2020-03-19 10:54:51 -07001685 | FLAG_PERMISSION_REVIEW_REQUIRED
1686 | FLAG_PERMISSION_ONE_TIME;
Todd Kennedyc971a452019-07-08 16:04:52 -07001687
1688 final int policyOrSystemFlags = FLAG_PERMISSION_SYSTEM_FIXED
1689 | FLAG_PERMISSION_POLICY_FIXED;
1690
1691 // Delay and combine non-async permission callbacks
Winson14ff7172019-10-23 10:42:27 -07001692 final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions());
Todd Kennedyc971a452019-07-08 16:04:52 -07001693 final boolean[] permissionRemoved = new boolean[1];
1694 final ArraySet<Long> revokedPermissions = new ArraySet<>();
1695 final IntArray syncUpdatedUsers = new IntArray(permissionCount);
1696 final IntArray asyncUpdatedUsers = new IntArray(permissionCount);
1697
1698 PermissionCallback delayingPermCallback = new PermissionCallback() {
1699 public void onGidsChanged(int appId, int userId) {
1700 mDefaultPermissionCallback.onGidsChanged(appId, userId);
1701 }
1702
1703 public void onPermissionChanged() {
1704 mDefaultPermissionCallback.onPermissionChanged();
1705 }
1706
1707 public void onPermissionGranted(int uid, int userId) {
1708 mDefaultPermissionCallback.onPermissionGranted(uid, userId);
1709 }
1710
1711 public void onInstallPermissionGranted() {
1712 mDefaultPermissionCallback.onInstallPermissionGranted();
1713 }
1714
Evan Seversonaacd48b2020-06-22 16:45:03 -07001715 public void onPermissionRevoked(int uid, int userId, String reason) {
Todd Kennedyc971a452019-07-08 16:04:52 -07001716 revokedPermissions.add(IntPair.of(uid, userId));
1717
1718 syncUpdatedUsers.add(userId);
1719 }
1720
1721 public void onInstallPermissionRevoked() {
1722 mDefaultPermissionCallback.onInstallPermissionRevoked();
1723 }
1724
1725 public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
1726 for (int userId : updatedUserIds) {
1727 if (sync) {
1728 syncUpdatedUsers.add(userId);
1729 asyncUpdatedUsers.remove(userId);
1730 } else {
1731 // Don't override sync=true by sync=false
1732 if (syncUpdatedUsers.indexOf(userId) == -1) {
1733 asyncUpdatedUsers.add(userId);
1734 }
1735 }
1736 }
1737 }
1738
1739 public void onPermissionRemoved() {
1740 permissionRemoved[0] = true;
1741 }
1742
1743 public void onInstallPermissionUpdated() {
1744 mDefaultPermissionCallback.onInstallPermissionUpdated();
1745 }
Nate Myrencc9e2c72019-11-08 14:57:15 -08001746
1747 public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds,
1748 boolean sync, int uid) {
1749 onPermissionUpdated(updatedUserIds, sync);
1750 mOnPermissionChangeListeners.onPermissionsChanged(uid);
1751 }
1752
1753 public void onInstallPermissionUpdatedNotifyListener(int uid) {
1754 mDefaultPermissionCallback.onInstallPermissionUpdatedNotifyListener(uid);
1755 }
Todd Kennedyc971a452019-07-08 16:04:52 -07001756 };
1757
1758 for (int i = 0; i < permissionCount; i++) {
Winson14ff7172019-10-23 10:42:27 -07001759 final String permName = pkg.getRequestedPermissions().get(i);
Todd Kennedyc971a452019-07-08 16:04:52 -07001760 final BasePermission bp;
1761 synchronized (mLock) {
1762 bp = mSettings.getPermissionLocked(permName);
1763 }
1764 if (bp == null) {
1765 continue;
1766 }
1767
1768 if (bp.isRemoved()) {
1769 continue;
1770 }
1771
1772 // If shared user we just reset the state to which only this app contributed.
Alan Stokes20fbef22019-12-17 15:33:12 +00001773 final String[] pkgNames = mPackageManagerInt.getSharedUserPackagesForPackage(
1774 pkg.getPackageName(), userId);
1775 if (pkgNames.length > 0) {
Todd Kennedyc971a452019-07-08 16:04:52 -07001776 boolean used = false;
Alan Stokes20fbef22019-12-17 15:33:12 +00001777 for (String sharedPkgName : pkgNames) {
Winson14ff7172019-10-23 10:42:27 -07001778 final AndroidPackage sharedPkg =
Todd Kennedyc971a452019-07-08 16:04:52 -07001779 mPackageManagerInt.getPackage(sharedPkgName);
Winson14ff7172019-10-23 10:42:27 -07001780 if (sharedPkg != null && !sharedPkg.getPackageName().equals(packageName)
1781 && sharedPkg.getRequestedPermissions().contains(permName)) {
Todd Kennedyc971a452019-07-08 16:04:52 -07001782 used = true;
1783 break;
1784 }
1785 }
1786 if (used) {
1787 continue;
1788 }
1789 }
1790
1791 final int oldFlags =
1792 getPermissionFlagsInternal(permName, packageName, Process.SYSTEM_UID, userId);
1793
1794 // Always clear the user settable flags.
1795 // If permission review is enabled and this is a legacy app, mark the
1796 // permission as requiring a review as this is the initial state.
1797 final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
Hai Zhang053c3a22019-08-23 15:08:03 -07001798 final int targetSdk = mPackageManagerInt.getUidTargetSdkVersion(uid);
Todd Kennedyc971a452019-07-08 16:04:52 -07001799 final int flags = (targetSdk < Build.VERSION_CODES.M && bp.isRuntime())
Hai Zhang50a5a9b2019-09-19 13:57:45 -07001800 ? FLAG_PERMISSION_REVIEW_REQUIRED | FLAG_PERMISSION_REVOKED_COMPAT
Todd Kennedyc971a452019-07-08 16:04:52 -07001801 : 0;
1802
1803 updatePermissionFlagsInternal(
1804 permName, packageName, userSettableMask, flags, Process.SYSTEM_UID, userId,
1805 false, delayingPermCallback);
1806
1807 // Below is only runtime permission handling.
1808 if (!bp.isRuntime()) {
1809 continue;
1810 }
1811
1812 // Never clobber system or policy.
1813 if ((oldFlags & policyOrSystemFlags) != 0) {
1814 continue;
1815 }
1816
Hai Zhang253fa2b2020-06-02 14:07:23 -07001817 // If this permission was granted by default or role, make sure it is.
1818 if ((oldFlags & FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0
1819 || (oldFlags & FLAG_PERMISSION_GRANTED_BY_ROLE) != 0) {
Hai Zhangab6a6822019-10-18 00:34:06 +00001820 // PermissionPolicyService will handle the app op for runtime permissions later.
Todd Kennedyc971a452019-07-08 16:04:52 -07001821 grantRuntimePermissionInternal(permName, packageName, false,
1822 Process.SYSTEM_UID, userId, delayingPermCallback);
1823 // If permission review is enabled the permissions for a legacy apps
1824 // are represented as constantly granted runtime ones, so don't revoke.
1825 } else if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
1826 // Otherwise, reset the permission.
1827 revokeRuntimePermissionInternal(permName, packageName, false, Process.SYSTEM_UID,
Evan Seversonaacd48b2020-06-22 16:45:03 -07001828 userId, null, delayingPermCallback);
Todd Kennedyc971a452019-07-08 16:04:52 -07001829 }
1830 }
1831
1832 // Execute delayed callbacks
1833 if (permissionRemoved[0]) {
1834 mDefaultPermissionCallback.onPermissionRemoved();
1835 }
1836
1837 // Slight variation on the code in mPermissionCallback.onPermissionRevoked() as we cannot
1838 // kill uid while holding mPackages-lock
1839 if (!revokedPermissions.isEmpty()) {
1840 int numRevokedPermissions = revokedPermissions.size();
1841 for (int i = 0; i < numRevokedPermissions; i++) {
1842 int revocationUID = IntPair.first(revokedPermissions.valueAt(i));
1843 int revocationUserId = IntPair.second(revokedPermissions.valueAt(i));
1844
1845 mOnPermissionChangeListeners.onPermissionsChanged(revocationUID);
1846
1847 // Kill app later as we are holding mPackages
1848 mHandler.post(() -> killUid(UserHandle.getAppId(revocationUID), revocationUserId,
1849 KILL_APP_REASON_PERMISSIONS_REVOKED));
1850 }
1851 }
1852
1853 mPackageManagerInt.writePermissionSettings(syncUpdatedUsers.toArray(), false);
1854 mPackageManagerInt.writePermissionSettings(asyncUpdatedUsers.toArray(), true);
1855 }
1856
Todd Kennedy583378d2019-07-12 06:50:30 -07001857 @Override
1858 public String getDefaultBrowser(int userId) {
1859 final int callingUid = Binder.getCallingUid();
1860 if (UserHandle.getUserId(callingUid) != userId) {
1861 mContext.enforceCallingOrSelfPermission(
1862 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
1863 }
1864 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
1865 return null;
1866 }
Hai Zhang109ff9d2019-09-24 17:18:05 -07001867 DefaultBrowserProvider provider;
Todd Kennedy583378d2019-07-12 06:50:30 -07001868 synchronized (mLock) {
Hai Zhang109ff9d2019-09-24 17:18:05 -07001869 provider = mDefaultBrowserProvider;
Todd Kennedy583378d2019-07-12 06:50:30 -07001870 }
Hai Zhang109ff9d2019-09-24 17:18:05 -07001871 return provider != null ? provider.getDefaultBrowser(userId) : null;
Todd Kennedy583378d2019-07-12 06:50:30 -07001872 }
1873
1874 @Override
1875 public boolean setDefaultBrowser(String packageName, int userId) {
1876 mContext.enforceCallingOrSelfPermission(
1877 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
1878 if (UserHandle.getCallingUserId() != userId) {
1879 mContext.enforceCallingOrSelfPermission(
1880 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
1881 }
1882 return setDefaultBrowserInternal(packageName, false, true, userId);
1883 }
1884
1885 private boolean setDefaultBrowserInternal(String packageName, boolean async,
1886 boolean doGrant, int userId) {
Hai Zhang109ff9d2019-09-24 17:18:05 -07001887 if (userId == UserHandle.USER_ALL) {
1888 return false;
1889 }
1890 DefaultBrowserProvider provider;
Todd Kennedy583378d2019-07-12 06:50:30 -07001891 synchronized (mLock) {
Hai Zhang109ff9d2019-09-24 17:18:05 -07001892 provider = mDefaultBrowserProvider;
1893 }
1894 if (provider == null) {
1895 return false;
1896 }
1897 if (async) {
1898 provider.setDefaultBrowserAsync(packageName, userId);
1899 } else {
1900 if (!provider.setDefaultBrowser(packageName, userId)) {
Todd Kennedy583378d2019-07-12 06:50:30 -07001901 return false;
1902 }
Hai Zhang109ff9d2019-09-24 17:18:05 -07001903 }
1904 if (doGrant && packageName != null) {
1905 synchronized (mLock) {
1906 mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultBrowser(packageName,
1907 userId);
Todd Kennedy583378d2019-07-12 06:50:30 -07001908 }
1909 }
1910 return true;
1911 }
1912
1913 @Override
1914 public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) {
1915 final int callingUid = Binder.getCallingUid();
1916 PackageManagerServiceUtils
1917 .enforceSystemOrPhoneCaller("grantPermissionsToEnabledCarrierApps", callingUid);
1918 synchronized (mLock) {
1919 Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
1920 .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId));
1921 }
1922 }
1923
1924 @Override
1925 public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId) {
1926 final int callingUid = Binder.getCallingUid();
1927 PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
1928 "grantDefaultPermissionsToEnabledImsServices", callingUid);
1929 synchronized (mLock) {
1930 Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
1931 .grantDefaultPermissionsToEnabledImsServices(packageNames, userId));
1932 }
1933 }
1934
1935 @Override
1936 public void grantDefaultPermissionsToEnabledTelephonyDataServices(
1937 String[] packageNames, int userId) {
1938 final int callingUid = Binder.getCallingUid();
1939 PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
1940 "grantDefaultPermissionsToEnabledTelephonyDataServices", callingUid);
1941 synchronized (mLock) {
1942 Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
1943 .grantDefaultPermissionsToEnabledTelephonyDataServices(
1944 packageNames, userId));
1945 }
1946 }
1947
1948 @Override
1949 public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
1950 String[] packageNames, int userId) {
1951 final int callingUid = Binder.getCallingUid();
1952 PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
1953 "revokeDefaultPermissionsFromDisabledTelephonyDataServices", callingUid);
1954 synchronized (mLock) {
1955 Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
1956 .revokeDefaultPermissionsFromDisabledTelephonyDataServices(
1957 packageNames, userId));
1958 }
1959 }
1960
1961 @Override
1962 public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
1963 final int callingUid = Binder.getCallingUid();
1964 PackageManagerServiceUtils
1965 .enforceSystemOrPhoneCaller("grantDefaultPermissionsToActiveLuiApp", callingUid);
1966 synchronized (mLock) {
1967 Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
1968 .grantDefaultPermissionsToActiveLuiApp(packageName, userId));
1969 }
1970 }
1971
1972 @Override
1973 public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
1974 final int callingUid = Binder.getCallingUid();
1975 PackageManagerServiceUtils
1976 .enforceSystemOrPhoneCaller("revokeDefaultPermissionsFromLuiApps", callingUid);
1977 synchronized (mLock) {
1978 Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
1979 .revokeDefaultPermissionsFromLuiApps(packageNames, userId));
1980 }
1981 }
1982
Todd Kennedyc5b0e862019-07-16 09:47:58 -07001983 @Override
1984 public void setPermissionEnforced(String permName, boolean enforced) {
1985 // TODO: Now that we no longer change GID for storage, this should to away.
1986 mContext.enforceCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
1987 "setPermissionEnforced");
1988 if (READ_EXTERNAL_STORAGE.equals(permName)) {
1989 mPackageManagerInt.setReadExternalStorageEnforced(enforced);
1990 // kill any non-foreground processes so we restart them and
1991 // grant/revoke the GID.
1992 final IActivityManager am = ActivityManager.getService();
1993 if (am != null) {
1994 final long token = Binder.clearCallingIdentity();
1995 try {
1996 am.killProcessesBelowForeground("setPermissionEnforcement");
1997 } catch (RemoteException e) {
1998 } finally {
1999 Binder.restoreCallingIdentity(token);
2000 }
2001 }
2002 } else {
2003 throw new IllegalArgumentException("No selective enforcement for " + permName);
2004 }
2005 }
2006
2007 /** @deprecated */
2008 @Override
2009 @Deprecated
2010 public boolean isPermissionEnforced(String permName) {
2011 // allow instant applications
2012 return true;
2013 }
2014
Evan Severson50a77742020-01-06 10:38:19 -08002015 /**
2016 * This change makes it so that apps are told to show rationale for asking for background
2017 * location access every time they request.
2018 */
2019 @ChangeId
2020 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
2021 private static final long BACKGROUND_RATIONALE_CHANGE_ID = 147316723L;
2022
Todd Kennedyc5b0e862019-07-16 09:47:58 -07002023 @Override
2024 public boolean shouldShowRequestPermissionRationale(String permName,
2025 String packageName, int userId) {
2026 final int callingUid = Binder.getCallingUid();
2027 if (UserHandle.getCallingUserId() != userId) {
2028 mContext.enforceCallingPermission(
2029 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
2030 "canShowRequestPermissionRationale for user " + userId);
2031 }
2032
2033 final int uid =
2034 mPackageManagerInt.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId);
2035 if (UserHandle.getAppId(callingUid) != UserHandle.getAppId(uid)) {
2036 return false;
2037 }
2038
2039 if (checkPermission(permName, packageName, userId)
2040 == PackageManager.PERMISSION_GRANTED) {
2041 return false;
2042 }
2043
2044 final int flags;
2045
2046 final long identity = Binder.clearCallingIdentity();
2047 try {
2048 flags = getPermissionFlagsInternal(permName, packageName, callingUid, userId);
2049 } finally {
2050 Binder.restoreCallingIdentity(identity);
2051 }
2052
2053 final int fixedFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
2054 | PackageManager.FLAG_PERMISSION_POLICY_FIXED
2055 | PackageManager.FLAG_PERMISSION_USER_FIXED;
2056
2057 if ((flags & fixedFlags) != 0) {
2058 return false;
2059 }
2060
atrost24274272020-02-17 19:26:41 +00002061 final long token = Binder.clearCallingIdentity();
Evan Severson50a77742020-01-06 10:38:19 -08002062 try {
2063 if (permName.equals(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
2064 && mPlatformCompat.isChangeEnabledByPackageName(BACKGROUND_RATIONALE_CHANGE_ID,
2065 packageName, userId)) {
2066 return true;
2067 }
2068 } catch (RemoteException e) {
2069 Log.e(TAG, "Unable to check if compatibility change is enabled.", e);
atrost24274272020-02-17 19:26:41 +00002070 } finally {
2071 Binder.restoreCallingIdentity(token);
Evan Severson50a77742020-01-06 10:38:19 -08002072 }
2073
Todd Kennedyc5b0e862019-07-16 09:47:58 -07002074 return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0;
2075 }
2076
2077 @Override
2078 public boolean isPermissionRevokedByPolicy(String permName, String packageName, int userId) {
2079 if (UserHandle.getCallingUserId() != userId) {
2080 mContext.enforceCallingPermission(
2081 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
2082 "isPermissionRevokedByPolicy for user " + userId);
2083 }
2084
2085 if (checkPermission(permName, packageName, userId) == PackageManager.PERMISSION_GRANTED) {
2086 return false;
2087 }
2088
2089 final int callingUid = Binder.getCallingUid();
2090 if (mPackageManagerInt.filterAppAccess(packageName, callingUid, userId)) {
2091 return false;
2092 }
2093
2094 final long identity = Binder.clearCallingIdentity();
2095 try {
2096 final int flags = getPermissionFlagsInternal(permName, packageName, callingUid, userId);
2097 return (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0;
2098 } finally {
2099 Binder.restoreCallingIdentity(identity);
2100 }
2101 }
2102
Hongwei Wangf391b552018-04-06 13:52:46 -07002103 /**
Philip P. Moltmann48456672019-01-20 13:14:03 -08002104 * Get the state of the runtime permissions as xml file.
2105 *
2106 * <p>Can not be called on main thread.
2107 *
2108 * @param user The user the data should be extracted for
2109 *
2110 * @return The state as a xml file
2111 */
2112 private @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user) {
2113 CompletableFuture<byte[]> backup = new CompletableFuture<>();
2114 mPermissionControllerManager.getRuntimePermissionBackup(user, mContext.getMainExecutor(),
2115 backup::complete);
2116
2117 try {
2118 return backup.get(BACKUP_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
2119 } catch (InterruptedException | ExecutionException | TimeoutException e) {
2120 Slog.e(TAG, "Cannot create permission backup for " + user, e);
2121 return null;
2122 }
2123 }
2124
2125 /**
2126 * Restore a permission state previously backed up via {@link #backupRuntimePermissions}.
2127 *
2128 * <p>If not all state can be restored, the un-appliable state will be delayed and can be
2129 * applied via {@link #restoreDelayedRuntimePermissions}.
2130 *
2131 * @param backup The state as an xml file
2132 * @param user The user the data should be restored for
2133 */
2134 private void restoreRuntimePermissions(@NonNull byte[] backup, @NonNull UserHandle user) {
2135 synchronized (mLock) {
2136 mHasNoDelayedPermBackup.delete(user.getIdentifier());
Philip P. Moltmann4a6c5de2019-09-13 11:15:44 -07002137 mPermissionControllerManager.stageAndApplyRuntimePermissionsBackup(backup, user);
Philip P. Moltmann48456672019-01-20 13:14:03 -08002138 }
2139 }
2140
2141 /**
2142 * Try to apply permission backup that was previously not applied.
2143 *
2144 * <p>Can not be called on main thread.
2145 *
2146 * @param packageName The package that is newly installed
2147 * @param user The user the package is installed for
2148 *
2149 * @see #restoreRuntimePermissions
2150 */
2151 private void restoreDelayedRuntimePermissions(@NonNull String packageName,
2152 @NonNull UserHandle user) {
2153 synchronized (mLock) {
2154 if (mHasNoDelayedPermBackup.get(user.getIdentifier(), false)) {
2155 return;
2156 }
2157
Philip P. Moltmann4a6c5de2019-09-13 11:15:44 -07002158 mPermissionControllerManager.applyStagedRuntimePermissionBackup(packageName, user,
Philip P. Moltmann48456672019-01-20 13:14:03 -08002159 mContext.getMainExecutor(), (hasMoreBackup) -> {
2160 if (hasMoreBackup) {
2161 return;
2162 }
2163
2164 synchronized (mLock) {
2165 mHasNoDelayedPermBackup.put(user.getIdentifier(), true);
2166 }
2167 });
2168 }
2169 }
2170
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002171 private void addOnRuntimePermissionStateChangedListener(@NonNull
2172 OnRuntimePermissionStateChangedListener listener) {
2173 synchronized (mLock) {
2174 mRuntimePermissionStateChangedListeners.add(listener);
2175 }
2176 }
2177
2178 private void removeOnRuntimePermissionStateChangedListener(@NonNull
2179 OnRuntimePermissionStateChangedListener listener) {
2180 synchronized (mLock) {
2181 mRuntimePermissionStateChangedListeners.remove(listener);
2182 }
2183 }
2184
2185 private void notifyRuntimePermissionStateChanged(@NonNull String packageName,
2186 @UserIdInt int userId) {
2187 FgThread.getHandler().sendMessage(PooledLambda.obtainMessage
2188 (PermissionManagerService::doNotifyRuntimePermissionStateChanged,
2189 PermissionManagerService.this, packageName, userId));
2190 }
2191
2192 private void doNotifyRuntimePermissionStateChanged(@NonNull String packageName,
2193 @UserIdInt int userId) {
2194 final ArrayList<OnRuntimePermissionStateChangedListener> listeners;
2195 synchronized (mLock) {
2196 if (mRuntimePermissionStateChangedListeners.isEmpty()) {
2197 return;
2198 }
2199 listeners = new ArrayList<>(mRuntimePermissionStateChangedListeners);
2200 }
2201 final int listenerCount = listeners.size();
2202 for (int i = 0; i < listenerCount; i++) {
2203 listeners.get(i).onRuntimePermissionStateChanged(packageName, userId);
2204 }
2205 }
2206
Todd Kennedy0eb97382017-10-03 16:57:22 -07002207 private int adjustPermissionProtectionFlagsLocked(
2208 int protectionLevel, String packageName, int uid) {
2209 // Signature permission flags area always reported
2210 final int protectionLevelMasked = protectionLevel
2211 & (PermissionInfo.PROTECTION_NORMAL
2212 | PermissionInfo.PROTECTION_DANGEROUS
2213 | PermissionInfo.PROTECTION_SIGNATURE);
2214 if (protectionLevelMasked == PermissionInfo.PROTECTION_SIGNATURE) {
2215 return protectionLevel;
2216 }
2217 // System sees all flags.
2218 final int appId = UserHandle.getAppId(uid);
2219 if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID
2220 || appId == Process.SHELL_UID) {
2221 return protectionLevel;
2222 }
2223 // Normalize package name to handle renamed packages and static libs
Winson14ff7172019-10-23 10:42:27 -07002224 final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
Todd Kennedy0eb97382017-10-03 16:57:22 -07002225 if (pkg == null) {
2226 return protectionLevel;
2227 }
Winson14ff7172019-10-23 10:42:27 -07002228 if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.O) {
Todd Kennedy0eb97382017-10-03 16:57:22 -07002229 return protectionLevelMasked;
2230 }
2231 // Apps that target O see flags for all protection levels.
Winson14ff7172019-10-23 10:42:27 -07002232 final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
2233 pkg.getPackageName());
Todd Kennedy0eb97382017-10-03 16:57:22 -07002234 if (ps == null) {
2235 return protectionLevel;
2236 }
2237 if (ps.getAppId() != appId) {
2238 return protectionLevel;
2239 }
2240 return protectionLevel;
2241 }
2242
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07002243 /**
2244 * We might auto-grant permissions if any permission of the group is already granted. Hence if
2245 * the group of a granted permission changes we need to revoke it to avoid having permissions of
2246 * the new group auto-granted.
2247 *
2248 * @param newPackage The new package that was installed
2249 * @param oldPackage The old package that was updated
2250 * @param allPackageNames All package names
2251 * @param permissionCallback Callback for permission changed
2252 */
2253 private void revokeRuntimePermissionsIfGroupChanged(
Winson14ff7172019-10-23 10:42:27 -07002254 @NonNull AndroidPackage newPackage,
2255 @NonNull AndroidPackage oldPackage,
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07002256 @NonNull ArrayList<String> allPackageNames,
2257 @NonNull PermissionCallback permissionCallback) {
Winson14ff7172019-10-23 10:42:27 -07002258 final int numOldPackagePermissions = ArrayUtils.size(oldPackage.getPermissions());
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07002259 final ArrayMap<String, String> oldPermissionNameToGroupName
2260 = new ArrayMap<>(numOldPackagePermissions);
2261
2262 for (int i = 0; i < numOldPackagePermissions; i++) {
Winson14ff7172019-10-23 10:42:27 -07002263 final ParsedPermission permission = oldPackage.getPermissions().get(i);
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07002264
Winsonf00c7552020-01-28 12:52:01 -08002265 if (permission.getParsedPermissionGroup() != null) {
Winson14ff7172019-10-23 10:42:27 -07002266 oldPermissionNameToGroupName.put(permission.getName(),
Winsonf00c7552020-01-28 12:52:01 -08002267 permission.getParsedPermissionGroup().getName());
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07002268 }
2269 }
2270
Todd Kennedyc971a452019-07-08 16:04:52 -07002271 final int callingUid = Binder.getCallingUid();
Winson14ff7172019-10-23 10:42:27 -07002272 final int numNewPackagePermissions = ArrayUtils.size(newPackage.getPermissions());
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07002273 for (int newPermissionNum = 0; newPermissionNum < numNewPackagePermissions;
2274 newPermissionNum++) {
Winson14ff7172019-10-23 10:42:27 -07002275 final ParsedPermission newPermission =
2276 newPackage.getPermissions().get(newPermissionNum);
2277 final int newProtection = newPermission.getProtection();
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07002278
2279 if ((newProtection & PermissionInfo.PROTECTION_DANGEROUS) != 0) {
Winson14ff7172019-10-23 10:42:27 -07002280 final String permissionName = newPermission.getName();
Winsonf00c7552020-01-28 12:52:01 -08002281 final String newPermissionGroupName =
2282 newPermission.getParsedPermissionGroup() == null
2283 ? null : newPermission.getParsedPermissionGroup().getName();
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07002284 final String oldPermissionGroupName = oldPermissionNameToGroupName.get(
2285 permissionName);
2286
2287 if (newPermissionGroupName != null
2288 && !newPermissionGroupName.equals(oldPermissionGroupName)) {
2289 final int[] userIds = mUserManagerInt.getUserIds();
2290 final int numUserIds = userIds.length;
2291 for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
2292 final int userId = userIds[userIdNum];
2293
2294 final int numPackages = allPackageNames.size();
2295 for (int packageNum = 0; packageNum < numPackages; packageNum++) {
2296 final String packageName = allPackageNames.get(packageNum);
Hai Zhang3b049a52019-08-16 15:37:46 -07002297 final int permissionState = checkPermission(permissionName, packageName,
2298 userId);
Todd Kennedyca1ea172019-07-03 15:02:28 -07002299 if (permissionState == PackageManager.PERMISSION_GRANTED) {
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07002300 EventLog.writeEvent(0x534e4554, "72710897",
Winson14ff7172019-10-23 10:42:27 -07002301 newPackage.getUid(),
Koji Fukuiacae3ef2018-05-09 11:38:01 +09002302 "Revoking permission " + permissionName +
2303 " from package " + packageName +
2304 " as the group changed from " + oldPermissionGroupName +
2305 " to " + newPermissionGroupName);
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07002306
2307 try {
Todd Kennedyc971a452019-07-08 16:04:52 -07002308 revokeRuntimePermissionInternal(permissionName, packageName,
Evan Seversonaacd48b2020-06-22 16:45:03 -07002309 false, callingUid, userId, null, permissionCallback);
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07002310 } catch (IllegalArgumentException e) {
2311 Slog.e(TAG, "Could not revoke " + permissionName + " from "
2312 + packageName, e);
2313 }
2314 }
2315 }
2316 }
2317 }
2318 }
2319 }
2320 }
2321
Winson14ff7172019-10-23 10:42:27 -07002322 private void addAllPermissions(AndroidPackage pkg, boolean chatty) {
2323 final int N = ArrayUtils.size(pkg.getPermissions());
Todd Kennedyc8423932017-10-05 08:58:36 -07002324 for (int i=0; i<N; i++) {
Winson14ff7172019-10-23 10:42:27 -07002325 ParsedPermission p = pkg.getPermissions().get(i);
Todd Kennedyc8423932017-10-05 08:58:36 -07002326
2327 // Assume by default that we did not install this permission into the system.
Winsonf00c7552020-01-28 12:52:01 -08002328 p.setFlags(p.getFlags() & ~PermissionInfo.FLAG_INSTALLED);
Todd Kennedyc8423932017-10-05 08:58:36 -07002329
Todd Kennedyc8423932017-10-05 08:58:36 -07002330 synchronized (PermissionManagerService.this.mLock) {
Todd Kennedy460f28c2017-10-06 13:46:22 -07002331 // Now that permission groups have a special meaning, we ignore permission
2332 // groups for legacy apps to prevent unexpected behavior. In particular,
2333 // permissions for one app being granted to someone just because they happen
2334 // to be in a group defined by another app (before this had no implications).
Winson14ff7172019-10-23 10:42:27 -07002335 if (pkg.getTargetSdkVersion() > Build.VERSION_CODES.LOLLIPOP_MR1) {
Winsonf00c7552020-01-28 12:52:01 -08002336 p.setParsedPermissionGroup(mSettings.mPermissionGroups.get(p.getGroup()));
Todd Kennedy460f28c2017-10-06 13:46:22 -07002337 // Warn for a permission in an unknown group.
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002338 if (DEBUG_PERMISSIONS
Winsonf00c7552020-01-28 12:52:01 -08002339 && p.getGroup() != null && p.getParsedPermissionGroup() == null) {
Winson14ff7172019-10-23 10:42:27 -07002340 Slog.i(TAG, "Permission " + p.getName() + " from package "
2341 + p.getPackageName() + " in an unknown group " + p.getGroup());
Todd Kennedy460f28c2017-10-06 13:46:22 -07002342 }
2343 }
2344
Winsonf00c7552020-01-28 12:52:01 -08002345 if (p.isTree()) {
Todd Kennedyc8423932017-10-05 08:58:36 -07002346 final BasePermission bp = BasePermission.createOrUpdate(
Winson14ff7172019-10-23 10:42:27 -07002347 mPackageManagerInt,
2348 mSettings.getPermissionTreeLocked(p.getName()), p, pkg,
Todd Kennedyc8423932017-10-05 08:58:36 -07002349 mSettings.getAllPermissionTreesLocked(), chatty);
Winson14ff7172019-10-23 10:42:27 -07002350 mSettings.putPermissionTreeLocked(p.getName(), bp);
Todd Kennedyc8423932017-10-05 08:58:36 -07002351 } else {
2352 final BasePermission bp = BasePermission.createOrUpdate(
Winson14ff7172019-10-23 10:42:27 -07002353 mPackageManagerInt,
2354 mSettings.getPermissionLocked(p.getName()),
Todd Kennedyc8423932017-10-05 08:58:36 -07002355 p, pkg, mSettings.getAllPermissionTreesLocked(), chatty);
Winson14ff7172019-10-23 10:42:27 -07002356 mSettings.putPermissionLocked(p.getName(), bp);
Todd Kennedyc8423932017-10-05 08:58:36 -07002357 }
2358 }
2359 }
2360 }
2361
Winson14ff7172019-10-23 10:42:27 -07002362 private void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
2363 final int N = ArrayUtils.size(pkg.getPermissionGroups());
Todd Kennedy460f28c2017-10-06 13:46:22 -07002364 StringBuilder r = null;
2365 for (int i=0; i<N; i++) {
Winson14ff7172019-10-23 10:42:27 -07002366 final ParsedPermissionGroup pg = pkg.getPermissionGroups().get(i);
2367 final ParsedPermissionGroup cur = mSettings.mPermissionGroups.get(pg.getName());
2368 final String curPackageName = (cur == null) ? null : cur.getPackageName();
2369 final boolean isPackageUpdate = pg.getPackageName().equals(curPackageName);
Todd Kennedy460f28c2017-10-06 13:46:22 -07002370 if (cur == null || isPackageUpdate) {
Winson14ff7172019-10-23 10:42:27 -07002371 mSettings.mPermissionGroups.put(pg.getName(), pg);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002372 if (chatty && DEBUG_PACKAGE_SCANNING) {
Todd Kennedy460f28c2017-10-06 13:46:22 -07002373 if (r == null) {
2374 r = new StringBuilder(256);
2375 } else {
2376 r.append(' ');
2377 }
2378 if (isPackageUpdate) {
2379 r.append("UPD:");
2380 }
Winson14ff7172019-10-23 10:42:27 -07002381 r.append(pg.getName());
Todd Kennedy460f28c2017-10-06 13:46:22 -07002382 }
2383 } else {
Winson14ff7172019-10-23 10:42:27 -07002384 Slog.w(TAG, "Permission group " + pg.getName() + " from package "
2385 + pg.getPackageName() + " ignored: original from "
2386 + cur.getPackageName());
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002387 if (chatty && DEBUG_PACKAGE_SCANNING) {
Todd Kennedy460f28c2017-10-06 13:46:22 -07002388 if (r == null) {
2389 r = new StringBuilder(256);
2390 } else {
2391 r.append(' ');
2392 }
2393 r.append("DUP:");
Winson14ff7172019-10-23 10:42:27 -07002394 r.append(pg.getName());
Todd Kennedy460f28c2017-10-06 13:46:22 -07002395 }
2396 }
2397 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002398 if (r != null && DEBUG_PACKAGE_SCANNING) {
Todd Kennedy460f28c2017-10-06 13:46:22 -07002399 Log.d(TAG, " Permission Groups: " + r);
2400 }
2401
2402 }
2403
Winson14ff7172019-10-23 10:42:27 -07002404 private void removeAllPermissions(AndroidPackage pkg, boolean chatty) {
Todd Kennedyc8423932017-10-05 08:58:36 -07002405 synchronized (mLock) {
Winson14ff7172019-10-23 10:42:27 -07002406 int N = ArrayUtils.size(pkg.getPermissions());
Todd Kennedyc8423932017-10-05 08:58:36 -07002407 StringBuilder r = null;
2408 for (int i=0; i<N; i++) {
Winson14ff7172019-10-23 10:42:27 -07002409 ParsedPermission p = pkg.getPermissions().get(i);
2410 BasePermission bp = mSettings.mPermissions.get(p.getName());
Todd Kennedyc8423932017-10-05 08:58:36 -07002411 if (bp == null) {
Winson14ff7172019-10-23 10:42:27 -07002412 bp = mSettings.mPermissionTrees.get(p.getName());
Todd Kennedyc8423932017-10-05 08:58:36 -07002413 }
2414 if (bp != null && bp.isPermission(p)) {
2415 bp.setPermission(null);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002416 if (DEBUG_REMOVE && chatty) {
Todd Kennedyc8423932017-10-05 08:58:36 -07002417 if (r == null) {
2418 r = new StringBuilder(256);
2419 } else {
2420 r.append(' ');
2421 }
Winson14ff7172019-10-23 10:42:27 -07002422 r.append(p.getName());
Todd Kennedyc8423932017-10-05 08:58:36 -07002423 }
2424 }
2425 if (p.isAppOp()) {
2426 ArraySet<String> appOpPkgs =
Winson14ff7172019-10-23 10:42:27 -07002427 mSettings.mAppOpPermissionPackages.get(p.getName());
Todd Kennedyc8423932017-10-05 08:58:36 -07002428 if (appOpPkgs != null) {
Winson14ff7172019-10-23 10:42:27 -07002429 appOpPkgs.remove(pkg.getPackageName());
Todd Kennedyc8423932017-10-05 08:58:36 -07002430 }
2431 }
2432 }
2433 if (r != null) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002434 if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
Todd Kennedyc8423932017-10-05 08:58:36 -07002435 }
2436
Winson14ff7172019-10-23 10:42:27 -07002437 N = pkg.getRequestedPermissions().size();
Todd Kennedyc8423932017-10-05 08:58:36 -07002438 r = null;
2439 for (int i=0; i<N; i++) {
Winson14ff7172019-10-23 10:42:27 -07002440 String perm = pkg.getRequestedPermissions().get(i);
Todd Kennedyc8423932017-10-05 08:58:36 -07002441 if (mSettings.isPermissionAppOp(perm)) {
2442 ArraySet<String> appOpPkgs = mSettings.mAppOpPermissionPackages.get(perm);
2443 if (appOpPkgs != null) {
Winson14ff7172019-10-23 10:42:27 -07002444 appOpPkgs.remove(pkg.getPackageName());
Todd Kennedyc8423932017-10-05 08:58:36 -07002445 if (appOpPkgs.isEmpty()) {
2446 mSettings.mAppOpPermissionPackages.remove(perm);
2447 }
2448 }
2449 }
2450 }
2451 if (r != null) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002452 if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
Todd Kennedyc8423932017-10-05 08:58:36 -07002453 }
2454 }
2455 }
2456
Philip P. Moltmanne0f00ea2018-10-30 10:43:15 -07002457 /**
2458 * Restore the permission state for a package.
2459 *
2460 * <ul>
2461 * <li>During boot the state gets restored from the disk</li>
2462 * <li>During app update the state gets restored from the last version of the app</li>
2463 * </ul>
2464 *
2465 * <p>This restores the permission state for all users.
2466 *
2467 * @param pkg the package the permissions belong to
2468 * @param replace if the package is getting replaced (this might change the requested
2469 * permissions of this package)
2470 * @param packageOfInterest If this is the name of {@code pkg} add extra logging
2471 * @param callback Result call back
2472 */
Winson14ff7172019-10-23 10:42:27 -07002473 private void restorePermissionState(@NonNull AndroidPackage pkg, boolean replace,
Philip P. Moltmanne0f00ea2018-10-30 10:43:15 -07002474 @Nullable String packageOfInterest, @Nullable PermissionCallback callback) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002475 // IMPORTANT: There are two types of permissions: install and runtime.
2476 // Install time permissions are granted when the app is installed to
2477 // all device users and users added in the future. Runtime permissions
2478 // are granted at runtime explicitly to specific users. Normal and signature
2479 // protected permissions are install time permissions. Dangerous permissions
2480 // are install permissions if the app's target SDK is Lollipop MR1 or older,
2481 // otherwise they are runtime permissions. This function does not manage
2482 // runtime permissions except for the case an app targeting Lollipop MR1
2483 // being upgraded to target a newer SDK, in which case dangerous permissions
2484 // are transformed from install time to runtime ones.
2485
Winson14ff7172019-10-23 10:42:27 -07002486 final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
2487 pkg.getPackageName());
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002488 if (ps == null) {
2489 return;
2490 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002491
2492 final PermissionsState permissionsState = ps.getPermissionsState();
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002493
2494 final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
2495
2496 boolean runtimePermissionsRevoked = false;
2497 int[] updatedUserIds = EMPTY_INT_ARRAY;
2498
Hai Zhang4c0d15b2020-05-18 16:06:58 -07002499 for (int userId : currentUserIds) {
2500 if (permissionsState.isMissing(userId)) {
2501 Collection<String> requestedPermissions;
2502 int targetSdkVersion;
2503 if (!ps.isSharedUser()) {
2504 requestedPermissions = pkg.getRequestedPermissions();
2505 targetSdkVersion = pkg.getTargetSdkVersion();
2506 } else {
2507 requestedPermissions = new ArraySet<>();
2508 targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
2509 List<AndroidPackage> packages = ps.getSharedUser().getPackages();
2510 int packagesSize = packages.size();
2511 for (int i = 0; i < packagesSize; i++) {
2512 AndroidPackage sharedUserPackage = packages.get(i);
2513 requestedPermissions.addAll(sharedUserPackage.getRequestedPermissions());
2514 targetSdkVersion = Math.min(targetSdkVersion,
2515 sharedUserPackage.getTargetSdkVersion());
2516 }
2517 }
2518
2519 for (String permissionName : requestedPermissions) {
2520 BasePermission permission = mSettings.getPermission(permissionName);
Hai Zhangd8ba6852020-06-16 13:28:48 -07002521 if (permission == null) {
2522 continue;
2523 }
Hai Zhang4c0d15b2020-05-18 16:06:58 -07002524 if (Objects.equals(permission.getSourcePackageName(), PLATFORM_PACKAGE_NAME)
2525 && permission.isRuntime() && !permission.isRemoved()) {
2526 if (permission.isHardOrSoftRestricted()
2527 || permission.isImmutablyRestricted()) {
2528 permissionsState.updatePermissionFlags(permission, userId,
Nate Myrenc92df182020-06-23 16:31:39 -07002529 FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
2530 FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
Hai Zhang4c0d15b2020-05-18 16:06:58 -07002531 }
2532 if (targetSdkVersion < Build.VERSION_CODES.M) {
2533 permissionsState.updatePermissionFlags(permission, userId,
2534 PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
2535 | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
2536 PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
2537 | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT);
2538 permissionsState.grantRuntimePermission(permission, userId);
2539 }
2540 }
2541 }
2542
2543 permissionsState.setMissing(false, userId);
2544 updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
2545 }
2546 }
2547
2548 PermissionsState origPermissions = permissionsState;
2549
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002550 boolean changedInstallPermission = false;
2551
2552 if (replace) {
2553 ps.setInstallPermissionsFixed(false);
2554 if (!ps.isSharedUser()) {
2555 origPermissions = new PermissionsState(permissionsState);
2556 permissionsState.reset();
2557 } else {
2558 // We need to know only about runtime permission changes since the
2559 // calling code always writes the install permissions state but
2560 // the runtime ones are written only if changed. The only cases of
2561 // changed runtime permissions here are promotion of an install to
2562 // runtime and revocation of a runtime from a shared user.
2563 synchronized (mLock) {
2564 updatedUserIds = revokeUnusedSharedUserPermissionsLocked(
2565 ps.getSharedUser(), UserManagerService.getInstance().getUserIds());
2566 if (!ArrayUtils.isEmpty(updatedUserIds)) {
2567 runtimePermissionsRevoked = true;
2568 }
2569 }
2570 }
2571 }
2572
2573 permissionsState.setGlobalGids(mGlobalGids);
2574
2575 synchronized (mLock) {
Philip P. Moltmanne1233192019-04-18 08:45:55 -07002576 ArraySet<String> newImplicitPermissions = new ArraySet<>();
2577
Winson14ff7172019-10-23 10:42:27 -07002578 final int N = pkg.getRequestedPermissions().size();
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002579 for (int i = 0; i < N; i++) {
Winson14ff7172019-10-23 10:42:27 -07002580 final String permName = pkg.getRequestedPermissions().get(i);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002581 final BasePermission bp = mSettings.getPermissionLocked(permName);
2582 final boolean appSupportsRuntimePermissions =
Winson14ff7172019-10-23 10:42:27 -07002583 pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;
Zimuzoe6411402019-05-13 16:32:57 +01002584 String upgradedActivityRecognitionPermission = null;
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002585
Songchun Fanbcc899e2020-04-06 16:51:45 -07002586 if (DEBUG_INSTALL && bp != null) {
Winson14ff7172019-10-23 10:42:27 -07002587 Log.i(TAG, "Package " + pkg.getPackageName()
2588 + " checking " + permName + ": " + bp);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002589 }
2590
Songchun Fane5c0afe2020-04-22 12:22:52 -07002591 if (bp == null || getSourcePackageSetting(bp) == null) {
Winson14ff7172019-10-23 10:42:27 -07002592 if (packageOfInterest == null || packageOfInterest.equals(
2593 pkg.getPackageName())) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002594 if (DEBUG_PERMISSIONS) {
2595 Slog.i(TAG, "Unknown permission " + permName
Winson14ff7172019-10-23 10:42:27 -07002596 + " in package " + pkg.getPackageName());
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002597 }
2598 }
2599 continue;
2600 }
2601
Philip P. Moltmanne1233192019-04-18 08:45:55 -07002602 // Cache newImplicitPermissions before modifing permissionsState as for the shared
2603 // uids the original and new state are the same object
2604 if (!origPermissions.hasRequestedPermission(permName)
Winson14ff7172019-10-23 10:42:27 -07002605 && (pkg.getImplicitPermissions().contains(permName)
Zimuzoe6411402019-05-13 16:32:57 +01002606 || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) {
Winson14ff7172019-10-23 10:42:27 -07002607 if (pkg.getImplicitPermissions().contains(permName)) {
Zimuzoe6411402019-05-13 16:32:57 +01002608 // If permName is an implicit permission, try to auto-grant
2609 newImplicitPermissions.add(permName);
Philip P. Moltmanne1233192019-04-18 08:45:55 -07002610
Zimuzoe6411402019-05-13 16:32:57 +01002611 if (DEBUG_PERMISSIONS) {
Winson14ff7172019-10-23 10:42:27 -07002612 Slog.i(TAG, permName + " is newly added for " + pkg.getPackageName());
Zimuzoe6411402019-05-13 16:32:57 +01002613 }
2614 } else {
2615 // Special case for Activity Recognition permission. Even if AR permission
2616 // is not an implicit permission we want to add it to the list (try to
2617 // auto-grant it) if the app was installed on a device before AR permission
2618 // was split, regardless of if the app now requests the new AR permission
2619 // or has updated its target SDK and AR is no longer implicit to it.
2620 // This is a compatibility workaround for apps when AR permission was
2621 // split in Q.
Anthony Hughde787d42019-08-22 15:35:48 -07002622 final List<SplitPermissionInfoParcelable> permissionList =
2623 getSplitPermissions();
2624 int numSplitPerms = permissionList.size();
Zimuzoe6411402019-05-13 16:32:57 +01002625 for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
Anthony Hughde787d42019-08-22 15:35:48 -07002626 SplitPermissionInfoParcelable sp = permissionList.get(splitPermNum);
Zimuzoe6411402019-05-13 16:32:57 +01002627 String splitPermName = sp.getSplitPermission();
2628 if (sp.getNewPermissions().contains(permName)
2629 && origPermissions.hasInstallPermission(splitPermName)) {
2630 upgradedActivityRecognitionPermission = splitPermName;
2631 newImplicitPermissions.add(permName);
2632
2633 if (DEBUG_PERMISSIONS) {
2634 Slog.i(TAG, permName + " is newly added for "
Winson14ff7172019-10-23 10:42:27 -07002635 + pkg.getPackageName());
Zimuzoe6411402019-05-13 16:32:57 +01002636 }
2637 break;
2638 }
2639 }
Philip P. Moltmanne1233192019-04-18 08:45:55 -07002640 }
2641 }
2642
Winson5e0a1d52020-01-24 12:00:33 -08002643 // TODO(b/140256621): The package instant app method has been removed
2644 // as part of work in b/135203078, so this has been commented out in the meantime
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002645 // Limit ephemeral apps to ephemeral allowed permissions.
Winson5e0a1d52020-01-24 12:00:33 -08002646// if (/*pkg.isInstantApp()*/ false && !bp.isInstant()) {
2647// if (DEBUG_PERMISSIONS) {
2648// Log.i(TAG, "Denying non-ephemeral permission " + bp.getName()
2649// + " for package " + pkg.getPackageName());
2650// }
2651// continue;
2652// }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002653
2654 if (bp.isRuntimeOnly() && !appSupportsRuntimePermissions) {
2655 if (DEBUG_PERMISSIONS) {
2656 Log.i(TAG, "Denying runtime-only permission " + bp.getName()
Winson14ff7172019-10-23 10:42:27 -07002657 + " for package " + pkg.getPackageName());
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002658 }
2659 continue;
2660 }
2661
2662 final String perm = bp.getName();
2663 boolean allowedSig = false;
2664 int grant = GRANT_DENIED;
2665
2666 // Keep track of app op permissions.
2667 if (bp.isAppOp()) {
Winson14ff7172019-10-23 10:42:27 -07002668 mSettings.addAppOpPackage(perm, pkg.getPackageName());
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002669 }
2670
2671 if (bp.isNormal()) {
2672 // For all apps normal permissions are install time ones.
2673 grant = GRANT_INSTALL;
2674 } else if (bp.isRuntime()) {
Zimuzoe6411402019-05-13 16:32:57 +01002675 if (origPermissions.hasInstallPermission(bp.getName())
2676 || upgradedActivityRecognitionPermission != null) {
Philip P. Moltmann48456672019-01-20 13:14:03 -08002677 // Before Q we represented some runtime permissions as install permissions,
2678 // in Q we cannot do this anymore. Hence upgrade them all.
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002679 grant = GRANT_UPGRADE;
2680 } else {
2681 // For modern apps keep runtime permissions unchanged.
2682 grant = GRANT_RUNTIME;
2683 }
2684 } else if (bp.isSignature()) {
2685 // For all apps signature permissions are install time ones.
Winsone0756292020-01-31 12:21:54 -08002686 allowedSig = grantSignaturePermission(perm, pkg, ps, bp, origPermissions);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002687 if (allowedSig) {
2688 grant = GRANT_INSTALL;
2689 }
2690 }
2691
2692 if (DEBUG_PERMISSIONS) {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002693 Slog.i(TAG, "Considering granting permission " + perm + " to package "
Winson14ff7172019-10-23 10:42:27 -07002694 + pkg.getPackageName());
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002695 }
2696
2697 if (grant != GRANT_DENIED) {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002698 if (!ps.isSystem() && ps.areInstallPermissionsFixed() && !bp.isRuntime()) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002699 // If this is an existing, non-system package, then
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002700 // we can't add any new permissions to it. Runtime
2701 // permissions can be added any time - they ad dynamic.
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002702 if (!allowedSig && !origPermissions.hasInstallPermission(perm)) {
2703 // Except... if this is a permission that was added
2704 // to the platform (note: need to only do this when
2705 // updating the platform).
2706 if (!isNewPlatformPermissionForPackage(perm, pkg)) {
2707 grant = GRANT_DENIED;
2708 }
2709 }
2710 }
2711
2712 switch (grant) {
2713 case GRANT_INSTALL: {
2714 // Revoke this as runtime permission to handle the case of
2715 // a runtime permission being downgraded to an install one.
2716 // Also in permission review mode we keep dangerous permissions
2717 // for legacy apps
2718 for (int userId : UserManagerService.getInstance().getUserIds()) {
2719 if (origPermissions.getRuntimePermissionState(
2720 perm, userId) != null) {
2721 // Revoke the runtime permission and clear the flags.
2722 origPermissions.revokeRuntimePermission(bp, userId);
2723 origPermissions.updatePermissionFlags(bp, userId,
Philip P. Moltmann76597692019-03-02 13:18:41 -08002724 PackageManager.MASK_PERMISSION_FLAGS_ALL, 0);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002725 // If we revoked a permission permission, we have to write.
2726 updatedUserIds = ArrayUtils.appendInt(
2727 updatedUserIds, userId);
2728 }
2729 }
2730 // Grant an install permission.
2731 if (permissionsState.grantInstallPermission(bp) !=
Philip P. Moltmann48456672019-01-20 13:14:03 -08002732 PERMISSION_OPERATION_FAILURE) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002733 changedInstallPermission = true;
2734 }
2735 } break;
2736
2737 case GRANT_RUNTIME: {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002738 boolean hardRestricted = bp.isHardRestricted();
2739 boolean softRestricted = bp.isSoftRestricted();
2740
Philip P. Moltmann48456672019-01-20 13:14:03 -08002741 for (int userId : currentUserIds) {
Svet Ganov3c499ea2019-07-26 17:45:56 -07002742 // If permission policy is not ready we don't deal with restricted
2743 // permissions as the policy may whitelist some permissions. Once
2744 // the policy is initialized we would re-evaluate permissions.
2745 final boolean permissionPolicyInitialized =
2746 mPermissionPolicyInternal != null
2747 && mPermissionPolicyInternal.isInitialized(userId);
2748
Philip P. Moltmann48456672019-01-20 13:14:03 -08002749 PermissionState permState = origPermissions
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002750 .getRuntimePermissionState(perm, userId);
Philip P. Moltmann48456672019-01-20 13:14:03 -08002751 int flags = permState != null ? permState.getFlags() : 0;
2752
2753 boolean wasChanged = false;
2754
Svet Ganov83a3a4a2019-05-03 18:50:43 -07002755 boolean restrictionExempt =
2756 (origPermissions.getPermissionFlags(bp.name, userId)
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002757 & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
2758 boolean restrictionApplied = (origPermissions.getPermissionFlags(
2759 bp.name, userId) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
2760
Philip P. Moltmann48456672019-01-20 13:14:03 -08002761 if (appSupportsRuntimePermissions) {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002762 // If hard restricted we don't allow holding it
Svet Ganov3c499ea2019-07-26 17:45:56 -07002763 if (permissionPolicyInitialized && hardRestricted) {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002764 if (!restrictionExempt) {
2765 if (permState != null && permState.isGranted()
2766 && permissionsState.revokeRuntimePermission(
2767 bp, userId) != PERMISSION_OPERATION_FAILURE) {
2768 wasChanged = true;
2769 }
2770 if (!restrictionApplied) {
2771 flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
2772 wasChanged = true;
2773 }
2774 }
2775 // If soft restricted we allow holding in a restricted form
Svet Ganov3c499ea2019-07-26 17:45:56 -07002776 } else if (permissionPolicyInitialized && softRestricted) {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002777 // Regardless if granted set the restriction flag as it
2778 // may affect app treatment based on this permission.
2779 if (!restrictionExempt && !restrictionApplied) {
2780 flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
2781 wasChanged = true;
2782 }
2783 }
2784
Philip P. Moltmann48456672019-01-20 13:14:03 -08002785 // Remove review flag as it is not necessary anymore
2786 if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
2787 flags &= ~FLAG_PERMISSION_REVIEW_REQUIRED;
2788 wasChanged = true;
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002789 }
Philip P. Moltmann48456672019-01-20 13:14:03 -08002790
Hai Zhang50a5a9b2019-09-19 13:57:45 -07002791 if ((flags & FLAG_PERMISSION_REVOKED_COMPAT) != 0) {
2792 flags &= ~FLAG_PERMISSION_REVOKED_COMPAT;
Philip P. Moltmann48456672019-01-20 13:14:03 -08002793 wasChanged = true;
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002794 // Hard restricted permissions cannot be held.
Svet Ganov3c499ea2019-07-26 17:45:56 -07002795 } else if (!permissionPolicyInitialized
2796 || (!hardRestricted || restrictionExempt)) {
Philip P. Moltmann48456672019-01-20 13:14:03 -08002797 if (permState != null && permState.isGranted()) {
2798 if (permissionsState.grantRuntimePermission(bp, userId)
2799 == PERMISSION_OPERATION_FAILURE) {
2800 wasChanged = true;
2801 }
2802 }
2803 }
2804 } else {
2805 if (permState == null) {
2806 // New permission
2807 if (PLATFORM_PACKAGE_NAME.equals(
2808 bp.getSourcePackageName())) {
2809 if (!bp.isRemoved()) {
2810 flags |= FLAG_PERMISSION_REVIEW_REQUIRED
Hai Zhang50a5a9b2019-09-19 13:57:45 -07002811 | FLAG_PERMISSION_REVOKED_COMPAT;
Philip P. Moltmann48456672019-01-20 13:14:03 -08002812 wasChanged = true;
2813 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002814 }
2815 }
2816
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002817 if (!permissionsState.hasRuntimePermission(bp.name, userId)
2818 && permissionsState.grantRuntimePermission(bp, userId)
2819 != PERMISSION_OPERATION_FAILURE) {
2820 wasChanged = true;
2821 }
2822
2823 // If legacy app always grant the permission but if restricted
2824 // and not exempt take a note a restriction should be applied.
Svet Ganov3c499ea2019-07-26 17:45:56 -07002825 if (permissionPolicyInitialized
2826 && (hardRestricted || softRestricted)
2827 && !restrictionExempt && !restrictionApplied) {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002828 flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
2829 wasChanged = true;
2830 }
2831 }
2832
2833 // If unrestricted or restriction exempt, don't apply restriction.
Svet Ganov3c499ea2019-07-26 17:45:56 -07002834 if (permissionPolicyInitialized) {
2835 if (!(hardRestricted || softRestricted) || restrictionExempt) {
2836 if (restrictionApplied) {
2837 flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
2838 // Dropping restriction on a legacy app implies a review
2839 if (!appSupportsRuntimePermissions) {
2840 flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
2841 }
2842 wasChanged = true;
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002843 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002844 }
2845 }
Philip P. Moltmann48456672019-01-20 13:14:03 -08002846
2847 if (wasChanged) {
2848 updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
2849 }
2850
Philip P. Moltmannc6e3a8e2019-02-21 13:57:31 -08002851 permissionsState.updatePermissionFlags(bp, userId,
Philip P. Moltmann76597692019-03-02 13:18:41 -08002852 MASK_PERMISSION_FLAGS_ALL, flags);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002853 }
2854 } break;
2855
2856 case GRANT_UPGRADE: {
Philip P. Moltmann48456672019-01-20 13:14:03 -08002857 // Upgrade from Pre-Q to Q permission model. Make all permissions
2858 // runtime
2859 PermissionState permState = origPermissions
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002860 .getInstallPermissionState(perm);
Philip P. Moltmann48456672019-01-20 13:14:03 -08002861 int flags = (permState != null) ? permState.getFlags() : 0;
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002862
Zimuzoe6411402019-05-13 16:32:57 +01002863 BasePermission bpToRevoke =
2864 upgradedActivityRecognitionPermission == null
2865 ? bp : mSettings.getPermissionLocked(
2866 upgradedActivityRecognitionPermission);
Philip P. Moltmann48456672019-01-20 13:14:03 -08002867 // Remove install permission
Zimuzoe6411402019-05-13 16:32:57 +01002868 if (origPermissions.revokeInstallPermission(bpToRevoke)
Philip P. Moltmann48456672019-01-20 13:14:03 -08002869 != PERMISSION_OPERATION_FAILURE) {
Zimuzoe6411402019-05-13 16:32:57 +01002870 origPermissions.updatePermissionFlags(bpToRevoke,
2871 UserHandle.USER_ALL,
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002872 (MASK_PERMISSION_FLAGS_ALL
2873 & ~FLAG_PERMISSION_APPLY_RESTRICTION), 0);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002874 changedInstallPermission = true;
2875 }
2876
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002877 boolean hardRestricted = bp.isHardRestricted();
2878 boolean softRestricted = bp.isSoftRestricted();
2879
Philip P. Moltmann48456672019-01-20 13:14:03 -08002880 for (int userId : currentUserIds) {
Svet Ganov3c499ea2019-07-26 17:45:56 -07002881 // If permission policy is not ready we don't deal with restricted
2882 // permissions as the policy may whitelist some permissions. Once
2883 // the policy is initialized we would re-evaluate permissions.
2884 final boolean permissionPolicyInitialized =
2885 mPermissionPolicyInternal != null
2886 && mPermissionPolicyInternal.isInitialized(userId);
2887
Philip P. Moltmann48456672019-01-20 13:14:03 -08002888 boolean wasChanged = false;
2889
Svet Ganov83a3a4a2019-05-03 18:50:43 -07002890 boolean restrictionExempt =
2891 (origPermissions.getPermissionFlags(bp.name, userId)
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002892 & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
2893 boolean restrictionApplied = (origPermissions.getPermissionFlags(
2894 bp.name, userId) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
2895
Philip P. Moltmann48456672019-01-20 13:14:03 -08002896 if (appSupportsRuntimePermissions) {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002897 // If hard restricted we don't allow holding it
Svet Ganov3c499ea2019-07-26 17:45:56 -07002898 if (permissionPolicyInitialized && hardRestricted) {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002899 if (!restrictionExempt) {
2900 if (permState != null && permState.isGranted()
2901 && permissionsState.revokeRuntimePermission(
2902 bp, userId) != PERMISSION_OPERATION_FAILURE) {
2903 wasChanged = true;
2904 }
2905 if (!restrictionApplied) {
2906 flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
2907 wasChanged = true;
2908 }
2909 }
2910 // If soft restricted we allow holding in a restricted form
Svet Ganov3c499ea2019-07-26 17:45:56 -07002911 } else if (permissionPolicyInitialized && softRestricted) {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002912 // Regardless if granted set the restriction flag as it
2913 // may affect app treatment based on this permission.
2914 if (!restrictionExempt && !restrictionApplied) {
2915 flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
2916 wasChanged = true;
2917 }
2918 }
2919
Philip P. Moltmann48456672019-01-20 13:14:03 -08002920 // Remove review flag as it is not necessary anymore
2921 if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
2922 flags &= ~FLAG_PERMISSION_REVIEW_REQUIRED;
2923 wasChanged = true;
2924 }
2925
Hai Zhang50a5a9b2019-09-19 13:57:45 -07002926 if ((flags & FLAG_PERMISSION_REVOKED_COMPAT) != 0) {
2927 flags &= ~FLAG_PERMISSION_REVOKED_COMPAT;
Philip P. Moltmann48456672019-01-20 13:14:03 -08002928 wasChanged = true;
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002929 // Hard restricted permissions cannot be held.
Svet Ganov3c499ea2019-07-26 17:45:56 -07002930 } else if (!permissionPolicyInitialized ||
2931 (!hardRestricted || restrictionExempt)) {
Philip P. Moltmann48456672019-01-20 13:14:03 -08002932 if (permissionsState.grantRuntimePermission(bp, userId) !=
2933 PERMISSION_OPERATION_FAILURE) {
2934 wasChanged = true;
2935 }
2936 }
2937 } else {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002938 if (!permissionsState.hasRuntimePermission(bp.name, userId)
2939 && permissionsState.grantRuntimePermission(bp,
2940 userId) != PERMISSION_OPERATION_FAILURE) {
Philip P. Moltmann48456672019-01-20 13:14:03 -08002941 flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
2942 wasChanged = true;
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002943 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002944
2945 // If legacy app always grant the permission but if restricted
2946 // and not exempt take a note a restriction should be applied.
Svet Ganov3c499ea2019-07-26 17:45:56 -07002947 if (permissionPolicyInitialized
2948 && (hardRestricted || softRestricted)
2949 && !restrictionExempt && !restrictionApplied) {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002950 flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
2951 wasChanged = true;
2952 }
2953 }
2954
2955 // If unrestricted or restriction exempt, don't apply restriction.
Svet Ganov3c499ea2019-07-26 17:45:56 -07002956 if (permissionPolicyInitialized) {
2957 if (!(hardRestricted || softRestricted) || restrictionExempt) {
2958 if (restrictionApplied) {
2959 flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
2960 // Dropping restriction on a legacy app implies a review
2961 if (!appSupportsRuntimePermissions) {
2962 flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
2963 }
2964 wasChanged = true;
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002965 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -07002966 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002967 }
Philip P. Moltmann48456672019-01-20 13:14:03 -08002968
2969 if (wasChanged) {
2970 updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
2971 }
2972
Philip P. Moltmannc6e3a8e2019-02-21 13:57:31 -08002973 permissionsState.updatePermissionFlags(bp, userId,
Philip P. Moltmann76597692019-03-02 13:18:41 -08002974 MASK_PERMISSION_FLAGS_ALL, flags);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002975 }
2976 } break;
2977
2978 default: {
2979 if (packageOfInterest == null
Winson14ff7172019-10-23 10:42:27 -07002980 || packageOfInterest.equals(pkg.getPackageName())) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002981 if (DEBUG_PERMISSIONS) {
2982 Slog.i(TAG, "Not granting permission " + perm
Winson14ff7172019-10-23 10:42:27 -07002983 + " to package " + pkg.getPackageName()
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002984 + " because it was previously installed without");
2985 }
2986 }
2987 } break;
2988 }
2989 } else {
2990 if (permissionsState.revokeInstallPermission(bp) !=
Philip P. Moltmann48456672019-01-20 13:14:03 -08002991 PERMISSION_OPERATION_FAILURE) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002992 // Also drop the permission flags.
2993 permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
Philip P. Moltmann76597692019-03-02 13:18:41 -08002994 MASK_PERMISSION_FLAGS_ALL, 0);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07002995 changedInstallPermission = true;
Nate Myrened67bdd2019-05-07 10:32:22 -07002996 if (DEBUG_PERMISSIONS) {
2997 Slog.i(TAG, "Un-granting permission " + perm
Winson14ff7172019-10-23 10:42:27 -07002998 + " from package " + pkg.getPackageName()
Nate Myrened67bdd2019-05-07 10:32:22 -07002999 + " (protectionLevel=" + bp.getProtectionLevel()
Winsonf00c7552020-01-28 12:52:01 -08003000 + " flags=0x"
3001 + Integer.toHexString(PackageInfoUtils.appInfoFlags(pkg, ps))
Nate Myrened67bdd2019-05-07 10:32:22 -07003002 + ")");
3003 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003004 } else if (bp.isAppOp()) {
3005 // Don't print warning for app op permissions, since it is fine for them
3006 // not to be granted, there is a UI for the user to decide.
3007 if (DEBUG_PERMISSIONS
3008 && (packageOfInterest == null
Winson14ff7172019-10-23 10:42:27 -07003009 || packageOfInterest.equals(pkg.getPackageName()))) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003010 Slog.i(TAG, "Not granting permission " + perm
Winson14ff7172019-10-23 10:42:27 -07003011 + " to package " + pkg.getPackageName()
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003012 + " (protectionLevel=" + bp.getProtectionLevel()
Winsonf00c7552020-01-28 12:52:01 -08003013 + " flags=0x"
3014 + Integer.toHexString(PackageInfoUtils.appInfoFlags(pkg, ps))
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003015 + ")");
3016 }
3017 }
3018 }
3019 }
3020
3021 if ((changedInstallPermission || replace) && !ps.areInstallPermissionsFixed() &&
Winson8359e402020-02-21 17:32:14 -08003022 !ps.isSystem() || ps.getPkgState().isUpdatedSystemApp()) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003023 // This is the first that we have heard about this package, so the
3024 // permissions we have now selected are fixed until explicitly
3025 // changed.
3026 ps.setInstallPermissionsFixed(true);
3027 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003028
3029 updatedUserIds = revokePermissionsNoLongerImplicitLocked(permissionsState, pkg,
3030 updatedUserIds);
3031 updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions,
Philip P. Moltmanne1233192019-04-18 08:45:55 -07003032 permissionsState, pkg, newImplicitPermissions, updatedUserIds);
Philip P. Moltmann74065c82019-05-15 10:46:32 -07003033 updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, updatedUserIds);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003034 }
3035
3036 // Persist the runtime permissions state for users with changes. If permissions
3037 // were revoked because no app in the shared user declares them we have to
3038 // write synchronously to avoid losing runtime permissions state.
3039 if (callback != null) {
3040 callback.onPermissionUpdated(updatedUserIds, runtimePermissionsRevoked);
3041 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003042
3043 for (int userId : updatedUserIds) {
Winson14ff7172019-10-23 10:42:27 -07003044 notifyRuntimePermissionStateChanged(pkg.getPackageName(), userId);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003045 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003046 }
3047
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003048 /**
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003049 * Revoke permissions that are not implicit anymore and that have
3050 * {@link PackageManager#FLAG_PERMISSION_REVOKE_WHEN_REQUESTED} set.
3051 *
3052 * @param ps The state of the permissions of the package
3053 * @param pkg The package that is currently looked at
3054 * @param updatedUserIds a list of user ids that needs to be amended if the permission state
3055 * for a user is changed.
3056 *
3057 * @return The updated value of the {@code updatedUserIds} parameter
3058 */
3059 private @NonNull int[] revokePermissionsNoLongerImplicitLocked(
Winson14ff7172019-10-23 10:42:27 -07003060 @NonNull PermissionsState ps, @NonNull AndroidPackage pkg,
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003061 @NonNull int[] updatedUserIds) {
Winson14ff7172019-10-23 10:42:27 -07003062 String pkgName = pkg.getPackageName();
3063 boolean supportsRuntimePermissions = pkg.getTargetSdkVersion()
Philip P. Moltmannd030ce22019-02-18 21:05:48 -08003064 >= Build.VERSION_CODES.M;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003065
3066 int[] users = UserManagerService.getInstance().getUserIds();
3067 int numUsers = users.length;
3068 for (int i = 0; i < numUsers; i++) {
3069 int userId = users[i];
3070
3071 for (String permission : ps.getPermissions(userId)) {
Winson14ff7172019-10-23 10:42:27 -07003072 if (!pkg.getImplicitPermissions().contains(permission)) {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003073 if (!ps.hasInstallPermission(permission)) {
3074 int flags = ps.getRuntimePermissionState(permission, userId).getFlags();
3075
3076 if ((flags & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED) != 0) {
3077 BasePermission bp = mSettings.getPermissionLocked(permission);
3078
Philip P. Moltmann8277ab62019-02-21 14:08:30 -08003079 int flagsToRemove = FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003080
Philip P. Moltmann319c4ee2019-02-25 09:21:23 -08003081 if ((flags & BLOCKING_PERMISSION_FLAGS) == 0
3082 && supportsRuntimePermissions) {
Philip P. Moltmann8277ab62019-02-21 14:08:30 -08003083 int revokeResult = ps.revokeRuntimePermission(bp, userId);
3084 if (revokeResult != PERMISSION_OPERATION_FAILURE) {
3085 if (DEBUG_PERMISSIONS) {
3086 Slog.i(TAG, "Revoking runtime permission "
3087 + permission + " for " + pkgName
3088 + " as it is now requested");
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003089 }
3090 }
3091
Philip P. Moltmann319c4ee2019-02-25 09:21:23 -08003092 flagsToRemove |= USER_PERMISSION_FLAGS;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003093 }
Philip P. Moltmann8277ab62019-02-21 14:08:30 -08003094
3095 ps.updatePermissionFlags(bp, userId, flagsToRemove, 0);
3096 updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003097 }
3098 }
3099 }
3100 }
3101 }
3102
3103 return updatedUserIds;
3104 }
3105
3106 /**
3107 * {@code newPerm} is newly added; Inherit the state from {@code sourcePerms}.
3108 *
3109 * <p>A single new permission can be split off from several source permissions. In this case
3110 * the most leniant state is inherited.
3111 *
3112 * <p>Warning: This does not handle foreground / background permissions
3113 *
3114 * @param sourcePerms The permissions to inherit from
3115 * @param newPerm The permission to inherit to
3116 * @param ps The permission state of the package
3117 * @param pkg The package requesting the permissions
3118 * @param userId The user the permission belongs to
3119 */
3120 private void inheritPermissionStateToNewImplicitPermissionLocked(
3121 @NonNull ArraySet<String> sourcePerms, @NonNull String newPerm,
Winson14ff7172019-10-23 10:42:27 -07003122 @NonNull PermissionsState ps, @NonNull AndroidPackage pkg,
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003123 @UserIdInt int userId) {
Winson14ff7172019-10-23 10:42:27 -07003124 String pkgName = pkg.getPackageName();
Philip P. Moltmann9408f582019-04-10 16:58:24 -07003125 boolean isGranted = false;
3126 int flags = 0;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003127
Philip P. Moltmann9408f582019-04-10 16:58:24 -07003128 int numSourcePerm = sourcePerms.size();
3129 for (int i = 0; i < numSourcePerm; i++) {
3130 String sourcePerm = sourcePerms.valueAt(i);
3131 if ((ps.hasRuntimePermission(sourcePerm, userId))
3132 || ps.hasInstallPermission(sourcePerm)) {
3133 if (!isGranted) {
3134 flags = 0;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003135 }
3136
Philip P. Moltmann9408f582019-04-10 16:58:24 -07003137 isGranted = true;
3138 flags |= ps.getPermissionFlags(sourcePerm, userId);
3139 } else {
3140 if (!isGranted) {
Philip P. Moltmanndddadd72019-02-25 09:21:23 -08003141 flags |= ps.getPermissionFlags(sourcePerm, userId);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003142 }
3143 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003144 }
Philip P. Moltmann9408f582019-04-10 16:58:24 -07003145
3146 if (isGranted) {
3147 if (DEBUG_PERMISSIONS) {
3148 Slog.i(TAG, newPerm + " inherits runtime perm grant from " + sourcePerms
3149 + " for " + pkgName);
3150 }
3151
3152 ps.grantRuntimePermission(mSettings.getPermissionLocked(newPerm), userId);
3153 }
3154
3155 // Add permission flags
3156 ps.updatePermissionFlags(mSettings.getPermission(newPerm), userId, flags, flags);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003157 }
3158
3159 /**
Philip P. Moltmann74065c82019-05-15 10:46:32 -07003160 * When the app has requested legacy storage we might need to update
3161 * {@link android.app.AppOpsManager#OP_LEGACY_STORAGE}. Hence force an update in
3162 * {@link com.android.server.policy.PermissionPolicyService#synchronizePackagePermissionsAndAppOpsForUser(Context, String, int)}
3163 *
3164 * @param pkg The package for which the permissions are updated
3165 * @param replace If the app is being replaced
3166 * @param updatedUserIds The ids of the users that already changed.
3167 *
3168 * @return The ids of the users that are changed
3169 */
3170 private @NonNull int[] checkIfLegacyStorageOpsNeedToBeUpdated(
Winson14ff7172019-10-23 10:42:27 -07003171 @NonNull AndroidPackage pkg, boolean replace, @NonNull int[] updatedUserIds) {
Winson5e0a1d52020-01-24 12:00:33 -08003172 if (replace && pkg.isRequestLegacyExternalStorage() && (
Winson14ff7172019-10-23 10:42:27 -07003173 pkg.getRequestedPermissions().contains(READ_EXTERNAL_STORAGE)
3174 || pkg.getRequestedPermissions().contains(WRITE_EXTERNAL_STORAGE))) {
Philip P. Moltmann74065c82019-05-15 10:46:32 -07003175 return UserManagerService.getInstance().getUserIds();
3176 }
3177
3178 return updatedUserIds;
3179 }
3180
3181 /**
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003182 * Set the state of a implicit permission that is seen for the first time.
3183 *
3184 * @param origPs The permission state of the package before the split
3185 * @param ps The new permission state
3186 * @param pkg The package the permission belongs to
3187 * @param updatedUserIds List of users for which the permission state has already been changed
3188 *
3189 * @return List of users for which the permission state has been changed
3190 */
3191 private @NonNull int[] setInitialGrantForNewImplicitPermissionsLocked(
3192 @NonNull PermissionsState origPs,
Winson14ff7172019-10-23 10:42:27 -07003193 @NonNull PermissionsState ps, @NonNull AndroidPackage pkg,
Philip P. Moltmanne1233192019-04-18 08:45:55 -07003194 @NonNull ArraySet<String> newImplicitPermissions,
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003195 @NonNull int[] updatedUserIds) {
Winson14ff7172019-10-23 10:42:27 -07003196 String pkgName = pkg.getPackageName();
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003197 ArrayMap<String, ArraySet<String>> newToSplitPerms = new ArrayMap<>();
3198
Anthony Hughde787d42019-08-22 15:35:48 -07003199 final List<SplitPermissionInfoParcelable> permissionList = getSplitPermissions();
3200 int numSplitPerms = permissionList.size();
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003201 for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
Anthony Hughde787d42019-08-22 15:35:48 -07003202 SplitPermissionInfoParcelable spi = permissionList.get(splitPermNum);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003203
3204 List<String> newPerms = spi.getNewPermissions();
3205 int numNewPerms = newPerms.size();
3206 for (int newPermNum = 0; newPermNum < numNewPerms; newPermNum++) {
3207 String newPerm = newPerms.get(newPermNum);
3208
3209 ArraySet<String> splitPerms = newToSplitPerms.get(newPerm);
3210 if (splitPerms == null) {
3211 splitPerms = new ArraySet<>();
3212 newToSplitPerms.put(newPerm, splitPerms);
3213 }
3214
3215 splitPerms.add(spi.getSplitPermission());
3216 }
3217 }
3218
3219 int numNewImplicitPerms = newImplicitPermissions.size();
3220 for (int newImplicitPermNum = 0; newImplicitPermNum < numNewImplicitPerms;
3221 newImplicitPermNum++) {
3222 String newPerm = newImplicitPermissions.valueAt(newImplicitPermNum);
3223 ArraySet<String> sourcePerms = newToSplitPerms.get(newPerm);
3224
3225 if (sourcePerms != null) {
3226 if (!ps.hasInstallPermission(newPerm)) {
3227 BasePermission bp = mSettings.getPermissionLocked(newPerm);
3228
3229 int[] users = UserManagerService.getInstance().getUserIds();
3230 int numUsers = users.length;
3231 for (int userNum = 0; userNum < numUsers; userNum++) {
3232 int userId = users[userNum];
3233
Zimuzoe6411402019-05-13 16:32:57 +01003234 if (!newPerm.equals(Manifest.permission.ACTIVITY_RECOGNITION)) {
3235 ps.updatePermissionFlags(bp, userId,
3236 FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
3237 FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
3238 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003239 updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
3240
Philip P. Moltmannd3e64162019-02-22 16:24:01 -08003241 boolean inheritsFromInstallPerm = false;
3242 for (int sourcePermNum = 0; sourcePermNum < sourcePerms.size();
3243 sourcePermNum++) {
3244 if (ps.hasInstallPermission(sourcePerms.valueAt(sourcePermNum))) {
3245 inheritsFromInstallPerm = true;
Philip P. Moltmannd82bdaf2018-10-30 12:46:40 -07003246 break;
Philip P. Moltmannd82bdaf2018-10-30 12:46:40 -07003247 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003248 }
Philip P. Moltmannd3e64162019-02-22 16:24:01 -08003249
3250 if (!origPs.hasRequestedPermission(sourcePerms)
3251 && !inheritsFromInstallPerm) {
3252 // Both permissions are new so nothing to inherit.
3253 if (DEBUG_PERMISSIONS) {
3254 Slog.i(TAG, newPerm + " does not inherit from " + sourcePerms
3255 + " for " + pkgName + " as split permission is also new");
3256 }
Philip P. Moltmannd3e64162019-02-22 16:24:01 -08003257 } else {
3258 // Inherit from new install or existing runtime permissions
3259 inheritPermissionStateToNewImplicitPermissionLocked(sourcePerms,
3260 newPerm, ps, pkg, userId);
3261 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07003262 }
3263 }
3264 }
3265 }
3266
3267 return updatedUserIds;
3268 }
3269
Anthony Hughde787d42019-08-22 15:35:48 -07003270 @Override
3271 public List<SplitPermissionInfoParcelable> getSplitPermissions() {
3272 return PermissionManager.splitPermissionInfoListToParcelableList(
3273 SystemConfig.getInstance().getSplitPermissions());
3274 }
3275
Evan Seversonb252d8b2019-11-20 08:41:33 -08003276 private OneTimePermissionUserManager getOneTimePermissionUserManager(@UserIdInt int userId) {
Evan Severson2cbceb92020-04-14 18:27:10 +00003277 OneTimePermissionUserManager oneTimePermissionUserManager;
Evan Seversonb252d8b2019-11-20 08:41:33 -08003278 synchronized (mLock) {
Evan Severson2cbceb92020-04-14 18:27:10 +00003279 oneTimePermissionUserManager =
Evan Seversonb252d8b2019-11-20 08:41:33 -08003280 mOneTimePermissionUserManagers.get(userId);
Evan Severson2cbceb92020-04-14 18:27:10 +00003281 if (oneTimePermissionUserManager != null) {
3282 return oneTimePermissionUserManager;
Evan Seversonb252d8b2019-11-20 08:41:33 -08003283 }
Evan Severson2cbceb92020-04-14 18:27:10 +00003284 oneTimePermissionUserManager = new OneTimePermissionUserManager(
3285 mContext.createContextAsUser(UserHandle.of(userId), /*flags*/ 0));
3286 mOneTimePermissionUserManagers.put(userId, oneTimePermissionUserManager);
Evan Seversonb252d8b2019-11-20 08:41:33 -08003287 }
Evan Severson2cbceb92020-04-14 18:27:10 +00003288 oneTimePermissionUserManager.registerUninstallListener();
3289 return oneTimePermissionUserManager;
Evan Seversonb252d8b2019-11-20 08:41:33 -08003290 }
3291
3292 @Override
3293 public void startOneTimePermissionSession(String packageName, @UserIdInt int userId,
3294 long timeoutMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) {
Evan Severson43e17e02020-01-03 10:04:38 -08003295 mContext.enforceCallingPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
3296 "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
3297 + " to register permissions as one time.");
Daulet Zhanguzin82adfcb2020-01-02 17:31:40 +00003298 Objects.requireNonNull(packageName);
Evan Seversonb252d8b2019-11-20 08:41:33 -08003299
3300 long token = Binder.clearCallingIdentity();
3301 try {
3302 getOneTimePermissionUserManager(userId).startPackageOneTimeSession(packageName,
3303 timeoutMillis, importanceToResetTimer, importanceToKeepSessionAlive);
3304 } finally {
3305 Binder.restoreCallingIdentity(token);
3306 }
3307 }
3308
3309 @Override
3310 public void stopOneTimePermissionSession(String packageName, @UserIdInt int userId) {
Evan Severson43e17e02020-01-03 10:04:38 -08003311 mContext.enforceCallingPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
3312 "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
3313 + " to remove permissions as one time.");
Daulet Zhanguzin82adfcb2020-01-02 17:31:40 +00003314 Objects.requireNonNull(packageName);
Evan Seversonb252d8b2019-11-20 08:41:33 -08003315
3316 long token = Binder.clearCallingIdentity();
3317 try {
3318 getOneTimePermissionUserManager(userId).stopPackageOneTimeSession(packageName);
3319 } finally {
3320 Binder.restoreCallingIdentity(token);
3321 }
3322 }
3323
Eugene Susladb77bc12020-03-03 12:09:00 -08003324 @Override
3325 public List<String> getAutoRevokeExemptionRequestedPackages(int userId) {
Eugene Susla49b84c32020-03-23 15:19:29 -07003326 return getPackagesWithAutoRevokePolicy(AUTO_REVOKE_DISCOURAGED, userId);
Eugene Susladb77bc12020-03-03 12:09:00 -08003327 }
3328
3329 @Override
3330 public List<String> getAutoRevokeExemptionGrantedPackages(int userId) {
Eugene Susla49b84c32020-03-23 15:19:29 -07003331 return getPackagesWithAutoRevokePolicy(AUTO_REVOKE_DISALLOWED, userId);
3332 }
3333
3334 @NonNull
3335 private List<String> getPackagesWithAutoRevokePolicy(int autoRevokePolicy, int userId) {
Eugene Susladb77bc12020-03-03 12:09:00 -08003336 mContext.enforceCallingPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
3337 "Must hold " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
3338
3339 List<String> result = new ArrayList<>();
3340 mPackageManagerInt.forEachInstalledPackage(pkg -> {
Eugene Susla49b84c32020-03-23 15:19:29 -07003341 if (pkg.getAutoRevokePermissions() == autoRevokePolicy) {
Eugene Susladb77bc12020-03-03 12:09:00 -08003342 result.add(pkg.getPackageName());
3343 }
3344 }, userId);
Eugene Susladb77bc12020-03-03 12:09:00 -08003345 return result;
3346 }
3347
Winson14ff7172019-10-23 10:42:27 -07003348 private boolean isNewPlatformPermissionForPackage(String perm, AndroidPackage pkg) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003349 boolean allowed = false;
3350 final int NP = PackageParser.NEW_PERMISSIONS.length;
3351 for (int ip=0; ip<NP; ip++) {
3352 final PackageParser.NewPermissionInfo npi
3353 = PackageParser.NEW_PERMISSIONS[ip];
3354 if (npi.name.equals(perm)
Winson14ff7172019-10-23 10:42:27 -07003355 && pkg.getTargetSdkVersion() < npi.sdkVersion) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003356 allowed = true;
3357 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
Winson14ff7172019-10-23 10:42:27 -07003358 + pkg.getPackageName());
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003359 break;
3360 }
3361 }
3362 return allowed;
3363 }
3364
3365 /**
3366 * Determines whether a package is whitelisted for a particular privapp permission.
3367 *
3368 * <p>Does NOT check whether the package is a privapp, just whether it's whitelisted.
3369 *
3370 * <p>This handles parent/child apps.
3371 */
Winson14ff7172019-10-23 10:42:27 -07003372 private boolean hasPrivappWhitelistEntry(String perm, AndroidPackage pkg) {
3373 ArraySet<String> wlPermissions;
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09003374 if (pkg.isVendor()) {
3375 wlPermissions =
Winson14ff7172019-10-23 10:42:27 -07003376 SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.getPackageName());
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09003377 } else if (pkg.isProduct()) {
3378 wlPermissions =
Winson14ff7172019-10-23 10:42:27 -07003379 SystemConfig.getInstance().getProductPrivAppPermissions(pkg.getPackageName());
Jeongik Cha9ec059a2019-07-04 21:12:06 +09003380 } else if (pkg.isSystemExt()) {
Dario Freni2bef1762018-06-01 14:02:08 +01003381 wlPermissions =
Jeongik Cha9ec059a2019-07-04 21:12:06 +09003382 SystemConfig.getInstance().getSystemExtPrivAppPermissions(
Winson14ff7172019-10-23 10:42:27 -07003383 pkg.getPackageName());
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09003384 } else {
Winson14ff7172019-10-23 10:42:27 -07003385 wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.getPackageName());
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09003386 }
Winson14ff7172019-10-23 10:42:27 -07003387
3388 return wlPermissions != null && wlPermissions.contains(perm);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003389 }
3390
Winson14ff7172019-10-23 10:42:27 -07003391 private boolean grantSignaturePermission(String perm, AndroidPackage pkg,
Winsone0756292020-01-31 12:21:54 -08003392 PackageSetting pkgSetting, BasePermission bp, PermissionsState origPermissions) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003393 boolean oemPermission = bp.isOEM();
Jiyong Park002fdbd2017-02-13 20:50:31 +09003394 boolean vendorPrivilegedPermission = bp.isVendorPrivileged();
3395 boolean privilegedPermission = bp.isPrivileged() || bp.isVendorPrivileged();
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003396 boolean privappPermissionsDisable =
3397 RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE;
3398 boolean platformPermission = PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName());
Winson14ff7172019-10-23 10:42:27 -07003399 boolean platformPackage = PLATFORM_PACKAGE_NAME.equals(pkg.getPackageName());
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003400 if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged()
3401 && !platformPackage && platformPermission) {
3402 if (!hasPrivappWhitelistEntry(perm, pkg)) {
Philip P. Moltmannbd278012020-03-10 14:46:27 -07003403 // Only enforce whitelist this on boot
3404 if (!mSystemReady
3405 // Updated system apps do not need to be whitelisted
Philip P. Moltmann67655a12020-03-26 17:22:40 -07003406 && !pkgSetting.getPkgState().isUpdatedSystemApp()) {
3407 ApexManager apexMgr = ApexManager.getInstance();
3408 String apexContainingPkg = apexMgr.getActiveApexPackageNameContainingPackage(
3409 pkg);
Fyodor Kupolovf5e600d2017-10-25 17:03:50 -07003410
Philip P. Moltmann67655a12020-03-26 17:22:40 -07003411 // Apps that are in updated apexs' do not need to be whitelisted
3412 if (apexContainingPkg == null || apexMgr.isFactory(
3413 apexMgr.getPackageInfo(apexContainingPkg, MATCH_ACTIVE_PACKAGE))) {
3414 // it's only a reportable violation if the permission isn't explicitly
3415 // denied
3416 ArraySet<String> deniedPermissions = null;
3417 if (pkg.isVendor()) {
3418 deniedPermissions = SystemConfig.getInstance()
3419 .getVendorPrivAppDenyPermissions(pkg.getPackageName());
3420 } else if (pkg.isProduct()) {
3421 deniedPermissions = SystemConfig.getInstance()
3422 .getProductPrivAppDenyPermissions(pkg.getPackageName());
3423 } else if (pkg.isSystemExt()) {
3424 deniedPermissions = SystemConfig.getInstance()
3425 .getSystemExtPrivAppDenyPermissions(pkg.getPackageName());
3426 } else {
3427 deniedPermissions = SystemConfig.getInstance()
3428 .getPrivAppDenyPermissions(pkg.getPackageName());
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003429 }
Philip P. Moltmann67655a12020-03-26 17:22:40 -07003430 final boolean permissionViolation =
3431 deniedPermissions == null || !deniedPermissions.contains(perm);
3432 if (permissionViolation) {
3433 Slog.w(TAG, "Privileged permission " + perm + " for package "
3434 + pkg.getPackageName() + " (" + pkg.getCodePath()
3435 + ") not in privapp-permissions whitelist");
3436
3437 if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
3438 if (mPrivappPermissionsViolations == null) {
3439 mPrivappPermissionsViolations = new ArraySet<>();
3440 }
3441 mPrivappPermissionsViolations.add(
3442 pkg.getPackageName() + " (" + pkg.getCodePath() + "): "
3443 + perm);
3444 }
3445 } else {
3446 return false;
3447 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003448 }
3449 }
3450 if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
3451 return false;
3452 }
3453 }
3454 }
Chen Xu45c183d2019-10-07 00:24:41 -07003455 // expect single system package
3456 String systemPackageName = ArrayUtils.firstOrNull(mPackageManagerInt.getKnownPackageNames(
3457 PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM));
Winson655a5b92019-10-23 10:49:32 -07003458 final AndroidPackage systemPackage =
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003459 mPackageManagerInt.getPackage(systemPackageName);
Dan Cashman1dbe6d02018-01-23 11:18:28 -08003460
3461 // check if the package is allow to use this signature permission. A package is allowed to
3462 // use a signature permission if:
3463 // - it has the same set of signing certificates as the source package
3464 // - or its signing certificate was rotated from the source package's certificate
3465 // - or its signing certificate is a previous signing certificate of the defining
3466 // package, and the defining package still trusts the old certificate for permissions
3467 // - or it shares the above relationships with the system package
Songchun Fane5c0afe2020-04-22 12:22:52 -07003468 final PackageParser.SigningDetails sourceSigningDetails =
3469 getSourcePackageSigningDetails(bp);
Dan Cashman1dbe6d02018-01-23 11:18:28 -08003470 boolean allowed =
Songchun Fane5c0afe2020-04-22 12:22:52 -07003471 pkg.getSigningDetails().hasAncestorOrSelf(sourceSigningDetails)
3472 || sourceSigningDetails.checkCapability(
Winson14ff7172019-10-23 10:42:27 -07003473 pkg.getSigningDetails(),
Dan Cashman1dbe6d02018-01-23 11:18:28 -08003474 PackageParser.SigningDetails.CertCapabilities.PERMISSION)
Winson14ff7172019-10-23 10:42:27 -07003475 || pkg.getSigningDetails().hasAncestorOrSelf(systemPackage.getSigningDetails())
3476 || systemPackage.getSigningDetails().checkCapability(
3477 pkg.getSigningDetails(),
Dan Cashman1dbe6d02018-01-23 11:18:28 -08003478 PackageParser.SigningDetails.CertCapabilities.PERMISSION);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003479 if (!allowed && (privilegedPermission || oemPermission)) {
3480 if (pkg.isSystem()) {
3481 // For updated system applications, a privileged/oem permission
3482 // is granted only if it had been defined by the original application.
Winsone0756292020-01-31 12:21:54 -08003483 if (pkgSetting.getPkgState().isUpdatedSystemApp()) {
3484 final PackageSetting disabledPs = mPackageManagerInt
Winson14ff7172019-10-23 10:42:27 -07003485 .getDisabledSystemPackage(pkg.getPackageName());
3486 final AndroidPackage disabledPkg = disabledPs == null ? null : disabledPs.pkg;
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003487 if (disabledPs != null
3488 && disabledPs.getPermissionsState().hasInstallPermission(perm)) {
3489 // If the original was granted this permission, we take
3490 // that grant decision as read and propagate it to the
3491 // update.
3492 if ((privilegedPermission && disabledPs.isPrivileged())
3493 || (oemPermission && disabledPs.isOem()
3494 && canGrantOemPermission(disabledPs, perm))) {
3495 allowed = true;
3496 }
3497 } else {
3498 // The system apk may have been updated with an older
3499 // version of the one on the data partition, but which
3500 // granted a new system permission that it didn't have
3501 // before. In this case we do want to allow the app to
3502 // now get the new permission if the ancestral apk is
3503 // privileged to get it.
Todd Kennedy1efb8332017-10-25 15:51:36 -07003504 if (disabledPs != null && disabledPkg != null
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003505 && isPackageRequestingPermission(disabledPkg, perm)
3506 && ((privilegedPermission && disabledPs.isPrivileged())
3507 || (oemPermission && disabledPs.isOem()
3508 && canGrantOemPermission(disabledPs, perm)))) {
3509 allowed = true;
3510 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003511 }
3512 } else {
Winson14ff7172019-10-23 10:42:27 -07003513 final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
3514 pkg.getPackageName());
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003515 allowed = (privilegedPermission && pkg.isPrivileged())
3516 || (oemPermission && pkg.isOem()
3517 && canGrantOemPermission(ps, perm));
3518 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09003519 // In any case, don't grant a privileged permission to privileged vendor apps, if
3520 // the permission's protectionLevel does not have the extra 'vendorPrivileged'
3521 // flag.
3522 if (allowed && privilegedPermission &&
3523 !vendorPrivilegedPermission && pkg.isVendor()) {
3524 Slog.w(TAG, "Permission " + perm + " cannot be granted to privileged vendor apk "
Winson14ff7172019-10-23 10:42:27 -07003525 + pkg.getPackageName()
3526 + " because it isn't a 'vendorPrivileged' permission.");
Jiyong Park002fdbd2017-02-13 20:50:31 +09003527 allowed = false;
3528 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003529 }
3530 }
3531 if (!allowed) {
3532 if (!allowed
3533 && bp.isPre23()
Winson14ff7172019-10-23 10:42:27 -07003534 && pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003535 // If this was a previously normal/dangerous permission that got moved
3536 // to a system permission as part of the runtime permission redesign, then
3537 // we still want to blindly grant it to old apps.
3538 allowed = true;
3539 }
Philip P. Moltmann8943ad62018-07-25 12:12:30 -07003540 // TODO (moltmann): The installer now shares the platforms signature. Hence it does not
3541 // need a separate flag anymore. Hence we need to check which
3542 // permissions are needed by the permission controller
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003543 if (!allowed && bp.isInstaller()
Chen Xu45c183d2019-10-07 00:24:41 -07003544 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3545 PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM),
Winson655a5b92019-10-23 10:49:32 -07003546 pkg.getPackageName()) || ArrayUtils.contains(
3547 mPackageManagerInt.getKnownPackageNames(
3548 PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER,
3549 UserHandle.USER_SYSTEM), pkg.getPackageName())) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003550 // If this permission is to be granted to the system installer and
3551 // this app is an installer, then it gets the permission.
3552 allowed = true;
3553 }
3554 if (!allowed && bp.isVerifier()
Chen Xu45c183d2019-10-07 00:24:41 -07003555 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3556 PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM),
Winson655a5b92019-10-23 10:49:32 -07003557 pkg.getPackageName())) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003558 // If this permission is to be granted to the system verifier and
3559 // this app is a verifier, then it gets the permission.
3560 allowed = true;
3561 }
3562 if (!allowed && bp.isPreInstalled()
3563 && pkg.isSystem()) {
3564 // Any pre-installed system app is allowed to get this permission.
3565 allowed = true;
3566 }
3567 if (!allowed && bp.isDevelopment()) {
3568 // For development permissions, a development permission
3569 // is granted only if it was already granted.
3570 allowed = origPermissions.hasInstallPermission(perm);
3571 }
3572 if (!allowed && bp.isSetup()
Chen Xu45c183d2019-10-07 00:24:41 -07003573 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3574 PackageManagerInternal.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM),
Winson655a5b92019-10-23 10:49:32 -07003575 pkg.getPackageName())) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003576 // If this permission is to be granted to the system setup wizard and
3577 // this app is a setup wizard, then it gets the permission.
3578 allowed = true;
3579 }
Makoto Onuki700feef2018-02-15 10:59:41 -08003580 if (!allowed && bp.isSystemTextClassifier()
Chen Xu45c183d2019-10-07 00:24:41 -07003581 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
Makoto Onuki700feef2018-02-15 10:59:41 -08003582 PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER,
Winson655a5b92019-10-23 10:49:32 -07003583 UserHandle.USER_SYSTEM), pkg.getPackageName())) {
Makoto Onuki700feef2018-02-15 10:59:41 -08003584 // Special permissions for the system default text classifier.
3585 allowed = true;
3586 }
Stanislav Zholnin596437f2018-12-28 15:34:23 +00003587 if (!allowed && bp.isConfigurator()
Chen Xu45c183d2019-10-07 00:24:41 -07003588 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3589 PackageManagerInternal.PACKAGE_CONFIGURATOR,
Winson655a5b92019-10-23 10:49:32 -07003590 UserHandle.USER_SYSTEM), pkg.getPackageName())) {
Stanislav Zholnin596437f2018-12-28 15:34:23 +00003591 // Special permissions for the device configurator.
3592 allowed = true;
3593 }
Varun Shah5f303652018-11-16 18:11:19 -08003594 if (!allowed && bp.isWellbeing()
Chen Xu45c183d2019-10-07 00:24:41 -07003595 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3596 PackageManagerInternal.PACKAGE_WELLBEING, UserHandle.USER_SYSTEM),
Winson655a5b92019-10-23 10:49:32 -07003597 pkg.getPackageName())) {
Varun Shah5f303652018-11-16 18:11:19 -08003598 // Special permission granted only to the OEM specified wellbeing app
3599 allowed = true;
3600 }
Jeff Sharkey15707b32018-12-10 12:08:41 -07003601 if (!allowed && bp.isDocumenter()
Chen Xu45c183d2019-10-07 00:24:41 -07003602 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3603 PackageManagerInternal.PACKAGE_DOCUMENTER, UserHandle.USER_SYSTEM),
Winson655a5b92019-10-23 10:49:32 -07003604 pkg.getPackageName())) {
Jeff Sharkey15707b32018-12-10 12:08:41 -07003605 // If this permission is to be granted to the documenter and
3606 // this app is the documenter, then it gets the permission.
3607 allowed = true;
3608 }
Joe Onorato5a15b552018-12-18 10:40:04 -08003609 if (!allowed && bp.isIncidentReportApprover()
Chen Xu45c183d2019-10-07 00:24:41 -07003610 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
Joe Onorato5a15b552018-12-18 10:40:04 -08003611 PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER,
Winson655a5b92019-10-23 10:49:32 -07003612 UserHandle.USER_SYSTEM), pkg.getPackageName())) {
Joe Onorato5a15b552018-12-18 10:40:04 -08003613 // If this permission is to be granted to the incident report approver and
3614 // this app is the incident report approver, then it gets the permission.
3615 allowed = true;
3616 }
George Hodulikcd7695d2019-01-29 18:17:05 -08003617 if (!allowed && bp.isAppPredictor()
Chen Xu45c183d2019-10-07 00:24:41 -07003618 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3619 PackageManagerInternal.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM),
Winson655a5b92019-10-23 10:49:32 -07003620 pkg.getPackageName())) {
George Hodulikcd7695d2019-01-29 18:17:05 -08003621 // Special permissions for the system app predictor.
3622 allowed = true;
3623 }
Eugene Susla1fa23ed02019-07-24 16:30:16 -07003624 if (!allowed && bp.isCompanion()
3625 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3626 PackageManagerInternal.PACKAGE_COMPANION, UserHandle.USER_SYSTEM),
3627 pkg.getPackageName())) {
3628 // Special permissions for the system companion device manager.
3629 allowed = true;
3630 }
wayneyang8126b1f2020-01-09 14:10:31 +08003631 if (!allowed && bp.isRetailDemo()
3632 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3633 PackageManagerInternal.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM),
3634 pkg.getPackageName()) && isProfileOwner(pkg.getUid())) {
3635 // Special permission granted only to the OEM specified retail demo app
3636 allowed = true;
3637 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003638 }
3639 return allowed;
3640 }
3641
Songchun Fane5c0afe2020-04-22 12:22:52 -07003642 @NonNull
3643 private PackageParser.SigningDetails getSourcePackageSigningDetails(
3644 @NonNull BasePermission bp) {
3645 final PackageSetting ps = getSourcePackageSetting(bp);
3646 if (ps == null) {
3647 return PackageParser.SigningDetails.UNKNOWN;
3648 }
3649 return ps.getSigningDetails();
3650 }
3651
3652 @Nullable
3653 private PackageSetting getSourcePackageSetting(@NonNull BasePermission bp) {
3654 final String sourcePackageName = bp.getSourcePackageName();
3655 return mPackageManagerInt.getPackageSetting(sourcePackageName);
3656 }
3657
wayneyang8126b1f2020-01-09 14:10:31 +08003658 private static boolean isProfileOwner(int uid) {
3659 DevicePolicyManagerInternal dpmInternal =
3660 LocalServices.getService(DevicePolicyManagerInternal.class);
3661 if (dpmInternal != null) {
3662 return dpmInternal
3663 .isActiveAdminWithPolicy(uid, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
3664 }
3665 return false;
3666 }
3667
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003668 private static boolean canGrantOemPermission(PackageSetting ps, String permission) {
3669 if (!ps.isOem()) {
3670 return false;
3671 }
3672 // all oem permissions must explicitly be granted or denied
3673 final Boolean granted =
3674 SystemConfig.getInstance().getOemPermissions(ps.name).get(permission);
3675 if (granted == null) {
3676 throw new IllegalStateException("OEM permission" + permission + " requested by package "
3677 + ps.name + " must be explicitly declared granted or not");
3678 }
3679 return Boolean.TRUE == granted;
3680 }
3681
Winson14ff7172019-10-23 10:42:27 -07003682 private boolean isPermissionsReviewRequired(@NonNull AndroidPackage pkg,
Philip P. Moltmannc91ff6f2019-06-14 14:35:42 -07003683 @UserIdInt int userId) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003684 // Permission review applies only to apps not supporting the new permission model.
Winson14ff7172019-10-23 10:42:27 -07003685 if (pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003686 return false;
3687 }
3688
3689 // Legacy apps have the permission and get user consent on launch.
Winson14ff7172019-10-23 10:42:27 -07003690 final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
3691 pkg.getPackageName());
3692 if (ps == null) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003693 return false;
3694 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003695 final PermissionsState permissionsState = ps.getPermissionsState();
3696 return permissionsState.isPermissionReviewRequired(userId);
3697 }
3698
Winson14ff7172019-10-23 10:42:27 -07003699 private boolean isPackageRequestingPermission(AndroidPackage pkg, String permission) {
3700 final int permCount = pkg.getRequestedPermissions().size();
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003701 for (int j = 0; j < permCount; j++) {
Winson14ff7172019-10-23 10:42:27 -07003702 String requestedPermission = pkg.getRequestedPermissions().get(j);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003703 if (permission.equals(requestedPermission)) {
3704 return true;
3705 }
3706 }
3707 return false;
3708 }
3709
Winson14ff7172019-10-23 10:42:27 -07003710 private void grantRequestedRuntimePermissions(AndroidPackage pkg, int[] userIds,
Todd Kennedy0eb97382017-10-03 16:57:22 -07003711 String[] grantedPermissions, int callingUid, PermissionCallback callback) {
3712 for (int userId : userIds) {
3713 grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions, callingUid,
3714 callback);
3715 }
3716 }
3717
Winson14ff7172019-10-23 10:42:27 -07003718 private void grantRequestedRuntimePermissionsForUser(AndroidPackage pkg, int userId,
Todd Kennedy0eb97382017-10-03 16:57:22 -07003719 String[] grantedPermissions, int callingUid, PermissionCallback callback) {
Winson14ff7172019-10-23 10:42:27 -07003720 PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
3721 pkg.getPackageName());
Todd Kennedy0eb97382017-10-03 16:57:22 -07003722 if (ps == null) {
3723 return;
3724 }
3725
3726 PermissionsState permissionsState = ps.getPermissionsState();
3727
3728 final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
3729 | PackageManager.FLAG_PERMISSION_POLICY_FIXED;
3730
Hai Zhangfa291702019-09-19 16:35:44 -07003731 final int compatFlags = PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
3732 | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
3733
Winson14ff7172019-10-23 10:42:27 -07003734 final boolean supportsRuntimePermissions = pkg.getTargetSdkVersion()
Todd Kennedy0eb97382017-10-03 16:57:22 -07003735 >= Build.VERSION_CODES.M;
3736
Winson14ff7172019-10-23 10:42:27 -07003737 final boolean instantApp = mPackageManagerInt.isInstantApp(pkg.getPackageName(), userId);
Todd Kennedy0eb97382017-10-03 16:57:22 -07003738
Winson14ff7172019-10-23 10:42:27 -07003739 for (String permission : pkg.getRequestedPermissions()) {
Todd Kennedy0eb97382017-10-03 16:57:22 -07003740 final BasePermission bp;
3741 synchronized (mLock) {
3742 bp = mSettings.getPermissionLocked(permission);
3743 }
3744 if (bp != null && (bp.isRuntime() || bp.isDevelopment())
3745 && (!instantApp || bp.isInstant())
3746 && (supportsRuntimePermissions || !bp.isRuntimeOnly())
3747 && (grantedPermissions == null
3748 || ArrayUtils.contains(grantedPermissions, permission))) {
3749 final int flags = permissionsState.getPermissionFlags(permission, userId);
3750 if (supportsRuntimePermissions) {
3751 // Installer cannot change immutable permissions.
3752 if ((flags & immutableFlags) == 0) {
Winson14ff7172019-10-23 10:42:27 -07003753 grantRuntimePermissionInternal(permission, pkg.getPackageName(), false,
Todd Kennedyc971a452019-07-08 16:04:52 -07003754 callingUid, userId, callback);
Todd Kennedy0eb97382017-10-03 16:57:22 -07003755 }
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07003756 } else {
Hai Zhangfa291702019-09-19 16:35:44 -07003757 // In permission review mode we clear the review flag and the revoked compat
3758 // flag when we are asked to install the app with all permissions granted.
3759 if ((flags & compatFlags) != 0) {
Winson14ff7172019-10-23 10:42:27 -07003760 updatePermissionFlagsInternal(permission, pkg.getPackageName(), compatFlags,
Hai Zhangfa291702019-09-19 16:35:44 -07003761 0, callingUid, userId, false, callback);
Todd Kennedy0eb97382017-10-03 16:57:22 -07003762 }
3763 }
3764 }
3765 }
3766 }
3767
Nate Myrenc92df182020-06-23 16:31:39 -07003768 private void setWhitelistedRestrictedPermissionsForUsers(@NonNull AndroidPackage pkg,
3769 @UserIdInt int[] userIds, @Nullable List<String> permissions, int callingUid,
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003770 @PermissionWhitelistFlags int whitelistFlags, PermissionCallback callback) {
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07003771 final PermissionsState permissionsState =
Winson14ff7172019-10-23 10:42:27 -07003772 PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07003773 if (permissionsState == null) {
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003774 return;
3775 }
3776
Nate Myrenc92df182020-06-23 16:31:39 -07003777 SparseArray<ArraySet<String>> oldGrantedRestrictedPermissions = new SparseArray<>();
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003778 boolean updatePermissions = false;
Winson14ff7172019-10-23 10:42:27 -07003779 final int permissionCount = pkg.getRequestedPermissions().size();
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003780
Nate Myrenc92df182020-06-23 16:31:39 -07003781 for (int i = 0; i < userIds.length; i++) {
3782 int userId = userIds[i];
3783 for (int j = 0; j < permissionCount; j++) {
3784 final String permissionName = pkg.getRequestedPermissions().get(j);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003785
Nate Myrenc92df182020-06-23 16:31:39 -07003786 final BasePermission bp = mSettings.getPermissionLocked(permissionName);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003787
Nate Myrenc92df182020-06-23 16:31:39 -07003788 if (bp == null || !bp.isHardOrSoftRestricted()) {
3789 continue;
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003790 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003791
Nate Myrenc92df182020-06-23 16:31:39 -07003792 if (permissionsState.hasPermission(permissionName, userId)) {
3793 if (oldGrantedRestrictedPermissions.get(userId) == null) {
3794 oldGrantedRestrictedPermissions.put(userId, new ArraySet<>());
3795 }
3796 oldGrantedRestrictedPermissions.get(userId).add(permissionName);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003797 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003798
Nate Myrenc92df182020-06-23 16:31:39 -07003799 final int oldFlags = permissionsState.getPermissionFlags(permissionName, userId);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003800
Nate Myrenc92df182020-06-23 16:31:39 -07003801 int newFlags = oldFlags;
3802 int mask = 0;
3803 int whitelistFlagsCopy = whitelistFlags;
3804 while (whitelistFlagsCopy != 0) {
3805 final int flag = 1 << Integer.numberOfTrailingZeros(whitelistFlagsCopy);
3806 whitelistFlagsCopy &= ~flag;
3807 switch (flag) {
3808 case FLAG_PERMISSION_WHITELIST_SYSTEM: {
3809 mask |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
3810 if (permissions != null && permissions.contains(permissionName)) {
3811 newFlags |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
3812 } else {
3813 newFlags &= ~FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
3814 }
3815 }
3816 break;
3817 case FLAG_PERMISSION_WHITELIST_UPGRADE: {
3818 mask |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
3819 if (permissions != null && permissions.contains(permissionName)) {
3820 newFlags |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
3821 } else {
3822 newFlags &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
3823 }
3824 }
3825 break;
3826 case FLAG_PERMISSION_WHITELIST_INSTALLER: {
3827 mask |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
3828 if (permissions != null && permissions.contains(permissionName)) {
3829 newFlags |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
3830 } else {
3831 newFlags &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
3832 }
3833 }
3834 break;
3835 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003836 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003837
Nate Myrenc92df182020-06-23 16:31:39 -07003838 if (oldFlags == newFlags) {
3839 continue;
3840 }
Svet Ganovd563e932019-04-14 13:07:41 -07003841
Nate Myrenc92df182020-06-23 16:31:39 -07003842 updatePermissions = true;
3843
3844 final boolean wasWhitelisted = (oldFlags
3845 & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
3846 final boolean isWhitelisted = (newFlags
3847 & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
3848
3849 // If the permission is policy fixed as granted but it is no longer
3850 // on any of the whitelists we need to clear the policy fixed flag
3851 // as whitelisting trumps policy i.e. policy cannot grant a non
3852 // grantable permission.
3853 if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
3854 final boolean isGranted = permissionsState.hasPermission(permissionName,
3855 userId);
3856 if (!isWhitelisted && isGranted) {
3857 mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED;
3858 newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
3859 }
3860 }
3861
3862 // If we are whitelisting an app that does not support runtime permissions
3863 // we need to make sure it goes through the permission review UI at launch.
3864 if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M
3865 && !wasWhitelisted && isWhitelisted) {
3866 mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
3867 newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
3868 }
3869
3870 updatePermissionFlagsInternal(permissionName, pkg.getPackageName(), mask, newFlags,
3871 callingUid, userId, false, null /*callback*/);
3872 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003873 }
3874
3875 if (updatePermissions) {
Philip P. Moltmannba742062019-04-08 13:22:44 -07003876 // Update permission of this app to take into account the new whitelist state.
Winson14ff7172019-10-23 10:42:27 -07003877 restorePermissionState(pkg, false, pkg.getPackageName(), callback);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003878
3879 // If this resulted in losing a permission we need to kill the app.
Nate Myrenc92df182020-06-23 16:31:39 -07003880 for (int i = 0; i < userIds.length; i++) {
3881 int userId = userIds[i];
3882 ArraySet<String> oldPermsForUser = oldGrantedRestrictedPermissions.get(userId);
3883 if (oldPermsForUser == null) {
3884 continue;
3885 }
3886
3887 final int oldGrantedCount = oldPermsForUser.size();
3888 for (int j = 0; j < oldGrantedCount; j++) {
3889 final String permission = oldPermsForUser.valueAt(j);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003890 // Sometimes we create a new permission state instance during update.
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07003891 final PermissionsState newPermissionsState =
Nate Myrenc92df182020-06-23 16:31:39 -07003892 PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt,
3893 pkg);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07003894 if (!newPermissionsState.hasPermission(permission, userId)) {
Evan Seversonaacd48b2020-06-22 16:45:03 -07003895 callback.onPermissionRevoked(pkg.getUid(), userId, null);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003896 break;
3897 }
3898 }
3899 }
3900 }
Todd Kennedy0eb97382017-10-03 16:57:22 -07003901 }
3902
Andreas Gampea36dc622018-02-05 17:19:22 -08003903 @GuardedBy("mLock")
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003904 private int[] revokeUnusedSharedUserPermissionsLocked(
3905 SharedUserSetting suSetting, int[] allUserIds) {
Todd Kennedy0eb97382017-10-03 16:57:22 -07003906 // Collect all used permissions in the UID
3907 final ArraySet<String> usedPermissions = new ArraySet<>();
Winson14ff7172019-10-23 10:42:27 -07003908 final List<AndroidPackage> pkgList = suSetting.getPackages();
Todd Kennedy0eb97382017-10-03 16:57:22 -07003909 if (pkgList == null || pkgList.size() == 0) {
3910 return EmptyArray.INT;
3911 }
Winson14ff7172019-10-23 10:42:27 -07003912 for (AndroidPackage pkg : pkgList) {
Winsone23ae202020-01-24 11:56:44 -08003913 if (pkg.getRequestedPermissions().isEmpty()) {
Svet Ganovd8308072018-03-24 00:04:38 -07003914 continue;
3915 }
Winson14ff7172019-10-23 10:42:27 -07003916 final int requestedPermCount = pkg.getRequestedPermissions().size();
Todd Kennedy0eb97382017-10-03 16:57:22 -07003917 for (int j = 0; j < requestedPermCount; j++) {
Winson14ff7172019-10-23 10:42:27 -07003918 String permission = pkg.getRequestedPermissions().get(j);
Todd Kennedy0eb97382017-10-03 16:57:22 -07003919 BasePermission bp = mSettings.getPermissionLocked(permission);
3920 if (bp != null) {
3921 usedPermissions.add(permission);
3922 }
3923 }
3924 }
3925
3926 PermissionsState permissionsState = suSetting.getPermissionsState();
3927 // Prune install permissions
3928 List<PermissionState> installPermStates = permissionsState.getInstallPermissionStates();
3929 final int installPermCount = installPermStates.size();
3930 for (int i = installPermCount - 1; i >= 0; i--) {
3931 PermissionState permissionState = installPermStates.get(i);
3932 if (!usedPermissions.contains(permissionState.getName())) {
3933 BasePermission bp = mSettings.getPermissionLocked(permissionState.getName());
3934 if (bp != null) {
3935 permissionsState.revokeInstallPermission(bp);
3936 permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
Philip P. Moltmann76597692019-03-02 13:18:41 -08003937 MASK_PERMISSION_FLAGS_ALL, 0);
Todd Kennedy0eb97382017-10-03 16:57:22 -07003938 }
3939 }
3940 }
3941
3942 int[] runtimePermissionChangedUserIds = EmptyArray.INT;
3943
3944 // Prune runtime permissions
3945 for (int userId : allUserIds) {
3946 List<PermissionState> runtimePermStates = permissionsState
3947 .getRuntimePermissionStates(userId);
3948 final int runtimePermCount = runtimePermStates.size();
3949 for (int i = runtimePermCount - 1; i >= 0; i--) {
3950 PermissionState permissionState = runtimePermStates.get(i);
3951 if (!usedPermissions.contains(permissionState.getName())) {
3952 BasePermission bp = mSettings.getPermissionLocked(permissionState.getName());
3953 if (bp != null) {
3954 permissionsState.revokeRuntimePermission(bp, userId);
3955 permissionsState.updatePermissionFlags(bp, userId,
Philip P. Moltmann76597692019-03-02 13:18:41 -08003956 MASK_PERMISSION_FLAGS_ALL, 0);
Todd Kennedy0eb97382017-10-03 16:57:22 -07003957 runtimePermissionChangedUserIds = ArrayUtils.appendInt(
3958 runtimePermissionChangedUserIds, userId);
3959 }
3960 }
3961 }
3962 }
3963
3964 return runtimePermissionChangedUserIds;
3965 }
3966
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07003967 /**
3968 * Update permissions when a package changed.
3969 *
3970 * <p><ol>
3971 * <li>Reconsider the ownership of permission</li>
3972 * <li>Update the state (grant, flags) of the permissions</li>
3973 * </ol>
3974 *
3975 * @param packageName The package that is updated
3976 * @param pkg The package that is updated, or {@code null} if package is deleted
3977 * @param allPackages All currently known packages
3978 * @param callback Callback to call after permission changes
3979 */
Winson14ff7172019-10-23 10:42:27 -07003980 private void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg,
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07003981 @NonNull PermissionCallback callback) {
Songchun Fanbcc899e2020-04-06 16:51:45 -07003982 // If the package is being deleted, update the permissions of all the apps
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07003983 final int flags =
Songchun Fanbcc899e2020-04-06 16:51:45 -07003984 (pkg == null ? UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG
3985 : UPDATE_PERMISSIONS_REPLACE_PKG);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003986 updatePermissions(
Todd Kennedyc971a452019-07-08 16:04:52 -07003987 packageName, pkg, getVolumeUuidForPackage(pkg), flags, callback);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07003988 }
3989
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07003990 /**
3991 * Update all permissions for all apps.
3992 *
3993 * <p><ol>
3994 * <li>Reconsider the ownership of permission</li>
3995 * <li>Update the state (grant, flags) of the permissions</li>
3996 * </ol>
3997 *
3998 * @param volumeUuid The volume of the packages to be updated, {@code null} for all volumes
3999 * @param allPackages All currently known packages
4000 * @param callback Callback to call after permission changes
4001 */
4002 private void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated,
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004003 @NonNull PermissionCallback callback) {
Daniel Colascione33fb4ef2020-03-04 17:27:56 -08004004 PackageManager.corkPackageInfoCache(); // Prevent invalidation storm
4005 try {
4006 final int flags = UPDATE_PERMISSIONS_ALL |
4007 (sdkUpdated
4008 ? UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL
4009 : 0);
4010 updatePermissions(null, null, volumeUuid, flags, callback);
4011 } finally {
4012 PackageManager.uncorkPackageInfoCache();
4013 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004014 }
4015
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004016 /**
4017 * Cache background->foreground permission mapping.
4018 *
4019 * <p>This is only run once.
4020 */
4021 private void cacheBackgroundToForegoundPermissionMapping() {
Philip P. Moltmanne1b277a2018-11-01 16:22:50 -07004022 synchronized (mLock) {
4023 if (mBackgroundPermissions == null) {
4024 // Cache background -> foreground permission mapping.
4025 // Only system declares background permissions, hence mapping does never change.
4026 mBackgroundPermissions = new ArrayMap<>();
4027 for (BasePermission bp : mSettings.getAllPermissionsLocked()) {
Winsonf00c7552020-01-28 12:52:01 -08004028 if (bp.perm != null && bp.perm.getBackgroundPermission() != null) {
Philip P. Moltmanne1b277a2018-11-01 16:22:50 -07004029 String fgPerm = bp.name;
Winsonf00c7552020-01-28 12:52:01 -08004030 String bgPerm = bp.perm.getBackgroundPermission();
Philip P. Moltmanne1b277a2018-11-01 16:22:50 -07004031
4032 List<String> fgPerms = mBackgroundPermissions.get(bgPerm);
4033 if (fgPerms == null) {
4034 fgPerms = new ArrayList<>();
4035 mBackgroundPermissions.put(bgPerm, fgPerms);
4036 }
4037
4038 fgPerms.add(fgPerm);
4039 }
4040 }
4041 }
4042 }
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004043 }
4044
4045 /**
4046 * Update all packages on the volume, <u>beside</u> the changing package. If the changing
4047 * package is set too, all packages are updated.
4048 */
4049 private static final int UPDATE_PERMISSIONS_ALL = 1 << 0;
4050 /** The changing package is replaced. Requires the changing package to be set */
4051 private static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1 << 1;
4052 /**
4053 * Schedule all packages <u>beside</u> the changing package for replacement. Requires
4054 * UPDATE_PERMISSIONS_ALL to be set
4055 */
4056 private static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1 << 2;
4057
4058 @IntDef(flag = true, prefix = { "UPDATE_PERMISSIONS_" }, value = {
4059 UPDATE_PERMISSIONS_ALL, UPDATE_PERMISSIONS_REPLACE_PKG,
4060 UPDATE_PERMISSIONS_REPLACE_ALL })
4061 @Retention(RetentionPolicy.SOURCE)
4062 private @interface UpdatePermissionFlags {}
4063
4064 /**
4065 * Update permissions when packages changed.
4066 *
4067 * <p><ol>
4068 * <li>Reconsider the ownership of permission</li>
4069 * <li>Update the state (grant, flags) of the permissions</li>
4070 * </ol>
4071 *
4072 * <p>Meaning of combination of package parameters:
4073 * <table>
4074 * <tr><th></th><th>changingPkgName != null</th><th>changingPkgName == null</th></tr>
4075 * <tr><th>changingPkg != null</th><td>package is updated</td><td>invalid</td></tr>
4076 * <tr><th>changingPkg == null</th><td>package is deleted</td><td>all packages are
4077 * updated</td></tr>
4078 * </table>
4079 *
4080 * @param changingPkgName The package that is updated, or {@code null} if all packages should be
4081 * updated
4082 * @param changingPkg The package that is updated, or {@code null} if all packages should be
4083 * updated or package is deleted
4084 * @param replaceVolumeUuid The volume of the packages to be updated are on, {@code null} for
4085 * all volumes
4086 * @param flags Control permission for which apps should be updated
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004087 * @param callback Callback to call after permission changes
4088 */
Todd Kennedyc971a452019-07-08 16:04:52 -07004089 private void updatePermissions(final @Nullable String changingPkgName,
Winson14ff7172019-10-23 10:42:27 -07004090 final @Nullable AndroidPackage changingPkg,
Todd Kennedyc971a452019-07-08 16:04:52 -07004091 final @Nullable String replaceVolumeUuid,
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004092 @UpdatePermissionFlags int flags,
Todd Kennedyc971a452019-07-08 16:04:52 -07004093 final @Nullable PermissionCallback callback) {
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004094 // TODO: Most of the methods exposing BasePermission internals [source package name,
4095 // etc..] shouldn't be needed. Instead, when we've parsed a permission that doesn't
4096 // have package settings, we should make note of it elsewhere [map between
4097 // source package name and BasePermission] and cycle through that here. Then we
4098 // define a single method on BasePermission that takes a PackageSetting, changing
4099 // package name and a package.
4100 // NOTE: With this approach, we also don't need to tree trees differently than
4101 // normal permissions. Today, we need two separate loops because these BasePermission
4102 // objects are stored separately.
4103 // Make sure there are no dangling permission trees.
4104 boolean permissionTreesSourcePackageChanged = updatePermissionTreeSourcePackage(
4105 changingPkgName, changingPkg);
4106 // Make sure all dynamic permissions have been assigned to a package,
4107 // and make sure there are no dangling permissions.
4108 boolean permissionSourcePackageChanged = updatePermissionSourcePackage(changingPkgName,
Hongming Jinbc4d0102019-08-16 14:28:30 -07004109 changingPkg, callback);
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004110
4111 if (permissionTreesSourcePackageChanged | permissionSourcePackageChanged) {
4112 // Permission ownership has changed. This e.g. changes which packages can get signature
4113 // permissions
Songchun Fanbcc899e2020-04-06 16:51:45 -07004114 Slog.i(TAG, "Permission ownership changed. Updating all permissions.");
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004115 flags |= UPDATE_PERMISSIONS_ALL;
4116 }
4117
4118 cacheBackgroundToForegoundPermissionMapping();
Philip P. Moltmanne1b277a2018-11-01 16:22:50 -07004119
Philip P. Moltmanne0f00ea2018-10-30 10:43:15 -07004120 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "restorePermissionState");
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004121 // Now update the permissions for all packages.
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004122 if ((flags & UPDATE_PERMISSIONS_ALL) != 0) {
Todd Kennedyc971a452019-07-08 16:04:52 -07004123 final boolean replaceAll = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0);
Winson14ff7172019-10-23 10:42:27 -07004124 mPackageManagerInt.forEachPackage((AndroidPackage pkg) -> {
Todd Kennedyc971a452019-07-08 16:04:52 -07004125 if (pkg == changingPkg) {
4126 return;
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004127 }
Todd Kennedyc971a452019-07-08 16:04:52 -07004128 // Only replace for packages on requested volume
4129 final String volumeUuid = getVolumeUuidForPackage(pkg);
4130 final boolean replace = replaceAll && Objects.equals(replaceVolumeUuid, volumeUuid);
4131 restorePermissionState(pkg, replace, changingPkgName, callback);
4132 });
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004133 }
4134
4135 if (changingPkg != null) {
4136 // Only replace for packages on requested volume
4137 final String volumeUuid = getVolumeUuidForPackage(changingPkg);
4138 final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_PKG) != 0)
4139 && Objects.equals(replaceVolumeUuid, volumeUuid);
Philip P. Moltmanne0f00ea2018-10-30 10:43:15 -07004140 restorePermissionState(changingPkg, replace, changingPkgName, callback);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004141 }
4142 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
4143 }
4144
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004145 /**
4146 * Update which app declares a permission.
4147 *
4148 * <p>Possible parameter combinations
4149 * <table>
4150 * <tr><th></th><th>packageName != null</th><th>packageName == null</th></tr>
4151 * <tr><th>pkg != null</th><td>package is updated</td><td>invalid</td></tr>
4152 * <tr><th>pkg == null</th><td>package is deleted</td><td>all packages are updated</td></tr>
4153 * </table>
4154 *
4155 * @param packageName The package that is updated, or {@code null} if all packages should be
4156 * updated
4157 * @param pkg The package that is updated, or {@code null} if all packages should be updated or
4158 * package is deleted
4159 *
4160 * @return {@code true} if a permission source package might have changed
4161 */
4162 private boolean updatePermissionSourcePackage(@Nullable String packageName,
Winson14ff7172019-10-23 10:42:27 -07004163 @Nullable AndroidPackage pkg,
Hongming Jinbc4d0102019-08-16 14:28:30 -07004164 final @Nullable PermissionCallback callback) {
Songchun Fanbcc899e2020-04-06 16:51:45 -07004165 // Always need update if packageName is null
4166 if (packageName == null) {
4167 return true;
4168 }
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004169
Songchun Fanbcc899e2020-04-06 16:51:45 -07004170 boolean changed = false;
Todd Kennedyc8423932017-10-05 08:58:36 -07004171 Set<BasePermission> needsUpdate = null;
4172 synchronized (mLock) {
4173 final Iterator<BasePermission> it = mSettings.mPermissions.values().iterator();
4174 while (it.hasNext()) {
4175 final BasePermission bp = it.next();
4176 if (bp.isDynamic()) {
4177 bp.updateDynamicPermission(mSettings.mPermissionTrees.values());
4178 }
Songchun Fane5c0afe2020-04-22 12:22:52 -07004179 if (!packageName.equals(bp.getSourcePackageName())) {
4180 // Not checking sourcePackageSetting because it can be null when
4181 // the permission source package is the target package and the target package is
4182 // being uninstalled,
Todd Kennedyc8423932017-10-05 08:58:36 -07004183 continue;
4184 }
Songchun Fanbcc899e2020-04-06 16:51:45 -07004185 // The target package is the source of the current permission
4186 // Set to changed for either install or uninstall
4187 changed = true;
4188 // If the target package is being uninstalled, we need to revoke this permission
4189 // From all other packages
4190 if (pkg == null || !hasPermission(pkg, bp.getName())) {
4191 Slog.i(TAG, "Removing permission " + bp.getName()
4192 + " that used to be declared by " + bp.getSourcePackageName());
4193 if (bp.isRuntime()) {
4194 final int[] userIds = mUserManagerInt.getUserIds();
4195 final int numUserIds = userIds.length;
4196 for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
4197 final int userId = userIds[userIdNum];
4198 mPackageManagerInt.forEachPackage((AndroidPackage p) ->
4199 revokePermissionFromPackageForUser(p.getPackageName(),
Evan Severson24f9d5a2020-04-28 18:45:22 -07004200 bp.getName(), true, userId, callback));
Songchun Fanbcc899e2020-04-06 16:51:45 -07004201 }
4202 }
4203 it.remove();
4204 }
Todd Kennedyc8423932017-10-05 08:58:36 -07004205 if (needsUpdate == null) {
4206 needsUpdate = new ArraySet<>(mSettings.mPermissions.size());
4207 }
4208 needsUpdate.add(bp);
4209 }
4210 }
4211 if (needsUpdate != null) {
4212 for (final BasePermission bp : needsUpdate) {
Winson14ff7172019-10-23 10:42:27 -07004213 final AndroidPackage sourcePkg =
Todd Kennedyc8423932017-10-05 08:58:36 -07004214 mPackageManagerInt.getPackage(bp.getSourcePackageName());
Winson14ff7172019-10-23 10:42:27 -07004215 final PackageSetting sourcePs =
4216 (PackageSetting) mPackageManagerInt.getPackageSetting(
4217 bp.getSourcePackageName());
Todd Kennedyc8423932017-10-05 08:58:36 -07004218 synchronized (mLock) {
Winson14ff7172019-10-23 10:42:27 -07004219 if (sourcePkg != null && sourcePs != null) {
Todd Kennedyc8423932017-10-05 08:58:36 -07004220 continue;
4221 }
4222 Slog.w(TAG, "Removing dangling permission: " + bp.getName()
4223 + " from package " + bp.getSourcePackageName());
4224 mSettings.removePermissionLocked(bp.getName());
4225 }
4226 }
4227 }
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004228 return changed;
Todd Kennedyc8423932017-10-05 08:58:36 -07004229 }
4230
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004231 /**
Songchun Fanbcc899e2020-04-06 16:51:45 -07004232 * Revoke a runtime permission from a package for a given user ID.
4233 */
4234 private void revokePermissionFromPackageForUser(@NonNull String pName,
Evan Severson24f9d5a2020-04-28 18:45:22 -07004235 @NonNull String permissionName, boolean overridePolicy, int userId,
4236 @Nullable PermissionCallback callback) {
Songchun Fanbcc899e2020-04-06 16:51:45 -07004237 final ApplicationInfo appInfo =
4238 mPackageManagerInt.getApplicationInfo(pName, 0,
4239 Process.SYSTEM_UID, UserHandle.USER_SYSTEM);
4240 if (appInfo != null
4241 && appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
4242 return;
4243 }
4244
4245 if (checkPermissionImpl(permissionName, pName, userId)
4246 == PackageManager.PERMISSION_GRANTED) {
4247 try {
4248 revokeRuntimePermissionInternal(
4249 permissionName,
4250 pName,
Evan Severson24f9d5a2020-04-28 18:45:22 -07004251 overridePolicy,
Songchun Fanbcc899e2020-04-06 16:51:45 -07004252 Process.SYSTEM_UID,
4253 userId,
Evan Seversonaacd48b2020-06-22 16:45:03 -07004254 null, callback);
Songchun Fanbcc899e2020-04-06 16:51:45 -07004255 } catch (IllegalArgumentException e) {
4256 Slog.e(TAG,
4257 "Failed to revoke "
4258 + permissionName
4259 + " from "
4260 + pName,
4261 e);
4262 }
4263 }
4264 }
4265 /**
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004266 * Update which app owns a permission trees.
4267 *
4268 * <p>Possible parameter combinations
4269 * <table>
4270 * <tr><th></th><th>packageName != null</th><th>packageName == null</th></tr>
4271 * <tr><th>pkg != null</th><td>package is updated</td><td>invalid</td></tr>
4272 * <tr><th>pkg == null</th><td>package is deleted</td><td>all packages are updated</td></tr>
4273 * </table>
4274 *
4275 * @param packageName The package that is updated, or {@code null} if all packages should be
4276 * updated
4277 * @param pkg The package that is updated, or {@code null} if all packages should be updated or
4278 * package is deleted
4279 *
4280 * @return {@code true} if a permission tree ownership might have changed
4281 */
4282 private boolean updatePermissionTreeSourcePackage(@Nullable String packageName,
Winson14ff7172019-10-23 10:42:27 -07004283 @Nullable AndroidPackage pkg) {
Songchun Fanbcc899e2020-04-06 16:51:45 -07004284 // Always need update if packageName is null
4285 if (packageName == null) {
4286 return true;
4287 }
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004288 boolean changed = false;
4289
Todd Kennedyc8423932017-10-05 08:58:36 -07004290 Set<BasePermission> needsUpdate = null;
4291 synchronized (mLock) {
4292 final Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
4293 while (it.hasNext()) {
4294 final BasePermission bp = it.next();
Songchun Fane5c0afe2020-04-22 12:22:52 -07004295 if (!packageName.equals(bp.getSourcePackageName())) {
4296 // Not checking sourcePackageSetting because it can be null when
4297 // the permission source package is the target package and the target package is
4298 // being uninstalled,
Todd Kennedyc8423932017-10-05 08:58:36 -07004299 continue;
4300 }
Songchun Fanbcc899e2020-04-06 16:51:45 -07004301 // The target package is the source of the current permission tree
4302 // Set to changed for either install or uninstall
4303 changed = true;
4304 if (pkg == null || !hasPermission(pkg, bp.getName())) {
4305 Slog.i(TAG, "Removing permission tree " + bp.getName()
4306 + " that used to be declared by " + bp.getSourcePackageName());
4307 it.remove();
4308 }
Todd Kennedyc8423932017-10-05 08:58:36 -07004309 if (needsUpdate == null) {
4310 needsUpdate = new ArraySet<>(mSettings.mPermissionTrees.size());
4311 }
4312 needsUpdate.add(bp);
4313 }
4314 }
4315 if (needsUpdate != null) {
4316 for (final BasePermission bp : needsUpdate) {
Winson14ff7172019-10-23 10:42:27 -07004317 final AndroidPackage sourcePkg =
Todd Kennedyc8423932017-10-05 08:58:36 -07004318 mPackageManagerInt.getPackage(bp.getSourcePackageName());
Winson14ff7172019-10-23 10:42:27 -07004319 final PackageSetting sourcePs =
4320 (PackageSetting) mPackageManagerInt.getPackageSetting(
4321 bp.getSourcePackageName());
Todd Kennedyc8423932017-10-05 08:58:36 -07004322 synchronized (mLock) {
Winson14ff7172019-10-23 10:42:27 -07004323 if (sourcePkg != null && sourcePs != null) {
Todd Kennedyc8423932017-10-05 08:58:36 -07004324 continue;
4325 }
4326 Slog.w(TAG, "Removing dangling permission tree: " + bp.getName()
4327 + " from package " + bp.getSourcePackageName());
4328 mSettings.removePermissionLocked(bp.getName());
4329 }
4330 }
4331 }
Philip P. Moltmanndc65aa32019-03-28 12:02:45 -07004332 return changed;
Todd Kennedyc8423932017-10-05 08:58:36 -07004333 }
4334
Todd Kennedy0eb97382017-10-03 16:57:22 -07004335 private void enforceGrantRevokeRuntimePermissionPermissions(String message) {
4336 if (mContext.checkCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
4337 != PackageManager.PERMISSION_GRANTED
4338 && mContext.checkCallingOrSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
4339 != PackageManager.PERMISSION_GRANTED) {
4340 throw new SecurityException(message + " requires "
4341 + Manifest.permission.GRANT_RUNTIME_PERMISSIONS + " or "
4342 + Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
4343 }
4344 }
4345
Philip P. Moltmannfc202f72019-03-05 20:17:00 -08004346 private void enforceGrantRevokeGetRuntimePermissionPermissions(@NonNull String message) {
4347 if (mContext.checkCallingOrSelfPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
4348 != PackageManager.PERMISSION_GRANTED
4349 && mContext.checkCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
4350 != PackageManager.PERMISSION_GRANTED
4351 && mContext.checkCallingOrSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
4352 != PackageManager.PERMISSION_GRANTED) {
4353 throw new SecurityException(message + " requires "
4354 + Manifest.permission.GRANT_RUNTIME_PERMISSIONS + " or "
4355 + Manifest.permission.REVOKE_RUNTIME_PERMISSIONS + " or "
4356 + Manifest.permission.GET_RUNTIME_PERMISSIONS);
4357 }
4358 }
4359
Todd Kennedy0eb97382017-10-03 16:57:22 -07004360 /**
4361 * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS
4362 * or INTERACT_ACROSS_USERS_FULL permissions, if the userid is not for the caller.
4363 * @param checkShell whether to prevent shell from access if there's a debugging restriction
4364 * @param message the message to log on security exception
4365 */
4366 private void enforceCrossUserPermission(int callingUid, int userId,
Todd Kennedyef9acb62018-05-29 15:18:06 -07004367 boolean requireFullPermission, boolean checkShell,
4368 boolean requirePermissionWhenSameUser, String message) {
Todd Kennedy0eb97382017-10-03 16:57:22 -07004369 if (userId < 0) {
4370 throw new IllegalArgumentException("Invalid userId " + userId);
4371 }
4372 if (checkShell) {
Patrick Baumann2f2fd712019-07-31 15:18:53 -07004373 PackageManagerServiceUtils.enforceShellRestriction(mUserManagerInt,
Todd Kennedy0eb97382017-10-03 16:57:22 -07004374 UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
4375 }
kholoud mohamed67ac7c62019-12-06 16:33:48 +00004376 final int callingUserId = UserHandle.getUserId(callingUid);
4377 if (hasCrossUserPermission(
4378 callingUid, callingUserId, userId, requireFullPermission,
4379 requirePermissionWhenSameUser)) {
4380 return;
Todd Kennedy0eb97382017-10-03 16:57:22 -07004381 }
kholoud mohamed67ac7c62019-12-06 16:33:48 +00004382 String errorMessage = buildInvalidCrossUserPermissionMessage(
4383 message, requireFullPermission);
4384 Slog.w(TAG, errorMessage);
4385 throw new SecurityException(errorMessage);
4386 }
4387
4388 /**
4389 * Checks if the request is from the system or an app that has the appropriate cross-user
4390 * permissions defined as follows:
4391 * <ul>
4392 * <li>INTERACT_ACROSS_USERS_FULL if {@code requireFullPermission} is true.</li>
4393 * <li>INTERACT_ACROSS_USERS if the given {@userId} is in a different profile group
4394 * to the caller.</li>
4395 * <li>Otherwise, INTERACT_ACROSS_PROFILES if the given {@userId} is in the same profile group
4396 * as the caller.</li>
4397 * </ul>
4398 *
4399 * @param checkShell whether to prevent shell from access if there's a debugging restriction
4400 * @param message the message to log on security exception
4401 */
4402 private void enforceCrossUserOrProfilePermission(int callingUid, int userId,
4403 boolean requireFullPermission, boolean checkShell,
4404 String message) {
4405 if (userId < 0) {
4406 throw new IllegalArgumentException("Invalid userId " + userId);
4407 }
4408 if (checkShell) {
4409 PackageManagerServiceUtils.enforceShellRestriction(mUserManagerInt,
4410 UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
4411 }
4412 final int callingUserId = UserHandle.getUserId(callingUid);
4413 if (hasCrossUserPermission(callingUid, callingUserId, userId, requireFullPermission,
4414 /*requirePermissionWhenSameUser= */ false)) {
4415 return;
4416 }
4417 final boolean isSameProfileGroup = isSameProfileGroup(callingUserId, userId);
kholoud mohamed79a89f02020-01-15 15:30:07 +00004418 if (isSameProfileGroup && PermissionChecker.checkPermissionForPreflight(
4419 mContext,
4420 android.Manifest.permission.INTERACT_ACROSS_PROFILES,
4421 PermissionChecker.PID_UNKNOWN,
4422 callingUid,
4423 mPackageManagerInt.getPackage(callingUid).getPackageName())
4424 == PermissionChecker.PERMISSION_GRANTED) {
kholoud mohamed67ac7c62019-12-06 16:33:48 +00004425 return;
4426 }
4427 String errorMessage = buildInvalidCrossUserOrProfilePermissionMessage(
4428 message, requireFullPermission, isSameProfileGroup);
4429 Slog.w(TAG, errorMessage);
4430 throw new SecurityException(errorMessage);
4431 }
4432
4433 private boolean hasCrossUserPermission(
4434 int callingUid, int callingUserId, int userId, boolean requireFullPermission,
4435 boolean requirePermissionWhenSameUser) {
4436 if (!requirePermissionWhenSameUser && userId == callingUserId) {
4437 return true;
4438 }
4439 if (callingUid == Process.SYSTEM_UID || callingUid == Process.ROOT_UID) {
4440 return true;
4441 }
4442 if (requireFullPermission) {
4443 return hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL);
4444 }
4445 return hasPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
4446 || hasPermission(Manifest.permission.INTERACT_ACROSS_USERS);
4447 }
4448
4449 private boolean hasPermission(String permission) {
4450 return mContext.checkCallingOrSelfPermission(permission)
4451 == PackageManager.PERMISSION_GRANTED;
4452 }
4453
4454 private boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId) {
4455 final long identity = Binder.clearCallingIdentity();
4456 try {
4457 return UserManagerService.getInstance().isSameProfileGroup(callerUserId, userId);
4458 } finally {
4459 Binder.restoreCallingIdentity(identity);
4460 }
4461 }
4462
4463 private static String buildInvalidCrossUserPermissionMessage(
4464 String message, boolean requireFullPermission) {
4465 StringBuilder builder = new StringBuilder();
4466 if (message != null) {
4467 builder.append(message);
4468 builder.append(": ");
4469 }
4470 builder.append("Requires ");
4471 builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
4472 if (requireFullPermission) {
4473 builder.append(".");
4474 return builder.toString();
4475 }
4476 builder.append(" or ");
4477 builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS);
4478 builder.append(".");
4479 return builder.toString();
4480 }
4481
4482 private static String buildInvalidCrossUserOrProfilePermissionMessage(
4483 String message, boolean requireFullPermission, boolean isSameProfileGroup) {
4484 StringBuilder builder = new StringBuilder();
4485 if (message != null) {
4486 builder.append(message);
4487 builder.append(": ");
4488 }
4489 builder.append("Requires ");
4490 builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
4491 if (requireFullPermission) {
4492 builder.append(".");
4493 return builder.toString();
4494 }
4495 builder.append(" or ");
4496 builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS);
4497 if (isSameProfileGroup) {
4498 builder.append(" or ");
4499 builder.append(android.Manifest.permission.INTERACT_ACROSS_PROFILES);
4500 }
4501 builder.append(".");
4502 return builder.toString();
Todd Kennedy0eb97382017-10-03 16:57:22 -07004503 }
4504
Andreas Gampea71bee82018-07-20 12:55:36 -07004505 @GuardedBy({"mSettings.mLock", "mLock"})
Todd Kennedy0eb97382017-10-03 16:57:22 -07004506 private int calculateCurrentPermissionFootprintLocked(BasePermission tree) {
4507 int size = 0;
Todd Kennedyc8423932017-10-05 08:58:36 -07004508 for (BasePermission perm : mSettings.mPermissions.values()) {
Todd Kennedy0eb97382017-10-03 16:57:22 -07004509 size += tree.calculateFootprint(perm);
4510 }
4511 return size;
4512 }
4513
Andreas Gampea71bee82018-07-20 12:55:36 -07004514 @GuardedBy({"mSettings.mLock", "mLock"})
Todd Kennedy0eb97382017-10-03 16:57:22 -07004515 private void enforcePermissionCapLocked(PermissionInfo info, BasePermission tree) {
4516 // We calculate the max size of permissions defined by this uid and throw
4517 // if that plus the size of 'info' would exceed our stated maximum.
4518 if (tree.getUid() != Process.SYSTEM_UID) {
4519 final int curTreeSize = calculateCurrentPermissionFootprintLocked(tree);
4520 if (curTreeSize + info.calculateFootprint() > MAX_PERMISSION_TREE_FOOTPRINT) {
4521 throw new SecurityException("Permission tree size cap exceeded");
4522 }
4523 }
4524 }
4525
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004526 private void systemReady() {
4527 mSystemReady = true;
4528 if (mPrivappPermissionsViolations != null) {
4529 throw new IllegalStateException("Signature|privileged permissions not in "
4530 + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
4531 }
Philip P. Moltmann48456672019-01-20 13:14:03 -08004532
4533 mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
Svet Ganov3c499ea2019-07-26 17:45:56 -07004534 mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
Todd Kennedy583378d2019-07-12 06:50:30 -07004535
4536 int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
4537 for (int userId : UserManagerService.getInstance().getUserIds()) {
Evan Severson0dc24cb2020-02-04 10:25:08 -08004538 if (mPackageManagerInt.isPermissionUpgradeNeeded(userId)) {
Todd Kennedy583378d2019-07-12 06:50:30 -07004539 grantPermissionsUserIds = ArrayUtils.appendInt(
4540 grantPermissionsUserIds, userId);
4541 }
4542 }
4543 // If we upgraded grant all default permissions before kicking off.
4544 for (int userId : grantPermissionsUserIds) {
4545 mDefaultPermissionGrantPolicy.grantDefaultPermissions(userId);
4546 }
4547 if (grantPermissionsUserIds == EMPTY_INT_ARRAY) {
4548 // If we did not grant default permissions, we preload from this the
4549 // default permission exceptions lazily to ensure we don't hit the
4550 // disk on a new user creation.
4551 mDefaultPermissionGrantPolicy.scheduleReadDefaultPermissionExceptions();
4552 }
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004553 }
4554
Winson14ff7172019-10-23 10:42:27 -07004555 private static String getVolumeUuidForPackage(AndroidPackage pkg) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004556 if (pkg == null) {
4557 return StorageManager.UUID_PRIVATE_INTERNAL;
4558 }
Winson5e0a1d52020-01-24 12:00:33 -08004559 if (pkg.isExternalStorage()) {
Winson14ff7172019-10-23 10:42:27 -07004560 if (TextUtils.isEmpty(pkg.getVolumeUuid())) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004561 return StorageManager.UUID_PRIMARY_PHYSICAL;
4562 } else {
Winson14ff7172019-10-23 10:42:27 -07004563 return pkg.getVolumeUuid();
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004564 }
4565 } else {
4566 return StorageManager.UUID_PRIVATE_INTERNAL;
4567 }
4568 }
4569
Winson14ff7172019-10-23 10:42:27 -07004570 private static boolean hasPermission(AndroidPackage pkg, String permName) {
Winsone23ae202020-01-24 11:56:44 -08004571 if (pkg.getPermissions().isEmpty()) {
Winson14ff7172019-10-23 10:42:27 -07004572 return false;
4573 }
4574
4575 for (int i = pkg.getPermissions().size() - 1; i >= 0; i--) {
4576 if (pkg.getPermissions().get(i).getName().equals(permName)) {
Todd Kennedyc8423932017-10-05 08:58:36 -07004577 return true;
4578 }
4579 }
4580 return false;
4581 }
4582
Todd Kennedy0eb97382017-10-03 16:57:22 -07004583 /**
Philip P. Moltmann8cff8b92017-10-25 14:32:41 -07004584 * Log that a permission request was granted/revoked.
Todd Kennedy0eb97382017-10-03 16:57:22 -07004585 *
Philip P. Moltmann8cff8b92017-10-25 14:32:41 -07004586 * @param action the action performed
Todd Kennedy0eb97382017-10-03 16:57:22 -07004587 * @param name name of the permission
Philip P. Moltmann8cff8b92017-10-25 14:32:41 -07004588 * @param packageName package permission is for
Todd Kennedy0eb97382017-10-03 16:57:22 -07004589 */
Philip P. Moltmann8cff8b92017-10-25 14:32:41 -07004590 private void logPermission(int action, @NonNull String name, @NonNull String packageName) {
4591 final LogMaker log = new LogMaker(action);
4592 log.setPackageName(packageName);
4593 log.addTaggedData(MetricsEvent.FIELD_PERMISSION, name);
Todd Kennedy0eb97382017-10-03 16:57:22 -07004594
Philip P. Moltmann8cff8b92017-10-25 14:32:41 -07004595 mMetricsLogger.write(log);
Todd Kennedy0eb97382017-10-03 16:57:22 -07004596 }
4597
Philip P. Moltmanne1b277a2018-11-01 16:22:50 -07004598 /**
4599 * Get the mapping of background permissions to their foreground permissions.
4600 *
4601 * <p>Only initialized in the system server.
4602 *
4603 * @return the map &lt;bg permission -> list&lt;fg perm&gt;&gt;
4604 */
4605 public @Nullable ArrayMap<String, List<String>> getBackgroundPermissions() {
4606 return mBackgroundPermissions;
4607 }
4608
Philip P. Moltmann48456672019-01-20 13:14:03 -08004609 private class PermissionManagerServiceInternalImpl extends PermissionManagerServiceInternal {
Todd Kennedy0eb97382017-10-03 16:57:22 -07004610 @Override
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004611 public void systemReady() {
4612 PermissionManagerService.this.systemReady();
4613 }
4614 @Override
Winson14ff7172019-10-23 10:42:27 -07004615 public boolean isPermissionsReviewRequired(@NonNull AndroidPackage pkg,
4616 @UserIdInt int userId) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004617 return PermissionManagerService.this.isPermissionsReviewRequired(pkg, userId);
4618 }
Winson14ff7172019-10-23 10:42:27 -07004619
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004620 @Override
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07004621 public void revokeRuntimePermissionsIfGroupChanged(
Winson14ff7172019-10-23 10:42:27 -07004622 @NonNull AndroidPackage newPackage,
4623 @NonNull AndroidPackage oldPackage,
Todd Kennedyc971a452019-07-08 16:04:52 -07004624 @NonNull ArrayList<String> allPackageNames) {
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07004625 PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage,
Todd Kennedyc971a452019-07-08 16:04:52 -07004626 oldPackage, allPackageNames, mDefaultPermissionCallback);
Philip P. Moltmannfae8a5282018-04-10 12:15:32 -07004627 }
4628 @Override
Winson14ff7172019-10-23 10:42:27 -07004629 public void addAllPermissions(AndroidPackage pkg, boolean chatty) {
Todd Kennedyc8423932017-10-05 08:58:36 -07004630 PermissionManagerService.this.addAllPermissions(pkg, chatty);
Todd Kennedy0eb97382017-10-03 16:57:22 -07004631 }
4632 @Override
Winson14ff7172019-10-23 10:42:27 -07004633 public void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
Todd Kennedy460f28c2017-10-06 13:46:22 -07004634 PermissionManagerService.this.addAllPermissionGroups(pkg, chatty);
4635 }
4636 @Override
Winson14ff7172019-10-23 10:42:27 -07004637 public void removeAllPermissions(AndroidPackage pkg, boolean chatty) {
Hongming Jinae750fb2018-09-27 23:00:20 +00004638 PermissionManagerService.this.removeAllPermissions(pkg, chatty);
Todd Kennedyc8423932017-10-05 08:58:36 -07004639 }
4640 @Override
Winson14ff7172019-10-23 10:42:27 -07004641 public void grantRequestedRuntimePermissions(AndroidPackage pkg, int[] userIds,
Todd Kennedyc971a452019-07-08 16:04:52 -07004642 String[] grantedPermissions, int callingUid) {
Todd Kennedy0eb97382017-10-03 16:57:22 -07004643 PermissionManagerService.this.grantRequestedRuntimePermissions(
Todd Kennedyc971a452019-07-08 16:04:52 -07004644 pkg, userIds, grantedPermissions, callingUid, mDefaultPermissionCallback);
Todd Kennedy0eb97382017-10-03 16:57:22 -07004645 }
4646 @Override
Winson14ff7172019-10-23 10:42:27 -07004647 public void setWhitelistedRestrictedPermissions(@NonNull AndroidPackage pkg,
Svet Ganovd8eb8b22019-04-05 18:52:08 -07004648 @NonNull int[] userIds, @Nullable List<String> permissions, int callingUid,
Todd Kennedyc971a452019-07-08 16:04:52 -07004649 @PackageManager.PermissionWhitelistFlags int flags) {
Nate Myrenc92df182020-06-23 16:31:39 -07004650 setWhitelistedRestrictedPermissionsForUsers(pkg, userIds, permissions,
4651 callingUid, flags, mDefaultPermissionCallback);
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07004652 }
4653 @Override
4654 public void setWhitelistedRestrictedPermissions(String packageName,
4655 List<String> permissions, int flags, int userId) {
4656 PermissionManagerService.this.setWhitelistedRestrictedPermissionsInternal(
4657 packageName, permissions, flags, userId);
Svet Ganovd8eb8b22019-04-05 18:52:08 -07004658 }
4659 @Override
Eugene Susla922cd082020-03-11 12:38:17 -07004660 public void setAutoRevokeWhitelisted(
4661 @NonNull String packageName, boolean whitelisted, int userId) {
4662 PermissionManagerService.this.setAutoRevokeWhitelisted(
4663 packageName, whitelisted, userId);
4664 }
4665 @Override
Winson14ff7172019-10-23 10:42:27 -07004666 public void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg) {
Todd Kennedyc971a452019-07-08 16:04:52 -07004667 PermissionManagerService.this
4668 .updatePermissions(packageName, pkg, mDefaultPermissionCallback);
Todd Kennedy0eb97382017-10-03 16:57:22 -07004669 }
4670 @Override
Todd Kennedyc971a452019-07-08 16:04:52 -07004671 public void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated) {
4672 PermissionManagerService.this
4673 .updateAllPermissions(volumeUuid, sdkUpdated, mDefaultPermissionCallback);
Todd Kennedyc29b11a2017-10-23 15:55:59 -07004674 }
4675 @Override
Winson14ff7172019-10-23 10:42:27 -07004676 public void resetRuntimePermissions(AndroidPackage pkg, int userId) {
Todd Kennedyc971a452019-07-08 16:04:52 -07004677 PermissionManagerService.this.resetRuntimePermissionsInternal(pkg, userId);
4678 }
4679 @Override
4680 public void resetAllRuntimePermissions(final int userId) {
4681 mPackageManagerInt.forEachPackage(
Winson14ff7172019-10-23 10:42:27 -07004682 (AndroidPackage pkg) -> resetRuntimePermissionsInternal(pkg, userId));
Todd Kennedy0eb97382017-10-03 16:57:22 -07004683 }
4684 @Override
Todd Kennedy8f135982019-07-02 07:35:15 -07004685 public String[] getAppOpPermissionPackages(String permName, int callingUid) {
4686 return PermissionManagerService.this
4687 .getAppOpPermissionPackagesInternal(permName, callingUid);
Todd Kennedyc8423932017-10-05 08:58:36 -07004688 }
4689 @Override
Todd Kennedy0eb97382017-10-03 16:57:22 -07004690 public void enforceCrossUserPermission(int callingUid, int userId,
4691 boolean requireFullPermission, boolean checkShell, String message) {
4692 PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId,
Todd Kennedyef9acb62018-05-29 15:18:06 -07004693 requireFullPermission, checkShell, false, message);
4694 }
4695 @Override
4696 public void enforceCrossUserPermission(int callingUid, int userId,
4697 boolean requireFullPermission, boolean checkShell,
4698 boolean requirePermissionWhenSameUser, String message) {
4699 PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId,
4700 requireFullPermission, checkShell, requirePermissionWhenSameUser, message);
Todd Kennedy0eb97382017-10-03 16:57:22 -07004701 }
kholoud mohamed67ac7c62019-12-06 16:33:48 +00004702
4703 @Override
4704 public void enforceCrossUserOrProfilePermission(int callingUid, int userId,
4705 boolean requireFullPermission, boolean checkShell, String message) {
kholoud mohamed79a89f02020-01-15 15:30:07 +00004706 PermissionManagerService.this.enforceCrossUserOrProfilePermission(
4707 callingUid,
kholoud mohamed67ac7c62019-12-06 16:33:48 +00004708 userId,
4709 requireFullPermission,
4710 checkShell,
4711 message);
4712 }
4713
Todd Kennedy0eb97382017-10-03 16:57:22 -07004714 @Override
4715 public void enforceGrantRevokeRuntimePermissionPermissions(String message) {
4716 PermissionManagerService.this.enforceGrantRevokeRuntimePermissionPermissions(message);
4717 }
4718 @Override
Todd Kennedy0eb97382017-10-03 16:57:22 -07004719 public PermissionSettings getPermissionSettings() {
4720 return mSettings;
4721 }
4722 @Override
Todd Kennedy0eb97382017-10-03 16:57:22 -07004723 public BasePermission getPermissionTEMP(String permName) {
4724 synchronized (PermissionManagerService.this.mLock) {
4725 return mSettings.getPermissionLocked(permName);
4726 }
4727 }
Philip P. Moltmann48456672019-01-20 13:14:03 -08004728
4729 @Override
Hai Zhanga7c60c02020-03-05 16:03:35 -08004730 public @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtection(
Hai Zhang57bc3122019-10-21 16:04:15 -07004731 @PermissionInfo.Protection int protection) {
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -07004732 ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
4733
Hai Zhanga7c60c02020-03-05 16:03:35 -08004734 synchronized (mLock) {
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -07004735 int numTotalPermissions = mSettings.mPermissions.size();
4736
4737 for (int i = 0; i < numTotalPermissions; i++) {
4738 BasePermission bp = mSettings.mPermissions.valueAt(i);
4739
Winson655a5b92019-10-23 10:49:32 -07004740 if (bp.perm != null && bp.perm.getProtection() == protection) {
4741 matchingPermissions.add(
4742 PackageInfoUtils.generatePermissionInfo(bp.perm, 0));
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -07004743 }
4744 }
4745 }
4746
4747 return matchingPermissions;
4748 }
4749
4750 @Override
Hai Zhanga7c60c02020-03-05 16:03:35 -08004751 public @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
4752 @PermissionInfo.ProtectionFlags int protectionFlags) {
4753 ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
4754
4755 synchronized (mLock) {
4756 int numTotalPermissions = mSettings.mPermissions.size();
4757
4758 for (int i = 0; i < numTotalPermissions; i++) {
4759 BasePermission bp = mSettings.mPermissions.valueAt(i);
4760
4761 if (bp.perm != null && (bp.perm.getProtectionFlags() & protectionFlags)
4762 == protectionFlags) {
4763 matchingPermissions.add(
4764 PackageInfoUtils.generatePermissionInfo(bp.perm, 0));
4765 }
4766 }
4767 }
4768
4769 return matchingPermissions;
4770 }
4771
4772 @Override
Philip P. Moltmann48456672019-01-20 13:14:03 -08004773 public @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user) {
4774 return PermissionManagerService.this.backupRuntimePermissions(user);
4775 }
4776
4777 @Override
4778 public void restoreRuntimePermissions(@NonNull byte[] backup, @NonNull UserHandle user) {
4779 PermissionManagerService.this.restoreRuntimePermissions(backup, user);
4780 }
4781
4782 @Override
4783 public void restoreDelayedRuntimePermissions(@NonNull String packageName,
4784 @NonNull UserHandle user) {
4785 PermissionManagerService.this.restoreDelayedRuntimePermissions(packageName, user);
4786 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -07004787
4788 @Override
4789 public void addOnRuntimePermissionStateChangedListener(
4790 OnRuntimePermissionStateChangedListener listener) {
4791 PermissionManagerService.this.addOnRuntimePermissionStateChangedListener(
4792 listener);
4793 }
4794
4795 @Override
4796 public void removeOnRuntimePermissionStateChangedListener(
4797 OnRuntimePermissionStateChangedListener listener) {
4798 PermissionManagerService.this.removeOnRuntimePermissionStateChangedListener(
4799 listener);
4800 }
Todd Kennedyca1ea172019-07-03 15:02:28 -07004801
4802 @Override
4803 public CheckPermissionDelegate getCheckPermissionDelegate() {
4804 synchronized (mLock) {
4805 return mCheckPermissionDelegate;
4806 }
4807 }
4808
4809 @Override
4810 public void setCheckPermissionDelegate(CheckPermissionDelegate delegate) {
4811 synchronized (mLock) {
Daniel Colascionea3c6c092020-02-27 03:51:30 -08004812 if (delegate != null || mCheckPermissionDelegate != null) {
4813 PackageManager.invalidatePackageInfoCache();
4814 }
Todd Kennedyca1ea172019-07-03 15:02:28 -07004815 mCheckPermissionDelegate = delegate;
4816 }
4817 }
Todd Kennedy583378d2019-07-12 06:50:30 -07004818
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07004819 @Override
Todd Kennedy583378d2019-07-12 06:50:30 -07004820 public void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider) {
4821 synchronized (mLock) {
4822 mDefaultBrowserProvider = provider;
4823 }
4824 }
4825
4826 @Override
4827 public void setDefaultBrowser(String packageName, boolean async, boolean doGrant,
4828 int userId) {
4829 setDefaultBrowserInternal(packageName, async, doGrant, userId);
4830 }
4831
4832 @Override
4833 public void setDefaultDialerProvider(@NonNull DefaultDialerProvider provider) {
4834 synchronized (mLock) {
4835 mDefaultDialerProvider = provider;
4836 }
4837 }
4838
4839 @Override
4840 public void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider) {
4841 synchronized (mLock) {
4842 mDefaultHomeProvider = provider;
4843 }
4844 }
4845
4846 @Override
4847 public void setDefaultHome(String packageName, int userId, Consumer<Boolean> callback) {
Hai Zhang109ff9d2019-09-24 17:18:05 -07004848 if (userId == UserHandle.USER_ALL) {
4849 return;
Todd Kennedy583378d2019-07-12 06:50:30 -07004850 }
Hai Zhang109ff9d2019-09-24 17:18:05 -07004851 DefaultHomeProvider provider;
4852 synchronized (mLock) {
4853 provider = mDefaultHomeProvider;
4854 }
4855 if (provider == null) {
4856 return;
4857 }
4858 provider.setDefaultHomeAsync(packageName, userId, callback);
Todd Kennedy583378d2019-07-12 06:50:30 -07004859 }
4860
4861 @Override
4862 public void setDialerAppPackagesProvider(PackagesProvider provider) {
4863 synchronized (mLock) {
4864 mDefaultPermissionGrantPolicy.setDialerAppPackagesProvider(provider);
4865 }
4866 }
4867
4868 @Override
4869 public void setLocationExtraPackagesProvider(PackagesProvider provider) {
4870 synchronized (mLock) {
4871 mDefaultPermissionGrantPolicy.setLocationExtraPackagesProvider(provider);
4872 }
4873 }
4874
4875 @Override
4876 public void setLocationPackagesProvider(PackagesProvider provider) {
4877 synchronized (mLock) {
4878 mDefaultPermissionGrantPolicy.setLocationPackagesProvider(provider);
4879 }
4880 }
4881
4882 @Override
4883 public void setSimCallManagerPackagesProvider(PackagesProvider provider) {
4884 synchronized (mLock) {
4885 mDefaultPermissionGrantPolicy.setSimCallManagerPackagesProvider(provider);
4886 }
4887 }
4888
4889 @Override
4890 public void setSmsAppPackagesProvider(PackagesProvider provider) {
4891 synchronized (mLock) {
4892 mDefaultPermissionGrantPolicy.setSmsAppPackagesProvider(provider);
4893 }
4894 }
4895
4896 @Override
4897 public void setSyncAdapterPackagesProvider(SyncAdapterPackagesProvider provider) {
4898 synchronized (mLock) {
4899 mDefaultPermissionGrantPolicy.setSyncAdapterPackagesProvider(provider);
4900 }
4901 }
4902
4903 @Override
4904 public void setUseOpenWifiAppPackagesProvider(PackagesProvider provider) {
4905 synchronized (mLock) {
4906 mDefaultPermissionGrantPolicy.setUseOpenWifiAppPackagesProvider(provider);
4907 }
4908 }
4909
4910 @Override
4911 public void setVoiceInteractionPackagesProvider(PackagesProvider provider) {
4912 synchronized (mLock) {
4913 mDefaultPermissionGrantPolicy.setVoiceInteractionPackagesProvider(provider);
4914 }
4915 }
4916
4917 @Override
4918 public String getDefaultBrowser(int userId) {
Hai Zhang109ff9d2019-09-24 17:18:05 -07004919 DefaultBrowserProvider provider;
Todd Kennedy583378d2019-07-12 06:50:30 -07004920 synchronized (mLock) {
Hai Zhang109ff9d2019-09-24 17:18:05 -07004921 provider = mDefaultBrowserProvider;
Todd Kennedy583378d2019-07-12 06:50:30 -07004922 }
Hai Zhang109ff9d2019-09-24 17:18:05 -07004923 return provider != null ? provider.getDefaultBrowser(userId) : null;
Todd Kennedy583378d2019-07-12 06:50:30 -07004924 }
4925
4926 @Override
4927 public String getDefaultDialer(int userId) {
Hai Zhang109ff9d2019-09-24 17:18:05 -07004928 DefaultDialerProvider provider;
Todd Kennedy583378d2019-07-12 06:50:30 -07004929 synchronized (mLock) {
Hai Zhang109ff9d2019-09-24 17:18:05 -07004930 provider = mDefaultDialerProvider;
Todd Kennedy583378d2019-07-12 06:50:30 -07004931 }
Hai Zhang109ff9d2019-09-24 17:18:05 -07004932 return provider != null ? provider.getDefaultDialer(userId) : null;
Todd Kennedy583378d2019-07-12 06:50:30 -07004933 }
4934
4935 @Override
4936 public String getDefaultHome(int userId) {
Hai Zhang109ff9d2019-09-24 17:18:05 -07004937 DefaultHomeProvider provider;
Todd Kennedy583378d2019-07-12 06:50:30 -07004938 synchronized (mLock) {
Hai Zhang109ff9d2019-09-24 17:18:05 -07004939 provider = mDefaultHomeProvider;
Todd Kennedy583378d2019-07-12 06:50:30 -07004940 }
Hai Zhang109ff9d2019-09-24 17:18:05 -07004941 return provider != null ? provider.getDefaultHome(userId) : null;
Todd Kennedy583378d2019-07-12 06:50:30 -07004942 }
4943
4944 @Override
4945 public void grantDefaultPermissionsToDefaultSimCallManager(String packageName, int userId) {
4946 synchronized (mLock) {
4947 mDefaultPermissionGrantPolicy
4948 .grantDefaultPermissionsToDefaultSimCallManager(packageName, userId);
4949 }
4950 }
4951
4952 @Override
4953 public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) {
4954 synchronized (mLock) {
4955 mDefaultPermissionGrantPolicy
4956 .grantDefaultPermissionsToDefaultUseOpenWifiApp(packageName, userId);
4957 }
4958 }
4959
4960 @Override
4961 public void grantDefaultPermissionsToDefaultBrowser(String packageName, int userId) {
4962 synchronized (mLock) {
4963 mDefaultPermissionGrantPolicy
4964 .grantDefaultPermissionsToDefaultBrowser(packageName, userId);
4965 }
4966 }
4967
4968 @Override
Todd Kennedy583378d2019-07-12 06:50:30 -07004969 public void onNewUserCreated(int userId) {
Hai Zhang93236822020-01-09 13:15:17 -08004970 mDefaultPermissionGrantPolicy.grantDefaultPermissions(userId);
Todd Kennedy583378d2019-07-12 06:50:30 -07004971 synchronized (mLock) {
Todd Kennedy583378d2019-07-12 06:50:30 -07004972 // NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG
4973 PermissionManagerService.this.updateAllPermissions(
4974 StorageManager.UUID_PRIVATE_INTERNAL, true, mDefaultPermissionCallback);
4975 }
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07004976 }
Winson10d51882020-05-26 10:52:23 -07004977
4978 @Override
4979 public void retainHardAndSoftRestrictedPermissions(@NonNull List<String> permissions) {
4980 synchronized (mLock) {
4981 Iterator<String> iterator = permissions.iterator();
4982 while (iterator.hasNext()) {
4983 String permission = iterator.next();
4984 BasePermission basePermission = mSettings.mPermissions.get(permission);
4985 if (basePermission == null || !basePermission.isHardOrSoftRestricted()) {
4986 iterator.remove();
4987 }
4988 }
4989 }
4990 }
Todd Kennedy7e3dd3a2019-07-08 10:34:29 -07004991 }
4992
4993 private static final class OnPermissionChangeListeners extends Handler {
4994 private static final int MSG_ON_PERMISSIONS_CHANGED = 1;
4995
4996 private final RemoteCallbackList<IOnPermissionsChangeListener> mPermissionListeners =
4997 new RemoteCallbackList<>();
4998
4999 OnPermissionChangeListeners(Looper looper) {
5000 super(looper);
5001 }
5002
5003 @Override
5004 public void handleMessage(Message msg) {
5005 switch (msg.what) {
5006 case MSG_ON_PERMISSIONS_CHANGED: {
5007 final int uid = msg.arg1;
5008 handleOnPermissionsChanged(uid);
5009 } break;
5010 }
5011 }
5012
5013 public void addListenerLocked(IOnPermissionsChangeListener listener) {
5014 mPermissionListeners.register(listener);
5015
5016 }
5017
5018 public void removeListenerLocked(IOnPermissionsChangeListener listener) {
5019 mPermissionListeners.unregister(listener);
5020 }
5021
5022 public void onPermissionsChanged(int uid) {
5023 if (mPermissionListeners.getRegisteredCallbackCount() > 0) {
5024 obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
5025 }
5026 }
5027
5028 private void handleOnPermissionsChanged(int uid) {
5029 final int count = mPermissionListeners.beginBroadcast();
5030 try {
5031 for (int i = 0; i < count; i++) {
5032 IOnPermissionsChangeListener callback = mPermissionListeners
5033 .getBroadcastItem(i);
5034 try {
5035 callback.onPermissionsChanged(uid);
5036 } catch (RemoteException e) {
5037 Log.e(TAG, "Permission listener is dead", e);
5038 }
5039 }
5040 } finally {
5041 mPermissionListeners.finishBroadcast();
5042 }
5043 }
Todd Kennedy0eb97382017-10-03 16:57:22 -07005044 }
Michael Groover56a84b22020-03-04 20:41:36 -08005045
5046 /**
5047 * Allows injection of services and method responses to facilitate testing.
5048 *
5049 * <p>Test classes can create a mock of this class and pass it to the PermissionManagerService
5050 * constructor to control behavior of services and external methods during execution.
5051 * @hide
5052 */
5053 @VisibleForTesting
5054 public static class Injector {
5055 private final Context mContext;
5056
5057 /**
5058 * Public constructor that accepts a {@code context} within which to operate.
5059 */
5060 public Injector(@NonNull Context context) {
5061 mContext = context;
5062 }
5063
5064 /**
5065 * Returns the UID of the calling package.
5066 */
5067 public int getCallingUid() {
5068 return Binder.getCallingUid();
5069 }
5070
5071 /**
5072 * Returns the process ID of the calling package.
5073 */
5074 public int getCallingPid() {
5075 return Binder.getCallingPid();
5076 }
5077
5078 /**
5079 * Invalidates the package info cache.
5080 */
5081 public void invalidatePackageInfoCache() {
5082 PackageManager.invalidatePackageInfoCache();
5083 }
5084
5085 /**
5086 * Disables the permission cache.
5087 */
5088 public void disablePermissionCache() {
5089 PermissionManager.disablePermissionCache();
5090 }
5091
5092 /**
5093 * Disables the package name permission cache.
5094 */
5095 public void disablePackageNamePermissionCache() {
5096 PermissionManager.disablePackageNamePermissionCache();
5097 }
5098
5099 /**
5100 * Checks if the package running under the specified {@code pid} and {@code uid} has been
5101 * granted the provided {@code permission}.
5102 *
5103 * @return {@link PackageManager#PERMISSION_GRANTED} if the package has been granted the
5104 * permission, {@link PackageManager#PERMISSION_DENIED} otherwise
5105 */
5106 public int checkPermission(@NonNull String permission, int pid, int uid) {
5107 return mContext.checkPermission(permission, pid, uid);
5108 }
5109
5110 /**
5111 * Clears the calling identity to allow subsequent calls to be treated as coming from this
5112 * package.
5113 *
5114 * @return a token that can be used to restore the calling identity
5115 */
5116 public long clearCallingIdentity() {
5117 return Binder.clearCallingIdentity();
5118 }
5119
5120 /**
5121 * Restores the calling identity to that of the calling package based on the provided
5122 * {@code token}.
5123 */
5124 public void restoreCallingIdentity(long token) {
5125 Binder.restoreCallingIdentity(token);
5126 }
5127
5128 /**
5129 * Returns the system service with the provided {@code name}.
5130 */
5131 public Object getSystemService(@NonNull String name) {
5132 return mContext.getSystemService(name);
5133 }
5134 }
Todd Kennedy0eb97382017-10-03 16:57:22 -07005135}