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