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