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.appop; 18 19 import static android.app.AppOpsManager.MAX_PRIORITY_UID_STATE; 20 import static android.app.AppOpsManager.MIN_PRIORITY_UID_STATE; 21 import static android.app.AppOpsManager.OP_CAMERA; 22 import static android.app.AppOpsManager.OP_FLAGS_ALL; 23 import static android.app.AppOpsManager.OP_NONE; 24 import static android.app.AppOpsManager.OP_PLAY_AUDIO; 25 import static android.app.AppOpsManager.OP_RECORD_AUDIO; 26 import static android.app.AppOpsManager.UID_STATE_BACKGROUND; 27 import static android.app.AppOpsManager.UID_STATE_CACHED; 28 import static android.app.AppOpsManager.UID_STATE_FOREGROUND; 29 import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE; 30 import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE_LOCATION; 31 import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED; 32 import static android.app.AppOpsManager.UID_STATE_PERSISTENT; 33 import static android.app.AppOpsManager.UID_STATE_TOP; 34 import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES; 35 import static android.app.AppOpsManager.modeToName; 36 import static android.app.AppOpsManager.opToName; 37 import static android.app.AppOpsManager.resolveFirstUnrestrictedUidState; 38 39 import static java.lang.Long.max; 40 41 import android.Manifest; 42 import android.annotation.NonNull; 43 import android.annotation.Nullable; 44 import android.app.ActivityManager; 45 import android.app.ActivityThread; 46 import android.app.AppGlobals; 47 import android.app.AppOpsManager; 48 import android.app.AppOpsManager.HistoricalOps; 49 import android.app.AppOpsManager.HistoricalOpsRequest; 50 import android.app.AppOpsManager.Mode; 51 import android.app.AppOpsManager.OpEntry; 52 import android.app.AppOpsManager.OpFlags; 53 import android.app.AppOpsManagerInternal; 54 import android.app.AppOpsManagerInternal.CheckOpsDelegate; 55 import android.content.BroadcastReceiver; 56 import android.content.ContentResolver; 57 import android.content.Context; 58 import android.content.Intent; 59 import android.content.IntentFilter; 60 import android.content.pm.ApplicationInfo; 61 import android.content.pm.IPackageManager; 62 import android.content.pm.PackageManager; 63 import android.content.pm.PackageManagerInternal; 64 import android.content.pm.UserInfo; 65 import android.database.ContentObserver; 66 import android.media.AudioAttributes; 67 import android.net.Uri; 68 import android.os.AsyncTask; 69 import android.os.Binder; 70 import android.os.Bundle; 71 import android.os.Handler; 72 import android.os.IBinder; 73 import android.os.Process; 74 import android.os.RemoteCallback; 75 import android.os.RemoteException; 76 import android.os.ResultReceiver; 77 import android.os.ServiceManager; 78 import android.os.ShellCallback; 79 import android.os.ShellCommand; 80 import android.os.SystemClock; 81 import android.os.UserHandle; 82 import android.os.UserManager; 83 import android.os.storage.StorageManager; 84 import android.os.storage.StorageManagerInternal; 85 import android.provider.Settings; 86 import android.util.ArrayMap; 87 import android.util.ArraySet; 88 import android.util.AtomicFile; 89 import android.util.KeyValueListParser; 90 import android.util.LongSparseArray; 91 import android.util.LongSparseLongArray; 92 import android.util.Slog; 93 import android.util.SparseArray; 94 import android.util.SparseBooleanArray; 95 import android.util.SparseIntArray; 96 import android.util.TimeUtils; 97 import android.util.Xml; 98 99 import com.android.internal.annotations.GuardedBy; 100 import com.android.internal.annotations.VisibleForTesting; 101 import com.android.internal.app.IAppOpsActiveCallback; 102 import com.android.internal.app.IAppOpsCallback; 103 import com.android.internal.app.IAppOpsNotedCallback; 104 import com.android.internal.app.IAppOpsService; 105 import com.android.internal.os.Zygote; 106 import com.android.internal.util.ArrayUtils; 107 import com.android.internal.util.DumpUtils; 108 import com.android.internal.util.FastXmlSerializer; 109 import com.android.internal.util.Preconditions; 110 import com.android.internal.util.XmlUtils; 111 import com.android.internal.util.function.pooled.PooledLambda; 112 import com.android.server.LocalServices; 113 import com.android.server.LockGuard; 114 115 import libcore.util.EmptyArray; 116 117 import org.xmlpull.v1.XmlPullParser; 118 import org.xmlpull.v1.XmlPullParserException; 119 import org.xmlpull.v1.XmlSerializer; 120 121 import java.io.File; 122 import java.io.FileDescriptor; 123 import java.io.FileInputStream; 124 import java.io.FileNotFoundException; 125 import java.io.FileOutputStream; 126 import java.io.IOException; 127 import java.io.PrintWriter; 128 import java.nio.charset.StandardCharsets; 129 import java.text.SimpleDateFormat; 130 import java.util.ArrayList; 131 import java.util.Arrays; 132 import java.util.Collections; 133 import java.util.Date; 134 import java.util.HashMap; 135 import java.util.Iterator; 136 import java.util.List; 137 import java.util.Map; 138 139 public class AppOpsService extends IAppOpsService.Stub { 140 static final String TAG = "AppOps"; 141 static final boolean DEBUG = false; 142 143 private static final int NO_VERSION = -1; 144 /** Increment by one every time and add the corresponding upgrade logic in 145 * {@link #upgradeLocked(int)} below. The first version was 1 */ 146 private static final int CURRENT_VERSION = 1; 147 148 // Write at most every 30 minutes. 149 static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000; 150 151 // Constant meaning that any UID should be matched when dispatching callbacks 152 private static final int UID_ANY = -2; 153 154 // Map from process states to the uid states we track. 155 private static final int[] PROCESS_STATE_TO_UID_STATE = new int[] { 156 UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT 157 UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI 158 UID_STATE_TOP, // ActivityManager.PROCESS_STATE_TOP 159 UID_STATE_FOREGROUND_SERVICE_LOCATION, 160 // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION 161 UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP 162 UID_STATE_FOREGROUND_SERVICE, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE 163 UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE 164 UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND 165 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND 166 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND 167 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_BACKUP 168 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_SERVICE 169 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_RECEIVER 170 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_TOP_SLEEPING 171 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT 172 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_HOME 173 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY 174 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY 175 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT 176 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_RECENT 177 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_EMPTY 178 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_NONEXISTENT 179 }; 180 181 private static final int[] OPS_RESTRICTED_ON_SUSPEND = { 182 OP_PLAY_AUDIO, 183 OP_RECORD_AUDIO, 184 OP_CAMERA, 185 }; 186 187 Context mContext; 188 final AtomicFile mFile; 189 final Handler mHandler; 190 191 private final AppOpsManagerInternalImpl mAppOpsManagerInternal 192 = new AppOpsManagerInternalImpl(); 193 194 boolean mWriteScheduled; 195 boolean mFastWriteScheduled; 196 final Runnable mWriteRunner = new Runnable() { 197 public void run() { 198 synchronized (AppOpsService.this) { 199 mWriteScheduled = false; 200 mFastWriteScheduled = false; 201 AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { 202 @Override protected Void doInBackground(Void... params) { 203 writeState(); 204 return null; 205 } 206 }; 207 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null); 208 } 209 } 210 }; 211 212 @VisibleForTesting 213 final SparseArray<UidState> mUidStates = new SparseArray<>(); 214 215 final HistoricalRegistry mHistoricalRegistry = new HistoricalRegistry(this); 216 217 long mLastRealtime; 218 219 /* 220 * These are app op restrictions imposed per user from various parties. 221 */ 222 private final ArrayMap<IBinder, ClientRestrictionState> mOpUserRestrictions = new ArrayMap<>(); 223 224 SparseIntArray mProfileOwners; 225 226 @GuardedBy("this") 227 private CheckOpsDelegate mCheckOpsDelegate; 228 229 /** 230 * All times are in milliseconds. These constants are kept synchronized with the system 231 * global Settings. Any access to this class or its fields should be done while 232 * holding the AppOpsService lock. 233 */ 234 @VisibleForTesting 235 final class Constants extends ContentObserver { 236 // Key names stored in the settings value. 237 private static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time"; 238 private static final String KEY_FG_SERVICE_STATE_SETTLE_TIME 239 = "fg_service_state_settle_time"; 240 private static final String KEY_BG_STATE_SETTLE_TIME = "bg_state_settle_time"; 241 242 /** 243 * How long we want for a drop in uid state from top to settle before applying it. 244 * @see Settings.Global#APP_OPS_CONSTANTS 245 * @see #KEY_TOP_STATE_SETTLE_TIME 246 */ 247 public long TOP_STATE_SETTLE_TIME; 248 249 /** 250 * How long we want for a drop in uid state from foreground to settle before applying it. 251 * @see Settings.Global#APP_OPS_CONSTANTS 252 * @see #KEY_FG_SERVICE_STATE_SETTLE_TIME 253 */ 254 public long FG_SERVICE_STATE_SETTLE_TIME; 255 256 /** 257 * How long we want for a drop in uid state from background to settle before applying it. 258 * @see Settings.Global#APP_OPS_CONSTANTS 259 * @see #KEY_BG_STATE_SETTLE_TIME 260 */ 261 public long BG_STATE_SETTLE_TIME; 262 263 private final KeyValueListParser mParser = new KeyValueListParser(','); 264 private ContentResolver mResolver; 265 Constants(Handler handler)266 public Constants(Handler handler) { 267 super(handler); 268 updateConstants(); 269 } 270 startMonitoring(ContentResolver resolver)271 public void startMonitoring(ContentResolver resolver) { 272 mResolver = resolver; 273 mResolver.registerContentObserver( 274 Settings.Global.getUriFor(Settings.Global.APP_OPS_CONSTANTS), 275 false, this); 276 updateConstants(); 277 } 278 279 @Override onChange(boolean selfChange, Uri uri)280 public void onChange(boolean selfChange, Uri uri) { 281 updateConstants(); 282 } 283 updateConstants()284 private void updateConstants() { 285 String value = mResolver != null ? Settings.Global.getString(mResolver, 286 Settings.Global.APP_OPS_CONSTANTS) : ""; 287 288 synchronized (AppOpsService.this) { 289 try { 290 mParser.setString(value); 291 } catch (IllegalArgumentException e) { 292 // Failed to parse the settings string, log this and move on 293 // with defaults. 294 Slog.e(TAG, "Bad app ops settings", e); 295 } 296 TOP_STATE_SETTLE_TIME = mParser.getDurationMillis( 297 KEY_TOP_STATE_SETTLE_TIME, 30 * 1000L); 298 FG_SERVICE_STATE_SETTLE_TIME = mParser.getDurationMillis( 299 KEY_FG_SERVICE_STATE_SETTLE_TIME, 10 * 1000L); 300 BG_STATE_SETTLE_TIME = mParser.getDurationMillis( 301 KEY_BG_STATE_SETTLE_TIME, 1 * 1000L); 302 } 303 } 304 dump(PrintWriter pw)305 void dump(PrintWriter pw) { 306 pw.println(" Settings:"); 307 308 pw.print(" "); pw.print(KEY_TOP_STATE_SETTLE_TIME); pw.print("="); 309 TimeUtils.formatDuration(TOP_STATE_SETTLE_TIME, pw); 310 pw.println(); 311 pw.print(" "); pw.print(KEY_FG_SERVICE_STATE_SETTLE_TIME); pw.print("="); 312 TimeUtils.formatDuration(FG_SERVICE_STATE_SETTLE_TIME, pw); 313 pw.println(); 314 pw.print(" "); pw.print(KEY_BG_STATE_SETTLE_TIME); pw.print("="); 315 TimeUtils.formatDuration(BG_STATE_SETTLE_TIME, pw); 316 pw.println(); 317 } 318 } 319 320 @VisibleForTesting 321 final Constants mConstants; 322 323 @VisibleForTesting 324 static final class UidState { 325 public final int uid; 326 327 public int state = UID_STATE_CACHED; 328 public int pendingState = UID_STATE_CACHED; 329 public long pendingStateCommitTime; 330 331 public int startNesting; 332 public ArrayMap<String, Ops> pkgOps; 333 public SparseIntArray opModes; 334 335 // true indicates there is an interested observer, false there isn't but it has such an op 336 public SparseBooleanArray foregroundOps; 337 public boolean hasForegroundWatchers; 338 UidState(int uid)339 public UidState(int uid) { 340 this.uid = uid; 341 } 342 clear()343 public void clear() { 344 pkgOps = null; 345 opModes = null; 346 } 347 isDefault()348 public boolean isDefault() { 349 return (pkgOps == null || pkgOps.isEmpty()) 350 && (opModes == null || opModes.size() <= 0) 351 && (state == UID_STATE_CACHED 352 && (pendingState == UID_STATE_CACHED)); 353 } 354 evalMode(int op, int mode)355 int evalMode(int op, int mode) { 356 if (mode == AppOpsManager.MODE_FOREGROUND) { 357 return state <= AppOpsManager.resolveFirstUnrestrictedUidState(op) 358 ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED; 359 } 360 return mode; 361 } 362 evalForegroundWatchers(int op, SparseArray<ArraySet<ModeCallback>> watchers, SparseBooleanArray which)363 private void evalForegroundWatchers(int op, SparseArray<ArraySet<ModeCallback>> watchers, 364 SparseBooleanArray which) { 365 boolean curValue = which.get(op, false); 366 ArraySet<ModeCallback> callbacks = watchers.get(op); 367 if (callbacks != null) { 368 for (int cbi = callbacks.size() - 1; !curValue && cbi >= 0; cbi--) { 369 if ((callbacks.valueAt(cbi).mFlags 370 & AppOpsManager.WATCH_FOREGROUND_CHANGES) != 0) { 371 hasForegroundWatchers = true; 372 curValue = true; 373 } 374 } 375 } 376 which.put(op, curValue); 377 } 378 evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers)379 public void evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers) { 380 SparseBooleanArray which = null; 381 hasForegroundWatchers = false; 382 if (opModes != null) { 383 for (int i = opModes.size() - 1; i >= 0; i--) { 384 if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) { 385 if (which == null) { 386 which = new SparseBooleanArray(); 387 } 388 evalForegroundWatchers(opModes.keyAt(i), watchers, which); 389 } 390 } 391 } 392 if (pkgOps != null) { 393 for (int i = pkgOps.size() - 1; i >= 0; i--) { 394 Ops ops = pkgOps.valueAt(i); 395 for (int j = ops.size() - 1; j >= 0; j--) { 396 if (ops.valueAt(j).mode == AppOpsManager.MODE_FOREGROUND) { 397 if (which == null) { 398 which = new SparseBooleanArray(); 399 } 400 evalForegroundWatchers(ops.keyAt(j), watchers, which); 401 } 402 } 403 } 404 } 405 foregroundOps = which; 406 } 407 } 408 409 final static class Ops extends SparseArray<Op> { 410 final String packageName; 411 final UidState uidState; 412 final boolean isPrivileged; 413 Ops(String _packageName, UidState _uidState, boolean _isPrivileged)414 Ops(String _packageName, UidState _uidState, boolean _isPrivileged) { 415 packageName = _packageName; 416 uidState = _uidState; 417 isPrivileged = _isPrivileged; 418 } 419 } 420 421 final static class Op { 422 int op; 423 boolean running; 424 final UidState uidState; 425 final @NonNull String packageName; 426 427 private @Mode int mode; 428 private @Nullable LongSparseLongArray mAccessTimes; 429 private @Nullable LongSparseLongArray mRejectTimes; 430 private @Nullable LongSparseLongArray mDurations; 431 private @Nullable LongSparseLongArray mProxyUids; 432 private @Nullable LongSparseArray<String> mProxyPackageNames; 433 434 int startNesting; 435 long startRealtime; 436 Op(UidState uidState, String packageName, int op)437 Op(UidState uidState, String packageName, int op) { 438 this.op = op; 439 this.uidState = uidState; 440 this.packageName = packageName; 441 this.mode = AppOpsManager.opToDefaultMode(op); 442 } 443 getMode()444 int getMode() { 445 return mode; 446 } 447 evalMode()448 int evalMode() { 449 return uidState.evalMode(op, mode); 450 } 451 452 /** @hide */ accessed(long time, int proxyUid, @Nullable String proxyPackageName, @AppOpsManager.UidState int uidState, @OpFlags int flags)453 public void accessed(long time, int proxyUid, @Nullable String proxyPackageName, 454 @AppOpsManager.UidState int uidState, @OpFlags int flags) { 455 final long key = AppOpsManager.makeKey(uidState, flags); 456 if (mAccessTimes == null) { 457 mAccessTimes = new LongSparseLongArray(); 458 } 459 mAccessTimes.put(key, time); 460 updateProxyState(key, proxyUid, proxyPackageName); 461 if (mDurations != null) { 462 mDurations.delete(key); 463 } 464 } 465 466 /** @hide */ rejected(long time, int proxyUid, @Nullable String proxyPackageName, @AppOpsManager.UidState int uidState, @OpFlags int flags)467 public void rejected(long time, int proxyUid, @Nullable String proxyPackageName, 468 @AppOpsManager.UidState int uidState, @OpFlags int flags) { 469 final long key = AppOpsManager.makeKey(uidState, flags); 470 if (mRejectTimes == null) { 471 mRejectTimes = new LongSparseLongArray(); 472 } 473 mRejectTimes.put(key, time); 474 updateProxyState(key, proxyUid, proxyPackageName); 475 if (mDurations != null) { 476 mDurations.delete(key); 477 } 478 } 479 480 /** @hide */ started(long time, @AppOpsManager.UidState int uidState, @OpFlags int flags)481 public void started(long time, @AppOpsManager.UidState int uidState, @OpFlags int flags) { 482 updateAccessTimeAndDuration(time, -1 /*duration*/, uidState, flags); 483 running = true; 484 } 485 486 /** @hide */ finished(long time, long duration, @AppOpsManager.UidState int uidState, @OpFlags int flags)487 public void finished(long time, long duration, @AppOpsManager.UidState int uidState, 488 @OpFlags int flags) { 489 updateAccessTimeAndDuration(time, duration, uidState, flags); 490 running = false; 491 } 492 493 /** @hide */ running(long time, long duration, @AppOpsManager.UidState int uidState, @OpFlags int flags)494 public void running(long time, long duration, @AppOpsManager.UidState int uidState, 495 @OpFlags int flags) { 496 updateAccessTimeAndDuration(time, duration, uidState, flags); 497 } 498 499 /** @hide */ continuing(long duration, @AppOpsManager.UidState int uidState, @OpFlags int flags)500 public void continuing(long duration, @AppOpsManager.UidState int uidState, 501 @OpFlags int flags) { 502 final long key = AppOpsManager.makeKey(uidState, flags); 503 if (mDurations == null) { 504 mDurations = new LongSparseLongArray(); 505 } 506 mDurations.put(key, duration); 507 } 508 updateAccessTimeAndDuration(long time, long duration, @AppOpsManager.UidState int uidState, @OpFlags int flags)509 private void updateAccessTimeAndDuration(long time, long duration, 510 @AppOpsManager.UidState int uidState, @OpFlags int flags) { 511 final long key = AppOpsManager.makeKey(uidState, flags); 512 if (mAccessTimes == null) { 513 mAccessTimes = new LongSparseLongArray(); 514 } 515 mAccessTimes.put(key, time); 516 if (mDurations == null) { 517 mDurations = new LongSparseLongArray(); 518 } 519 mDurations.put(key, duration); 520 } 521 updateProxyState(long key, int proxyUid, @Nullable String proxyPackageName)522 private void updateProxyState(long key, int proxyUid, 523 @Nullable String proxyPackageName) { 524 if (mProxyUids == null) { 525 mProxyUids = new LongSparseLongArray(); 526 } 527 mProxyUids.put(key, proxyUid); 528 if (mProxyPackageNames == null) { 529 mProxyPackageNames = new LongSparseArray<>(); 530 } 531 mProxyPackageNames.put(key, proxyPackageName); 532 } 533 hasAnyTime()534 boolean hasAnyTime() { 535 return (mAccessTimes != null && mAccessTimes.size() > 0) 536 || (mRejectTimes != null && mRejectTimes.size() > 0); 537 } 538 } 539 540 final SparseArray<ArraySet<ModeCallback>> mOpModeWatchers = new SparseArray<>(); 541 final ArrayMap<String, ArraySet<ModeCallback>> mPackageModeWatchers = new ArrayMap<>(); 542 final ArrayMap<IBinder, ModeCallback> mModeWatchers = new ArrayMap<>(); 543 final ArrayMap<IBinder, SparseArray<ActiveCallback>> mActiveWatchers = new ArrayMap<>(); 544 final ArrayMap<IBinder, SparseArray<NotedCallback>> mNotedWatchers = new ArrayMap<>(); 545 final SparseArray<SparseArray<Restriction>> mAudioRestrictions = new SparseArray<>(); 546 547 final class ModeCallback implements DeathRecipient { 548 final IAppOpsCallback mCallback; 549 final int mWatchingUid; 550 final int mFlags; 551 final int mCallingUid; 552 final int mCallingPid; 553 ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int callingUid, int callingPid)554 ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int callingUid, 555 int callingPid) { 556 mCallback = callback; 557 mWatchingUid = watchingUid; 558 mFlags = flags; 559 mCallingUid = callingUid; 560 mCallingPid = callingPid; 561 try { 562 mCallback.asBinder().linkToDeath(this, 0); 563 } catch (RemoteException e) { 564 /*ignored*/ 565 } 566 } 567 isWatchingUid(int uid)568 public boolean isWatchingUid(int uid) { 569 return uid == UID_ANY || mWatchingUid < 0 || mWatchingUid == uid; 570 } 571 572 @Override toString()573 public String toString() { 574 StringBuilder sb = new StringBuilder(128); 575 sb.append("ModeCallback{"); 576 sb.append(Integer.toHexString(System.identityHashCode(this))); 577 sb.append(" watchinguid="); 578 UserHandle.formatUid(sb, mWatchingUid); 579 sb.append(" flags=0x"); 580 sb.append(Integer.toHexString(mFlags)); 581 sb.append(" from uid="); 582 UserHandle.formatUid(sb, mCallingUid); 583 sb.append(" pid="); 584 sb.append(mCallingPid); 585 sb.append('}'); 586 return sb.toString(); 587 } 588 unlinkToDeath()589 void unlinkToDeath() { 590 mCallback.asBinder().unlinkToDeath(this, 0); 591 } 592 593 @Override binderDied()594 public void binderDied() { 595 stopWatchingMode(mCallback); 596 } 597 } 598 599 final class ActiveCallback implements DeathRecipient { 600 final IAppOpsActiveCallback mCallback; 601 final int mWatchingUid; 602 final int mCallingUid; 603 final int mCallingPid; 604 ActiveCallback(IAppOpsActiveCallback callback, int watchingUid, int callingUid, int callingPid)605 ActiveCallback(IAppOpsActiveCallback callback, int watchingUid, int callingUid, 606 int callingPid) { 607 mCallback = callback; 608 mWatchingUid = watchingUid; 609 mCallingUid = callingUid; 610 mCallingPid = callingPid; 611 try { 612 mCallback.asBinder().linkToDeath(this, 0); 613 } catch (RemoteException e) { 614 /*ignored*/ 615 } 616 } 617 618 @Override toString()619 public String toString() { 620 StringBuilder sb = new StringBuilder(128); 621 sb.append("ActiveCallback{"); 622 sb.append(Integer.toHexString(System.identityHashCode(this))); 623 sb.append(" watchinguid="); 624 UserHandle.formatUid(sb, mWatchingUid); 625 sb.append(" from uid="); 626 UserHandle.formatUid(sb, mCallingUid); 627 sb.append(" pid="); 628 sb.append(mCallingPid); 629 sb.append('}'); 630 return sb.toString(); 631 } 632 destroy()633 void destroy() { 634 mCallback.asBinder().unlinkToDeath(this, 0); 635 } 636 637 @Override binderDied()638 public void binderDied() { 639 stopWatchingActive(mCallback); 640 } 641 } 642 643 final class NotedCallback implements DeathRecipient { 644 final IAppOpsNotedCallback mCallback; 645 final int mWatchingUid; 646 final int mCallingUid; 647 final int mCallingPid; 648 NotedCallback(IAppOpsNotedCallback callback, int watchingUid, int callingUid, int callingPid)649 NotedCallback(IAppOpsNotedCallback callback, int watchingUid, int callingUid, 650 int callingPid) { 651 mCallback = callback; 652 mWatchingUid = watchingUid; 653 mCallingUid = callingUid; 654 mCallingPid = callingPid; 655 try { 656 mCallback.asBinder().linkToDeath(this, 0); 657 } catch (RemoteException e) { 658 /*ignored*/ 659 } 660 } 661 662 @Override toString()663 public String toString() { 664 StringBuilder sb = new StringBuilder(128); 665 sb.append("NotedCallback{"); 666 sb.append(Integer.toHexString(System.identityHashCode(this))); 667 sb.append(" watchinguid="); 668 UserHandle.formatUid(sb, mWatchingUid); 669 sb.append(" from uid="); 670 UserHandle.formatUid(sb, mCallingUid); 671 sb.append(" pid="); 672 sb.append(mCallingPid); 673 sb.append('}'); 674 return sb.toString(); 675 } 676 destroy()677 void destroy() { 678 mCallback.asBinder().unlinkToDeath(this, 0); 679 } 680 681 @Override binderDied()682 public void binderDied() { 683 stopWatchingNoted(mCallback); 684 } 685 } 686 687 final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>(); 688 689 final class ClientState extends Binder implements DeathRecipient { 690 final ArrayList<Op> mStartedOps = new ArrayList<>(); 691 final IBinder mAppToken; 692 final int mPid; 693 ClientState(IBinder appToken)694 ClientState(IBinder appToken) { 695 mAppToken = appToken; 696 mPid = Binder.getCallingPid(); 697 // Watch only for remote processes dying 698 if (!(appToken instanceof Binder)) { 699 try { 700 mAppToken.linkToDeath(this, 0); 701 } catch (RemoteException e) { 702 /* do nothing */ 703 } 704 } 705 } 706 707 @Override toString()708 public String toString() { 709 return "ClientState{" + 710 "mAppToken=" + mAppToken + 711 ", " + "pid=" + mPid + 712 '}'; 713 } 714 715 @Override binderDied()716 public void binderDied() { 717 synchronized (AppOpsService.this) { 718 for (int i=mStartedOps.size()-1; i>=0; i--) { 719 finishOperationLocked(mStartedOps.get(i), /*finishNested*/ true); 720 } 721 mClients.remove(mAppToken); 722 } 723 } 724 } 725 AppOpsService(File storagePath, Handler handler)726 public AppOpsService(File storagePath, Handler handler) { 727 LockGuard.installLock(this, LockGuard.INDEX_APP_OPS); 728 mFile = new AtomicFile(storagePath, "appops"); 729 mHandler = handler; 730 mConstants = new Constants(mHandler); 731 readState(); 732 } 733 publish(Context context)734 public void publish(Context context) { 735 mContext = context; 736 ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder()); 737 LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal); 738 } 739 systemReady()740 public void systemReady() { 741 mConstants.startMonitoring(mContext.getContentResolver()); 742 mHistoricalRegistry.systemReady(mContext.getContentResolver()); 743 744 synchronized (this) { 745 boolean changed = false; 746 for (int i = mUidStates.size() - 1; i >= 0; i--) { 747 UidState uidState = mUidStates.valueAt(i); 748 749 String[] packageNames = getPackagesForUid(uidState.uid); 750 if (ArrayUtils.isEmpty(packageNames)) { 751 uidState.clear(); 752 mUidStates.removeAt(i); 753 changed = true; 754 continue; 755 } 756 757 ArrayMap<String, Ops> pkgs = uidState.pkgOps; 758 if (pkgs == null) { 759 continue; 760 } 761 762 Iterator<Ops> it = pkgs.values().iterator(); 763 while (it.hasNext()) { 764 Ops ops = it.next(); 765 int curUid = -1; 766 try { 767 curUid = AppGlobals.getPackageManager().getPackageUid(ops.packageName, 768 PackageManager.MATCH_UNINSTALLED_PACKAGES, 769 UserHandle.getUserId(ops.uidState.uid)); 770 } catch (RemoteException ignored) { 771 } 772 if (curUid != ops.uidState.uid) { 773 Slog.i(TAG, "Pruning old package " + ops.packageName 774 + "/" + ops.uidState + ": new uid=" + curUid); 775 it.remove(); 776 changed = true; 777 } 778 } 779 780 if (uidState.isDefault()) { 781 mUidStates.removeAt(i); 782 } 783 } 784 if (changed) { 785 scheduleFastWriteLocked(); 786 } 787 } 788 789 final IntentFilter packageSuspendFilter = new IntentFilter(); 790 packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED); 791 packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED); 792 mContext.registerReceiver(new BroadcastReceiver() { 793 @Override 794 public void onReceive(Context context, Intent intent) { 795 final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST); 796 final String[] changedPkgs = intent.getStringArrayExtra( 797 Intent.EXTRA_CHANGED_PACKAGE_LIST); 798 for (int code : OPS_RESTRICTED_ON_SUSPEND) { 799 ArraySet<ModeCallback> callbacks; 800 synchronized (AppOpsService.this) { 801 callbacks = mOpModeWatchers.get(code); 802 if (callbacks == null) { 803 continue; 804 } 805 callbacks = new ArraySet<>(callbacks); 806 } 807 for (int i = 0; i < changedUids.length; i++) { 808 final int changedUid = changedUids[i]; 809 final String changedPkg = changedPkgs[i]; 810 // We trust packagemanager to insert matching uid and packageNames in the 811 // extras 812 notifyOpChanged(callbacks, code, changedUid, changedPkg); 813 } 814 } 815 } 816 }, packageSuspendFilter); 817 818 PackageManagerInternal packageManagerInternal = LocalServices.getService( 819 PackageManagerInternal.class); 820 packageManagerInternal.setExternalSourcesPolicy( 821 new PackageManagerInternal.ExternalSourcesPolicy() { 822 @Override 823 public int getPackageTrustedToInstallApps(String packageName, int uid) { 824 int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, 825 uid, packageName); 826 switch (appOpMode) { 827 case AppOpsManager.MODE_ALLOWED: 828 return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED; 829 case AppOpsManager.MODE_ERRORED: 830 return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED; 831 default: 832 return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT; 833 } 834 } 835 }); 836 837 if (!StorageManager.hasIsolatedStorage()) { 838 StorageManagerInternal storageManagerInternal = LocalServices.getService( 839 StorageManagerInternal.class); 840 storageManagerInternal.addExternalStoragePolicy( 841 new StorageManagerInternal.ExternalStorageMountPolicy() { 842 @Override 843 public int getMountMode(int uid, String packageName) { 844 if (Process.isIsolated(uid)) { 845 return Zygote.MOUNT_EXTERNAL_NONE; 846 } 847 if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid, 848 packageName) != AppOpsManager.MODE_ALLOWED) { 849 return Zygote.MOUNT_EXTERNAL_NONE; 850 } 851 if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid, 852 packageName) != AppOpsManager.MODE_ALLOWED) { 853 return Zygote.MOUNT_EXTERNAL_READ; 854 } 855 return Zygote.MOUNT_EXTERNAL_WRITE; 856 } 857 858 @Override 859 public boolean hasExternalStorage(int uid, String packageName) { 860 final int mountMode = getMountMode(uid, packageName); 861 return mountMode == Zygote.MOUNT_EXTERNAL_READ 862 || mountMode == Zygote.MOUNT_EXTERNAL_WRITE; 863 } 864 }); 865 } 866 } 867 packageRemoved(int uid, String packageName)868 public void packageRemoved(int uid, String packageName) { 869 synchronized (this) { 870 UidState uidState = mUidStates.get(uid); 871 if (uidState == null) { 872 return; 873 } 874 875 Ops ops = null; 876 877 // Remove any package state if such. 878 if (uidState.pkgOps != null) { 879 ops = uidState.pkgOps.remove(packageName); 880 } 881 882 // If we just nuked the last package state check if the UID is valid. 883 if (ops != null && uidState.pkgOps.isEmpty() 884 && getPackagesForUid(uid).length <= 0) { 885 mUidStates.remove(uid); 886 } 887 888 // Finish ops other packages started on behalf of the package. 889 final int clientCount = mClients.size(); 890 for (int i = 0; i < clientCount; i++) { 891 final ClientState client = mClients.valueAt(i); 892 if (client.mStartedOps == null) { 893 continue; 894 } 895 final int opCount = client.mStartedOps.size(); 896 for (int j = opCount - 1; j >= 0; j--) { 897 final Op op = client.mStartedOps.get(j); 898 if (uid == op.uidState.uid && packageName.equals(op.packageName)) { 899 finishOperationLocked(op, /*finishNested*/ true); 900 client.mStartedOps.remove(j); 901 if (op.startNesting <= 0) { 902 scheduleOpActiveChangedIfNeededLocked(op.op, 903 uid, packageName, false); 904 } 905 } 906 } 907 } 908 909 if (ops != null) { 910 scheduleFastWriteLocked(); 911 912 final int opCount = ops.size(); 913 for (int i = 0; i < opCount; i++) { 914 final Op op = ops.valueAt(i); 915 if (op.running) { 916 scheduleOpActiveChangedIfNeededLocked( 917 op.op, op.uidState.uid, op.packageName, false); 918 } 919 } 920 } 921 922 mHistoricalRegistry.clearHistory(uid, packageName); 923 } 924 } 925 uidRemoved(int uid)926 public void uidRemoved(int uid) { 927 synchronized (this) { 928 if (mUidStates.indexOfKey(uid) >= 0) { 929 mUidStates.remove(uid); 930 scheduleFastWriteLocked(); 931 } 932 } 933 } 934 935 /** 936 * Update the pending state for the uid 937 * 938 * @param currentTime The current elapsed real time 939 * @param uid The uid that has a pending state 940 */ updatePendingState(long currentTime, int uid)941 private void updatePendingState(long currentTime, int uid) { 942 synchronized (this) { 943 mLastRealtime = max(currentTime, mLastRealtime); 944 updatePendingStateIfNeededLocked(mUidStates.get(uid)); 945 } 946 } 947 updateUidProcState(int uid, int procState)948 public void updateUidProcState(int uid, int procState) { 949 synchronized (this) { 950 final UidState uidState = getUidStateLocked(uid, true); 951 int newState = PROCESS_STATE_TO_UID_STATE[procState]; 952 if (uidState != null && uidState.pendingState != newState) { 953 final int oldPendingState = uidState.pendingState; 954 uidState.pendingState = newState; 955 if (newState < uidState.state 956 || (newState <= UID_STATE_MAX_LAST_NON_RESTRICTED 957 && uidState.state > UID_STATE_MAX_LAST_NON_RESTRICTED)) { 958 // We are moving to a more important state, or the new state may be in the 959 // foreground and the old state is in the background, then always do it 960 // immediately. 961 commitUidPendingStateLocked(uidState); 962 } else if (uidState.pendingStateCommitTime == 0) { 963 // We are moving to a less important state for the first time, 964 // delay the application for a bit. 965 final long settleTime; 966 if (uidState.state <= UID_STATE_TOP) { 967 settleTime = mConstants.TOP_STATE_SETTLE_TIME; 968 } else if (uidState.state <= UID_STATE_FOREGROUND_SERVICE) { 969 settleTime = mConstants.FG_SERVICE_STATE_SETTLE_TIME; 970 } else { 971 settleTime = mConstants.BG_STATE_SETTLE_TIME; 972 } 973 final long commitTime = SystemClock.elapsedRealtime() + settleTime; 974 uidState.pendingStateCommitTime = commitTime; 975 976 mHandler.sendMessageDelayed( 977 PooledLambda.obtainMessage(AppOpsService::updatePendingState, this, 978 commitTime + 1, uid), settleTime + 1); 979 } 980 if (uidState.startNesting != 0) { 981 // There is some actively running operation... need to find it 982 // and appropriately update its state. 983 final long now = System.currentTimeMillis(); 984 for (int i = uidState.pkgOps.size() - 1; i >= 0; i--) { 985 final Ops ops = uidState.pkgOps.valueAt(i); 986 for (int j = ops.size() - 1; j >= 0; j--) { 987 final Op op = ops.valueAt(j); 988 if (op.startNesting > 0) { 989 final long duration = SystemClock.elapsedRealtime() 990 - op.startRealtime; 991 // We don't support proxy long running ops (start/stop) 992 mHistoricalRegistry.increaseOpAccessDuration(op.op, 993 op.uidState.uid, op.packageName, oldPendingState, 994 AppOpsManager.OP_FLAG_SELF, duration); 995 // Finish the op in the old state 996 op.finished(now, duration, oldPendingState, 997 AppOpsManager.OP_FLAG_SELF); 998 // Start the op in the new state 999 op.startRealtime = now; 1000 op.started(now, newState, AppOpsManager.OP_FLAG_SELF); 1001 } 1002 } 1003 } 1004 } 1005 } 1006 } 1007 } 1008 shutdown()1009 public void shutdown() { 1010 Slog.w(TAG, "Writing app ops before shutdown..."); 1011 boolean doWrite = false; 1012 synchronized (this) { 1013 if (mWriteScheduled) { 1014 mWriteScheduled = false; 1015 doWrite = true; 1016 } 1017 } 1018 if (doWrite) { 1019 writeState(); 1020 } 1021 } 1022 collectOps(Ops pkgOps, int[] ops)1023 private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) { 1024 ArrayList<AppOpsManager.OpEntry> resOps = null; 1025 final long elapsedNow = SystemClock.elapsedRealtime(); 1026 if (ops == null) { 1027 resOps = new ArrayList<>(); 1028 for (int j=0; j<pkgOps.size(); j++) { 1029 Op curOp = pkgOps.valueAt(j); 1030 resOps.add(getOpEntryForResult(curOp, elapsedNow)); 1031 } 1032 } else { 1033 for (int j=0; j<ops.length; j++) { 1034 Op curOp = pkgOps.get(ops[j]); 1035 if (curOp != null) { 1036 if (resOps == null) { 1037 resOps = new ArrayList<>(); 1038 } 1039 resOps.add(getOpEntryForResult(curOp, elapsedNow)); 1040 } 1041 } 1042 } 1043 return resOps; 1044 } 1045 collectOps(SparseIntArray uidOps, int[] ops)1046 private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) { 1047 if (uidOps == null) { 1048 return null; 1049 } 1050 ArrayList<AppOpsManager.OpEntry> resOps = null; 1051 if (ops == null) { 1052 resOps = new ArrayList<>(); 1053 for (int j=0; j<uidOps.size(); j++) { 1054 resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j))); 1055 } 1056 } else { 1057 for (int j=0; j<ops.length; j++) { 1058 int index = uidOps.indexOfKey(ops[j]); 1059 if (index >= 0) { 1060 if (resOps == null) { 1061 resOps = new ArrayList<>(); 1062 } 1063 resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j))); 1064 } 1065 } 1066 } 1067 return resOps; 1068 } 1069 getOpEntryForResult(@onNull Op op, long elapsedNow)1070 private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, long elapsedNow) { 1071 if (op.running) { 1072 op.continuing(elapsedNow - op.startRealtime, 1073 op.uidState.state, AppOpsManager.OP_FLAG_SELF); 1074 } 1075 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, 1076 op.mAccessTimes != null ? op.mAccessTimes.clone() : null, 1077 op.mRejectTimes != null ? op.mRejectTimes.clone() : null, 1078 op.mDurations != null ? op.mDurations.clone() : null, 1079 op.mProxyUids != null ? op.mProxyUids.clone() : null, 1080 op.mProxyPackageNames != null ? op.mProxyPackageNames.clone() : null); 1081 return entry; 1082 } 1083 1084 @Override getPackagesForOps(int[] ops)1085 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { 1086 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 1087 Binder.getCallingPid(), Binder.getCallingUid(), null); 1088 ArrayList<AppOpsManager.PackageOps> res = null; 1089 synchronized (this) { 1090 final int uidStateCount = mUidStates.size(); 1091 for (int i = 0; i < uidStateCount; i++) { 1092 UidState uidState = mUidStates.valueAt(i); 1093 if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()) { 1094 continue; 1095 } 1096 ArrayMap<String, Ops> packages = uidState.pkgOps; 1097 final int packageCount = packages.size(); 1098 for (int j = 0; j < packageCount; j++) { 1099 Ops pkgOps = packages.valueAt(j); 1100 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 1101 if (resOps != null) { 1102 if (res == null) { 1103 res = new ArrayList<AppOpsManager.PackageOps>(); 1104 } 1105 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 1106 pkgOps.packageName, pkgOps.uidState.uid, resOps); 1107 res.add(resPackage); 1108 } 1109 } 1110 } 1111 } 1112 return res; 1113 } 1114 1115 @Override getOpsForPackage(int uid, String packageName, int[] ops)1116 public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, 1117 int[] ops) { 1118 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 1119 Binder.getCallingPid(), Binder.getCallingUid(), null); 1120 String resolvedPackageName = resolvePackageName(uid, packageName); 1121 if (resolvedPackageName == null) { 1122 return Collections.emptyList(); 1123 } 1124 synchronized (this) { 1125 Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false /* edit */, 1126 false /* uidMismatchExpected */); 1127 if (pkgOps == null) { 1128 return null; 1129 } 1130 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 1131 if (resOps == null) { 1132 return null; 1133 } 1134 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); 1135 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 1136 pkgOps.packageName, pkgOps.uidState.uid, resOps); 1137 res.add(resPackage); 1138 return res; 1139 } 1140 } 1141 1142 @Override getHistoricalOps(int uid, @NonNull String packageName, @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis, @OpFlags int flags, @NonNull RemoteCallback callback)1143 public void getHistoricalOps(int uid, @NonNull String packageName, 1144 @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis, 1145 @OpFlags int flags, @NonNull RemoteCallback callback) { 1146 // Use the builder to validate arguments. 1147 new HistoricalOpsRequest.Builder( 1148 beginTimeMillis, endTimeMillis) 1149 .setUid(uid) 1150 .setPackageName(packageName) 1151 .setOpNames(opNames) 1152 .setFlags(flags) 1153 .build(); 1154 Preconditions.checkNotNull(callback, "callback cannot be null"); 1155 1156 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 1157 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); 1158 1159 final String[] opNamesArray = (opNames != null) 1160 ? opNames.toArray(new String[opNames.size()]) : null; 1161 1162 // Must not hold the appops lock 1163 mHistoricalRegistry.getHistoricalOps(uid, packageName, opNamesArray, 1164 beginTimeMillis, endTimeMillis, flags, callback); 1165 } 1166 1167 @Override getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName, @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis, @OpFlags int flags, @NonNull RemoteCallback callback)1168 public void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName, 1169 @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis, 1170 @OpFlags int flags, @NonNull RemoteCallback callback) { 1171 // Use the builder to validate arguments. 1172 new HistoricalOpsRequest.Builder( 1173 beginTimeMillis, endTimeMillis) 1174 .setUid(uid) 1175 .setPackageName(packageName) 1176 .setOpNames(opNames) 1177 .setFlags(flags) 1178 .build(); 1179 Preconditions.checkNotNull(callback, "callback cannot be null"); 1180 1181 mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS, 1182 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); 1183 1184 final String[] opNamesArray = (opNames != null) 1185 ? opNames.toArray(new String[opNames.size()]) : null; 1186 1187 // Must not hold the appops lock 1188 mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNamesArray, 1189 beginTimeMillis, endTimeMillis, flags, callback); 1190 } 1191 1192 @Override reloadNonHistoricalState()1193 public void reloadNonHistoricalState() { 1194 mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS, 1195 Binder.getCallingPid(), Binder.getCallingUid(), "reloadNonHistoricalState"); 1196 writeState(); 1197 readState(); 1198 } 1199 1200 @Override getUidOps(int uid, int[] ops)1201 public List<AppOpsManager.PackageOps> getUidOps(int uid, int[] ops) { 1202 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 1203 Binder.getCallingPid(), Binder.getCallingUid(), null); 1204 synchronized (this) { 1205 UidState uidState = getUidStateLocked(uid, false); 1206 if (uidState == null) { 1207 return null; 1208 } 1209 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops); 1210 if (resOps == null) { 1211 return null; 1212 } 1213 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); 1214 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 1215 null, uidState.uid, resOps); 1216 res.add(resPackage); 1217 return res; 1218 } 1219 } 1220 pruneOp(Op op, int uid, String packageName)1221 private void pruneOp(Op op, int uid, String packageName) { 1222 if (!op.hasAnyTime()) { 1223 Ops ops = getOpsRawLocked(uid, packageName, false /* edit */, 1224 false /* uidMismatchExpected */); 1225 if (ops != null) { 1226 ops.remove(op.op); 1227 if (ops.size() <= 0) { 1228 UidState uidState = ops.uidState; 1229 ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 1230 if (pkgOps != null) { 1231 pkgOps.remove(ops.packageName); 1232 if (pkgOps.isEmpty()) { 1233 uidState.pkgOps = null; 1234 } 1235 if (uidState.isDefault()) { 1236 mUidStates.remove(uid); 1237 } 1238 } 1239 } 1240 } 1241 } 1242 } 1243 enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid)1244 private void enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid) { 1245 if (callingPid == Process.myPid()) { 1246 return; 1247 } 1248 final int callingUser = UserHandle.getUserId(callingUid); 1249 synchronized (this) { 1250 if (mProfileOwners != null && mProfileOwners.get(callingUser, -1) == callingUid) { 1251 if (targetUid >= 0 && callingUser == UserHandle.getUserId(targetUid)) { 1252 // Profile owners are allowed to change modes but only for apps 1253 // within their user. 1254 return; 1255 } 1256 } 1257 } 1258 mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES, 1259 Binder.getCallingPid(), Binder.getCallingUid(), null); 1260 } 1261 1262 @Override setUidMode(int code, int uid, int mode)1263 public void setUidMode(int code, int uid, int mode) { 1264 if (DEBUG) { 1265 Slog.i(TAG, "uid " + uid + " OP_" + opToName(code) + " := " + modeToName(mode) 1266 + " by uid " + Binder.getCallingUid()); 1267 } 1268 1269 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); 1270 verifyIncomingOp(code); 1271 code = AppOpsManager.opToSwitch(code); 1272 1273 synchronized (this) { 1274 final int defaultMode = AppOpsManager.opToDefaultMode(code); 1275 1276 UidState uidState = getUidStateLocked(uid, false); 1277 if (uidState == null) { 1278 if (mode == defaultMode) { 1279 return; 1280 } 1281 uidState = new UidState(uid); 1282 uidState.opModes = new SparseIntArray(); 1283 uidState.opModes.put(code, mode); 1284 mUidStates.put(uid, uidState); 1285 scheduleWriteLocked(); 1286 } else if (uidState.opModes == null) { 1287 if (mode != defaultMode) { 1288 uidState.opModes = new SparseIntArray(); 1289 uidState.opModes.put(code, mode); 1290 scheduleWriteLocked(); 1291 } 1292 } else { 1293 if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) { 1294 return; 1295 } 1296 if (mode == defaultMode) { 1297 uidState.opModes.delete(code); 1298 if (uidState.opModes.size() <= 0) { 1299 uidState.opModes = null; 1300 } 1301 } else { 1302 uidState.opModes.put(code, mode); 1303 } 1304 scheduleWriteLocked(); 1305 } 1306 uidState.evalForegroundOps(mOpModeWatchers); 1307 } 1308 1309 notifyOpChangedForAllPkgsInUid(code, uid, false); 1310 notifyOpChangedSync(code, uid, null, mode); 1311 } 1312 1313 /** 1314 * Notify that an op changed for all packages in an uid. 1315 * 1316 * @param code The op that changed 1317 * @param uid The uid the op was changed for 1318 * @param onlyForeground Only notify watchers that watch for foreground changes 1319 */ notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground)1320 private void notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground) { 1321 String[] uidPackageNames = getPackagesForUid(uid); 1322 ArrayMap<ModeCallback, ArraySet<String>> callbackSpecs = null; 1323 1324 synchronized (this) { 1325 ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code); 1326 if (callbacks != null) { 1327 final int callbackCount = callbacks.size(); 1328 for (int i = 0; i < callbackCount; i++) { 1329 ModeCallback callback = callbacks.valueAt(i); 1330 if (onlyForeground && (callback.mFlags & WATCH_FOREGROUND_CHANGES) == 0) { 1331 continue; 1332 } 1333 1334 ArraySet<String> changedPackages = new ArraySet<>(); 1335 Collections.addAll(changedPackages, uidPackageNames); 1336 if (callbackSpecs == null) { 1337 callbackSpecs = new ArrayMap<>(); 1338 } 1339 callbackSpecs.put(callback, changedPackages); 1340 } 1341 } 1342 1343 for (String uidPackageName : uidPackageNames) { 1344 callbacks = mPackageModeWatchers.get(uidPackageName); 1345 if (callbacks != null) { 1346 if (callbackSpecs == null) { 1347 callbackSpecs = new ArrayMap<>(); 1348 } 1349 final int callbackCount = callbacks.size(); 1350 for (int i = 0; i < callbackCount; i++) { 1351 ModeCallback callback = callbacks.valueAt(i); 1352 if (onlyForeground && (callback.mFlags & WATCH_FOREGROUND_CHANGES) == 0) { 1353 continue; 1354 } 1355 1356 ArraySet<String> changedPackages = callbackSpecs.get(callback); 1357 if (changedPackages == null) { 1358 changedPackages = new ArraySet<>(); 1359 callbackSpecs.put(callback, changedPackages); 1360 } 1361 changedPackages.add(uidPackageName); 1362 } 1363 } 1364 } 1365 } 1366 1367 if (callbackSpecs == null) { 1368 return; 1369 } 1370 1371 for (int i = 0; i < callbackSpecs.size(); i++) { 1372 final ModeCallback callback = callbackSpecs.keyAt(i); 1373 final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i); 1374 if (reportedPackageNames == null) { 1375 mHandler.sendMessage(PooledLambda.obtainMessage( 1376 AppOpsService::notifyOpChanged, 1377 this, callback, code, uid, (String) null)); 1378 1379 } else { 1380 final int reportedPackageCount = reportedPackageNames.size(); 1381 for (int j = 0; j < reportedPackageCount; j++) { 1382 final String reportedPackageName = reportedPackageNames.valueAt(j); 1383 mHandler.sendMessage(PooledLambda.obtainMessage( 1384 AppOpsService::notifyOpChanged, 1385 this, callback, code, uid, reportedPackageName)); 1386 } 1387 } 1388 } 1389 } 1390 notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode)1391 private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode) { 1392 final StorageManagerInternal storageManagerInternal = 1393 LocalServices.getService(StorageManagerInternal.class); 1394 if (storageManagerInternal != null) { 1395 storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode); 1396 } 1397 } 1398 1399 /** 1400 * Set all {@link #setMode (package) modes} for this uid to the default value. 1401 * 1402 * @param code The app-op 1403 * @param uid The uid 1404 */ setAllPkgModesToDefault(int code, int uid)1405 private void setAllPkgModesToDefault(int code, int uid) { 1406 synchronized (this) { 1407 UidState uidState = getUidStateLocked(uid, false); 1408 if (uidState == null) { 1409 return; 1410 } 1411 1412 ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 1413 if (pkgOps == null) { 1414 return; 1415 } 1416 1417 boolean scheduleWrite = false; 1418 1419 int numPkgs = pkgOps.size(); 1420 for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) { 1421 Ops ops = pkgOps.valueAt(pkgNum); 1422 1423 Op op = ops.get(code); 1424 if (op == null) { 1425 continue; 1426 } 1427 1428 int defaultMode = AppOpsManager.opToDefaultMode(code); 1429 if (op.mode != defaultMode) { 1430 op.mode = defaultMode; 1431 scheduleWrite = true; 1432 } 1433 } 1434 1435 if (scheduleWrite) { 1436 scheduleWriteLocked(); 1437 } 1438 } 1439 } 1440 1441 @Override setMode(int code, int uid, String packageName, int mode)1442 public void setMode(int code, int uid, String packageName, int mode) { 1443 setMode(code, uid, packageName, mode, true, false); 1444 } 1445 1446 /** 1447 * Sets the mode for a certain op and uid. 1448 * 1449 * @param code The op code to set 1450 * @param uid The UID for which to set 1451 * @param packageName The package for which to set 1452 * @param mode The new mode to set 1453 * @param verifyUid Iff {@code true}, check that the package name belongs to the uid 1454 * @param isPrivileged Whether the package is privileged. (Only used if {@code verifyUid == 1455 * false}) 1456 */ setMode(int code, int uid, @NonNull String packageName, int mode, boolean verifyUid, boolean isPrivileged)1457 private void setMode(int code, int uid, @NonNull String packageName, int mode, 1458 boolean verifyUid, boolean isPrivileged) { 1459 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); 1460 verifyIncomingOp(code); 1461 ArraySet<ModeCallback> repCbs = null; 1462 code = AppOpsManager.opToSwitch(code); 1463 synchronized (this) { 1464 UidState uidState = getUidStateLocked(uid, false); 1465 Op op = getOpLocked(code, uid, packageName, true, verifyUid, isPrivileged); 1466 if (op != null) { 1467 if (op.mode != mode) { 1468 op.mode = mode; 1469 if (uidState != null) { 1470 uidState.evalForegroundOps(mOpModeWatchers); 1471 } 1472 ArraySet<ModeCallback> cbs = mOpModeWatchers.get(code); 1473 if (cbs != null) { 1474 if (repCbs == null) { 1475 repCbs = new ArraySet<>(); 1476 } 1477 repCbs.addAll(cbs); 1478 } 1479 cbs = mPackageModeWatchers.get(packageName); 1480 if (cbs != null) { 1481 if (repCbs == null) { 1482 repCbs = new ArraySet<>(); 1483 } 1484 repCbs.addAll(cbs); 1485 } 1486 if (mode == AppOpsManager.opToDefaultMode(op.op)) { 1487 // If going into the default mode, prune this op 1488 // if there is nothing else interesting in it. 1489 pruneOp(op, uid, packageName); 1490 } 1491 scheduleFastWriteLocked(); 1492 } 1493 } 1494 } 1495 if (repCbs != null) { 1496 mHandler.sendMessage(PooledLambda.obtainMessage( 1497 AppOpsService::notifyOpChanged, 1498 this, repCbs, code, uid, packageName)); 1499 } 1500 1501 notifyOpChangedSync(code, uid, packageName, mode); 1502 } 1503 notifyOpChanged(ArraySet<ModeCallback> callbacks, int code, int uid, String packageName)1504 private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code, 1505 int uid, String packageName) { 1506 for (int i = 0; i < callbacks.size(); i++) { 1507 final ModeCallback callback = callbacks.valueAt(i); 1508 notifyOpChanged(callback, code, uid, packageName); 1509 } 1510 } 1511 notifyOpChanged(ModeCallback callback, int code, int uid, String packageName)1512 private void notifyOpChanged(ModeCallback callback, int code, 1513 int uid, String packageName) { 1514 if (uid != UID_ANY && callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 1515 return; 1516 } 1517 // There are components watching for mode changes such as window manager 1518 // and location manager which are in our process. The callbacks in these 1519 // components may require permissions our remote caller does not have. 1520 final long identity = Binder.clearCallingIdentity(); 1521 try { 1522 callback.mCallback.opChanged(code, uid, packageName); 1523 } catch (RemoteException e) { 1524 /* ignore */ 1525 } finally { 1526 Binder.restoreCallingIdentity(identity); 1527 } 1528 } 1529 addCallbacks( HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks, int op, int uid, String packageName, ArraySet<ModeCallback> cbs)1530 private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks( 1531 HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks, 1532 int op, int uid, String packageName, ArraySet<ModeCallback> cbs) { 1533 if (cbs == null) { 1534 return callbacks; 1535 } 1536 if (callbacks == null) { 1537 callbacks = new HashMap<>(); 1538 } 1539 boolean duplicate = false; 1540 final int N = cbs.size(); 1541 for (int i=0; i<N; i++) { 1542 ModeCallback cb = cbs.valueAt(i); 1543 ArrayList<ChangeRec> reports = callbacks.get(cb); 1544 if (reports == null) { 1545 reports = new ArrayList<>(); 1546 callbacks.put(cb, reports); 1547 } else { 1548 final int reportCount = reports.size(); 1549 for (int j = 0; j < reportCount; j++) { 1550 ChangeRec report = reports.get(j); 1551 if (report.op == op && report.pkg.equals(packageName)) { 1552 duplicate = true; 1553 break; 1554 } 1555 } 1556 } 1557 if (!duplicate) { 1558 reports.add(new ChangeRec(op, uid, packageName)); 1559 } 1560 } 1561 return callbacks; 1562 } 1563 1564 static final class ChangeRec { 1565 final int op; 1566 final int uid; 1567 final String pkg; 1568 ChangeRec(int _op, int _uid, String _pkg)1569 ChangeRec(int _op, int _uid, String _pkg) { 1570 op = _op; 1571 uid = _uid; 1572 pkg = _pkg; 1573 } 1574 } 1575 1576 @Override resetAllModes(int reqUserId, String reqPackageName)1577 public void resetAllModes(int reqUserId, String reqPackageName) { 1578 final int callingPid = Binder.getCallingPid(); 1579 final int callingUid = Binder.getCallingUid(); 1580 reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId, 1581 true, true, "resetAllModes", null); 1582 1583 int reqUid = -1; 1584 if (reqPackageName != null) { 1585 try { 1586 reqUid = AppGlobals.getPackageManager().getPackageUid( 1587 reqPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, reqUserId); 1588 } catch (RemoteException e) { 1589 /* ignore - local call */ 1590 } 1591 } 1592 1593 enforceManageAppOpsModes(callingPid, callingUid, reqUid); 1594 1595 HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks = null; 1596 synchronized (this) { 1597 boolean changed = false; 1598 for (int i = mUidStates.size() - 1; i >= 0; i--) { 1599 UidState uidState = mUidStates.valueAt(i); 1600 1601 SparseIntArray opModes = uidState.opModes; 1602 if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) { 1603 final int uidOpCount = opModes.size(); 1604 for (int j = uidOpCount - 1; j >= 0; j--) { 1605 final int code = opModes.keyAt(j); 1606 if (AppOpsManager.opAllowsReset(code)) { 1607 opModes.removeAt(j); 1608 if (opModes.size() <= 0) { 1609 uidState.opModes = null; 1610 } 1611 for (String packageName : getPackagesForUid(uidState.uid)) { 1612 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, 1613 mOpModeWatchers.get(code)); 1614 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, 1615 mPackageModeWatchers.get(packageName)); 1616 } 1617 } 1618 } 1619 } 1620 1621 if (uidState.pkgOps == null) { 1622 continue; 1623 } 1624 1625 if (reqUserId != UserHandle.USER_ALL 1626 && reqUserId != UserHandle.getUserId(uidState.uid)) { 1627 // Skip any ops for a different user 1628 continue; 1629 } 1630 1631 Map<String, Ops> packages = uidState.pkgOps; 1632 Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator(); 1633 boolean uidChanged = false; 1634 while (it.hasNext()) { 1635 Map.Entry<String, Ops> ent = it.next(); 1636 String packageName = ent.getKey(); 1637 if (reqPackageName != null && !reqPackageName.equals(packageName)) { 1638 // Skip any ops for a different package 1639 continue; 1640 } 1641 Ops pkgOps = ent.getValue(); 1642 for (int j=pkgOps.size()-1; j>=0; j--) { 1643 Op curOp = pkgOps.valueAt(j); 1644 if (AppOpsManager.opAllowsReset(curOp.op) 1645 && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) { 1646 curOp.mode = AppOpsManager.opToDefaultMode(curOp.op); 1647 changed = true; 1648 uidChanged = true; 1649 final int uid = curOp.uidState.uid; 1650 callbacks = addCallbacks(callbacks, curOp.op, uid, packageName, 1651 mOpModeWatchers.get(curOp.op)); 1652 callbacks = addCallbacks(callbacks, curOp.op, uid, packageName, 1653 mPackageModeWatchers.get(packageName)); 1654 if (!curOp.hasAnyTime()) { 1655 pkgOps.removeAt(j); 1656 } 1657 } 1658 } 1659 if (pkgOps.size() == 0) { 1660 it.remove(); 1661 } 1662 } 1663 if (uidState.isDefault()) { 1664 mUidStates.remove(uidState.uid); 1665 } 1666 if (uidChanged) { 1667 uidState.evalForegroundOps(mOpModeWatchers); 1668 } 1669 } 1670 1671 if (changed) { 1672 scheduleFastWriteLocked(); 1673 } 1674 } 1675 if (callbacks != null) { 1676 for (Map.Entry<ModeCallback, ArrayList<ChangeRec>> ent : callbacks.entrySet()) { 1677 ModeCallback cb = ent.getKey(); 1678 ArrayList<ChangeRec> reports = ent.getValue(); 1679 for (int i=0; i<reports.size(); i++) { 1680 ChangeRec rep = reports.get(i); 1681 mHandler.sendMessage(PooledLambda.obtainMessage( 1682 AppOpsService::notifyOpChanged, 1683 this, cb, rep.op, rep.uid, rep.pkg)); 1684 } 1685 } 1686 } 1687 } 1688 evalAllForegroundOpsLocked()1689 private void evalAllForegroundOpsLocked() { 1690 for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) { 1691 final UidState uidState = mUidStates.valueAt(uidi); 1692 if (uidState.foregroundOps != null) { 1693 uidState.evalForegroundOps(mOpModeWatchers); 1694 } 1695 } 1696 } 1697 1698 @Override startWatchingMode(int op, String packageName, IAppOpsCallback callback)1699 public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) { 1700 startWatchingModeWithFlags(op, packageName, 0, callback); 1701 } 1702 1703 @Override startWatchingModeWithFlags(int op, String packageName, int flags, IAppOpsCallback callback)1704 public void startWatchingModeWithFlags(int op, String packageName, int flags, 1705 IAppOpsCallback callback) { 1706 int watchedUid = -1; 1707 final int callingUid = Binder.getCallingUid(); 1708 final int callingPid = Binder.getCallingPid(); 1709 // TODO: should have a privileged permission to protect this. 1710 // Also, if the caller has requested WATCH_FOREGROUND_CHANGES, should we require 1711 // the USAGE_STATS permission since this can provide information about when an 1712 // app is in the foreground? 1713 Preconditions.checkArgumentInRange(op, AppOpsManager.OP_NONE, 1714 AppOpsManager._NUM_OP - 1, "Invalid op code: " + op); 1715 if (callback == null) { 1716 return; 1717 } 1718 synchronized (this) { 1719 op = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op; 1720 ModeCallback cb = mModeWatchers.get(callback.asBinder()); 1721 if (cb == null) { 1722 cb = new ModeCallback(callback, watchedUid, flags, callingUid, callingPid); 1723 mModeWatchers.put(callback.asBinder(), cb); 1724 } 1725 if (op != AppOpsManager.OP_NONE) { 1726 ArraySet<ModeCallback> cbs = mOpModeWatchers.get(op); 1727 if (cbs == null) { 1728 cbs = new ArraySet<>(); 1729 mOpModeWatchers.put(op, cbs); 1730 } 1731 cbs.add(cb); 1732 } 1733 if (packageName != null) { 1734 ArraySet<ModeCallback> cbs = mPackageModeWatchers.get(packageName); 1735 if (cbs == null) { 1736 cbs = new ArraySet<>(); 1737 mPackageModeWatchers.put(packageName, cbs); 1738 } 1739 cbs.add(cb); 1740 } 1741 evalAllForegroundOpsLocked(); 1742 } 1743 } 1744 1745 @Override stopWatchingMode(IAppOpsCallback callback)1746 public void stopWatchingMode(IAppOpsCallback callback) { 1747 if (callback == null) { 1748 return; 1749 } 1750 synchronized (this) { 1751 ModeCallback cb = mModeWatchers.remove(callback.asBinder()); 1752 if (cb != null) { 1753 cb.unlinkToDeath(); 1754 for (int i=mOpModeWatchers.size()-1; i>=0; i--) { 1755 ArraySet<ModeCallback> cbs = mOpModeWatchers.valueAt(i); 1756 cbs.remove(cb); 1757 if (cbs.size() <= 0) { 1758 mOpModeWatchers.removeAt(i); 1759 } 1760 } 1761 for (int i=mPackageModeWatchers.size()-1; i>=0; i--) { 1762 ArraySet<ModeCallback> cbs = mPackageModeWatchers.valueAt(i); 1763 cbs.remove(cb); 1764 if (cbs.size() <= 0) { 1765 mPackageModeWatchers.removeAt(i); 1766 } 1767 } 1768 } 1769 evalAllForegroundOpsLocked(); 1770 } 1771 } 1772 1773 @Override getToken(IBinder clientToken)1774 public IBinder getToken(IBinder clientToken) { 1775 synchronized (this) { 1776 ClientState cs = mClients.get(clientToken); 1777 if (cs == null) { 1778 cs = new ClientState(clientToken); 1779 mClients.put(clientToken, cs); 1780 } 1781 return cs; 1782 } 1783 } 1784 getAppOpsServiceDelegate()1785 public CheckOpsDelegate getAppOpsServiceDelegate() { 1786 synchronized (this) { 1787 return mCheckOpsDelegate; 1788 } 1789 } 1790 setAppOpsServiceDelegate(CheckOpsDelegate delegate)1791 public void setAppOpsServiceDelegate(CheckOpsDelegate delegate) { 1792 synchronized (this) { 1793 mCheckOpsDelegate = delegate; 1794 } 1795 } 1796 1797 @Override checkOperationRaw(int code, int uid, String packageName)1798 public int checkOperationRaw(int code, int uid, String packageName) { 1799 return checkOperationInternal(code, uid, packageName, true /*raw*/); 1800 } 1801 1802 @Override checkOperation(int code, int uid, String packageName)1803 public int checkOperation(int code, int uid, String packageName) { 1804 return checkOperationInternal(code, uid, packageName, false /*raw*/); 1805 } 1806 checkOperationInternal(int code, int uid, String packageName, boolean raw)1807 private int checkOperationInternal(int code, int uid, String packageName, boolean raw) { 1808 final CheckOpsDelegate delegate; 1809 synchronized (this) { 1810 delegate = mCheckOpsDelegate; 1811 } 1812 if (delegate == null) { 1813 return checkOperationImpl(code, uid, packageName, raw); 1814 } 1815 return delegate.checkOperation(code, uid, packageName, raw, 1816 AppOpsService.this::checkOperationImpl); 1817 } 1818 checkOperationImpl(int code, int uid, String packageName, boolean raw)1819 private int checkOperationImpl(int code, int uid, String packageName, 1820 boolean raw) { 1821 verifyIncomingUid(uid); 1822 verifyIncomingOp(code); 1823 String resolvedPackageName = resolvePackageName(uid, packageName); 1824 if (resolvedPackageName == null) { 1825 return AppOpsManager.MODE_IGNORED; 1826 } 1827 return checkOperationUnchecked(code, uid, resolvedPackageName, raw); 1828 } 1829 1830 /** 1831 * @see #checkOperationUnchecked(int, int, String, boolean, boolean) 1832 */ checkOperationUnchecked(int code, int uid, @NonNull String packageName, boolean raw)1833 private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName, 1834 boolean raw) { 1835 return checkOperationUnchecked(code, uid, packageName, raw, true); 1836 } 1837 1838 /** 1839 * Get the mode of an app-op. 1840 * 1841 * @param code The code of the op 1842 * @param uid The uid of the package the op belongs to 1843 * @param packageName The package the op belongs to 1844 * @param raw If the raw state of eval-ed state should be checked. 1845 * @param verify If the code should check the package belongs to the uid 1846 * 1847 * @return The mode of the op 1848 */ checkOperationUnchecked(int code, int uid, @NonNull String packageName, boolean raw, boolean verify)1849 private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName, 1850 boolean raw, boolean verify) { 1851 if (isOpRestrictedDueToSuspend(code, packageName, uid)) { 1852 return AppOpsManager.MODE_IGNORED; 1853 } 1854 synchronized (this) { 1855 if (verify) { 1856 checkPackage(uid, packageName); 1857 } 1858 if (isOpRestrictedLocked(uid, code, packageName)) { 1859 return AppOpsManager.MODE_IGNORED; 1860 } 1861 code = AppOpsManager.opToSwitch(code); 1862 UidState uidState = getUidStateLocked(uid, false); 1863 if (uidState != null && uidState.opModes != null 1864 && uidState.opModes.indexOfKey(code) >= 0) { 1865 final int rawMode = uidState.opModes.get(code); 1866 return raw ? rawMode : uidState.evalMode(code, rawMode); 1867 } 1868 Op op = getOpLocked(code, uid, packageName, false, verify, false); 1869 if (op == null) { 1870 return AppOpsManager.opToDefaultMode(code); 1871 } 1872 return raw ? op.mode : op.evalMode(); 1873 } 1874 } 1875 1876 @Override checkAudioOperation(int code, int usage, int uid, String packageName)1877 public int checkAudioOperation(int code, int usage, int uid, String packageName) { 1878 final CheckOpsDelegate delegate; 1879 synchronized (this) { 1880 delegate = mCheckOpsDelegate; 1881 } 1882 if (delegate == null) { 1883 return checkAudioOperationImpl(code, usage, uid, packageName); 1884 } 1885 return delegate.checkAudioOperation(code, usage, uid, packageName, 1886 AppOpsService.this::checkAudioOperationImpl); 1887 } 1888 checkAudioOperationImpl(int code, int usage, int uid, String packageName)1889 private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) { 1890 boolean suspended; 1891 try { 1892 suspended = isPackageSuspendedForUser(packageName, uid); 1893 } catch (IllegalArgumentException ex) { 1894 // Package not found. 1895 suspended = false; 1896 } 1897 1898 if (suspended) { 1899 Slog.i(TAG, "Audio disabled for suspended package=" + packageName 1900 + " for uid=" + uid); 1901 return AppOpsManager.MODE_IGNORED; 1902 } 1903 1904 synchronized (this) { 1905 final int mode = checkRestrictionLocked(code, usage, uid, packageName); 1906 if (mode != AppOpsManager.MODE_ALLOWED) { 1907 return mode; 1908 } 1909 } 1910 return checkOperation(code, uid, packageName); 1911 } 1912 isPackageSuspendedForUser(String pkg, int uid)1913 private boolean isPackageSuspendedForUser(String pkg, int uid) { 1914 final long identity = Binder.clearCallingIdentity(); 1915 try { 1916 return AppGlobals.getPackageManager().isPackageSuspendedForUser( 1917 pkg, UserHandle.getUserId(uid)); 1918 } catch (RemoteException re) { 1919 throw new SecurityException("Could not talk to package manager service"); 1920 } finally { 1921 Binder.restoreCallingIdentity(identity); 1922 } 1923 } 1924 checkRestrictionLocked(int code, int usage, int uid, String packageName)1925 private int checkRestrictionLocked(int code, int usage, int uid, String packageName) { 1926 final SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code); 1927 if (usageRestrictions != null) { 1928 final Restriction r = usageRestrictions.get(usage); 1929 if (r != null && !r.exceptionPackages.contains(packageName)) { 1930 return r.mode; 1931 } 1932 } 1933 return AppOpsManager.MODE_ALLOWED; 1934 } 1935 1936 @Override setAudioRestriction(int code, int usage, int uid, int mode, String[] exceptionPackages)1937 public void setAudioRestriction(int code, int usage, int uid, int mode, 1938 String[] exceptionPackages) { 1939 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); 1940 verifyIncomingUid(uid); 1941 verifyIncomingOp(code); 1942 synchronized (this) { 1943 SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code); 1944 if (usageRestrictions == null) { 1945 usageRestrictions = new SparseArray<Restriction>(); 1946 mAudioRestrictions.put(code, usageRestrictions); 1947 } 1948 usageRestrictions.remove(usage); 1949 if (mode != AppOpsManager.MODE_ALLOWED) { 1950 final Restriction r = new Restriction(); 1951 r.mode = mode; 1952 if (exceptionPackages != null) { 1953 final int N = exceptionPackages.length; 1954 r.exceptionPackages = new ArraySet<String>(N); 1955 for (int i = 0; i < N; i++) { 1956 final String pkg = exceptionPackages[i]; 1957 if (pkg != null) { 1958 r.exceptionPackages.add(pkg.trim()); 1959 } 1960 } 1961 } 1962 usageRestrictions.put(usage, r); 1963 } 1964 } 1965 1966 mHandler.sendMessage(PooledLambda.obtainMessage( 1967 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY)); 1968 } 1969 1970 @Override checkPackage(int uid, String packageName)1971 public int checkPackage(int uid, String packageName) { 1972 Preconditions.checkNotNull(packageName); 1973 synchronized (this) { 1974 Ops ops = getOpsRawLocked(uid, packageName, true /* edit */, 1975 true /* uidMismatchExpected */); 1976 if (ops != null) { 1977 return AppOpsManager.MODE_ALLOWED; 1978 } else { 1979 return AppOpsManager.MODE_ERRORED; 1980 } 1981 } 1982 } 1983 1984 @Override noteProxyOperation(int code, int proxyUid, String proxyPackageName, int proxiedUid, String proxiedPackageName)1985 public int noteProxyOperation(int code, int proxyUid, 1986 String proxyPackageName, int proxiedUid, String proxiedPackageName) { 1987 verifyIncomingUid(proxyUid); 1988 verifyIncomingOp(code); 1989 1990 String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName); 1991 if (resolveProxyPackageName == null) { 1992 return AppOpsManager.MODE_IGNORED; 1993 } 1994 1995 final boolean isProxyTrusted = mContext.checkPermission( 1996 Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid) 1997 == PackageManager.PERMISSION_GRANTED; 1998 1999 final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY 2000 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY; 2001 final int proxyMode = noteOperationUnchecked(code, proxyUid, 2002 resolveProxyPackageName, Process.INVALID_UID, null, proxyFlags); 2003 if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) { 2004 return proxyMode; 2005 } 2006 2007 String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName); 2008 if (resolveProxiedPackageName == null) { 2009 return AppOpsManager.MODE_IGNORED; 2010 } 2011 final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED 2012 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED; 2013 return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName, 2014 proxyUid, resolveProxyPackageName, proxiedFlags); 2015 } 2016 2017 @Override noteOperation(int code, int uid, String packageName)2018 public int noteOperation(int code, int uid, String packageName) { 2019 final CheckOpsDelegate delegate; 2020 synchronized (this) { 2021 delegate = mCheckOpsDelegate; 2022 } 2023 if (delegate == null) { 2024 return noteOperationImpl(code, uid, packageName); 2025 } 2026 return delegate.noteOperation(code, uid, packageName, 2027 AppOpsService.this::noteOperationImpl); 2028 } 2029 noteOperationImpl(int code, int uid, String packageName)2030 private int noteOperationImpl(int code, int uid, String packageName) { 2031 verifyIncomingUid(uid); 2032 verifyIncomingOp(code); 2033 String resolvedPackageName = resolvePackageName(uid, packageName); 2034 if (resolvedPackageName == null) { 2035 return AppOpsManager.MODE_IGNORED; 2036 } 2037 return noteOperationUnchecked(code, uid, resolvedPackageName, Process.INVALID_UID, null, 2038 AppOpsManager.OP_FLAG_SELF); 2039 } 2040 noteOperationUnchecked(int code, int uid, String packageName, int proxyUid, String proxyPackageName, @OpFlags int flags)2041 private int noteOperationUnchecked(int code, int uid, String packageName, 2042 int proxyUid, String proxyPackageName, @OpFlags int flags) { 2043 synchronized (this) { 2044 final Ops ops = getOpsRawLocked(uid, packageName, true /* edit */, 2045 false /* uidMismatchExpected */); 2046 if (ops == null) { 2047 scheduleOpNotedIfNeededLocked(code, uid, packageName, 2048 AppOpsManager.MODE_IGNORED); 2049 if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid 2050 + " package " + packageName); 2051 return AppOpsManager.MODE_ERRORED; 2052 } 2053 final Op op = getOpLocked(ops, code, true); 2054 if (isOpRestrictedLocked(uid, code, packageName)) { 2055 scheduleOpNotedIfNeededLocked(code, uid, packageName, 2056 AppOpsManager.MODE_IGNORED); 2057 return AppOpsManager.MODE_IGNORED; 2058 } 2059 final UidState uidState = ops.uidState; 2060 if (op.running) { 2061 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes, 2062 op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames); 2063 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName 2064 + " code " + code + " time=" + entry.getLastAccessTime(uidState.state, 2065 uidState.state, flags) + " duration=" + entry.getLastDuration( 2066 uidState.state, uidState.state, flags)); 2067 } 2068 2069 final int switchCode = AppOpsManager.opToSwitch(code); 2070 // If there is a non-default per UID policy (we set UID op mode only if 2071 // non-default) it takes over, otherwise use the per package policy. 2072 if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) { 2073 final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode)); 2074 if (uidMode != AppOpsManager.MODE_ALLOWED) { 2075 if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code " 2076 + switchCode + " (" + code + ") uid " + uid + " package " 2077 + packageName); 2078 op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName, 2079 uidState.state, flags); 2080 mHistoricalRegistry.incrementOpRejected(code, uid, packageName, 2081 uidState.state, flags); 2082 scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode); 2083 return uidMode; 2084 } 2085 } else { 2086 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; 2087 final int mode = switchOp.evalMode(); 2088 if (switchOp.mode != AppOpsManager.MODE_ALLOWED) { 2089 if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code " 2090 + switchCode + " (" + code + ") uid " + uid + " package " 2091 + packageName); 2092 op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName, 2093 uidState.state, flags); 2094 mHistoricalRegistry.incrementOpRejected(code, uid, packageName, 2095 uidState.state, flags); 2096 scheduleOpNotedIfNeededLocked(code, uid, packageName, mode); 2097 return mode; 2098 } 2099 } 2100 if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid 2101 + " package " + packageName); 2102 op.accessed(System.currentTimeMillis(), proxyUid, proxyPackageName, 2103 uidState.state, flags); 2104 mHistoricalRegistry.incrementOpAccessedCount(op.op, uid, packageName, 2105 uidState.state, flags); 2106 scheduleOpNotedIfNeededLocked(code, uid, packageName, 2107 AppOpsManager.MODE_ALLOWED); 2108 return AppOpsManager.MODE_ALLOWED; 2109 } 2110 } 2111 2112 @Override startWatchingActive(int[] ops, IAppOpsActiveCallback callback)2113 public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) { 2114 int watchedUid = -1; 2115 final int callingUid = Binder.getCallingUid(); 2116 final int callingPid = Binder.getCallingPid(); 2117 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 2118 != PackageManager.PERMISSION_GRANTED) { 2119 watchedUid = callingUid; 2120 } 2121 if (ops != null) { 2122 Preconditions.checkArrayElementsInRange(ops, 0, 2123 AppOpsManager._NUM_OP - 1, "Invalid op code in: " + Arrays.toString(ops)); 2124 } 2125 if (callback == null) { 2126 return; 2127 } 2128 synchronized (this) { 2129 SparseArray<ActiveCallback> callbacks = mActiveWatchers.get(callback.asBinder()); 2130 if (callbacks == null) { 2131 callbacks = new SparseArray<>(); 2132 mActiveWatchers.put(callback.asBinder(), callbacks); 2133 } 2134 final ActiveCallback activeCallback = new ActiveCallback(callback, watchedUid, 2135 callingUid, callingPid); 2136 for (int op : ops) { 2137 callbacks.put(op, activeCallback); 2138 } 2139 } 2140 } 2141 2142 @Override stopWatchingActive(IAppOpsActiveCallback callback)2143 public void stopWatchingActive(IAppOpsActiveCallback callback) { 2144 if (callback == null) { 2145 return; 2146 } 2147 synchronized (this) { 2148 final SparseArray<ActiveCallback> activeCallbacks = 2149 mActiveWatchers.remove(callback.asBinder()); 2150 if (activeCallbacks == null) { 2151 return; 2152 } 2153 final int callbackCount = activeCallbacks.size(); 2154 for (int i = 0; i < callbackCount; i++) { 2155 activeCallbacks.valueAt(i).destroy(); 2156 } 2157 } 2158 } 2159 2160 @Override startWatchingNoted(@onNull int[] ops, @NonNull IAppOpsNotedCallback callback)2161 public void startWatchingNoted(@NonNull int[] ops, @NonNull IAppOpsNotedCallback callback) { 2162 int watchedUid = Process.INVALID_UID; 2163 final int callingUid = Binder.getCallingUid(); 2164 final int callingPid = Binder.getCallingPid(); 2165 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 2166 != PackageManager.PERMISSION_GRANTED) { 2167 watchedUid = callingUid; 2168 } 2169 Preconditions.checkArgument(!ArrayUtils.isEmpty(ops), "Ops cannot be null or empty"); 2170 Preconditions.checkArrayElementsInRange(ops, 0, AppOpsManager._NUM_OP - 1, 2171 "Invalid op code in: " + Arrays.toString(ops)); 2172 Preconditions.checkNotNull(callback, "Callback cannot be null"); 2173 synchronized (this) { 2174 SparseArray<NotedCallback> callbacks = mNotedWatchers.get(callback.asBinder()); 2175 if (callbacks == null) { 2176 callbacks = new SparseArray<>(); 2177 mNotedWatchers.put(callback.asBinder(), callbacks); 2178 } 2179 final NotedCallback notedCallback = new NotedCallback(callback, watchedUid, 2180 callingUid, callingPid); 2181 for (int op : ops) { 2182 callbacks.put(op, notedCallback); 2183 } 2184 } 2185 } 2186 2187 @Override stopWatchingNoted(IAppOpsNotedCallback callback)2188 public void stopWatchingNoted(IAppOpsNotedCallback callback) { 2189 Preconditions.checkNotNull(callback, "Callback cannot be null"); 2190 synchronized (this) { 2191 final SparseArray<NotedCallback> notedCallbacks = 2192 mNotedWatchers.remove(callback.asBinder()); 2193 if (notedCallbacks == null) { 2194 return; 2195 } 2196 final int callbackCount = notedCallbacks.size(); 2197 for (int i = 0; i < callbackCount; i++) { 2198 notedCallbacks.valueAt(i).destroy(); 2199 } 2200 } 2201 } 2202 2203 @Override startOperation(IBinder token, int code, int uid, String packageName, boolean startIfModeDefault)2204 public int startOperation(IBinder token, int code, int uid, String packageName, 2205 boolean startIfModeDefault) { 2206 verifyIncomingUid(uid); 2207 verifyIncomingOp(code); 2208 String resolvedPackageName = resolvePackageName(uid, packageName); 2209 if (resolvedPackageName == null) { 2210 return AppOpsManager.MODE_IGNORED; 2211 } 2212 ClientState client = (ClientState)token; 2213 synchronized (this) { 2214 final Ops ops = getOpsRawLocked(uid, resolvedPackageName, true /* edit */, 2215 false /* uidMismatchExpected */); 2216 if (ops == null) { 2217 if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid 2218 + " package " + resolvedPackageName); 2219 return AppOpsManager.MODE_ERRORED; 2220 } 2221 final Op op = getOpLocked(ops, code, true); 2222 if (isOpRestrictedLocked(uid, code, resolvedPackageName)) { 2223 return AppOpsManager.MODE_IGNORED; 2224 } 2225 final int switchCode = AppOpsManager.opToSwitch(code); 2226 final UidState uidState = ops.uidState; 2227 // If there is a non-default per UID policy (we set UID op mode only if 2228 // non-default) it takes over, otherwise use the per package policy. 2229 final int opCode = op.op; 2230 if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) { 2231 final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode)); 2232 if (uidMode != AppOpsManager.MODE_ALLOWED 2233 && (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) { 2234 if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code " 2235 + switchCode + " (" + code + ") uid " + uid + " package " 2236 + resolvedPackageName); 2237 // We don't support proxy long running ops (start/stop) 2238 op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/, 2239 null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF); 2240 mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName, 2241 uidState.state, AppOpsManager.OP_FLAG_SELF); 2242 return uidMode; 2243 } 2244 } else { 2245 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; 2246 final int mode = switchOp.evalMode(); 2247 if (mode != AppOpsManager.MODE_ALLOWED 2248 && (!startIfModeDefault || mode != AppOpsManager.MODE_DEFAULT)) { 2249 if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code " 2250 + switchCode + " (" + code + ") uid " + uid + " package " 2251 + resolvedPackageName); 2252 // We don't support proxy long running ops (start/stop) 2253 op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/, 2254 null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF); 2255 mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName, 2256 uidState.state, AppOpsManager.OP_FLAG_SELF); 2257 return mode; 2258 } 2259 } 2260 if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid 2261 + " package " + resolvedPackageName); 2262 if (op.startNesting == 0) { 2263 op.startRealtime = SystemClock.elapsedRealtime(); 2264 // We don't support proxy long running ops (start/stop) 2265 op.started(System.currentTimeMillis(), uidState.state, 2266 AppOpsManager.OP_FLAG_SELF); 2267 mHistoricalRegistry.incrementOpAccessedCount(opCode, uid, packageName, 2268 uidState.state, AppOpsManager.OP_FLAG_SELF); 2269 2270 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true); 2271 } 2272 op.startNesting++; 2273 uidState.startNesting++; 2274 if (client.mStartedOps != null) { 2275 client.mStartedOps.add(op); 2276 } 2277 } 2278 2279 return AppOpsManager.MODE_ALLOWED; 2280 } 2281 2282 @Override finishOperation(IBinder token, int code, int uid, String packageName)2283 public void finishOperation(IBinder token, int code, int uid, String packageName) { 2284 verifyIncomingUid(uid); 2285 verifyIncomingOp(code); 2286 String resolvedPackageName = resolvePackageName(uid, packageName); 2287 if (resolvedPackageName == null) { 2288 return; 2289 } 2290 if (!(token instanceof ClientState)) { 2291 return; 2292 } 2293 ClientState client = (ClientState) token; 2294 synchronized (this) { 2295 Op op = getOpLocked(code, uid, resolvedPackageName, true, true, false); 2296 if (op == null) { 2297 return; 2298 } 2299 if (!client.mStartedOps.remove(op)) { 2300 // We finish ops when packages get removed to guarantee no dangling 2301 // started ops. However, some part of the system may asynchronously 2302 // finish ops for an already gone package. Hence, finishing an op 2303 // for a non existing package is fine and we don't log as a wtf. 2304 final long identity = Binder.clearCallingIdentity(); 2305 try { 2306 if (LocalServices.getService(PackageManagerInternal.class).getPackageUid( 2307 resolvedPackageName, 0, UserHandle.getUserId(uid)) < 0) { 2308 Slog.i(TAG, "Finishing op=" + AppOpsManager.opToName(code) 2309 + " for non-existing package=" + resolvedPackageName 2310 + " in uid=" + uid); 2311 return; 2312 } 2313 } finally { 2314 Binder.restoreCallingIdentity(identity); 2315 } 2316 Slog.wtf(TAG, "Operation not started: uid=" + op.uidState.uid + " pkg=" 2317 + op.packageName + " op=" + AppOpsManager.opToName(op.op)); 2318 return; 2319 } 2320 finishOperationLocked(op, /*finishNested*/ false); 2321 if (op.startNesting <= 0) { 2322 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, false); 2323 } 2324 } 2325 } 2326 scheduleOpActiveChangedIfNeededLocked(int code, int uid, String packageName, boolean active)2327 private void scheduleOpActiveChangedIfNeededLocked(int code, int uid, String packageName, 2328 boolean active) { 2329 ArraySet<ActiveCallback> dispatchedCallbacks = null; 2330 final int callbackListCount = mActiveWatchers.size(); 2331 for (int i = 0; i < callbackListCount; i++) { 2332 final SparseArray<ActiveCallback> callbacks = mActiveWatchers.valueAt(i); 2333 ActiveCallback callback = callbacks.get(code); 2334 if (callback != null) { 2335 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 2336 continue; 2337 } 2338 if (dispatchedCallbacks == null) { 2339 dispatchedCallbacks = new ArraySet<>(); 2340 } 2341 dispatchedCallbacks.add(callback); 2342 } 2343 } 2344 if (dispatchedCallbacks == null) { 2345 return; 2346 } 2347 mHandler.sendMessage(PooledLambda.obtainMessage( 2348 AppOpsService::notifyOpActiveChanged, 2349 this, dispatchedCallbacks, code, uid, packageName, active)); 2350 } 2351 notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks, int code, int uid, String packageName, boolean active)2352 private void notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks, 2353 int code, int uid, String packageName, boolean active) { 2354 // There are components watching for mode changes such as window manager 2355 // and location manager which are in our process. The callbacks in these 2356 // components may require permissions our remote caller does not have. 2357 final long identity = Binder.clearCallingIdentity(); 2358 try { 2359 final int callbackCount = callbacks.size(); 2360 for (int i = 0; i < callbackCount; i++) { 2361 final ActiveCallback callback = callbacks.valueAt(i); 2362 try { 2363 callback.mCallback.opActiveChanged(code, uid, packageName, active); 2364 } catch (RemoteException e) { 2365 /* do nothing */ 2366 } 2367 } 2368 } finally { 2369 Binder.restoreCallingIdentity(identity); 2370 } 2371 } 2372 scheduleOpNotedIfNeededLocked(int code, int uid, String packageName, int result)2373 private void scheduleOpNotedIfNeededLocked(int code, int uid, String packageName, 2374 int result) { 2375 ArraySet<NotedCallback> dispatchedCallbacks = null; 2376 final int callbackListCount = mNotedWatchers.size(); 2377 for (int i = 0; i < callbackListCount; i++) { 2378 final SparseArray<NotedCallback> callbacks = mNotedWatchers.valueAt(i); 2379 final NotedCallback callback = callbacks.get(code); 2380 if (callback != null) { 2381 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 2382 continue; 2383 } 2384 if (dispatchedCallbacks == null) { 2385 dispatchedCallbacks = new ArraySet<>(); 2386 } 2387 dispatchedCallbacks.add(callback); 2388 } 2389 } 2390 if (dispatchedCallbacks == null) { 2391 return; 2392 } 2393 mHandler.sendMessage(PooledLambda.obtainMessage( 2394 AppOpsService::notifyOpChecked, 2395 this, dispatchedCallbacks, code, uid, packageName, result)); 2396 } 2397 notifyOpChecked(ArraySet<NotedCallback> callbacks, int code, int uid, String packageName, int result)2398 private void notifyOpChecked(ArraySet<NotedCallback> callbacks, 2399 int code, int uid, String packageName, int result) { 2400 // There are components watching for checks in our process. The callbacks in 2401 // these components may require permissions our remote caller does not have. 2402 final long identity = Binder.clearCallingIdentity(); 2403 try { 2404 final int callbackCount = callbacks.size(); 2405 for (int i = 0; i < callbackCount; i++) { 2406 final NotedCallback callback = callbacks.valueAt(i); 2407 try { 2408 callback.mCallback.opNoted(code, uid, packageName, result); 2409 } catch (RemoteException e) { 2410 /* do nothing */ 2411 } 2412 } 2413 } finally { 2414 Binder.restoreCallingIdentity(identity); 2415 } 2416 } 2417 2418 @Override permissionToOpCode(String permission)2419 public int permissionToOpCode(String permission) { 2420 if (permission == null) { 2421 return AppOpsManager.OP_NONE; 2422 } 2423 return AppOpsManager.permissionToOpCode(permission); 2424 } 2425 finishOperationLocked(Op op, boolean finishNested)2426 void finishOperationLocked(Op op, boolean finishNested) { 2427 final int opCode = op.op; 2428 final int uid = op.uidState.uid; 2429 if (op.startNesting <= 1 || finishNested) { 2430 if (op.startNesting == 1 || finishNested) { 2431 // We don't support proxy long running ops (start/stop) 2432 final long duration = SystemClock.elapsedRealtime() - op.startRealtime; 2433 op.finished(System.currentTimeMillis(), duration, op.uidState.state, 2434 AppOpsManager.OP_FLAG_SELF); 2435 mHistoricalRegistry.increaseOpAccessDuration(opCode, uid, op.packageName, 2436 op.uidState.state, AppOpsManager.OP_FLAG_SELF, duration); 2437 } else { 2438 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes, 2439 op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames); 2440 Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg " 2441 + op.packageName + " code " + opCode + " time=" 2442 + entry.getLastAccessTime(OP_FLAGS_ALL) 2443 + " duration=" + entry.getLastDuration(MAX_PRIORITY_UID_STATE, 2444 MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL) + " nesting=" + op.startNesting); 2445 } 2446 if (op.startNesting >= 1) { 2447 op.uidState.startNesting -= op.startNesting; 2448 } 2449 op.startNesting = 0; 2450 } else { 2451 op.startNesting--; 2452 op.uidState.startNesting--; 2453 } 2454 } 2455 verifyIncomingUid(int uid)2456 private void verifyIncomingUid(int uid) { 2457 if (uid == Binder.getCallingUid()) { 2458 return; 2459 } 2460 if (Binder.getCallingPid() == Process.myPid()) { 2461 return; 2462 } 2463 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 2464 Binder.getCallingPid(), Binder.getCallingUid(), null); 2465 } 2466 verifyIncomingOp(int op)2467 private void verifyIncomingOp(int op) { 2468 if (op >= 0 && op < AppOpsManager._NUM_OP) { 2469 return; 2470 } 2471 throw new IllegalArgumentException("Bad operation #" + op); 2472 } 2473 getUidStateLocked(int uid, boolean edit)2474 private @Nullable UidState getUidStateLocked(int uid, boolean edit) { 2475 UidState uidState = mUidStates.get(uid); 2476 if (uidState == null) { 2477 if (!edit) { 2478 return null; 2479 } 2480 uidState = new UidState(uid); 2481 mUidStates.put(uid, uidState); 2482 } else { 2483 updatePendingStateIfNeededLocked(uidState); 2484 } 2485 return uidState; 2486 } 2487 2488 /** 2489 * Check if the pending state should be updated and do so if needed 2490 * 2491 * @param uidState The uidState that might have a pending state 2492 */ updatePendingStateIfNeededLocked(@onNull UidState uidState)2493 private void updatePendingStateIfNeededLocked(@NonNull UidState uidState) { 2494 if (uidState != null) { 2495 if (uidState.pendingStateCommitTime != 0) { 2496 if (uidState.pendingStateCommitTime < mLastRealtime) { 2497 commitUidPendingStateLocked(uidState); 2498 } else { 2499 mLastRealtime = SystemClock.elapsedRealtime(); 2500 if (uidState.pendingStateCommitTime < mLastRealtime) { 2501 commitUidPendingStateLocked(uidState); 2502 } 2503 } 2504 } 2505 } 2506 } 2507 commitUidPendingStateLocked(UidState uidState)2508 private void commitUidPendingStateLocked(UidState uidState) { 2509 if (uidState.hasForegroundWatchers) { 2510 for (int fgi = uidState.foregroundOps.size() - 1; fgi >= 0; fgi--) { 2511 if (!uidState.foregroundOps.valueAt(fgi)) { 2512 continue; 2513 } 2514 final int code = uidState.foregroundOps.keyAt(fgi); 2515 // For location ops we consider fg state only if the fg service 2516 // is of location type, for all other ops any fg service will do. 2517 final long firstUnrestrictedUidState = resolveFirstUnrestrictedUidState(code); 2518 final boolean resolvedLastFg = uidState.state <= firstUnrestrictedUidState; 2519 final boolean resolvedNowFg = uidState.pendingState <= firstUnrestrictedUidState; 2520 if (resolvedLastFg == resolvedNowFg) { 2521 continue; 2522 } 2523 2524 if (uidState.opModes != null 2525 && uidState.opModes.indexOfKey(code) >= 0 2526 && uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND) { 2527 mHandler.sendMessage(PooledLambda.obtainMessage( 2528 AppOpsService::notifyOpChangedForAllPkgsInUid, 2529 this, code, uidState.uid, true)); 2530 } else { 2531 final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code); 2532 if (callbacks != null) { 2533 for (int cbi = callbacks.size() - 1; cbi >= 0; cbi--) { 2534 final ModeCallback callback = callbacks.valueAt(cbi); 2535 if ((callback.mFlags & AppOpsManager.WATCH_FOREGROUND_CHANGES) == 0 2536 || !callback.isWatchingUid(uidState.uid)) { 2537 continue; 2538 } 2539 for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) { 2540 final Op op = uidState.pkgOps.valueAt(pkgi).get(code); 2541 if (op == null) { 2542 continue; 2543 } 2544 if (op.mode == AppOpsManager.MODE_FOREGROUND) { 2545 mHandler.sendMessage(PooledLambda.obtainMessage( 2546 AppOpsService::notifyOpChanged, 2547 this, callback, code, uidState.uid, 2548 uidState.pkgOps.keyAt(pkgi))); 2549 } 2550 } 2551 } 2552 } 2553 } 2554 } 2555 } 2556 uidState.state = uidState.pendingState; 2557 uidState.pendingStateCommitTime = 0; 2558 } 2559 getOpsRawLocked(int uid, String packageName, boolean edit, boolean uidMismatchExpected)2560 private Ops getOpsRawLocked(int uid, String packageName, boolean edit, 2561 boolean uidMismatchExpected) { 2562 UidState uidState = getUidStateLocked(uid, edit); 2563 if (uidState == null) { 2564 return null; 2565 } 2566 2567 if (uidState.pkgOps == null) { 2568 if (!edit) { 2569 return null; 2570 } 2571 uidState.pkgOps = new ArrayMap<>(); 2572 } 2573 2574 Ops ops = uidState.pkgOps.get(packageName); 2575 if (ops == null) { 2576 if (!edit) { 2577 return null; 2578 } 2579 boolean isPrivileged = false; 2580 // This is the first time we have seen this package name under this uid, 2581 // so let's make sure it is valid. 2582 if (uid != 0) { 2583 final long ident = Binder.clearCallingIdentity(); 2584 try { 2585 int pkgUid = -1; 2586 try { 2587 ApplicationInfo appInfo = ActivityThread.getPackageManager() 2588 .getApplicationInfo(packageName, 2589 PackageManager.MATCH_DIRECT_BOOT_AWARE 2590 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 2591 UserHandle.getUserId(uid)); 2592 if (appInfo != null) { 2593 pkgUid = appInfo.uid; 2594 isPrivileged = (appInfo.privateFlags 2595 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; 2596 } else { 2597 pkgUid = resolveUid(packageName); 2598 if (pkgUid >= 0) { 2599 isPrivileged = false; 2600 } 2601 } 2602 } catch (RemoteException e) { 2603 Slog.w(TAG, "Could not contact PackageManager", e); 2604 } 2605 if (pkgUid != uid) { 2606 // Oops! The package name is not valid for the uid they are calling 2607 // under. Abort. 2608 if (!uidMismatchExpected) { 2609 RuntimeException ex = new RuntimeException("here"); 2610 ex.fillInStackTrace(); 2611 Slog.w(TAG, "Bad call: specified package " + packageName 2612 + " under uid " + uid + " but it is really " + pkgUid, ex); 2613 } 2614 return null; 2615 } 2616 } finally { 2617 Binder.restoreCallingIdentity(ident); 2618 } 2619 } 2620 ops = new Ops(packageName, uidState, isPrivileged); 2621 uidState.pkgOps.put(packageName, ops); 2622 } 2623 return ops; 2624 } 2625 2626 /** 2627 * Get the state of all ops for a package, <b>don't verify that package belongs to uid</b>. 2628 * 2629 * <p>Usually callers should use {@link #getOpLocked} and not call this directly. 2630 * 2631 * @param uid The uid the of the package 2632 * @param packageName The package name for which to get the state for 2633 * @param edit Iff {@code true} create the {@link Ops} object if not yet created 2634 * @param isPrivileged Whether the package is privileged or not 2635 * 2636 * @return The {@link Ops state} of all ops for the package 2637 */ getOpsRawNoVerifyLocked(int uid, @NonNull String packageName, boolean edit, boolean isPrivileged)2638 private @Nullable Ops getOpsRawNoVerifyLocked(int uid, @NonNull String packageName, 2639 boolean edit, boolean isPrivileged) { 2640 UidState uidState = getUidStateLocked(uid, edit); 2641 if (uidState == null) { 2642 return null; 2643 } 2644 2645 if (uidState.pkgOps == null) { 2646 if (!edit) { 2647 return null; 2648 } 2649 uidState.pkgOps = new ArrayMap<>(); 2650 } 2651 2652 Ops ops = uidState.pkgOps.get(packageName); 2653 if (ops == null) { 2654 if (!edit) { 2655 return null; 2656 } 2657 ops = new Ops(packageName, uidState, isPrivileged); 2658 uidState.pkgOps.put(packageName, ops); 2659 } 2660 return ops; 2661 } 2662 scheduleWriteLocked()2663 private void scheduleWriteLocked() { 2664 if (!mWriteScheduled) { 2665 mWriteScheduled = true; 2666 mHandler.postDelayed(mWriteRunner, WRITE_DELAY); 2667 } 2668 } 2669 scheduleFastWriteLocked()2670 private void scheduleFastWriteLocked() { 2671 if (!mFastWriteScheduled) { 2672 mWriteScheduled = true; 2673 mFastWriteScheduled = true; 2674 mHandler.removeCallbacks(mWriteRunner); 2675 mHandler.postDelayed(mWriteRunner, 10*1000); 2676 } 2677 } 2678 2679 /** 2680 * Get the state of an op for a uid. 2681 * 2682 * @param code The code of the op 2683 * @param uid The uid the of the package 2684 * @param packageName The package name for which to get the state for 2685 * @param edit Iff {@code true} create the {@link Op} object if not yet created 2686 * @param verifyUid Iff {@code true} check that the package belongs to the uid 2687 * @param isPrivileged Whether the package is privileged or not (only used if {@code verifyUid 2688 * == false}) 2689 * 2690 * @return The {@link Op state} of the op 2691 */ getOpLocked(int code, int uid, @NonNull String packageName, boolean edit, boolean verifyUid, boolean isPrivileged)2692 private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName, boolean edit, 2693 boolean verifyUid, boolean isPrivileged) { 2694 Ops ops; 2695 2696 if (verifyUid) { 2697 ops = getOpsRawLocked(uid, packageName, edit, false /* uidMismatchExpected */); 2698 } else { 2699 ops = getOpsRawNoVerifyLocked(uid, packageName, edit, isPrivileged); 2700 } 2701 2702 if (ops == null) { 2703 return null; 2704 } 2705 return getOpLocked(ops, code, edit); 2706 } 2707 getOpLocked(Ops ops, int code, boolean edit)2708 private Op getOpLocked(Ops ops, int code, boolean edit) { 2709 Op op = ops.get(code); 2710 if (op == null) { 2711 if (!edit) { 2712 return null; 2713 } 2714 op = new Op(ops.uidState, ops.packageName, code); 2715 ops.put(code, op); 2716 } 2717 if (edit) { 2718 scheduleWriteLocked(); 2719 } 2720 return op; 2721 } 2722 isOpRestrictedDueToSuspend(int code, String packageName, int uid)2723 private boolean isOpRestrictedDueToSuspend(int code, String packageName, int uid) { 2724 if (!ArrayUtils.contains(OPS_RESTRICTED_ON_SUSPEND, code)) { 2725 return false; 2726 } 2727 final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); 2728 return pmi.isPackageSuspended(packageName, UserHandle.getUserId(uid)); 2729 } 2730 isOpRestrictedLocked(int uid, int code, String packageName)2731 private boolean isOpRestrictedLocked(int uid, int code, String packageName) { 2732 int userHandle = UserHandle.getUserId(uid); 2733 final int restrictionSetCount = mOpUserRestrictions.size(); 2734 2735 for (int i = 0; i < restrictionSetCount; i++) { 2736 // For each client, check that the given op is not restricted, or that the given 2737 // package is exempt from the restriction. 2738 ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); 2739 if (restrictionState.hasRestriction(code, packageName, userHandle)) { 2740 if (AppOpsManager.opAllowSystemBypassRestriction(code)) { 2741 // If we are the system, bypass user restrictions for certain codes 2742 synchronized (this) { 2743 Ops ops = getOpsRawLocked(uid, packageName, true /* edit */, 2744 false /* uidMismatchExpected */); 2745 if ((ops != null) && ops.isPrivileged) { 2746 return false; 2747 } 2748 } 2749 } 2750 return true; 2751 } 2752 } 2753 return false; 2754 } 2755 readState()2756 void readState() { 2757 int oldVersion = NO_VERSION; 2758 synchronized (mFile) { 2759 synchronized (this) { 2760 FileInputStream stream; 2761 try { 2762 stream = mFile.openRead(); 2763 } catch (FileNotFoundException e) { 2764 Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty"); 2765 return; 2766 } 2767 boolean success = false; 2768 mUidStates.clear(); 2769 try { 2770 XmlPullParser parser = Xml.newPullParser(); 2771 parser.setInput(stream, StandardCharsets.UTF_8.name()); 2772 int type; 2773 while ((type = parser.next()) != XmlPullParser.START_TAG 2774 && type != XmlPullParser.END_DOCUMENT) { 2775 ; 2776 } 2777 2778 if (type != XmlPullParser.START_TAG) { 2779 throw new IllegalStateException("no start tag found"); 2780 } 2781 2782 final String versionString = parser.getAttributeValue(null, "v"); 2783 if (versionString != null) { 2784 oldVersion = Integer.parseInt(versionString); 2785 } 2786 2787 int outerDepth = parser.getDepth(); 2788 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2789 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2790 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2791 continue; 2792 } 2793 2794 String tagName = parser.getName(); 2795 if (tagName.equals("pkg")) { 2796 readPackage(parser); 2797 } else if (tagName.equals("uid")) { 2798 readUidOps(parser); 2799 } else { 2800 Slog.w(TAG, "Unknown element under <app-ops>: " 2801 + parser.getName()); 2802 XmlUtils.skipCurrentTag(parser); 2803 } 2804 } 2805 success = true; 2806 } catch (IllegalStateException e) { 2807 Slog.w(TAG, "Failed parsing " + e); 2808 } catch (NullPointerException e) { 2809 Slog.w(TAG, "Failed parsing " + e); 2810 } catch (NumberFormatException e) { 2811 Slog.w(TAG, "Failed parsing " + e); 2812 } catch (XmlPullParserException e) { 2813 Slog.w(TAG, "Failed parsing " + e); 2814 } catch (IOException e) { 2815 Slog.w(TAG, "Failed parsing " + e); 2816 } catch (IndexOutOfBoundsException e) { 2817 Slog.w(TAG, "Failed parsing " + e); 2818 } finally { 2819 if (!success) { 2820 mUidStates.clear(); 2821 } 2822 try { 2823 stream.close(); 2824 } catch (IOException e) { 2825 } 2826 } 2827 } 2828 } 2829 synchronized (this) { 2830 upgradeLocked(oldVersion); 2831 } 2832 } 2833 upgradeRunAnyInBackgroundLocked()2834 private void upgradeRunAnyInBackgroundLocked() { 2835 for (int i = 0; i < mUidStates.size(); i++) { 2836 final UidState uidState = mUidStates.valueAt(i); 2837 if (uidState == null) { 2838 continue; 2839 } 2840 if (uidState.opModes != null) { 2841 final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND); 2842 if (idx >= 0) { 2843 uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, 2844 uidState.opModes.valueAt(idx)); 2845 } 2846 } 2847 if (uidState.pkgOps == null) { 2848 continue; 2849 } 2850 boolean changed = false; 2851 for (int j = 0; j < uidState.pkgOps.size(); j++) { 2852 Ops ops = uidState.pkgOps.valueAt(j); 2853 if (ops != null) { 2854 final Op op = ops.get(AppOpsManager.OP_RUN_IN_BACKGROUND); 2855 if (op != null && op.mode != AppOpsManager.opToDefaultMode(op.op)) { 2856 final Op copy = new Op(op.uidState, op.packageName, 2857 AppOpsManager.OP_RUN_ANY_IN_BACKGROUND); 2858 copy.mode = op.mode; 2859 ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy); 2860 changed = true; 2861 } 2862 } 2863 } 2864 if (changed) { 2865 uidState.evalForegroundOps(mOpModeWatchers); 2866 } 2867 } 2868 } 2869 upgradeLocked(int oldVersion)2870 private void upgradeLocked(int oldVersion) { 2871 if (oldVersion >= CURRENT_VERSION) { 2872 return; 2873 } 2874 Slog.d(TAG, "Upgrading app-ops xml from version " + oldVersion + " to " + CURRENT_VERSION); 2875 switch (oldVersion) { 2876 case NO_VERSION: 2877 upgradeRunAnyInBackgroundLocked(); 2878 // fall through 2879 case 1: 2880 // for future upgrades 2881 } 2882 scheduleFastWriteLocked(); 2883 } 2884 readUidOps(XmlPullParser parser)2885 private void readUidOps(XmlPullParser parser) throws NumberFormatException, 2886 XmlPullParserException, IOException { 2887 final int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 2888 int outerDepth = parser.getDepth(); 2889 int type; 2890 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2891 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2892 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2893 continue; 2894 } 2895 2896 String tagName = parser.getName(); 2897 if (tagName.equals("op")) { 2898 final int code = Integer.parseInt(parser.getAttributeValue(null, "n")); 2899 final int mode = Integer.parseInt(parser.getAttributeValue(null, "m")); 2900 UidState uidState = getUidStateLocked(uid, true); 2901 if (uidState.opModes == null) { 2902 uidState.opModes = new SparseIntArray(); 2903 } 2904 uidState.opModes.put(code, mode); 2905 } else { 2906 Slog.w(TAG, "Unknown element under <uid-ops>: " 2907 + parser.getName()); 2908 XmlUtils.skipCurrentTag(parser); 2909 } 2910 } 2911 } 2912 readPackage(XmlPullParser parser)2913 private void readPackage(XmlPullParser parser) 2914 throws NumberFormatException, XmlPullParserException, IOException { 2915 String pkgName = parser.getAttributeValue(null, "n"); 2916 int outerDepth = parser.getDepth(); 2917 int type; 2918 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2919 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2920 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2921 continue; 2922 } 2923 2924 String tagName = parser.getName(); 2925 if (tagName.equals("uid")) { 2926 readUid(parser, pkgName); 2927 } else { 2928 Slog.w(TAG, "Unknown element under <pkg>: " 2929 + parser.getName()); 2930 XmlUtils.skipCurrentTag(parser); 2931 } 2932 } 2933 } 2934 readUid(XmlPullParser parser, String pkgName)2935 private void readUid(XmlPullParser parser, String pkgName) 2936 throws NumberFormatException, XmlPullParserException, IOException { 2937 int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 2938 final UidState uidState = getUidStateLocked(uid, true); 2939 String isPrivilegedString = parser.getAttributeValue(null, "p"); 2940 boolean isPrivileged = false; 2941 if (isPrivilegedString == null) { 2942 try { 2943 IPackageManager packageManager = ActivityThread.getPackageManager(); 2944 if (packageManager != null) { 2945 ApplicationInfo appInfo = ActivityThread.getPackageManager() 2946 .getApplicationInfo(pkgName, 0, UserHandle.getUserId(uid)); 2947 if (appInfo != null) { 2948 isPrivileged = (appInfo.privateFlags 2949 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; 2950 } 2951 } else { 2952 // Could not load data, don't add to cache so it will be loaded later. 2953 return; 2954 } 2955 } catch (RemoteException e) { 2956 Slog.w(TAG, "Could not contact PackageManager", e); 2957 } 2958 } else { 2959 isPrivileged = Boolean.parseBoolean(isPrivilegedString); 2960 } 2961 int outerDepth = parser.getDepth(); 2962 int type; 2963 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2964 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2965 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2966 continue; 2967 } 2968 String tagName = parser.getName(); 2969 if (tagName.equals("op")) { 2970 readOp(parser, uidState, pkgName, isPrivileged); 2971 } else { 2972 Slog.w(TAG, "Unknown element under <pkg>: " 2973 + parser.getName()); 2974 XmlUtils.skipCurrentTag(parser); 2975 } 2976 } 2977 uidState.evalForegroundOps(mOpModeWatchers); 2978 } 2979 readOp(XmlPullParser parser, @NonNull UidState uidState, @NonNull String pkgName, boolean isPrivileged)2980 private void readOp(XmlPullParser parser, @NonNull UidState uidState, 2981 @NonNull String pkgName, boolean isPrivileged) throws NumberFormatException, 2982 XmlPullParserException, IOException { 2983 Op op = new Op(uidState, pkgName, 2984 Integer.parseInt(parser.getAttributeValue(null, "n"))); 2985 2986 final int mode = XmlUtils.readIntAttribute(parser, "m", 2987 AppOpsManager.opToDefaultMode(op.op)); 2988 op.mode = mode; 2989 2990 int outerDepth = parser.getDepth(); 2991 int type; 2992 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2993 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2994 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2995 continue; 2996 } 2997 String tagName = parser.getName(); 2998 if (tagName.equals("st")) { 2999 final long key = XmlUtils.readLongAttribute(parser, "n"); 3000 3001 final int flags = AppOpsManager.extractFlagsFromKey(key); 3002 final int state = AppOpsManager.extractUidStateFromKey(key); 3003 3004 final long accessTime = XmlUtils.readLongAttribute(parser, "t", 0); 3005 final long rejectTime = XmlUtils.readLongAttribute(parser, "r", 0); 3006 final long accessDuration = XmlUtils.readLongAttribute(parser, "d", 0); 3007 final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp"); 3008 final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", 0); 3009 3010 if (accessTime > 0) { 3011 op.accessed(accessTime, proxyUid, proxyPkg, state, flags); 3012 } 3013 if (rejectTime > 0) { 3014 op.rejected(rejectTime, proxyUid, proxyPkg, state, flags); 3015 } 3016 if (accessDuration > 0) { 3017 op.running(accessTime, accessDuration, state, flags); 3018 } 3019 } else { 3020 Slog.w(TAG, "Unknown element under <op>: " 3021 + parser.getName()); 3022 XmlUtils.skipCurrentTag(parser); 3023 } 3024 } 3025 3026 if (uidState.pkgOps == null) { 3027 uidState.pkgOps = new ArrayMap<>(); 3028 } 3029 Ops ops = uidState.pkgOps.get(pkgName); 3030 if (ops == null) { 3031 ops = new Ops(pkgName, uidState, isPrivileged); 3032 uidState.pkgOps.put(pkgName, ops); 3033 } 3034 ops.put(op.op, op); 3035 } 3036 writeState()3037 void writeState() { 3038 synchronized (mFile) { 3039 FileOutputStream stream; 3040 try { 3041 stream = mFile.startWrite(); 3042 } catch (IOException e) { 3043 Slog.w(TAG, "Failed to write state: " + e); 3044 return; 3045 } 3046 3047 List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null); 3048 3049 try { 3050 XmlSerializer out = new FastXmlSerializer(); 3051 out.setOutput(stream, StandardCharsets.UTF_8.name()); 3052 out.startDocument(null, true); 3053 out.startTag(null, "app-ops"); 3054 out.attribute(null, "v", String.valueOf(CURRENT_VERSION)); 3055 3056 final int uidStateCount = mUidStates.size(); 3057 for (int i = 0; i < uidStateCount; i++) { 3058 UidState uidState = mUidStates.valueAt(i); 3059 if (uidState.opModes != null && uidState.opModes.size() > 0) { 3060 out.startTag(null, "uid"); 3061 out.attribute(null, "n", Integer.toString(uidState.uid)); 3062 SparseIntArray uidOpModes = uidState.opModes; 3063 final int opCount = uidOpModes.size(); 3064 for (int j = 0; j < opCount; j++) { 3065 final int op = uidOpModes.keyAt(j); 3066 final int mode = uidOpModes.valueAt(j); 3067 out.startTag(null, "op"); 3068 out.attribute(null, "n", Integer.toString(op)); 3069 out.attribute(null, "m", Integer.toString(mode)); 3070 out.endTag(null, "op"); 3071 } 3072 out.endTag(null, "uid"); 3073 } 3074 } 3075 3076 if (allOps != null) { 3077 String lastPkg = null; 3078 for (int i=0; i<allOps.size(); i++) { 3079 AppOpsManager.PackageOps pkg = allOps.get(i); 3080 if (!pkg.getPackageName().equals(lastPkg)) { 3081 if (lastPkg != null) { 3082 out.endTag(null, "pkg"); 3083 } 3084 lastPkg = pkg.getPackageName(); 3085 out.startTag(null, "pkg"); 3086 out.attribute(null, "n", lastPkg); 3087 } 3088 out.startTag(null, "uid"); 3089 out.attribute(null, "n", Integer.toString(pkg.getUid())); 3090 synchronized (this) { 3091 Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), 3092 false /* edit */, false /* uidMismatchExpected */); 3093 // Should always be present as the list of PackageOps is generated 3094 // from Ops. 3095 if (ops != null) { 3096 out.attribute(null, "p", Boolean.toString(ops.isPrivileged)); 3097 } else { 3098 out.attribute(null, "p", Boolean.toString(false)); 3099 } 3100 } 3101 List<AppOpsManager.OpEntry> ops = pkg.getOps(); 3102 for (int j=0; j<ops.size(); j++) { 3103 AppOpsManager.OpEntry op = ops.get(j); 3104 out.startTag(null, "op"); 3105 out.attribute(null, "n", Integer.toString(op.getOp())); 3106 if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) { 3107 out.attribute(null, "m", Integer.toString(op.getMode())); 3108 } 3109 3110 final LongSparseArray keys = op.collectKeys(); 3111 if (keys == null || keys.size() <= 0) { 3112 out.endTag(null, "op"); 3113 continue; 3114 } 3115 3116 final int keyCount = keys.size(); 3117 for (int k = 0; k < keyCount; k++) { 3118 final long key = keys.keyAt(k); 3119 3120 final int uidState = AppOpsManager.extractUidStateFromKey(key); 3121 final int flags = AppOpsManager.extractFlagsFromKey(key); 3122 3123 final long accessTime = op.getLastAccessTime( 3124 uidState, uidState, flags); 3125 final long rejectTime = op.getLastRejectTime( 3126 uidState, uidState, flags); 3127 final long accessDuration = op.getLastDuration( 3128 uidState, uidState, flags); 3129 final String proxyPkg = op.getProxyPackageName(uidState, flags); 3130 final int proxyUid = op.getProxyUid(uidState, flags); 3131 3132 if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0 3133 && proxyPkg == null && proxyUid < 0) { 3134 continue; 3135 } 3136 3137 out.startTag(null, "st"); 3138 out.attribute(null, "n", Long.toString(key)); 3139 if (accessTime > 0) { 3140 out.attribute(null, "t", Long.toString(accessTime)); 3141 } 3142 if (rejectTime > 0) { 3143 out.attribute(null, "r", Long.toString(rejectTime)); 3144 } 3145 if (accessDuration > 0) { 3146 out.attribute(null, "d", Long.toString(accessDuration)); 3147 } 3148 if (proxyPkg != null) { 3149 out.attribute(null, "pp", proxyPkg); 3150 } 3151 if (proxyUid >= 0) { 3152 out.attribute(null, "pu", Integer.toString(proxyUid)); 3153 } 3154 out.endTag(null, "st"); 3155 } 3156 3157 out.endTag(null, "op"); 3158 } 3159 out.endTag(null, "uid"); 3160 } 3161 if (lastPkg != null) { 3162 out.endTag(null, "pkg"); 3163 } 3164 } 3165 3166 out.endTag(null, "app-ops"); 3167 out.endDocument(); 3168 mFile.finishWrite(stream); 3169 } catch (IOException e) { 3170 Slog.w(TAG, "Failed to write state, restoring backup.", e); 3171 mFile.failWrite(stream); 3172 } 3173 } 3174 } 3175 3176 static class Shell extends ShellCommand { 3177 final IAppOpsService mInterface; 3178 final AppOpsService mInternal; 3179 3180 int userId = UserHandle.USER_SYSTEM; 3181 String packageName; 3182 String opStr; 3183 String modeStr; 3184 int op; 3185 int mode; 3186 int packageUid; 3187 int nonpackageUid; 3188 final static Binder sBinder = new Binder(); 3189 IBinder mToken; 3190 boolean targetsUid; 3191 Shell(IAppOpsService iface, AppOpsService internal)3192 Shell(IAppOpsService iface, AppOpsService internal) { 3193 mInterface = iface; 3194 mInternal = internal; 3195 try { 3196 mToken = mInterface.getToken(sBinder); 3197 } catch (RemoteException e) { 3198 } 3199 } 3200 3201 @Override onCommand(String cmd)3202 public int onCommand(String cmd) { 3203 return onShellCommand(this, cmd); 3204 } 3205 3206 @Override onHelp()3207 public void onHelp() { 3208 PrintWriter pw = getOutPrintWriter(); 3209 dumpCommandHelp(pw); 3210 } 3211 strOpToOp(String op, PrintWriter err)3212 static private int strOpToOp(String op, PrintWriter err) { 3213 try { 3214 return AppOpsManager.strOpToOp(op); 3215 } catch (IllegalArgumentException e) { 3216 } 3217 try { 3218 return Integer.parseInt(op); 3219 } catch (NumberFormatException e) { 3220 } 3221 try { 3222 return AppOpsManager.strDebugOpToOp(op); 3223 } catch (IllegalArgumentException e) { 3224 err.println("Error: " + e.getMessage()); 3225 return -1; 3226 } 3227 } 3228 strModeToMode(String modeStr, PrintWriter err)3229 static int strModeToMode(String modeStr, PrintWriter err) { 3230 for (int i = AppOpsManager.MODE_NAMES.length - 1; i >= 0; i--) { 3231 if (AppOpsManager.MODE_NAMES[i].equals(modeStr)) { 3232 return i; 3233 } 3234 } 3235 try { 3236 return Integer.parseInt(modeStr); 3237 } catch (NumberFormatException e) { 3238 } 3239 err.println("Error: Mode " + modeStr + " is not valid"); 3240 return -1; 3241 } 3242 parseUserOpMode(int defMode, PrintWriter err)3243 int parseUserOpMode(int defMode, PrintWriter err) throws RemoteException { 3244 userId = UserHandle.USER_CURRENT; 3245 opStr = null; 3246 modeStr = null; 3247 for (String argument; (argument = getNextArg()) != null;) { 3248 if ("--user".equals(argument)) { 3249 userId = UserHandle.parseUserArg(getNextArgRequired()); 3250 } else { 3251 if (opStr == null) { 3252 opStr = argument; 3253 } else if (modeStr == null) { 3254 modeStr = argument; 3255 break; 3256 } 3257 } 3258 } 3259 if (opStr == null) { 3260 err.println("Error: Operation not specified."); 3261 return -1; 3262 } 3263 op = strOpToOp(opStr, err); 3264 if (op < 0) { 3265 return -1; 3266 } 3267 if (modeStr != null) { 3268 if ((mode=strModeToMode(modeStr, err)) < 0) { 3269 return -1; 3270 } 3271 } else { 3272 mode = defMode; 3273 } 3274 return 0; 3275 } 3276 parseUserPackageOp(boolean reqOp, PrintWriter err)3277 int parseUserPackageOp(boolean reqOp, PrintWriter err) throws RemoteException { 3278 userId = UserHandle.USER_CURRENT; 3279 packageName = null; 3280 opStr = null; 3281 for (String argument; (argument = getNextArg()) != null;) { 3282 if ("--user".equals(argument)) { 3283 userId = UserHandle.parseUserArg(getNextArgRequired()); 3284 } else if ("--uid".equals(argument)) { 3285 targetsUid = true; 3286 } else { 3287 if (packageName == null) { 3288 packageName = argument; 3289 } else if (opStr == null) { 3290 opStr = argument; 3291 break; 3292 } 3293 } 3294 } 3295 if (packageName == null) { 3296 err.println("Error: Package name not specified."); 3297 return -1; 3298 } else if (opStr == null && reqOp) { 3299 err.println("Error: Operation not specified."); 3300 return -1; 3301 } 3302 if (opStr != null) { 3303 op = strOpToOp(opStr, err); 3304 if (op < 0) { 3305 return -1; 3306 } 3307 } else { 3308 op = AppOpsManager.OP_NONE; 3309 } 3310 if (userId == UserHandle.USER_CURRENT) { 3311 userId = ActivityManager.getCurrentUser(); 3312 } 3313 nonpackageUid = -1; 3314 try { 3315 nonpackageUid = Integer.parseInt(packageName); 3316 } catch (NumberFormatException e) { 3317 } 3318 if (nonpackageUid == -1 && packageName.length() > 1 && packageName.charAt(0) == 'u' 3319 && packageName.indexOf('.') < 0) { 3320 int i = 1; 3321 while (i < packageName.length() && packageName.charAt(i) >= '0' 3322 && packageName.charAt(i) <= '9') { 3323 i++; 3324 } 3325 if (i > 1 && i < packageName.length()) { 3326 String userStr = packageName.substring(1, i); 3327 try { 3328 int user = Integer.parseInt(userStr); 3329 char type = packageName.charAt(i); 3330 i++; 3331 int startTypeVal = i; 3332 while (i < packageName.length() && packageName.charAt(i) >= '0' 3333 && packageName.charAt(i) <= '9') { 3334 i++; 3335 } 3336 if (i > startTypeVal) { 3337 String typeValStr = packageName.substring(startTypeVal, i); 3338 try { 3339 int typeVal = Integer.parseInt(typeValStr); 3340 if (type == 'a') { 3341 nonpackageUid = UserHandle.getUid(user, 3342 typeVal + Process.FIRST_APPLICATION_UID); 3343 } else if (type == 's') { 3344 nonpackageUid = UserHandle.getUid(user, typeVal); 3345 } 3346 } catch (NumberFormatException e) { 3347 } 3348 } 3349 } catch (NumberFormatException e) { 3350 } 3351 } 3352 } 3353 if (nonpackageUid != -1) { 3354 packageName = null; 3355 } else { 3356 packageUid = resolveUid(packageName); 3357 if (packageUid < 0) { 3358 packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, 3359 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); 3360 } 3361 if (packageUid < 0) { 3362 err.println("Error: No UID for " + packageName + " in user " + userId); 3363 return -1; 3364 } 3365 } 3366 return 0; 3367 } 3368 } 3369 onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)3370 @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, 3371 FileDescriptor err, String[] args, ShellCallback callback, 3372 ResultReceiver resultReceiver) { 3373 (new Shell(this, this)).exec(this, in, out, err, args, callback, resultReceiver); 3374 } 3375 dumpCommandHelp(PrintWriter pw)3376 static void dumpCommandHelp(PrintWriter pw) { 3377 pw.println("AppOps service (appops) commands:"); 3378 pw.println(" help"); 3379 pw.println(" Print this help text."); 3380 pw.println(" start [--user <USER_ID>] <PACKAGE | UID> <OP> "); 3381 pw.println(" Starts a given operation for a particular application."); 3382 pw.println(" stop [--user <USER_ID>] <PACKAGE | UID> <OP> "); 3383 pw.println(" Stops a given operation for a particular application."); 3384 pw.println(" set [--user <USER_ID>] <[--uid] PACKAGE | UID> <OP> <MODE>"); 3385 pw.println(" Set the mode for a particular application and operation."); 3386 pw.println(" get [--user <USER_ID>] <PACKAGE | UID> [<OP>]"); 3387 pw.println(" Return the mode for a particular application and optional operation."); 3388 pw.println(" query-op [--user <USER_ID>] <OP> [<MODE>]"); 3389 pw.println(" Print all packages that currently have the given op in the given mode."); 3390 pw.println(" reset [--user <USER_ID>] [<PACKAGE>]"); 3391 pw.println(" Reset the given application or all applications to default modes."); 3392 pw.println(" write-settings"); 3393 pw.println(" Immediately write pending changes to storage."); 3394 pw.println(" read-settings"); 3395 pw.println(" Read the last written settings, replacing current state in RAM."); 3396 pw.println(" options:"); 3397 pw.println(" <PACKAGE> an Android package name or its UID if prefixed by --uid"); 3398 pw.println(" <OP> an AppOps operation."); 3399 pw.println(" <MODE> one of allow, ignore, deny, or default"); 3400 pw.println(" <USER_ID> the user id under which the package is installed. If --user is not"); 3401 pw.println(" specified, the current user is assumed."); 3402 } 3403 onShellCommand(Shell shell, String cmd)3404 static int onShellCommand(Shell shell, String cmd) { 3405 if (cmd == null) { 3406 return shell.handleDefaultCommands(cmd); 3407 } 3408 PrintWriter pw = shell.getOutPrintWriter(); 3409 PrintWriter err = shell.getErrPrintWriter(); 3410 try { 3411 switch (cmd) { 3412 case "set": { 3413 int res = shell.parseUserPackageOp(true, err); 3414 if (res < 0) { 3415 return res; 3416 } 3417 String modeStr = shell.getNextArg(); 3418 if (modeStr == null) { 3419 err.println("Error: Mode not specified."); 3420 return -1; 3421 } 3422 3423 final int mode = shell.strModeToMode(modeStr, err); 3424 if (mode < 0) { 3425 return -1; 3426 } 3427 3428 if (!shell.targetsUid && shell.packageName != null) { 3429 shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName, 3430 mode); 3431 } else if (shell.targetsUid && shell.packageName != null) { 3432 try { 3433 final int uid = shell.mInternal.mContext.getPackageManager() 3434 .getPackageUid(shell.packageName, shell.userId); 3435 shell.mInterface.setUidMode(shell.op, uid, mode); 3436 } catch (PackageManager.NameNotFoundException e) { 3437 return -1; 3438 } 3439 } else { 3440 shell.mInterface.setUidMode(shell.op, shell.nonpackageUid, mode); 3441 } 3442 return 0; 3443 } 3444 case "get": { 3445 int res = shell.parseUserPackageOp(false, err); 3446 if (res < 0) { 3447 return res; 3448 } 3449 3450 List<AppOpsManager.PackageOps> ops = new ArrayList<>(); 3451 if (shell.packageName != null) { 3452 // Uid mode overrides package mode, so make sure it's also reported 3453 List<AppOpsManager.PackageOps> r = shell.mInterface.getUidOps( 3454 shell.packageUid, 3455 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); 3456 if (r != null) { 3457 ops.addAll(r); 3458 } 3459 r = shell.mInterface.getOpsForPackage( 3460 shell.packageUid, shell.packageName, 3461 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); 3462 if (r != null) { 3463 ops.addAll(r); 3464 } 3465 } else { 3466 ops = shell.mInterface.getUidOps( 3467 shell.nonpackageUid, 3468 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); 3469 } 3470 if (ops == null || ops.size() <= 0) { 3471 pw.println("No operations."); 3472 if (shell.op > AppOpsManager.OP_NONE && shell.op < AppOpsManager._NUM_OP) { 3473 pw.println("Default mode: " + AppOpsManager.modeToName( 3474 AppOpsManager.opToDefaultMode(shell.op))); 3475 } 3476 return 0; 3477 } 3478 final long now = System.currentTimeMillis(); 3479 for (int i=0; i<ops.size(); i++) { 3480 AppOpsManager.PackageOps packageOps = ops.get(i); 3481 if (packageOps.getPackageName() == null) { 3482 pw.print("Uid mode: "); 3483 } 3484 List<AppOpsManager.OpEntry> entries = packageOps.getOps(); 3485 for (int j=0; j<entries.size(); j++) { 3486 AppOpsManager.OpEntry ent = entries.get(j); 3487 pw.print(AppOpsManager.opToName(ent.getOp())); 3488 pw.print(": "); 3489 pw.print(AppOpsManager.modeToName(ent.getMode())); 3490 if (ent.getTime() != 0) { 3491 pw.print("; time="); 3492 TimeUtils.formatDuration(now - ent.getTime(), pw); 3493 pw.print(" ago"); 3494 } 3495 if (ent.getRejectTime() != 0) { 3496 pw.print("; rejectTime="); 3497 TimeUtils.formatDuration(now - ent.getRejectTime(), pw); 3498 pw.print(" ago"); 3499 } 3500 if (ent.getDuration() == -1) { 3501 pw.print(" (running)"); 3502 } else if (ent.getDuration() != 0) { 3503 pw.print("; duration="); 3504 TimeUtils.formatDuration(ent.getDuration(), pw); 3505 } 3506 pw.println(); 3507 } 3508 } 3509 return 0; 3510 } 3511 case "query-op": { 3512 int res = shell.parseUserOpMode(AppOpsManager.MODE_IGNORED, err); 3513 if (res < 0) { 3514 return res; 3515 } 3516 List<AppOpsManager.PackageOps> ops = shell.mInterface.getPackagesForOps( 3517 new int[] {shell.op}); 3518 if (ops == null || ops.size() <= 0) { 3519 pw.println("No operations."); 3520 return 0; 3521 } 3522 for (int i=0; i<ops.size(); i++) { 3523 final AppOpsManager.PackageOps pkg = ops.get(i); 3524 boolean hasMatch = false; 3525 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps(); 3526 for (int j=0; j<entries.size(); j++) { 3527 AppOpsManager.OpEntry ent = entries.get(j); 3528 if (ent.getOp() == shell.op && ent.getMode() == shell.mode) { 3529 hasMatch = true; 3530 break; 3531 } 3532 } 3533 if (hasMatch) { 3534 pw.println(pkg.getPackageName()); 3535 } 3536 } 3537 return 0; 3538 } 3539 case "reset": { 3540 String packageName = null; 3541 int userId = UserHandle.USER_CURRENT; 3542 for (String argument; (argument = shell.getNextArg()) != null;) { 3543 if ("--user".equals(argument)) { 3544 String userStr = shell.getNextArgRequired(); 3545 userId = UserHandle.parseUserArg(userStr); 3546 } else { 3547 if (packageName == null) { 3548 packageName = argument; 3549 } else { 3550 err.println("Error: Unsupported argument: " + argument); 3551 return -1; 3552 } 3553 } 3554 } 3555 3556 if (userId == UserHandle.USER_CURRENT) { 3557 userId = ActivityManager.getCurrentUser(); 3558 } 3559 3560 shell.mInterface.resetAllModes(userId, packageName); 3561 pw.print("Reset all modes for: "); 3562 if (userId == UserHandle.USER_ALL) { 3563 pw.print("all users"); 3564 } else { 3565 pw.print("user "); pw.print(userId); 3566 } 3567 pw.print(", "); 3568 if (packageName == null) { 3569 pw.println("all packages"); 3570 } else { 3571 pw.print("package "); pw.println(packageName); 3572 } 3573 return 0; 3574 } 3575 case "write-settings": { 3576 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(), 3577 Binder.getCallingUid(), -1); 3578 long token = Binder.clearCallingIdentity(); 3579 try { 3580 synchronized (shell.mInternal) { 3581 shell.mInternal.mHandler.removeCallbacks(shell.mInternal.mWriteRunner); 3582 } 3583 shell.mInternal.writeState(); 3584 pw.println("Current settings written."); 3585 } finally { 3586 Binder.restoreCallingIdentity(token); 3587 } 3588 return 0; 3589 } 3590 case "read-settings": { 3591 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(), 3592 Binder.getCallingUid(), -1); 3593 long token = Binder.clearCallingIdentity(); 3594 try { 3595 shell.mInternal.readState(); 3596 pw.println("Last settings read."); 3597 } finally { 3598 Binder.restoreCallingIdentity(token); 3599 } 3600 return 0; 3601 } 3602 case "start": { 3603 int res = shell.parseUserPackageOp(true, err); 3604 if (res < 0) { 3605 return res; 3606 } 3607 3608 if (shell.packageName != null) { 3609 shell.mInterface.startOperation(shell.mToken, 3610 shell.op, shell.packageUid, shell.packageName, true); 3611 } else { 3612 return -1; 3613 } 3614 return 0; 3615 } 3616 case "stop": { 3617 int res = shell.parseUserPackageOp(true, err); 3618 if (res < 0) { 3619 return res; 3620 } 3621 3622 if (shell.packageName != null) { 3623 shell.mInterface.finishOperation(shell.mToken, 3624 shell.op, shell.packageUid, shell.packageName); 3625 } else { 3626 return -1; 3627 } 3628 return 0; 3629 } 3630 default: 3631 return shell.handleDefaultCommands(cmd); 3632 } 3633 } catch (RemoteException e) { 3634 pw.println("Remote exception: " + e); 3635 } 3636 return -1; 3637 } 3638 dumpHelp(PrintWriter pw)3639 private void dumpHelp(PrintWriter pw) { 3640 pw.println("AppOps service (appops) dump options:"); 3641 pw.println(" -h"); 3642 pw.println(" Print this help text."); 3643 pw.println(" --op [OP]"); 3644 pw.println(" Limit output to data associated with the given app op code."); 3645 pw.println(" --mode [MODE]"); 3646 pw.println(" Limit output to data associated with the given app op mode."); 3647 pw.println(" --package [PACKAGE]"); 3648 pw.println(" Limit output to data associated with the given package name."); 3649 pw.println(" --watchers"); 3650 pw.println(" Only output the watcher sections."); 3651 } 3652 dumpStatesLocked(@onNull PrintWriter pw, @NonNull Op op, long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix)3653 private void dumpStatesLocked(@NonNull PrintWriter pw, @NonNull Op op, 3654 long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix) { 3655 3656 final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes, 3657 op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames); 3658 3659 final LongSparseArray keys = entry.collectKeys(); 3660 if (keys == null || keys.size() <= 0) { 3661 return; 3662 } 3663 3664 final int keyCount = keys.size(); 3665 for (int k = 0; k < keyCount; k++) { 3666 final long key = keys.keyAt(k); 3667 3668 final int uidState = AppOpsManager.extractUidStateFromKey(key); 3669 final int flags = AppOpsManager.extractFlagsFromKey(key); 3670 3671 final long accessTime = entry.getLastAccessTime( 3672 uidState, uidState, flags); 3673 final long rejectTime = entry.getLastRejectTime( 3674 uidState, uidState, flags); 3675 final long accessDuration = entry.getLastDuration( 3676 uidState, uidState, flags); 3677 final String proxyPkg = entry.getProxyPackageName(uidState, flags); 3678 final int proxyUid = entry.getProxyUid(uidState, flags); 3679 3680 if (accessTime > 0) { 3681 pw.print(prefix); 3682 pw.print("Access: "); 3683 pw.print(AppOpsManager.keyToString(key)); 3684 pw.print(" "); 3685 date.setTime(accessTime); 3686 pw.print(sdf.format(date)); 3687 pw.print(" ("); 3688 TimeUtils.formatDuration(accessTime - now, pw); 3689 pw.print(")"); 3690 if (accessDuration > 0) { 3691 pw.print(" duration="); 3692 TimeUtils.formatDuration(accessDuration, pw); 3693 } 3694 if (proxyUid >= 0) { 3695 pw.print(" proxy["); 3696 pw.print("uid="); 3697 pw.print(proxyUid); 3698 pw.print(", pkg="); 3699 pw.print(proxyPkg); 3700 pw.print("]"); 3701 } 3702 pw.println(); 3703 } 3704 3705 if (rejectTime > 0) { 3706 pw.print(prefix); 3707 pw.print("Reject: "); 3708 pw.print(AppOpsManager.keyToString(key)); 3709 date.setTime(rejectTime); 3710 pw.print(sdf.format(date)); 3711 pw.print(" ("); 3712 TimeUtils.formatDuration(rejectTime - now, pw); 3713 pw.print(")"); 3714 if (proxyUid >= 0) { 3715 pw.print(" proxy["); 3716 pw.print("uid="); 3717 pw.print(proxyUid); 3718 pw.print(", pkg="); 3719 pw.print(proxyPkg); 3720 pw.print("]"); 3721 } 3722 pw.println(); 3723 } 3724 } 3725 } 3726 3727 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)3728 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 3729 if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; 3730 3731 int dumpOp = OP_NONE; 3732 String dumpPackage = null; 3733 int dumpUid = Process.INVALID_UID; 3734 int dumpMode = -1; 3735 boolean dumpWatchers = false; 3736 boolean dumpHistory = false; 3737 3738 if (args != null) { 3739 for (int i=0; i<args.length; i++) { 3740 String arg = args[i]; 3741 if ("-h".equals(arg)) { 3742 dumpHelp(pw); 3743 return; 3744 } else if ("-a".equals(arg)) { 3745 // dump all data 3746 } else if ("--op".equals(arg)) { 3747 i++; 3748 if (i >= args.length) { 3749 pw.println("No argument for --op option"); 3750 return; 3751 } 3752 dumpOp = Shell.strOpToOp(args[i], pw); 3753 if (dumpOp < 0) { 3754 return; 3755 } 3756 } else if ("--package".equals(arg)) { 3757 i++; 3758 if (i >= args.length) { 3759 pw.println("No argument for --package option"); 3760 return; 3761 } 3762 dumpPackage = args[i]; 3763 try { 3764 dumpUid = AppGlobals.getPackageManager().getPackageUid(dumpPackage, 3765 PackageManager.MATCH_KNOWN_PACKAGES | PackageManager.MATCH_INSTANT, 3766 0); 3767 } catch (RemoteException e) { 3768 } 3769 if (dumpUid < 0) { 3770 pw.println("Unknown package: " + dumpPackage); 3771 return; 3772 } 3773 dumpUid = UserHandle.getAppId(dumpUid); 3774 } else if ("--mode".equals(arg)) { 3775 i++; 3776 if (i >= args.length) { 3777 pw.println("No argument for --mode option"); 3778 return; 3779 } 3780 dumpMode = Shell.strModeToMode(args[i], pw); 3781 if (dumpMode < 0) { 3782 return; 3783 } 3784 } else if ("--watchers".equals(arg)) { 3785 dumpWatchers = true; 3786 } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 3787 pw.println("Unknown option: " + arg); 3788 return; 3789 } else { 3790 pw.println("Unknown command: " + arg); 3791 return; 3792 } 3793 } 3794 } 3795 3796 synchronized (this) { 3797 pw.println("Current AppOps Service state:"); 3798 if (!dumpHistory && !dumpWatchers) { 3799 mConstants.dump(pw); 3800 } 3801 pw.println(); 3802 final long now = System.currentTimeMillis(); 3803 final long nowElapsed = SystemClock.elapsedRealtime(); 3804 final long nowUptime = SystemClock.uptimeMillis(); 3805 final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 3806 final Date date = new Date(); 3807 boolean needSep = false; 3808 if (dumpOp < 0 && dumpMode < 0 && dumpPackage == null && mProfileOwners != null 3809 && !dumpWatchers && !dumpHistory) { 3810 pw.println(" Profile owners:"); 3811 for (int poi = 0; poi < mProfileOwners.size(); poi++) { 3812 pw.print(" User #"); 3813 pw.print(mProfileOwners.keyAt(poi)); 3814 pw.print(": "); 3815 UserHandle.formatUid(pw, mProfileOwners.valueAt(poi)); 3816 pw.println(); 3817 } 3818 pw.println(); 3819 } 3820 if (mOpModeWatchers.size() > 0 && !dumpHistory) { 3821 boolean printedHeader = false; 3822 for (int i=0; i<mOpModeWatchers.size(); i++) { 3823 if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) { 3824 continue; 3825 } 3826 boolean printedOpHeader = false; 3827 ArraySet<ModeCallback> callbacks = mOpModeWatchers.valueAt(i); 3828 for (int j=0; j<callbacks.size(); j++) { 3829 final ModeCallback cb = callbacks.valueAt(j); 3830 if (dumpPackage != null 3831 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 3832 continue; 3833 } 3834 needSep = true; 3835 if (!printedHeader) { 3836 pw.println(" Op mode watchers:"); 3837 printedHeader = true; 3838 } 3839 if (!printedOpHeader) { 3840 pw.print(" Op "); 3841 pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i))); 3842 pw.println(":"); 3843 printedOpHeader = true; 3844 } 3845 pw.print(" #"); pw.print(j); pw.print(": "); 3846 pw.println(cb); 3847 } 3848 } 3849 } 3850 if (mPackageModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) { 3851 boolean printedHeader = false; 3852 for (int i=0; i<mPackageModeWatchers.size(); i++) { 3853 if (dumpPackage != null && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) { 3854 continue; 3855 } 3856 needSep = true; 3857 if (!printedHeader) { 3858 pw.println(" Package mode watchers:"); 3859 printedHeader = true; 3860 } 3861 pw.print(" Pkg "); pw.print(mPackageModeWatchers.keyAt(i)); 3862 pw.println(":"); 3863 ArraySet<ModeCallback> callbacks = mPackageModeWatchers.valueAt(i); 3864 for (int j=0; j<callbacks.size(); j++) { 3865 pw.print(" #"); pw.print(j); pw.print(": "); 3866 pw.println(callbacks.valueAt(j)); 3867 } 3868 } 3869 } 3870 if (mModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) { 3871 boolean printedHeader = false; 3872 for (int i=0; i<mModeWatchers.size(); i++) { 3873 final ModeCallback cb = mModeWatchers.valueAt(i); 3874 if (dumpPackage != null 3875 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 3876 continue; 3877 } 3878 needSep = true; 3879 if (!printedHeader) { 3880 pw.println(" All op mode watchers:"); 3881 printedHeader = true; 3882 } 3883 pw.print(" "); 3884 pw.print(Integer.toHexString(System.identityHashCode(mModeWatchers.keyAt(i)))); 3885 pw.print(": "); pw.println(cb); 3886 } 3887 } 3888 if (mActiveWatchers.size() > 0 && dumpMode < 0) { 3889 needSep = true; 3890 boolean printedHeader = false; 3891 for (int watcherNum = 0; watcherNum < mActiveWatchers.size(); watcherNum++) { 3892 final SparseArray<ActiveCallback> activeWatchers = 3893 mActiveWatchers.valueAt(watcherNum); 3894 if (activeWatchers.size() <= 0) { 3895 continue; 3896 } 3897 final ActiveCallback cb = activeWatchers.valueAt(0); 3898 if (dumpOp >= 0 && activeWatchers.indexOfKey(dumpOp) < 0) { 3899 continue; 3900 } 3901 if (dumpPackage != null 3902 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 3903 continue; 3904 } 3905 if (!printedHeader) { 3906 pw.println(" All op active watchers:"); 3907 printedHeader = true; 3908 } 3909 pw.print(" "); 3910 pw.print(Integer.toHexString(System.identityHashCode( 3911 mActiveWatchers.keyAt(watcherNum)))); 3912 pw.println(" ->"); 3913 pw.print(" ["); 3914 final int opCount = activeWatchers.size(); 3915 for (int opNum = 0; opNum < opCount; opNum++) { 3916 if (opNum > 0) { 3917 pw.print(' '); 3918 } 3919 pw.print(AppOpsManager.opToName(activeWatchers.keyAt(opNum))); 3920 if (opNum < opCount - 1) { 3921 pw.print(','); 3922 } 3923 } 3924 pw.println("]"); 3925 pw.print(" "); 3926 pw.println(cb); 3927 } 3928 } 3929 if (mNotedWatchers.size() > 0 && dumpMode < 0) { 3930 needSep = true; 3931 boolean printedHeader = false; 3932 for (int i = 0; i < mNotedWatchers.size(); i++) { 3933 final SparseArray<NotedCallback> notedWatchers = mNotedWatchers.valueAt(i); 3934 if (notedWatchers.size() <= 0) { 3935 continue; 3936 } 3937 final NotedCallback cb = notedWatchers.valueAt(0); 3938 if (dumpOp >= 0 && notedWatchers.indexOfKey(dumpOp) < 0) { 3939 continue; 3940 } 3941 if (dumpPackage != null 3942 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 3943 continue; 3944 } 3945 if (!printedHeader) { 3946 pw.println(" All op noted watchers:"); 3947 printedHeader = true; 3948 } 3949 pw.print(" "); 3950 pw.print(Integer.toHexString(System.identityHashCode( 3951 mNotedWatchers.keyAt(i)))); 3952 pw.println(" ->"); 3953 pw.print(" ["); 3954 final int opCount = notedWatchers.size(); 3955 for (i = 0; i < opCount; i++) { 3956 if (i > 0) { 3957 pw.print(' '); 3958 } 3959 pw.print(AppOpsManager.opToName(notedWatchers.keyAt(i))); 3960 if (i < opCount - 1) { 3961 pw.print(','); 3962 } 3963 } 3964 pw.println("]"); 3965 pw.print(" "); 3966 pw.println(cb); 3967 } 3968 } 3969 if (mClients.size() > 0 && dumpMode < 0 && !dumpWatchers && !dumpHistory) { 3970 needSep = true; 3971 boolean printedHeader = false; 3972 for (int i=0; i<mClients.size(); i++) { 3973 boolean printedClient = false; 3974 ClientState cs = mClients.valueAt(i); 3975 if (cs.mStartedOps.size() > 0) { 3976 boolean printedStarted = false; 3977 for (int j=0; j<cs.mStartedOps.size(); j++) { 3978 Op op = cs.mStartedOps.get(j); 3979 if (dumpOp >= 0 && op.op != dumpOp) { 3980 continue; 3981 } 3982 if (dumpPackage != null && !dumpPackage.equals(op.packageName)) { 3983 continue; 3984 } 3985 if (!printedHeader) { 3986 pw.println(" Clients:"); 3987 printedHeader = true; 3988 } 3989 if (!printedClient) { 3990 pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":"); 3991 pw.print(" "); pw.println(cs); 3992 printedClient = true; 3993 } 3994 if (!printedStarted) { 3995 pw.println(" Started ops:"); 3996 printedStarted = true; 3997 } 3998 pw.print(" "); pw.print("uid="); pw.print(op.uidState.uid); 3999 pw.print(" pkg="); pw.print(op.packageName); 4000 pw.print(" op="); pw.println(AppOpsManager.opToName(op.op)); 4001 } 4002 } 4003 } 4004 } 4005 if (mAudioRestrictions.size() > 0 && dumpOp < 0 && dumpPackage != null 4006 && dumpMode < 0 && !dumpWatchers && !dumpWatchers) { 4007 boolean printedHeader = false; 4008 for (int o=0; o<mAudioRestrictions.size(); o++) { 4009 final String op = AppOpsManager.opToName(mAudioRestrictions.keyAt(o)); 4010 final SparseArray<Restriction> restrictions = mAudioRestrictions.valueAt(o); 4011 for (int i=0; i<restrictions.size(); i++) { 4012 if (!printedHeader){ 4013 pw.println(" Audio Restrictions:"); 4014 printedHeader = true; 4015 needSep = true; 4016 } 4017 final int usage = restrictions.keyAt(i); 4018 pw.print(" "); pw.print(op); 4019 pw.print(" usage="); pw.print(AudioAttributes.usageToString(usage)); 4020 Restriction r = restrictions.valueAt(i); 4021 pw.print(": mode="); pw.println(AppOpsManager.modeToName(r.mode)); 4022 if (!r.exceptionPackages.isEmpty()) { 4023 pw.println(" Exceptions:"); 4024 for (int j=0; j<r.exceptionPackages.size(); j++) { 4025 pw.print(" "); pw.println(r.exceptionPackages.valueAt(j)); 4026 } 4027 } 4028 } 4029 } 4030 } 4031 if (needSep) { 4032 pw.println(); 4033 } 4034 for (int i=0; i<mUidStates.size(); i++) { 4035 UidState uidState = mUidStates.valueAt(i); 4036 final SparseIntArray opModes = uidState.opModes; 4037 final ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 4038 4039 if (dumpWatchers || dumpHistory) { 4040 continue; 4041 } 4042 if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) { 4043 boolean hasOp = dumpOp < 0 || (uidState.opModes != null 4044 && uidState.opModes.indexOfKey(dumpOp) >= 0); 4045 boolean hasPackage = dumpPackage == null; 4046 boolean hasMode = dumpMode < 0; 4047 if (!hasMode && opModes != null) { 4048 for (int opi = 0; !hasMode && opi < opModes.size(); opi++) { 4049 if (opModes.valueAt(opi) == dumpMode) { 4050 hasMode = true; 4051 } 4052 } 4053 } 4054 if (pkgOps != null) { 4055 for (int pkgi = 0; 4056 (!hasOp || !hasPackage || !hasMode) && pkgi < pkgOps.size(); 4057 pkgi++) { 4058 Ops ops = pkgOps.valueAt(pkgi); 4059 if (!hasOp && ops != null && ops.indexOfKey(dumpOp) >= 0) { 4060 hasOp = true; 4061 } 4062 if (!hasMode) { 4063 for (int opi = 0; !hasMode && opi < ops.size(); opi++) { 4064 if (ops.valueAt(opi).mode == dumpMode) { 4065 hasMode = true; 4066 } 4067 } 4068 } 4069 if (!hasPackage && dumpPackage.equals(ops.packageName)) { 4070 hasPackage = true; 4071 } 4072 } 4073 } 4074 if (uidState.foregroundOps != null && !hasOp) { 4075 if (uidState.foregroundOps.indexOfKey(dumpOp) > 0) { 4076 hasOp = true; 4077 } 4078 } 4079 if (!hasOp || !hasPackage || !hasMode) { 4080 continue; 4081 } 4082 } 4083 4084 pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":"); 4085 pw.print(" state="); 4086 pw.println(AppOpsManager.getUidStateName(uidState.state)); 4087 if (uidState.state != uidState.pendingState) { 4088 pw.print(" pendingState="); 4089 pw.println(AppOpsManager.getUidStateName(uidState.pendingState)); 4090 } 4091 if (uidState.pendingStateCommitTime != 0) { 4092 pw.print(" pendingStateCommitTime="); 4093 TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowElapsed, pw); 4094 pw.println(); 4095 } 4096 if (uidState.startNesting != 0) { 4097 pw.print(" startNesting="); 4098 pw.println(uidState.startNesting); 4099 } 4100 if (uidState.foregroundOps != null && (dumpMode < 0 4101 || dumpMode == AppOpsManager.MODE_FOREGROUND)) { 4102 pw.println(" foregroundOps:"); 4103 for (int j = 0; j < uidState.foregroundOps.size(); j++) { 4104 if (dumpOp >= 0 && dumpOp != uidState.foregroundOps.keyAt(j)) { 4105 continue; 4106 } 4107 pw.print(" "); 4108 pw.print(AppOpsManager.opToName(uidState.foregroundOps.keyAt(j))); 4109 pw.print(": "); 4110 pw.println(uidState.foregroundOps.valueAt(j) ? "WATCHER" : "SILENT"); 4111 } 4112 pw.print(" hasForegroundWatchers="); 4113 pw.println(uidState.hasForegroundWatchers); 4114 } 4115 needSep = true; 4116 4117 if (opModes != null) { 4118 final int opModeCount = opModes.size(); 4119 for (int j = 0; j < opModeCount; j++) { 4120 final int code = opModes.keyAt(j); 4121 final int mode = opModes.valueAt(j); 4122 if (dumpOp >= 0 && dumpOp != code) { 4123 continue; 4124 } 4125 if (dumpMode >= 0 && dumpMode != mode) { 4126 continue; 4127 } 4128 pw.print(" "); pw.print(AppOpsManager.opToName(code)); 4129 pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode)); 4130 } 4131 } 4132 4133 if (pkgOps == null) { 4134 continue; 4135 } 4136 4137 for (int pkgi = 0; pkgi < pkgOps.size(); pkgi++) { 4138 final Ops ops = pkgOps.valueAt(pkgi); 4139 if (dumpPackage != null && !dumpPackage.equals(ops.packageName)) { 4140 continue; 4141 } 4142 boolean printedPackage = false; 4143 for (int j=0; j<ops.size(); j++) { 4144 final Op op = ops.valueAt(j); 4145 final int opCode = op.op; 4146 if (dumpOp >= 0 && dumpOp != opCode) { 4147 continue; 4148 } 4149 if (dumpMode >= 0 && dumpMode != op.mode) { 4150 continue; 4151 } 4152 if (!printedPackage) { 4153 pw.print(" Package "); pw.print(ops.packageName); pw.println(":"); 4154 printedPackage = true; 4155 } 4156 pw.print(" "); pw.print(AppOpsManager.opToName(opCode)); 4157 pw.print(" ("); pw.print(AppOpsManager.modeToName(op.mode)); 4158 final int switchOp = AppOpsManager.opToSwitch(opCode); 4159 if (switchOp != opCode) { 4160 pw.print(" / switch "); 4161 pw.print(AppOpsManager.opToName(switchOp)); 4162 final Op switchObj = ops.get(switchOp); 4163 int mode = switchObj != null ? switchObj.mode 4164 : AppOpsManager.opToDefaultMode(switchOp); 4165 pw.print("="); pw.print(AppOpsManager.modeToName(mode)); 4166 } 4167 pw.println("): "); 4168 dumpStatesLocked(pw, op, now, sdf, date, " "); 4169 if (op.running) { 4170 pw.print(" Running start at: "); 4171 TimeUtils.formatDuration(nowElapsed-op.startRealtime, pw); 4172 pw.println(); 4173 } 4174 if (op.startNesting != 0) { 4175 pw.print(" startNesting="); 4176 pw.println(op.startNesting); 4177 } 4178 } 4179 } 4180 } 4181 if (needSep) { 4182 pw.println(); 4183 } 4184 4185 final int userRestrictionCount = mOpUserRestrictions.size(); 4186 for (int i = 0; i < userRestrictionCount; i++) { 4187 IBinder token = mOpUserRestrictions.keyAt(i); 4188 ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); 4189 boolean printedTokenHeader = false; 4190 4191 if (dumpMode >= 0 || dumpWatchers || dumpHistory) { 4192 continue; 4193 } 4194 4195 final int restrictionCount = restrictionState.perUserRestrictions != null 4196 ? restrictionState.perUserRestrictions.size() : 0; 4197 if (restrictionCount > 0 && dumpPackage == null) { 4198 boolean printedOpsHeader = false; 4199 for (int j = 0; j < restrictionCount; j++) { 4200 int userId = restrictionState.perUserRestrictions.keyAt(j); 4201 boolean[] restrictedOps = restrictionState.perUserRestrictions.valueAt(j); 4202 if (restrictedOps == null) { 4203 continue; 4204 } 4205 if (dumpOp >= 0 && (dumpOp >= restrictedOps.length 4206 || !restrictedOps[dumpOp])) { 4207 continue; 4208 } 4209 if (!printedTokenHeader) { 4210 pw.println(" User restrictions for token " + token + ":"); 4211 printedTokenHeader = true; 4212 } 4213 if (!printedOpsHeader) { 4214 pw.println(" Restricted ops:"); 4215 printedOpsHeader = true; 4216 } 4217 StringBuilder restrictedOpsValue = new StringBuilder(); 4218 restrictedOpsValue.append("["); 4219 final int restrictedOpCount = restrictedOps.length; 4220 for (int k = 0; k < restrictedOpCount; k++) { 4221 if (restrictedOps[k]) { 4222 if (restrictedOpsValue.length() > 1) { 4223 restrictedOpsValue.append(", "); 4224 } 4225 restrictedOpsValue.append(AppOpsManager.opToName(k)); 4226 } 4227 } 4228 restrictedOpsValue.append("]"); 4229 pw.print(" "); pw.print("user: "); pw.print(userId); 4230 pw.print(" restricted ops: "); pw.println(restrictedOpsValue); 4231 } 4232 } 4233 4234 final int excludedPackageCount = restrictionState.perUserExcludedPackages != null 4235 ? restrictionState.perUserExcludedPackages.size() : 0; 4236 if (excludedPackageCount > 0 && dumpOp < 0) { 4237 boolean printedPackagesHeader = false; 4238 for (int j = 0; j < excludedPackageCount; j++) { 4239 int userId = restrictionState.perUserExcludedPackages.keyAt(j); 4240 String[] packageNames = restrictionState.perUserExcludedPackages.valueAt(j); 4241 if (packageNames == null) { 4242 continue; 4243 } 4244 boolean hasPackage; 4245 if (dumpPackage != null) { 4246 hasPackage = false; 4247 for (String pkg : packageNames) { 4248 if (dumpPackage.equals(pkg)) { 4249 hasPackage = true; 4250 break; 4251 } 4252 } 4253 } else { 4254 hasPackage = true; 4255 } 4256 if (!hasPackage) { 4257 continue; 4258 } 4259 if (!printedTokenHeader) { 4260 pw.println(" User restrictions for token " + token + ":"); 4261 printedTokenHeader = true; 4262 } 4263 if (!printedPackagesHeader) { 4264 pw.println(" Excluded packages:"); 4265 printedPackagesHeader = true; 4266 } 4267 pw.print(" "); pw.print("user: "); pw.print(userId); 4268 pw.print(" packages: "); pw.println(Arrays.toString(packageNames)); 4269 } 4270 } 4271 } 4272 } 4273 4274 // Must not hold the appops lock 4275 if (dumpHistory && !dumpWatchers) { 4276 mHistoricalRegistry.dump(" ", pw, dumpUid, dumpPackage, dumpOp); 4277 } 4278 } 4279 4280 private static final class Restriction { 4281 private static final ArraySet<String> NO_EXCEPTIONS = new ArraySet<String>(); 4282 int mode; 4283 ArraySet<String> exceptionPackages = NO_EXCEPTIONS; 4284 } 4285 4286 @Override setUserRestrictions(Bundle restrictions, IBinder token, int userHandle)4287 public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) { 4288 checkSystemUid("setUserRestrictions"); 4289 Preconditions.checkNotNull(restrictions); 4290 Preconditions.checkNotNull(token); 4291 for (int i = 0; i < AppOpsManager._NUM_OP; i++) { 4292 String restriction = AppOpsManager.opToRestriction(i); 4293 if (restriction != null) { 4294 setUserRestrictionNoCheck(i, restrictions.getBoolean(restriction, false), token, 4295 userHandle, null); 4296 } 4297 } 4298 } 4299 4300 @Override setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, String[] exceptionPackages)4301 public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, 4302 String[] exceptionPackages) { 4303 if (Binder.getCallingPid() != Process.myPid()) { 4304 mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS, 4305 Binder.getCallingPid(), Binder.getCallingUid(), null); 4306 } 4307 if (userHandle != UserHandle.getCallingUserId()) { 4308 if (mContext.checkCallingOrSelfPermission(Manifest.permission 4309 .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED 4310 && mContext.checkCallingOrSelfPermission(Manifest.permission 4311 .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) { 4312 throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or" 4313 + " INTERACT_ACROSS_USERS to interact cross user "); 4314 } 4315 } 4316 verifyIncomingOp(code); 4317 Preconditions.checkNotNull(token); 4318 setUserRestrictionNoCheck(code, restricted, token, userHandle, exceptionPackages); 4319 } 4320 setUserRestrictionNoCheck(int code, boolean restricted, IBinder token, int userHandle, String[] exceptionPackages)4321 private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token, 4322 int userHandle, String[] exceptionPackages) { 4323 synchronized (AppOpsService.this) { 4324 ClientRestrictionState restrictionState = mOpUserRestrictions.get(token); 4325 4326 if (restrictionState == null) { 4327 try { 4328 restrictionState = new ClientRestrictionState(token); 4329 } catch (RemoteException e) { 4330 return; 4331 } 4332 mOpUserRestrictions.put(token, restrictionState); 4333 } 4334 4335 if (restrictionState.setRestriction(code, restricted, exceptionPackages, userHandle)) { 4336 mHandler.sendMessage(PooledLambda.obtainMessage( 4337 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY)); 4338 } 4339 4340 if (restrictionState.isDefault()) { 4341 mOpUserRestrictions.remove(token); 4342 restrictionState.destroy(); 4343 } 4344 } 4345 } 4346 notifyWatchersOfChange(int code, int uid)4347 private void notifyWatchersOfChange(int code, int uid) { 4348 final ArraySet<ModeCallback> clonedCallbacks; 4349 synchronized (this) { 4350 ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code); 4351 if (callbacks == null) { 4352 return; 4353 } 4354 clonedCallbacks = new ArraySet<>(callbacks); 4355 } 4356 4357 notifyOpChanged(clonedCallbacks, code, uid, null); 4358 } 4359 4360 @Override removeUser(int userHandle)4361 public void removeUser(int userHandle) throws RemoteException { 4362 checkSystemUid("removeUser"); 4363 synchronized (AppOpsService.this) { 4364 final int tokenCount = mOpUserRestrictions.size(); 4365 for (int i = tokenCount - 1; i >= 0; i--) { 4366 ClientRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i); 4367 opRestrictions.removeUser(userHandle); 4368 } 4369 removeUidsForUserLocked(userHandle); 4370 } 4371 } 4372 4373 @Override isOperationActive(int code, int uid, String packageName)4374 public boolean isOperationActive(int code, int uid, String packageName) { 4375 if (Binder.getCallingUid() != uid) { 4376 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 4377 != PackageManager.PERMISSION_GRANTED) { 4378 return false; 4379 } 4380 } 4381 verifyIncomingOp(code); 4382 final String resolvedPackageName = resolvePackageName(uid, packageName); 4383 if (resolvedPackageName == null) { 4384 return false; 4385 } 4386 synchronized (AppOpsService.this) { 4387 for (int i = mClients.size() - 1; i >= 0; i--) { 4388 final ClientState client = mClients.valueAt(i); 4389 for (int j = client.mStartedOps.size() - 1; j >= 0; j--) { 4390 final Op op = client.mStartedOps.get(j); 4391 if (op.op == code && op.uidState.uid == uid) return true; 4392 } 4393 } 4394 } 4395 return false; 4396 } 4397 4398 @Override setHistoryParameters(@ppOpsManager.HistoricalMode int mode, long baseSnapshotInterval, int compressionStep)4399 public void setHistoryParameters(@AppOpsManager.HistoricalMode int mode, 4400 long baseSnapshotInterval, int compressionStep) { 4401 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 4402 "setHistoryParameters"); 4403 // Must not hold the appops lock 4404 mHistoricalRegistry.setHistoryParameters(mode, baseSnapshotInterval, compressionStep); 4405 } 4406 4407 @Override offsetHistory(long offsetMillis)4408 public void offsetHistory(long offsetMillis) { 4409 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 4410 "offsetHistory"); 4411 // Must not hold the appops lock 4412 mHistoricalRegistry.offsetHistory(offsetMillis); 4413 } 4414 4415 @Override addHistoricalOps(HistoricalOps ops)4416 public void addHistoricalOps(HistoricalOps ops) { 4417 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 4418 "addHistoricalOps"); 4419 // Must not hold the appops lock 4420 mHistoricalRegistry.addHistoricalOps(ops); 4421 } 4422 4423 @Override resetHistoryParameters()4424 public void resetHistoryParameters() { 4425 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 4426 "resetHistoryParameters"); 4427 // Must not hold the appops lock 4428 mHistoricalRegistry.resetHistoryParameters(); 4429 } 4430 4431 @Override clearHistory()4432 public void clearHistory() { 4433 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 4434 "clearHistory"); 4435 // Must not hold the appops lock 4436 mHistoricalRegistry.clearHistory(); 4437 } 4438 removeUidsForUserLocked(int userHandle)4439 private void removeUidsForUserLocked(int userHandle) { 4440 for (int i = mUidStates.size() - 1; i >= 0; --i) { 4441 final int uid = mUidStates.keyAt(i); 4442 if (UserHandle.getUserId(uid) == userHandle) { 4443 mUidStates.removeAt(i); 4444 } 4445 } 4446 } 4447 checkSystemUid(String function)4448 private void checkSystemUid(String function) { 4449 int uid = Binder.getCallingUid(); 4450 if (uid != Process.SYSTEM_UID) { 4451 throw new SecurityException(function + " must by called by the system"); 4452 } 4453 } 4454 resolvePackageName(int uid, String packageName)4455 private static String resolvePackageName(int uid, String packageName) { 4456 if (uid == Process.ROOT_UID) { 4457 return "root"; 4458 } else if (uid == Process.SHELL_UID) { 4459 return "com.android.shell"; 4460 } else if (uid == Process.MEDIA_UID) { 4461 return "media"; 4462 } else if (uid == Process.AUDIOSERVER_UID) { 4463 return "audioserver"; 4464 } else if (uid == Process.CAMERASERVER_UID) { 4465 return "cameraserver"; 4466 } else if (uid == Process.SYSTEM_UID && packageName == null) { 4467 return "android"; 4468 } 4469 return packageName; 4470 } 4471 resolveUid(String packageName)4472 private static int resolveUid(String packageName) { 4473 if (packageName == null) { 4474 return -1; 4475 } 4476 switch (packageName) { 4477 case "root": 4478 return Process.ROOT_UID; 4479 case "shell": 4480 return Process.SHELL_UID; 4481 case "media": 4482 return Process.MEDIA_UID; 4483 case "audioserver": 4484 return Process.AUDIOSERVER_UID; 4485 case "cameraserver": 4486 return Process.CAMERASERVER_UID; 4487 } 4488 return -1; 4489 } 4490 getPackagesForUid(int uid)4491 private static String[] getPackagesForUid(int uid) { 4492 String[] packageNames = null; 4493 4494 // Very early during boot the package manager is not yet or not yet fully started. At this 4495 // time there are no packages yet. 4496 if (AppGlobals.getPackageManager() != null) { 4497 try { 4498 packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid); 4499 } catch (RemoteException e) { 4500 /* ignore - local call */ 4501 } 4502 } 4503 if (packageNames == null) { 4504 return EmptyArray.STRING; 4505 } 4506 return packageNames; 4507 } 4508 4509 private final class ClientRestrictionState implements DeathRecipient { 4510 private final IBinder token; 4511 SparseArray<boolean[]> perUserRestrictions; 4512 SparseArray<String[]> perUserExcludedPackages; 4513 ClientRestrictionState(IBinder token)4514 public ClientRestrictionState(IBinder token) 4515 throws RemoteException { 4516 token.linkToDeath(this, 0); 4517 this.token = token; 4518 } 4519 setRestriction(int code, boolean restricted, String[] excludedPackages, int userId)4520 public boolean setRestriction(int code, boolean restricted, 4521 String[] excludedPackages, int userId) { 4522 boolean changed = false; 4523 4524 if (perUserRestrictions == null && restricted) { 4525 perUserRestrictions = new SparseArray<>(); 4526 } 4527 4528 int[] users; 4529 if (userId == UserHandle.USER_ALL) { 4530 List<UserInfo> liveUsers = UserManager.get(mContext).getUsers(false); 4531 4532 users = new int[liveUsers.size()]; 4533 for (int i = 0; i < liveUsers.size(); i++) { 4534 users[i] = liveUsers.get(i).id; 4535 } 4536 } else { 4537 users = new int[]{userId}; 4538 } 4539 4540 if (perUserRestrictions != null) { 4541 int numUsers = users.length; 4542 4543 for (int i = 0; i < numUsers; i++) { 4544 int thisUserId = users[i]; 4545 4546 boolean[] userRestrictions = perUserRestrictions.get(thisUserId); 4547 if (userRestrictions == null && restricted) { 4548 userRestrictions = new boolean[AppOpsManager._NUM_OP]; 4549 perUserRestrictions.put(thisUserId, userRestrictions); 4550 } 4551 if (userRestrictions != null && userRestrictions[code] != restricted) { 4552 userRestrictions[code] = restricted; 4553 if (!restricted && isDefault(userRestrictions)) { 4554 perUserRestrictions.remove(thisUserId); 4555 userRestrictions = null; 4556 } 4557 changed = true; 4558 } 4559 4560 if (userRestrictions != null) { 4561 final boolean noExcludedPackages = ArrayUtils.isEmpty(excludedPackages); 4562 if (perUserExcludedPackages == null && !noExcludedPackages) { 4563 perUserExcludedPackages = new SparseArray<>(); 4564 } 4565 if (perUserExcludedPackages != null && !Arrays.equals(excludedPackages, 4566 perUserExcludedPackages.get(thisUserId))) { 4567 if (noExcludedPackages) { 4568 perUserExcludedPackages.remove(thisUserId); 4569 if (perUserExcludedPackages.size() <= 0) { 4570 perUserExcludedPackages = null; 4571 } 4572 } else { 4573 perUserExcludedPackages.put(thisUserId, excludedPackages); 4574 } 4575 changed = true; 4576 } 4577 } 4578 } 4579 } 4580 4581 return changed; 4582 } 4583 hasRestriction(int restriction, String packageName, int userId)4584 public boolean hasRestriction(int restriction, String packageName, int userId) { 4585 if (perUserRestrictions == null) { 4586 return false; 4587 } 4588 boolean[] restrictions = perUserRestrictions.get(userId); 4589 if (restrictions == null) { 4590 return false; 4591 } 4592 if (!restrictions[restriction]) { 4593 return false; 4594 } 4595 if (perUserExcludedPackages == null) { 4596 return true; 4597 } 4598 String[] perUserExclusions = perUserExcludedPackages.get(userId); 4599 if (perUserExclusions == null) { 4600 return true; 4601 } 4602 return !ArrayUtils.contains(perUserExclusions, packageName); 4603 } 4604 removeUser(int userId)4605 public void removeUser(int userId) { 4606 if (perUserExcludedPackages != null) { 4607 perUserExcludedPackages.remove(userId); 4608 if (perUserExcludedPackages.size() <= 0) { 4609 perUserExcludedPackages = null; 4610 } 4611 } 4612 if (perUserRestrictions != null) { 4613 perUserRestrictions.remove(userId); 4614 if (perUserRestrictions.size() <= 0) { 4615 perUserRestrictions = null; 4616 } 4617 } 4618 } 4619 isDefault()4620 public boolean isDefault() { 4621 return perUserRestrictions == null || perUserRestrictions.size() <= 0; 4622 } 4623 4624 @Override binderDied()4625 public void binderDied() { 4626 synchronized (AppOpsService.this) { 4627 mOpUserRestrictions.remove(token); 4628 if (perUserRestrictions == null) { 4629 return; 4630 } 4631 final int userCount = perUserRestrictions.size(); 4632 for (int i = 0; i < userCount; i++) { 4633 final boolean[] restrictions = perUserRestrictions.valueAt(i); 4634 final int restrictionCount = restrictions.length; 4635 for (int j = 0; j < restrictionCount; j++) { 4636 if (restrictions[j]) { 4637 final int changedCode = j; 4638 mHandler.post(() -> notifyWatchersOfChange(changedCode, UID_ANY)); 4639 } 4640 } 4641 } 4642 destroy(); 4643 } 4644 } 4645 destroy()4646 public void destroy() { 4647 token.unlinkToDeath(this, 0); 4648 } 4649 isDefault(boolean[] array)4650 private boolean isDefault(boolean[] array) { 4651 if (ArrayUtils.isEmpty(array)) { 4652 return true; 4653 } 4654 for (boolean value : array) { 4655 if (value) { 4656 return false; 4657 } 4658 } 4659 return true; 4660 } 4661 } 4662 4663 private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal { setDeviceAndProfileOwners(SparseIntArray owners)4664 @Override public void setDeviceAndProfileOwners(SparseIntArray owners) { 4665 synchronized (AppOpsService.this) { 4666 mProfileOwners = owners; 4667 } 4668 } 4669 4670 @Override setUidMode(int code, int uid, int mode)4671 public void setUidMode(int code, int uid, int mode) { 4672 AppOpsService.this.setUidMode(code, uid, mode); 4673 } 4674 4675 @Override setAllPkgModesToDefault(int code, int uid)4676 public void setAllPkgModesToDefault(int code, int uid) { 4677 AppOpsService.this.setAllPkgModesToDefault(code, uid); 4678 } 4679 4680 @Override checkOperationUnchecked(int code, int uid, @NonNull String packageName)4681 public @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName) { 4682 return AppOpsService.this.checkOperationUnchecked(code, uid, packageName, true, false); 4683 } 4684 } 4685 } 4686