1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import android.Manifest; 20 import android.app.ActivityManager; 21 import android.app.ActivityThread; 22 import android.app.AppGlobals; 23 import android.app.AppOpsManager; 24 import android.app.AppOpsManagerInternal; 25 import android.content.ContentResolver; 26 import android.content.Context; 27 import android.content.pm.ApplicationInfo; 28 import android.content.pm.IPackageManager; 29 import android.content.pm.PackageManager; 30 import android.content.pm.PackageManagerInternal; 31 import android.content.pm.UserInfo; 32 import android.database.ContentObserver; 33 import android.media.AudioAttributes; 34 import android.net.Uri; 35 import android.os.AsyncTask; 36 import android.os.Binder; 37 import android.os.Bundle; 38 import android.os.Handler; 39 import android.os.IBinder; 40 import android.os.Process; 41 import android.os.RemoteException; 42 import android.os.ResultReceiver; 43 import android.os.ServiceManager; 44 import android.os.ShellCallback; 45 import android.os.ShellCommand; 46 import android.os.SystemClock; 47 import android.os.UserHandle; 48 import android.os.UserManager; 49 import android.os.storage.StorageManagerInternal; 50 import android.provider.Settings; 51 import android.util.ArrayMap; 52 import android.util.ArraySet; 53 import android.util.AtomicFile; 54 import android.util.KeyValueListParser; 55 import android.util.Slog; 56 import android.util.SparseArray; 57 import android.util.SparseBooleanArray; 58 import android.util.SparseIntArray; 59 import android.util.TimeUtils; 60 import android.util.Xml; 61 62 import com.android.internal.annotations.VisibleForTesting; 63 import com.android.internal.app.IAppOpsActiveCallback; 64 import com.android.internal.app.IAppOpsCallback; 65 import com.android.internal.app.IAppOpsService; 66 import com.android.internal.os.Zygote; 67 import com.android.internal.util.ArrayUtils; 68 import com.android.internal.util.DumpUtils; 69 import com.android.internal.util.FastXmlSerializer; 70 import com.android.internal.util.Preconditions; 71 import com.android.internal.util.XmlUtils; 72 import com.android.internal.util.function.pooled.PooledLambda; 73 74 import libcore.util.EmptyArray; 75 76 import org.xmlpull.v1.XmlPullParser; 77 import org.xmlpull.v1.XmlPullParserException; 78 import org.xmlpull.v1.XmlSerializer; 79 80 import java.io.File; 81 import java.io.FileDescriptor; 82 import java.io.FileInputStream; 83 import java.io.FileNotFoundException; 84 import java.io.FileOutputStream; 85 import java.io.IOException; 86 import java.io.PrintWriter; 87 import java.nio.charset.StandardCharsets; 88 import java.text.SimpleDateFormat; 89 import java.util.ArrayList; 90 import java.util.Arrays; 91 import java.util.Collections; 92 import java.util.Date; 93 import java.util.HashMap; 94 import java.util.Iterator; 95 import java.util.List; 96 import java.util.Map; 97 98 import static android.app.AppOpsManager._NUM_UID_STATE; 99 import static android.app.AppOpsManager.UID_STATE_BACKGROUND; 100 import static android.app.AppOpsManager.UID_STATE_CACHED; 101 import static android.app.AppOpsManager.UID_STATE_FOREGROUND; 102 import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE; 103 import static android.app.AppOpsManager.UID_STATE_LAST_NON_RESTRICTED; 104 import static android.app.AppOpsManager.UID_STATE_PERSISTENT; 105 import static android.app.AppOpsManager.UID_STATE_TOP; 106 107 public class AppOpsService extends IAppOpsService.Stub { 108 static final String TAG = "AppOps"; 109 static final boolean DEBUG = false; 110 111 private static final int NO_VERSION = -1; 112 /** Increment by one every time and add the corresponding upgrade logic in 113 * {@link #upgradeLocked(int)} below. The first version was 1 */ 114 private static final int CURRENT_VERSION = 1; 115 116 // Write at most every 30 minutes. 117 static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000; 118 119 // Constant meaning that any UID should be matched when dispatching callbacks 120 private static final int UID_ANY = -2; 121 122 // Map from process states to the uid states we track. 123 private static final int[] PROCESS_STATE_TO_UID_STATE = new int[] { 124 UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT 125 UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI 126 UID_STATE_TOP, // ActivityManager.PROCESS_STATE_TOP 127 UID_STATE_FOREGROUND_SERVICE, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE 128 UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE 129 UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND 130 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND 131 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND 132 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_BACKUP 133 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_SERVICE 134 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_RECEIVER 135 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_TOP_SLEEPING 136 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT 137 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_HOME 138 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY 139 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY 140 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT 141 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_RECENT 142 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_EMPTY 143 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_NONEXISTENT 144 }; 145 146 static final String[] UID_STATE_NAMES = new String[] { 147 "pers ", // UID_STATE_PERSISTENT 148 "top ", // UID_STATE_TOP 149 "fgsvc", // UID_STATE_FOREGROUND_SERVICE 150 "fg ", // UID_STATE_FOREGROUND 151 "bg ", // UID_STATE_BACKGROUND 152 "cch ", // UID_STATE_CACHED 153 }; 154 155 static final String[] UID_STATE_TIME_ATTRS = new String[] { 156 "tp", // UID_STATE_PERSISTENT 157 "tt", // UID_STATE_TOP 158 "tfs", // UID_STATE_FOREGROUND_SERVICE 159 "tf", // UID_STATE_FOREGROUND 160 "tb", // UID_STATE_BACKGROUND 161 "tc", // UID_STATE_CACHED 162 }; 163 164 static final String[] UID_STATE_REJECT_ATTRS = new String[] { 165 "rp", // UID_STATE_PERSISTENT 166 "rt", // UID_STATE_TOP 167 "rfs", // UID_STATE_FOREGROUND_SERVICE 168 "rf", // UID_STATE_FOREGROUND 169 "rb", // UID_STATE_BACKGROUND 170 "rc", // UID_STATE_CACHED 171 }; 172 173 Context mContext; 174 final AtomicFile mFile; 175 final Handler mHandler; 176 177 private final AppOpsManagerInternalImpl mAppOpsManagerInternal 178 = new AppOpsManagerInternalImpl(); 179 180 boolean mWriteScheduled; 181 boolean mFastWriteScheduled; 182 final Runnable mWriteRunner = new Runnable() { 183 public void run() { 184 synchronized (AppOpsService.this) { 185 mWriteScheduled = false; 186 mFastWriteScheduled = false; 187 AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { 188 @Override protected Void doInBackground(Void... params) { 189 writeState(); 190 return null; 191 } 192 }; 193 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null); 194 } 195 } 196 }; 197 198 @VisibleForTesting 199 final SparseArray<UidState> mUidStates = new SparseArray<>(); 200 201 long mLastUptime; 202 203 /* 204 * These are app op restrictions imposed per user from various parties. 205 */ 206 private final ArrayMap<IBinder, ClientRestrictionState> mOpUserRestrictions = new ArrayMap<>(); 207 208 SparseIntArray mProfileOwners; 209 210 /** 211 * All times are in milliseconds. These constants are kept synchronized with the system 212 * global Settings. Any access to this class or its fields should be done while 213 * holding the AppOpsService lock. 214 */ 215 private final class Constants extends ContentObserver { 216 // Key names stored in the settings value. 217 private static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time"; 218 private static final String KEY_FG_SERVICE_STATE_SETTLE_TIME 219 = "fg_service_state_settle_time"; 220 private static final String KEY_BG_STATE_SETTLE_TIME = "bg_state_settle_time"; 221 222 /** 223 * How long we want for a drop in uid state from top to settle before applying it. 224 * @see Settings.Global#APP_OPS_CONSTANTS 225 * @see #KEY_TOP_STATE_SETTLE_TIME 226 */ 227 public long TOP_STATE_SETTLE_TIME; 228 229 /** 230 * How long we want for a drop in uid state from foreground to settle before applying it. 231 * @see Settings.Global#APP_OPS_CONSTANTS 232 * @see #KEY_FG_SERVICE_STATE_SETTLE_TIME 233 */ 234 public long FG_SERVICE_STATE_SETTLE_TIME; 235 236 /** 237 * How long we want for a drop in uid state from background to settle before applying it. 238 * @see Settings.Global#APP_OPS_CONSTANTS 239 * @see #KEY_BG_STATE_SETTLE_TIME 240 */ 241 public long BG_STATE_SETTLE_TIME; 242 243 private final KeyValueListParser mParser = new KeyValueListParser(','); 244 private ContentResolver mResolver; 245 Constants(Handler handler)246 public Constants(Handler handler) { 247 super(handler); 248 updateConstants(); 249 } 250 startMonitoring(ContentResolver resolver)251 public void startMonitoring(ContentResolver resolver) { 252 mResolver = resolver; 253 mResolver.registerContentObserver( 254 Settings.Global.getUriFor(Settings.Global.APP_OPS_CONSTANTS), 255 false, this); 256 updateConstants(); 257 } 258 259 @Override onChange(boolean selfChange, Uri uri)260 public void onChange(boolean selfChange, Uri uri) { 261 updateConstants(); 262 } 263 updateConstants()264 private void updateConstants() { 265 String value = mResolver != null ? Settings.Global.getString(mResolver, 266 Settings.Global.APP_OPS_CONSTANTS) : ""; 267 268 synchronized (AppOpsService.this) { 269 try { 270 mParser.setString(value); 271 } catch (IllegalArgumentException e) { 272 // Failed to parse the settings string, log this and move on 273 // with defaults. 274 Slog.e(TAG, "Bad app ops settings", e); 275 } 276 TOP_STATE_SETTLE_TIME = mParser.getDurationMillis( 277 KEY_TOP_STATE_SETTLE_TIME, 30 * 1000L); 278 FG_SERVICE_STATE_SETTLE_TIME = mParser.getDurationMillis( 279 KEY_FG_SERVICE_STATE_SETTLE_TIME, 10 * 1000L); 280 BG_STATE_SETTLE_TIME = mParser.getDurationMillis( 281 KEY_BG_STATE_SETTLE_TIME, 1 * 1000L); 282 } 283 } 284 dump(PrintWriter pw)285 void dump(PrintWriter pw) { 286 pw.println(" Settings:"); 287 288 pw.print(" "); pw.print(KEY_TOP_STATE_SETTLE_TIME); pw.print("="); 289 TimeUtils.formatDuration(TOP_STATE_SETTLE_TIME, pw); 290 pw.println(); 291 pw.print(" "); pw.print(KEY_FG_SERVICE_STATE_SETTLE_TIME); pw.print("="); 292 TimeUtils.formatDuration(FG_SERVICE_STATE_SETTLE_TIME, pw); 293 pw.println(); 294 pw.print(" "); pw.print(KEY_BG_STATE_SETTLE_TIME); pw.print("="); 295 TimeUtils.formatDuration(BG_STATE_SETTLE_TIME, pw); 296 pw.println(); 297 } 298 } 299 300 private final Constants mConstants; 301 302 @VisibleForTesting 303 static final class UidState { 304 public final int uid; 305 306 public int state = UID_STATE_CACHED; 307 public int pendingState = UID_STATE_CACHED; 308 public long pendingStateCommitTime; 309 310 public int startNesting; 311 public ArrayMap<String, Ops> pkgOps; 312 public SparseIntArray opModes; 313 314 // true indicates there is an interested observer, false there isn't but it has such an op 315 public SparseBooleanArray foregroundOps; 316 public boolean hasForegroundWatchers; 317 UidState(int uid)318 public UidState(int uid) { 319 this.uid = uid; 320 } 321 clear()322 public void clear() { 323 pkgOps = null; 324 opModes = null; 325 } 326 isDefault()327 public boolean isDefault() { 328 return (pkgOps == null || pkgOps.isEmpty()) 329 && (opModes == null || opModes.size() <= 0); 330 } 331 evalMode(int mode)332 int evalMode(int mode) { 333 if (mode == AppOpsManager.MODE_FOREGROUND) { 334 return state <= UID_STATE_LAST_NON_RESTRICTED 335 ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED; 336 } 337 return mode; 338 } 339 evalForegroundWatchers(int op, SparseArray<ArraySet<ModeCallback>> watchers, SparseBooleanArray which)340 private void evalForegroundWatchers(int op, SparseArray<ArraySet<ModeCallback>> watchers, 341 SparseBooleanArray which) { 342 boolean curValue = which.get(op, false); 343 ArraySet<ModeCallback> callbacks = watchers.get(op); 344 if (callbacks != null) { 345 for (int cbi = callbacks.size() - 1; !curValue && cbi >= 0; cbi--) { 346 if ((callbacks.valueAt(cbi).mFlags 347 & AppOpsManager.WATCH_FOREGROUND_CHANGES) != 0) { 348 hasForegroundWatchers = true; 349 curValue = true; 350 } 351 } 352 } 353 which.put(op, curValue); 354 } 355 evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers)356 public void evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers) { 357 SparseBooleanArray which = null; 358 hasForegroundWatchers = false; 359 if (opModes != null) { 360 for (int i = opModes.size() - 1; i >= 0; i--) { 361 if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) { 362 if (which == null) { 363 which = new SparseBooleanArray(); 364 } 365 evalForegroundWatchers(opModes.keyAt(i), watchers, which); 366 } 367 } 368 } 369 if (pkgOps != null) { 370 for (int i = pkgOps.size() - 1; i >= 0; i--) { 371 Ops ops = pkgOps.valueAt(i); 372 for (int j = ops.size() - 1; j >= 0; j--) { 373 if (ops.valueAt(j).mode == AppOpsManager.MODE_FOREGROUND) { 374 if (which == null) { 375 which = new SparseBooleanArray(); 376 } 377 evalForegroundWatchers(ops.keyAt(j), watchers, which); 378 } 379 } 380 } 381 } 382 foregroundOps = which; 383 } 384 } 385 386 final static class Ops extends SparseArray<Op> { 387 final String packageName; 388 final UidState uidState; 389 final boolean isPrivileged; 390 Ops(String _packageName, UidState _uidState, boolean _isPrivileged)391 Ops(String _packageName, UidState _uidState, boolean _isPrivileged) { 392 packageName = _packageName; 393 uidState = _uidState; 394 isPrivileged = _isPrivileged; 395 } 396 } 397 398 final static class Op { 399 final UidState uidState; 400 final int uid; 401 final String packageName; 402 final int op; 403 int proxyUid = -1; 404 String proxyPackageName; 405 int mode; 406 int duration; 407 long time[] = new long[_NUM_UID_STATE]; 408 long rejectTime[] = new long[_NUM_UID_STATE]; 409 int startNesting; 410 long startRealtime; 411 Op(UidState _uidState, String _packageName, int _op)412 Op(UidState _uidState, String _packageName, int _op) { 413 uidState = _uidState; 414 uid = _uidState.uid; 415 packageName = _packageName; 416 op = _op; 417 mode = AppOpsManager.opToDefaultMode(op); 418 } 419 hasAnyTime()420 boolean hasAnyTime() { 421 for (int i = 0; i < AppOpsManager._NUM_UID_STATE; i++) { 422 if (time[i] != 0) { 423 return true; 424 } 425 if (rejectTime[i] != 0) { 426 return true; 427 } 428 } 429 return false; 430 } 431 getMode()432 int getMode() { 433 return uidState.evalMode(mode); 434 } 435 } 436 437 final SparseArray<ArraySet<ModeCallback>> mOpModeWatchers = new SparseArray<>(); 438 final ArrayMap<String, ArraySet<ModeCallback>> mPackageModeWatchers = new ArrayMap<>(); 439 final ArrayMap<IBinder, ModeCallback> mModeWatchers = new ArrayMap<>(); 440 final ArrayMap<IBinder, SparseArray<ActiveCallback>> mActiveWatchers = new ArrayMap<>(); 441 final SparseArray<SparseArray<Restriction>> mAudioRestrictions = new SparseArray<>(); 442 443 final class ModeCallback implements DeathRecipient { 444 final IAppOpsCallback mCallback; 445 final int mWatchingUid; 446 final int mFlags; 447 final int mCallingUid; 448 final int mCallingPid; 449 ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int callingUid, int callingPid)450 ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int callingUid, 451 int callingPid) { 452 mCallback = callback; 453 mWatchingUid = watchingUid; 454 mFlags = flags; 455 mCallingUid = callingUid; 456 mCallingPid = callingPid; 457 try { 458 mCallback.asBinder().linkToDeath(this, 0); 459 } catch (RemoteException e) { 460 } 461 } 462 isWatchingUid(int uid)463 public boolean isWatchingUid(int uid) { 464 return uid == UID_ANY || mWatchingUid < 0 || mWatchingUid == uid; 465 } 466 467 @Override toString()468 public String toString() { 469 StringBuilder sb = new StringBuilder(128); 470 sb.append("ModeCallback{"); 471 sb.append(Integer.toHexString(System.identityHashCode(this))); 472 sb.append(" watchinguid="); 473 UserHandle.formatUid(sb, mWatchingUid); 474 sb.append(" flags=0x"); 475 sb.append(Integer.toHexString(mFlags)); 476 sb.append(" from uid="); 477 UserHandle.formatUid(sb, mCallingUid); 478 sb.append(" pid="); 479 sb.append(mCallingPid); 480 sb.append('}'); 481 return sb.toString(); 482 } 483 unlinkToDeath()484 void unlinkToDeath() { 485 mCallback.asBinder().unlinkToDeath(this, 0); 486 } 487 488 @Override binderDied()489 public void binderDied() { 490 stopWatchingMode(mCallback); 491 } 492 } 493 494 final class ActiveCallback implements DeathRecipient { 495 final IAppOpsActiveCallback mCallback; 496 final int mWatchingUid; 497 final int mCallingUid; 498 final int mCallingPid; 499 ActiveCallback(IAppOpsActiveCallback callback, int watchingUid, int callingUid, int callingPid)500 ActiveCallback(IAppOpsActiveCallback callback, int watchingUid, int callingUid, 501 int callingPid) { 502 mCallback = callback; 503 mWatchingUid = watchingUid; 504 mCallingUid = callingUid; 505 mCallingPid = callingPid; 506 try { 507 mCallback.asBinder().linkToDeath(this, 0); 508 } catch (RemoteException e) { 509 } 510 } 511 512 @Override toString()513 public String toString() { 514 StringBuilder sb = new StringBuilder(128); 515 sb.append("ActiveCallback{"); 516 sb.append(Integer.toHexString(System.identityHashCode(this))); 517 sb.append(" watchinguid="); 518 UserHandle.formatUid(sb, mWatchingUid); 519 sb.append(" from uid="); 520 UserHandle.formatUid(sb, mCallingUid); 521 sb.append(" pid="); 522 sb.append(mCallingPid); 523 sb.append('}'); 524 return sb.toString(); 525 } 526 destroy()527 void destroy() { 528 mCallback.asBinder().unlinkToDeath(this, 0); 529 } 530 531 @Override binderDied()532 public void binderDied() { 533 stopWatchingActive(mCallback); 534 } 535 } 536 537 final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>(); 538 539 final class ClientState extends Binder implements DeathRecipient { 540 final ArrayList<Op> mStartedOps = new ArrayList<>(); 541 final IBinder mAppToken; 542 final int mPid; 543 ClientState(IBinder appToken)544 ClientState(IBinder appToken) { 545 mAppToken = appToken; 546 mPid = Binder.getCallingPid(); 547 // Watch only for remote processes dying 548 if (!(appToken instanceof Binder)) { 549 try { 550 mAppToken.linkToDeath(this, 0); 551 } catch (RemoteException e) { 552 /* do nothing */ 553 } 554 } 555 } 556 557 @Override toString()558 public String toString() { 559 return "ClientState{" + 560 "mAppToken=" + mAppToken + 561 ", " + "pid=" + mPid + 562 '}'; 563 } 564 565 @Override binderDied()566 public void binderDied() { 567 synchronized (AppOpsService.this) { 568 for (int i=mStartedOps.size()-1; i>=0; i--) { 569 finishOperationLocked(mStartedOps.get(i), /*finishNested*/ true); 570 } 571 mClients.remove(mAppToken); 572 } 573 } 574 } 575 AppOpsService(File storagePath, Handler handler)576 public AppOpsService(File storagePath, Handler handler) { 577 LockGuard.installLock(this, LockGuard.INDEX_APP_OPS); 578 mFile = new AtomicFile(storagePath, "appops"); 579 mHandler = handler; 580 mConstants = new Constants(mHandler); 581 readState(); 582 } 583 publish(Context context)584 public void publish(Context context) { 585 mContext = context; 586 ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder()); 587 LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal); 588 } 589 systemReady()590 public void systemReady() { 591 mConstants.startMonitoring(mContext.getContentResolver()); 592 593 synchronized (this) { 594 boolean changed = false; 595 for (int i = mUidStates.size() - 1; i >= 0; i--) { 596 UidState uidState = mUidStates.valueAt(i); 597 598 String[] packageNames = getPackagesForUid(uidState.uid); 599 if (ArrayUtils.isEmpty(packageNames)) { 600 uidState.clear(); 601 mUidStates.removeAt(i); 602 changed = true; 603 continue; 604 } 605 606 ArrayMap<String, Ops> pkgs = uidState.pkgOps; 607 if (pkgs == null) { 608 continue; 609 } 610 611 Iterator<Ops> it = pkgs.values().iterator(); 612 while (it.hasNext()) { 613 Ops ops = it.next(); 614 int curUid = -1; 615 try { 616 curUid = AppGlobals.getPackageManager().getPackageUid(ops.packageName, 617 PackageManager.MATCH_UNINSTALLED_PACKAGES, 618 UserHandle.getUserId(ops.uidState.uid)); 619 } catch (RemoteException ignored) { 620 } 621 if (curUid != ops.uidState.uid) { 622 Slog.i(TAG, "Pruning old package " + ops.packageName 623 + "/" + ops.uidState + ": new uid=" + curUid); 624 it.remove(); 625 changed = true; 626 } 627 } 628 629 if (uidState.isDefault()) { 630 mUidStates.removeAt(i); 631 } 632 } 633 if (changed) { 634 scheduleFastWriteLocked(); 635 } 636 } 637 638 PackageManagerInternal packageManagerInternal = LocalServices.getService( 639 PackageManagerInternal.class); 640 packageManagerInternal.setExternalSourcesPolicy( 641 new PackageManagerInternal.ExternalSourcesPolicy() { 642 @Override 643 public int getPackageTrustedToInstallApps(String packageName, int uid) { 644 int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, 645 uid, packageName); 646 switch (appOpMode) { 647 case AppOpsManager.MODE_ALLOWED: 648 return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED; 649 case AppOpsManager.MODE_ERRORED: 650 return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED; 651 default: 652 return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT; 653 } 654 } 655 }); 656 657 StorageManagerInternal storageManagerInternal = LocalServices.getService( 658 StorageManagerInternal.class); 659 storageManagerInternal.addExternalStoragePolicy( 660 new StorageManagerInternal.ExternalStorageMountPolicy() { 661 @Override 662 public int getMountMode(int uid, String packageName) { 663 if (Process.isIsolated(uid)) { 664 return Zygote.MOUNT_EXTERNAL_NONE; 665 } 666 if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid, 667 packageName) != AppOpsManager.MODE_ALLOWED) { 668 return Zygote.MOUNT_EXTERNAL_NONE; 669 } 670 if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid, 671 packageName) != AppOpsManager.MODE_ALLOWED) { 672 return Zygote.MOUNT_EXTERNAL_READ; 673 } 674 return Zygote.MOUNT_EXTERNAL_WRITE; 675 } 676 677 @Override 678 public boolean hasExternalStorage(int uid, String packageName) { 679 final int mountMode = getMountMode(uid, packageName); 680 return mountMode == Zygote.MOUNT_EXTERNAL_READ 681 || mountMode == Zygote.MOUNT_EXTERNAL_WRITE; 682 } 683 }); 684 } 685 packageRemoved(int uid, String packageName)686 public void packageRemoved(int uid, String packageName) { 687 synchronized (this) { 688 UidState uidState = mUidStates.get(uid); 689 if (uidState == null) { 690 return; 691 } 692 693 Ops ops = null; 694 695 // Remove any package state if such. 696 if (uidState.pkgOps != null) { 697 ops = uidState.pkgOps.remove(packageName); 698 } 699 700 // If we just nuked the last package state check if the UID is valid. 701 if (ops != null && uidState.pkgOps.isEmpty() 702 && getPackagesForUid(uid).length <= 0) { 703 mUidStates.remove(uid); 704 } 705 706 // Finish ops other packages started on behalf of the package. 707 final int clientCount = mClients.size(); 708 for (int i = 0; i < clientCount; i++) { 709 final ClientState client = mClients.valueAt(i); 710 if (client.mStartedOps == null) { 711 continue; 712 } 713 final int opCount = client.mStartedOps.size(); 714 for (int j = opCount - 1; j >= 0; j--) { 715 final Op op = client.mStartedOps.get(j); 716 if (uid == op.uid && packageName.equals(op.packageName)) { 717 finishOperationLocked(op, /*finishNested*/ true); 718 client.mStartedOps.remove(j); 719 if (op.startNesting <= 0) { 720 scheduleOpActiveChangedIfNeededLocked(op.op, 721 uid, packageName, false); 722 } 723 } 724 } 725 } 726 727 if (ops != null) { 728 scheduleFastWriteLocked(); 729 730 final int opCount = ops.size(); 731 for (int i = 0; i < opCount; i++) { 732 final Op op = ops.valueAt(i); 733 if (op.duration == -1) { 734 scheduleOpActiveChangedIfNeededLocked( 735 op.op, op.uid, op.packageName, false); 736 } 737 } 738 } 739 } 740 } 741 uidRemoved(int uid)742 public void uidRemoved(int uid) { 743 synchronized (this) { 744 if (mUidStates.indexOfKey(uid) >= 0) { 745 mUidStates.remove(uid); 746 scheduleFastWriteLocked(); 747 } 748 } 749 } 750 updateUidProcState(int uid, int procState)751 public void updateUidProcState(int uid, int procState) { 752 synchronized (this) { 753 final UidState uidState = getUidStateLocked(uid, true); 754 final int newState = PROCESS_STATE_TO_UID_STATE[procState]; 755 if (uidState != null && uidState.pendingState != newState) { 756 final int oldPendingState = uidState.pendingState; 757 uidState.pendingState = newState; 758 if (newState < uidState.state || newState <= UID_STATE_LAST_NON_RESTRICTED) { 759 // We are moving to a more important state, or the new state is in the 760 // foreground, then always do it immediately. 761 commitUidPendingStateLocked(uidState); 762 } else if (uidState.pendingStateCommitTime == 0) { 763 // We are moving to a less important state for the first time, 764 // delay the application for a bit. 765 final long settleTime; 766 if (uidState.state <= UID_STATE_TOP) { 767 settleTime = mConstants.TOP_STATE_SETTLE_TIME; 768 } else if (uidState.state <= UID_STATE_FOREGROUND_SERVICE) { 769 settleTime = mConstants.FG_SERVICE_STATE_SETTLE_TIME; 770 } else { 771 settleTime = mConstants.BG_STATE_SETTLE_TIME; 772 } 773 uidState.pendingStateCommitTime = SystemClock.uptimeMillis() + settleTime; 774 } 775 if (uidState.startNesting != 0) { 776 // There is some actively running operation... need to find it 777 // and appropriately update its state. 778 final long now = System.currentTimeMillis(); 779 for (int i = uidState.pkgOps.size() - 1; i >= 0; i--) { 780 final Ops ops = uidState.pkgOps.valueAt(i); 781 for (int j = ops.size() - 1; j >= 0; j--) { 782 final Op op = ops.valueAt(j); 783 if (op.startNesting > 0) { 784 op.time[oldPendingState] = now; 785 op.time[newState] = now; 786 } 787 } 788 } 789 } 790 } 791 } 792 } 793 shutdown()794 public void shutdown() { 795 Slog.w(TAG, "Writing app ops before shutdown..."); 796 boolean doWrite = false; 797 synchronized (this) { 798 if (mWriteScheduled) { 799 mWriteScheduled = false; 800 doWrite = true; 801 } 802 } 803 if (doWrite) { 804 writeState(); 805 } 806 } 807 collectOps(Ops pkgOps, int[] ops)808 private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) { 809 ArrayList<AppOpsManager.OpEntry> resOps = null; 810 final long elapsedNow = SystemClock.elapsedRealtime(); 811 if (ops == null) { 812 resOps = new ArrayList<>(); 813 for (int j=0; j<pkgOps.size(); j++) { 814 Op curOp = pkgOps.valueAt(j); 815 final boolean running = curOp.duration == -1; 816 long duration = running 817 ? (elapsedNow - curOp.startRealtime) 818 : curOp.duration; 819 resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time, 820 curOp.rejectTime, (int) duration, running, curOp.proxyUid, 821 curOp.proxyPackageName)); 822 } 823 } else { 824 for (int j=0; j<ops.length; j++) { 825 Op curOp = pkgOps.get(ops[j]); 826 if (curOp != null) { 827 if (resOps == null) { 828 resOps = new ArrayList<>(); 829 } 830 final boolean running = curOp.duration == -1; 831 final long duration = running 832 ? (elapsedNow - curOp.startRealtime) 833 : curOp.duration; 834 resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time, 835 curOp.rejectTime, (int) duration, running, curOp.proxyUid, 836 curOp.proxyPackageName)); 837 } 838 } 839 } 840 return resOps; 841 } 842 collectOps(SparseIntArray uidOps, int[] ops)843 private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) { 844 ArrayList<AppOpsManager.OpEntry> resOps = null; 845 if (ops == null) { 846 resOps = new ArrayList<>(); 847 for (int j=0; j<uidOps.size(); j++) { 848 resOps.add(new AppOpsManager.OpEntry(uidOps.keyAt(j), uidOps.valueAt(j), 849 0, 0, 0, -1, null)); 850 } 851 } else { 852 for (int j=0; j<ops.length; j++) { 853 int index = uidOps.indexOfKey(ops[j]); 854 if (index >= 0) { 855 if (resOps == null) { 856 resOps = new ArrayList<>(); 857 } 858 resOps.add(new AppOpsManager.OpEntry(uidOps.keyAt(index), uidOps.valueAt(index), 859 0, 0, 0, -1, null)); 860 } 861 } 862 } 863 return resOps; 864 } 865 866 @Override getPackagesForOps(int[] ops)867 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { 868 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 869 Binder.getCallingPid(), Binder.getCallingUid(), null); 870 ArrayList<AppOpsManager.PackageOps> res = null; 871 synchronized (this) { 872 final int uidStateCount = mUidStates.size(); 873 for (int i = 0; i < uidStateCount; i++) { 874 UidState uidState = mUidStates.valueAt(i); 875 if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()) { 876 continue; 877 } 878 ArrayMap<String, Ops> packages = uidState.pkgOps; 879 final int packageCount = packages.size(); 880 for (int j = 0; j < packageCount; j++) { 881 Ops pkgOps = packages.valueAt(j); 882 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 883 if (resOps != null) { 884 if (res == null) { 885 res = new ArrayList<AppOpsManager.PackageOps>(); 886 } 887 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 888 pkgOps.packageName, pkgOps.uidState.uid, resOps); 889 res.add(resPackage); 890 } 891 } 892 } 893 } 894 return res; 895 } 896 897 @Override getOpsForPackage(int uid, String packageName, int[] ops)898 public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, 899 int[] ops) { 900 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 901 Binder.getCallingPid(), Binder.getCallingUid(), null); 902 String resolvedPackageName = resolvePackageName(uid, packageName); 903 if (resolvedPackageName == null) { 904 return Collections.emptyList(); 905 } 906 synchronized (this) { 907 Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false /* edit */, 908 false /* uidMismatchExpected */); 909 if (pkgOps == null) { 910 return null; 911 } 912 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 913 if (resOps == null) { 914 return null; 915 } 916 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); 917 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 918 pkgOps.packageName, pkgOps.uidState.uid, resOps); 919 res.add(resPackage); 920 return res; 921 } 922 } 923 924 @Override getUidOps(int uid, int[] ops)925 public List<AppOpsManager.PackageOps> getUidOps(int uid, int[] ops) { 926 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 927 Binder.getCallingPid(), Binder.getCallingUid(), null); 928 synchronized (this) { 929 UidState uidState = getUidStateLocked(uid, false); 930 if (uidState == null) { 931 return null; 932 } 933 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops); 934 if (resOps == null) { 935 return null; 936 } 937 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); 938 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 939 null, uidState.uid, resOps); 940 res.add(resPackage); 941 return res; 942 } 943 } 944 pruneOp(Op op, int uid, String packageName)945 private void pruneOp(Op op, int uid, String packageName) { 946 if (!op.hasAnyTime()) { 947 Ops ops = getOpsRawLocked(uid, packageName, false /* edit */, 948 false /* uidMismatchExpected */); 949 if (ops != null) { 950 ops.remove(op.op); 951 if (ops.size() <= 0) { 952 UidState uidState = ops.uidState; 953 ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 954 if (pkgOps != null) { 955 pkgOps.remove(ops.packageName); 956 if (pkgOps.isEmpty()) { 957 uidState.pkgOps = null; 958 } 959 if (uidState.isDefault()) { 960 mUidStates.remove(uid); 961 } 962 } 963 } 964 } 965 } 966 } 967 enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid)968 void enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid) { 969 if (callingPid == Process.myPid()) { 970 return; 971 } 972 final int callingUser = UserHandle.getUserId(callingUid); 973 synchronized (this) { 974 if (mProfileOwners != null && mProfileOwners.get(callingUser, -1) == callingUid) { 975 if (targetUid >= 0 && callingUser == UserHandle.getUserId(targetUid)) { 976 // Profile owners are allowed to change modes but only for apps 977 // within their user. 978 return; 979 } 980 } 981 } 982 mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES, 983 Binder.getCallingPid(), Binder.getCallingUid(), null); 984 } 985 986 @Override setUidMode(int code, int uid, int mode)987 public void setUidMode(int code, int uid, int mode) { 988 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); 989 verifyIncomingOp(code); 990 code = AppOpsManager.opToSwitch(code); 991 992 synchronized (this) { 993 final int defaultMode = AppOpsManager.opToDefaultMode(code); 994 995 UidState uidState = getUidStateLocked(uid, false); 996 if (uidState == null) { 997 if (mode == defaultMode) { 998 return; 999 } 1000 uidState = new UidState(uid); 1001 uidState.opModes = new SparseIntArray(); 1002 uidState.opModes.put(code, mode); 1003 mUidStates.put(uid, uidState); 1004 scheduleWriteLocked(); 1005 } else if (uidState.opModes == null) { 1006 if (mode != defaultMode) { 1007 uidState.opModes = new SparseIntArray(); 1008 uidState.opModes.put(code, mode); 1009 scheduleWriteLocked(); 1010 } 1011 } else { 1012 if (uidState.opModes.get(code) == mode) { 1013 return; 1014 } 1015 if (mode == defaultMode) { 1016 uidState.opModes.delete(code); 1017 if (uidState.opModes.size() <= 0) { 1018 uidState.opModes = null; 1019 } 1020 } else { 1021 uidState.opModes.put(code, mode); 1022 } 1023 scheduleWriteLocked(); 1024 } 1025 } 1026 1027 String[] uidPackageNames = getPackagesForUid(uid); 1028 ArrayMap<ModeCallback, ArraySet<String>> callbackSpecs = null; 1029 1030 synchronized (this) { 1031 ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code); 1032 if (callbacks != null) { 1033 final int callbackCount = callbacks.size(); 1034 for (int i = 0; i < callbackCount; i++) { 1035 ModeCallback callback = callbacks.valueAt(i); 1036 ArraySet<String> changedPackages = new ArraySet<>(); 1037 Collections.addAll(changedPackages, uidPackageNames); 1038 if (callbackSpecs == null) { 1039 callbackSpecs = new ArrayMap<>(); 1040 } 1041 callbackSpecs.put(callback, changedPackages); 1042 } 1043 } 1044 1045 for (String uidPackageName : uidPackageNames) { 1046 callbacks = mPackageModeWatchers.get(uidPackageName); 1047 if (callbacks != null) { 1048 if (callbackSpecs == null) { 1049 callbackSpecs = new ArrayMap<>(); 1050 } 1051 final int callbackCount = callbacks.size(); 1052 for (int i = 0; i < callbackCount; i++) { 1053 ModeCallback callback = callbacks.valueAt(i); 1054 ArraySet<String> changedPackages = callbackSpecs.get(callback); 1055 if (changedPackages == null) { 1056 changedPackages = new ArraySet<>(); 1057 callbackSpecs.put(callback, changedPackages); 1058 } 1059 changedPackages.add(uidPackageName); 1060 } 1061 } 1062 } 1063 } 1064 1065 if (callbackSpecs == null) { 1066 return; 1067 } 1068 1069 for (int i = 0; i < callbackSpecs.size(); i++) { 1070 final ModeCallback callback = callbackSpecs.keyAt(i); 1071 final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i); 1072 if (reportedPackageNames == null) { 1073 mHandler.sendMessage(PooledLambda.obtainMessage( 1074 AppOpsService::notifyOpChanged, 1075 this, callback, code, uid, (String) null)); 1076 1077 } else { 1078 final int reportedPackageCount = reportedPackageNames.size(); 1079 for (int j = 0; j < reportedPackageCount; j++) { 1080 final String reportedPackageName = reportedPackageNames.valueAt(j); 1081 mHandler.sendMessage(PooledLambda.obtainMessage( 1082 AppOpsService::notifyOpChanged, 1083 this, callback, code, uid, reportedPackageName)); 1084 } 1085 } 1086 } 1087 } 1088 1089 @Override setMode(int code, int uid, String packageName, int mode)1090 public void setMode(int code, int uid, String packageName, int mode) { 1091 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); 1092 verifyIncomingOp(code); 1093 ArraySet<ModeCallback> repCbs = null; 1094 code = AppOpsManager.opToSwitch(code); 1095 synchronized (this) { 1096 UidState uidState = getUidStateLocked(uid, false); 1097 Op op = getOpLocked(code, uid, packageName, true); 1098 if (op != null) { 1099 if (op.mode != mode) { 1100 op.mode = mode; 1101 if (uidState != null) { 1102 uidState.evalForegroundOps(mOpModeWatchers); 1103 } 1104 ArraySet<ModeCallback> cbs = mOpModeWatchers.get(code); 1105 if (cbs != null) { 1106 if (repCbs == null) { 1107 repCbs = new ArraySet<>(); 1108 } 1109 repCbs.addAll(cbs); 1110 } 1111 cbs = mPackageModeWatchers.get(packageName); 1112 if (cbs != null) { 1113 if (repCbs == null) { 1114 repCbs = new ArraySet<>(); 1115 } 1116 repCbs.addAll(cbs); 1117 } 1118 if (mode == AppOpsManager.opToDefaultMode(op.op)) { 1119 // If going into the default mode, prune this op 1120 // if there is nothing else interesting in it. 1121 pruneOp(op, uid, packageName); 1122 } 1123 scheduleFastWriteLocked(); 1124 } 1125 } 1126 } 1127 if (repCbs != null) { 1128 mHandler.sendMessage(PooledLambda.obtainMessage( 1129 AppOpsService::notifyOpChanged, 1130 this, repCbs, code, uid, packageName)); 1131 } 1132 } 1133 notifyOpChanged(ArraySet<ModeCallback> callbacks, int code, int uid, String packageName)1134 private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code, 1135 int uid, String packageName) { 1136 for (int i = 0; i < callbacks.size(); i++) { 1137 final ModeCallback callback = callbacks.valueAt(i); 1138 notifyOpChanged(callback, code, uid, packageName); 1139 } 1140 } 1141 notifyOpChanged(ModeCallback callback, int code, int uid, String packageName)1142 private void notifyOpChanged(ModeCallback callback, int code, 1143 int uid, String packageName) { 1144 if (uid != UID_ANY && callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 1145 return; 1146 } 1147 // There are components watching for mode changes such as window manager 1148 // and location manager which are in our process. The callbacks in these 1149 // components may require permissions our remote caller does not have. 1150 final long identity = Binder.clearCallingIdentity(); 1151 try { 1152 callback.mCallback.opChanged(code, uid, packageName); 1153 } catch (RemoteException e) { 1154 /* ignore */ 1155 } finally { 1156 Binder.restoreCallingIdentity(identity); 1157 } 1158 } 1159 addCallbacks( HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks, int op, int uid, String packageName, ArraySet<ModeCallback> cbs)1160 private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks( 1161 HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks, 1162 int op, int uid, String packageName, ArraySet<ModeCallback> cbs) { 1163 if (cbs == null) { 1164 return callbacks; 1165 } 1166 if (callbacks == null) { 1167 callbacks = new HashMap<>(); 1168 } 1169 boolean duplicate = false; 1170 final int N = cbs.size(); 1171 for (int i=0; i<N; i++) { 1172 ModeCallback cb = cbs.valueAt(i); 1173 ArrayList<ChangeRec> reports = callbacks.get(cb); 1174 if (reports == null) { 1175 reports = new ArrayList<>(); 1176 callbacks.put(cb, reports); 1177 } else { 1178 final int reportCount = reports.size(); 1179 for (int j = 0; j < reportCount; j++) { 1180 ChangeRec report = reports.get(j); 1181 if (report.op == op && report.pkg.equals(packageName)) { 1182 duplicate = true; 1183 break; 1184 } 1185 } 1186 } 1187 if (!duplicate) { 1188 reports.add(new ChangeRec(op, uid, packageName)); 1189 } 1190 } 1191 return callbacks; 1192 } 1193 1194 static final class ChangeRec { 1195 final int op; 1196 final int uid; 1197 final String pkg; 1198 ChangeRec(int _op, int _uid, String _pkg)1199 ChangeRec(int _op, int _uid, String _pkg) { 1200 op = _op; 1201 uid = _uid; 1202 pkg = _pkg; 1203 } 1204 } 1205 1206 @Override resetAllModes(int reqUserId, String reqPackageName)1207 public void resetAllModes(int reqUserId, String reqPackageName) { 1208 final int callingPid = Binder.getCallingPid(); 1209 final int callingUid = Binder.getCallingUid(); 1210 reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId, 1211 true, true, "resetAllModes", null); 1212 1213 int reqUid = -1; 1214 if (reqPackageName != null) { 1215 try { 1216 reqUid = AppGlobals.getPackageManager().getPackageUid( 1217 reqPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, reqUserId); 1218 } catch (RemoteException e) { 1219 /* ignore - local call */ 1220 } 1221 } 1222 1223 enforceManageAppOpsModes(callingPid, callingUid, reqUid); 1224 1225 HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks = null; 1226 synchronized (this) { 1227 boolean changed = false; 1228 for (int i = mUidStates.size() - 1; i >= 0; i--) { 1229 UidState uidState = mUidStates.valueAt(i); 1230 1231 SparseIntArray opModes = uidState.opModes; 1232 if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) { 1233 final int uidOpCount = opModes.size(); 1234 for (int j = uidOpCount - 1; j >= 0; j--) { 1235 final int code = opModes.keyAt(j); 1236 if (AppOpsManager.opAllowsReset(code)) { 1237 opModes.removeAt(j); 1238 if (opModes.size() <= 0) { 1239 uidState.opModes = null; 1240 } 1241 for (String packageName : getPackagesForUid(uidState.uid)) { 1242 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, 1243 mOpModeWatchers.get(code)); 1244 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, 1245 mPackageModeWatchers.get(packageName)); 1246 } 1247 } 1248 } 1249 } 1250 1251 if (uidState.pkgOps == null) { 1252 continue; 1253 } 1254 1255 if (reqUserId != UserHandle.USER_ALL 1256 && reqUserId != UserHandle.getUserId(uidState.uid)) { 1257 // Skip any ops for a different user 1258 continue; 1259 } 1260 1261 Map<String, Ops> packages = uidState.pkgOps; 1262 Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator(); 1263 boolean uidChanged = false; 1264 while (it.hasNext()) { 1265 Map.Entry<String, Ops> ent = it.next(); 1266 String packageName = ent.getKey(); 1267 if (reqPackageName != null && !reqPackageName.equals(packageName)) { 1268 // Skip any ops for a different package 1269 continue; 1270 } 1271 Ops pkgOps = ent.getValue(); 1272 for (int j=pkgOps.size()-1; j>=0; j--) { 1273 Op curOp = pkgOps.valueAt(j); 1274 if (AppOpsManager.opAllowsReset(curOp.op) 1275 && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) { 1276 curOp.mode = AppOpsManager.opToDefaultMode(curOp.op); 1277 changed = true; 1278 uidChanged = true; 1279 callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName, 1280 mOpModeWatchers.get(curOp.op)); 1281 callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName, 1282 mPackageModeWatchers.get(packageName)); 1283 if (!curOp.hasAnyTime()) { 1284 pkgOps.removeAt(j); 1285 } 1286 } 1287 } 1288 if (pkgOps.size() == 0) { 1289 it.remove(); 1290 } 1291 } 1292 if (uidState.isDefault()) { 1293 mUidStates.remove(uidState.uid); 1294 } 1295 if (uidChanged) { 1296 uidState.evalForegroundOps(mOpModeWatchers); 1297 } 1298 } 1299 1300 if (changed) { 1301 scheduleFastWriteLocked(); 1302 } 1303 } 1304 if (callbacks != null) { 1305 for (Map.Entry<ModeCallback, ArrayList<ChangeRec>> ent : callbacks.entrySet()) { 1306 ModeCallback cb = ent.getKey(); 1307 ArrayList<ChangeRec> reports = ent.getValue(); 1308 for (int i=0; i<reports.size(); i++) { 1309 ChangeRec rep = reports.get(i); 1310 mHandler.sendMessage(PooledLambda.obtainMessage( 1311 AppOpsService::notifyOpChanged, 1312 this, cb, rep.op, rep.uid, rep.pkg)); 1313 } 1314 } 1315 } 1316 } 1317 evalAllForegroundOpsLocked()1318 private void evalAllForegroundOpsLocked() { 1319 for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) { 1320 final UidState uidState = mUidStates.valueAt(uidi); 1321 if (uidState.foregroundOps != null) { 1322 uidState.evalForegroundOps(mOpModeWatchers); 1323 } 1324 } 1325 } 1326 1327 @Override startWatchingMode(int op, String packageName, IAppOpsCallback callback)1328 public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) { 1329 startWatchingModeWithFlags(op, packageName, 0, callback); 1330 } 1331 1332 @Override startWatchingModeWithFlags(int op, String packageName, int flags, IAppOpsCallback callback)1333 public void startWatchingModeWithFlags(int op, String packageName, int flags, 1334 IAppOpsCallback callback) { 1335 int watchedUid = -1; 1336 final int callingUid = Binder.getCallingUid(); 1337 final int callingPid = Binder.getCallingPid(); 1338 // TODO: should have a privileged permission to protect this. 1339 // Also, if the caller has requested WATCH_FOREGROUND_CHANGES, should we require 1340 // the USAGE_STATS permission since this can provide information about when an 1341 // app is in the foreground? 1342 Preconditions.checkArgumentInRange(op, AppOpsManager.OP_NONE, 1343 AppOpsManager._NUM_OP - 1, "Invalid op code: " + op); 1344 if (callback == null) { 1345 return; 1346 } 1347 synchronized (this) { 1348 op = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op; 1349 ModeCallback cb = mModeWatchers.get(callback.asBinder()); 1350 if (cb == null) { 1351 cb = new ModeCallback(callback, watchedUid, flags, callingUid, callingPid); 1352 mModeWatchers.put(callback.asBinder(), cb); 1353 } 1354 if (op != AppOpsManager.OP_NONE) { 1355 ArraySet<ModeCallback> cbs = mOpModeWatchers.get(op); 1356 if (cbs == null) { 1357 cbs = new ArraySet<>(); 1358 mOpModeWatchers.put(op, cbs); 1359 } 1360 cbs.add(cb); 1361 } 1362 if (packageName != null) { 1363 ArraySet<ModeCallback> cbs = mPackageModeWatchers.get(packageName); 1364 if (cbs == null) { 1365 cbs = new ArraySet<>(); 1366 mPackageModeWatchers.put(packageName, cbs); 1367 } 1368 cbs.add(cb); 1369 } 1370 evalAllForegroundOpsLocked(); 1371 } 1372 } 1373 1374 @Override stopWatchingMode(IAppOpsCallback callback)1375 public void stopWatchingMode(IAppOpsCallback callback) { 1376 if (callback == null) { 1377 return; 1378 } 1379 synchronized (this) { 1380 ModeCallback cb = mModeWatchers.remove(callback.asBinder()); 1381 if (cb != null) { 1382 cb.unlinkToDeath(); 1383 for (int i=mOpModeWatchers.size()-1; i>=0; i--) { 1384 ArraySet<ModeCallback> cbs = mOpModeWatchers.valueAt(i); 1385 cbs.remove(cb); 1386 if (cbs.size() <= 0) { 1387 mOpModeWatchers.removeAt(i); 1388 } 1389 } 1390 for (int i=mPackageModeWatchers.size()-1; i>=0; i--) { 1391 ArraySet<ModeCallback> cbs = mPackageModeWatchers.valueAt(i); 1392 cbs.remove(cb); 1393 if (cbs.size() <= 0) { 1394 mPackageModeWatchers.removeAt(i); 1395 } 1396 } 1397 } 1398 evalAllForegroundOpsLocked(); 1399 } 1400 } 1401 1402 @Override getToken(IBinder clientToken)1403 public IBinder getToken(IBinder clientToken) { 1404 synchronized (this) { 1405 ClientState cs = mClients.get(clientToken); 1406 if (cs == null) { 1407 cs = new ClientState(clientToken); 1408 mClients.put(clientToken, cs); 1409 } 1410 return cs; 1411 } 1412 } 1413 1414 @Override checkOperation(int code, int uid, String packageName)1415 public int checkOperation(int code, int uid, String packageName) { 1416 verifyIncomingUid(uid); 1417 verifyIncomingOp(code); 1418 String resolvedPackageName = resolvePackageName(uid, packageName); 1419 if (resolvedPackageName == null) { 1420 return AppOpsManager.MODE_IGNORED; 1421 } 1422 synchronized (this) { 1423 if (isOpRestrictedLocked(uid, code, resolvedPackageName)) { 1424 return AppOpsManager.MODE_IGNORED; 1425 } 1426 code = AppOpsManager.opToSwitch(code); 1427 UidState uidState = getUidStateLocked(uid, false); 1428 if (uidState != null && uidState.opModes != null 1429 && uidState.opModes.indexOfKey(code) >= 0) { 1430 return uidState.opModes.get(code); 1431 } 1432 Op op = getOpLocked(code, uid, resolvedPackageName, false); 1433 if (op == null) { 1434 return AppOpsManager.opToDefaultMode(code); 1435 } 1436 return op.mode; 1437 } 1438 } 1439 1440 @Override checkAudioOperation(int code, int usage, int uid, String packageName)1441 public int checkAudioOperation(int code, int usage, int uid, String packageName) { 1442 boolean suspended; 1443 try { 1444 suspended = isPackageSuspendedForUser(packageName, uid); 1445 } catch (IllegalArgumentException ex) { 1446 // Package not found. 1447 suspended = false; 1448 } 1449 1450 if (suspended) { 1451 Slog.i(TAG, "Audio disabled for suspended package=" + packageName + " for uid=" + uid); 1452 return AppOpsManager.MODE_IGNORED; 1453 } 1454 1455 synchronized (this) { 1456 final int mode = checkRestrictionLocked(code, usage, uid, packageName); 1457 if (mode != AppOpsManager.MODE_ALLOWED) { 1458 return mode; 1459 } 1460 } 1461 return checkOperation(code, uid, packageName); 1462 } 1463 isPackageSuspendedForUser(String pkg, int uid)1464 private boolean isPackageSuspendedForUser(String pkg, int uid) { 1465 try { 1466 return AppGlobals.getPackageManager().isPackageSuspendedForUser( 1467 pkg, UserHandle.getUserId(uid)); 1468 } catch (RemoteException re) { 1469 throw new SecurityException("Could not talk to package manager service"); 1470 } 1471 } 1472 checkRestrictionLocked(int code, int usage, int uid, String packageName)1473 private int checkRestrictionLocked(int code, int usage, int uid, String packageName) { 1474 final SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code); 1475 if (usageRestrictions != null) { 1476 final Restriction r = usageRestrictions.get(usage); 1477 if (r != null && !r.exceptionPackages.contains(packageName)) { 1478 return r.mode; 1479 } 1480 } 1481 return AppOpsManager.MODE_ALLOWED; 1482 } 1483 1484 @Override setAudioRestriction(int code, int usage, int uid, int mode, String[] exceptionPackages)1485 public void setAudioRestriction(int code, int usage, int uid, int mode, 1486 String[] exceptionPackages) { 1487 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); 1488 verifyIncomingUid(uid); 1489 verifyIncomingOp(code); 1490 synchronized (this) { 1491 SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code); 1492 if (usageRestrictions == null) { 1493 usageRestrictions = new SparseArray<Restriction>(); 1494 mAudioRestrictions.put(code, usageRestrictions); 1495 } 1496 usageRestrictions.remove(usage); 1497 if (mode != AppOpsManager.MODE_ALLOWED) { 1498 final Restriction r = new Restriction(); 1499 r.mode = mode; 1500 if (exceptionPackages != null) { 1501 final int N = exceptionPackages.length; 1502 r.exceptionPackages = new ArraySet<String>(N); 1503 for (int i = 0; i < N; i++) { 1504 final String pkg = exceptionPackages[i]; 1505 if (pkg != null) { 1506 r.exceptionPackages.add(pkg.trim()); 1507 } 1508 } 1509 } 1510 usageRestrictions.put(usage, r); 1511 } 1512 } 1513 1514 mHandler.sendMessage(PooledLambda.obtainMessage( 1515 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY)); 1516 } 1517 1518 @Override checkPackage(int uid, String packageName)1519 public int checkPackage(int uid, String packageName) { 1520 Preconditions.checkNotNull(packageName); 1521 synchronized (this) { 1522 Ops ops = getOpsRawLocked(uid, packageName, true /* edit */, 1523 true /* uidMismatchExpected */); 1524 if (ops != null) { 1525 return AppOpsManager.MODE_ALLOWED; 1526 } else { 1527 return AppOpsManager.MODE_ERRORED; 1528 } 1529 } 1530 } 1531 1532 @Override noteProxyOperation(int code, String proxyPackageName, int proxiedUid, String proxiedPackageName)1533 public int noteProxyOperation(int code, String proxyPackageName, 1534 int proxiedUid, String proxiedPackageName) { 1535 verifyIncomingOp(code); 1536 final int proxyUid = Binder.getCallingUid(); 1537 String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName); 1538 if (resolveProxyPackageName == null) { 1539 return AppOpsManager.MODE_IGNORED; 1540 } 1541 final int proxyMode = noteOperationUnchecked(code, proxyUid, 1542 resolveProxyPackageName, -1, null); 1543 if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) { 1544 return proxyMode; 1545 } 1546 String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName); 1547 if (resolveProxiedPackageName == null) { 1548 return AppOpsManager.MODE_IGNORED; 1549 } 1550 return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName, 1551 proxyMode, resolveProxyPackageName); 1552 } 1553 1554 @Override noteOperation(int code, int uid, String packageName)1555 public int noteOperation(int code, int uid, String packageName) { 1556 verifyIncomingUid(uid); 1557 verifyIncomingOp(code); 1558 String resolvedPackageName = resolvePackageName(uid, packageName); 1559 if (resolvedPackageName == null) { 1560 return AppOpsManager.MODE_IGNORED; 1561 } 1562 return noteOperationUnchecked(code, uid, resolvedPackageName, 0, null); 1563 } 1564 noteOperationUnchecked(int code, int uid, String packageName, int proxyUid, String proxyPackageName)1565 private int noteOperationUnchecked(int code, int uid, String packageName, 1566 int proxyUid, String proxyPackageName) { 1567 synchronized (this) { 1568 final Ops ops = getOpsRawLocked(uid, packageName, true /* edit */, 1569 false /* uidMismatchExpected */); 1570 if (ops == null) { 1571 if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid 1572 + " package " + packageName); 1573 return AppOpsManager.MODE_ERRORED; 1574 } 1575 final Op op = getOpLocked(ops, code, true); 1576 if (isOpRestrictedLocked(uid, code, packageName)) { 1577 return AppOpsManager.MODE_IGNORED; 1578 } 1579 final UidState uidState = ops.uidState; 1580 if (op.duration == -1) { 1581 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName 1582 + " code " + code + " time=" + op.time[uidState.state] 1583 + " duration=" + op.duration); 1584 } 1585 op.duration = 0; 1586 final int switchCode = AppOpsManager.opToSwitch(code); 1587 // If there is a non-default per UID policy (we set UID op mode only if 1588 // non-default) it takes over, otherwise use the per package policy. 1589 if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) { 1590 final int uidMode = uidState.evalMode(uidState.opModes.get(switchCode)); 1591 if (uidMode != AppOpsManager.MODE_ALLOWED) { 1592 if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code " 1593 + switchCode + " (" + code + ") uid " + uid + " package " 1594 + packageName); 1595 op.rejectTime[uidState.state] = System.currentTimeMillis(); 1596 return uidMode; 1597 } 1598 } else { 1599 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; 1600 final int mode = switchOp.getMode(); 1601 if (mode != AppOpsManager.MODE_ALLOWED) { 1602 if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code " 1603 + switchCode + " (" + code + ") uid " + uid + " package " 1604 + packageName); 1605 op.rejectTime[uidState.state] = System.currentTimeMillis(); 1606 return mode; 1607 } 1608 } 1609 if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid 1610 + " package " + packageName); 1611 op.time[uidState.state] = System.currentTimeMillis(); 1612 op.rejectTime[uidState.state] = 0; 1613 op.proxyUid = proxyUid; 1614 op.proxyPackageName = proxyPackageName; 1615 return AppOpsManager.MODE_ALLOWED; 1616 } 1617 } 1618 1619 @Override startWatchingActive(int[] ops, IAppOpsActiveCallback callback)1620 public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) { 1621 int watchedUid = -1; 1622 final int callingUid = Binder.getCallingUid(); 1623 final int callingPid = Binder.getCallingPid(); 1624 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 1625 != PackageManager.PERMISSION_GRANTED) { 1626 watchedUid = callingUid; 1627 } 1628 if (ops != null) { 1629 Preconditions.checkArrayElementsInRange(ops, 0, 1630 AppOpsManager._NUM_OP - 1, "Invalid op code in: " + Arrays.toString(ops)); 1631 } 1632 if (callback == null) { 1633 return; 1634 } 1635 synchronized (this) { 1636 SparseArray<ActiveCallback> callbacks = mActiveWatchers.get(callback.asBinder()); 1637 if (callbacks == null) { 1638 callbacks = new SparseArray<>(); 1639 mActiveWatchers.put(callback.asBinder(), callbacks); 1640 } 1641 final ActiveCallback activeCallback = new ActiveCallback(callback, watchedUid, 1642 callingUid, callingPid); 1643 for (int op : ops) { 1644 callbacks.put(op, activeCallback); 1645 } 1646 } 1647 } 1648 1649 @Override stopWatchingActive(IAppOpsActiveCallback callback)1650 public void stopWatchingActive(IAppOpsActiveCallback callback) { 1651 if (callback == null) { 1652 return; 1653 } 1654 synchronized (this) { 1655 final SparseArray<ActiveCallback> activeCallbacks = 1656 mActiveWatchers.remove(callback.asBinder()); 1657 if (activeCallbacks == null) { 1658 return; 1659 } 1660 final int callbackCount = activeCallbacks.size(); 1661 for (int i = 0; i < callbackCount; i++) { 1662 // Apps ops are mapped to a singleton 1663 if (i == 0) { 1664 activeCallbacks.valueAt(i).destroy(); 1665 } 1666 } 1667 } 1668 } 1669 1670 @Override startOperation(IBinder token, int code, int uid, String packageName, boolean startIfModeDefault)1671 public int startOperation(IBinder token, int code, int uid, String packageName, 1672 boolean startIfModeDefault) { 1673 verifyIncomingUid(uid); 1674 verifyIncomingOp(code); 1675 String resolvedPackageName = resolvePackageName(uid, packageName); 1676 if (resolvedPackageName == null) { 1677 return AppOpsManager.MODE_IGNORED; 1678 } 1679 ClientState client = (ClientState)token; 1680 synchronized (this) { 1681 final Ops ops = getOpsRawLocked(uid, resolvedPackageName, true /* edit */, 1682 false /* uidMismatchExpected */); 1683 if (ops == null) { 1684 if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid 1685 + " package " + resolvedPackageName); 1686 return AppOpsManager.MODE_ERRORED; 1687 } 1688 final Op op = getOpLocked(ops, code, true); 1689 if (isOpRestrictedLocked(uid, code, resolvedPackageName)) { 1690 return AppOpsManager.MODE_IGNORED; 1691 } 1692 final int switchCode = AppOpsManager.opToSwitch(code); 1693 final UidState uidState = ops.uidState; 1694 // If there is a non-default per UID policy (we set UID op mode only if 1695 // non-default) it takes over, otherwise use the per package policy. 1696 if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) { 1697 final int uidMode = uidState.evalMode(uidState.opModes.get(switchCode)); 1698 if (uidMode != AppOpsManager.MODE_ALLOWED 1699 && (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) { 1700 if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code " 1701 + switchCode + " (" + code + ") uid " + uid + " package " 1702 + resolvedPackageName); 1703 op.rejectTime[uidState.state] = System.currentTimeMillis(); 1704 return uidMode; 1705 } 1706 } else { 1707 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; 1708 final int mode = switchOp.getMode(); 1709 if (mode != AppOpsManager.MODE_ALLOWED 1710 && (!startIfModeDefault || mode != AppOpsManager.MODE_DEFAULT)) { 1711 if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code " 1712 + switchCode + " (" + code + ") uid " + uid + " package " 1713 + resolvedPackageName); 1714 op.rejectTime[uidState.state] = System.currentTimeMillis(); 1715 return mode; 1716 } 1717 } 1718 if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid 1719 + " package " + resolvedPackageName); 1720 if (op.startNesting == 0) { 1721 op.startRealtime = SystemClock.elapsedRealtime(); 1722 op.time[uidState.state] = System.currentTimeMillis(); 1723 op.rejectTime[uidState.state] = 0; 1724 op.duration = -1; 1725 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true); 1726 } 1727 op.startNesting++; 1728 uidState.startNesting++; 1729 if (client.mStartedOps != null) { 1730 client.mStartedOps.add(op); 1731 } 1732 } 1733 1734 return AppOpsManager.MODE_ALLOWED; 1735 } 1736 1737 @Override finishOperation(IBinder token, int code, int uid, String packageName)1738 public void finishOperation(IBinder token, int code, int uid, String packageName) { 1739 verifyIncomingUid(uid); 1740 verifyIncomingOp(code); 1741 String resolvedPackageName = resolvePackageName(uid, packageName); 1742 if (resolvedPackageName == null) { 1743 return; 1744 } 1745 if (!(token instanceof ClientState)) { 1746 return; 1747 } 1748 ClientState client = (ClientState) token; 1749 synchronized (this) { 1750 Op op = getOpLocked(code, uid, resolvedPackageName, true); 1751 if (op == null) { 1752 return; 1753 } 1754 if (!client.mStartedOps.remove(op)) { 1755 // We finish ops when packages get removed to guarantee no dangling 1756 // started ops. However, some part of the system may asynchronously 1757 // finish ops for an already gone package. Hence, finishing an op 1758 // for a non existing package is fine and we don't log as a wtf. 1759 final long identity = Binder.clearCallingIdentity(); 1760 try { 1761 if (LocalServices.getService(PackageManagerInternal.class).getPackageUid( 1762 resolvedPackageName, 0, UserHandle.getUserId(uid)) < 0) { 1763 Slog.i(TAG, "Finishing op=" + AppOpsManager.opToName(code) 1764 + " for non-existing package=" + resolvedPackageName 1765 + " in uid=" + uid); 1766 return; 1767 } 1768 } finally { 1769 Binder.restoreCallingIdentity(identity); 1770 } 1771 Slog.wtf(TAG, "Operation not started: uid=" + op.uid + " pkg=" 1772 + op.packageName + " op=" + AppOpsManager.opToName(op.op)); 1773 return; 1774 } 1775 finishOperationLocked(op, /*finishNested*/ false); 1776 if (op.startNesting <= 0) { 1777 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, false); 1778 } 1779 } 1780 } 1781 scheduleOpActiveChangedIfNeededLocked(int code, int uid, String packageName, boolean active)1782 private void scheduleOpActiveChangedIfNeededLocked(int code, int uid, String packageName, 1783 boolean active) { 1784 ArraySet<ActiveCallback> dispatchedCallbacks = null; 1785 final int callbackListCount = mActiveWatchers.size(); 1786 for (int i = 0; i < callbackListCount; i++) { 1787 final SparseArray<ActiveCallback> callbacks = mActiveWatchers.valueAt(i); 1788 ActiveCallback callback = callbacks.get(code); 1789 if (callback != null) { 1790 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 1791 continue; 1792 } 1793 if (dispatchedCallbacks == null) { 1794 dispatchedCallbacks = new ArraySet<>(); 1795 } 1796 dispatchedCallbacks.add(callback); 1797 } 1798 } 1799 if (dispatchedCallbacks == null) { 1800 return; 1801 } 1802 mHandler.sendMessage(PooledLambda.obtainMessage( 1803 AppOpsService::notifyOpActiveChanged, 1804 this, dispatchedCallbacks, code, uid, packageName, active)); 1805 } 1806 notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks, int code, int uid, String packageName, boolean active)1807 private void notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks, 1808 int code, int uid, String packageName, boolean active) { 1809 // There are components watching for mode changes such as window manager 1810 // and location manager which are in our process. The callbacks in these 1811 // components may require permissions our remote caller does not have. 1812 final long identity = Binder.clearCallingIdentity(); 1813 try { 1814 final int callbackCount = callbacks.size(); 1815 for (int i = 0; i < callbackCount; i++) { 1816 final ActiveCallback callback = callbacks.valueAt(i); 1817 try { 1818 callback.mCallback.opActiveChanged(code, uid, packageName, active); 1819 } catch (RemoteException e) { 1820 /* do nothing */ 1821 } 1822 } 1823 } finally { 1824 Binder.restoreCallingIdentity(identity); 1825 } 1826 } 1827 1828 @Override permissionToOpCode(String permission)1829 public int permissionToOpCode(String permission) { 1830 if (permission == null) { 1831 return AppOpsManager.OP_NONE; 1832 } 1833 return AppOpsManager.permissionToOpCode(permission); 1834 } 1835 finishOperationLocked(Op op, boolean finishNested)1836 void finishOperationLocked(Op op, boolean finishNested) { 1837 if (op.startNesting <= 1 || finishNested) { 1838 if (op.startNesting == 1 || finishNested) { 1839 op.duration = (int)(SystemClock.elapsedRealtime() - op.startRealtime); 1840 op.time[op.uidState.state] = System.currentTimeMillis(); 1841 } else { 1842 Slog.w(TAG, "Finishing op nesting under-run: uid " + op.uid + " pkg " 1843 + op.packageName + " code " + op.op + " time=" + op.time 1844 + " duration=" + op.duration + " nesting=" + op.startNesting); 1845 } 1846 if (op.startNesting >= 1) { 1847 op.uidState.startNesting -= op.startNesting; 1848 } 1849 op.startNesting = 0; 1850 } else { 1851 op.startNesting--; 1852 op.uidState.startNesting--; 1853 } 1854 } 1855 verifyIncomingUid(int uid)1856 private void verifyIncomingUid(int uid) { 1857 if (uid == Binder.getCallingUid()) { 1858 return; 1859 } 1860 if (Binder.getCallingPid() == Process.myPid()) { 1861 return; 1862 } 1863 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 1864 Binder.getCallingPid(), Binder.getCallingUid(), null); 1865 } 1866 verifyIncomingOp(int op)1867 private void verifyIncomingOp(int op) { 1868 if (op >= 0 && op < AppOpsManager._NUM_OP) { 1869 return; 1870 } 1871 throw new IllegalArgumentException("Bad operation #" + op); 1872 } 1873 getUidStateLocked(int uid, boolean edit)1874 private UidState getUidStateLocked(int uid, boolean edit) { 1875 UidState uidState = mUidStates.get(uid); 1876 if (uidState == null) { 1877 if (!edit) { 1878 return null; 1879 } 1880 uidState = new UidState(uid); 1881 mUidStates.put(uid, uidState); 1882 } else { 1883 if (uidState.pendingStateCommitTime != 0) { 1884 if (uidState.pendingStateCommitTime < mLastUptime) { 1885 commitUidPendingStateLocked(uidState); 1886 } else { 1887 mLastUptime = SystemClock.uptimeMillis(); 1888 if (uidState.pendingStateCommitTime < mLastUptime) { 1889 commitUidPendingStateLocked(uidState); 1890 } 1891 } 1892 } 1893 } 1894 return uidState; 1895 } 1896 commitUidPendingStateLocked(UidState uidState)1897 private void commitUidPendingStateLocked(UidState uidState) { 1898 final boolean lastForeground = uidState.state <= UID_STATE_LAST_NON_RESTRICTED; 1899 final boolean nowForeground = uidState.pendingState <= UID_STATE_LAST_NON_RESTRICTED; 1900 uidState.state = uidState.pendingState; 1901 uidState.pendingStateCommitTime = 0; 1902 if (uidState.hasForegroundWatchers && lastForeground != nowForeground) { 1903 for (int fgi = uidState.foregroundOps.size() - 1; fgi >= 0; fgi--) { 1904 if (!uidState.foregroundOps.valueAt(fgi)) { 1905 continue; 1906 } 1907 final int code = uidState.foregroundOps.keyAt(fgi); 1908 1909 final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code); 1910 if (callbacks != null) { 1911 for (int cbi = callbacks.size() - 1; cbi >= 0; cbi--) { 1912 final ModeCallback callback = callbacks.valueAt(cbi); 1913 if ((callback.mFlags & AppOpsManager.WATCH_FOREGROUND_CHANGES) == 0 1914 || !callback.isWatchingUid(uidState.uid)) { 1915 continue; 1916 } 1917 boolean doAllPackages = uidState.opModes != null 1918 && uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND; 1919 if (uidState.pkgOps != null) { 1920 for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) { 1921 final Op op = uidState.pkgOps.valueAt(pkgi).get(code); 1922 if (doAllPackages || (op != null 1923 && op.mode == AppOpsManager.MODE_FOREGROUND)) { 1924 mHandler.sendMessage(PooledLambda.obtainMessage( 1925 AppOpsService::notifyOpChanged, 1926 this, callback, code, uidState.uid, 1927 uidState.pkgOps.keyAt(pkgi))); 1928 } 1929 } 1930 } 1931 } 1932 } 1933 } 1934 } 1935 } 1936 getOpsRawLocked(int uid, String packageName, boolean edit, boolean uidMismatchExpected)1937 private Ops getOpsRawLocked(int uid, String packageName, boolean edit, 1938 boolean uidMismatchExpected) { 1939 UidState uidState = getUidStateLocked(uid, edit); 1940 if (uidState == null) { 1941 return null; 1942 } 1943 1944 if (uidState.pkgOps == null) { 1945 if (!edit) { 1946 return null; 1947 } 1948 uidState.pkgOps = new ArrayMap<>(); 1949 } 1950 1951 Ops ops = uidState.pkgOps.get(packageName); 1952 if (ops == null) { 1953 if (!edit) { 1954 return null; 1955 } 1956 boolean isPrivileged = false; 1957 // This is the first time we have seen this package name under this uid, 1958 // so let's make sure it is valid. 1959 if (uid != 0) { 1960 final long ident = Binder.clearCallingIdentity(); 1961 try { 1962 int pkgUid = -1; 1963 try { 1964 ApplicationInfo appInfo = ActivityThread.getPackageManager() 1965 .getApplicationInfo(packageName, 1966 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 1967 UserHandle.getUserId(uid)); 1968 if (appInfo != null) { 1969 pkgUid = appInfo.uid; 1970 isPrivileged = (appInfo.privateFlags 1971 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; 1972 } else { 1973 pkgUid = resolveUid(packageName); 1974 if (pkgUid >= 0) { 1975 isPrivileged = false; 1976 } 1977 } 1978 } catch (RemoteException e) { 1979 Slog.w(TAG, "Could not contact PackageManager", e); 1980 } 1981 if (pkgUid != uid) { 1982 // Oops! The package name is not valid for the uid they are calling 1983 // under. Abort. 1984 if (!uidMismatchExpected) { 1985 RuntimeException ex = new RuntimeException("here"); 1986 ex.fillInStackTrace(); 1987 Slog.w(TAG, "Bad call: specified package " + packageName 1988 + " under uid " + uid + " but it is really " + pkgUid, ex); 1989 } 1990 return null; 1991 } 1992 } finally { 1993 Binder.restoreCallingIdentity(ident); 1994 } 1995 } 1996 ops = new Ops(packageName, uidState, isPrivileged); 1997 uidState.pkgOps.put(packageName, ops); 1998 } 1999 return ops; 2000 } 2001 scheduleWriteLocked()2002 private void scheduleWriteLocked() { 2003 if (!mWriteScheduled) { 2004 mWriteScheduled = true; 2005 mHandler.postDelayed(mWriteRunner, WRITE_DELAY); 2006 } 2007 } 2008 scheduleFastWriteLocked()2009 private void scheduleFastWriteLocked() { 2010 if (!mFastWriteScheduled) { 2011 mWriteScheduled = true; 2012 mFastWriteScheduled = true; 2013 mHandler.removeCallbacks(mWriteRunner); 2014 mHandler.postDelayed(mWriteRunner, 10*1000); 2015 } 2016 } 2017 getOpLocked(int code, int uid, String packageName, boolean edit)2018 private Op getOpLocked(int code, int uid, String packageName, boolean edit) { 2019 Ops ops = getOpsRawLocked(uid, packageName, edit, 2020 false /* uidMismatchExpected */); 2021 if (ops == null) { 2022 return null; 2023 } 2024 return getOpLocked(ops, code, edit); 2025 } 2026 getOpLocked(Ops ops, int code, boolean edit)2027 private Op getOpLocked(Ops ops, int code, boolean edit) { 2028 Op op = ops.get(code); 2029 if (op == null) { 2030 if (!edit) { 2031 return null; 2032 } 2033 op = new Op(ops.uidState, ops.packageName, code); 2034 ops.put(code, op); 2035 } 2036 if (edit) { 2037 scheduleWriteLocked(); 2038 } 2039 return op; 2040 } 2041 isOpRestrictedLocked(int uid, int code, String packageName)2042 private boolean isOpRestrictedLocked(int uid, int code, String packageName) { 2043 int userHandle = UserHandle.getUserId(uid); 2044 final int restrictionSetCount = mOpUserRestrictions.size(); 2045 2046 for (int i = 0; i < restrictionSetCount; i++) { 2047 // For each client, check that the given op is not restricted, or that the given 2048 // package is exempt from the restriction. 2049 ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); 2050 if (restrictionState.hasRestriction(code, packageName, userHandle)) { 2051 if (AppOpsManager.opAllowSystemBypassRestriction(code)) { 2052 // If we are the system, bypass user restrictions for certain codes 2053 synchronized (this) { 2054 Ops ops = getOpsRawLocked(uid, packageName, true /* edit */, 2055 false /* uidMismatchExpected */); 2056 if ((ops != null) && ops.isPrivileged) { 2057 return false; 2058 } 2059 } 2060 } 2061 return true; 2062 } 2063 } 2064 return false; 2065 } 2066 readState()2067 void readState() { 2068 int oldVersion = NO_VERSION; 2069 synchronized (mFile) { 2070 synchronized (this) { 2071 FileInputStream stream; 2072 try { 2073 stream = mFile.openRead(); 2074 } catch (FileNotFoundException e) { 2075 Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty"); 2076 return; 2077 } 2078 boolean success = false; 2079 mUidStates.clear(); 2080 try { 2081 XmlPullParser parser = Xml.newPullParser(); 2082 parser.setInput(stream, StandardCharsets.UTF_8.name()); 2083 int type; 2084 while ((type = parser.next()) != XmlPullParser.START_TAG 2085 && type != XmlPullParser.END_DOCUMENT) { 2086 ; 2087 } 2088 2089 if (type != XmlPullParser.START_TAG) { 2090 throw new IllegalStateException("no start tag found"); 2091 } 2092 2093 final String versionString = parser.getAttributeValue(null, "v"); 2094 if (versionString != null) { 2095 oldVersion = Integer.parseInt(versionString); 2096 } 2097 2098 int outerDepth = parser.getDepth(); 2099 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2100 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2101 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2102 continue; 2103 } 2104 2105 String tagName = parser.getName(); 2106 if (tagName.equals("pkg")) { 2107 readPackage(parser); 2108 } else if (tagName.equals("uid")) { 2109 readUidOps(parser); 2110 } else { 2111 Slog.w(TAG, "Unknown element under <app-ops>: " 2112 + parser.getName()); 2113 XmlUtils.skipCurrentTag(parser); 2114 } 2115 } 2116 success = true; 2117 } catch (IllegalStateException e) { 2118 Slog.w(TAG, "Failed parsing " + e); 2119 } catch (NullPointerException e) { 2120 Slog.w(TAG, "Failed parsing " + e); 2121 } catch (NumberFormatException e) { 2122 Slog.w(TAG, "Failed parsing " + e); 2123 } catch (XmlPullParserException e) { 2124 Slog.w(TAG, "Failed parsing " + e); 2125 } catch (IOException e) { 2126 Slog.w(TAG, "Failed parsing " + e); 2127 } catch (IndexOutOfBoundsException e) { 2128 Slog.w(TAG, "Failed parsing " + e); 2129 } finally { 2130 if (!success) { 2131 mUidStates.clear(); 2132 } 2133 try { 2134 stream.close(); 2135 } catch (IOException e) { 2136 } 2137 } 2138 } 2139 } 2140 synchronized (this) { 2141 upgradeLocked(oldVersion); 2142 } 2143 } 2144 upgradeRunAnyInBackgroundLocked()2145 private void upgradeRunAnyInBackgroundLocked() { 2146 for (int i = 0; i < mUidStates.size(); i++) { 2147 final UidState uidState = mUidStates.valueAt(i); 2148 if (uidState == null) { 2149 continue; 2150 } 2151 if (uidState.opModes != null) { 2152 final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND); 2153 if (idx >= 0) { 2154 uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, 2155 uidState.opModes.valueAt(idx)); 2156 } 2157 } 2158 if (uidState.pkgOps == null) { 2159 continue; 2160 } 2161 boolean changed = false; 2162 for (int j = 0; j < uidState.pkgOps.size(); j++) { 2163 Ops ops = uidState.pkgOps.valueAt(j); 2164 if (ops != null) { 2165 final Op op = ops.get(AppOpsManager.OP_RUN_IN_BACKGROUND); 2166 if (op != null && op.mode != AppOpsManager.opToDefaultMode(op.op)) { 2167 final Op copy = new Op(op.uidState, op.packageName, 2168 AppOpsManager.OP_RUN_ANY_IN_BACKGROUND); 2169 copy.mode = op.mode; 2170 ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy); 2171 changed = true; 2172 } 2173 } 2174 } 2175 if (changed) { 2176 uidState.evalForegroundOps(mOpModeWatchers); 2177 } 2178 } 2179 } 2180 upgradeLocked(int oldVersion)2181 private void upgradeLocked(int oldVersion) { 2182 if (oldVersion >= CURRENT_VERSION) { 2183 return; 2184 } 2185 Slog.d(TAG, "Upgrading app-ops xml from version " + oldVersion + " to " + CURRENT_VERSION); 2186 switch (oldVersion) { 2187 case NO_VERSION: 2188 upgradeRunAnyInBackgroundLocked(); 2189 // fall through 2190 case 1: 2191 // for future upgrades 2192 } 2193 scheduleFastWriteLocked(); 2194 } 2195 readUidOps(XmlPullParser parser)2196 void readUidOps(XmlPullParser parser) throws NumberFormatException, 2197 XmlPullParserException, IOException { 2198 final int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 2199 int outerDepth = parser.getDepth(); 2200 int type; 2201 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2202 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2203 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2204 continue; 2205 } 2206 2207 String tagName = parser.getName(); 2208 if (tagName.equals("op")) { 2209 final int code = Integer.parseInt(parser.getAttributeValue(null, "n")); 2210 final int mode = Integer.parseInt(parser.getAttributeValue(null, "m")); 2211 UidState uidState = getUidStateLocked(uid, true); 2212 if (uidState.opModes == null) { 2213 uidState.opModes = new SparseIntArray(); 2214 } 2215 uidState.opModes.put(code, mode); 2216 } else { 2217 Slog.w(TAG, "Unknown element under <uid-ops>: " 2218 + parser.getName()); 2219 XmlUtils.skipCurrentTag(parser); 2220 } 2221 } 2222 } 2223 readPackage(XmlPullParser parser)2224 void readPackage(XmlPullParser parser) throws NumberFormatException, 2225 XmlPullParserException, IOException { 2226 String pkgName = parser.getAttributeValue(null, "n"); 2227 int outerDepth = parser.getDepth(); 2228 int type; 2229 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2230 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2231 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2232 continue; 2233 } 2234 2235 String tagName = parser.getName(); 2236 if (tagName.equals("uid")) { 2237 readUid(parser, pkgName); 2238 } else { 2239 Slog.w(TAG, "Unknown element under <pkg>: " 2240 + parser.getName()); 2241 XmlUtils.skipCurrentTag(parser); 2242 } 2243 } 2244 } 2245 readUid(XmlPullParser parser, String pkgName)2246 void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException, 2247 XmlPullParserException, IOException { 2248 int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 2249 String isPrivilegedString = parser.getAttributeValue(null, "p"); 2250 boolean isPrivileged = false; 2251 if (isPrivilegedString == null) { 2252 try { 2253 IPackageManager packageManager = ActivityThread.getPackageManager(); 2254 if (packageManager != null) { 2255 ApplicationInfo appInfo = ActivityThread.getPackageManager() 2256 .getApplicationInfo(pkgName, 0, UserHandle.getUserId(uid)); 2257 if (appInfo != null) { 2258 isPrivileged = (appInfo.privateFlags 2259 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; 2260 } 2261 } else { 2262 // Could not load data, don't add to cache so it will be loaded later. 2263 return; 2264 } 2265 } catch (RemoteException e) { 2266 Slog.w(TAG, "Could not contact PackageManager", e); 2267 } 2268 } else { 2269 isPrivileged = Boolean.parseBoolean(isPrivilegedString); 2270 } 2271 int outerDepth = parser.getDepth(); 2272 int type; 2273 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2274 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2275 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2276 continue; 2277 } 2278 2279 String tagName = parser.getName(); 2280 if (tagName.equals("op")) { 2281 UidState uidState = getUidStateLocked(uid, true); 2282 if (uidState.pkgOps == null) { 2283 uidState.pkgOps = new ArrayMap<>(); 2284 } 2285 2286 Op op = new Op(uidState, pkgName, 2287 Integer.parseInt(parser.getAttributeValue(null, "n"))); 2288 2289 for (int i = parser.getAttributeCount()-1; i >= 0; i--) { 2290 final String name = parser.getAttributeName(i); 2291 final String value = parser.getAttributeValue(i); 2292 switch (name) { 2293 case "m": 2294 op.mode = Integer.parseInt(value); 2295 break; 2296 case "d": 2297 op.duration = Integer.parseInt(value); 2298 break; 2299 case "pu": 2300 op.proxyUid = Integer.parseInt(value); 2301 break; 2302 case "pp": 2303 op.proxyPackageName = value; 2304 break; 2305 case "tp": 2306 op.time[AppOpsManager.UID_STATE_PERSISTENT] = Long.parseLong(value); 2307 break; 2308 case "tt": 2309 op.time[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value); 2310 break; 2311 case "tfs": 2312 op.time[AppOpsManager.UID_STATE_FOREGROUND_SERVICE] 2313 = Long.parseLong(value); 2314 break; 2315 case "tf": 2316 op.time[AppOpsManager.UID_STATE_FOREGROUND] = Long.parseLong(value); 2317 break; 2318 case "tb": 2319 op.time[AppOpsManager.UID_STATE_BACKGROUND] = Long.parseLong(value); 2320 break; 2321 case "tc": 2322 op.time[AppOpsManager.UID_STATE_CACHED] = Long.parseLong(value); 2323 break; 2324 case "rp": 2325 op.rejectTime[AppOpsManager.UID_STATE_PERSISTENT] 2326 = Long.parseLong(value); 2327 break; 2328 case "rt": 2329 op.rejectTime[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value); 2330 break; 2331 case "rfs": 2332 op.rejectTime[AppOpsManager.UID_STATE_FOREGROUND_SERVICE] 2333 = Long.parseLong(value); 2334 break; 2335 case "rf": 2336 op.rejectTime[AppOpsManager.UID_STATE_FOREGROUND] 2337 = Long.parseLong(value); 2338 break; 2339 case "rb": 2340 op.rejectTime[AppOpsManager.UID_STATE_BACKGROUND] 2341 = Long.parseLong(value); 2342 break; 2343 case "rc": 2344 op.rejectTime[AppOpsManager.UID_STATE_CACHED] 2345 = Long.parseLong(value); 2346 break; 2347 case "t": 2348 // Backwards compat. 2349 op.time[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value); 2350 break; 2351 case "r": 2352 // Backwards compat. 2353 op.rejectTime[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value); 2354 break; 2355 default: 2356 Slog.w(TAG, "Unknown attribute in 'op' tag: " + name); 2357 break; 2358 } 2359 } 2360 2361 Ops ops = uidState.pkgOps.get(pkgName); 2362 if (ops == null) { 2363 ops = new Ops(pkgName, uidState, isPrivileged); 2364 uidState.pkgOps.put(pkgName, ops); 2365 } 2366 ops.put(op.op, op); 2367 } else { 2368 Slog.w(TAG, "Unknown element under <pkg>: " 2369 + parser.getName()); 2370 XmlUtils.skipCurrentTag(parser); 2371 } 2372 } 2373 UidState uidState = getUidStateLocked(uid, false); 2374 if (uidState != null) { 2375 uidState.evalForegroundOps(mOpModeWatchers); 2376 } 2377 } 2378 writeState()2379 void writeState() { 2380 synchronized (mFile) { 2381 FileOutputStream stream; 2382 try { 2383 stream = mFile.startWrite(); 2384 } catch (IOException e) { 2385 Slog.w(TAG, "Failed to write state: " + e); 2386 return; 2387 } 2388 2389 List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null); 2390 2391 try { 2392 XmlSerializer out = new FastXmlSerializer(); 2393 out.setOutput(stream, StandardCharsets.UTF_8.name()); 2394 out.startDocument(null, true); 2395 out.startTag(null, "app-ops"); 2396 out.attribute(null, "v", String.valueOf(CURRENT_VERSION)); 2397 2398 final int uidStateCount = mUidStates.size(); 2399 for (int i = 0; i < uidStateCount; i++) { 2400 UidState uidState = mUidStates.valueAt(i); 2401 if (uidState.opModes != null && uidState.opModes.size() > 0) { 2402 out.startTag(null, "uid"); 2403 out.attribute(null, "n", Integer.toString(uidState.uid)); 2404 SparseIntArray uidOpModes = uidState.opModes; 2405 final int opCount = uidOpModes.size(); 2406 for (int j = 0; j < opCount; j++) { 2407 final int op = uidOpModes.keyAt(j); 2408 final int mode = uidOpModes.valueAt(j); 2409 out.startTag(null, "op"); 2410 out.attribute(null, "n", Integer.toString(op)); 2411 out.attribute(null, "m", Integer.toString(mode)); 2412 out.endTag(null, "op"); 2413 } 2414 out.endTag(null, "uid"); 2415 } 2416 } 2417 2418 if (allOps != null) { 2419 String lastPkg = null; 2420 for (int i=0; i<allOps.size(); i++) { 2421 AppOpsManager.PackageOps pkg = allOps.get(i); 2422 if (!pkg.getPackageName().equals(lastPkg)) { 2423 if (lastPkg != null) { 2424 out.endTag(null, "pkg"); 2425 } 2426 lastPkg = pkg.getPackageName(); 2427 out.startTag(null, "pkg"); 2428 out.attribute(null, "n", lastPkg); 2429 } 2430 out.startTag(null, "uid"); 2431 out.attribute(null, "n", Integer.toString(pkg.getUid())); 2432 synchronized (this) { 2433 Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), 2434 false /* edit */, false /* uidMismatchExpected */); 2435 // Should always be present as the list of PackageOps is generated 2436 // from Ops. 2437 if (ops != null) { 2438 out.attribute(null, "p", Boolean.toString(ops.isPrivileged)); 2439 } else { 2440 out.attribute(null, "p", Boolean.toString(false)); 2441 } 2442 } 2443 List<AppOpsManager.OpEntry> ops = pkg.getOps(); 2444 for (int j=0; j<ops.size(); j++) { 2445 AppOpsManager.OpEntry op = ops.get(j); 2446 out.startTag(null, "op"); 2447 out.attribute(null, "n", Integer.toString(op.getOp())); 2448 if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) { 2449 out.attribute(null, "m", Integer.toString(op.getMode())); 2450 } 2451 for (int k = 0; k < _NUM_UID_STATE; k++) { 2452 final long time = op.getLastTimeFor(k); 2453 if (time != 0) { 2454 out.attribute(null, UID_STATE_TIME_ATTRS[k], 2455 Long.toString(time)); 2456 } 2457 final long rejectTime = op.getLastRejectTimeFor(k); 2458 if (rejectTime != 0) { 2459 out.attribute(null, UID_STATE_REJECT_ATTRS[k], 2460 Long.toString(rejectTime)); 2461 } 2462 } 2463 int dur = op.getDuration(); 2464 if (dur != 0) { 2465 out.attribute(null, "d", Integer.toString(dur)); 2466 } 2467 int proxyUid = op.getProxyUid(); 2468 if (proxyUid != -1) { 2469 out.attribute(null, "pu", Integer.toString(proxyUid)); 2470 } 2471 String proxyPackageName = op.getProxyPackageName(); 2472 if (proxyPackageName != null) { 2473 out.attribute(null, "pp", proxyPackageName); 2474 } 2475 out.endTag(null, "op"); 2476 } 2477 out.endTag(null, "uid"); 2478 } 2479 if (lastPkg != null) { 2480 out.endTag(null, "pkg"); 2481 } 2482 } 2483 2484 out.endTag(null, "app-ops"); 2485 out.endDocument(); 2486 mFile.finishWrite(stream); 2487 } catch (IOException e) { 2488 Slog.w(TAG, "Failed to write state, restoring backup.", e); 2489 mFile.failWrite(stream); 2490 } 2491 } 2492 } 2493 2494 static class Shell extends ShellCommand { 2495 final IAppOpsService mInterface; 2496 final AppOpsService mInternal; 2497 2498 int userId = UserHandle.USER_SYSTEM; 2499 String packageName; 2500 String opStr; 2501 String modeStr; 2502 int op; 2503 int mode; 2504 int packageUid; 2505 int nonpackageUid; 2506 final static Binder sBinder = new Binder(); 2507 IBinder mToken; 2508 Shell(IAppOpsService iface, AppOpsService internal)2509 Shell(IAppOpsService iface, AppOpsService internal) { 2510 mInterface = iface; 2511 mInternal = internal; 2512 try { 2513 mToken = mInterface.getToken(sBinder); 2514 } catch (RemoteException e) { 2515 } 2516 } 2517 2518 @Override onCommand(String cmd)2519 public int onCommand(String cmd) { 2520 return onShellCommand(this, cmd); 2521 } 2522 2523 @Override onHelp()2524 public void onHelp() { 2525 PrintWriter pw = getOutPrintWriter(); 2526 dumpCommandHelp(pw); 2527 } 2528 strOpToOp(String op, PrintWriter err)2529 static private int strOpToOp(String op, PrintWriter err) { 2530 try { 2531 return AppOpsManager.strOpToOp(op); 2532 } catch (IllegalArgumentException e) { 2533 } 2534 try { 2535 return Integer.parseInt(op); 2536 } catch (NumberFormatException e) { 2537 } 2538 try { 2539 return AppOpsManager.strDebugOpToOp(op); 2540 } catch (IllegalArgumentException e) { 2541 err.println("Error: " + e.getMessage()); 2542 return -1; 2543 } 2544 } 2545 strModeToMode(String modeStr, PrintWriter err)2546 static int strModeToMode(String modeStr, PrintWriter err) { 2547 for (int i = AppOpsManager.MODE_NAMES.length - 1; i >= 0; i--) { 2548 if (AppOpsManager.MODE_NAMES[i].equals(modeStr)) { 2549 return i; 2550 } 2551 } 2552 try { 2553 return Integer.parseInt(modeStr); 2554 } catch (NumberFormatException e) { 2555 } 2556 err.println("Error: Mode " + modeStr + " is not valid"); 2557 return -1; 2558 } 2559 parseUserOpMode(int defMode, PrintWriter err)2560 int parseUserOpMode(int defMode, PrintWriter err) throws RemoteException { 2561 userId = UserHandle.USER_CURRENT; 2562 opStr = null; 2563 modeStr = null; 2564 for (String argument; (argument = getNextArg()) != null;) { 2565 if ("--user".equals(argument)) { 2566 userId = UserHandle.parseUserArg(getNextArgRequired()); 2567 } else { 2568 if (opStr == null) { 2569 opStr = argument; 2570 } else if (modeStr == null) { 2571 modeStr = argument; 2572 break; 2573 } 2574 } 2575 } 2576 if (opStr == null) { 2577 err.println("Error: Operation not specified."); 2578 return -1; 2579 } 2580 op = strOpToOp(opStr, err); 2581 if (op < 0) { 2582 return -1; 2583 } 2584 if (modeStr != null) { 2585 if ((mode=strModeToMode(modeStr, err)) < 0) { 2586 return -1; 2587 } 2588 } else { 2589 mode = defMode; 2590 } 2591 return 0; 2592 } 2593 parseUserPackageOp(boolean reqOp, PrintWriter err)2594 int parseUserPackageOp(boolean reqOp, PrintWriter err) throws RemoteException { 2595 userId = UserHandle.USER_CURRENT; 2596 packageName = null; 2597 opStr = null; 2598 for (String argument; (argument = getNextArg()) != null;) { 2599 if ("--user".equals(argument)) { 2600 userId = UserHandle.parseUserArg(getNextArgRequired()); 2601 } else { 2602 if (packageName == null) { 2603 packageName = argument; 2604 } else if (opStr == null) { 2605 opStr = argument; 2606 break; 2607 } 2608 } 2609 } 2610 if (packageName == null) { 2611 err.println("Error: Package name not specified."); 2612 return -1; 2613 } else if (opStr == null && reqOp) { 2614 err.println("Error: Operation not specified."); 2615 return -1; 2616 } 2617 if (opStr != null) { 2618 op = strOpToOp(opStr, err); 2619 if (op < 0) { 2620 return -1; 2621 } 2622 } else { 2623 op = AppOpsManager.OP_NONE; 2624 } 2625 if (userId == UserHandle.USER_CURRENT) { 2626 userId = ActivityManager.getCurrentUser(); 2627 } 2628 nonpackageUid = -1; 2629 try { 2630 nonpackageUid = Integer.parseInt(packageName); 2631 } catch (NumberFormatException e) { 2632 } 2633 if (nonpackageUid == -1 && packageName.length() > 1 && packageName.charAt(0) == 'u' 2634 && packageName.indexOf('.') < 0) { 2635 int i = 1; 2636 while (i < packageName.length() && packageName.charAt(i) >= '0' 2637 && packageName.charAt(i) <= '9') { 2638 i++; 2639 } 2640 if (i > 1 && i < packageName.length()) { 2641 String userStr = packageName.substring(1, i); 2642 try { 2643 int user = Integer.parseInt(userStr); 2644 char type = packageName.charAt(i); 2645 i++; 2646 int startTypeVal = i; 2647 while (i < packageName.length() && packageName.charAt(i) >= '0' 2648 && packageName.charAt(i) <= '9') { 2649 i++; 2650 } 2651 if (i > startTypeVal) { 2652 String typeValStr = packageName.substring(startTypeVal, i); 2653 try { 2654 int typeVal = Integer.parseInt(typeValStr); 2655 if (type == 'a') { 2656 nonpackageUid = UserHandle.getUid(user, 2657 typeVal + Process.FIRST_APPLICATION_UID); 2658 } else if (type == 's') { 2659 nonpackageUid = UserHandle.getUid(user, typeVal); 2660 } 2661 } catch (NumberFormatException e) { 2662 } 2663 } 2664 } catch (NumberFormatException e) { 2665 } 2666 } 2667 } 2668 if (nonpackageUid != -1) { 2669 packageName = null; 2670 } else { 2671 packageUid = resolveUid(packageName); 2672 if (packageUid < 0) { 2673 packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, 2674 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); 2675 } 2676 if (packageUid < 0) { 2677 err.println("Error: No UID for " + packageName + " in user " + userId); 2678 return -1; 2679 } 2680 } 2681 return 0; 2682 } 2683 } 2684 onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)2685 @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, 2686 FileDescriptor err, String[] args, ShellCallback callback, 2687 ResultReceiver resultReceiver) { 2688 (new Shell(this, this)).exec(this, in, out, err, args, callback, resultReceiver); 2689 } 2690 dumpCommandHelp(PrintWriter pw)2691 static void dumpCommandHelp(PrintWriter pw) { 2692 pw.println("AppOps service (appops) commands:"); 2693 pw.println(" help"); 2694 pw.println(" Print this help text."); 2695 pw.println(" start [--user <USER_ID>] <PACKAGE | UID> <OP> "); 2696 pw.println(" Starts a given operation for a particular application."); 2697 pw.println(" stop [--user <USER_ID>] <PACKAGE | UID> <OP> "); 2698 pw.println(" Stops a given operation for a particular application."); 2699 pw.println(" set [--user <USER_ID>] <PACKAGE | UID> <OP> <MODE>"); 2700 pw.println(" Set the mode for a particular application and operation."); 2701 pw.println(" get [--user <USER_ID>] <PACKAGE | UID> [<OP>]"); 2702 pw.println(" Return the mode for a particular application and optional operation."); 2703 pw.println(" query-op [--user <USER_ID>] <OP> [<MODE>]"); 2704 pw.println(" Print all packages that currently have the given op in the given mode."); 2705 pw.println(" reset [--user <USER_ID>] [<PACKAGE>]"); 2706 pw.println(" Reset the given application or all applications to default modes."); 2707 pw.println(" write-settings"); 2708 pw.println(" Immediately write pending changes to storage."); 2709 pw.println(" read-settings"); 2710 pw.println(" Read the last written settings, replacing current state in RAM."); 2711 pw.println(" options:"); 2712 pw.println(" <PACKAGE> an Android package name."); 2713 pw.println(" <OP> an AppOps operation."); 2714 pw.println(" <MODE> one of allow, ignore, deny, or default"); 2715 pw.println(" <USER_ID> the user id under which the package is installed. If --user is not"); 2716 pw.println(" specified, the current user is assumed."); 2717 } 2718 onShellCommand(Shell shell, String cmd)2719 static int onShellCommand(Shell shell, String cmd) { 2720 if (cmd == null) { 2721 return shell.handleDefaultCommands(cmd); 2722 } 2723 PrintWriter pw = shell.getOutPrintWriter(); 2724 PrintWriter err = shell.getErrPrintWriter(); 2725 try { 2726 switch (cmd) { 2727 case "set": { 2728 int res = shell.parseUserPackageOp(true, err); 2729 if (res < 0) { 2730 return res; 2731 } 2732 String modeStr = shell.getNextArg(); 2733 if (modeStr == null) { 2734 err.println("Error: Mode not specified."); 2735 return -1; 2736 } 2737 2738 final int mode = shell.strModeToMode(modeStr, err); 2739 if (mode < 0) { 2740 return -1; 2741 } 2742 2743 if (shell.packageName != null) { 2744 shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName, 2745 mode); 2746 } else { 2747 shell.mInterface.setUidMode(shell.op, shell.nonpackageUid, mode); 2748 } 2749 return 0; 2750 } 2751 case "get": { 2752 int res = shell.parseUserPackageOp(false, err); 2753 if (res < 0) { 2754 return res; 2755 } 2756 2757 List<AppOpsManager.PackageOps> ops; 2758 if (shell.packageName != null) { 2759 ops = shell.mInterface.getOpsForPackage( 2760 shell.packageUid, shell.packageName, 2761 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); 2762 } else { 2763 ops = shell.mInterface.getUidOps( 2764 shell.nonpackageUid, 2765 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); 2766 } 2767 if (ops == null || ops.size() <= 0) { 2768 pw.println("No operations."); 2769 if (shell.op > AppOpsManager.OP_NONE && shell.op < AppOpsManager._NUM_OP) { 2770 pw.println("Default mode: " + AppOpsManager.modeToName( 2771 AppOpsManager.opToDefaultMode(shell.op))); 2772 } 2773 return 0; 2774 } 2775 final long now = System.currentTimeMillis(); 2776 for (int i=0; i<ops.size(); i++) { 2777 List<AppOpsManager.OpEntry> entries = ops.get(i).getOps(); 2778 for (int j=0; j<entries.size(); j++) { 2779 AppOpsManager.OpEntry ent = entries.get(j); 2780 pw.print(AppOpsManager.opToName(ent.getOp())); 2781 pw.print(": "); 2782 pw.print(AppOpsManager.modeToName(ent.getMode())); 2783 if (ent.getTime() != 0) { 2784 pw.print("; time="); 2785 TimeUtils.formatDuration(now - ent.getTime(), pw); 2786 pw.print(" ago"); 2787 } 2788 if (ent.getRejectTime() != 0) { 2789 pw.print("; rejectTime="); 2790 TimeUtils.formatDuration(now - ent.getRejectTime(), pw); 2791 pw.print(" ago"); 2792 } 2793 if (ent.getDuration() == -1) { 2794 pw.print(" (running)"); 2795 } else if (ent.getDuration() != 0) { 2796 pw.print("; duration="); 2797 TimeUtils.formatDuration(ent.getDuration(), pw); 2798 } 2799 pw.println(); 2800 } 2801 } 2802 return 0; 2803 } 2804 case "query-op": { 2805 int res = shell.parseUserOpMode(AppOpsManager.MODE_IGNORED, err); 2806 if (res < 0) { 2807 return res; 2808 } 2809 List<AppOpsManager.PackageOps> ops = shell.mInterface.getPackagesForOps( 2810 new int[] {shell.op}); 2811 if (ops == null || ops.size() <= 0) { 2812 pw.println("No operations."); 2813 return 0; 2814 } 2815 for (int i=0; i<ops.size(); i++) { 2816 final AppOpsManager.PackageOps pkg = ops.get(i); 2817 boolean hasMatch = false; 2818 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps(); 2819 for (int j=0; j<entries.size(); j++) { 2820 AppOpsManager.OpEntry ent = entries.get(j); 2821 if (ent.getOp() == shell.op && ent.getMode() == shell.mode) { 2822 hasMatch = true; 2823 break; 2824 } 2825 } 2826 if (hasMatch) { 2827 pw.println(pkg.getPackageName()); 2828 } 2829 } 2830 return 0; 2831 } 2832 case "reset": { 2833 String packageName = null; 2834 int userId = UserHandle.USER_CURRENT; 2835 for (String argument; (argument = shell.getNextArg()) != null;) { 2836 if ("--user".equals(argument)) { 2837 String userStr = shell.getNextArgRequired(); 2838 userId = UserHandle.parseUserArg(userStr); 2839 } else { 2840 if (packageName == null) { 2841 packageName = argument; 2842 } else { 2843 err.println("Error: Unsupported argument: " + argument); 2844 return -1; 2845 } 2846 } 2847 } 2848 2849 if (userId == UserHandle.USER_CURRENT) { 2850 userId = ActivityManager.getCurrentUser(); 2851 } 2852 2853 shell.mInterface.resetAllModes(userId, packageName); 2854 pw.print("Reset all modes for: "); 2855 if (userId == UserHandle.USER_ALL) { 2856 pw.print("all users"); 2857 } else { 2858 pw.print("user "); pw.print(userId); 2859 } 2860 pw.print(", "); 2861 if (packageName == null) { 2862 pw.println("all packages"); 2863 } else { 2864 pw.print("package "); pw.println(packageName); 2865 } 2866 return 0; 2867 } 2868 case "write-settings": { 2869 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(), 2870 Binder.getCallingUid(), -1); 2871 long token = Binder.clearCallingIdentity(); 2872 try { 2873 synchronized (shell.mInternal) { 2874 shell.mInternal.mHandler.removeCallbacks(shell.mInternal.mWriteRunner); 2875 } 2876 shell.mInternal.writeState(); 2877 pw.println("Current settings written."); 2878 } finally { 2879 Binder.restoreCallingIdentity(token); 2880 } 2881 return 0; 2882 } 2883 case "read-settings": { 2884 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(), 2885 Binder.getCallingUid(), -1); 2886 long token = Binder.clearCallingIdentity(); 2887 try { 2888 shell.mInternal.readState(); 2889 pw.println("Last settings read."); 2890 } finally { 2891 Binder.restoreCallingIdentity(token); 2892 } 2893 return 0; 2894 } 2895 case "start": { 2896 int res = shell.parseUserPackageOp(true, err); 2897 if (res < 0) { 2898 return res; 2899 } 2900 2901 if (shell.packageName != null) { 2902 shell.mInterface.startOperation(shell.mToken, 2903 shell.op, shell.packageUid, shell.packageName, true); 2904 } else { 2905 return -1; 2906 } 2907 return 0; 2908 } 2909 case "stop": { 2910 int res = shell.parseUserPackageOp(true, err); 2911 if (res < 0) { 2912 return res; 2913 } 2914 2915 if (shell.packageName != null) { 2916 shell.mInterface.finishOperation(shell.mToken, 2917 shell.op, shell.packageUid, shell.packageName); 2918 } else { 2919 return -1; 2920 } 2921 return 0; 2922 } 2923 default: 2924 return shell.handleDefaultCommands(cmd); 2925 } 2926 } catch (RemoteException e) { 2927 pw.println("Remote exception: " + e); 2928 } 2929 return -1; 2930 } 2931 dumpHelp(PrintWriter pw)2932 private void dumpHelp(PrintWriter pw) { 2933 pw.println("AppOps service (appops) dump options:"); 2934 pw.println(" -h"); 2935 pw.println(" Print this help text."); 2936 pw.println(" --op [OP]"); 2937 pw.println(" Limit output to data associated with the given app op code."); 2938 pw.println(" --mode [MODE]"); 2939 pw.println(" Limit output to data associated with the given app op mode."); 2940 pw.println(" --package [PACKAGE]"); 2941 pw.println(" Limit output to data associated with the given package name."); 2942 } 2943 dumpTimesLocked(PrintWriter pw, String firstPrefix, String prefix, long[] times, long now, SimpleDateFormat sdf, Date date)2944 private void dumpTimesLocked(PrintWriter pw, String firstPrefix, String prefix, long[] times, 2945 long now, SimpleDateFormat sdf, Date date) { 2946 boolean hasTime = false; 2947 for (int i = 0; i < _NUM_UID_STATE; i++) { 2948 if (times[i] != 0) { 2949 hasTime = true; 2950 break; 2951 } 2952 } 2953 if (!hasTime) { 2954 return; 2955 } 2956 boolean first = true; 2957 for (int i = 0; i < _NUM_UID_STATE; i++) { 2958 if (times[i] != 0) { 2959 pw.print(first ? firstPrefix : prefix); 2960 first = false; 2961 pw.print(UID_STATE_NAMES[i]); 2962 pw.print(" = "); 2963 date.setTime(times[i]); 2964 pw.print(sdf.format(date)); 2965 pw.print(" ("); 2966 TimeUtils.formatDuration(times[i]-now, pw); 2967 pw.println(")"); 2968 } 2969 } 2970 } 2971 2972 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)2973 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2974 if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; 2975 2976 int dumpOp = -1; 2977 String dumpPackage = null; 2978 int dumpUid = -1; 2979 int dumpMode = -1; 2980 2981 if (args != null) { 2982 for (int i=0; i<args.length; i++) { 2983 String arg = args[i]; 2984 if ("-h".equals(arg)) { 2985 dumpHelp(pw); 2986 return; 2987 } else if ("-a".equals(arg)) { 2988 // dump all data 2989 } else if ("--op".equals(arg)) { 2990 i++; 2991 if (i >= args.length) { 2992 pw.println("No argument for --op option"); 2993 return; 2994 } 2995 dumpOp = Shell.strOpToOp(args[i], pw); 2996 if (dumpOp < 0) { 2997 return; 2998 } 2999 } else if ("--package".equals(arg)) { 3000 i++; 3001 if (i >= args.length) { 3002 pw.println("No argument for --package option"); 3003 return; 3004 } 3005 dumpPackage = args[i]; 3006 try { 3007 dumpUid = AppGlobals.getPackageManager().getPackageUid(dumpPackage, 3008 PackageManager.MATCH_KNOWN_PACKAGES | PackageManager.MATCH_INSTANT, 3009 0); 3010 } catch (RemoteException e) { 3011 } 3012 if (dumpUid < 0) { 3013 pw.println("Unknown package: " + dumpPackage); 3014 return; 3015 } 3016 dumpUid = UserHandle.getAppId(dumpUid); 3017 } else if ("--mode".equals(arg)) { 3018 i++; 3019 if (i >= args.length) { 3020 pw.println("No argument for --mode option"); 3021 return; 3022 } 3023 dumpMode = Shell.strModeToMode(args[i], pw); 3024 if (dumpMode < 0) { 3025 return; 3026 } 3027 } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 3028 pw.println("Unknown option: " + arg); 3029 return; 3030 } else { 3031 pw.println("Unknown command: " + arg); 3032 return; 3033 } 3034 } 3035 } 3036 3037 synchronized (this) { 3038 pw.println("Current AppOps Service state:"); 3039 mConstants.dump(pw); 3040 pw.println(); 3041 final long now = System.currentTimeMillis(); 3042 final long nowElapsed = SystemClock.elapsedRealtime(); 3043 final long nowUptime = SystemClock.uptimeMillis(); 3044 final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 3045 final Date date = new Date(); 3046 boolean needSep = false; 3047 if (dumpOp < 0 && dumpMode < 0 && dumpPackage == null && mProfileOwners != null) { 3048 pw.println(" Profile owners:"); 3049 for (int poi = 0; poi < mProfileOwners.size(); poi++) { 3050 pw.print(" User #"); 3051 pw.print(mProfileOwners.keyAt(poi)); 3052 pw.print(": "); 3053 UserHandle.formatUid(pw, mProfileOwners.valueAt(poi)); 3054 pw.println(); 3055 } 3056 pw.println(); 3057 } 3058 if (mOpModeWatchers.size() > 0) { 3059 boolean printedHeader = false; 3060 for (int i=0; i<mOpModeWatchers.size(); i++) { 3061 if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) { 3062 continue; 3063 } 3064 boolean printedOpHeader = false; 3065 ArraySet<ModeCallback> callbacks = mOpModeWatchers.valueAt(i); 3066 for (int j=0; j<callbacks.size(); j++) { 3067 final ModeCallback cb = callbacks.valueAt(j); 3068 if (dumpPackage != null && cb.mWatchingUid >= 0 3069 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 3070 continue; 3071 } 3072 needSep = true; 3073 if (!printedHeader) { 3074 pw.println(" Op mode watchers:"); 3075 printedHeader = true; 3076 } 3077 if (!printedOpHeader) { 3078 pw.print(" Op "); 3079 pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i))); 3080 pw.println(":"); 3081 printedOpHeader = true; 3082 } 3083 pw.print(" #"); pw.print(j); pw.print(": "); 3084 pw.println(cb); 3085 } 3086 } 3087 } 3088 if (mPackageModeWatchers.size() > 0 && dumpOp < 0) { 3089 boolean printedHeader = false; 3090 for (int i=0; i<mPackageModeWatchers.size(); i++) { 3091 if (dumpPackage != null && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) { 3092 continue; 3093 } 3094 needSep = true; 3095 if (!printedHeader) { 3096 pw.println(" Package mode watchers:"); 3097 printedHeader = true; 3098 } 3099 pw.print(" Pkg "); pw.print(mPackageModeWatchers.keyAt(i)); 3100 pw.println(":"); 3101 ArraySet<ModeCallback> callbacks = mPackageModeWatchers.valueAt(i); 3102 for (int j=0; j<callbacks.size(); j++) { 3103 pw.print(" #"); pw.print(j); pw.print(": "); 3104 pw.println(callbacks.valueAt(j)); 3105 } 3106 } 3107 } 3108 if (mModeWatchers.size() > 0 && dumpOp < 0) { 3109 boolean printedHeader = false; 3110 for (int i=0; i<mModeWatchers.size(); i++) { 3111 final ModeCallback cb = mModeWatchers.valueAt(i); 3112 if (dumpPackage != null && cb.mWatchingUid >= 0 3113 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 3114 continue; 3115 } 3116 needSep = true; 3117 if (!printedHeader) { 3118 pw.println(" All op mode watchers:"); 3119 printedHeader = true; 3120 } 3121 pw.print(" "); 3122 pw.print(Integer.toHexString(System.identityHashCode(mModeWatchers.keyAt(i)))); 3123 pw.print(": "); pw.println(cb); 3124 } 3125 } 3126 if (mActiveWatchers.size() > 0 && dumpMode < 0) { 3127 needSep = true; 3128 boolean printedHeader = false; 3129 for (int i = 0; i < mActiveWatchers.size(); i++) { 3130 final SparseArray<ActiveCallback> activeWatchers = mActiveWatchers.valueAt(i); 3131 if (activeWatchers.size() <= 0) { 3132 continue; 3133 } 3134 final ActiveCallback cb = activeWatchers.valueAt(0); 3135 if (dumpOp >= 0 && activeWatchers.indexOfKey(dumpOp) < 0) { 3136 continue; 3137 } 3138 if (dumpPackage != null && cb.mWatchingUid >= 0 3139 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 3140 continue; 3141 } 3142 if (!printedHeader) { 3143 pw.println(" All op active watchers:"); 3144 printedHeader = true; 3145 } 3146 pw.print(" "); 3147 pw.print(Integer.toHexString(System.identityHashCode( 3148 mActiveWatchers.keyAt(i)))); 3149 pw.println(" ->"); 3150 pw.print(" ["); 3151 final int opCount = activeWatchers.size(); 3152 for (i = 0; i < opCount; i++) { 3153 if (i > 0) { 3154 pw.print(' '); 3155 } 3156 pw.print(AppOpsManager.opToName(activeWatchers.keyAt(i))); 3157 if (i < opCount - 1) { 3158 pw.print(','); 3159 } 3160 } 3161 pw.println("]"); 3162 pw.print(" "); 3163 pw.println(cb); 3164 } 3165 } 3166 if (mClients.size() > 0 && dumpMode < 0) { 3167 needSep = true; 3168 boolean printedHeader = false; 3169 for (int i=0; i<mClients.size(); i++) { 3170 boolean printedClient = false; 3171 ClientState cs = mClients.valueAt(i); 3172 if (cs.mStartedOps.size() > 0) { 3173 boolean printedStarted = false; 3174 for (int j=0; j<cs.mStartedOps.size(); j++) { 3175 Op op = cs.mStartedOps.get(j); 3176 if (dumpOp >= 0 && op.op != dumpOp) { 3177 continue; 3178 } 3179 if (dumpPackage != null && !dumpPackage.equals(op.packageName)) { 3180 continue; 3181 } 3182 if (!printedHeader) { 3183 pw.println(" Clients:"); 3184 printedHeader = true; 3185 } 3186 if (!printedClient) { 3187 pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":"); 3188 pw.print(" "); pw.println(cs); 3189 printedClient = true; 3190 } 3191 if (!printedStarted) { 3192 pw.println(" Started ops:"); 3193 printedStarted = true; 3194 } 3195 pw.print(" "); pw.print("uid="); pw.print(op.uid); 3196 pw.print(" pkg="); pw.print(op.packageName); 3197 pw.print(" op="); pw.println(AppOpsManager.opToName(op.op)); 3198 } 3199 } 3200 } 3201 } 3202 if (mAudioRestrictions.size() > 0 && dumpOp < 0 && dumpPackage != null 3203 && dumpMode < 0) { 3204 boolean printedHeader = false; 3205 for (int o=0; o<mAudioRestrictions.size(); o++) { 3206 final String op = AppOpsManager.opToName(mAudioRestrictions.keyAt(o)); 3207 final SparseArray<Restriction> restrictions = mAudioRestrictions.valueAt(o); 3208 for (int i=0; i<restrictions.size(); i++) { 3209 if (!printedHeader){ 3210 pw.println(" Audio Restrictions:"); 3211 printedHeader = true; 3212 needSep = true; 3213 } 3214 final int usage = restrictions.keyAt(i); 3215 pw.print(" "); pw.print(op); 3216 pw.print(" usage="); pw.print(AudioAttributes.usageToString(usage)); 3217 Restriction r = restrictions.valueAt(i); 3218 pw.print(": mode="); pw.println(AppOpsManager.modeToName(r.mode)); 3219 if (!r.exceptionPackages.isEmpty()) { 3220 pw.println(" Exceptions:"); 3221 for (int j=0; j<r.exceptionPackages.size(); j++) { 3222 pw.print(" "); pw.println(r.exceptionPackages.valueAt(j)); 3223 } 3224 } 3225 } 3226 } 3227 } 3228 if (needSep) { 3229 pw.println(); 3230 } 3231 for (int i=0; i<mUidStates.size(); i++) { 3232 UidState uidState = mUidStates.valueAt(i); 3233 final SparseIntArray opModes = uidState.opModes; 3234 final ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 3235 3236 if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) { 3237 boolean hasOp = dumpOp < 0 || (uidState.opModes != null 3238 && uidState.opModes.indexOfKey(dumpOp) >= 0); 3239 boolean hasPackage = dumpPackage == null; 3240 boolean hasMode = dumpMode < 0; 3241 if (!hasMode && opModes != null) { 3242 for (int opi = 0; !hasMode && opi < opModes.size(); opi++) { 3243 if (opModes.valueAt(opi) == dumpMode) { 3244 hasMode = true; 3245 } 3246 } 3247 } 3248 if (pkgOps != null) { 3249 for (int pkgi = 0; 3250 (!hasOp || !hasPackage || !hasMode) && pkgi < pkgOps.size(); 3251 pkgi++) { 3252 Ops ops = pkgOps.valueAt(pkgi); 3253 if (!hasOp && ops != null && ops.indexOfKey(dumpOp) >= 0) { 3254 hasOp = true; 3255 } 3256 if (!hasMode) { 3257 for (int opi = 0; !hasMode && opi < ops.size(); opi++) { 3258 if (ops.valueAt(opi).mode == dumpMode) { 3259 hasMode = true; 3260 } 3261 } 3262 } 3263 if (!hasPackage && dumpPackage.equals(ops.packageName)) { 3264 hasPackage = true; 3265 } 3266 } 3267 } 3268 if (uidState.foregroundOps != null && !hasOp) { 3269 if (uidState.foregroundOps.indexOfKey(dumpOp) > 0) { 3270 hasOp = true; 3271 } 3272 } 3273 if (!hasOp || !hasPackage || !hasMode) { 3274 continue; 3275 } 3276 } 3277 3278 pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":"); 3279 pw.print(" state="); 3280 pw.println(UID_STATE_NAMES[uidState.state]); 3281 if (uidState.state != uidState.pendingState) { 3282 pw.print(" pendingState="); 3283 pw.println(UID_STATE_NAMES[uidState.pendingState]); 3284 } 3285 if (uidState.pendingStateCommitTime != 0) { 3286 pw.print(" pendingStateCommitTime="); 3287 TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowUptime, pw); 3288 pw.println(); 3289 } 3290 if (uidState.startNesting != 0) { 3291 pw.print(" startNesting="); 3292 pw.println(uidState.startNesting); 3293 } 3294 if (uidState.foregroundOps != null && (dumpMode < 0 3295 || dumpMode == AppOpsManager.MODE_FOREGROUND)) { 3296 pw.println(" foregroundOps:"); 3297 for (int j = 0; j < uidState.foregroundOps.size(); j++) { 3298 if (dumpOp >= 0 && dumpOp != uidState.foregroundOps.keyAt(j)) { 3299 continue; 3300 } 3301 pw.print(" "); 3302 pw.print(AppOpsManager.opToName(uidState.foregroundOps.keyAt(j))); 3303 pw.print(": "); 3304 pw.println(uidState.foregroundOps.valueAt(j) ? "WATCHER" : "SILENT"); 3305 } 3306 pw.print(" hasForegroundWatchers="); 3307 pw.println(uidState.hasForegroundWatchers); 3308 } 3309 needSep = true; 3310 3311 if (opModes != null) { 3312 final int opModeCount = opModes.size(); 3313 for (int j = 0; j < opModeCount; j++) { 3314 final int code = opModes.keyAt(j); 3315 final int mode = opModes.valueAt(j); 3316 if (dumpOp >= 0 && dumpOp != code) { 3317 continue; 3318 } 3319 if (dumpMode >= 0 && dumpMode != mode) { 3320 continue; 3321 } 3322 pw.print(" "); pw.print(AppOpsManager.opToName(code)); 3323 pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode)); 3324 } 3325 } 3326 3327 if (pkgOps == null) { 3328 continue; 3329 } 3330 3331 for (int pkgi = 0; pkgi < pkgOps.size(); pkgi++) { 3332 final Ops ops = pkgOps.valueAt(pkgi); 3333 if (dumpPackage != null && !dumpPackage.equals(ops.packageName)) { 3334 continue; 3335 } 3336 boolean printedPackage = false; 3337 for (int j=0; j<ops.size(); j++) { 3338 final Op op = ops.valueAt(j); 3339 if (dumpOp >= 0 && dumpOp != op.op) { 3340 continue; 3341 } 3342 if (dumpMode >= 0 && dumpMode != op.mode) { 3343 continue; 3344 } 3345 if (!printedPackage) { 3346 pw.print(" Package "); pw.print(ops.packageName); pw.println(":"); 3347 printedPackage = true; 3348 } 3349 pw.print(" "); pw.print(AppOpsManager.opToName(op.op)); 3350 pw.print(" ("); pw.print(AppOpsManager.modeToName(op.mode)); 3351 final int switchOp = AppOpsManager.opToSwitch(op.op); 3352 if (switchOp != op.op) { 3353 pw.print(" / switch "); 3354 pw.print(AppOpsManager.opToName(switchOp)); 3355 final Op switchObj = ops.get(switchOp); 3356 int mode = switchObj != null 3357 ? switchObj.mode : AppOpsManager.opToDefaultMode(switchOp); 3358 pw.print("="); pw.print(AppOpsManager.modeToName(mode)); 3359 } 3360 pw.println("): "); 3361 dumpTimesLocked(pw, 3362 " Access: ", 3363 " ", op.time, now, sdf, date); 3364 dumpTimesLocked(pw, 3365 " Reject: ", 3366 " ", op.rejectTime, now, sdf, date); 3367 if (op.duration == -1) { 3368 pw.print(" Running start at: "); 3369 TimeUtils.formatDuration(nowElapsed-op.startRealtime, pw); 3370 pw.println(); 3371 } else if (op.duration != 0) { 3372 pw.print(" duration="); 3373 TimeUtils.formatDuration(op.duration, pw); 3374 pw.println(); 3375 } 3376 if (op.startNesting != 0) { 3377 pw.print(" startNesting="); 3378 pw.println(op.startNesting); 3379 } 3380 } 3381 } 3382 } 3383 if (needSep) { 3384 pw.println(); 3385 } 3386 3387 final int userRestrictionCount = mOpUserRestrictions.size(); 3388 for (int i = 0; i < userRestrictionCount; i++) { 3389 IBinder token = mOpUserRestrictions.keyAt(i); 3390 ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); 3391 pw.println(" User restrictions for token " + token + ":"); 3392 3393 final int restrictionCount = restrictionState.perUserRestrictions != null 3394 ? restrictionState.perUserRestrictions.size() : 0; 3395 if (restrictionCount > 0) { 3396 pw.println(" Restricted ops:"); 3397 for (int j = 0; j < restrictionCount; j++) { 3398 int userId = restrictionState.perUserRestrictions.keyAt(j); 3399 boolean[] restrictedOps = restrictionState.perUserRestrictions.valueAt(j); 3400 if (restrictedOps == null) { 3401 continue; 3402 } 3403 StringBuilder restrictedOpsValue = new StringBuilder(); 3404 restrictedOpsValue.append("["); 3405 final int restrictedOpCount = restrictedOps.length; 3406 for (int k = 0; k < restrictedOpCount; k++) { 3407 if (restrictedOps[k]) { 3408 if (restrictedOpsValue.length() > 1) { 3409 restrictedOpsValue.append(", "); 3410 } 3411 restrictedOpsValue.append(AppOpsManager.opToName(k)); 3412 } 3413 } 3414 restrictedOpsValue.append("]"); 3415 pw.print(" "); pw.print("user: "); pw.print(userId); 3416 pw.print(" restricted ops: "); pw.println(restrictedOpsValue); 3417 } 3418 } 3419 3420 final int excludedPackageCount = restrictionState.perUserExcludedPackages != null 3421 ? restrictionState.perUserExcludedPackages.size() : 0; 3422 if (excludedPackageCount > 0) { 3423 pw.println(" Excluded packages:"); 3424 for (int j = 0; j < excludedPackageCount; j++) { 3425 int userId = restrictionState.perUserExcludedPackages.keyAt(j); 3426 String[] packageNames = restrictionState.perUserExcludedPackages.valueAt(j); 3427 pw.print(" "); pw.print("user: "); pw.print(userId); 3428 pw.print(" packages: "); pw.println(Arrays.toString(packageNames)); 3429 } 3430 } 3431 } 3432 } 3433 } 3434 3435 private static final class Restriction { 3436 private static final ArraySet<String> NO_EXCEPTIONS = new ArraySet<String>(); 3437 int mode; 3438 ArraySet<String> exceptionPackages = NO_EXCEPTIONS; 3439 } 3440 3441 @Override 3442 public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) { 3443 checkSystemUid("setUserRestrictions"); 3444 Preconditions.checkNotNull(restrictions); 3445 Preconditions.checkNotNull(token); 3446 for (int i = 0; i < AppOpsManager._NUM_OP; i++) { 3447 String restriction = AppOpsManager.opToRestriction(i); 3448 if (restriction != null) { 3449 setUserRestrictionNoCheck(i, restrictions.getBoolean(restriction, false), token, 3450 userHandle, null); 3451 } 3452 } 3453 } 3454 3455 @Override 3456 public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, 3457 String[] exceptionPackages) { 3458 if (Binder.getCallingPid() != Process.myPid()) { 3459 mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS, 3460 Binder.getCallingPid(), Binder.getCallingUid(), null); 3461 } 3462 if (userHandle != UserHandle.getCallingUserId()) { 3463 if (mContext.checkCallingOrSelfPermission(Manifest.permission 3464 .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED 3465 && mContext.checkCallingOrSelfPermission(Manifest.permission 3466 .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) { 3467 throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or" 3468 + " INTERACT_ACROSS_USERS to interact cross user "); 3469 } 3470 } 3471 verifyIncomingOp(code); 3472 Preconditions.checkNotNull(token); 3473 setUserRestrictionNoCheck(code, restricted, token, userHandle, exceptionPackages); 3474 } 3475 3476 private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token, 3477 int userHandle, String[] exceptionPackages) { 3478 synchronized (AppOpsService.this) { 3479 ClientRestrictionState restrictionState = mOpUserRestrictions.get(token); 3480 3481 if (restrictionState == null) { 3482 try { 3483 restrictionState = new ClientRestrictionState(token); 3484 } catch (RemoteException e) { 3485 return; 3486 } 3487 mOpUserRestrictions.put(token, restrictionState); 3488 } 3489 3490 if (restrictionState.setRestriction(code, restricted, exceptionPackages, userHandle)) { 3491 mHandler.sendMessage(PooledLambda.obtainMessage( 3492 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY)); 3493 } 3494 3495 if (restrictionState.isDefault()) { 3496 mOpUserRestrictions.remove(token); 3497 restrictionState.destroy(); 3498 } 3499 } 3500 } 3501 3502 private void notifyWatchersOfChange(int code, int uid) { 3503 final ArraySet<ModeCallback> clonedCallbacks; 3504 synchronized (this) { 3505 ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code); 3506 if (callbacks == null) { 3507 return; 3508 } 3509 clonedCallbacks = new ArraySet<>(callbacks); 3510 } 3511 3512 notifyOpChanged(clonedCallbacks, code, uid, null); 3513 } 3514 3515 @Override 3516 public void removeUser(int userHandle) throws RemoteException { 3517 checkSystemUid("removeUser"); 3518 synchronized (AppOpsService.this) { 3519 final int tokenCount = mOpUserRestrictions.size(); 3520 for (int i = tokenCount - 1; i >= 0; i--) { 3521 ClientRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i); 3522 opRestrictions.removeUser(userHandle); 3523 } 3524 removeUidsForUserLocked(userHandle); 3525 } 3526 } 3527 3528 @Override 3529 public boolean isOperationActive(int code, int uid, String packageName) { 3530 if (Binder.getCallingUid() != uid) { 3531 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 3532 != PackageManager.PERMISSION_GRANTED) { 3533 return false; 3534 } 3535 } 3536 verifyIncomingOp(code); 3537 final String resolvedPackageName = resolvePackageName(uid, packageName); 3538 if (resolvedPackageName == null) { 3539 return false; 3540 } 3541 synchronized (AppOpsService.this) { 3542 for (int i = mClients.size() - 1; i >= 0; i--) { 3543 final ClientState client = mClients.valueAt(i); 3544 for (int j = client.mStartedOps.size() - 1; j >= 0; j--) { 3545 final Op op = client.mStartedOps.get(j); 3546 if (op.op == code && op.uid == uid) return true; 3547 } 3548 } 3549 } 3550 return false; 3551 } 3552 3553 private void removeUidsForUserLocked(int userHandle) { 3554 for (int i = mUidStates.size() - 1; i >= 0; --i) { 3555 final int uid = mUidStates.keyAt(i); 3556 if (UserHandle.getUserId(uid) == userHandle) { 3557 mUidStates.removeAt(i); 3558 } 3559 } 3560 } 3561 checkSystemUid(String function)3562 private void checkSystemUid(String function) { 3563 int uid = Binder.getCallingUid(); 3564 if (uid != Process.SYSTEM_UID) { 3565 throw new SecurityException(function + " must by called by the system"); 3566 } 3567 } 3568 resolvePackageName(int uid, String packageName)3569 private static String resolvePackageName(int uid, String packageName) { 3570 if (uid == Process.ROOT_UID) { 3571 return "root"; 3572 } else if (uid == Process.SHELL_UID) { 3573 return "com.android.shell"; 3574 } else if (uid == Process.MEDIA_UID) { 3575 return "media"; 3576 } else if (uid == Process.AUDIOSERVER_UID) { 3577 return "audioserver"; 3578 } else if (uid == Process.CAMERASERVER_UID) { 3579 return "cameraserver"; 3580 } else if (uid == Process.SYSTEM_UID && packageName == null) { 3581 return "android"; 3582 } 3583 return packageName; 3584 } 3585 resolveUid(String packageName)3586 private static int resolveUid(String packageName) { 3587 if (packageName == null) { 3588 return -1; 3589 } 3590 switch (packageName) { 3591 case "root": 3592 return Process.ROOT_UID; 3593 case "shell": 3594 return Process.SHELL_UID; 3595 case "media": 3596 return Process.MEDIA_UID; 3597 case "audioserver": 3598 return Process.AUDIOSERVER_UID; 3599 case "cameraserver": 3600 return Process.CAMERASERVER_UID; 3601 } 3602 return -1; 3603 } 3604 getPackagesForUid(int uid)3605 private static String[] getPackagesForUid(int uid) { 3606 String[] packageNames = null; 3607 try { 3608 packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid); 3609 } catch (RemoteException e) { 3610 /* ignore - local call */ 3611 } 3612 if (packageNames == null) { 3613 return EmptyArray.STRING; 3614 } 3615 return packageNames; 3616 } 3617 3618 private final class ClientRestrictionState implements DeathRecipient { 3619 private final IBinder token; 3620 SparseArray<boolean[]> perUserRestrictions; 3621 SparseArray<String[]> perUserExcludedPackages; 3622 ClientRestrictionState(IBinder token)3623 public ClientRestrictionState(IBinder token) 3624 throws RemoteException { 3625 token.linkToDeath(this, 0); 3626 this.token = token; 3627 } 3628 setRestriction(int code, boolean restricted, String[] excludedPackages, int userId)3629 public boolean setRestriction(int code, boolean restricted, 3630 String[] excludedPackages, int userId) { 3631 boolean changed = false; 3632 3633 if (perUserRestrictions == null && restricted) { 3634 perUserRestrictions = new SparseArray<>(); 3635 } 3636 3637 int[] users; 3638 if (userId == UserHandle.USER_ALL) { 3639 List<UserInfo> liveUsers = UserManager.get(mContext).getUsers(false); 3640 3641 users = new int[liveUsers.size()]; 3642 for (int i = 0; i < liveUsers.size(); i++) { 3643 users[i] = liveUsers.get(i).id; 3644 } 3645 } else { 3646 users = new int[]{userId}; 3647 } 3648 3649 if (perUserRestrictions != null) { 3650 int numUsers = users.length; 3651 3652 for (int i = 0; i < numUsers; i++) { 3653 int thisUserId = users[i]; 3654 3655 boolean[] userRestrictions = perUserRestrictions.get(thisUserId); 3656 if (userRestrictions == null && restricted) { 3657 userRestrictions = new boolean[AppOpsManager._NUM_OP]; 3658 perUserRestrictions.put(thisUserId, userRestrictions); 3659 } 3660 if (userRestrictions != null && userRestrictions[code] != restricted) { 3661 userRestrictions[code] = restricted; 3662 if (!restricted && isDefault(userRestrictions)) { 3663 perUserRestrictions.remove(thisUserId); 3664 userRestrictions = null; 3665 } 3666 changed = true; 3667 } 3668 3669 if (userRestrictions != null) { 3670 final boolean noExcludedPackages = ArrayUtils.isEmpty(excludedPackages); 3671 if (perUserExcludedPackages == null && !noExcludedPackages) { 3672 perUserExcludedPackages = new SparseArray<>(); 3673 } 3674 if (perUserExcludedPackages != null && !Arrays.equals(excludedPackages, 3675 perUserExcludedPackages.get(thisUserId))) { 3676 if (noExcludedPackages) { 3677 perUserExcludedPackages.remove(thisUserId); 3678 if (perUserExcludedPackages.size() <= 0) { 3679 perUserExcludedPackages = null; 3680 } 3681 } else { 3682 perUserExcludedPackages.put(thisUserId, excludedPackages); 3683 } 3684 changed = true; 3685 } 3686 } 3687 } 3688 } 3689 3690 return changed; 3691 } 3692 hasRestriction(int restriction, String packageName, int userId)3693 public boolean hasRestriction(int restriction, String packageName, int userId) { 3694 if (perUserRestrictions == null) { 3695 return false; 3696 } 3697 boolean[] restrictions = perUserRestrictions.get(userId); 3698 if (restrictions == null) { 3699 return false; 3700 } 3701 if (!restrictions[restriction]) { 3702 return false; 3703 } 3704 if (perUserExcludedPackages == null) { 3705 return true; 3706 } 3707 String[] perUserExclusions = perUserExcludedPackages.get(userId); 3708 if (perUserExclusions == null) { 3709 return true; 3710 } 3711 return !ArrayUtils.contains(perUserExclusions, packageName); 3712 } 3713 removeUser(int userId)3714 public void removeUser(int userId) { 3715 if (perUserExcludedPackages != null) { 3716 perUserExcludedPackages.remove(userId); 3717 if (perUserExcludedPackages.size() <= 0) { 3718 perUserExcludedPackages = null; 3719 } 3720 } 3721 if (perUserRestrictions != null) { 3722 perUserRestrictions.remove(userId); 3723 if (perUserRestrictions.size() <= 0) { 3724 perUserRestrictions = null; 3725 } 3726 } 3727 } 3728 isDefault()3729 public boolean isDefault() { 3730 return perUserRestrictions == null || perUserRestrictions.size() <= 0; 3731 } 3732 3733 @Override binderDied()3734 public void binderDied() { 3735 synchronized (AppOpsService.this) { 3736 mOpUserRestrictions.remove(token); 3737 if (perUserRestrictions == null) { 3738 return; 3739 } 3740 final int userCount = perUserRestrictions.size(); 3741 for (int i = 0; i < userCount; i++) { 3742 final boolean[] restrictions = perUserRestrictions.valueAt(i); 3743 final int restrictionCount = restrictions.length; 3744 for (int j = 0; j < restrictionCount; j++) { 3745 if (restrictions[j]) { 3746 final int changedCode = j; 3747 mHandler.post(() -> notifyWatchersOfChange(changedCode, UID_ANY)); 3748 } 3749 } 3750 } 3751 destroy(); 3752 } 3753 } 3754 destroy()3755 public void destroy() { 3756 token.unlinkToDeath(this, 0); 3757 } 3758 isDefault(boolean[] array)3759 private boolean isDefault(boolean[] array) { 3760 if (ArrayUtils.isEmpty(array)) { 3761 return true; 3762 } 3763 for (boolean value : array) { 3764 if (value) { 3765 return false; 3766 } 3767 } 3768 return true; 3769 } 3770 } 3771 3772 private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal { setDeviceAndProfileOwners(SparseIntArray owners)3773 @Override public void setDeviceAndProfileOwners(SparseIntArray owners) { 3774 synchronized (AppOpsService.this) { 3775 mProfileOwners = owners; 3776 } 3777 } 3778 } 3779 } 3780