blob: 37f088b170ebda149515537b977a03a70b95ed97 [file] [log] [blame]
Svet Ganovd8eb8b22019-04-05 18:52:08 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.policy;
18
Philip P. Moltmannfaa788a2019-05-29 16:18:18 -070019import static android.app.AppOpsManager.MODE_ALLOWED;
Philip P. Moltmann404b51c2019-06-11 09:01:59 -070020import static android.app.AppOpsManager.MODE_FOREGROUND;
Philip P. Moltmannfaa788a2019-05-29 16:18:18 -070021import static android.app.AppOpsManager.MODE_IGNORED;
22import static android.app.AppOpsManager.OP_NONE;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070023import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
Philip P. Moltmann4e369a72019-06-14 11:08:16 -070024import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
Hai Zhangfa291702019-09-19 16:35:44 -070025import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
Philip P. Moltmann48687722019-04-11 10:40:30 -070026import static android.content.pm.PackageManager.GET_PERMISSIONS;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070027
28import android.annotation.NonNull;
Philip P. Moltmann48687722019-04-11 10:40:30 -070029import android.annotation.Nullable;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070030import android.annotation.UserIdInt;
31import android.app.AppOpsManager;
Hai Zhangf4ef0392020-02-03 14:49:35 -080032import android.app.AppOpsManagerInternal;
Nate Myrend15dcf92020-04-07 19:30:37 +000033import android.content.BroadcastReceiver;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070034import android.content.Context;
Hai Zhangf4da9be2019-05-01 13:46:06 +080035import android.content.Intent;
Eugene Susla4fce75d2019-12-10 09:51:58 -080036import android.content.IntentFilter;
Hai Zhangf4da9be2019-05-01 13:46:06 +080037import android.content.pm.ApplicationInfo;
Svet Ganov38a06312019-04-09 23:55:05 -070038import android.content.pm.PackageInfo;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070039import android.content.pm.PackageManager;
Svet Ganov38a06312019-04-09 23:55:05 -070040import android.content.pm.PackageManager.NameNotFoundException;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070041import android.content.pm.PackageManagerInternal;
42import android.content.pm.PackageManagerInternal.PackageListObserver;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070043import android.content.pm.PermissionInfo;
Philip P. Moltmann9408f582019-04-10 16:58:24 -070044import android.os.Build;
Philip P. Moltmannf94866082020-02-18 17:05:16 +000045import android.os.Process;
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -070046import android.os.RemoteException;
47import android.os.ServiceManager;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070048import android.os.UserHandle;
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -070049import android.os.UserManagerInternal;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070050import android.permission.PermissionControllerManager;
Nate Myrend15dcf92020-04-07 19:30:37 +000051import android.provider.Settings;
Hai Zhangf4da9be2019-05-01 13:46:06 +080052import android.provider.Telephony;
Hai Zhang114afc32019-05-01 14:16:23 +080053import android.telecom.TelecomManager;
Hai Zhang0c123fa2019-10-21 12:41:59 -070054import android.util.ArrayMap;
Philip P. Moltmann78c155b2019-06-14 09:02:24 -070055import android.util.ArraySet;
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -070056import android.util.LongSparseLongArray;
Philip P. Moltmannf94866082020-02-18 17:05:16 +000057import android.util.Pair;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070058import android.util.Slog;
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -070059import android.util.SparseBooleanArray;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070060
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -070061import com.android.internal.annotations.GuardedBy;
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -070062import com.android.internal.app.IAppOpsCallback;
63import com.android.internal.app.IAppOpsService;
Hai Zhang72ddbff2020-01-09 17:35:07 -080064import com.android.internal.infra.AndroidFuture;
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -070065import com.android.internal.util.IntPair;
Philip P. Moltmann78c155b2019-06-14 09:02:24 -070066import com.android.internal.util.function.pooled.PooledLambda;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070067import com.android.server.FgThread;
68import com.android.server.LocalServices;
69import com.android.server.SystemService;
Winson5e0a1d52020-01-24 12:00:33 -080070import com.android.server.pm.parsing.pkg.AndroidPackage;
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -070071import com.android.server.pm.permission.PermissionManagerServiceInternal;
Svet Ganov3c499ea2019-07-26 17:45:56 -070072import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
Eugene Susla27455542019-08-30 16:20:11 -070073
Svet Ganov38a06312019-04-09 23:55:05 -070074import java.util.ArrayList;
Hai Zhanga7c60c02020-03-05 16:03:35 -080075import java.util.Collections;
Nate Myrend15dcf92020-04-07 19:30:37 +000076import java.util.HashMap;
Hai Zhang0c123fa2019-10-21 12:41:59 -070077import java.util.List;
Nate Myrend15dcf92020-04-07 19:30:37 +000078import java.util.Map;
Hai Zhang72ddbff2020-01-09 17:35:07 -080079import java.util.concurrent.ExecutionException;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070080
81/**
82 * This is a permission policy that governs over all permission mechanism
83 * such as permissions, app ops, etc. For example, the policy ensures that
84 * permission state and app ops is synchronized for cases where there is a
85 * dependency between permission state (permissions or permission flags)
86 * and app ops - and vise versa.
87 */
88public final class PermissionPolicyService extends SystemService {
Svet Ganovd8eb8b22019-04-05 18:52:08 -070089 private static final String LOG_TAG = PermissionPolicyService.class.getSimpleName();
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -070090 private static final boolean DEBUG = false;
Nate Myren6b55e952020-05-14 13:48:44 -070091 private static final long USER_SENSITIVE_UPDATE_DELAY_MS = 10000;
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -070092
93 private final Object mLock = new Object();
94
Hai Zhangf4ef0392020-02-03 14:49:35 -080095 private IAppOpsCallback mAppOpsCallback;
96
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -070097 /** Whether the user is started but not yet stopped */
98 @GuardedBy("mLock")
99 private final SparseBooleanArray mIsStarted = new SparseBooleanArray();
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700100
Svet Ganov3c499ea2019-07-26 17:45:56 -0700101 /** Callbacks for when a user is initialized */
102 @GuardedBy("mLock")
103 private OnInitializedCallback mOnInitializedCallback;
104
Philip P. Moltmann78c155b2019-06-14 09:02:24 -0700105 /**
106 * Whether an async {@link #synchronizePackagePermissionsAndAppOpsForUser} is currently
107 * scheduled for a package/user.
108 */
109 @GuardedBy("mLock")
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000110 private final ArraySet<Pair<String, Integer>> mIsPackageSyncsScheduled = new ArraySet<>();
Philip P. Moltmann78c155b2019-06-14 09:02:24 -0700111
Hai Zhanga7c60c02020-03-05 16:03:35 -0800112 /**
113 * Whether an async {@link #resetAppOpPermissionsIfNotRequestedForUid} is currently
114 * scheduled for a uid.
115 */
116 @GuardedBy("mLock")
117 private final SparseBooleanArray mIsUidSyncScheduled = new SparseBooleanArray();
118
119 private List<String> mAppOpPermissions;
120
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700121 public PermissionPolicyService(@NonNull Context context) {
122 super(context);
Hai Zhangf4da9be2019-05-01 13:46:06 +0800123
124 LocalServices.addService(PermissionPolicyInternal.class, new Internal());
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700125 }
126
127 @Override
128 public void onStart() {
129 final PackageManagerInternal packageManagerInternal = LocalServices.getService(
130 PackageManagerInternal.class);
Hai Zhanga7c60c02020-03-05 16:03:35 -0800131 final PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -0700132 PermissionManagerServiceInternal.class);
133 final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
134 ServiceManager.getService(Context.APP_OPS_SERVICE));
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700135
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700136 packageManagerInternal.getPackageList(new PackageListObserver() {
137 @Override
138 public void onPackageAdded(String packageName, int uid) {
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000139 final int userId = UserHandle.getUserId(uid);
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000140 if (isStarted(userId)) {
141 synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700142 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700143 }
144
145 @Override
Hai Zhanga7c60c02020-03-05 16:03:35 -0800146 public void onPackageChanged(String packageName, int uid) {
147 final int userId = UserHandle.getUserId(uid);
148 if (isStarted(userId)) {
149 synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
150 resetAppOpPermissionsIfNotRequestedForUid(uid);
151 }
152 }
153
154 @Override
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700155 public void onPackageRemoved(String packageName, int uid) {
Hai Zhanga7c60c02020-03-05 16:03:35 -0800156 final int userId = UserHandle.getUserId(uid);
157 if (isStarted(userId)) {
158 resetAppOpPermissionsIfNotRequestedForUid(uid);
159 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700160 }
161 });
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700162
Hai Zhanga7c60c02020-03-05 16:03:35 -0800163 permissionManagerInternal.addOnRuntimePermissionStateChangedListener(
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000164 this::synchronizePackagePermissionsAndAppOpsAsyncForUser);
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -0700165
Hai Zhangf4ef0392020-02-03 14:49:35 -0800166 mAppOpsCallback = new IAppOpsCallback.Stub() {
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -0700167 public void opChanged(int op, int uid, String packageName) {
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000168 synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName,
169 UserHandle.getUserId(uid));
Hai Zhanga7c60c02020-03-05 16:03:35 -0800170 resetAppOpPermissionsIfNotRequestedForUidAsync(uid);
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -0700171 }
172 };
173
174 final ArrayList<PermissionInfo> dangerousPerms =
Hai Zhanga7c60c02020-03-05 16:03:35 -0800175 permissionManagerInternal.getAllPermissionsWithProtection(
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -0700176 PermissionInfo.PROTECTION_DANGEROUS);
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -0700177 try {
178 int numDangerousPerms = dangerousPerms.size();
179 for (int i = 0; i < numDangerousPerms; i++) {
180 PermissionInfo perm = dangerousPerms.get(i);
181
Hai Zhangab6a6822019-10-18 00:34:06 +0000182 if (perm.isRuntime()) {
Hai Zhangf4ef0392020-02-03 14:49:35 -0800183 appOpsService.startWatchingMode(getSwitchOp(perm.name), null, mAppOpsCallback);
Hai Zhangbcfb0752019-10-07 14:52:30 -0700184 }
185 if (perm.isSoftRestricted()) {
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -0700186 SoftRestrictedPermissionPolicy policy =
Hai Zhangfa291702019-09-19 16:35:44 -0700187 SoftRestrictedPermissionPolicy.forPermission(null, null, null,
Winson33eacc62020-01-24 12:02:58 -0800188 null, perm.name);
Hai Zhangfa291702019-09-19 16:35:44 -0700189 int extraAppOp = policy.getExtraAppOpCode();
190 if (extraAppOp != OP_NONE) {
Hai Zhangf4ef0392020-02-03 14:49:35 -0800191 appOpsService.startWatchingMode(extraAppOp, null, mAppOpsCallback);
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -0700192 }
193 }
194 }
195 } catch (RemoteException doesNotHappen) {
196 Slog.wtf(LOG_TAG, "Cannot set up app-ops listener");
197 }
Eugene Susla4fce75d2019-12-10 09:51:58 -0800198
Hai Zhanga7c60c02020-03-05 16:03:35 -0800199 final List<PermissionInfo> appOpPermissionInfos =
200 permissionManagerInternal.getAllPermissionsWithProtectionFlags(
201 PermissionInfo.PROTECTION_FLAG_APPOP);
202 mAppOpPermissions = new ArrayList<>();
203 final int appOpPermissionInfosSize = appOpPermissionInfos.size();
204 for (int i = 0; i < appOpPermissionInfosSize; i++) {
205 final PermissionInfo appOpPermissionInfo = appOpPermissionInfos.get(i);
206
Hai Zhang17ae9542020-05-08 12:00:48 -0700207 switch (appOpPermissionInfo.name) {
208 case android.Manifest.permission.ACCESS_NOTIFICATIONS:
209 case android.Manifest.permission.MANAGE_IPSEC_TUNNELS:
210 continue;
Hai Zhang643f9132020-05-28 14:12:20 -0700211 case android.Manifest.permission.REQUEST_INSTALL_PACKAGES:
212 // Settings allows the user to control the app op if it's not in the default
213 // mode, regardless of whether the app has requested the permission, so we
214 // should not reset it.
215 continue;
Hai Zhang17ae9542020-05-08 12:00:48 -0700216 default:
217 final int appOpCode = AppOpsManager.permissionToOpCode(
218 appOpPermissionInfo.name);
219 if (appOpCode != OP_NONE) {
220 mAppOpPermissions.add(appOpPermissionInfo.name);
221 try {
222 appOpsService.startWatchingMode(appOpCode, null, mAppOpsCallback);
223 } catch (RemoteException e) {
224 Slog.wtf(LOG_TAG, "Cannot set up app-ops listener", e);
225 }
226 }
Hai Zhanga7c60c02020-03-05 16:03:35 -0800227 }
228 }
229
Eugene Susla4fce75d2019-12-10 09:51:58 -0800230 IntentFilter intentFilter = new IntentFilter();
231 intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
232 intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
233 intentFilter.addDataScheme("package");
234
Eugene Susla4fce75d2019-12-10 09:51:58 -0800235 getContext().registerReceiverAsUser(new BroadcastReceiver() {
236 final List<Integer> mUserSetupUids = new ArrayList<>(200);
237 final Map<UserHandle, PermissionControllerManager> mPermControllerManagers =
238 new HashMap<>();
239
240 @Override
241 public void onReceive(Context context, Intent intent) {
242 boolean hasSetupRun = true;
243 try {
244 hasSetupRun = Settings.Secure.getInt(getContext().getContentResolver(),
245 Settings.Secure.USER_SETUP_COMPLETE) != 0;
246 } catch (Settings.SettingNotFoundException e) {
247 // Ignore error, assume setup has run
248 }
249 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
250 // If there is no valid package for the given UID, return immediately
251 if (packageManagerInternal.getPackage(uid) == null) {
252 return;
253 }
254
255 if (hasSetupRun) {
256 if (!mUserSetupUids.isEmpty()) {
257 synchronized (mUserSetupUids) {
258 for (int i = mUserSetupUids.size() - 1; i >= 0; i--) {
259 updateUid(mUserSetupUids.get(i));
260 }
261 mUserSetupUids.clear();
262 }
263 }
264 updateUid(uid);
265 } else {
266 synchronized (mUserSetupUids) {
267 if (!mUserSetupUids.contains(uid)) {
268 mUserSetupUids.add(uid);
269 }
270 }
271 }
272 }
273
274 private void updateUid(int uid) {
275 UserHandle user = UserHandle.getUserHandleForUid(uid);
276 PermissionControllerManager manager = mPermControllerManagers.get(user);
277 if (manager == null) {
278 manager = new PermissionControllerManager(
279 getUserContext(getContext(), user), FgThread.getHandler());
280 mPermControllerManagers.put(user, manager);
281 }
282 manager.updateUserSensitiveForApp(uid);
283 }
284 }, UserHandle.ALL, intentFilter, null, null);
Philip P. Moltmann78c155b2019-06-14 09:02:24 -0700285 }
286
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700287 /**
288 * Get op that controls the access related to the permission.
289 *
290 * <p>Usually the permission-op relationship is 1:1 but some permissions (e.g. fine location)
291 * {@link AppOpsManager#sOpToSwitch share an op} to control the access.
292 *
293 * @param permission The permission
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700294 * @return The op that controls the access of the permission
295 */
296 private static int getSwitchOp(@NonNull String permission) {
297 int op = AppOpsManager.permissionToOpCode(permission);
298 if (op == OP_NONE) {
299 return OP_NONE;
300 }
301
302 return AppOpsManager.opToSwitch(op);
303 }
304
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000305 private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
306 @UserIdInt int changedUserId) {
307 if (isStarted(changedUserId)) {
Philip P. Moltmann78c155b2019-06-14 09:02:24 -0700308 synchronized (mLock) {
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000309 if (mIsPackageSyncsScheduled.add(new Pair<>(packageName, changedUserId))) {
Philip P. Moltmann78c155b2019-06-14 09:02:24 -0700310 FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
311 PermissionPolicyService
312 ::synchronizePackagePermissionsAndAppOpsForUser,
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000313 this, packageName, changedUserId));
Philip P. Moltmann78c155b2019-06-14 09:02:24 -0700314 } else {
315 if (DEBUG) {
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000316 Slog.v(LOG_TAG, "sync for " + packageName + "/" + changedUserId
317 + " already scheduled");
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700318 }
Philip P. Moltmann78c155b2019-06-14 09:02:24 -0700319 }
320 }
321 }
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700322 }
323
324 @Override
325 public void onBootPhase(int phase) {
326 if (DEBUG) Slog.i(LOG_TAG, "onBootPhase(" + phase + ")");
327
328 if (phase == PHASE_ACTIVITY_MANAGER_READY) {
329 final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);
330
331 // For some users we might not receive a onStartUser, hence force one here
332 for (int userId : um.getUserIds()) {
333 if (um.isUserRunning(userId)) {
334 onStartUser(userId);
335 }
336 }
337 }
338 }
339
340 /**
341 * @return Whether the user is started but not yet stopped
342 */
343 private boolean isStarted(@UserIdInt int userId) {
344 synchronized (mLock) {
345 return mIsStarted.get(userId);
346 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700347 }
348
349 @Override
350 public void onStartUser(@UserIdInt int userId) {
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700351 if (DEBUG) Slog.i(LOG_TAG, "onStartUser(" + userId + ")");
352
353 if (isStarted(userId)) {
354 return;
355 }
356
357 grantOrUpgradeDefaultRuntimePermissionsIfNeeded(userId);
358
Svet Ganov3c499ea2019-07-26 17:45:56 -0700359 final OnInitializedCallback callback;
360
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700361 synchronized (mLock) {
362 mIsStarted.put(userId, true);
Svet Ganov3c499ea2019-07-26 17:45:56 -0700363 callback = mOnInitializedCallback;
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700364 }
365
366 // Force synchronization as permissions might have changed
367 synchronizePermissionsAndAppOpsForUser(userId);
Svet Ganov3c499ea2019-07-26 17:45:56 -0700368
369 // Tell observers we are initialized for this user.
370 if (callback != null) {
371 callback.onInitialized(userId);
372 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700373 }
374
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700375 @Override
376 public void onStopUser(@UserIdInt int userId) {
377 if (DEBUG) Slog.i(LOG_TAG, "onStopUser(" + userId + ")");
378
379 synchronized (mLock) {
380 mIsStarted.delete(userId);
381 }
382 }
383
384 private void grantOrUpgradeDefaultRuntimePermissionsIfNeeded(@UserIdInt int userId) {
385 if (DEBUG) Slog.i(LOG_TAG, "grantOrUpgradeDefaultPermsIfNeeded(" + userId + ")");
386
Todd Kennedy583378d2019-07-12 06:50:30 -0700387 final PackageManagerInternal packageManagerInternal =
388 LocalServices.getService(PackageManagerInternal.class);
389 final PermissionManagerServiceInternal permissionManagerInternal =
390 LocalServices.getService(PermissionManagerServiceInternal.class);
Evan Severson0dc24cb2020-02-04 10:25:08 -0800391 if (packageManagerInternal.isPermissionUpgradeNeeded(userId)) {
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700392 if (DEBUG) Slog.i(LOG_TAG, "defaultPermsWereGrantedSinceBoot(" + userId + ")");
393
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700394 // Now call into the permission controller to apply policy around permissions
Hai Zhang72ddbff2020-01-09 17:35:07 -0800395 final AndroidFuture<Boolean> future = new AndroidFuture<>();
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700396
397 // We need to create a local manager that does not schedule work on the main
398 // there as we are on the main thread and want to block until the work is
399 // completed or we time out.
400 final PermissionControllerManager permissionControllerManager =
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700401 new PermissionControllerManager(
402 getUserContext(getContext(), UserHandle.of(userId)),
Philip P. Moltmann7870aa02019-05-10 15:01:32 -0700403 FgThread.getHandler());
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700404 permissionControllerManager.grantOrUpgradeDefaultRuntimePermissions(
Hai Zhang72ddbff2020-01-09 17:35:07 -0800405 FgThread.getExecutor(), successful -> {
406 if (successful) {
407 future.complete(null);
408 } else {
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700409 // We are in an undefined state now, let us crash and have
410 // rescue party suggest a wipe to recover to a good one.
Hai Zhang72ddbff2020-01-09 17:35:07 -0800411 final String message = "Error granting/upgrading runtime permissions"
412 + " for user " + userId;
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700413 Slog.wtf(LOG_TAG, message);
Hai Zhang72ddbff2020-01-09 17:35:07 -0800414 future.completeExceptionally(new IllegalStateException(message));
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700415 }
Hai Zhang72ddbff2020-01-09 17:35:07 -0800416 });
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700417 try {
Hai Zhang72ddbff2020-01-09 17:35:07 -0800418 future.get();
419 } catch (InterruptedException | ExecutionException e) {
420 throw new IllegalStateException(e);
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700421 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700422
Nate Myren6b55e952020-05-14 13:48:44 -0700423 FgThread.getHandler().postDelayed(permissionControllerManager::updateUserSensitive,
424 USER_SENSITIVE_UPDATE_DELAY_MS);
Eugene Susla27455542019-08-30 16:20:11 -0700425
Evan Severson0dc24cb2020-02-04 10:25:08 -0800426 packageManagerInternal.updateRuntimePermissionsFingerprint(userId);
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700427 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700428 }
429
Philip P. Moltmann48687722019-04-11 10:40:30 -0700430 private static @Nullable Context getUserContext(@NonNull Context context,
Svet Ganovd563e932019-04-14 13:07:41 -0700431 @Nullable UserHandle user) {
Philip P. Moltmann48687722019-04-11 10:40:30 -0700432 if (context.getUser().equals(user)) {
433 return context;
434 } else {
435 try {
436 return context.createPackageContextAsUser(context.getPackageName(), 0, user);
437 } catch (NameNotFoundException e) {
438 Slog.e(LOG_TAG, "Cannot create context for user " + user, e);
439 return null;
440 }
441 }
442 }
443
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700444 /**
445 * Synchronize a single package.
446 */
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000447 private void synchronizePackagePermissionsAndAppOpsForUser(@NonNull String packageName,
448 @UserIdInt int userId) {
Philip P. Moltmann78c155b2019-06-14 09:02:24 -0700449 synchronized (mLock) {
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000450 mIsPackageSyncsScheduled.remove(new Pair<>(packageName, userId));
Philip P. Moltmann78c155b2019-06-14 09:02:24 -0700451 }
452
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700453 if (DEBUG) {
454 Slog.v(LOG_TAG,
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000455 "synchronizePackagePermissionsAndAppOpsForUser(" + packageName + ", "
456 + userId + ")");
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700457 }
458
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000459 final PackageManagerInternal packageManagerInternal = LocalServices.getService(
460 PackageManagerInternal.class);
461 final PackageInfo pkg = packageManagerInternal.getPackageInfo(packageName, 0,
462 Process.SYSTEM_UID, userId);
463 if (pkg == null) {
464 return;
465 }
Philip P. Moltmann48687722019-04-11 10:40:30 -0700466 final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser(
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000467 getUserContext(getContext(), UserHandle.of(userId)));
468 synchroniser.addPackage(pkg.packageName);
469 final String[] sharedPkgNames = packageManagerInternal.getSharedUserPackagesForPackage(
470 pkg.packageName, userId);
471
472 for (String sharedPkgName : sharedPkgNames) {
473 final AndroidPackage sharedPkg = packageManagerInternal
474 .getPackage(sharedPkgName);
475 if (sharedPkg != null) {
476 synchroniser.addPackage(sharedPkg.getPackageName());
477 }
478 }
479 synchroniser.syncPackages();
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700480 }
481
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700482 /**
483 * Synchronize all packages
484 */
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700485 private void synchronizePermissionsAndAppOpsForUser(@UserIdInt int userId) {
486 if (DEBUG) Slog.i(LOG_TAG, "synchronizePermissionsAndAppOpsForUser(" + userId + ")");
487
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700488 final PackageManagerInternal packageManagerInternal = LocalServices.getService(
489 PackageManagerInternal.class);
Philip P. Moltmann48687722019-04-11 10:40:30 -0700490 final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser(
Philip P. Moltmann5f5783e2019-05-22 14:57:18 -0700491 getUserContext(getContext(), UserHandle.of(userId)));
Winson14ff7172019-10-23 10:42:27 -0700492 packageManagerInternal.forEachPackage(
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000493 (pkg) -> synchronizer.addPackage(pkg.getPackageName()));
494 synchronizer.syncPackages();
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700495 }
496
Hai Zhanga7c60c02020-03-05 16:03:35 -0800497 private void resetAppOpPermissionsIfNotRequestedForUidAsync(int uid) {
498 if (isStarted(UserHandle.getUserId(uid))) {
499 synchronized (mLock) {
500 if (!mIsUidSyncScheduled.get(uid)) {
501 mIsUidSyncScheduled.put(uid, true);
502 FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
503 PermissionPolicyService::resetAppOpPermissionsIfNotRequestedForUid,
504 this, uid));
505 }
506 }
507 }
508 }
509
510 private void resetAppOpPermissionsIfNotRequestedForUid(int uid) {
511 synchronized (mLock) {
512 mIsUidSyncScheduled.delete(uid);
513 }
514
515 final Context context = getContext();
516 final PackageManager userPackageManager = getUserContext(context,
517 UserHandle.getUserHandleForUid(uid)).getPackageManager();
518 final String[] packageNames = userPackageManager.getPackagesForUid(uid);
519 if (packageNames == null || packageNames.length == 0) {
520 return;
521 }
522
523 final ArraySet<String> requestedPermissions = new ArraySet<>();
524 for (String packageName : packageNames) {
525 final PackageInfo packageInfo;
526 try {
527 packageInfo = userPackageManager.getPackageInfo(packageName, GET_PERMISSIONS);
528 } catch (NameNotFoundException e) {
529 continue;
530 }
531 if (packageInfo == null || packageInfo.requestedPermissions == null) {
532 continue;
533 }
534 Collections.addAll(requestedPermissions, packageInfo.requestedPermissions);
535 }
536
537 final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
538 final AppOpsManagerInternal appOpsManagerInternal = LocalServices.getService(
539 AppOpsManagerInternal.class);
540 final int appOpPermissionsSize = mAppOpPermissions.size();
541 for (int i = 0; i < appOpPermissionsSize; i++) {
542 final String appOpPermission = mAppOpPermissions.get(i);
543
544 if (!requestedPermissions.contains(appOpPermission)) {
545 final int appOpCode = AppOpsManager.permissionToOpCode(appOpPermission);
546 final int defaultAppOpMode = AppOpsManager.opToDefaultMode(appOpCode);
547 for (String packageName : packageNames) {
548 final int appOpMode = appOpsManager.unsafeCheckOpRawNoThrow(appOpCode, uid,
549 packageName);
550 if (appOpMode != defaultAppOpMode) {
551 appOpsManagerInternal.setUidModeFromPermissionPolicy(appOpCode, uid,
552 defaultAppOpMode, mAppOpsCallback);
553 appOpsManagerInternal.setModeFromPermissionPolicy(appOpCode, uid,
554 packageName, defaultAppOpMode, mAppOpsCallback);
555 }
556 }
557 }
558 }
559 }
560
Svet Ganov38a06312019-04-09 23:55:05 -0700561 /**
562 * Synchronizes permission to app ops. You *must* always sync all packages
563 * in a shared UID at the same time to ensure proper synchronization.
564 */
Hai Zhangf4ef0392020-02-03 14:49:35 -0800565 private class PermissionToOpSynchroniser {
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700566 private final @NonNull Context mContext;
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700567 private final @NonNull PackageManager mPackageManager;
568 private final @NonNull AppOpsManager mAppOpsManager;
Hai Zhangf4ef0392020-02-03 14:49:35 -0800569 private final @NonNull AppOpsManagerInternal mAppOpsManagerInternal;
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700570
Hai Zhang0c123fa2019-10-21 12:41:59 -0700571 private final @NonNull ArrayMap<String, PermissionInfo> mRuntimePermissionInfos;
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700572
573 /**
Philip P. Moltmann74065c82019-05-15 10:46:32 -0700574 * All ops that need to be flipped to allow.
575 *
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000576 * @see #syncPackages
Philip P. Moltmann74065c82019-05-15 10:46:32 -0700577 */
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000578 private final @NonNull ArrayList<OpToChange> mOpsToAllow = new ArrayList<>();
Svet Ganovd563e932019-04-14 13:07:41 -0700579
580 /**
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700581 * All ops that need to be flipped to ignore.
Philip P. Moltmann9408f582019-04-10 16:58:24 -0700582 *
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000583 * @see #syncPackages
Philip P. Moltmann9408f582019-04-10 16:58:24 -0700584 */
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000585 private final @NonNull ArrayList<OpToChange> mOpsToIgnore = new ArrayList<>();
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700586
587 /**
Hai Zhangfa291702019-09-19 16:35:44 -0700588 * All ops that need to be flipped to ignore if not allowed.
589 *
590 * Currently, only used by soft restricted permissions logic.
591 *
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000592 * @see #syncPackages
Hai Zhangfa291702019-09-19 16:35:44 -0700593 */
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000594 private final @NonNull ArrayList<OpToChange> mOpsToIgnoreIfNotAllowed = new ArrayList<>();
Hai Zhangfa291702019-09-19 16:35:44 -0700595
596 /**
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700597 * All ops that need to be flipped to foreground.
598 *
599 * Currently, only used by the foreground/background permissions logic.
600 *
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000601 * @see #syncPackages
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700602 */
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000603 private final @NonNull ArrayList<OpToChange> mOpsToForeground = new ArrayList<>();
Philip P. Moltmann9408f582019-04-10 16:58:24 -0700604
Svet Ganov38a06312019-04-09 23:55:05 -0700605 PermissionToOpSynchroniser(@NonNull Context context) {
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700606 mContext = context;
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700607 mPackageManager = context.getPackageManager();
608 mAppOpsManager = context.getSystemService(AppOpsManager.class);
Hai Zhangf4ef0392020-02-03 14:49:35 -0800609 mAppOpsManagerInternal = LocalServices.getService(AppOpsManagerInternal.class);
Hai Zhang0c123fa2019-10-21 12:41:59 -0700610
611 mRuntimePermissionInfos = new ArrayMap<>();
612 PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
613 PermissionManagerServiceInternal.class);
614 List<PermissionInfo> permissionInfos =
Hai Zhanga7c60c02020-03-05 16:03:35 -0800615 permissionManagerInternal.getAllPermissionsWithProtection(
Hai Zhang0c123fa2019-10-21 12:41:59 -0700616 PermissionInfo.PROTECTION_DANGEROUS);
617 int permissionInfosSize = permissionInfos.size();
618 for (int i = 0; i < permissionInfosSize; i++) {
619 PermissionInfo permissionInfo = permissionInfos.get(i);
620 mRuntimePermissionInfos.put(permissionInfo.name, permissionInfo);
621 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700622 }
623
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700624 /**
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000625 * Set app ops that were added in {@link #addPackage}.
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700626 *
Hai Zhangea87b472019-09-27 15:48:07 -0700627 * <p>This processes ops previously added by {@link #addAppOps(PackageInfo, String)}
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700628 */
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000629 private void syncPackages() {
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700630 // Remember which ops were already set. This makes sure that we always set the most
631 // permissive mode if two OpChanges are scheduled. This can e.g. happen if two
632 // permissions change the same op. See {@link #getSwitchOp}.
633 LongSparseLongArray alreadySetAppOps = new LongSparseLongArray();
634
Svet Ganovd563e932019-04-14 13:07:41 -0700635 final int allowCount = mOpsToAllow.size();
636 for (int i = 0; i < allowCount; i++) {
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000637 final OpToChange op = mOpsToAllow.get(i);
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700638
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000639 setUidModeAllowed(op.code, op.uid, op.packageName);
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700640 alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
Philip P. Moltmann74065c82019-05-15 10:46:32 -0700641 }
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700642
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700643 final int foregroundCount = mOpsToForeground.size();
644 for (int i = 0; i < foregroundCount; i++) {
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000645 final OpToChange op = mOpsToForeground.get(i);
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700646 if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
647 continue;
648 }
649
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000650 setUidModeForeground(op.code, op.uid, op.packageName);
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700651 alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700652 }
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700653
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700654 final int ignoreCount = mOpsToIgnore.size();
655 for (int i = 0; i < ignoreCount; i++) {
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000656 final OpToChange op = mOpsToIgnore.get(i);
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700657 if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
658 continue;
659 }
660
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000661 setUidModeIgnored(op.code, op.uid, op.packageName);
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700662 alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700663 }
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700664
Hai Zhangfa291702019-09-19 16:35:44 -0700665 final int ignoreIfNotAllowedCount = mOpsToIgnoreIfNotAllowed.size();
666 for (int i = 0; i < ignoreIfNotAllowedCount; i++) {
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000667 final OpToChange op = mOpsToIgnoreIfNotAllowed.get(i);
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700668 if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
669 continue;
670 }
671
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000672 boolean wasSet = setUidModeIgnoredIfNotAllowed(op.code, op.uid, op.packageName);
Philip P. Moltmann3b8c14c2019-06-26 10:18:34 -0700673 if (wasSet) {
674 alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
675 }
Svet Ganovd563e932019-04-14 13:07:41 -0700676 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700677 }
678
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700679 /**
Hai Zhangea87b472019-09-27 15:48:07 -0700680 * Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700681 */
Winson33eacc62020-01-24 12:02:58 -0800682 private void addAppOps(@NonNull PackageInfo packageInfo, @NonNull AndroidPackage pkg,
683 @NonNull String permissionName) {
Hai Zhang0c123fa2019-10-21 12:41:59 -0700684 PermissionInfo permissionInfo = mRuntimePermissionInfos.get(permissionName);
Hai Zhangea87b472019-09-27 15:48:07 -0700685 if (permissionInfo == null) {
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700686 return;
687 }
Winson33eacc62020-01-24 12:02:58 -0800688 addPermissionAppOp(packageInfo, pkg, permissionInfo);
689 addExtraAppOp(packageInfo, pkg, permissionInfo);
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700690 }
691
Hai Zhangea87b472019-09-27 15:48:07 -0700692 private void addPermissionAppOp(@NonNull PackageInfo packageInfo,
Winson33eacc62020-01-24 12:02:58 -0800693 @NonNull AndroidPackage pkg, @NonNull PermissionInfo permissionInfo) {
Hai Zhangab6a6822019-10-18 00:34:06 +0000694 if (!permissionInfo.isRuntime()) {
Philip P. Moltmann9408f582019-04-10 16:58:24 -0700695 return;
696 }
697
Hai Zhangea87b472019-09-27 15:48:07 -0700698 String permissionName = permissionInfo.name;
699 String packageName = packageInfo.packageName;
700 int permissionFlags = mPackageManager.getPermissionFlags(permissionName,
701 packageName, mContext.getUser());
702 boolean isReviewRequired = (permissionFlags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0;
703 if (isReviewRequired) {
Philip P. Moltmann4e369a72019-06-14 11:08:16 -0700704 return;
705 }
706
Hai Zhangea87b472019-09-27 15:48:07 -0700707 // TODO: COARSE_LOCATION and FINE_LOCATION shares the same app op. We are solving this
708 // with switch op but once we start syncing single permission this won't work.
709 int appOpCode = getSwitchOp(permissionName);
710 if (appOpCode == OP_NONE) {
711 // Note that background permissions don't have an associated app op.
712 return;
713 }
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700714
Hai Zhangea87b472019-09-27 15:48:07 -0700715 int appOpMode;
Winson33eacc62020-01-24 12:02:58 -0800716 boolean shouldGrantAppOp = shouldGrantAppOp(packageInfo, pkg, permissionInfo);
Hai Zhangea87b472019-09-27 15:48:07 -0700717 if (shouldGrantAppOp) {
718 if (permissionInfo.backgroundPermission != null) {
Hai Zhang0c123fa2019-10-21 12:41:59 -0700719 PermissionInfo backgroundPermissionInfo = mRuntimePermissionInfos.get(
Hai Zhangea87b472019-09-27 15:48:07 -0700720 permissionInfo.backgroundPermission);
721 boolean shouldGrantBackgroundAppOp = backgroundPermissionInfo != null
Winson33eacc62020-01-24 12:02:58 -0800722 && shouldGrantAppOp(packageInfo, pkg, backgroundPermissionInfo);
Hai Zhangea87b472019-09-27 15:48:07 -0700723 appOpMode = shouldGrantBackgroundAppOp ? MODE_ALLOWED : MODE_FOREGROUND;
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700724 } else {
Hai Zhangea87b472019-09-27 15:48:07 -0700725 appOpMode = MODE_ALLOWED;
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700726 }
727 } else {
Hai Zhangea87b472019-09-27 15:48:07 -0700728 appOpMode = MODE_IGNORED;
729 }
730
731 int uid = packageInfo.applicationInfo.uid;
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000732 OpToChange opToChange = new OpToChange(uid, packageName, appOpCode);
Hai Zhangea87b472019-09-27 15:48:07 -0700733 switch (appOpMode) {
734 case MODE_ALLOWED:
735 mOpsToAllow.add(opToChange);
736 break;
737 case MODE_FOREGROUND:
738 mOpsToForeground.add(opToChange);
739 break;
740 case MODE_IGNORED:
741 mOpsToIgnore.add(opToChange);
742 break;
743 }
744 }
745
Hai Zhangea87b472019-09-27 15:48:07 -0700746 private boolean shouldGrantAppOp(@NonNull PackageInfo packageInfo,
Winson33eacc62020-01-24 12:02:58 -0800747 @NonNull AndroidPackage pkg, @NonNull PermissionInfo permissionInfo) {
Hai Zhangea87b472019-09-27 15:48:07 -0700748 String permissionName = permissionInfo.name;
749 String packageName = packageInfo.packageName;
750 boolean isGranted = mPackageManager.checkPermission(permissionName, packageName)
751 == PackageManager.PERMISSION_GRANTED;
752 if (!isGranted) {
753 return false;
754 }
755
756 int permissionFlags = mPackageManager.getPermissionFlags(permissionName, packageName,
757 mContext.getUser());
758 boolean isRevokedCompat = (permissionFlags & FLAG_PERMISSION_REVOKED_COMPAT)
759 == FLAG_PERMISSION_REVOKED_COMPAT;
760 if (isRevokedCompat) {
761 return false;
762 }
763
764 if (permissionInfo.isHardRestricted()) {
765 boolean shouldApplyRestriction =
766 (permissionFlags & FLAG_PERMISSION_APPLY_RESTRICTION)
767 == FLAG_PERMISSION_APPLY_RESTRICTION;
768 return !shouldApplyRestriction;
769 } else if (permissionInfo.isSoftRestricted()) {
770 SoftRestrictedPermissionPolicy policy =
771 SoftRestrictedPermissionPolicy.forPermission(mContext,
Winson33eacc62020-01-24 12:02:58 -0800772 packageInfo.applicationInfo, pkg, mContext.getUser(),
773 permissionName);
Hai Zhangea87b472019-09-27 15:48:07 -0700774 return policy.mayGrantPermission();
775 } else {
776 return true;
777 }
778 }
779
Winson33eacc62020-01-24 12:02:58 -0800780 private void addExtraAppOp(@NonNull PackageInfo packageInfo, @NonNull AndroidPackage pkg,
Hai Zhangea87b472019-09-27 15:48:07 -0700781 @NonNull PermissionInfo permissionInfo) {
782 if (!permissionInfo.isSoftRestricted()) {
783 return;
784 }
785
786 String permissionName = permissionInfo.name;
787 SoftRestrictedPermissionPolicy policy =
788 SoftRestrictedPermissionPolicy.forPermission(mContext,
Winson33eacc62020-01-24 12:02:58 -0800789 packageInfo.applicationInfo, pkg, mContext.getUser(), permissionName);
Hai Zhangea87b472019-09-27 15:48:07 -0700790 int extraOpCode = policy.getExtraAppOpCode();
791 if (extraOpCode == OP_NONE) {
792 return;
793 }
794
795 int uid = packageInfo.applicationInfo.uid;
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000796 String packageName = packageInfo.packageName;
797 OpToChange extraOpToChange = new OpToChange(uid, packageName, extraOpCode);
Hai Zhangea87b472019-09-27 15:48:07 -0700798 if (policy.mayAllowExtraAppOp()) {
799 mOpsToAllow.add(extraOpToChange);
800 } else {
801 if (policy.mayDenyExtraAppOpIfGranted()) {
802 mOpsToIgnore.add(extraOpToChange);
803 } else {
804 mOpsToIgnoreIfNotAllowed.add(extraOpToChange);
805 }
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700806 }
Philip P. Moltmann9408f582019-04-10 16:58:24 -0700807 }
808
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700809 /**
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000810 * Add a package for {@link #syncPackages() processing} later.
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700811 *
812 * <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
813 *
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000814 * @param pkgName The package to add for later processing.
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700815 */
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000816 void addPackage(@NonNull String pkgName) {
Winson33eacc62020-01-24 12:02:58 -0800817 PackageManagerInternal pmInternal =
818 LocalServices.getService(PackageManagerInternal.class);
819 final PackageInfo pkgInfo;
820 final AndroidPackage pkg;
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000821 try {
Winson33eacc62020-01-24 12:02:58 -0800822 pkgInfo = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
823 pkg = pmInternal.getPackage(pkgName);
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000824 } catch (NameNotFoundException e) {
Philip P. Moltmann48687722019-04-11 10:40:30 -0700825 return;
826 }
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700827
Hai Zhang20eff342020-06-17 14:03:49 -0700828 if (pkgInfo == null || pkg == null || pkgInfo.applicationInfo == null
829 || pkgInfo.requestedPermissions == null) {
830 return;
831 }
832
833 final int uid = pkgInfo.applicationInfo.uid;
834 if (uid == Process.ROOT_UID || uid == Process.SYSTEM_UID) {
835 // Root and system server always pass permission checks, so don't touch their app
836 // ops to keep compatibility.
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000837 return;
838 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700839
Winson33eacc62020-01-24 12:02:58 -0800840 for (String permission : pkgInfo.requestedPermissions) {
841 addAppOps(pkgInfo, pkg, permission);
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700842 }
843 }
844
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000845 private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
846 setUidMode(opCode, uid, MODE_ALLOWED, packageName);
Philip P. Moltmann74065c82019-05-15 10:46:32 -0700847 }
848
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000849 private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
850 setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700851 }
852
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000853 private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
854 setUidMode(opCode, uid, MODE_IGNORED, packageName);
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -0700855 }
856
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000857 private boolean setUidModeIgnoredIfNotAllowed(int opCode, int uid,
858 @NonNull String packageName) {
Hai Zhangfa291702019-09-19 16:35:44 -0700859 final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000860 opCode), uid, packageName);
Hai Zhangfa291702019-09-19 16:35:44 -0700861 if (currentMode != MODE_ALLOWED) {
862 if (currentMode != MODE_IGNORED) {
Hai Zhang8846aaa2020-02-13 15:19:54 -0800863 mAppOpsManagerInternal.setUidModeFromPermissionPolicy(opCode, uid, MODE_IGNORED,
Hai Zhangf4ef0392020-02-03 14:49:35 -0800864 mAppOpsCallback);
Hai Zhangfa291702019-09-19 16:35:44 -0700865 }
866 return true;
867 }
868 return false;
869 }
870
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000871 private void setUidMode(int opCode, int uid, int mode,
872 @NonNull String packageName) {
Hai Zhanga7ed4752019-12-10 13:45:54 -0800873 final int oldMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000874 opCode), uid, packageName);
Hai Zhanga7ed4752019-12-10 13:45:54 -0800875 if (oldMode != mode) {
Hai Zhang8846aaa2020-02-13 15:19:54 -0800876 mAppOpsManagerInternal.setUidModeFromPermissionPolicy(opCode, uid, mode,
Hai Zhangf4ef0392020-02-03 14:49:35 -0800877 mAppOpsCallback);
Hai Zhanga7ed4752019-12-10 13:45:54 -0800878 final int newMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000879 opCode), uid, packageName);
Hai Zhanga7ed4752019-12-10 13:45:54 -0800880 if (newMode != mode) {
881 // Work around incorrectly-set package mode. It never makes sense for app ops
882 // related to runtime permissions, but can get in the way and we have to reset
883 // it.
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000884 mAppOpsManagerInternal.setModeFromPermissionPolicy(opCode, uid, packageName,
Hai Zhangf4ef0392020-02-03 14:49:35 -0800885 AppOpsManager.opToDefaultMode(opCode), mAppOpsCallback);
Hai Zhanga7ed4752019-12-10 13:45:54 -0800886 }
Philip P. Moltmannfad1a8f2019-06-14 09:02:24 -0700887 }
Philip P. Moltmann404b51c2019-06-11 09:01:59 -0700888 }
889
Philip P. Moltmanne9f4b5a2019-06-20 14:51:52 -0700890 private class OpToChange {
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700891 final int uid;
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000892 final @NonNull String packageName;
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700893 final int code;
894
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000895 OpToChange(int uid, @NonNull String packageName, int code) {
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700896 this.uid = uid;
Philip P. Moltmannf94866082020-02-18 17:05:16 +0000897 this.packageName = packageName;
Philip P. Moltmannbd4943b2019-04-11 10:05:48 -0700898 this.code = code;
899 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700900 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700901 }
Hai Zhangf4da9be2019-05-01 13:46:06 +0800902
903 private class Internal extends PermissionPolicyInternal {
904
905 @Override
906 public boolean checkStartActivity(@NonNull Intent intent, int callingUid,
Hai Zhang639360a2019-05-20 15:35:33 -0700907 @Nullable String callingPackage) {
Hai Zhang560aa572019-07-11 17:30:45 -0700908 if (callingPackage != null && isActionRemovedForCallingPackage(intent, callingUid,
Hai Zhang639360a2019-05-20 15:35:33 -0700909 callingPackage)) {
Hai Zhangf4da9be2019-05-01 13:46:06 +0800910 Slog.w(LOG_TAG, "Action Removed: starting " + intent.toString() + " from "
911 + callingPackage + " (uid=" + callingUid + ")");
912 return false;
913 }
914 return true;
915 }
916
Svet Ganov3c499ea2019-07-26 17:45:56 -0700917 @Override
918 public boolean isInitialized(int userId) {
919 return isStarted(userId);
920 }
921
922 @Override
923 public void setOnInitializedCallback(@NonNull OnInitializedCallback callback) {
924 synchronized (mLock) {
925 mOnInitializedCallback = callback;
926 }
927 }
928
Hai Zhangf4da9be2019-05-01 13:46:06 +0800929 /**
930 * Check if the intent action is removed for the calling package (often based on target SDK
931 * version). If the action is removed, we'll silently cancel the activity launch.
932 */
Hai Zhang560aa572019-07-11 17:30:45 -0700933 private boolean isActionRemovedForCallingPackage(@NonNull Intent intent, int callingUid,
Hai Zhangf4da9be2019-05-01 13:46:06 +0800934 @NonNull String callingPackage) {
Hai Zhang560aa572019-07-11 17:30:45 -0700935 String action = intent.getAction();
Hai Zhangf4da9be2019-05-01 13:46:06 +0800936 if (action == null) {
937 return false;
938 }
939 switch (action) {
Hai Zhang114afc32019-05-01 14:16:23 +0800940 case TelecomManager.ACTION_CHANGE_DEFAULT_DIALER:
Hai Zhangf4da9be2019-05-01 13:46:06 +0800941 case Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT: {
942 ApplicationInfo applicationInfo;
943 try {
Hai Zhang560aa572019-07-11 17:30:45 -0700944 applicationInfo = getContext().getPackageManager().getApplicationInfoAsUser(
945 callingPackage, 0, UserHandle.getUserId(callingUid));
946 if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) {
947 // Applications targeting Q or higher should use
948 // RoleManager.createRequestRoleIntent() instead.
949 return true;
950 }
Hai Zhangf4da9be2019-05-01 13:46:06 +0800951 } catch (PackageManager.NameNotFoundException e) {
952 Slog.i(LOG_TAG, "Cannot find application info for " + callingPackage);
Hai Zhangf4da9be2019-05-01 13:46:06 +0800953 }
Hai Zhang560aa572019-07-11 17:30:45 -0700954 // Make sure RequestRoleActivity can know the calling package if we allow it.
955 intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage);
956 return false;
Hai Zhangf4da9be2019-05-01 13:46:06 +0800957 }
958 default:
959 return false;
960 }
961 }
962 }
Svet Ganovd8eb8b22019-04-05 18:52:08 -0700963}