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.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA; 20 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION; 21 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; 22 import static android.app.AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE; 23 import static android.app.AppOpsManager.ATTRIBUTION_FLAG_TRUSTED; 24 import static android.app.AppOpsManager.CALL_BACK_ON_SWITCHED_OP; 25 import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG; 26 import static android.app.AppOpsManager.FILTER_BY_OP_NAMES; 27 import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME; 28 import static android.app.AppOpsManager.FILTER_BY_UID; 29 import static android.app.AppOpsManager.HISTORY_FLAG_GET_ATTRIBUTION_CHAINS; 30 import static android.app.AppOpsManager.HistoricalOpsRequestFilter; 31 import static android.app.AppOpsManager.KEY_BG_STATE_SETTLE_TIME; 32 import static android.app.AppOpsManager.KEY_FG_SERVICE_STATE_SETTLE_TIME; 33 import static android.app.AppOpsManager.KEY_TOP_STATE_SETTLE_TIME; 34 import static android.app.AppOpsManager.MODE_ALLOWED; 35 import static android.app.AppOpsManager.MODE_DEFAULT; 36 import static android.app.AppOpsManager.MODE_ERRORED; 37 import static android.app.AppOpsManager.MODE_FOREGROUND; 38 import static android.app.AppOpsManager.MODE_IGNORED; 39 import static android.app.AppOpsManager.NoteOpEvent; 40 import static android.app.AppOpsManager.OP_CAMERA; 41 import static android.app.AppOpsManager.OP_FLAGS_ALL; 42 import static android.app.AppOpsManager.OP_FLAG_SELF; 43 import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED; 44 import static android.app.AppOpsManager.OP_NONE; 45 import static android.app.AppOpsManager.OP_PLAY_AUDIO; 46 import static android.app.AppOpsManager.OP_RECORD_AUDIO; 47 import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD; 48 import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_FAILED; 49 import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_RESUMED; 50 import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_STARTED; 51 import static android.app.AppOpsManager.OpEventProxyInfo; 52 import static android.app.AppOpsManager.RestrictionBypass; 53 import static android.app.AppOpsManager.SAMPLING_STRATEGY_BOOT_TIME_SAMPLING; 54 import static android.app.AppOpsManager.SAMPLING_STRATEGY_RARELY_USED; 55 import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM; 56 import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM_OPS; 57 import static android.app.AppOpsManager.SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE; 58 import static android.app.AppOpsManager.UID_STATE_BACKGROUND; 59 import static android.app.AppOpsManager.UID_STATE_CACHED; 60 import static android.app.AppOpsManager.UID_STATE_FOREGROUND; 61 import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE; 62 import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED; 63 import static android.app.AppOpsManager.UID_STATE_PERSISTENT; 64 import static android.app.AppOpsManager.UID_STATE_TOP; 65 import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES; 66 import static android.app.AppOpsManager._NUM_OP; 67 import static android.app.AppOpsManager.extractFlagsFromKey; 68 import static android.app.AppOpsManager.extractUidStateFromKey; 69 import static android.app.AppOpsManager.makeKey; 70 import static android.app.AppOpsManager.modeToName; 71 import static android.app.AppOpsManager.opAllowSystemBypassRestriction; 72 import static android.app.AppOpsManager.opToName; 73 import static android.app.AppOpsManager.opToPublicName; 74 import static android.app.AppOpsManager.resolveFirstUnrestrictedUidState; 75 import static android.content.Intent.ACTION_PACKAGE_REMOVED; 76 import static android.content.Intent.EXTRA_REPLACING; 77 import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; 78 import static android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP; 79 80 import static com.android.server.appop.AppOpsService.ModeCallback.ALL_OPS; 81 82 import static java.lang.Long.max; 83 84 import android.Manifest; 85 import android.annotation.IntRange; 86 import android.annotation.NonNull; 87 import android.annotation.Nullable; 88 import android.annotation.UserIdInt; 89 import android.app.ActivityManager; 90 import android.app.ActivityManagerInternal; 91 import android.app.AppGlobals; 92 import android.app.AppOpsManager; 93 import android.app.AppOpsManager.AttributedOpEntry; 94 import android.app.AppOpsManager.AttributionFlags; 95 import android.app.AppOpsManager.HistoricalOps; 96 import android.app.AppOpsManager.Mode; 97 import android.app.AppOpsManager.OpEntry; 98 import android.app.AppOpsManager.OpFlags; 99 import android.app.AppOpsManagerInternal; 100 import android.app.AppOpsManagerInternal.CheckOpsDelegate; 101 import android.app.AsyncNotedAppOp; 102 import android.app.RuntimeAppOpAccessMessage; 103 import android.app.SyncNotedAppOp; 104 import android.app.admin.DevicePolicyManagerInternal; 105 import android.content.AttributionSource; 106 import android.content.BroadcastReceiver; 107 import android.content.ContentResolver; 108 import android.content.Context; 109 import android.content.Intent; 110 import android.content.IntentFilter; 111 import android.content.pm.PackageInfo; 112 import android.content.pm.PackageManager; 113 import android.content.pm.PackageManagerInternal; 114 import android.content.pm.PermissionInfo; 115 import android.content.pm.UserInfo; 116 import android.content.pm.parsing.component.ParsedAttribution; 117 import android.database.ContentObserver; 118 import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION; 119 import android.net.Uri; 120 import android.os.AsyncTask; 121 import android.os.Binder; 122 import android.os.Build; 123 import android.os.Bundle; 124 import android.os.Handler; 125 import android.os.IBinder; 126 import android.os.PackageTagsList; 127 import android.os.Process; 128 import android.os.RemoteCallback; 129 import android.os.RemoteCallbackList; 130 import android.os.RemoteException; 131 import android.os.ResultReceiver; 132 import android.os.ServiceManager; 133 import android.os.ShellCallback; 134 import android.os.ShellCommand; 135 import android.os.SystemClock; 136 import android.os.UserHandle; 137 import android.os.UserManager; 138 import android.os.storage.StorageManagerInternal; 139 import android.permission.PermissionManager; 140 import android.provider.Settings; 141 import android.util.ArrayMap; 142 import android.util.ArraySet; 143 import android.util.AtomicFile; 144 import android.util.IndentingPrintWriter; 145 import android.util.KeyValueListParser; 146 import android.util.LongSparseArray; 147 import android.util.Pair; 148 import android.util.Pools; 149 import android.util.Pools.SimplePool; 150 import android.util.Slog; 151 import android.util.SparseArray; 152 import android.util.SparseBooleanArray; 153 import android.util.SparseIntArray; 154 import android.util.TimeUtils; 155 import android.util.TypedXmlPullParser; 156 import android.util.TypedXmlSerializer; 157 import android.util.Xml; 158 159 import com.android.internal.annotations.GuardedBy; 160 import com.android.internal.annotations.Immutable; 161 import com.android.internal.annotations.VisibleForTesting; 162 import com.android.internal.app.IAppOpsActiveCallback; 163 import com.android.internal.app.IAppOpsAsyncNotedCallback; 164 import com.android.internal.app.IAppOpsCallback; 165 import com.android.internal.app.IAppOpsNotedCallback; 166 import com.android.internal.app.IAppOpsService; 167 import com.android.internal.app.IAppOpsStartedCallback; 168 import com.android.internal.app.MessageSamplingConfig; 169 import com.android.internal.compat.IPlatformCompat; 170 import com.android.internal.util.ArrayUtils; 171 import com.android.internal.util.DumpUtils; 172 import com.android.internal.util.Preconditions; 173 import com.android.internal.util.XmlUtils; 174 import com.android.internal.util.function.pooled.PooledLambda; 175 import com.android.server.LocalServices; 176 import com.android.server.LockGuard; 177 import com.android.server.SystemServerInitThreadPool; 178 import com.android.server.SystemServiceManager; 179 import com.android.server.pm.PackageList; 180 import com.android.server.pm.parsing.pkg.AndroidPackage; 181 182 import libcore.util.EmptyArray; 183 184 import org.json.JSONException; 185 import org.json.JSONObject; 186 import org.xmlpull.v1.XmlPullParser; 187 import org.xmlpull.v1.XmlPullParserException; 188 189 import java.io.File; 190 import java.io.FileDescriptor; 191 import java.io.FileInputStream; 192 import java.io.FileNotFoundException; 193 import java.io.FileOutputStream; 194 import java.io.FileWriter; 195 import java.io.IOException; 196 import java.io.PrintWriter; 197 import java.text.SimpleDateFormat; 198 import java.time.Instant; 199 import java.time.temporal.ChronoUnit; 200 import java.util.ArrayList; 201 import java.util.Arrays; 202 import java.util.Collections; 203 import java.util.Date; 204 import java.util.HashMap; 205 import java.util.Iterator; 206 import java.util.List; 207 import java.util.Map; 208 import java.util.NoSuchElementException; 209 import java.util.Objects; 210 import java.util.Scanner; 211 import java.util.Set; 212 import java.util.concurrent.ThreadLocalRandom; 213 import java.util.function.Consumer; 214 215 public class AppOpsService extends IAppOpsService.Stub { 216 static final String TAG = "AppOps"; 217 static final boolean DEBUG = false; 218 219 /** 220 * Used for data access validation collection, we wish to only log a specific access once 221 */ 222 private final ArraySet<NoteOpTrace> mNoteOpCallerStacktraces = new ArraySet<>(); 223 224 private static final int NO_VERSION = -1; 225 /** Increment by one every time and add the corresponding upgrade logic in 226 * {@link #upgradeLocked(int)} below. The first version was 1 */ 227 private static final int CURRENT_VERSION = 1; 228 229 // Write at most every 30 minutes. 230 static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000; 231 232 // Constant meaning that any UID should be matched when dispatching callbacks 233 private static final int UID_ANY = -2; 234 235 // Map from process states to the uid states we track. 236 private static final int[] PROCESS_STATE_TO_UID_STATE = new int[] { 237 UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT 238 UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI 239 UID_STATE_TOP, // ActivityManager.PROCESS_STATE_TOP 240 UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP 241 UID_STATE_FOREGROUND_SERVICE, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE 242 UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE 243 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND 244 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND 245 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND 246 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_BACKUP 247 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_SERVICE 248 UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_RECEIVER 249 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_TOP_SLEEPING 250 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT 251 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_HOME 252 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY 253 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY 254 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT 255 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_RECENT 256 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_CACHED_EMPTY 257 UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_NONEXISTENT 258 }; 259 260 private static final int[] OPS_RESTRICTED_ON_SUSPEND = { 261 OP_PLAY_AUDIO, 262 OP_RECORD_AUDIO, 263 OP_CAMERA, 264 }; 265 266 private static final int MAX_UNFORWARDED_OPS = 10; 267 private static final int MAX_UNUSED_POOLED_OBJECTS = 3; 268 private static final int RARELY_USED_PACKAGES_INITIALIZATION_DELAY_MILLIS = 300000; 269 270 final Context mContext; 271 final AtomicFile mFile; 272 private final @Nullable File mNoteOpCallerStacktracesFile; 273 final Handler mHandler; 274 275 /** Pool for {@link OpEventProxyInfoPool} to avoid to constantly reallocate new objects */ 276 @GuardedBy("this") 277 private final OpEventProxyInfoPool mOpEventProxyInfoPool = new OpEventProxyInfoPool(); 278 279 /** Pool for {@link InProgressStartOpEventPool} to avoid to constantly reallocate new objects */ 280 @GuardedBy("this") 281 private final InProgressStartOpEventPool mInProgressStartOpEventPool = 282 new InProgressStartOpEventPool(); 283 284 private final AppOpsManagerInternalImpl mAppOpsManagerInternal 285 = new AppOpsManagerInternalImpl(); 286 @Nullable private final DevicePolicyManagerInternal dpmi = 287 LocalServices.getService(DevicePolicyManagerInternal.class); 288 289 private final IPlatformCompat mPlatformCompat = IPlatformCompat.Stub.asInterface( 290 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); 291 292 /** 293 * Registered callbacks, called from {@link #collectAsyncNotedOp}. 294 * 295 * <p>(package name, uid) -> callbacks 296 * 297 * @see #getAsyncNotedOpsKey(String, int) 298 */ 299 @GuardedBy("this") 300 private final ArrayMap<Pair<String, Integer>, RemoteCallbackList<IAppOpsAsyncNotedCallback>> 301 mAsyncOpWatchers = new ArrayMap<>(); 302 303 /** 304 * Async note-ops collected from {@link #collectAsyncNotedOp} that have not been delivered to a 305 * callback yet. 306 * 307 * <p>(package name, uid) -> list<ops> 308 * 309 * @see #getAsyncNotedOpsKey(String, int) 310 */ 311 @GuardedBy("this") 312 private final ArrayMap<Pair<String, Integer>, ArrayList<AsyncNotedAppOp>> 313 mUnforwardedAsyncNotedOps = new ArrayMap<>(); 314 315 boolean mWriteNoteOpsScheduled; 316 317 boolean mWriteScheduled; 318 boolean mFastWriteScheduled; 319 final Runnable mWriteRunner = new Runnable() { 320 public void run() { 321 synchronized (AppOpsService.this) { 322 mWriteScheduled = false; 323 mFastWriteScheduled = false; 324 AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { 325 @Override protected Void doInBackground(Void... params) { 326 writeState(); 327 return null; 328 } 329 }; 330 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null); 331 } 332 } 333 }; 334 335 @GuardedBy("this") 336 @VisibleForTesting 337 final SparseArray<UidState> mUidStates = new SparseArray<>(); 338 339 volatile @NonNull HistoricalRegistry mHistoricalRegistry = new HistoricalRegistry(this); 340 341 long mLastRealtime; 342 343 /* 344 * These are app op restrictions imposed per user from various parties. 345 */ 346 private final ArrayMap<IBinder, ClientUserRestrictionState> mOpUserRestrictions = 347 new ArrayMap<>(); 348 349 /* 350 * These are app op restrictions imposed globally from various parties within the system. 351 */ 352 private final ArrayMap<IBinder, ClientGlobalRestrictionState> mOpGlobalRestrictions = 353 new ArrayMap<>(); 354 355 SparseIntArray mProfileOwners; 356 357 private volatile CheckOpsDelegateDispatcher mCheckOpsDelegateDispatcher = 358 new CheckOpsDelegateDispatcher(/*policy*/ null, /*delegate*/ null); 359 360 /** 361 * Reverse lookup for {@link AppOpsManager#opToSwitch(int)}. Initialized once and never 362 * changed 363 */ 364 private final SparseArray<int[]> mSwitchedOps = new SparseArray<>(); 365 366 private ActivityManagerInternal mActivityManagerInternal; 367 368 /** Package sampled for message collection in the current session */ 369 @GuardedBy("this") 370 private String mSampledPackage = null; 371 372 /** Appop sampled for message collection in the current session */ 373 @GuardedBy("this") 374 private int mSampledAppOpCode = OP_NONE; 375 376 /** Maximum distance for appop to be considered for message collection in the current session */ 377 @GuardedBy("this") 378 private int mAcceptableLeftDistance = 0; 379 380 /** Number of messages collected for sampled package and appop in the current session */ 381 @GuardedBy("this") 382 private float mMessagesCollectedCount; 383 384 /** List of rarely used packages priorities for message collection */ 385 @GuardedBy("this") 386 private ArraySet<String> mRarelyUsedPackages = new ArraySet<>(); 387 388 /** Sampling strategy used for current session */ 389 @GuardedBy("this") 390 @AppOpsManager.SamplingStrategy 391 private int mSamplingStrategy; 392 393 /** Last runtime permission access message collected and ready for reporting */ 394 @GuardedBy("this") 395 private RuntimeAppOpAccessMessage mCollectedRuntimePermissionMessage; 396 397 /** Package Manager internal. Access via {@link #getPackageManagerInternal()} */ 398 private @Nullable PackageManagerInternal mPackageManagerInternal; 399 400 /** 401 * An unsynchronized pool of {@link OpEventProxyInfo} objects. 402 */ 403 private class OpEventProxyInfoPool extends SimplePool<OpEventProxyInfo> { OpEventProxyInfoPool()404 OpEventProxyInfoPool() { 405 super(MAX_UNUSED_POOLED_OBJECTS); 406 } 407 acquire(@ntRangefrom = 0) int uid, @Nullable String packageName, @Nullable String attributionTag)408 OpEventProxyInfo acquire(@IntRange(from = 0) int uid, @Nullable String packageName, 409 @Nullable String attributionTag) { 410 OpEventProxyInfo recycled = acquire(); 411 if (recycled != null) { 412 recycled.reinit(uid, packageName, attributionTag); 413 return recycled; 414 } 415 416 return new OpEventProxyInfo(uid, packageName, attributionTag); 417 } 418 } 419 420 /** 421 * An unsynchronized pool of {@link InProgressStartOpEvent} objects. 422 */ 423 private class InProgressStartOpEventPool extends SimplePool<InProgressStartOpEvent> { InProgressStartOpEventPool()424 InProgressStartOpEventPool() { 425 super(MAX_UNUSED_POOLED_OBJECTS); 426 } 427 acquire(long startTime, long elapsedTime, @NonNull IBinder clientId, @Nullable String attributionTag, @NonNull Runnable onDeath, int proxyUid, @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState, @OpFlags int flags, @AttributionFlags int attributionFlags, int attributionChainId)428 InProgressStartOpEvent acquire(long startTime, long elapsedTime, @NonNull IBinder clientId, 429 @Nullable String attributionTag, @NonNull Runnable onDeath, int proxyUid, 430 @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, 431 @AppOpsManager.UidState int uidState, @OpFlags int flags, @AttributionFlags 432 int attributionFlags, int attributionChainId) throws RemoteException { 433 434 InProgressStartOpEvent recycled = acquire(); 435 436 OpEventProxyInfo proxyInfo = null; 437 if (proxyUid != Process.INVALID_UID) { 438 proxyInfo = mOpEventProxyInfoPool.acquire(proxyUid, proxyPackageName, 439 proxyAttributionTag); 440 } 441 442 if (recycled != null) { 443 recycled.reinit(startTime, elapsedTime, clientId, attributionTag, onDeath, 444 uidState, flags, proxyInfo, attributionFlags, attributionChainId, 445 mOpEventProxyInfoPool); 446 return recycled; 447 } 448 449 return new InProgressStartOpEvent(startTime, elapsedTime, clientId, attributionTag, 450 onDeath, uidState, proxyInfo, flags, attributionFlags, attributionChainId); 451 } 452 } 453 454 /** 455 * All times are in milliseconds. These constants are kept synchronized with the system 456 * global Settings. Any access to this class or its fields should be done while 457 * holding the AppOpsService lock. 458 */ 459 @VisibleForTesting 460 final class Constants extends ContentObserver { 461 462 /** 463 * How long we want for a drop in uid state from top to settle before applying it. 464 * @see Settings.Global#APP_OPS_CONSTANTS 465 * @see AppOpsManager#KEY_TOP_STATE_SETTLE_TIME 466 */ 467 public long TOP_STATE_SETTLE_TIME; 468 469 /** 470 * How long we want for a drop in uid state from foreground to settle before applying it. 471 * @see Settings.Global#APP_OPS_CONSTANTS 472 * @see AppOpsManager#KEY_FG_SERVICE_STATE_SETTLE_TIME 473 */ 474 public long FG_SERVICE_STATE_SETTLE_TIME; 475 476 /** 477 * How long we want for a drop in uid state from background to settle before applying it. 478 * @see Settings.Global#APP_OPS_CONSTANTS 479 * @see AppOpsManager#KEY_BG_STATE_SETTLE_TIME 480 */ 481 public long BG_STATE_SETTLE_TIME; 482 483 private final KeyValueListParser mParser = new KeyValueListParser(','); 484 private ContentResolver mResolver; 485 Constants(Handler handler)486 public Constants(Handler handler) { 487 super(handler); 488 updateConstants(); 489 } 490 startMonitoring(ContentResolver resolver)491 public void startMonitoring(ContentResolver resolver) { 492 mResolver = resolver; 493 mResolver.registerContentObserver( 494 Settings.Global.getUriFor(Settings.Global.APP_OPS_CONSTANTS), 495 false, this); 496 updateConstants(); 497 } 498 499 @Override onChange(boolean selfChange, Uri uri)500 public void onChange(boolean selfChange, Uri uri) { 501 updateConstants(); 502 } 503 updateConstants()504 private void updateConstants() { 505 String value = mResolver != null ? Settings.Global.getString(mResolver, 506 Settings.Global.APP_OPS_CONSTANTS) : ""; 507 508 synchronized (AppOpsService.this) { 509 try { 510 mParser.setString(value); 511 } catch (IllegalArgumentException e) { 512 // Failed to parse the settings string, log this and move on 513 // with defaults. 514 Slog.e(TAG, "Bad app ops settings", e); 515 } 516 TOP_STATE_SETTLE_TIME = mParser.getDurationMillis( 517 KEY_TOP_STATE_SETTLE_TIME, 5 * 1000L); 518 FG_SERVICE_STATE_SETTLE_TIME = mParser.getDurationMillis( 519 KEY_FG_SERVICE_STATE_SETTLE_TIME, 5 * 1000L); 520 BG_STATE_SETTLE_TIME = mParser.getDurationMillis( 521 KEY_BG_STATE_SETTLE_TIME, 1 * 1000L); 522 } 523 } 524 dump(PrintWriter pw)525 void dump(PrintWriter pw) { 526 pw.println(" Settings:"); 527 528 pw.print(" "); pw.print(KEY_TOP_STATE_SETTLE_TIME); pw.print("="); 529 TimeUtils.formatDuration(TOP_STATE_SETTLE_TIME, pw); 530 pw.println(); 531 pw.print(" "); pw.print(KEY_FG_SERVICE_STATE_SETTLE_TIME); pw.print("="); 532 TimeUtils.formatDuration(FG_SERVICE_STATE_SETTLE_TIME, pw); 533 pw.println(); 534 pw.print(" "); pw.print(KEY_BG_STATE_SETTLE_TIME); pw.print("="); 535 TimeUtils.formatDuration(BG_STATE_SETTLE_TIME, pw); 536 pw.println(); 537 } 538 } 539 540 @VisibleForTesting 541 final Constants mConstants; 542 543 @VisibleForTesting 544 final class UidState { 545 public final int uid; 546 547 public int state = UID_STATE_CACHED; 548 public int pendingState = UID_STATE_CACHED; 549 public long pendingStateCommitTime; 550 public int capability; 551 public int pendingCapability; 552 public boolean appWidgetVisible; 553 public boolean pendingAppWidgetVisible; 554 555 public ArrayMap<String, Ops> pkgOps; 556 public SparseIntArray opModes; 557 558 // true indicates there is an interested observer, false there isn't but it has such an op 559 public SparseBooleanArray foregroundOps; 560 public boolean hasForegroundWatchers; 561 UidState(int uid)562 public UidState(int uid) { 563 this.uid = uid; 564 } 565 clear()566 public void clear() { 567 pkgOps = null; 568 opModes = null; 569 } 570 isDefault()571 public boolean isDefault() { 572 return (pkgOps == null || pkgOps.isEmpty()) 573 && (opModes == null || opModes.size() <= 0) 574 && (state == UID_STATE_CACHED 575 && (pendingState == UID_STATE_CACHED)); 576 } 577 evalMode(int op, int mode)578 int evalMode(int op, int mode) { 579 if (mode == MODE_FOREGROUND) { 580 if (appWidgetVisible) { 581 return MODE_ALLOWED; 582 } else if (mActivityManagerInternal != null 583 && mActivityManagerInternal.isPendingTopUid(uid)) { 584 return MODE_ALLOWED; 585 } else if (mActivityManagerInternal != null 586 && mActivityManagerInternal.isTempAllowlistedForFgsWhileInUse(uid)) { 587 return MODE_ALLOWED; 588 } else if (state <= UID_STATE_TOP) { 589 // process is in TOP. 590 return MODE_ALLOWED; 591 } else if (state <= AppOpsManager.resolveFirstUnrestrictedUidState(op)) { 592 // process is in foreground, check its capability. 593 switch (op) { 594 case AppOpsManager.OP_FINE_LOCATION: 595 case AppOpsManager.OP_COARSE_LOCATION: 596 case AppOpsManager.OP_MONITOR_LOCATION: 597 case AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION: 598 if ((capability & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) { 599 return MODE_ALLOWED; 600 } else { 601 return MODE_IGNORED; 602 } 603 case OP_CAMERA: 604 if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) { 605 return MODE_ALLOWED; 606 } else { 607 return MODE_IGNORED; 608 } 609 case OP_RECORD_AUDIO: 610 if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) { 611 return MODE_ALLOWED; 612 } else { 613 return MODE_IGNORED; 614 } 615 default: 616 return MODE_ALLOWED; 617 } 618 } else { 619 // process is not in foreground. 620 return MODE_IGNORED; 621 } 622 } 623 return mode; 624 } 625 evalForegroundWatchers(int op, SparseArray<ArraySet<ModeCallback>> watchers, SparseBooleanArray which)626 private void evalForegroundWatchers(int op, SparseArray<ArraySet<ModeCallback>> watchers, 627 SparseBooleanArray which) { 628 boolean curValue = which.get(op, false); 629 ArraySet<ModeCallback> callbacks = watchers.get(op); 630 if (callbacks != null) { 631 for (int cbi = callbacks.size() - 1; !curValue && cbi >= 0; cbi--) { 632 if ((callbacks.valueAt(cbi).mFlags 633 & AppOpsManager.WATCH_FOREGROUND_CHANGES) != 0) { 634 hasForegroundWatchers = true; 635 curValue = true; 636 } 637 } 638 } 639 which.put(op, curValue); 640 } 641 evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers)642 public void evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers) { 643 SparseBooleanArray which = null; 644 hasForegroundWatchers = false; 645 if (opModes != null) { 646 for (int i = opModes.size() - 1; i >= 0; i--) { 647 if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) { 648 if (which == null) { 649 which = new SparseBooleanArray(); 650 } 651 evalForegroundWatchers(opModes.keyAt(i), watchers, which); 652 } 653 } 654 } 655 if (pkgOps != null) { 656 for (int i = pkgOps.size() - 1; i >= 0; i--) { 657 Ops ops = pkgOps.valueAt(i); 658 for (int j = ops.size() - 1; j >= 0; j--) { 659 if (ops.valueAt(j).mode == AppOpsManager.MODE_FOREGROUND) { 660 if (which == null) { 661 which = new SparseBooleanArray(); 662 } 663 evalForegroundWatchers(ops.keyAt(j), watchers, which); 664 } 665 } 666 } 667 } 668 foregroundOps = which; 669 } 670 } 671 672 final static class Ops extends SparseArray<Op> { 673 final String packageName; 674 final UidState uidState; 675 676 /** 677 * The restriction properties of the package. If {@code null} it could not have been read 678 * yet and has to be refreshed. 679 */ 680 @Nullable RestrictionBypass bypass; 681 682 /** Lazily populated cache of attributionTags of this package */ 683 final @NonNull ArraySet<String> knownAttributionTags = new ArraySet<>(); 684 685 /** 686 * Lazily populated cache of <b>valid</b> attributionTags of this package, a set smaller 687 * than or equal to {@link #knownAttributionTags}. 688 */ 689 final @NonNull ArraySet<String> validAttributionTags = new ArraySet<>(); 690 Ops(String _packageName, UidState _uidState)691 Ops(String _packageName, UidState _uidState) { 692 packageName = _packageName; 693 uidState = _uidState; 694 } 695 } 696 697 /** Returned from {@link #verifyAndGetBypass(int, String, String, String, boolean)}. */ 698 private static final class PackageVerificationResult { 699 700 final RestrictionBypass bypass; 701 final boolean isAttributionTagValid; 702 PackageVerificationResult(RestrictionBypass bypass, boolean isAttributionTagValid)703 PackageVerificationResult(RestrictionBypass bypass, boolean isAttributionTagValid) { 704 this.bypass = bypass; 705 this.isAttributionTagValid = isAttributionTagValid; 706 } 707 } 708 709 /** A in progress startOp->finishOp event */ 710 private static final class InProgressStartOpEvent implements IBinder.DeathRecipient { 711 /** Wall clock time of startOp event (not monotonic) */ 712 private long mStartTime; 713 714 /** Elapsed time since boot of startOp event */ 715 private long mStartElapsedTime; 716 717 /** Id of the client that started the event */ 718 private @NonNull IBinder mClientId; 719 720 /** The attribution tag for this operation */ 721 private @Nullable String mAttributionTag; 722 723 /** To call when client dies */ 724 private @NonNull Runnable mOnDeath; 725 726 /** uidstate used when calling startOp */ 727 private @AppOpsManager.UidState int mUidState; 728 729 /** Proxy information of the startOp event */ 730 private @Nullable OpEventProxyInfo mProxy; 731 732 /** Proxy flag information */ 733 private @OpFlags int mFlags; 734 735 /** How many times the op was started but not finished yet */ 736 int numUnfinishedStarts; 737 738 /** The attribution flags related to this event */ 739 private @AttributionFlags int mAttributionFlags; 740 741 /** The id of the attribution chain this even is a part of */ 742 private int mAttributionChainId; 743 744 /** 745 * Create a new {@link InProgressStartOpEvent}. 746 * 747 * @param startTime The time {@link #startOperation} was called 748 * @param startElapsedTime The elapsed time when {@link #startOperation} was called 749 * @param clientId The client id of the caller of {@link #startOperation} 750 * @param attributionTag The attribution tag for the operation. 751 * @param onDeath The code to execute on client death 752 * @param uidState The uidstate of the app {@link #startOperation} was called for 753 * @param attributionFlags the attribution flags for this operation. 754 * @param attributionChainId the unique id of the attribution chain this op is a part of. 755 * @param proxy The proxy information, if {@link #startProxyOperation} was called 756 * @param flags The trusted/nontrusted/self flags. 757 * 758 * @throws RemoteException If the client is dying 759 */ InProgressStartOpEvent(long startTime, long startElapsedTime, @NonNull IBinder clientId, @Nullable String attributionTag, @NonNull Runnable onDeath, @AppOpsManager.UidState int uidState, @Nullable OpEventProxyInfo proxy, @OpFlags int flags, @AttributionFlags int attributionFlags, int attributionChainId)760 private InProgressStartOpEvent(long startTime, long startElapsedTime, 761 @NonNull IBinder clientId, @Nullable String attributionTag, 762 @NonNull Runnable onDeath, @AppOpsManager.UidState int uidState, 763 @Nullable OpEventProxyInfo proxy, @OpFlags int flags, 764 @AttributionFlags int attributionFlags, int attributionChainId) 765 throws RemoteException { 766 mStartTime = startTime; 767 mStartElapsedTime = startElapsedTime; 768 mClientId = clientId; 769 mAttributionTag = attributionTag; 770 mOnDeath = onDeath; 771 mUidState = uidState; 772 mProxy = proxy; 773 mFlags = flags; 774 mAttributionFlags = attributionFlags; 775 mAttributionChainId = attributionChainId; 776 777 clientId.linkToDeath(this, 0); 778 } 779 780 /** Clean up event */ finish()781 public void finish() { 782 try { 783 mClientId.unlinkToDeath(this, 0); 784 } catch (NoSuchElementException e) { 785 // Either not linked, or already unlinked. Either way, nothing to do. 786 } 787 } 788 789 @Override binderDied()790 public void binderDied() { 791 mOnDeath.run(); 792 } 793 794 /** 795 * Reinit existing object with new state. 796 * 797 * @param startTime The time {@link #startOperation} was called 798 * @param startElapsedTime The elapsed time when {@link #startOperation} was called 799 * @param clientId The client id of the caller of {@link #startOperation} 800 * @param attributionTag The attribution tag for this operation. 801 * @param onDeath The code to execute on client death 802 * @param uidState The uidstate of the app {@link #startOperation} was called for 803 * @param flags The flags relating to the proxy 804 * @param proxy The proxy information, if {@link #startProxyOperation} was called 805 * @param attributionFlags the attribution flags for this operation. 806 * @param attributionChainId the unique id of the attribution chain this op is a part of. 807 * @param proxyPool The pool to release previous {@link OpEventProxyInfo} to 808 * 809 * @throws RemoteException If the client is dying 810 */ reinit(long startTime, long startElapsedTime, @NonNull IBinder clientId, @Nullable String attributionTag, @NonNull Runnable onDeath, @AppOpsManager.UidState int uidState, @OpFlags int flags, @Nullable OpEventProxyInfo proxy, @AttributionFlags int attributionFlags, int attributionChainId, @NonNull Pools.Pool<OpEventProxyInfo> proxyPool )811 public void reinit(long startTime, long startElapsedTime, @NonNull IBinder clientId, 812 @Nullable String attributionTag, @NonNull Runnable onDeath, 813 @AppOpsManager.UidState int uidState, @OpFlags int flags, 814 @Nullable OpEventProxyInfo proxy, @AttributionFlags int attributionFlags, 815 int attributionChainId, @NonNull Pools.Pool<OpEventProxyInfo> proxyPool 816 ) throws RemoteException { 817 mStartTime = startTime; 818 mStartElapsedTime = startElapsedTime; 819 mClientId = clientId; 820 mAttributionTag = attributionTag; 821 mOnDeath = onDeath; 822 mUidState = uidState; 823 mFlags = flags; 824 825 if (mProxy != null) { 826 proxyPool.release(mProxy); 827 } 828 mProxy = proxy; 829 mAttributionFlags = attributionFlags; 830 mAttributionChainId = attributionChainId; 831 832 clientId.linkToDeath(this, 0); 833 } 834 835 /** @return Wall clock time of startOp event */ getStartTime()836 public long getStartTime() { 837 return mStartTime; 838 } 839 840 /** @return Elapsed time since boot of startOp event */ getStartElapsedTime()841 public long getStartElapsedTime() { 842 return mStartElapsedTime; 843 } 844 845 /** @return Id of the client that started the event */ getClientId()846 public @NonNull IBinder getClientId() { 847 return mClientId; 848 } 849 850 /** @return uidstate used when calling startOp */ getUidState()851 public @AppOpsManager.UidState int getUidState() { 852 return mUidState; 853 } 854 855 /** @return proxy tag for the access */ getProxy()856 public @Nullable OpEventProxyInfo getProxy() { 857 return mProxy; 858 } 859 860 /** @return flags used for the access */ getFlags()861 public @OpFlags int getFlags() { 862 return mFlags; 863 } 864 865 /** @return attributoin flags used for the access */ getAttributionFlags()866 public @AttributionFlags int getAttributionFlags() { 867 return mAttributionFlags; 868 } 869 870 /** @return attribution chain id for the access */ getAttributionChainId()871 public int getAttributionChainId() { 872 return mAttributionChainId; 873 } 874 } 875 876 private final class AttributedOp { 877 public final @Nullable String tag; 878 public final @NonNull Op parent; 879 880 /** 881 * Last successful accesses (noteOp + finished startOp) for each uidState/opFlag combination 882 * 883 * <p>Key is {@link AppOpsManager#makeKey} 884 */ 885 @GuardedBy("AppOpsService.this") 886 private @Nullable LongSparseArray<NoteOpEvent> mAccessEvents; 887 888 /** 889 * Last rejected accesses for each uidState/opFlag combination 890 * 891 * <p>Key is {@link AppOpsManager#makeKey} 892 */ 893 @GuardedBy("AppOpsService.this") 894 private @Nullable LongSparseArray<NoteOpEvent> mRejectEvents; 895 896 /** 897 * Currently in progress startOp events 898 * 899 * <p>Key is clientId 900 */ 901 @GuardedBy("AppOpsService.this") 902 private @Nullable ArrayMap<IBinder, InProgressStartOpEvent> mInProgressEvents; 903 904 /** 905 * Currently paused startOp events 906 * 907 * <p>Key is clientId 908 */ 909 @GuardedBy("AppOpsService.this") 910 private @Nullable ArrayMap<IBinder, InProgressStartOpEvent> mPausedInProgressEvents; 911 AttributedOp(@ullable String tag, @NonNull Op parent)912 AttributedOp(@Nullable String tag, @NonNull Op parent) { 913 this.tag = tag; 914 this.parent = parent; 915 } 916 917 /** 918 * Update state when noteOp was rejected or startOp->finishOp event finished 919 * 920 * @param proxyUid The uid of the proxy 921 * @param proxyPackageName The package name of the proxy 922 * @param proxyAttributionTag the attributionTag in the proxies package 923 * @param uidState UID state of the app noteOp/startOp was called for 924 * @param flags OpFlags of the call 925 */ accessed(int proxyUid, @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState, @OpFlags int flags)926 public void accessed(int proxyUid, @Nullable String proxyPackageName, 927 @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState, 928 @OpFlags int flags) { 929 long accessTime = System.currentTimeMillis(); 930 accessed(accessTime, -1, proxyUid, proxyPackageName, 931 proxyAttributionTag, uidState, flags); 932 933 mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName, 934 tag, uidState, flags, accessTime, AppOpsManager.ATTRIBUTION_FLAGS_NONE, 935 AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE); 936 } 937 938 /** 939 * Add an access that was previously collected. 940 * 941 * @param noteTime The time of the event 942 * @param duration The duration of the event 943 * @param proxyUid The uid of the proxy 944 * @param proxyPackageName The package name of the proxy 945 * @param proxyAttributionTag the attributionTag in the proxies package 946 * @param uidState UID state of the app noteOp/startOp was called for 947 * @param flags OpFlags of the call 948 */ accessed(long noteTime, long duration, int proxyUid, @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState, @OpFlags int flags)949 public void accessed(long noteTime, long duration, int proxyUid, 950 @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, 951 @AppOpsManager.UidState int uidState, @OpFlags int flags) { 952 long key = makeKey(uidState, flags); 953 954 if (mAccessEvents == null) { 955 mAccessEvents = new LongSparseArray<>(1); 956 } 957 958 OpEventProxyInfo proxyInfo = null; 959 if (proxyUid != Process.INVALID_UID) { 960 proxyInfo = mOpEventProxyInfoPool.acquire(proxyUid, proxyPackageName, 961 proxyAttributionTag); 962 } 963 964 NoteOpEvent existingEvent = mAccessEvents.get(key); 965 if (existingEvent != null) { 966 existingEvent.reinit(noteTime, duration, proxyInfo, mOpEventProxyInfoPool); 967 } else { 968 mAccessEvents.put(key, new NoteOpEvent(noteTime, duration, proxyInfo)); 969 } 970 } 971 972 /** 973 * Update state when noteOp/startOp was rejected. 974 * 975 * @param uidState UID state of the app noteOp is called for 976 * @param flags OpFlags of the call 977 */ rejected(@ppOpsManager.UidState int uidState, @OpFlags int flags)978 public void rejected(@AppOpsManager.UidState int uidState, @OpFlags int flags) { 979 rejected(System.currentTimeMillis(), uidState, flags); 980 981 mHistoricalRegistry.incrementOpRejected(parent.op, parent.uid, parent.packageName, 982 tag, uidState, flags); 983 } 984 985 /** 986 * Add an rejection that was previously collected 987 * 988 * @param noteTime The time of the event 989 * @param uidState UID state of the app noteOp/startOp was called for 990 * @param flags OpFlags of the call 991 */ rejected(long noteTime, @AppOpsManager.UidState int uidState, @OpFlags int flags)992 public void rejected(long noteTime, @AppOpsManager.UidState int uidState, 993 @OpFlags int flags) { 994 long key = makeKey(uidState, flags); 995 996 if (mRejectEvents == null) { 997 mRejectEvents = new LongSparseArray<>(1); 998 } 999 1000 // We do not collect proxy information for rejections yet 1001 NoteOpEvent existingEvent = mRejectEvents.get(key); 1002 if (existingEvent != null) { 1003 existingEvent.reinit(noteTime, -1, null, mOpEventProxyInfoPool); 1004 } else { 1005 mRejectEvents.put(key, new NoteOpEvent(noteTime, -1, null)); 1006 } 1007 } 1008 1009 /** 1010 * Update state when start was called 1011 * 1012 * @param clientId Id of the startOp caller 1013 * @param proxyUid The UID of the proxy app 1014 * @param proxyPackageName The package name of the proxy app 1015 * @param proxyAttributionTag The attribution tag of the proxy app 1016 * @param uidState UID state of the app startOp is called for 1017 * @param flags The proxy flags 1018 * @param attributionFlags The attribution flags associated with this operation. 1019 * @param attributionChainId The if of the attribution chain this operations is a part of. 1020 */ started(@onNull IBinder clientId, int proxyUid, @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState, @OpFlags int flags, @AttributionFlags int attributionFlags, int attributionChainId)1021 public void started(@NonNull IBinder clientId, int proxyUid, 1022 @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, 1023 @AppOpsManager.UidState int uidState, @OpFlags int flags, @AttributionFlags 1024 int attributionFlags, int attributionChainId) throws RemoteException { 1025 started(clientId, proxyUid, proxyPackageName, proxyAttributionTag, 1026 uidState, flags,/*triggerCallbackIfNeeded*/ true, attributionFlags, 1027 attributionChainId); 1028 } 1029 started(@onNull IBinder clientId, int proxyUid, @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState, @OpFlags int flags, boolean triggerCallbackIfNeeded, @AttributionFlags int attributionFlags, int attributionChainId)1030 private void started(@NonNull IBinder clientId, int proxyUid, 1031 @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, 1032 @AppOpsManager.UidState int uidState, @OpFlags int flags, 1033 boolean triggerCallbackIfNeeded, @AttributionFlags int attributionFlags, 1034 int attributionChainId) throws RemoteException { 1035 startedOrPaused(clientId, proxyUid, proxyPackageName, 1036 proxyAttributionTag, uidState, flags, triggerCallbackIfNeeded, 1037 /*triggerCallbackIfNeeded*/ true, attributionFlags, attributionChainId); 1038 } 1039 startedOrPaused(@onNull IBinder clientId, int proxyUid, @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState, @OpFlags int flags, boolean triggerCallbackIfNeeded, boolean isStarted, @AttributionFlags int attributionFlags, int attributionChainId)1040 private void startedOrPaused(@NonNull IBinder clientId, int proxyUid, 1041 @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, 1042 @AppOpsManager.UidState int uidState, @OpFlags int flags, 1043 boolean triggerCallbackIfNeeded, boolean isStarted, @AttributionFlags 1044 int attributionFlags, int attributionChainId) throws RemoteException { 1045 if (triggerCallbackIfNeeded && !parent.isRunning() && isStarted) { 1046 scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid, parent.packageName, 1047 tag, true, attributionFlags, attributionChainId); 1048 } 1049 1050 if (isStarted && mInProgressEvents == null) { 1051 mInProgressEvents = new ArrayMap<>(1); 1052 } else if (!isStarted && mPausedInProgressEvents == null) { 1053 mPausedInProgressEvents = new ArrayMap<>(1); 1054 } 1055 ArrayMap<IBinder, InProgressStartOpEvent> events = isStarted 1056 ? mInProgressEvents : mPausedInProgressEvents; 1057 1058 long startTime = System.currentTimeMillis(); 1059 InProgressStartOpEvent event = events.get(clientId); 1060 if (event == null) { 1061 event = mInProgressStartOpEventPool.acquire(startTime, 1062 SystemClock.elapsedRealtime(), clientId, tag, 1063 PooledLambda.obtainRunnable(AppOpsService::onClientDeath, this, clientId), 1064 proxyUid, proxyPackageName, proxyAttributionTag, uidState, flags, 1065 attributionFlags, attributionChainId); 1066 events.put(clientId, event); 1067 } else { 1068 if (uidState != event.mUidState) { 1069 onUidStateChanged(uidState); 1070 } 1071 } 1072 1073 event.numUnfinishedStarts++; 1074 1075 if (isStarted) { 1076 mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, 1077 parent.packageName, tag, uidState, flags, startTime, attributionFlags, 1078 attributionChainId); 1079 } 1080 } 1081 1082 /** 1083 * Update state when finishOp was called. Will finish started ops, and delete paused ops. 1084 * 1085 * @param clientId Id of the finishOp caller 1086 */ finished(@onNull IBinder clientId)1087 public void finished(@NonNull IBinder clientId) { 1088 finished(clientId, true); 1089 } 1090 finished(@onNull IBinder clientId, boolean triggerCallbackIfNeeded)1091 private void finished(@NonNull IBinder clientId, boolean triggerCallbackIfNeeded) { 1092 finishOrPause(clientId, triggerCallbackIfNeeded, false); 1093 } 1094 1095 /** 1096 * Update state when paused or finished is called. If pausing, it records the op as 1097 * stopping in the HistoricalRegistry, but does not delete it. 1098 */ finishOrPause(@onNull IBinder clientId, boolean triggerCallbackIfNeeded, boolean isPausing)1099 private void finishOrPause(@NonNull IBinder clientId, boolean triggerCallbackIfNeeded, 1100 boolean isPausing) { 1101 int indexOfToken = isRunning() ? mInProgressEvents.indexOfKey(clientId) : -1; 1102 if (indexOfToken < 0) { 1103 finishPossiblyPaused(clientId, isPausing); 1104 return; 1105 } 1106 1107 InProgressStartOpEvent event = mInProgressEvents.valueAt(indexOfToken); 1108 if (!isPausing) { 1109 event.numUnfinishedStarts--; 1110 } 1111 // If we are pausing, create a NoteOpEvent, but don't change the InProgress event 1112 if (event.numUnfinishedStarts == 0 || isPausing) { 1113 if (!isPausing) { 1114 event.finish(); 1115 mInProgressEvents.removeAt(indexOfToken); 1116 } 1117 1118 if (mAccessEvents == null) { 1119 mAccessEvents = new LongSparseArray<>(1); 1120 } 1121 1122 OpEventProxyInfo proxyCopy = event.getProxy() != null 1123 ? new OpEventProxyInfo(event.getProxy()) : null; 1124 1125 long accessDurationMillis = 1126 SystemClock.elapsedRealtime() - event.getStartElapsedTime(); 1127 NoteOpEvent finishedEvent = new NoteOpEvent(event.getStartTime(), 1128 accessDurationMillis, proxyCopy); 1129 mAccessEvents.put(makeKey(event.getUidState(), event.getFlags()), 1130 finishedEvent); 1131 1132 mHistoricalRegistry.increaseOpAccessDuration(parent.op, parent.uid, 1133 parent.packageName, tag, event.getUidState(), 1134 event.getFlags(), finishedEvent.getNoteTime(), finishedEvent.getDuration(), 1135 event.getAttributionFlags(), event.getAttributionChainId()); 1136 1137 if (!isPausing) { 1138 mInProgressStartOpEventPool.release(event); 1139 if (mInProgressEvents.isEmpty()) { 1140 mInProgressEvents = null; 1141 1142 // TODO ntmyren: Also callback for single attribution tag activity changes 1143 if (triggerCallbackIfNeeded && !parent.isRunning()) { 1144 scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid, 1145 parent.packageName, tag, false, event.getAttributionFlags(), 1146 event.getAttributionChainId()); 1147 } 1148 } 1149 } 1150 } 1151 } 1152 1153 // Finish or pause (no-op) an already paused op finishPossiblyPaused(@onNull IBinder clientId, boolean isPausing)1154 private void finishPossiblyPaused(@NonNull IBinder clientId, boolean isPausing) { 1155 if (!isPaused()) { 1156 Slog.wtf(TAG, "No ops running or paused"); 1157 return; 1158 } 1159 1160 int indexOfToken = mPausedInProgressEvents.indexOfKey(clientId); 1161 if (indexOfToken < 0) { 1162 Slog.wtf(TAG, "No op running or paused for the client"); 1163 return; 1164 } else if (isPausing) { 1165 // already paused 1166 return; 1167 } 1168 1169 // no need to record a paused event finishing. 1170 InProgressStartOpEvent event = mPausedInProgressEvents.valueAt(indexOfToken); 1171 event.numUnfinishedStarts--; 1172 if (event.numUnfinishedStarts == 0) { 1173 mPausedInProgressEvents.removeAt(indexOfToken); 1174 mInProgressStartOpEventPool.release(event); 1175 if (mPausedInProgressEvents.isEmpty()) { 1176 mPausedInProgressEvents = null; 1177 } 1178 } 1179 } 1180 1181 /** 1182 * Create an event that will be started, if the op is unpaused. 1183 */ createPaused(@onNull IBinder clientId, int proxyUid, @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState, @OpFlags int flags, @AttributionFlags int attributionFlags, int attributionChainId)1184 public void createPaused(@NonNull IBinder clientId, int proxyUid, 1185 @Nullable String proxyPackageName, @Nullable String proxyAttributionTag, 1186 @AppOpsManager.UidState int uidState, @OpFlags int flags, @AttributionFlags 1187 int attributionFlags, int attributionChainId) throws RemoteException { 1188 startedOrPaused(clientId, proxyUid, proxyPackageName, proxyAttributionTag, 1189 uidState, flags, true, false, attributionFlags, attributionChainId); 1190 } 1191 1192 /** 1193 * Pause all currently started ops. This will create a HistoricalRegistry 1194 */ pause()1195 public void pause() { 1196 if (!isRunning()) { 1197 return; 1198 } 1199 1200 if (mPausedInProgressEvents == null) { 1201 mPausedInProgressEvents = new ArrayMap<>(1); 1202 } 1203 1204 for (int i = 0; i < mInProgressEvents.size(); i++) { 1205 InProgressStartOpEvent event = mInProgressEvents.valueAt(i); 1206 mPausedInProgressEvents.put(event.mClientId, event); 1207 finishOrPause(event.mClientId, true, true); 1208 1209 scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid, 1210 parent.packageName, tag, false, 1211 event.getAttributionFlags(), event.getAttributionChainId()); 1212 } 1213 mInProgressEvents = null; 1214 } 1215 1216 /** 1217 * Unpause all currently paused ops. This will reinitialize their start and duration 1218 * times, but keep all other values the same 1219 */ resume()1220 public void resume() { 1221 if (!isPaused()) { 1222 return; 1223 } 1224 1225 if (mInProgressEvents == null) { 1226 mInProgressEvents = new ArrayMap<>(mPausedInProgressEvents.size()); 1227 } 1228 boolean shouldSendActive = !mPausedInProgressEvents.isEmpty() 1229 && mInProgressEvents.isEmpty(); 1230 1231 long startTime = System.currentTimeMillis(); 1232 for (int i = 0; i < mPausedInProgressEvents.size(); i++) { 1233 InProgressStartOpEvent event = mPausedInProgressEvents.valueAt(i); 1234 mInProgressEvents.put(event.mClientId, event); 1235 event.mStartElapsedTime = SystemClock.elapsedRealtime(); 1236 event.mStartTime = startTime; 1237 mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, 1238 parent.packageName, tag, event.mUidState, event.mFlags, startTime, 1239 event.getAttributionFlags(), event.getAttributionChainId()); 1240 if (shouldSendActive) { 1241 scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid, parent.packageName, 1242 tag, true, event.getAttributionFlags(), event.getAttributionChainId()); 1243 } 1244 // Note: this always sends MODE_ALLOWED, even if the mode is FOREGROUND 1245 // TODO ntmyren: figure out how to get the real mode. 1246 scheduleOpStartedIfNeededLocked(parent.op, parent.uid, parent.packageName, 1247 tag, event.getFlags(), MODE_ALLOWED, START_TYPE_RESUMED, 1248 event.getAttributionFlags(), event.getAttributionChainId()); 1249 } 1250 mPausedInProgressEvents = null; 1251 } 1252 1253 /** 1254 * Called in the case the client dies without calling finish first 1255 * 1256 * @param clientId The client that died 1257 */ onClientDeath(@onNull IBinder clientId)1258 void onClientDeath(@NonNull IBinder clientId) { 1259 synchronized (AppOpsService.this) { 1260 if (!isPaused() && !isRunning()) { 1261 return; 1262 } 1263 1264 ArrayMap<IBinder, InProgressStartOpEvent> events = isPaused() 1265 ? mPausedInProgressEvents : mInProgressEvents; 1266 InProgressStartOpEvent deadEvent = events.get(clientId); 1267 if (deadEvent != null) { 1268 deadEvent.numUnfinishedStarts = 1; 1269 } 1270 1271 finished(clientId); 1272 } 1273 } 1274 1275 /** 1276 * Notify that the state of the uid changed 1277 * 1278 * @param newState The new state 1279 */ onUidStateChanged(@ppOpsManager.UidState int newState)1280 public void onUidStateChanged(@AppOpsManager.UidState int newState) { 1281 if (!isPaused() && !isRunning()) { 1282 return; 1283 } 1284 1285 boolean isRunning = isRunning(); 1286 ArrayMap<IBinder, AppOpsService.InProgressStartOpEvent> events = 1287 isRunning ? mInProgressEvents : mPausedInProgressEvents; 1288 1289 int numInProgressEvents = events.size(); 1290 List<IBinder> binders = new ArrayList<>(events.keySet()); 1291 for (int i = 0; i < numInProgressEvents; i++) { 1292 InProgressStartOpEvent event = events.get(binders.get(i)); 1293 1294 if (event != null && event.getUidState() != newState) { 1295 try { 1296 // Remove all but one unfinished start count and then call finished() to 1297 // remove start event object 1298 int numPreviousUnfinishedStarts = event.numUnfinishedStarts; 1299 event.numUnfinishedStarts = 1; 1300 OpEventProxyInfo proxy = event.getProxy(); 1301 1302 finished(event.getClientId(), false); 1303 1304 // Call started() to add a new start event object and then add the 1305 // previously removed unfinished start counts back 1306 if (proxy != null) { 1307 startedOrPaused(event.getClientId(), proxy.getUid(), 1308 proxy.getPackageName(), proxy.getAttributionTag(), newState, 1309 event.getFlags(), false, isRunning, 1310 event.getAttributionFlags(), event.getAttributionChainId()); 1311 } else { 1312 startedOrPaused(event.getClientId(), Process.INVALID_UID, null, null, 1313 newState, event.getFlags(), false, isRunning, 1314 event.getAttributionFlags(), event.getAttributionChainId()); 1315 } 1316 1317 events = isRunning ? mInProgressEvents : mPausedInProgressEvents; 1318 InProgressStartOpEvent newEvent = events.get(binders.get(i)); 1319 if (newEvent != null) { 1320 newEvent.numUnfinishedStarts += numPreviousUnfinishedStarts - 1; 1321 } 1322 } catch (RemoteException e) { 1323 if (DEBUG) Slog.e(TAG, "Cannot switch to new uidState " + newState); 1324 } 1325 } 1326 } 1327 } 1328 1329 /** 1330 * Combine {@code a} and {@code b} and return the result. The result might be {@code a} 1331 * or {@code b}. If there is an event for the same key in both the later event is retained. 1332 */ add(@ullable LongSparseArray<NoteOpEvent> a, @Nullable LongSparseArray<NoteOpEvent> b)1333 private @Nullable LongSparseArray<NoteOpEvent> add(@Nullable LongSparseArray<NoteOpEvent> a, 1334 @Nullable LongSparseArray<NoteOpEvent> b) { 1335 if (a == null) { 1336 return b; 1337 } 1338 1339 if (b == null) { 1340 return a; 1341 } 1342 1343 int numEventsToAdd = b.size(); 1344 for (int i = 0; i < numEventsToAdd; i++) { 1345 long keyOfEventToAdd = b.keyAt(i); 1346 NoteOpEvent bEvent = b.valueAt(i); 1347 NoteOpEvent aEvent = a.get(keyOfEventToAdd); 1348 1349 if (aEvent == null || bEvent.getNoteTime() > aEvent.getNoteTime()) { 1350 a.put(keyOfEventToAdd, bEvent); 1351 } 1352 } 1353 1354 return a; 1355 } 1356 1357 /** 1358 * Add all data from the {@code opToAdd} to this op. 1359 * 1360 * <p>If there is an event for the same key in both the later event is retained. 1361 * <p>{@code opToAdd} should not be used after this method is called. 1362 * 1363 * @param opToAdd The op to add 1364 */ add(@onNull AttributedOp opToAdd)1365 public void add(@NonNull AttributedOp opToAdd) { 1366 if (opToAdd.isRunning() || opToAdd.isPaused()) { 1367 ArrayMap<IBinder, InProgressStartOpEvent> ignoredEvents = opToAdd.isRunning() 1368 ? opToAdd.mInProgressEvents : opToAdd.mPausedInProgressEvents; 1369 Slog.w(TAG, "Ignoring " + ignoredEvents.size() + " app-ops, running: " 1370 + opToAdd.isRunning()); 1371 1372 int numInProgressEvents = ignoredEvents.size(); 1373 for (int i = 0; i < numInProgressEvents; i++) { 1374 InProgressStartOpEvent event = ignoredEvents.valueAt(i); 1375 1376 event.finish(); 1377 mInProgressStartOpEventPool.release(event); 1378 } 1379 } 1380 1381 mAccessEvents = add(mAccessEvents, opToAdd.mAccessEvents); 1382 mRejectEvents = add(mRejectEvents, opToAdd.mRejectEvents); 1383 } 1384 isRunning()1385 public boolean isRunning() { 1386 return mInProgressEvents != null && !mInProgressEvents.isEmpty(); 1387 } 1388 isPaused()1389 public boolean isPaused() { 1390 return mPausedInProgressEvents != null && !mPausedInProgressEvents.isEmpty(); 1391 } 1392 hasAnyTime()1393 boolean hasAnyTime() { 1394 return (mAccessEvents != null && mAccessEvents.size() > 0) 1395 || (mRejectEvents != null && mRejectEvents.size() > 0); 1396 } 1397 1398 /** 1399 * Clone a {@link LongSparseArray} and clone all values. 1400 */ deepClone( @ullable LongSparseArray<NoteOpEvent> original)1401 private @Nullable LongSparseArray<NoteOpEvent> deepClone( 1402 @Nullable LongSparseArray<NoteOpEvent> original) { 1403 if (original == null) { 1404 return original; 1405 } 1406 1407 int size = original.size(); 1408 LongSparseArray<NoteOpEvent> clone = new LongSparseArray<>(size); 1409 for (int i = 0; i < size; i++) { 1410 clone.put(original.keyAt(i), new NoteOpEvent(original.valueAt(i))); 1411 } 1412 1413 return clone; 1414 } 1415 createAttributedOpEntryLocked()1416 @NonNull AttributedOpEntry createAttributedOpEntryLocked() { 1417 LongSparseArray<NoteOpEvent> accessEvents = deepClone(mAccessEvents); 1418 1419 // Add in progress events as access events 1420 if (isRunning()) { 1421 long now = SystemClock.elapsedRealtime(); 1422 int numInProgressEvents = mInProgressEvents.size(); 1423 1424 if (accessEvents == null) { 1425 accessEvents = new LongSparseArray<>(numInProgressEvents); 1426 } 1427 1428 for (int i = 0; i < numInProgressEvents; i++) { 1429 InProgressStartOpEvent event = mInProgressEvents.valueAt(i); 1430 1431 accessEvents.append(makeKey(event.getUidState(), event.getFlags()), 1432 new NoteOpEvent(event.getStartTime(), now - event.getStartElapsedTime(), 1433 event.getProxy())); 1434 } 1435 } 1436 1437 LongSparseArray<NoteOpEvent> rejectEvents = deepClone(mRejectEvents); 1438 1439 return new AttributedOpEntry(parent.op, isRunning(), accessEvents, rejectEvents); 1440 } 1441 } 1442 1443 final class Op { 1444 int op; 1445 int uid; 1446 final UidState uidState; 1447 final @NonNull String packageName; 1448 1449 private @Mode int mode; 1450 1451 /** attributionTag -> AttributedOp */ 1452 final ArrayMap<String, AttributedOp> mAttributions = new ArrayMap<>(1); 1453 Op(UidState uidState, String packageName, int op, int uid)1454 Op(UidState uidState, String packageName, int op, int uid) { 1455 this.op = op; 1456 this.uid = uid; 1457 this.uidState = uidState; 1458 this.packageName = packageName; 1459 this.mode = AppOpsManager.opToDefaultMode(op); 1460 } 1461 getMode()1462 int getMode() { 1463 return mode; 1464 } 1465 evalMode()1466 int evalMode() { 1467 return uidState.evalMode(op, mode); 1468 } 1469 removeAttributionsWithNoTime()1470 void removeAttributionsWithNoTime() { 1471 for (int i = mAttributions.size() - 1; i >= 0; i--) { 1472 if (!mAttributions.valueAt(i).hasAnyTime()) { 1473 mAttributions.removeAt(i); 1474 } 1475 } 1476 } 1477 getOrCreateAttribution(@onNull Op parent, @Nullable String attributionTag)1478 private @NonNull AttributedOp getOrCreateAttribution(@NonNull Op parent, 1479 @Nullable String attributionTag) { 1480 AttributedOp attributedOp; 1481 1482 attributedOp = mAttributions.get(attributionTag); 1483 if (attributedOp == null) { 1484 attributedOp = new AttributedOp(attributionTag, parent); 1485 mAttributions.put(attributionTag, attributedOp); 1486 } 1487 1488 return attributedOp; 1489 } 1490 createEntryLocked()1491 @NonNull OpEntry createEntryLocked() { 1492 final int numAttributions = mAttributions.size(); 1493 1494 final ArrayMap<String, AppOpsManager.AttributedOpEntry> attributionEntries = 1495 new ArrayMap<>(numAttributions); 1496 for (int i = 0; i < numAttributions; i++) { 1497 attributionEntries.put(mAttributions.keyAt(i), 1498 mAttributions.valueAt(i).createAttributedOpEntryLocked()); 1499 } 1500 1501 return new OpEntry(op, mode, attributionEntries); 1502 } 1503 createSingleAttributionEntryLocked(@ullable String attributionTag)1504 @NonNull OpEntry createSingleAttributionEntryLocked(@Nullable String attributionTag) { 1505 final int numAttributions = mAttributions.size(); 1506 1507 final ArrayMap<String, AttributedOpEntry> attributionEntries = new ArrayMap<>(1); 1508 for (int i = 0; i < numAttributions; i++) { 1509 if (Objects.equals(mAttributions.keyAt(i), attributionTag)) { 1510 attributionEntries.put(mAttributions.keyAt(i), 1511 mAttributions.valueAt(i).createAttributedOpEntryLocked()); 1512 break; 1513 } 1514 } 1515 1516 return new OpEntry(op, mode, attributionEntries); 1517 } 1518 isRunning()1519 boolean isRunning() { 1520 final int numAttributions = mAttributions.size(); 1521 for (int i = 0; i < numAttributions; i++) { 1522 if (mAttributions.valueAt(i).isRunning()) { 1523 return true; 1524 } 1525 } 1526 1527 return false; 1528 } 1529 } 1530 1531 final SparseArray<ArraySet<ModeCallback>> mOpModeWatchers = new SparseArray<>(); 1532 final ArrayMap<String, ArraySet<ModeCallback>> mPackageModeWatchers = new ArrayMap<>(); 1533 final ArrayMap<IBinder, ModeCallback> mModeWatchers = new ArrayMap<>(); 1534 final ArrayMap<IBinder, SparseArray<ActiveCallback>> mActiveWatchers = new ArrayMap<>(); 1535 final ArrayMap<IBinder, SparseArray<StartedCallback>> mStartedWatchers = new ArrayMap<>(); 1536 final ArrayMap<IBinder, SparseArray<NotedCallback>> mNotedWatchers = new ArrayMap<>(); 1537 final AudioRestrictionManager mAudioRestrictionManager = new AudioRestrictionManager(); 1538 1539 final class ModeCallback implements DeathRecipient { 1540 /** If mWatchedOpCode==ALL_OPS notify for ops affected by the switch-op */ 1541 public static final int ALL_OPS = -2; 1542 1543 final IAppOpsCallback mCallback; 1544 final int mWatchingUid; 1545 final int mFlags; 1546 final int mWatchedOpCode; 1547 final int mCallingUid; 1548 final int mCallingPid; 1549 ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int watchedOp, int callingUid, int callingPid)1550 ModeCallback(IAppOpsCallback callback, int watchingUid, int flags, int watchedOp, 1551 int callingUid, int callingPid) { 1552 mCallback = callback; 1553 mWatchingUid = watchingUid; 1554 mFlags = flags; 1555 mWatchedOpCode = watchedOp; 1556 mCallingUid = callingUid; 1557 mCallingPid = callingPid; 1558 try { 1559 mCallback.asBinder().linkToDeath(this, 0); 1560 } catch (RemoteException e) { 1561 /*ignored*/ 1562 } 1563 } 1564 isWatchingUid(int uid)1565 public boolean isWatchingUid(int uid) { 1566 return uid == UID_ANY || mWatchingUid < 0 || mWatchingUid == uid; 1567 } 1568 1569 @Override toString()1570 public String toString() { 1571 StringBuilder sb = new StringBuilder(128); 1572 sb.append("ModeCallback{"); 1573 sb.append(Integer.toHexString(System.identityHashCode(this))); 1574 sb.append(" watchinguid="); 1575 UserHandle.formatUid(sb, mWatchingUid); 1576 sb.append(" flags=0x"); 1577 sb.append(Integer.toHexString(mFlags)); 1578 switch (mWatchedOpCode) { 1579 case OP_NONE: 1580 break; 1581 case ALL_OPS: 1582 sb.append(" op=(all)"); 1583 break; 1584 default: 1585 sb.append(" op="); 1586 sb.append(opToName(mWatchedOpCode)); 1587 break; 1588 } 1589 sb.append(" from uid="); 1590 UserHandle.formatUid(sb, mCallingUid); 1591 sb.append(" pid="); 1592 sb.append(mCallingPid); 1593 sb.append('}'); 1594 return sb.toString(); 1595 } 1596 unlinkToDeath()1597 void unlinkToDeath() { 1598 mCallback.asBinder().unlinkToDeath(this, 0); 1599 } 1600 1601 @Override binderDied()1602 public void binderDied() { 1603 stopWatchingMode(mCallback); 1604 } 1605 } 1606 1607 final class ActiveCallback implements DeathRecipient { 1608 final IAppOpsActiveCallback mCallback; 1609 final int mWatchingUid; 1610 final int mCallingUid; 1611 final int mCallingPid; 1612 ActiveCallback(IAppOpsActiveCallback callback, int watchingUid, int callingUid, int callingPid)1613 ActiveCallback(IAppOpsActiveCallback callback, int watchingUid, int callingUid, 1614 int callingPid) { 1615 mCallback = callback; 1616 mWatchingUid = watchingUid; 1617 mCallingUid = callingUid; 1618 mCallingPid = callingPid; 1619 try { 1620 mCallback.asBinder().linkToDeath(this, 0); 1621 } catch (RemoteException e) { 1622 /*ignored*/ 1623 } 1624 } 1625 1626 @Override toString()1627 public String toString() { 1628 StringBuilder sb = new StringBuilder(128); 1629 sb.append("ActiveCallback{"); 1630 sb.append(Integer.toHexString(System.identityHashCode(this))); 1631 sb.append(" watchinguid="); 1632 UserHandle.formatUid(sb, mWatchingUid); 1633 sb.append(" from uid="); 1634 UserHandle.formatUid(sb, mCallingUid); 1635 sb.append(" pid="); 1636 sb.append(mCallingPid); 1637 sb.append('}'); 1638 return sb.toString(); 1639 } 1640 destroy()1641 void destroy() { 1642 mCallback.asBinder().unlinkToDeath(this, 0); 1643 } 1644 1645 @Override binderDied()1646 public void binderDied() { 1647 stopWatchingActive(mCallback); 1648 } 1649 } 1650 1651 final class StartedCallback implements DeathRecipient { 1652 final IAppOpsStartedCallback mCallback; 1653 final int mWatchingUid; 1654 final int mCallingUid; 1655 final int mCallingPid; 1656 StartedCallback(IAppOpsStartedCallback callback, int watchingUid, int callingUid, int callingPid)1657 StartedCallback(IAppOpsStartedCallback callback, int watchingUid, int callingUid, 1658 int callingPid) { 1659 mCallback = callback; 1660 mWatchingUid = watchingUid; 1661 mCallingUid = callingUid; 1662 mCallingPid = callingPid; 1663 try { 1664 mCallback.asBinder().linkToDeath(this, 0); 1665 } catch (RemoteException e) { 1666 /*ignored*/ 1667 } 1668 } 1669 1670 @Override toString()1671 public String toString() { 1672 StringBuilder sb = new StringBuilder(128); 1673 sb.append("StartedCallback{"); 1674 sb.append(Integer.toHexString(System.identityHashCode(this))); 1675 sb.append(" watchinguid="); 1676 UserHandle.formatUid(sb, mWatchingUid); 1677 sb.append(" from uid="); 1678 UserHandle.formatUid(sb, mCallingUid); 1679 sb.append(" pid="); 1680 sb.append(mCallingPid); 1681 sb.append('}'); 1682 return sb.toString(); 1683 } 1684 destroy()1685 void destroy() { 1686 mCallback.asBinder().unlinkToDeath(this, 0); 1687 } 1688 1689 @Override binderDied()1690 public void binderDied() { 1691 stopWatchingStarted(mCallback); 1692 } 1693 } 1694 1695 final class NotedCallback implements DeathRecipient { 1696 final IAppOpsNotedCallback mCallback; 1697 final int mWatchingUid; 1698 final int mCallingUid; 1699 final int mCallingPid; 1700 NotedCallback(IAppOpsNotedCallback callback, int watchingUid, int callingUid, int callingPid)1701 NotedCallback(IAppOpsNotedCallback callback, int watchingUid, int callingUid, 1702 int callingPid) { 1703 mCallback = callback; 1704 mWatchingUid = watchingUid; 1705 mCallingUid = callingUid; 1706 mCallingPid = callingPid; 1707 try { 1708 mCallback.asBinder().linkToDeath(this, 0); 1709 } catch (RemoteException e) { 1710 /*ignored*/ 1711 } 1712 } 1713 1714 @Override toString()1715 public String toString() { 1716 StringBuilder sb = new StringBuilder(128); 1717 sb.append("NotedCallback{"); 1718 sb.append(Integer.toHexString(System.identityHashCode(this))); 1719 sb.append(" watchinguid="); 1720 UserHandle.formatUid(sb, mWatchingUid); 1721 sb.append(" from uid="); 1722 UserHandle.formatUid(sb, mCallingUid); 1723 sb.append(" pid="); 1724 sb.append(mCallingPid); 1725 sb.append('}'); 1726 return sb.toString(); 1727 } 1728 destroy()1729 void destroy() { 1730 mCallback.asBinder().unlinkToDeath(this, 0); 1731 } 1732 1733 @Override binderDied()1734 public void binderDied() { 1735 stopWatchingNoted(mCallback); 1736 } 1737 } 1738 1739 /** 1740 * Call {@link AttributedOp#onClientDeath attributedOp.onClientDeath(clientId)}. 1741 */ onClientDeath(@onNull AttributedOp attributedOp, @NonNull IBinder clientId)1742 private static void onClientDeath(@NonNull AttributedOp attributedOp, 1743 @NonNull IBinder clientId) { 1744 attributedOp.onClientDeath(clientId); 1745 } 1746 1747 1748 /** 1749 * Loads the OpsValidation file results into a hashmap {@link #mNoteOpCallerStacktraces} 1750 * so that we do not log the same operation twice between instances 1751 */ readNoteOpCallerStackTraces()1752 private void readNoteOpCallerStackTraces() { 1753 try { 1754 if (!mNoteOpCallerStacktracesFile.exists()) { 1755 mNoteOpCallerStacktracesFile.createNewFile(); 1756 return; 1757 } 1758 1759 try (Scanner read = new Scanner(mNoteOpCallerStacktracesFile)) { 1760 read.useDelimiter("\\},"); 1761 while (read.hasNext()) { 1762 String jsonOps = read.next(); 1763 mNoteOpCallerStacktraces.add(NoteOpTrace.fromJson(jsonOps)); 1764 } 1765 } 1766 } catch (Exception e) { 1767 Slog.e(TAG, "Cannot parse traces noteOps", e); 1768 } 1769 } 1770 AppOpsService(File storagePath, Handler handler, Context context)1771 public AppOpsService(File storagePath, Handler handler, Context context) { 1772 mContext = context; 1773 1774 LockGuard.installLock(this, LockGuard.INDEX_APP_OPS); 1775 mFile = new AtomicFile(storagePath, "appops"); 1776 if (AppOpsManager.NOTE_OP_COLLECTION_ENABLED) { 1777 mNoteOpCallerStacktracesFile = new File(SystemServiceManager.ensureSystemDir(), 1778 "noteOpStackTraces.json"); 1779 readNoteOpCallerStackTraces(); 1780 } else { 1781 mNoteOpCallerStacktracesFile = null; 1782 } 1783 mHandler = handler; 1784 mConstants = new Constants(mHandler); 1785 readState(); 1786 1787 for (int switchedCode = 0; switchedCode < _NUM_OP; switchedCode++) { 1788 int switchCode = AppOpsManager.opToSwitch(switchedCode); 1789 mSwitchedOps.put(switchCode, 1790 ArrayUtils.appendInt(mSwitchedOps.get(switchCode), switchedCode)); 1791 } 1792 } 1793 publish()1794 public void publish() { 1795 ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder()); 1796 LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal); 1797 } 1798 1799 /** Handler for work when packages are removed or updated */ 1800 private BroadcastReceiver mOnPackageUpdatedReceiver = new BroadcastReceiver() { 1801 @Override 1802 public void onReceive(Context context, Intent intent) { 1803 String action = intent.getAction(); 1804 String pkgName = intent.getData().getEncodedSchemeSpecificPart(); 1805 int uid = intent.getIntExtra(Intent.EXTRA_UID, Process.INVALID_UID); 1806 1807 if (action.equals(ACTION_PACKAGE_REMOVED) && !intent.hasExtra(EXTRA_REPLACING)) { 1808 synchronized (AppOpsService.this) { 1809 UidState uidState = mUidStates.get(uid); 1810 if (uidState == null || uidState.pkgOps == null) { 1811 return; 1812 } 1813 1814 Ops removedOps = uidState.pkgOps.remove(pkgName); 1815 if (removedOps != null) { 1816 scheduleFastWriteLocked(); 1817 } 1818 } 1819 } else if (action.equals(Intent.ACTION_PACKAGE_REPLACED)) { 1820 AndroidPackage pkg = getPackageManagerInternal().getPackage(pkgName); 1821 if (pkg == null) { 1822 return; 1823 } 1824 1825 ArrayMap<String, String> dstAttributionTags = new ArrayMap<>(); 1826 ArraySet<String> attributionTags = new ArraySet<>(); 1827 attributionTags.add(null); 1828 if (pkg.getAttributions() != null) { 1829 int numAttributions = pkg.getAttributions().size(); 1830 for (int attributionNum = 0; attributionNum < numAttributions; 1831 attributionNum++) { 1832 ParsedAttribution attribution = pkg.getAttributions().get(attributionNum); 1833 attributionTags.add(attribution.tag); 1834 1835 int numInheritFrom = attribution.inheritFrom.size(); 1836 for (int inheritFromNum = 0; inheritFromNum < numInheritFrom; 1837 inheritFromNum++) { 1838 dstAttributionTags.put(attribution.inheritFrom.get(inheritFromNum), 1839 attribution.tag); 1840 } 1841 } 1842 } 1843 1844 synchronized (AppOpsService.this) { 1845 UidState uidState = mUidStates.get(uid); 1846 if (uidState == null || uidState.pkgOps == null) { 1847 return; 1848 } 1849 1850 Ops ops = uidState.pkgOps.get(pkgName); 1851 if (ops == null) { 1852 return; 1853 } 1854 1855 // Reset cached package properties to re-initialize when needed 1856 ops.bypass = null; 1857 ops.knownAttributionTags.clear(); 1858 1859 // Merge data collected for removed attributions into their successor 1860 // attributions 1861 int numOps = ops.size(); 1862 for (int opNum = 0; opNum < numOps; opNum++) { 1863 Op op = ops.valueAt(opNum); 1864 1865 int numAttributions = op.mAttributions.size(); 1866 for (int attributionNum = numAttributions - 1; attributionNum >= 0; 1867 attributionNum--) { 1868 String attributionTag = op.mAttributions.keyAt(attributionNum); 1869 1870 if (attributionTags.contains(attributionTag)) { 1871 // attribution still exist after upgrade 1872 continue; 1873 } 1874 1875 String newAttributionTag = dstAttributionTags.get(attributionTag); 1876 1877 AttributedOp newAttributedOp = op.getOrCreateAttribution(op, 1878 newAttributionTag); 1879 newAttributedOp.add(op.mAttributions.valueAt(attributionNum)); 1880 op.mAttributions.removeAt(attributionNum); 1881 1882 scheduleFastWriteLocked(); 1883 } 1884 } 1885 } 1886 } 1887 } 1888 }; 1889 systemReady()1890 public void systemReady() { 1891 mConstants.startMonitoring(mContext.getContentResolver()); 1892 mHistoricalRegistry.systemReady(mContext.getContentResolver()); 1893 1894 IntentFilter packageUpdateFilter = new IntentFilter(); 1895 packageUpdateFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 1896 packageUpdateFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); 1897 packageUpdateFilter.addDataScheme("package"); 1898 1899 mContext.registerReceiverAsUser(mOnPackageUpdatedReceiver, UserHandle.ALL, 1900 packageUpdateFilter, null, null); 1901 1902 synchronized (this) { 1903 for (int uidNum = mUidStates.size() - 1; uidNum >= 0; uidNum--) { 1904 int uid = mUidStates.keyAt(uidNum); 1905 UidState uidState = mUidStates.valueAt(uidNum); 1906 1907 String[] pkgsInUid = getPackagesForUid(uidState.uid); 1908 if (ArrayUtils.isEmpty(pkgsInUid)) { 1909 uidState.clear(); 1910 mUidStates.removeAt(uidNum); 1911 scheduleFastWriteLocked(); 1912 continue; 1913 } 1914 1915 ArrayMap<String, Ops> pkgs = uidState.pkgOps; 1916 if (pkgs == null) { 1917 continue; 1918 } 1919 1920 int numPkgs = pkgs.size(); 1921 for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) { 1922 String pkg = pkgs.keyAt(pkgNum); 1923 1924 String action; 1925 if (!ArrayUtils.contains(pkgsInUid, pkg)) { 1926 action = Intent.ACTION_PACKAGE_REMOVED; 1927 } else { 1928 action = Intent.ACTION_PACKAGE_REPLACED; 1929 } 1930 1931 SystemServerInitThreadPool.submit( 1932 () -> mOnPackageUpdatedReceiver.onReceive(mContext, new Intent(action) 1933 .setData(Uri.fromParts("package", pkg, null)) 1934 .putExtra(Intent.EXTRA_UID, uid)), 1935 "Update app-ops uidState in case package " + pkg + " changed"); 1936 } 1937 } 1938 } 1939 1940 final IntentFilter packageSuspendFilter = new IntentFilter(); 1941 packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED); 1942 packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED); 1943 mContext.registerReceiverAsUser(new BroadcastReceiver() { 1944 @Override 1945 public void onReceive(Context context, Intent intent) { 1946 final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST); 1947 final String[] changedPkgs = intent.getStringArrayExtra( 1948 Intent.EXTRA_CHANGED_PACKAGE_LIST); 1949 for (int code : OPS_RESTRICTED_ON_SUSPEND) { 1950 ArraySet<ModeCallback> callbacks; 1951 synchronized (AppOpsService.this) { 1952 callbacks = mOpModeWatchers.get(code); 1953 if (callbacks == null) { 1954 continue; 1955 } 1956 callbacks = new ArraySet<>(callbacks); 1957 } 1958 for (int i = 0; i < changedUids.length; i++) { 1959 final int changedUid = changedUids[i]; 1960 final String changedPkg = changedPkgs[i]; 1961 // We trust packagemanager to insert matching uid and packageNames in the 1962 // extras 1963 notifyOpChanged(callbacks, code, changedUid, changedPkg); 1964 } 1965 } 1966 } 1967 }, UserHandle.ALL, packageSuspendFilter, null, null); 1968 1969 final IntentFilter packageAddedFilter = new IntentFilter(); 1970 packageAddedFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 1971 packageAddedFilter.addDataScheme("package"); 1972 mContext.registerReceiver(new BroadcastReceiver() { 1973 @Override 1974 public void onReceive(Context context, Intent intent) { 1975 final Uri data = intent.getData(); 1976 1977 final String packageName = data.getSchemeSpecificPart(); 1978 PackageInfo pi = getPackageManagerInternal().getPackageInfo(packageName, 1979 PackageManager.GET_PERMISSIONS, Process.myUid(), mContext.getUserId()); 1980 if (isSamplingTarget(pi)) { 1981 synchronized (this) { 1982 mRarelyUsedPackages.add(packageName); 1983 } 1984 } 1985 } 1986 }, packageAddedFilter); 1987 1988 mHandler.postDelayed(new Runnable() { 1989 @Override 1990 public void run() { 1991 List<String> packageNames = getPackageListAndResample(); 1992 initializeRarelyUsedPackagesList(new ArraySet<>(packageNames)); 1993 } 1994 }, RARELY_USED_PACKAGES_INITIALIZATION_DELAY_MILLIS); 1995 1996 getPackageManagerInternal().setExternalSourcesPolicy( 1997 new PackageManagerInternal.ExternalSourcesPolicy() { 1998 @Override 1999 public int getPackageTrustedToInstallApps(String packageName, int uid) { 2000 int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, 2001 uid, packageName); 2002 switch (appOpMode) { 2003 case AppOpsManager.MODE_ALLOWED: 2004 return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED; 2005 case AppOpsManager.MODE_ERRORED: 2006 return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED; 2007 default: 2008 return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT; 2009 } 2010 } 2011 }); 2012 2013 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); 2014 } 2015 2016 /** 2017 * Sets a policy for handling app ops. 2018 * 2019 * @param policy The policy. 2020 */ setAppOpsPolicy(@ullable CheckOpsDelegate policy)2021 public void setAppOpsPolicy(@Nullable CheckOpsDelegate policy) { 2022 final CheckOpsDelegateDispatcher oldDispatcher = mCheckOpsDelegateDispatcher; 2023 final CheckOpsDelegate delegate = (oldDispatcher != null) 2024 ? oldDispatcher.mCheckOpsDelegate : null; 2025 mCheckOpsDelegateDispatcher = new CheckOpsDelegateDispatcher(policy, delegate); 2026 } 2027 packageRemoved(int uid, String packageName)2028 public void packageRemoved(int uid, String packageName) { 2029 synchronized (this) { 2030 UidState uidState = mUidStates.get(uid); 2031 if (uidState == null) { 2032 return; 2033 } 2034 2035 Ops ops = null; 2036 2037 // Remove any package state if such. 2038 if (uidState.pkgOps != null) { 2039 ops = uidState.pkgOps.remove(packageName); 2040 } 2041 2042 // If we just nuked the last package state check if the UID is valid. 2043 if (ops != null && uidState.pkgOps.isEmpty() 2044 && getPackagesForUid(uid).length <= 0) { 2045 mUidStates.remove(uid); 2046 } 2047 2048 if (ops != null) { 2049 scheduleFastWriteLocked(); 2050 2051 final int numOps = ops.size(); 2052 for (int opNum = 0; opNum < numOps; opNum++) { 2053 final Op op = ops.valueAt(opNum); 2054 2055 final int numAttributions = op.mAttributions.size(); 2056 for (int attributionNum = 0; attributionNum < numAttributions; 2057 attributionNum++) { 2058 AttributedOp attributedOp = op.mAttributions.valueAt(attributionNum); 2059 2060 while (attributedOp.isRunning()) { 2061 attributedOp.finished(attributedOp.mInProgressEvents.keyAt(0)); 2062 } 2063 while (attributedOp.isPaused()) { 2064 attributedOp.finished(attributedOp.mPausedInProgressEvents.keyAt(0)); 2065 } 2066 } 2067 } 2068 } 2069 } 2070 2071 mHandler.post(PooledLambda.obtainRunnable(HistoricalRegistry::clearHistory, 2072 mHistoricalRegistry, uid, packageName)); 2073 } 2074 uidRemoved(int uid)2075 public void uidRemoved(int uid) { 2076 synchronized (this) { 2077 if (mUidStates.indexOfKey(uid) >= 0) { 2078 mUidStates.remove(uid); 2079 scheduleFastWriteLocked(); 2080 } 2081 } 2082 } 2083 2084 /** 2085 * Update the pending state for the uid 2086 * 2087 * @param currentTime The current elapsed real time 2088 * @param uid The uid that has a pending state 2089 */ updatePendingState(long currentTime, int uid)2090 private void updatePendingState(long currentTime, int uid) { 2091 synchronized (this) { 2092 mLastRealtime = max(currentTime, mLastRealtime); 2093 updatePendingStateIfNeededLocked(mUidStates.get(uid)); 2094 } 2095 } 2096 updateUidProcState(int uid, int procState, @ActivityManager.ProcessCapability int capability)2097 public void updateUidProcState(int uid, int procState, 2098 @ActivityManager.ProcessCapability int capability) { 2099 synchronized (this) { 2100 final UidState uidState = getUidStateLocked(uid, true); 2101 final int newState = PROCESS_STATE_TO_UID_STATE[procState]; 2102 if (uidState != null && (uidState.pendingState != newState 2103 || uidState.pendingCapability != capability)) { 2104 final int oldPendingState = uidState.pendingState; 2105 uidState.pendingState = newState; 2106 uidState.pendingCapability = capability; 2107 if (newState < uidState.state 2108 || (newState <= UID_STATE_MAX_LAST_NON_RESTRICTED 2109 && uidState.state > UID_STATE_MAX_LAST_NON_RESTRICTED)) { 2110 // We are moving to a more important state, or the new state may be in the 2111 // foreground and the old state is in the background, then always do it 2112 // immediately. 2113 commitUidPendingStateLocked(uidState); 2114 } else if (newState == uidState.state && capability != uidState.capability) { 2115 // No change on process state, but process capability has changed. 2116 commitUidPendingStateLocked(uidState); 2117 } else if (uidState.pendingStateCommitTime == 0) { 2118 // We are moving to a less important state for the first time, 2119 // delay the application for a bit. 2120 final long settleTime; 2121 if (uidState.state <= UID_STATE_TOP) { 2122 settleTime = mConstants.TOP_STATE_SETTLE_TIME; 2123 } else if (uidState.state <= UID_STATE_FOREGROUND_SERVICE) { 2124 settleTime = mConstants.FG_SERVICE_STATE_SETTLE_TIME; 2125 } else { 2126 settleTime = mConstants.BG_STATE_SETTLE_TIME; 2127 } 2128 final long commitTime = SystemClock.elapsedRealtime() + settleTime; 2129 uidState.pendingStateCommitTime = commitTime; 2130 2131 mHandler.sendMessageDelayed( 2132 PooledLambda.obtainMessage(AppOpsService::updatePendingState, this, 2133 commitTime + 1, uid), settleTime + 1); 2134 } 2135 2136 if (uidState.pkgOps != null) { 2137 int numPkgs = uidState.pkgOps.size(); 2138 for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) { 2139 Ops ops = uidState.pkgOps.valueAt(pkgNum); 2140 2141 int numOps = ops.size(); 2142 for (int opNum = 0; opNum < numOps; opNum++) { 2143 Op op = ops.valueAt(opNum); 2144 2145 int numAttributions = op.mAttributions.size(); 2146 for (int attributionNum = 0; attributionNum < numAttributions; 2147 attributionNum++) { 2148 AttributedOp attributedOp = op.mAttributions.valueAt( 2149 attributionNum); 2150 2151 attributedOp.onUidStateChanged(newState); 2152 } 2153 } 2154 } 2155 } 2156 } 2157 } 2158 } 2159 shutdown()2160 public void shutdown() { 2161 Slog.w(TAG, "Writing app ops before shutdown..."); 2162 boolean doWrite = false; 2163 synchronized (this) { 2164 if (mWriteScheduled) { 2165 mWriteScheduled = false; 2166 mFastWriteScheduled = false; 2167 mHandler.removeCallbacks(mWriteRunner); 2168 doWrite = true; 2169 } 2170 } 2171 if (doWrite) { 2172 writeState(); 2173 } 2174 if (AppOpsManager.NOTE_OP_COLLECTION_ENABLED && mWriteNoteOpsScheduled) { 2175 writeNoteOps(); 2176 } 2177 2178 mHistoricalRegistry.shutdown(); 2179 } 2180 collectOps(Ops pkgOps, int[] ops)2181 private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) { 2182 ArrayList<AppOpsManager.OpEntry> resOps = null; 2183 final long elapsedNow = SystemClock.elapsedRealtime(); 2184 if (ops == null) { 2185 resOps = new ArrayList<>(); 2186 for (int j=0; j<pkgOps.size(); j++) { 2187 Op curOp = pkgOps.valueAt(j); 2188 resOps.add(getOpEntryForResult(curOp, elapsedNow)); 2189 } 2190 } else { 2191 for (int j=0; j<ops.length; j++) { 2192 Op curOp = pkgOps.get(ops[j]); 2193 if (curOp != null) { 2194 if (resOps == null) { 2195 resOps = new ArrayList<>(); 2196 } 2197 resOps.add(getOpEntryForResult(curOp, elapsedNow)); 2198 } 2199 } 2200 } 2201 return resOps; 2202 } 2203 2204 @Nullable collectUidOps(@onNull UidState uidState, @Nullable int[] ops)2205 private ArrayList<AppOpsManager.OpEntry> collectUidOps(@NonNull UidState uidState, 2206 @Nullable int[] ops) { 2207 if (uidState.opModes == null) { 2208 return null; 2209 } 2210 2211 int opModeCount = uidState.opModes.size(); 2212 if (opModeCount == 0) { 2213 return null; 2214 } 2215 ArrayList<AppOpsManager.OpEntry> resOps = null; 2216 if (ops == null) { 2217 resOps = new ArrayList<>(); 2218 for (int i = 0; i < opModeCount; i++) { 2219 int code = uidState.opModes.keyAt(i); 2220 resOps.add(new OpEntry(code, uidState.opModes.get(code), Collections.emptyMap())); 2221 } 2222 } else { 2223 for (int j=0; j<ops.length; j++) { 2224 int code = ops[j]; 2225 if (uidState.opModes.indexOfKey(code) >= 0) { 2226 if (resOps == null) { 2227 resOps = new ArrayList<>(); 2228 } 2229 resOps.add(new OpEntry(code, uidState.opModes.get(code), 2230 Collections.emptyMap())); 2231 } 2232 } 2233 } 2234 return resOps; 2235 } 2236 getOpEntryForResult(@onNull Op op, long elapsedNow)2237 private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, long elapsedNow) { 2238 return op.createEntryLocked(); 2239 } 2240 2241 @Override getPackagesForOps(int[] ops)2242 public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { 2243 final int callingUid = Binder.getCallingUid(); 2244 final boolean hasAllPackageAccess = mContext.checkPermission( 2245 Manifest.permission.GET_APP_OPS_STATS, Binder.getCallingPid(), 2246 Binder.getCallingUid(), null) == PackageManager.PERMISSION_GRANTED; 2247 ArrayList<AppOpsManager.PackageOps> res = null; 2248 synchronized (this) { 2249 final int uidStateCount = mUidStates.size(); 2250 for (int i = 0; i < uidStateCount; i++) { 2251 UidState uidState = mUidStates.valueAt(i); 2252 if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()) { 2253 continue; 2254 } 2255 ArrayMap<String, Ops> packages = uidState.pkgOps; 2256 final int packageCount = packages.size(); 2257 for (int j = 0; j < packageCount; j++) { 2258 Ops pkgOps = packages.valueAt(j); 2259 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 2260 if (resOps != null) { 2261 if (res == null) { 2262 res = new ArrayList<>(); 2263 } 2264 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 2265 pkgOps.packageName, pkgOps.uidState.uid, resOps); 2266 // Caller can always see their packages and with a permission all. 2267 if (hasAllPackageAccess || callingUid == pkgOps.uidState.uid) { 2268 res.add(resPackage); 2269 } 2270 } 2271 } 2272 } 2273 } 2274 return res; 2275 } 2276 2277 @Override getOpsForPackage(int uid, String packageName, int[] ops)2278 public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, 2279 int[] ops) { 2280 enforceGetAppOpsStatsPermissionIfNeeded(uid,packageName); 2281 String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); 2282 if (resolvedPackageName == null) { 2283 return Collections.emptyList(); 2284 } 2285 synchronized (this) { 2286 Ops pkgOps = getOpsLocked(uid, resolvedPackageName, null, false, null, 2287 /* edit */ false); 2288 if (pkgOps == null) { 2289 return null; 2290 } 2291 ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 2292 if (resOps == null) { 2293 return null; 2294 } 2295 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); 2296 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 2297 pkgOps.packageName, pkgOps.uidState.uid, resOps); 2298 res.add(resPackage); 2299 return res; 2300 } 2301 } 2302 enforceGetAppOpsStatsPermissionIfNeeded(int uid, String packageName)2303 private void enforceGetAppOpsStatsPermissionIfNeeded(int uid, String packageName) { 2304 final int callingUid = Binder.getCallingUid(); 2305 // We get to access everything 2306 if (callingUid == Process.myPid()) { 2307 return; 2308 } 2309 // Apps can access their own data 2310 if (uid == callingUid && packageName != null 2311 && checkPackage(uid, packageName) == MODE_ALLOWED) { 2312 return; 2313 } 2314 // Otherwise, you need a permission... 2315 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 2316 Binder.getCallingPid(), callingUid, null); 2317 } 2318 2319 /** 2320 * Verify that historical appop request arguments are valid. 2321 */ ensureHistoricalOpRequestIsValid(int uid, String packageName, String attributionTag, List<String> opNames, int filter, long beginTimeMillis, long endTimeMillis, int flags)2322 private void ensureHistoricalOpRequestIsValid(int uid, String packageName, 2323 String attributionTag, List<String> opNames, int filter, long beginTimeMillis, 2324 long endTimeMillis, int flags) { 2325 if ((filter & FILTER_BY_UID) != 0) { 2326 Preconditions.checkArgument(uid != Process.INVALID_UID); 2327 } else { 2328 Preconditions.checkArgument(uid == Process.INVALID_UID); 2329 } 2330 2331 if ((filter & FILTER_BY_PACKAGE_NAME) != 0) { 2332 Objects.requireNonNull(packageName); 2333 } else { 2334 Preconditions.checkArgument(packageName == null); 2335 } 2336 2337 if ((filter & FILTER_BY_ATTRIBUTION_TAG) == 0) { 2338 Preconditions.checkArgument(attributionTag == null); 2339 } 2340 2341 if ((filter & FILTER_BY_OP_NAMES) != 0) { 2342 Objects.requireNonNull(opNames); 2343 } else { 2344 Preconditions.checkArgument(opNames == null); 2345 } 2346 2347 Preconditions.checkFlagsArgument(filter, 2348 FILTER_BY_UID | FILTER_BY_PACKAGE_NAME | FILTER_BY_ATTRIBUTION_TAG 2349 | FILTER_BY_OP_NAMES); 2350 Preconditions.checkArgumentNonnegative(beginTimeMillis); 2351 Preconditions.checkArgument(endTimeMillis > beginTimeMillis); 2352 Preconditions.checkFlagsArgument(flags, OP_FLAGS_ALL); 2353 } 2354 2355 @Override getHistoricalOps(int uid, String packageName, String attributionTag, List<String> opNames, int dataType, int filter, long beginTimeMillis, long endTimeMillis, int flags, RemoteCallback callback)2356 public void getHistoricalOps(int uid, String packageName, String attributionTag, 2357 List<String> opNames, int dataType, int filter, long beginTimeMillis, 2358 long endTimeMillis, int flags, RemoteCallback callback) { 2359 PackageManager pm = mContext.getPackageManager(); 2360 2361 ensureHistoricalOpRequestIsValid(uid, packageName, attributionTag, opNames, filter, 2362 beginTimeMillis, endTimeMillis, flags); 2363 Objects.requireNonNull(callback, "callback cannot be null"); 2364 ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class); 2365 boolean isSelfRequest = (filter & FILTER_BY_UID) != 0 && uid == Binder.getCallingUid(); 2366 if (!isSelfRequest) { 2367 boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(Binder.getCallingUid()); 2368 boolean isCallerSystem = Binder.getCallingPid() == Process.myPid(); 2369 boolean isCallerPermissionController; 2370 try { 2371 isCallerPermissionController = pm.getPackageUidAsUser( 2372 mContext.getPackageManager().getPermissionControllerPackageName(), 0, 2373 UserHandle.getUserId(Binder.getCallingUid())) 2374 == Binder.getCallingUid(); 2375 } catch (PackageManager.NameNotFoundException doesNotHappen) { 2376 return; 2377 } 2378 2379 if (!isCallerSystem && !isCallerInstrumented && !isCallerPermissionController) { 2380 mHandler.post(() -> callback.sendResult(new Bundle())); 2381 return; 2382 } 2383 2384 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 2385 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); 2386 } 2387 2388 final String[] opNamesArray = (opNames != null) 2389 ? opNames.toArray(new String[opNames.size()]) : null; 2390 2391 Set<String> attributionChainExemptPackages = null; 2392 if ((dataType & HISTORY_FLAG_GET_ATTRIBUTION_CHAINS) != 0) { 2393 attributionChainExemptPackages = 2394 PermissionManager.getIndicatorExemptedPackages(mContext); 2395 } 2396 2397 final String[] chainExemptPkgArray = attributionChainExemptPackages != null 2398 ? attributionChainExemptPackages.toArray( 2399 new String[attributionChainExemptPackages.size()]) : null; 2400 2401 // Must not hold the appops lock 2402 mHandler.post(PooledLambda.obtainRunnable(HistoricalRegistry::getHistoricalOps, 2403 mHistoricalRegistry, uid, packageName, attributionTag, opNamesArray, dataType, 2404 filter, beginTimeMillis, endTimeMillis, flags, chainExemptPkgArray, 2405 callback).recycleOnUse()); 2406 } 2407 2408 @Override getHistoricalOpsFromDiskRaw(int uid, String packageName, String attributionTag, List<String> opNames, int dataType, int filter, long beginTimeMillis, long endTimeMillis, int flags, RemoteCallback callback)2409 public void getHistoricalOpsFromDiskRaw(int uid, String packageName, String attributionTag, 2410 List<String> opNames, int dataType, int filter, long beginTimeMillis, 2411 long endTimeMillis, int flags, RemoteCallback callback) { 2412 ensureHistoricalOpRequestIsValid(uid, packageName, attributionTag, opNames, filter, 2413 beginTimeMillis, endTimeMillis, flags); 2414 Objects.requireNonNull(callback, "callback cannot be null"); 2415 2416 mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS, 2417 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); 2418 2419 final String[] opNamesArray = (opNames != null) 2420 ? opNames.toArray(new String[opNames.size()]) : null; 2421 2422 Set<String> attributionChainExemptPackages = null; 2423 if ((dataType & HISTORY_FLAG_GET_ATTRIBUTION_CHAINS) != 0) { 2424 attributionChainExemptPackages = 2425 PermissionManager.getIndicatorExemptedPackages(mContext); 2426 } 2427 2428 final String[] chainExemptPkgArray = attributionChainExemptPackages != null 2429 ? attributionChainExemptPackages.toArray( 2430 new String[attributionChainExemptPackages.size()]) : null; 2431 2432 // Must not hold the appops lock 2433 mHandler.post(PooledLambda.obtainRunnable(HistoricalRegistry::getHistoricalOpsFromDiskRaw, 2434 mHistoricalRegistry, uid, packageName, attributionTag, opNamesArray, dataType, 2435 filter, beginTimeMillis, endTimeMillis, flags, chainExemptPkgArray, 2436 callback).recycleOnUse()); 2437 } 2438 2439 @Override reloadNonHistoricalState()2440 public void reloadNonHistoricalState() { 2441 mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS, 2442 Binder.getCallingPid(), Binder.getCallingUid(), "reloadNonHistoricalState"); 2443 writeState(); 2444 readState(); 2445 } 2446 2447 @Override getUidOps(int uid, int[] ops)2448 public List<AppOpsManager.PackageOps> getUidOps(int uid, int[] ops) { 2449 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 2450 Binder.getCallingPid(), Binder.getCallingUid(), null); 2451 synchronized (this) { 2452 UidState uidState = getUidStateLocked(uid, false); 2453 if (uidState == null) { 2454 return null; 2455 } 2456 ArrayList<AppOpsManager.OpEntry> resOps = collectUidOps(uidState, ops); 2457 if (resOps == null) { 2458 return null; 2459 } 2460 ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); 2461 AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 2462 null, uidState.uid, resOps); 2463 res.add(resPackage); 2464 return res; 2465 } 2466 } 2467 pruneOpLocked(Op op, int uid, String packageName)2468 private void pruneOpLocked(Op op, int uid, String packageName) { 2469 op.removeAttributionsWithNoTime(); 2470 2471 if (op.mAttributions.isEmpty()) { 2472 Ops ops = getOpsLocked(uid, packageName, null, false, null, /* edit */ false); 2473 if (ops != null) { 2474 ops.remove(op.op); 2475 if (ops.size() <= 0) { 2476 UidState uidState = ops.uidState; 2477 ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 2478 if (pkgOps != null) { 2479 pkgOps.remove(ops.packageName); 2480 if (pkgOps.isEmpty()) { 2481 uidState.pkgOps = null; 2482 } 2483 if (uidState.isDefault()) { 2484 mUidStates.remove(uid); 2485 } 2486 } 2487 } 2488 } 2489 } 2490 } 2491 enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid)2492 private void enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid) { 2493 if (callingPid == Process.myPid()) { 2494 return; 2495 } 2496 final int callingUser = UserHandle.getUserId(callingUid); 2497 synchronized (this) { 2498 if (mProfileOwners != null && mProfileOwners.get(callingUser, -1) == callingUid) { 2499 if (targetUid >= 0 && callingUser == UserHandle.getUserId(targetUid)) { 2500 // Profile owners are allowed to change modes but only for apps 2501 // within their user. 2502 return; 2503 } 2504 } 2505 } 2506 mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES, 2507 Binder.getCallingPid(), Binder.getCallingUid(), null); 2508 } 2509 2510 @Override setUidMode(int code, int uid, int mode)2511 public void setUidMode(int code, int uid, int mode) { 2512 setUidMode(code, uid, mode, null); 2513 } 2514 setUidMode(int code, int uid, int mode, @Nullable IAppOpsCallback permissionPolicyCallback)2515 private void setUidMode(int code, int uid, int mode, 2516 @Nullable IAppOpsCallback permissionPolicyCallback) { 2517 if (DEBUG) { 2518 Slog.i(TAG, "uid " + uid + " OP_" + opToName(code) + " := " + modeToName(mode) 2519 + " by uid " + Binder.getCallingUid()); 2520 } 2521 2522 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); 2523 verifyIncomingOp(code); 2524 code = AppOpsManager.opToSwitch(code); 2525 2526 if (permissionPolicyCallback == null) { 2527 updatePermissionRevokedCompat(uid, code, mode); 2528 } 2529 2530 int previousMode; 2531 synchronized (this) { 2532 final int defaultMode = AppOpsManager.opToDefaultMode(code); 2533 2534 UidState uidState = getUidStateLocked(uid, false); 2535 if (uidState == null) { 2536 if (mode == defaultMode) { 2537 return; 2538 } 2539 previousMode = MODE_DEFAULT; 2540 uidState = new UidState(uid); 2541 uidState.opModes = new SparseIntArray(); 2542 uidState.opModes.put(code, mode); 2543 mUidStates.put(uid, uidState); 2544 scheduleWriteLocked(); 2545 } else if (uidState.opModes == null) { 2546 previousMode = MODE_DEFAULT; 2547 if (mode != defaultMode) { 2548 uidState.opModes = new SparseIntArray(); 2549 uidState.opModes.put(code, mode); 2550 scheduleWriteLocked(); 2551 } 2552 } else { 2553 if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) { 2554 return; 2555 } 2556 previousMode = uidState.opModes.get(code); 2557 if (mode == defaultMode) { 2558 uidState.opModes.delete(code); 2559 if (uidState.opModes.size() <= 0) { 2560 uidState.opModes = null; 2561 } 2562 } else { 2563 uidState.opModes.put(code, mode); 2564 } 2565 scheduleWriteLocked(); 2566 } 2567 uidState.evalForegroundOps(mOpModeWatchers); 2568 if (mode != MODE_ERRORED && mode != previousMode) { 2569 updateStartedOpModeForUidLocked(code, mode == MODE_IGNORED, uid); 2570 } 2571 } 2572 2573 notifyOpChangedForAllPkgsInUid(code, uid, false, permissionPolicyCallback); 2574 notifyOpChangedSync(code, uid, null, mode, previousMode); 2575 } 2576 2577 /** 2578 * Notify that an op changed for all packages in an uid. 2579 * 2580 * @param code The op that changed 2581 * @param uid The uid the op was changed for 2582 * @param onlyForeground Only notify watchers that watch for foreground changes 2583 */ notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground, @Nullable IAppOpsCallback callbackToIgnore)2584 private void notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground, 2585 @Nullable IAppOpsCallback callbackToIgnore) { 2586 String[] uidPackageNames = getPackagesForUid(uid); 2587 ArrayMap<ModeCallback, ArraySet<String>> callbackSpecs = null; 2588 2589 synchronized (this) { 2590 ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code); 2591 if (callbacks != null) { 2592 final int callbackCount = callbacks.size(); 2593 for (int i = 0; i < callbackCount; i++) { 2594 ModeCallback callback = callbacks.valueAt(i); 2595 if (onlyForeground && (callback.mFlags & WATCH_FOREGROUND_CHANGES) == 0) { 2596 continue; 2597 } 2598 2599 ArraySet<String> changedPackages = new ArraySet<>(); 2600 Collections.addAll(changedPackages, uidPackageNames); 2601 if (callbackSpecs == null) { 2602 callbackSpecs = new ArrayMap<>(); 2603 } 2604 callbackSpecs.put(callback, changedPackages); 2605 } 2606 } 2607 2608 for (String uidPackageName : uidPackageNames) { 2609 callbacks = mPackageModeWatchers.get(uidPackageName); 2610 if (callbacks != null) { 2611 if (callbackSpecs == null) { 2612 callbackSpecs = new ArrayMap<>(); 2613 } 2614 final int callbackCount = callbacks.size(); 2615 for (int i = 0; i < callbackCount; i++) { 2616 ModeCallback callback = callbacks.valueAt(i); 2617 if (onlyForeground && (callback.mFlags & WATCH_FOREGROUND_CHANGES) == 0) { 2618 continue; 2619 } 2620 2621 ArraySet<String> changedPackages = callbackSpecs.get(callback); 2622 if (changedPackages == null) { 2623 changedPackages = new ArraySet<>(); 2624 callbackSpecs.put(callback, changedPackages); 2625 } 2626 changedPackages.add(uidPackageName); 2627 } 2628 } 2629 } 2630 2631 if (callbackSpecs != null && callbackToIgnore != null) { 2632 callbackSpecs.remove(mModeWatchers.get(callbackToIgnore.asBinder())); 2633 } 2634 } 2635 2636 if (callbackSpecs == null) { 2637 return; 2638 } 2639 2640 for (int i = 0; i < callbackSpecs.size(); i++) { 2641 final ModeCallback callback = callbackSpecs.keyAt(i); 2642 final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i); 2643 if (reportedPackageNames == null) { 2644 mHandler.sendMessage(PooledLambda.obtainMessage( 2645 AppOpsService::notifyOpChanged, 2646 this, callback, code, uid, (String) null)); 2647 2648 } else { 2649 final int reportedPackageCount = reportedPackageNames.size(); 2650 for (int j = 0; j < reportedPackageCount; j++) { 2651 final String reportedPackageName = reportedPackageNames.valueAt(j); 2652 mHandler.sendMessage(PooledLambda.obtainMessage( 2653 AppOpsService::notifyOpChanged, 2654 this, callback, code, uid, reportedPackageName)); 2655 } 2656 } 2657 } 2658 } 2659 updatePermissionRevokedCompat(int uid, int switchCode, int mode)2660 private void updatePermissionRevokedCompat(int uid, int switchCode, int mode) { 2661 PackageManager packageManager = mContext.getPackageManager(); 2662 if (packageManager == null) { 2663 // This can only happen during early boot. At this time the permission state and appop 2664 // state are in sync 2665 return; 2666 } 2667 2668 String[] packageNames = packageManager.getPackagesForUid(uid); 2669 if (ArrayUtils.isEmpty(packageNames)) { 2670 return; 2671 } 2672 String packageName = packageNames[0]; 2673 2674 int[] ops = mSwitchedOps.get(switchCode); 2675 for (int code : ops) { 2676 String permissionName = AppOpsManager.opToPermission(code); 2677 if (permissionName == null) { 2678 continue; 2679 } 2680 2681 if (packageManager.checkPermission(permissionName, packageName) 2682 != PackageManager.PERMISSION_GRANTED) { 2683 continue; 2684 } 2685 2686 PermissionInfo permissionInfo; 2687 try { 2688 permissionInfo = packageManager.getPermissionInfo(permissionName, 0); 2689 } catch (PackageManager.NameNotFoundException e) { 2690 e.printStackTrace(); 2691 continue; 2692 } 2693 2694 if (!permissionInfo.isRuntime()) { 2695 continue; 2696 } 2697 2698 boolean supportsRuntimePermissions = getPackageManagerInternal() 2699 .getUidTargetSdkVersion(uid) >= Build.VERSION_CODES.M; 2700 2701 UserHandle user = UserHandle.getUserHandleForUid(uid); 2702 boolean isRevokedCompat; 2703 if (permissionInfo.backgroundPermission != null) { 2704 if (packageManager.checkPermission(permissionInfo.backgroundPermission, packageName) 2705 == PackageManager.PERMISSION_GRANTED) { 2706 boolean isBackgroundRevokedCompat = mode != AppOpsManager.MODE_ALLOWED; 2707 2708 if (isBackgroundRevokedCompat && supportsRuntimePermissions) { 2709 Slog.w(TAG, "setUidMode() called with a mode inconsistent with runtime" 2710 + " permission state, this is discouraged and you should revoke the" 2711 + " runtime permission instead: uid=" + uid + ", switchCode=" 2712 + switchCode + ", mode=" + mode + ", permission=" 2713 + permissionInfo.backgroundPermission); 2714 } 2715 2716 final long identity = Binder.clearCallingIdentity(); 2717 try { 2718 packageManager.updatePermissionFlags(permissionInfo.backgroundPermission, 2719 packageName, PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, 2720 isBackgroundRevokedCompat 2721 ? PackageManager.FLAG_PERMISSION_REVOKED_COMPAT : 0, user); 2722 } finally { 2723 Binder.restoreCallingIdentity(identity); 2724 } 2725 } 2726 2727 isRevokedCompat = mode != AppOpsManager.MODE_ALLOWED 2728 && mode != AppOpsManager.MODE_FOREGROUND; 2729 } else { 2730 isRevokedCompat = mode != AppOpsManager.MODE_ALLOWED; 2731 } 2732 2733 if (isRevokedCompat && supportsRuntimePermissions) { 2734 Slog.w(TAG, "setUidMode() called with a mode inconsistent with runtime" 2735 + " permission state, this is discouraged and you should revoke the" 2736 + " runtime permission instead: uid=" + uid + ", switchCode=" 2737 + switchCode + ", mode=" + mode + ", permission=" + permissionName); 2738 } 2739 2740 final long identity = Binder.clearCallingIdentity(); 2741 try { 2742 packageManager.updatePermissionFlags(permissionName, packageName, 2743 PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, isRevokedCompat 2744 ? PackageManager.FLAG_PERMISSION_REVOKED_COMPAT : 0, user); 2745 } finally { 2746 Binder.restoreCallingIdentity(identity); 2747 } 2748 } 2749 } 2750 notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode, int previousMode)2751 private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode, 2752 int previousMode) { 2753 final StorageManagerInternal storageManagerInternal = 2754 LocalServices.getService(StorageManagerInternal.class); 2755 if (storageManagerInternal != null) { 2756 storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode, previousMode); 2757 } 2758 } 2759 2760 /** 2761 * Sets the mode for a certain op and uid. 2762 * 2763 * @param code The op code to set 2764 * @param uid The UID for which to set 2765 * @param packageName The package for which to set 2766 * @param mode The new mode to set 2767 */ 2768 @Override setMode(int code, int uid, @NonNull String packageName, int mode)2769 public void setMode(int code, int uid, @NonNull String packageName, int mode) { 2770 setMode(code, uid, packageName, mode, null); 2771 } 2772 setMode(int code, int uid, @NonNull String packageName, int mode, @Nullable IAppOpsCallback permissionPolicyCallback)2773 private void setMode(int code, int uid, @NonNull String packageName, int mode, 2774 @Nullable IAppOpsCallback permissionPolicyCallback) { 2775 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); 2776 verifyIncomingOp(code); 2777 verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); 2778 2779 ArraySet<ModeCallback> repCbs = null; 2780 code = AppOpsManager.opToSwitch(code); 2781 2782 PackageVerificationResult pvr; 2783 try { 2784 pvr = verifyAndGetBypass(uid, packageName, null); 2785 } catch (SecurityException e) { 2786 Slog.e(TAG, "Cannot setMode", e); 2787 return; 2788 } 2789 2790 int previousMode = MODE_DEFAULT; 2791 synchronized (this) { 2792 UidState uidState = getUidStateLocked(uid, false); 2793 Op op = getOpLocked(code, uid, packageName, null, false, pvr.bypass, /* edit */ true); 2794 if (op != null) { 2795 if (op.mode != mode) { 2796 previousMode = op.mode; 2797 op.mode = mode; 2798 if (uidState != null) { 2799 uidState.evalForegroundOps(mOpModeWatchers); 2800 } 2801 ArraySet<ModeCallback> cbs = mOpModeWatchers.get(code); 2802 if (cbs != null) { 2803 if (repCbs == null) { 2804 repCbs = new ArraySet<>(); 2805 } 2806 repCbs.addAll(cbs); 2807 } 2808 cbs = mPackageModeWatchers.get(packageName); 2809 if (cbs != null) { 2810 if (repCbs == null) { 2811 repCbs = new ArraySet<>(); 2812 } 2813 repCbs.addAll(cbs); 2814 } 2815 if (repCbs != null && permissionPolicyCallback != null) { 2816 repCbs.remove(mModeWatchers.get(permissionPolicyCallback.asBinder())); 2817 } 2818 if (mode == AppOpsManager.opToDefaultMode(op.op)) { 2819 // If going into the default mode, prune this op 2820 // if there is nothing else interesting in it. 2821 pruneOpLocked(op, uid, packageName); 2822 } 2823 scheduleFastWriteLocked(); 2824 if (mode != MODE_ERRORED) { 2825 updateStartedOpModeForUidLocked(code, mode == MODE_IGNORED, uid); 2826 } 2827 } 2828 } 2829 } 2830 if (repCbs != null) { 2831 mHandler.sendMessage(PooledLambda.obtainMessage( 2832 AppOpsService::notifyOpChanged, 2833 this, repCbs, code, uid, packageName)); 2834 } 2835 2836 notifyOpChangedSync(code, uid, packageName, mode, previousMode); 2837 } 2838 notifyOpChanged(ArraySet<ModeCallback> callbacks, int code, int uid, String packageName)2839 private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code, 2840 int uid, String packageName) { 2841 for (int i = 0; i < callbacks.size(); i++) { 2842 final ModeCallback callback = callbacks.valueAt(i); 2843 notifyOpChanged(callback, code, uid, packageName); 2844 } 2845 } 2846 notifyOpChanged(ModeCallback callback, int code, int uid, String packageName)2847 private void notifyOpChanged(ModeCallback callback, int code, 2848 int uid, String packageName) { 2849 if (uid != UID_ANY && callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 2850 return; 2851 } 2852 2853 // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE 2854 int[] switchedCodes; 2855 if (callback.mWatchedOpCode == ALL_OPS) { 2856 switchedCodes = mSwitchedOps.get(code); 2857 } else if (callback.mWatchedOpCode == OP_NONE) { 2858 switchedCodes = new int[]{code}; 2859 } else { 2860 switchedCodes = new int[]{callback.mWatchedOpCode}; 2861 } 2862 2863 for (int switchedCode : switchedCodes) { 2864 // There are features watching for mode changes such as window manager 2865 // and location manager which are in our process. The callbacks in these 2866 // features may require permissions our remote caller does not have. 2867 final long identity = Binder.clearCallingIdentity(); 2868 try { 2869 callback.mCallback.opChanged(switchedCode, uid, packageName); 2870 } catch (RemoteException e) { 2871 /* ignore */ 2872 } finally { 2873 Binder.restoreCallingIdentity(identity); 2874 } 2875 } 2876 } 2877 addChange(ArrayList<ChangeRec> reports, int op, int uid, String packageName, int previousMode)2878 private static ArrayList<ChangeRec> addChange(ArrayList<ChangeRec> reports, 2879 int op, int uid, String packageName, int previousMode) { 2880 boolean duplicate = false; 2881 if (reports == null) { 2882 reports = new ArrayList<>(); 2883 } else { 2884 final int reportCount = reports.size(); 2885 for (int j = 0; j < reportCount; j++) { 2886 ChangeRec report = reports.get(j); 2887 if (report.op == op && report.pkg.equals(packageName)) { 2888 duplicate = true; 2889 break; 2890 } 2891 } 2892 } 2893 if (!duplicate) { 2894 reports.add(new ChangeRec(op, uid, packageName, previousMode)); 2895 } 2896 2897 return reports; 2898 } 2899 addCallbacks( HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks, int op, int uid, String packageName, int previousMode, ArraySet<ModeCallback> cbs)2900 private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks( 2901 HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks, 2902 int op, int uid, String packageName, int previousMode, ArraySet<ModeCallback> cbs) { 2903 if (cbs == null) { 2904 return callbacks; 2905 } 2906 if (callbacks == null) { 2907 callbacks = new HashMap<>(); 2908 } 2909 final int N = cbs.size(); 2910 for (int i=0; i<N; i++) { 2911 ModeCallback cb = cbs.valueAt(i); 2912 ArrayList<ChangeRec> reports = callbacks.get(cb); 2913 ArrayList<ChangeRec> changed = addChange(reports, op, uid, packageName, previousMode); 2914 if (changed != reports) { 2915 callbacks.put(cb, changed); 2916 } 2917 } 2918 return callbacks; 2919 } 2920 2921 static final class ChangeRec { 2922 final int op; 2923 final int uid; 2924 final String pkg; 2925 final int previous_mode; 2926 ChangeRec(int _op, int _uid, String _pkg, int _previous_mode)2927 ChangeRec(int _op, int _uid, String _pkg, int _previous_mode) { 2928 op = _op; 2929 uid = _uid; 2930 pkg = _pkg; 2931 previous_mode = _previous_mode; 2932 } 2933 } 2934 2935 @Override resetAllModes(int reqUserId, String reqPackageName)2936 public void resetAllModes(int reqUserId, String reqPackageName) { 2937 final int callingPid = Binder.getCallingPid(); 2938 final int callingUid = Binder.getCallingUid(); 2939 reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId, 2940 true, true, "resetAllModes", null); 2941 2942 int reqUid = -1; 2943 if (reqPackageName != null) { 2944 try { 2945 reqUid = AppGlobals.getPackageManager().getPackageUid( 2946 reqPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, reqUserId); 2947 } catch (RemoteException e) { 2948 /* ignore - local call */ 2949 } 2950 } 2951 2952 enforceManageAppOpsModes(callingPid, callingUid, reqUid); 2953 2954 HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks = null; 2955 ArrayList<ChangeRec> allChanges = new ArrayList<>(); 2956 synchronized (this) { 2957 boolean changed = false; 2958 for (int i = mUidStates.size() - 1; i >= 0; i--) { 2959 UidState uidState = mUidStates.valueAt(i); 2960 2961 SparseIntArray opModes = uidState.opModes; 2962 if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) { 2963 final int uidOpCount = opModes.size(); 2964 for (int j = uidOpCount - 1; j >= 0; j--) { 2965 final int code = opModes.keyAt(j); 2966 if (AppOpsManager.opAllowsReset(code)) { 2967 int previousMode = opModes.valueAt(j); 2968 opModes.removeAt(j); 2969 if (opModes.size() <= 0) { 2970 uidState.opModes = null; 2971 } 2972 for (String packageName : getPackagesForUid(uidState.uid)) { 2973 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, 2974 previousMode, mOpModeWatchers.get(code)); 2975 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, 2976 previousMode, mPackageModeWatchers.get(packageName)); 2977 2978 allChanges = addChange(allChanges, code, uidState.uid, 2979 packageName, previousMode); 2980 } 2981 } 2982 } 2983 } 2984 2985 if (uidState.pkgOps == null) { 2986 continue; 2987 } 2988 2989 if (reqUserId != UserHandle.USER_ALL 2990 && reqUserId != UserHandle.getUserId(uidState.uid)) { 2991 // Skip any ops for a different user 2992 continue; 2993 } 2994 2995 Map<String, Ops> packages = uidState.pkgOps; 2996 Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator(); 2997 boolean uidChanged = false; 2998 while (it.hasNext()) { 2999 Map.Entry<String, Ops> ent = it.next(); 3000 String packageName = ent.getKey(); 3001 if (reqPackageName != null && !reqPackageName.equals(packageName)) { 3002 // Skip any ops for a different package 3003 continue; 3004 } 3005 Ops pkgOps = ent.getValue(); 3006 for (int j=pkgOps.size()-1; j>=0; j--) { 3007 Op curOp = pkgOps.valueAt(j); 3008 if (shouldDeferResetOpToDpm(curOp.op)) { 3009 deferResetOpToDpm(curOp.op, reqPackageName, reqUserId); 3010 continue; 3011 } 3012 if (AppOpsManager.opAllowsReset(curOp.op) 3013 && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) { 3014 int previousMode = curOp.mode; 3015 curOp.mode = AppOpsManager.opToDefaultMode(curOp.op); 3016 changed = true; 3017 uidChanged = true; 3018 final int uid = curOp.uidState.uid; 3019 callbacks = addCallbacks(callbacks, curOp.op, uid, packageName, 3020 previousMode, mOpModeWatchers.get(curOp.op)); 3021 callbacks = addCallbacks(callbacks, curOp.op, uid, packageName, 3022 previousMode, mPackageModeWatchers.get(packageName)); 3023 3024 allChanges = addChange(allChanges, curOp.op, uid, packageName, 3025 previousMode); 3026 curOp.removeAttributionsWithNoTime(); 3027 if (curOp.mAttributions.isEmpty()) { 3028 pkgOps.removeAt(j); 3029 } 3030 } 3031 } 3032 if (pkgOps.size() == 0) { 3033 it.remove(); 3034 } 3035 } 3036 if (uidState.isDefault()) { 3037 mUidStates.remove(uidState.uid); 3038 } 3039 if (uidChanged) { 3040 uidState.evalForegroundOps(mOpModeWatchers); 3041 } 3042 } 3043 3044 if (changed) { 3045 scheduleFastWriteLocked(); 3046 } 3047 } 3048 if (callbacks != null) { 3049 for (Map.Entry<ModeCallback, ArrayList<ChangeRec>> ent : callbacks.entrySet()) { 3050 ModeCallback cb = ent.getKey(); 3051 ArrayList<ChangeRec> reports = ent.getValue(); 3052 for (int i=0; i<reports.size(); i++) { 3053 ChangeRec rep = reports.get(i); 3054 mHandler.sendMessage(PooledLambda.obtainMessage( 3055 AppOpsService::notifyOpChanged, 3056 this, cb, rep.op, rep.uid, rep.pkg)); 3057 } 3058 } 3059 } 3060 3061 int numChanges = allChanges.size(); 3062 for (int i = 0; i < numChanges; i++) { 3063 ChangeRec change = allChanges.get(i); 3064 notifyOpChangedSync(change.op, change.uid, change.pkg, 3065 AppOpsManager.opToDefaultMode(change.op), change.previous_mode); 3066 } 3067 } 3068 shouldDeferResetOpToDpm(int op)3069 private boolean shouldDeferResetOpToDpm(int op) { 3070 // TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission 3071 // pre-grants to a role-based mechanism or another general-purpose mechanism. 3072 return dpmi != null && dpmi.supportsResetOp(op); 3073 } 3074 3075 /** Assumes {@link #shouldDeferResetOpToDpm(int)} is true. */ deferResetOpToDpm(int op, String packageName, @UserIdInt int userId)3076 private void deferResetOpToDpm(int op, String packageName, @UserIdInt int userId) { 3077 // TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission 3078 // pre-grants to a role-based mechanism or another general-purpose mechanism. 3079 dpmi.resetOp(op, packageName, userId); 3080 } 3081 evalAllForegroundOpsLocked()3082 private void evalAllForegroundOpsLocked() { 3083 for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) { 3084 final UidState uidState = mUidStates.valueAt(uidi); 3085 if (uidState.foregroundOps != null) { 3086 uidState.evalForegroundOps(mOpModeWatchers); 3087 } 3088 } 3089 } 3090 3091 @Override startWatchingMode(int op, String packageName, IAppOpsCallback callback)3092 public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) { 3093 startWatchingModeWithFlags(op, packageName, 0, callback); 3094 } 3095 3096 @Override startWatchingModeWithFlags(int op, String packageName, int flags, IAppOpsCallback callback)3097 public void startWatchingModeWithFlags(int op, String packageName, int flags, 3098 IAppOpsCallback callback) { 3099 int watchedUid = -1; 3100 final int callingUid = Binder.getCallingUid(); 3101 final int callingPid = Binder.getCallingPid(); 3102 // TODO: should have a privileged permission to protect this. 3103 // Also, if the caller has requested WATCH_FOREGROUND_CHANGES, should we require 3104 // the USAGE_STATS permission since this can provide information about when an 3105 // app is in the foreground? 3106 Preconditions.checkArgumentInRange(op, AppOpsManager.OP_NONE, 3107 AppOpsManager._NUM_OP - 1, "Invalid op code: " + op); 3108 if (callback == null) { 3109 return; 3110 } 3111 final boolean mayWatchPackageName = 3112 packageName != null && !filterAppAccessUnlocked(packageName); 3113 synchronized (this) { 3114 int switchOp = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op; 3115 3116 int notifiedOps; 3117 if ((flags & CALL_BACK_ON_SWITCHED_OP) == 0) { 3118 if (op == OP_NONE) { 3119 notifiedOps = ALL_OPS; 3120 } else { 3121 notifiedOps = op; 3122 } 3123 } else { 3124 notifiedOps = switchOp; 3125 } 3126 3127 ModeCallback cb = mModeWatchers.get(callback.asBinder()); 3128 if (cb == null) { 3129 cb = new ModeCallback(callback, watchedUid, flags, notifiedOps, callingUid, 3130 callingPid); 3131 mModeWatchers.put(callback.asBinder(), cb); 3132 } 3133 if (switchOp != AppOpsManager.OP_NONE) { 3134 ArraySet<ModeCallback> cbs = mOpModeWatchers.get(switchOp); 3135 if (cbs == null) { 3136 cbs = new ArraySet<>(); 3137 mOpModeWatchers.put(switchOp, cbs); 3138 } 3139 cbs.add(cb); 3140 } 3141 if (mayWatchPackageName) { 3142 ArraySet<ModeCallback> cbs = mPackageModeWatchers.get(packageName); 3143 if (cbs == null) { 3144 cbs = new ArraySet<>(); 3145 mPackageModeWatchers.put(packageName, cbs); 3146 } 3147 cbs.add(cb); 3148 } 3149 evalAllForegroundOpsLocked(); 3150 } 3151 } 3152 3153 @Override stopWatchingMode(IAppOpsCallback callback)3154 public void stopWatchingMode(IAppOpsCallback callback) { 3155 if (callback == null) { 3156 return; 3157 } 3158 synchronized (this) { 3159 ModeCallback cb = mModeWatchers.remove(callback.asBinder()); 3160 if (cb != null) { 3161 cb.unlinkToDeath(); 3162 for (int i=mOpModeWatchers.size()-1; i>=0; i--) { 3163 ArraySet<ModeCallback> cbs = mOpModeWatchers.valueAt(i); 3164 cbs.remove(cb); 3165 if (cbs.size() <= 0) { 3166 mOpModeWatchers.removeAt(i); 3167 } 3168 } 3169 for (int i=mPackageModeWatchers.size()-1; i>=0; i--) { 3170 ArraySet<ModeCallback> cbs = mPackageModeWatchers.valueAt(i); 3171 cbs.remove(cb); 3172 if (cbs.size() <= 0) { 3173 mPackageModeWatchers.removeAt(i); 3174 } 3175 } 3176 } 3177 evalAllForegroundOpsLocked(); 3178 } 3179 } 3180 getAppOpsServiceDelegate()3181 public CheckOpsDelegate getAppOpsServiceDelegate() { 3182 synchronized (AppOpsService.this) { 3183 final CheckOpsDelegateDispatcher dispatcher = mCheckOpsDelegateDispatcher; 3184 return (dispatcher != null) ? dispatcher.getCheckOpsDelegate() : null; 3185 } 3186 } 3187 setAppOpsServiceDelegate(CheckOpsDelegate delegate)3188 public void setAppOpsServiceDelegate(CheckOpsDelegate delegate) { 3189 synchronized (AppOpsService.this) { 3190 final CheckOpsDelegateDispatcher oldDispatcher = mCheckOpsDelegateDispatcher; 3191 final CheckOpsDelegate policy = (oldDispatcher != null) ? oldDispatcher.mPolicy : null; 3192 mCheckOpsDelegateDispatcher = new CheckOpsDelegateDispatcher(policy, delegate); 3193 } 3194 } 3195 3196 @Override checkOperationRaw(int code, int uid, String packageName, @Nullable String attributionTag)3197 public int checkOperationRaw(int code, int uid, String packageName, 3198 @Nullable String attributionTag) { 3199 return mCheckOpsDelegateDispatcher.checkOperation(code, uid, packageName, attributionTag, 3200 true /*raw*/); 3201 } 3202 3203 @Override checkOperation(int code, int uid, String packageName)3204 public int checkOperation(int code, int uid, String packageName) { 3205 return mCheckOpsDelegateDispatcher.checkOperation(code, uid, packageName, null, 3206 false /*raw*/); 3207 } 3208 checkOperationImpl(int code, int uid, String packageName, @Nullable String attributionTag, boolean raw)3209 private int checkOperationImpl(int code, int uid, String packageName, 3210 @Nullable String attributionTag, boolean raw) { 3211 verifyIncomingOp(code); 3212 verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); 3213 3214 String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); 3215 if (resolvedPackageName == null) { 3216 return AppOpsManager.MODE_IGNORED; 3217 } 3218 return checkOperationUnchecked(code, uid, resolvedPackageName, attributionTag, raw); 3219 } 3220 3221 /** 3222 * Get the mode of an app-op. 3223 * 3224 * @param code The code of the op 3225 * @param uid The uid of the package the op belongs to 3226 * @param packageName The package the op belongs to 3227 * @param raw If the raw state of eval-ed state should be checked. 3228 * 3229 * @return The mode of the op 3230 */ checkOperationUnchecked(int code, int uid, @NonNull String packageName, @Nullable String attributionTag, boolean raw)3231 private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName, 3232 @Nullable String attributionTag, boolean raw) { 3233 PackageVerificationResult pvr; 3234 try { 3235 pvr = verifyAndGetBypass(uid, packageName, null); 3236 } catch (SecurityException e) { 3237 Slog.e(TAG, "checkOperation", e); 3238 return AppOpsManager.opToDefaultMode(code); 3239 } 3240 3241 if (isOpRestrictedDueToSuspend(code, packageName, uid)) { 3242 return AppOpsManager.MODE_IGNORED; 3243 } 3244 synchronized (this) { 3245 if (isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass)) { 3246 return AppOpsManager.MODE_IGNORED; 3247 } 3248 code = AppOpsManager.opToSwitch(code); 3249 UidState uidState = getUidStateLocked(uid, false); 3250 if (uidState != null && uidState.opModes != null 3251 && uidState.opModes.indexOfKey(code) >= 0) { 3252 final int rawMode = uidState.opModes.get(code); 3253 return raw ? rawMode : uidState.evalMode(code, rawMode); 3254 } 3255 Op op = getOpLocked(code, uid, packageName, null, false, pvr.bypass, /* edit */ false); 3256 if (op == null) { 3257 return AppOpsManager.opToDefaultMode(code); 3258 } 3259 return raw ? op.mode : op.evalMode(); 3260 } 3261 } 3262 3263 @Override checkAudioOperation(int code, int usage, int uid, String packageName)3264 public int checkAudioOperation(int code, int usage, int uid, String packageName) { 3265 return mCheckOpsDelegateDispatcher.checkAudioOperation(code, usage, uid, packageName); 3266 } 3267 checkAudioOperationImpl(int code, int usage, int uid, String packageName)3268 private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) { 3269 final int mode = mAudioRestrictionManager.checkAudioOperation( 3270 code, usage, uid, packageName); 3271 if (mode != AppOpsManager.MODE_ALLOWED) { 3272 return mode; 3273 } 3274 return checkOperation(code, uid, packageName); 3275 } 3276 3277 @Override setAudioRestriction(int code, int usage, int uid, int mode, String[] exceptionPackages)3278 public void setAudioRestriction(int code, int usage, int uid, int mode, 3279 String[] exceptionPackages) { 3280 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); 3281 verifyIncomingUid(uid); 3282 verifyIncomingOp(code); 3283 3284 mAudioRestrictionManager.setZenModeAudioRestriction( 3285 code, usage, uid, mode, exceptionPackages); 3286 3287 mHandler.sendMessage(PooledLambda.obtainMessage( 3288 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY)); 3289 } 3290 3291 3292 @Override setCameraAudioRestriction(@AMERA_AUDIO_RESTRICTION int mode)3293 public void setCameraAudioRestriction(@CAMERA_AUDIO_RESTRICTION int mode) { 3294 enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), -1); 3295 3296 mAudioRestrictionManager.setCameraAudioRestriction(mode); 3297 3298 mHandler.sendMessage(PooledLambda.obtainMessage( 3299 AppOpsService::notifyWatchersOfChange, this, 3300 AppOpsManager.OP_PLAY_AUDIO, UID_ANY)); 3301 mHandler.sendMessage(PooledLambda.obtainMessage( 3302 AppOpsService::notifyWatchersOfChange, this, 3303 AppOpsManager.OP_VIBRATE, UID_ANY)); 3304 } 3305 3306 @Override checkPackage(int uid, String packageName)3307 public int checkPackage(int uid, String packageName) { 3308 Objects.requireNonNull(packageName); 3309 try { 3310 verifyAndGetBypass(uid, packageName, null); 3311 if (filterAppAccessUnlocked(packageName)) { 3312 return AppOpsManager.MODE_ERRORED; 3313 } 3314 return AppOpsManager.MODE_ALLOWED; 3315 } catch (SecurityException ignored) { 3316 return AppOpsManager.MODE_ERRORED; 3317 } 3318 } 3319 3320 /** 3321 * This method will check with PackageManager to determine if the package provided should 3322 * be visible to the {@link Binder#getCallingUid()}. 3323 * 3324 * NOTE: This must not be called while synchronized on {@code this} to avoid dead locks 3325 */ filterAppAccessUnlocked(String packageName)3326 private boolean filterAppAccessUnlocked(String packageName) { 3327 final int callingUid = Binder.getCallingUid(); 3328 return LocalServices.getService(PackageManagerInternal.class) 3329 .filterAppAccess(packageName, callingUid, UserHandle.getUserId(callingUid)); 3330 } 3331 3332 @Override noteProxyOperation(int code, AttributionSource attributionSource, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation)3333 public SyncNotedAppOp noteProxyOperation(int code, AttributionSource attributionSource, 3334 boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, 3335 boolean skipProxyOperation) { 3336 return mCheckOpsDelegateDispatcher.noteProxyOperation(code, attributionSource, 3337 shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation); 3338 } 3339 noteProxyOperationImpl(int code, AttributionSource attributionSource, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation)3340 private SyncNotedAppOp noteProxyOperationImpl(int code, AttributionSource attributionSource, 3341 boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, 3342 boolean skipProxyOperation) { 3343 final int proxyUid = attributionSource.getUid(); 3344 final String proxyPackageName = attributionSource.getPackageName(); 3345 final String proxyAttributionTag = attributionSource.getAttributionTag(); 3346 final int proxiedUid = attributionSource.getNextUid(); 3347 final String proxiedPackageName = attributionSource.getNextPackageName(); 3348 final String proxiedAttributionTag = attributionSource.getNextAttributionTag(); 3349 3350 verifyIncomingProxyUid(attributionSource); 3351 verifyIncomingOp(code); 3352 verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid)); 3353 verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid)); 3354 3355 skipProxyOperation = skipProxyOperation 3356 && isCallerAndAttributionTrusted(attributionSource); 3357 3358 String resolveProxyPackageName = AppOpsManager.resolvePackageName(proxyUid, 3359 proxyPackageName); 3360 if (resolveProxyPackageName == null) { 3361 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, 3362 proxiedAttributionTag, proxiedPackageName); 3363 } 3364 3365 final boolean isSelfBlame = Binder.getCallingUid() == proxiedUid; 3366 final boolean isProxyTrusted = mContext.checkPermission( 3367 Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid) 3368 == PackageManager.PERMISSION_GRANTED || isSelfBlame; 3369 3370 if (!skipProxyOperation) { 3371 final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY 3372 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY; 3373 3374 final SyncNotedAppOp proxyReturn = noteOperationUnchecked(code, proxyUid, 3375 resolveProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null, 3376 proxyFlags, !isProxyTrusted, "proxy " + message, shouldCollectMessage); 3377 if (proxyReturn.getOpMode() != AppOpsManager.MODE_ALLOWED) { 3378 return new SyncNotedAppOp(proxyReturn.getOpMode(), code, proxiedAttributionTag, 3379 proxiedPackageName); 3380 } 3381 } 3382 3383 String resolveProxiedPackageName = AppOpsManager.resolvePackageName(proxiedUid, 3384 proxiedPackageName); 3385 if (resolveProxiedPackageName == null) { 3386 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, proxiedAttributionTag, 3387 proxiedPackageName); 3388 } 3389 3390 final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED 3391 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED; 3392 return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName, 3393 proxiedAttributionTag, proxyUid, resolveProxyPackageName, proxyAttributionTag, 3394 proxiedFlags, shouldCollectAsyncNotedOp, message, shouldCollectMessage); 3395 } 3396 3397 @Override noteOperation(int code, int uid, String packageName, String attributionTag, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage)3398 public SyncNotedAppOp noteOperation(int code, int uid, String packageName, 3399 String attributionTag, boolean shouldCollectAsyncNotedOp, String message, 3400 boolean shouldCollectMessage) { 3401 return mCheckOpsDelegateDispatcher.noteOperation(code, uid, packageName, 3402 attributionTag, shouldCollectAsyncNotedOp, message, shouldCollectMessage); 3403 } 3404 noteOperationImpl(int code, int uid, @Nullable String packageName, @Nullable String attributionTag, boolean shouldCollectAsyncNotedOp, @Nullable String message, boolean shouldCollectMessage)3405 private SyncNotedAppOp noteOperationImpl(int code, int uid, @Nullable String packageName, 3406 @Nullable String attributionTag, boolean shouldCollectAsyncNotedOp, 3407 @Nullable String message, boolean shouldCollectMessage) { 3408 verifyIncomingUid(uid); 3409 verifyIncomingOp(code); 3410 verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); 3411 3412 String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); 3413 if (resolvedPackageName == null) { 3414 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag, 3415 packageName); 3416 } 3417 return noteOperationUnchecked(code, uid, resolvedPackageName, attributionTag, 3418 Process.INVALID_UID, null, null, AppOpsManager.OP_FLAG_SELF, 3419 shouldCollectAsyncNotedOp, message, shouldCollectMessage); 3420 } 3421 noteOperationUnchecked(int code, int uid, @NonNull String packageName, @Nullable String attributionTag, int proxyUid, String proxyPackageName, @Nullable String proxyAttributionTag, @OpFlags int flags, boolean shouldCollectAsyncNotedOp, @Nullable String message, boolean shouldCollectMessage)3422 private SyncNotedAppOp noteOperationUnchecked(int code, int uid, @NonNull String packageName, 3423 @Nullable String attributionTag, int proxyUid, String proxyPackageName, 3424 @Nullable String proxyAttributionTag, @OpFlags int flags, 3425 boolean shouldCollectAsyncNotedOp, @Nullable String message, 3426 boolean shouldCollectMessage) { 3427 PackageVerificationResult pvr; 3428 try { 3429 pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName); 3430 boolean wasNull = attributionTag == null; 3431 if (!pvr.isAttributionTagValid) { 3432 attributionTag = null; 3433 } 3434 } catch (SecurityException e) { 3435 Slog.e(TAG, "noteOperation", e); 3436 return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, 3437 packageName); 3438 } 3439 3440 synchronized (this) { 3441 final Ops ops = getOpsLocked(uid, packageName, attributionTag, 3442 pvr.isAttributionTagValid, pvr.bypass, /* edit */ true); 3443 if (ops == null) { 3444 scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags, 3445 AppOpsManager.MODE_IGNORED); 3446 if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid 3447 + " package " + packageName + "flags: " + 3448 AppOpsManager.flagsToString(flags)); 3449 return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, 3450 packageName); 3451 } 3452 final Op op = getOpLocked(ops, code, uid, true); 3453 final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag); 3454 if (attributedOp.isRunning()) { 3455 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName + " code " 3456 + code + " startTime of in progress event=" 3457 + attributedOp.mInProgressEvents.valueAt(0).getStartTime()); 3458 } 3459 3460 final int switchCode = AppOpsManager.opToSwitch(code); 3461 final UidState uidState = ops.uidState; 3462 if (isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass)) { 3463 attributedOp.rejected(uidState.state, flags); 3464 scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags, 3465 AppOpsManager.MODE_IGNORED); 3466 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag, 3467 packageName); 3468 } 3469 // If there is a non-default per UID policy (we set UID op mode only if 3470 // non-default) it takes over, otherwise use the per package policy. 3471 if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) { 3472 final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode)); 3473 if (uidMode != AppOpsManager.MODE_ALLOWED) { 3474 if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code " 3475 + switchCode + " (" + code + ") uid " + uid + " package " 3476 + packageName + " flags: " + AppOpsManager.flagsToString(flags)); 3477 attributedOp.rejected(uidState.state, flags); 3478 scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags, 3479 uidMode); 3480 return new SyncNotedAppOp(uidMode, code, attributionTag, packageName); 3481 } 3482 } else { 3483 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, uid, true) 3484 : op; 3485 final int mode = switchOp.evalMode(); 3486 if (mode != AppOpsManager.MODE_ALLOWED) { 3487 if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code " 3488 + switchCode + " (" + code + ") uid " + uid + " package " 3489 + packageName + " flags: " + AppOpsManager.flagsToString(flags)); 3490 attributedOp.rejected(uidState.state, flags); 3491 scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags, 3492 mode); 3493 return new SyncNotedAppOp(mode, code, attributionTag, packageName); 3494 } 3495 } 3496 if (DEBUG) { 3497 Slog.d(TAG, 3498 "noteOperation: allowing code " + code + " uid " + uid + " package " 3499 + packageName + (attributionTag == null ? "" 3500 : "." + attributionTag) + " flags: " 3501 + AppOpsManager.flagsToString(flags)); 3502 } 3503 scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags, 3504 AppOpsManager.MODE_ALLOWED); 3505 attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag, uidState.state, 3506 flags); 3507 3508 if (shouldCollectAsyncNotedOp) { 3509 collectAsyncNotedOp(uid, packageName, code, attributionTag, flags, message, 3510 shouldCollectMessage); 3511 } 3512 3513 return new SyncNotedAppOp(AppOpsManager.MODE_ALLOWED, code, attributionTag, 3514 packageName); 3515 } 3516 } 3517 3518 // TODO moltmann: Allow watching for attribution ops 3519 @Override startWatchingActive(int[] ops, IAppOpsActiveCallback callback)3520 public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) { 3521 int watchedUid = Process.INVALID_UID; 3522 final int callingUid = Binder.getCallingUid(); 3523 final int callingPid = Binder.getCallingPid(); 3524 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 3525 != PackageManager.PERMISSION_GRANTED) { 3526 watchedUid = callingUid; 3527 } 3528 if (ops != null) { 3529 Preconditions.checkArrayElementsInRange(ops, 0, 3530 AppOpsManager._NUM_OP - 1, "Invalid op code in: " + Arrays.toString(ops)); 3531 } 3532 if (callback == null) { 3533 return; 3534 } 3535 synchronized (this) { 3536 SparseArray<ActiveCallback> callbacks = mActiveWatchers.get(callback.asBinder()); 3537 if (callbacks == null) { 3538 callbacks = new SparseArray<>(); 3539 mActiveWatchers.put(callback.asBinder(), callbacks); 3540 } 3541 final ActiveCallback activeCallback = new ActiveCallback(callback, watchedUid, 3542 callingUid, callingPid); 3543 for (int op : ops) { 3544 callbacks.put(op, activeCallback); 3545 } 3546 } 3547 } 3548 3549 @Override stopWatchingActive(IAppOpsActiveCallback callback)3550 public void stopWatchingActive(IAppOpsActiveCallback callback) { 3551 if (callback == null) { 3552 return; 3553 } 3554 synchronized (this) { 3555 final SparseArray<ActiveCallback> activeCallbacks = 3556 mActiveWatchers.remove(callback.asBinder()); 3557 if (activeCallbacks == null) { 3558 return; 3559 } 3560 final int callbackCount = activeCallbacks.size(); 3561 for (int i = 0; i < callbackCount; i++) { 3562 activeCallbacks.valueAt(i).destroy(); 3563 } 3564 } 3565 } 3566 3567 @Override startWatchingStarted(int[] ops, @NonNull IAppOpsStartedCallback callback)3568 public void startWatchingStarted(int[] ops, @NonNull IAppOpsStartedCallback callback) { 3569 int watchedUid = Process.INVALID_UID; 3570 final int callingUid = Binder.getCallingUid(); 3571 final int callingPid = Binder.getCallingPid(); 3572 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 3573 != PackageManager.PERMISSION_GRANTED) { 3574 watchedUid = callingUid; 3575 } 3576 3577 Preconditions.checkArgument(!ArrayUtils.isEmpty(ops), "Ops cannot be null or empty"); 3578 Preconditions.checkArrayElementsInRange(ops, 0, AppOpsManager._NUM_OP - 1, 3579 "Invalid op code in: " + Arrays.toString(ops)); 3580 Objects.requireNonNull(callback, "Callback cannot be null"); 3581 3582 synchronized (this) { 3583 SparseArray<StartedCallback> callbacks = mStartedWatchers.get(callback.asBinder()); 3584 if (callbacks == null) { 3585 callbacks = new SparseArray<>(); 3586 mStartedWatchers.put(callback.asBinder(), callbacks); 3587 } 3588 3589 final StartedCallback startedCallback = new StartedCallback(callback, watchedUid, 3590 callingUid, callingPid); 3591 for (int op : ops) { 3592 callbacks.put(op, startedCallback); 3593 } 3594 } 3595 } 3596 3597 @Override stopWatchingStarted(IAppOpsStartedCallback callback)3598 public void stopWatchingStarted(IAppOpsStartedCallback callback) { 3599 Objects.requireNonNull(callback, "Callback cannot be null"); 3600 3601 synchronized (this) { 3602 final SparseArray<StartedCallback> startedCallbacks = 3603 mStartedWatchers.remove(callback.asBinder()); 3604 if (startedCallbacks == null) { 3605 return; 3606 } 3607 3608 final int callbackCount = startedCallbacks.size(); 3609 for (int i = 0; i < callbackCount; i++) { 3610 startedCallbacks.valueAt(i).destroy(); 3611 } 3612 } 3613 } 3614 3615 @Override startWatchingNoted(@onNull int[] ops, @NonNull IAppOpsNotedCallback callback)3616 public void startWatchingNoted(@NonNull int[] ops, @NonNull IAppOpsNotedCallback callback) { 3617 int watchedUid = Process.INVALID_UID; 3618 final int callingUid = Binder.getCallingUid(); 3619 final int callingPid = Binder.getCallingPid(); 3620 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 3621 != PackageManager.PERMISSION_GRANTED) { 3622 watchedUid = callingUid; 3623 } 3624 Preconditions.checkArgument(!ArrayUtils.isEmpty(ops), "Ops cannot be null or empty"); 3625 Preconditions.checkArrayElementsInRange(ops, 0, AppOpsManager._NUM_OP - 1, 3626 "Invalid op code in: " + Arrays.toString(ops)); 3627 Objects.requireNonNull(callback, "Callback cannot be null"); 3628 synchronized (this) { 3629 SparseArray<NotedCallback> callbacks = mNotedWatchers.get(callback.asBinder()); 3630 if (callbacks == null) { 3631 callbacks = new SparseArray<>(); 3632 mNotedWatchers.put(callback.asBinder(), callbacks); 3633 } 3634 final NotedCallback notedCallback = new NotedCallback(callback, watchedUid, 3635 callingUid, callingPid); 3636 for (int op : ops) { 3637 callbacks.put(op, notedCallback); 3638 } 3639 } 3640 } 3641 3642 @Override stopWatchingNoted(IAppOpsNotedCallback callback)3643 public void stopWatchingNoted(IAppOpsNotedCallback callback) { 3644 Objects.requireNonNull(callback, "Callback cannot be null"); 3645 synchronized (this) { 3646 final SparseArray<NotedCallback> notedCallbacks = 3647 mNotedWatchers.remove(callback.asBinder()); 3648 if (notedCallbacks == null) { 3649 return; 3650 } 3651 final int callbackCount = notedCallbacks.size(); 3652 for (int i = 0; i < callbackCount; i++) { 3653 notedCallbacks.valueAt(i).destroy(); 3654 } 3655 } 3656 } 3657 3658 /** 3659 * Collect an {@link AsyncNotedAppOp}. 3660 * 3661 * @param uid The uid the op was noted for 3662 * @param packageName The package the op was noted for 3663 * @param opCode The code of the op noted 3664 * @param attributionTag attribution tag the op was noted for 3665 * @param message The message for the op noting 3666 */ collectAsyncNotedOp(int uid, @NonNull String packageName, int opCode, @Nullable String attributionTag, @OpFlags int flags, @NonNull String message, boolean shouldCollectMessage)3667 private void collectAsyncNotedOp(int uid, @NonNull String packageName, int opCode, 3668 @Nullable String attributionTag, @OpFlags int flags, @NonNull String message, 3669 boolean shouldCollectMessage) { 3670 Objects.requireNonNull(message); 3671 3672 int callingUid = Binder.getCallingUid(); 3673 3674 final long token = Binder.clearCallingIdentity(); 3675 try { 3676 synchronized (this) { 3677 Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid); 3678 3679 RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key); 3680 AsyncNotedAppOp asyncNotedOp = new AsyncNotedAppOp(opCode, callingUid, 3681 attributionTag, message, System.currentTimeMillis()); 3682 final boolean[] wasNoteForwarded = {false}; 3683 3684 if ((flags & (OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED)) != 0 3685 && shouldCollectMessage) { 3686 reportRuntimeAppOpAccessMessageAsyncLocked(uid, packageName, opCode, 3687 attributionTag, message); 3688 } 3689 3690 if (callbacks != null) { 3691 callbacks.broadcast((cb) -> { 3692 try { 3693 cb.opNoted(asyncNotedOp); 3694 wasNoteForwarded[0] = true; 3695 } catch (RemoteException e) { 3696 Slog.e(TAG, 3697 "Could not forward noteOp of " + opCode + " to " + packageName 3698 + "/" + uid + "(" + attributionTag + ")", e); 3699 } 3700 }); 3701 } 3702 3703 if (!wasNoteForwarded[0]) { 3704 ArrayList<AsyncNotedAppOp> unforwardedOps = mUnforwardedAsyncNotedOps.get(key); 3705 if (unforwardedOps == null) { 3706 unforwardedOps = new ArrayList<>(1); 3707 mUnforwardedAsyncNotedOps.put(key, unforwardedOps); 3708 } 3709 3710 unforwardedOps.add(asyncNotedOp); 3711 if (unforwardedOps.size() > MAX_UNFORWARDED_OPS) { 3712 unforwardedOps.remove(0); 3713 } 3714 } 3715 } 3716 } finally { 3717 Binder.restoreCallingIdentity(token); 3718 } 3719 } 3720 3721 /** 3722 * Compute a key to be used in {@link #mAsyncOpWatchers} and {@link #mUnforwardedAsyncNotedOps} 3723 * 3724 * @param packageName The package name of the app 3725 * @param uid The uid of the app 3726 * 3727 * @return They key uniquely identifying the app 3728 */ getAsyncNotedOpsKey(@onNull String packageName, int uid)3729 private @NonNull Pair<String, Integer> getAsyncNotedOpsKey(@NonNull String packageName, 3730 int uid) { 3731 return new Pair<>(packageName, uid); 3732 } 3733 3734 @Override startWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback)3735 public void startWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback) { 3736 Objects.requireNonNull(packageName); 3737 Objects.requireNonNull(callback); 3738 3739 int uid = Binder.getCallingUid(); 3740 Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid); 3741 3742 verifyAndGetBypass(uid, packageName, null); 3743 3744 synchronized (this) { 3745 RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key); 3746 if (callbacks == null) { 3747 callbacks = new RemoteCallbackList<IAppOpsAsyncNotedCallback>() { 3748 @Override 3749 public void onCallbackDied(IAppOpsAsyncNotedCallback callback) { 3750 synchronized (AppOpsService.this) { 3751 if (getRegisteredCallbackCount() == 0) { 3752 mAsyncOpWatchers.remove(key); 3753 } 3754 } 3755 } 3756 }; 3757 mAsyncOpWatchers.put(key, callbacks); 3758 } 3759 3760 callbacks.register(callback); 3761 } 3762 } 3763 3764 @Override stopWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback)3765 public void stopWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback) { 3766 Objects.requireNonNull(packageName); 3767 Objects.requireNonNull(callback); 3768 3769 int uid = Binder.getCallingUid(); 3770 Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid); 3771 3772 verifyAndGetBypass(uid, packageName, null); 3773 3774 synchronized (this) { 3775 RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key); 3776 if (callbacks != null) { 3777 callbacks.unregister(callback); 3778 if (callbacks.getRegisteredCallbackCount() == 0) { 3779 mAsyncOpWatchers.remove(key); 3780 } 3781 } 3782 } 3783 } 3784 3785 @Override extractAsyncOps(String packageName)3786 public List<AsyncNotedAppOp> extractAsyncOps(String packageName) { 3787 Objects.requireNonNull(packageName); 3788 3789 int uid = Binder.getCallingUid(); 3790 3791 verifyAndGetBypass(uid, packageName, null); 3792 3793 synchronized (this) { 3794 return mUnforwardedAsyncNotedOps.remove(getAsyncNotedOpsKey(packageName, uid)); 3795 } 3796 } 3797 3798 @Override startOperation(IBinder token, int code, int uid, @Nullable String packageName, @Nullable String attributionTag, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, @AttributionFlags int attributionFlags, int attributionChainId)3799 public SyncNotedAppOp startOperation(IBinder token, int code, int uid, 3800 @Nullable String packageName, @Nullable String attributionTag, 3801 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, 3802 String message, boolean shouldCollectMessage, @AttributionFlags int attributionFlags, 3803 int attributionChainId) { 3804 return mCheckOpsDelegateDispatcher.startOperation(token, code, uid, packageName, 3805 attributionTag, startIfModeDefault, shouldCollectAsyncNotedOp, message, 3806 shouldCollectMessage, attributionFlags, attributionChainId); 3807 } 3808 startOperationImpl(@onNull IBinder clientId, int code, int uid, @Nullable String packageName, @Nullable String attributionTag, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @NonNull String message, boolean shouldCollectMessage, @AttributionFlags int attributionFlags, int attributionChainId)3809 private SyncNotedAppOp startOperationImpl(@NonNull IBinder clientId, int code, int uid, 3810 @Nullable String packageName, @Nullable String attributionTag, 3811 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @NonNull String message, 3812 boolean shouldCollectMessage, @AttributionFlags int attributionFlags, 3813 int attributionChainId) { 3814 verifyIncomingUid(uid); 3815 verifyIncomingOp(code); 3816 verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); 3817 3818 String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); 3819 if (resolvedPackageName == null) { 3820 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag, 3821 packageName); 3822 } 3823 3824 // As a special case for OP_RECORD_AUDIO_HOTWORD, which we use only for attribution 3825 // purposes and not as a check, also make sure that the caller is allowed to access 3826 // the data gated by OP_RECORD_AUDIO. 3827 // 3828 // TODO: Revert this change before Android 12. 3829 if (code == OP_RECORD_AUDIO_HOTWORD) { 3830 int result = checkOperation(OP_RECORD_AUDIO, uid, packageName); 3831 if (result != AppOpsManager.MODE_ALLOWED) { 3832 return new SyncNotedAppOp(result, code, attributionTag, packageName); 3833 } 3834 } 3835 return startOperationUnchecked(clientId, code, uid, packageName, attributionTag, 3836 Process.INVALID_UID, null, null, OP_FLAG_SELF, startIfModeDefault, 3837 shouldCollectAsyncNotedOp, message, shouldCollectMessage, attributionFlags, 3838 attributionChainId, /*dryRun*/ false); 3839 } 3840 3841 @Override startProxyOperation(int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId)3842 public SyncNotedAppOp startProxyOperation(int code, 3843 @NonNull AttributionSource attributionSource, boolean startIfModeDefault, 3844 boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, 3845 boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, 3846 @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { 3847 return mCheckOpsDelegateDispatcher.startProxyOperation(code, attributionSource, 3848 startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, 3849 skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, 3850 attributionChainId); 3851 } 3852 startProxyOperationImpl(int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId)3853 private SyncNotedAppOp startProxyOperationImpl(int code, 3854 @NonNull AttributionSource attributionSource, 3855 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, 3856 boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags 3857 int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, 3858 int attributionChainId) { 3859 final int proxyUid = attributionSource.getUid(); 3860 final String proxyPackageName = attributionSource.getPackageName(); 3861 final String proxyAttributionTag = attributionSource.getAttributionTag(); 3862 final IBinder proxyToken = attributionSource.getToken(); 3863 final int proxiedUid = attributionSource.getNextUid(); 3864 final String proxiedPackageName = attributionSource.getNextPackageName(); 3865 final String proxiedAttributionTag = attributionSource.getNextAttributionTag(); 3866 final IBinder proxiedToken = attributionSource.getNextToken(); 3867 3868 verifyIncomingProxyUid(attributionSource); 3869 verifyIncomingOp(code); 3870 verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid)); 3871 verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid)); 3872 3873 boolean isCallerTrusted = isCallerAndAttributionTrusted(attributionSource); 3874 skipProxyOperation = isCallerTrusted && skipProxyOperation; 3875 3876 String resolvedProxyPackageName = AppOpsManager.resolvePackageName(proxyUid, 3877 proxyPackageName); 3878 if (resolvedProxyPackageName == null) { 3879 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, proxiedAttributionTag, 3880 proxiedPackageName); 3881 } 3882 3883 final boolean isChainTrusted = isCallerTrusted 3884 && attributionChainId != ATTRIBUTION_CHAIN_ID_NONE 3885 && ((proxyAttributionFlags & ATTRIBUTION_FLAG_TRUSTED) != 0 3886 || (proxiedAttributionFlags & ATTRIBUTION_FLAG_TRUSTED) != 0); 3887 final boolean isSelfBlame = Binder.getCallingUid() == proxiedUid; 3888 final boolean isProxyTrusted = mContext.checkPermission( 3889 Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid) 3890 == PackageManager.PERMISSION_GRANTED || isSelfBlame 3891 || isChainTrusted; 3892 3893 String resolvedProxiedPackageName = AppOpsManager.resolvePackageName(proxiedUid, 3894 proxiedPackageName); 3895 if (resolvedProxiedPackageName == null) { 3896 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, proxiedAttributionTag, 3897 proxiedPackageName); 3898 } 3899 3900 final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED 3901 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED; 3902 3903 if (!skipProxyOperation) { 3904 // Test if the proxied operation will succeed before starting the proxy operation 3905 final SyncNotedAppOp testProxiedOp = startOperationUnchecked(proxiedToken, code, 3906 proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag, proxyUid, 3907 resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault, 3908 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 3909 proxiedAttributionFlags, attributionChainId, /*dryRun*/ true); 3910 if (!shouldStartForMode(testProxiedOp.getOpMode(), startIfModeDefault)) { 3911 return testProxiedOp; 3912 } 3913 3914 final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY 3915 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY; 3916 3917 final SyncNotedAppOp proxyAppOp = startOperationUnchecked(proxyToken, code, proxyUid, 3918 resolvedProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null, 3919 proxyFlags, startIfModeDefault, !isProxyTrusted, "proxy " + message, 3920 shouldCollectMessage, proxyAttributionFlags, attributionChainId, 3921 /*dryRun*/ false); 3922 if (!shouldStartForMode(proxyAppOp.getOpMode(), startIfModeDefault)) { 3923 return proxyAppOp; 3924 } 3925 } 3926 3927 return startOperationUnchecked(proxiedToken, code, proxiedUid, resolvedProxiedPackageName, 3928 proxiedAttributionTag, proxyUid, resolvedProxyPackageName, proxyAttributionTag, 3929 proxiedFlags, startIfModeDefault, shouldCollectAsyncNotedOp, message, 3930 shouldCollectMessage, proxiedAttributionFlags, attributionChainId, 3931 /*dryRun*/ false); 3932 } 3933 shouldStartForMode(int mode, boolean startIfModeDefault)3934 private boolean shouldStartForMode(int mode, boolean startIfModeDefault) { 3935 return (mode == MODE_ALLOWED || (mode == MODE_DEFAULT && startIfModeDefault)); 3936 } 3937 startOperationUnchecked(IBinder clientId, int code, int uid, @NonNull String packageName, @Nullable String attributionTag, int proxyUid, String proxyPackageName, @Nullable String proxyAttributionTag, @OpFlags int flags, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @Nullable String message, boolean shouldCollectMessage, @AttributionFlags int attributionFlags, int attributionChainId, boolean dryRun)3938 private SyncNotedAppOp startOperationUnchecked(IBinder clientId, int code, int uid, 3939 @NonNull String packageName, @Nullable String attributionTag, int proxyUid, 3940 String proxyPackageName, @Nullable String proxyAttributionTag, @OpFlags int flags, 3941 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @Nullable String message, 3942 boolean shouldCollectMessage, @AttributionFlags int attributionFlags, 3943 int attributionChainId, boolean dryRun) { 3944 PackageVerificationResult pvr; 3945 try { 3946 pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName); 3947 if (!pvr.isAttributionTagValid) { 3948 attributionTag = null; 3949 } 3950 } catch (SecurityException e) { 3951 Slog.e(TAG, "startOperation", e); 3952 return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, 3953 packageName); 3954 } 3955 3956 boolean isRestricted = false; 3957 int startType = START_TYPE_FAILED; 3958 synchronized (this) { 3959 final Ops ops = getOpsLocked(uid, packageName, attributionTag, 3960 pvr.isAttributionTagValid, pvr.bypass, /* edit */ true); 3961 if (ops == null) { 3962 if (!dryRun) { 3963 scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag, 3964 flags, AppOpsManager.MODE_IGNORED, startType, attributionFlags, 3965 attributionChainId); 3966 } 3967 if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid 3968 + " package " + packageName + " flags: " 3969 + AppOpsManager.flagsToString(flags)); 3970 return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, 3971 packageName); 3972 } 3973 final Op op = getOpLocked(ops, code, uid, true); 3974 final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag); 3975 final UidState uidState = ops.uidState; 3976 isRestricted = isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass); 3977 final int switchCode = AppOpsManager.opToSwitch(code); 3978 // If there is a non-default per UID policy (we set UID op mode only if 3979 // non-default) it takes over, otherwise use the per package policy. 3980 if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) { 3981 final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode)); 3982 if (!shouldStartForMode(uidMode, startIfModeDefault)) { 3983 if (DEBUG) { 3984 Slog.d(TAG, "startOperation: uid reject #" + uidMode + " for code " 3985 + switchCode + " (" + code + ") uid " + uid + " package " 3986 + packageName + " flags: " + AppOpsManager.flagsToString(flags)); 3987 } 3988 if (!dryRun) { 3989 attributedOp.rejected(uidState.state, flags); 3990 scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag, 3991 flags, uidMode, startType, attributionFlags, attributionChainId); 3992 } 3993 return new SyncNotedAppOp(uidMode, code, attributionTag, packageName); 3994 } 3995 } else { 3996 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, uid, true) 3997 : op; 3998 final int mode = switchOp.evalMode(); 3999 if (mode != AppOpsManager.MODE_ALLOWED 4000 && (!startIfModeDefault || mode != MODE_DEFAULT)) { 4001 if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code " 4002 + switchCode + " (" + code + ") uid " + uid + " package " 4003 + packageName + " flags: " + AppOpsManager.flagsToString(flags)); 4004 if (!dryRun) { 4005 attributedOp.rejected(uidState.state, flags); 4006 scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag, 4007 flags, mode, startType, attributionFlags, attributionChainId); 4008 } 4009 return new SyncNotedAppOp(mode, code, attributionTag, packageName); 4010 } 4011 } 4012 if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid 4013 + " package " + packageName + " restricted: " + isRestricted 4014 + " flags: " + AppOpsManager.flagsToString(flags)); 4015 if (!dryRun) { 4016 try { 4017 if (isRestricted) { 4018 attributedOp.createPaused(clientId, proxyUid, proxyPackageName, 4019 proxyAttributionTag, uidState.state, flags, attributionFlags, 4020 attributionChainId); 4021 } else { 4022 attributedOp.started(clientId, proxyUid, proxyPackageName, 4023 proxyAttributionTag, uidState.state, flags, attributionFlags, 4024 attributionChainId); 4025 startType = START_TYPE_STARTED; 4026 } 4027 } catch (RemoteException e) { 4028 throw new RuntimeException(e); 4029 } 4030 scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag, flags, 4031 isRestricted ? MODE_IGNORED : MODE_ALLOWED, startType, attributionFlags, 4032 attributionChainId); 4033 } 4034 } 4035 4036 if (shouldCollectAsyncNotedOp && !dryRun && !isRestricted) { 4037 collectAsyncNotedOp(uid, packageName, code, attributionTag, AppOpsManager.OP_FLAG_SELF, 4038 message, shouldCollectMessage); 4039 } 4040 4041 return new SyncNotedAppOp(isRestricted ? MODE_IGNORED : MODE_ALLOWED, code, attributionTag, 4042 packageName); 4043 } 4044 4045 @Override finishOperation(IBinder clientId, int code, int uid, String packageName, String attributionTag)4046 public void finishOperation(IBinder clientId, int code, int uid, String packageName, 4047 String attributionTag) { 4048 mCheckOpsDelegateDispatcher.finishOperation(clientId, code, uid, packageName, 4049 attributionTag); 4050 } 4051 finishOperationImpl(IBinder clientId, int code, int uid, String packageName, String attributionTag)4052 private void finishOperationImpl(IBinder clientId, int code, int uid, String packageName, 4053 String attributionTag) { 4054 verifyIncomingUid(uid); 4055 verifyIncomingOp(code); 4056 verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); 4057 4058 String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); 4059 if (resolvedPackageName == null) { 4060 return; 4061 } 4062 4063 finishOperationUnchecked(clientId, code, uid, resolvedPackageName, attributionTag); 4064 } 4065 4066 @Override finishProxyOperation(int code, @NonNull AttributionSource attributionSource, boolean skipProxyOperation)4067 public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource, 4068 boolean skipProxyOperation) { 4069 mCheckOpsDelegateDispatcher.finishProxyOperation(code, attributionSource, 4070 skipProxyOperation); 4071 } 4072 finishProxyOperationImpl(int code, @NonNull AttributionSource attributionSource, boolean skipProxyOperation)4073 private Void finishProxyOperationImpl(int code, @NonNull AttributionSource attributionSource, 4074 boolean skipProxyOperation) { 4075 final int proxyUid = attributionSource.getUid(); 4076 final String proxyPackageName = attributionSource.getPackageName(); 4077 final String proxyAttributionTag = attributionSource.getAttributionTag(); 4078 final IBinder proxyToken = attributionSource.getToken(); 4079 final int proxiedUid = attributionSource.getNextUid(); 4080 final String proxiedPackageName = attributionSource.getNextPackageName(); 4081 final String proxiedAttributionTag = attributionSource.getNextAttributionTag(); 4082 final IBinder proxiedToken = attributionSource.getNextToken(); 4083 4084 skipProxyOperation = skipProxyOperation 4085 && isCallerAndAttributionTrusted(attributionSource); 4086 4087 verifyIncomingProxyUid(attributionSource); 4088 verifyIncomingOp(code); 4089 verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid)); 4090 verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid)); 4091 4092 String resolvedProxyPackageName = AppOpsManager.resolvePackageName(proxyUid, 4093 proxyPackageName); 4094 if (resolvedProxyPackageName == null) { 4095 return null; 4096 } 4097 4098 if (!skipProxyOperation) { 4099 finishOperationUnchecked(proxyToken, code, proxyUid, resolvedProxyPackageName, 4100 proxyAttributionTag); 4101 } 4102 4103 String resolvedProxiedPackageName = AppOpsManager.resolvePackageName(proxiedUid, 4104 proxiedPackageName); 4105 if (resolvedProxiedPackageName == null) { 4106 return null; 4107 } 4108 4109 finishOperationUnchecked(proxiedToken, code, proxiedUid, resolvedProxiedPackageName, 4110 proxiedAttributionTag); 4111 4112 return null; 4113 } 4114 finishOperationUnchecked(IBinder clientId, int code, int uid, String packageName, String attributionTag)4115 private void finishOperationUnchecked(IBinder clientId, int code, int uid, String packageName, 4116 String attributionTag) { 4117 PackageVerificationResult pvr; 4118 try { 4119 pvr = verifyAndGetBypass(uid, packageName, attributionTag); 4120 if (!pvr.isAttributionTagValid) { 4121 attributionTag = null; 4122 } 4123 } catch (SecurityException e) { 4124 Slog.e(TAG, "Cannot finishOperation", e); 4125 return; 4126 } 4127 4128 synchronized (this) { 4129 Op op = getOpLocked(code, uid, packageName, attributionTag, pvr.isAttributionTagValid, 4130 pvr.bypass, /* edit */ true); 4131 if (op == null) { 4132 Slog.e(TAG, "Operation not found: uid=" + uid + " pkg=" + packageName + "(" 4133 + attributionTag + ") op=" + AppOpsManager.opToName(code)); 4134 return; 4135 } 4136 final AttributedOp attributedOp = op.mAttributions.get(attributionTag); 4137 if (attributedOp == null) { 4138 Slog.e(TAG, "Attribution not found: uid=" + uid + " pkg=" + packageName + "(" 4139 + attributionTag + ") op=" + AppOpsManager.opToName(code)); 4140 return; 4141 } 4142 4143 if (attributedOp.isRunning() || attributedOp.isPaused()) { 4144 attributedOp.finished(clientId); 4145 } else { 4146 Slog.e(TAG, "Operation not started: uid=" + uid + " pkg=" + packageName + "(" 4147 + attributionTag + ") op=" + AppOpsManager.opToName(code)); 4148 } 4149 } 4150 } 4151 scheduleOpActiveChangedIfNeededLocked(int code, int uid, @NonNull String packageName, @Nullable String attributionTag, boolean active, @AttributionFlags int attributionFlags, int attributionChainId)4152 private void scheduleOpActiveChangedIfNeededLocked(int code, int uid, @NonNull 4153 String packageName, @Nullable String attributionTag, boolean active, @AttributionFlags 4154 int attributionFlags, int attributionChainId) { 4155 ArraySet<ActiveCallback> dispatchedCallbacks = null; 4156 final int callbackListCount = mActiveWatchers.size(); 4157 for (int i = 0; i < callbackListCount; i++) { 4158 final SparseArray<ActiveCallback> callbacks = mActiveWatchers.valueAt(i); 4159 ActiveCallback callback = callbacks.get(code); 4160 if (callback != null) { 4161 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 4162 continue; 4163 } 4164 if (dispatchedCallbacks == null) { 4165 dispatchedCallbacks = new ArraySet<>(); 4166 } 4167 dispatchedCallbacks.add(callback); 4168 } 4169 } 4170 if (dispatchedCallbacks == null) { 4171 return; 4172 } 4173 mHandler.sendMessage(PooledLambda.obtainMessage( 4174 AppOpsService::notifyOpActiveChanged, 4175 this, dispatchedCallbacks, code, uid, packageName, attributionTag, active, 4176 attributionFlags, attributionChainId)); 4177 } 4178 notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks, int code, int uid, @NonNull String packageName, @Nullable String attributionTag, boolean active, @AttributionFlags int attributionFlags, int attributionChainId)4179 private void notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks, 4180 int code, int uid, @NonNull String packageName, @Nullable String attributionTag, 4181 boolean active, @AttributionFlags int attributionFlags, int attributionChainId) { 4182 // There are features watching for mode changes such as window manager 4183 // and location manager which are in our process. The callbacks in these 4184 // features may require permissions our remote caller does not have. 4185 final long identity = Binder.clearCallingIdentity(); 4186 try { 4187 final int callbackCount = callbacks.size(); 4188 for (int i = 0; i < callbackCount; i++) { 4189 final ActiveCallback callback = callbacks.valueAt(i); 4190 try { 4191 callback.mCallback.opActiveChanged(code, uid, packageName, attributionTag, 4192 active, attributionFlags, attributionChainId); 4193 } catch (RemoteException e) { 4194 /* do nothing */ 4195 } 4196 } 4197 } finally { 4198 Binder.restoreCallingIdentity(identity); 4199 } 4200 } 4201 scheduleOpStartedIfNeededLocked(int code, int uid, String pkgName, String attributionTag, @OpFlags int flags, @Mode int result, @AppOpsManager.OnOpStartedListener.StartedType int startedType, @AttributionFlags int attributionFlags, int attributionChainId)4202 private void scheduleOpStartedIfNeededLocked(int code, int uid, String pkgName, 4203 String attributionTag, @OpFlags int flags, @Mode int result, 4204 @AppOpsManager.OnOpStartedListener.StartedType int startedType, 4205 @AttributionFlags int attributionFlags, int attributionChainId) { 4206 ArraySet<StartedCallback> dispatchedCallbacks = null; 4207 final int callbackListCount = mStartedWatchers.size(); 4208 for (int i = 0; i < callbackListCount; i++) { 4209 final SparseArray<StartedCallback> callbacks = mStartedWatchers.valueAt(i); 4210 4211 StartedCallback callback = callbacks.get(code); 4212 if (callback != null) { 4213 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 4214 continue; 4215 } 4216 4217 if (dispatchedCallbacks == null) { 4218 dispatchedCallbacks = new ArraySet<>(); 4219 } 4220 dispatchedCallbacks.add(callback); 4221 } 4222 } 4223 4224 if (dispatchedCallbacks == null) { 4225 return; 4226 } 4227 4228 mHandler.sendMessage(PooledLambda.obtainMessage( 4229 AppOpsService::notifyOpStarted, 4230 this, dispatchedCallbacks, code, uid, pkgName, attributionTag, flags, 4231 result, startedType, attributionFlags, attributionChainId)); 4232 } 4233 notifyOpStarted(ArraySet<StartedCallback> callbacks, int code, int uid, String packageName, String attributionTag, @OpFlags int flags, @Mode int result, @AppOpsManager.OnOpStartedListener.StartedType int startedType, @AttributionFlags int attributionFlags, int attributionChainId)4234 private void notifyOpStarted(ArraySet<StartedCallback> callbacks, 4235 int code, int uid, String packageName, String attributionTag, @OpFlags int flags, 4236 @Mode int result, @AppOpsManager.OnOpStartedListener.StartedType int startedType, 4237 @AttributionFlags int attributionFlags, int attributionChainId) { 4238 final long identity = Binder.clearCallingIdentity(); 4239 try { 4240 final int callbackCount = callbacks.size(); 4241 for (int i = 0; i < callbackCount; i++) { 4242 final StartedCallback callback = callbacks.valueAt(i); 4243 try { 4244 callback.mCallback.opStarted(code, uid, packageName, attributionTag, flags, 4245 result, startedType, attributionFlags, attributionChainId); 4246 } catch (RemoteException e) { 4247 /* do nothing */ 4248 } 4249 } 4250 } finally { 4251 Binder.restoreCallingIdentity(identity); 4252 } 4253 } 4254 scheduleOpNotedIfNeededLocked(int code, int uid, String packageName, String attributionTag, @OpFlags int flags, @Mode int result)4255 private void scheduleOpNotedIfNeededLocked(int code, int uid, String packageName, 4256 String attributionTag, @OpFlags int flags, @Mode int result) { 4257 ArraySet<NotedCallback> dispatchedCallbacks = null; 4258 final int callbackListCount = mNotedWatchers.size(); 4259 for (int i = 0; i < callbackListCount; i++) { 4260 final SparseArray<NotedCallback> callbacks = mNotedWatchers.valueAt(i); 4261 final NotedCallback callback = callbacks.get(code); 4262 if (callback != null) { 4263 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 4264 continue; 4265 } 4266 if (dispatchedCallbacks == null) { 4267 dispatchedCallbacks = new ArraySet<>(); 4268 } 4269 dispatchedCallbacks.add(callback); 4270 } 4271 } 4272 if (dispatchedCallbacks == null) { 4273 return; 4274 } 4275 mHandler.sendMessage(PooledLambda.obtainMessage( 4276 AppOpsService::notifyOpChecked, 4277 this, dispatchedCallbacks, code, uid, packageName, attributionTag, flags, 4278 result)); 4279 } 4280 notifyOpChecked(ArraySet<NotedCallback> callbacks, int code, int uid, String packageName, String attributionTag, @OpFlags int flags, @Mode int result)4281 private void notifyOpChecked(ArraySet<NotedCallback> callbacks, 4282 int code, int uid, String packageName, String attributionTag, @OpFlags int flags, 4283 @Mode int result) { 4284 // There are features watching for checks in our process. The callbacks in 4285 // these features may require permissions our remote caller does not have. 4286 final long identity = Binder.clearCallingIdentity(); 4287 try { 4288 final int callbackCount = callbacks.size(); 4289 for (int i = 0; i < callbackCount; i++) { 4290 final NotedCallback callback = callbacks.valueAt(i); 4291 try { 4292 callback.mCallback.opNoted(code, uid, packageName, attributionTag, flags, 4293 result); 4294 } catch (RemoteException e) { 4295 /* do nothing */ 4296 } 4297 } 4298 } finally { 4299 Binder.restoreCallingIdentity(identity); 4300 } 4301 } 4302 4303 @Override permissionToOpCode(String permission)4304 public int permissionToOpCode(String permission) { 4305 if (permission == null) { 4306 return AppOpsManager.OP_NONE; 4307 } 4308 return AppOpsManager.permissionToOpCode(permission); 4309 } 4310 4311 @Override shouldCollectNotes(int opCode)4312 public boolean shouldCollectNotes(int opCode) { 4313 Preconditions.checkArgumentInRange(opCode, 0, _NUM_OP - 1, "opCode"); 4314 4315 String perm = AppOpsManager.opToPermission(opCode); 4316 if (perm == null) { 4317 return false; 4318 } 4319 4320 PermissionInfo permInfo; 4321 try { 4322 permInfo = mContext.getPackageManager().getPermissionInfo(perm, 0); 4323 } catch (PackageManager.NameNotFoundException e) { 4324 return false; 4325 } 4326 4327 return permInfo.getProtection() == PROTECTION_DANGEROUS 4328 || (permInfo.getProtectionFlags() & PROTECTION_FLAG_APPOP) != 0; 4329 } 4330 verifyIncomingProxyUid(@onNull AttributionSource attributionSource)4331 private void verifyIncomingProxyUid(@NonNull AttributionSource attributionSource) { 4332 if (attributionSource.getUid() == Binder.getCallingUid()) { 4333 return; 4334 } 4335 if (Binder.getCallingPid() == Process.myPid()) { 4336 return; 4337 } 4338 if (attributionSource.isTrusted(mContext)) { 4339 return; 4340 } 4341 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 4342 Binder.getCallingPid(), Binder.getCallingUid(), null); 4343 } 4344 verifyIncomingUid(int uid)4345 private void verifyIncomingUid(int uid) { 4346 if (uid == Binder.getCallingUid()) { 4347 return; 4348 } 4349 if (Binder.getCallingPid() == Process.myPid()) { 4350 return; 4351 } 4352 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 4353 Binder.getCallingPid(), Binder.getCallingUid(), null); 4354 } 4355 verifyIncomingOp(int op)4356 private void verifyIncomingOp(int op) { 4357 if (op >= 0 && op < AppOpsManager._NUM_OP) { 4358 return; 4359 } 4360 throw new IllegalArgumentException("Bad operation #" + op); 4361 } 4362 verifyIncomingPackage(@ullable String packageName, @UserIdInt int userId)4363 private void verifyIncomingPackage(@Nullable String packageName, @UserIdInt int userId) { 4364 if (packageName != null && getPackageManagerInternal().filterAppAccess(packageName, 4365 Binder.getCallingUid(), userId)) { 4366 throw new IllegalArgumentException( 4367 packageName + " not found from " + Binder.getCallingUid()); 4368 } 4369 } 4370 isCallerAndAttributionTrusted(@onNull AttributionSource attributionSource)4371 private boolean isCallerAndAttributionTrusted(@NonNull AttributionSource attributionSource) { 4372 if (attributionSource.getUid() != Binder.getCallingUid() 4373 && attributionSource.isTrusted(mContext)) { 4374 return true; 4375 } 4376 return mContext.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 4377 Binder.getCallingPid(), Binder.getCallingUid(), null) 4378 == PackageManager.PERMISSION_GRANTED; 4379 } 4380 getUidStateLocked(int uid, boolean edit)4381 private @Nullable UidState getUidStateLocked(int uid, boolean edit) { 4382 UidState uidState = mUidStates.get(uid); 4383 if (uidState == null) { 4384 if (!edit) { 4385 return null; 4386 } 4387 uidState = new UidState(uid); 4388 mUidStates.put(uid, uidState); 4389 } else { 4390 updatePendingStateIfNeededLocked(uidState); 4391 } 4392 return uidState; 4393 } 4394 4395 /** 4396 * Check if the pending state should be updated and do so if needed 4397 * 4398 * @param uidState The uidState that might have a pending state 4399 */ updatePendingStateIfNeededLocked(@onNull UidState uidState)4400 private void updatePendingStateIfNeededLocked(@NonNull UidState uidState) { 4401 if (uidState != null) { 4402 if (uidState.pendingStateCommitTime != 0) { 4403 if (uidState.pendingStateCommitTime < mLastRealtime) { 4404 commitUidPendingStateLocked(uidState); 4405 } else { 4406 mLastRealtime = SystemClock.elapsedRealtime(); 4407 if (uidState.pendingStateCommitTime < mLastRealtime) { 4408 commitUidPendingStateLocked(uidState); 4409 } 4410 } 4411 } 4412 } 4413 } 4414 commitUidPendingStateLocked(UidState uidState)4415 private void commitUidPendingStateLocked(UidState uidState) { 4416 if (uidState.hasForegroundWatchers) { 4417 for (int fgi = uidState.foregroundOps.size() - 1; fgi >= 0; fgi--) { 4418 if (!uidState.foregroundOps.valueAt(fgi)) { 4419 continue; 4420 } 4421 final int code = uidState.foregroundOps.keyAt(fgi); 4422 // For location ops we consider fg state only if the fg service 4423 // is of location type, for all other ops any fg service will do. 4424 final long firstUnrestrictedUidState = resolveFirstUnrestrictedUidState(code); 4425 final boolean resolvedLastFg = uidState.state <= firstUnrestrictedUidState; 4426 final boolean resolvedNowFg = uidState.pendingState <= firstUnrestrictedUidState; 4427 if (resolvedLastFg == resolvedNowFg 4428 && uidState.capability == uidState.pendingCapability 4429 && uidState.appWidgetVisible == uidState.pendingAppWidgetVisible) { 4430 continue; 4431 } 4432 4433 if (uidState.opModes != null 4434 && uidState.opModes.indexOfKey(code) >= 0 4435 && uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND) { 4436 mHandler.sendMessage(PooledLambda.obtainMessage( 4437 AppOpsService::notifyOpChangedForAllPkgsInUid, 4438 this, code, uidState.uid, true, null)); 4439 } else if (uidState.pkgOps != null) { 4440 final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code); 4441 if (callbacks != null) { 4442 for (int cbi = callbacks.size() - 1; cbi >= 0; cbi--) { 4443 final ModeCallback callback = callbacks.valueAt(cbi); 4444 if ((callback.mFlags & AppOpsManager.WATCH_FOREGROUND_CHANGES) == 0 4445 || !callback.isWatchingUid(uidState.uid)) { 4446 continue; 4447 } 4448 for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) { 4449 final Op op = uidState.pkgOps.valueAt(pkgi).get(code); 4450 if (op == null) { 4451 continue; 4452 } 4453 if (op.mode == AppOpsManager.MODE_FOREGROUND) { 4454 mHandler.sendMessage(PooledLambda.obtainMessage( 4455 AppOpsService::notifyOpChanged, 4456 this, callback, code, uidState.uid, 4457 uidState.pkgOps.keyAt(pkgi))); 4458 } 4459 } 4460 } 4461 } 4462 } 4463 } 4464 } 4465 uidState.state = uidState.pendingState; 4466 uidState.capability = uidState.pendingCapability; 4467 uidState.appWidgetVisible = uidState.pendingAppWidgetVisible; 4468 uidState.pendingStateCommitTime = 0; 4469 } 4470 updateAppWidgetVisibility(SparseArray<String> uidPackageNames, boolean visible)4471 private void updateAppWidgetVisibility(SparseArray<String> uidPackageNames, boolean visible) { 4472 synchronized (this) { 4473 for (int i = uidPackageNames.size() - 1; i >= 0; i--) { 4474 final int uid = uidPackageNames.keyAt(i); 4475 final UidState uidState = getUidStateLocked(uid, true); 4476 if (uidState != null && (uidState.pendingAppWidgetVisible != visible)) { 4477 uidState.pendingAppWidgetVisible = visible; 4478 if (uidState.pendingAppWidgetVisible != uidState.appWidgetVisible) { 4479 commitUidPendingStateLocked(uidState); 4480 } 4481 } 4482 } 4483 } 4484 } 4485 4486 /** 4487 * @return {@link PackageManagerInternal} 4488 */ getPackageManagerInternal()4489 private @NonNull PackageManagerInternal getPackageManagerInternal() { 4490 if (mPackageManagerInternal == null) { 4491 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); 4492 } 4493 4494 return mPackageManagerInternal; 4495 } 4496 4497 /** 4498 * Create a restriction description matching the properties of the package. 4499 * 4500 * @param pkg The package to create the restriction description for 4501 * 4502 * @return The restriction matching the package 4503 */ getBypassforPackage(@onNull AndroidPackage pkg)4504 private RestrictionBypass getBypassforPackage(@NonNull AndroidPackage pkg) { 4505 return new RestrictionBypass(pkg.isPrivileged(), mContext.checkPermission( 4506 android.Manifest.permission.EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS, -1, pkg.getUid()) 4507 == PackageManager.PERMISSION_GRANTED); 4508 } 4509 4510 /** 4511 * @see #verifyAndGetBypass(int, String, String, String) 4512 */ verifyAndGetBypass(int uid, String packageName, @Nullable String attributionTag)4513 private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName, 4514 @Nullable String attributionTag) { 4515 return verifyAndGetBypass(uid, packageName, attributionTag, null); 4516 } 4517 4518 /** 4519 * Verify that package belongs to uid and return the {@link RestrictionBypass bypass 4520 * description} for the package, along with a boolean indicating whether the attribution tag is 4521 * valid. 4522 * 4523 * @param uid The uid the package belongs to 4524 * @param packageName The package the might belong to the uid 4525 * @param attributionTag attribution tag or {@code null} if no need to verify 4526 * @param proxyPackageName The proxy package, from which the attribution tag is to be pulled 4527 * 4528 * @return PackageVerificationResult containing {@link RestrictionBypass} and whether the 4529 * attribution tag is valid 4530 */ verifyAndGetBypass(int uid, String packageName, @Nullable String attributionTag, @Nullable String proxyPackageName)4531 private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName, 4532 @Nullable String attributionTag, @Nullable String proxyPackageName) { 4533 if (uid == Process.ROOT_UID) { 4534 // For backwards compatibility, don't check package name for root UID. 4535 return new PackageVerificationResult(null, 4536 /* isAttributionTagValid */ true); 4537 } 4538 4539 // Do not check if uid/packageName/attributionTag is already known. 4540 synchronized (this) { 4541 UidState uidState = mUidStates.get(uid); 4542 if (uidState != null && uidState.pkgOps != null) { 4543 Ops ops = uidState.pkgOps.get(packageName); 4544 4545 if (ops != null && (attributionTag == null || ops.knownAttributionTags.contains( 4546 attributionTag)) && ops.bypass != null) { 4547 return new PackageVerificationResult(ops.bypass, 4548 ops.validAttributionTags.contains(attributionTag)); 4549 } 4550 } 4551 } 4552 4553 int callingUid = Binder.getCallingUid(); 4554 4555 // Allow any attribution tag for resolvable uids 4556 int pkgUid; 4557 if (Objects.equals(packageName, "com.android.shell")) { 4558 // Special case for the shell which is a package but should be able 4559 // to bypass app attribution tag restrictions. 4560 pkgUid = Process.SHELL_UID; 4561 } else { 4562 pkgUid = resolveUid(packageName); 4563 } 4564 if (pkgUid != Process.INVALID_UID) { 4565 if (pkgUid != UserHandle.getAppId(uid)) { 4566 String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not"; 4567 throw new SecurityException("Specified package " + packageName + " under uid " 4568 + UserHandle.getAppId(uid) + otherUidMessage); 4569 } 4570 return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED, 4571 /* isAttributionTagValid */ true); 4572 } 4573 4574 int userId = UserHandle.getUserId(uid); 4575 RestrictionBypass bypass = null; 4576 boolean isAttributionTagValid = false; 4577 4578 final long ident = Binder.clearCallingIdentity(); 4579 try { 4580 PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); 4581 AndroidPackage pkg = pmInt.getPackage(packageName); 4582 if (pkg != null) { 4583 isAttributionTagValid = isAttributionInPackage(pkg, attributionTag); 4584 pkgUid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid())); 4585 bypass = getBypassforPackage(pkg); 4586 } 4587 if (!isAttributionTagValid) { 4588 AndroidPackage proxyPkg = proxyPackageName != null 4589 ? pmInt.getPackage(proxyPackageName) : null; 4590 // Re-check in proxy. 4591 isAttributionTagValid = isAttributionInPackage(proxyPkg, attributionTag); 4592 String msg; 4593 if (pkg != null && isAttributionTagValid) { 4594 msg = "attributionTag " + attributionTag + " declared in manifest of the proxy" 4595 + " package " + proxyPackageName + ", this is not advised"; 4596 } else if (pkg != null) { 4597 msg = "attributionTag " + attributionTag + " not declared in manifest of " 4598 + packageName; 4599 } else { 4600 msg = "package " + packageName + " not found, can't check for " 4601 + "attributionTag " + attributionTag; 4602 } 4603 4604 try { 4605 if (!mPlatformCompat.isChangeEnabledByPackageName( 4606 SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, packageName, 4607 userId) || !mPlatformCompat.isChangeEnabledByUid( 4608 SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, 4609 callingUid)) { 4610 // Do not override tags if overriding is not enabled for this package 4611 isAttributionTagValid = true; 4612 } 4613 Slog.e(TAG, msg); 4614 } catch (RemoteException neverHappens) { 4615 } 4616 } 4617 } finally { 4618 Binder.restoreCallingIdentity(ident); 4619 } 4620 4621 if (pkgUid != uid) { 4622 String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not"; 4623 throw new SecurityException("Specified package " + packageName + " under uid " + uid 4624 + otherUidMessage); 4625 } 4626 4627 return new PackageVerificationResult(bypass, isAttributionTagValid); 4628 } 4629 isAttributionInPackage(@ullable AndroidPackage pkg, @Nullable String attributionTag)4630 private boolean isAttributionInPackage(@Nullable AndroidPackage pkg, 4631 @Nullable String attributionTag) { 4632 if (pkg == null) { 4633 return false; 4634 } else if (attributionTag == null) { 4635 return true; 4636 } 4637 if (pkg.getAttributions() != null) { 4638 int numAttributions = pkg.getAttributions().size(); 4639 for (int i = 0; i < numAttributions; i++) { 4640 if (pkg.getAttributions().get(i).tag.equals(attributionTag)) { 4641 return true; 4642 } 4643 } 4644 } 4645 4646 return false; 4647 } 4648 4649 /** 4650 * Get (and potentially create) ops. 4651 * 4652 * @param uid The uid the package belongs to 4653 * @param packageName The name of the package 4654 * @param attributionTag attribution tag 4655 * @param isAttributionTagValid whether the given attribution tag is valid 4656 * @param bypass When to bypass certain op restrictions (can be null if edit == false) 4657 * @param edit If an ops does not exist, create the ops? 4658 4659 * @return The ops 4660 */ getOpsLocked(int uid, String packageName, @Nullable String attributionTag, boolean isAttributionTagValid, @Nullable RestrictionBypass bypass, boolean edit)4661 private Ops getOpsLocked(int uid, String packageName, @Nullable String attributionTag, 4662 boolean isAttributionTagValid, @Nullable RestrictionBypass bypass, boolean edit) { 4663 UidState uidState = getUidStateLocked(uid, edit); 4664 if (uidState == null) { 4665 return null; 4666 } 4667 4668 if (uidState.pkgOps == null) { 4669 if (!edit) { 4670 return null; 4671 } 4672 uidState.pkgOps = new ArrayMap<>(); 4673 } 4674 4675 Ops ops = uidState.pkgOps.get(packageName); 4676 if (ops == null) { 4677 if (!edit) { 4678 return null; 4679 } 4680 ops = new Ops(packageName, uidState); 4681 uidState.pkgOps.put(packageName, ops); 4682 } 4683 4684 if (edit) { 4685 if (bypass != null) { 4686 ops.bypass = bypass; 4687 } 4688 4689 if (attributionTag != null) { 4690 ops.knownAttributionTags.add(attributionTag); 4691 if (isAttributionTagValid) { 4692 ops.validAttributionTags.add(attributionTag); 4693 } else { 4694 ops.validAttributionTags.remove(attributionTag); 4695 } 4696 } 4697 } 4698 4699 return ops; 4700 } 4701 scheduleWriteLocked()4702 private void scheduleWriteLocked() { 4703 if (!mWriteScheduled) { 4704 mWriteScheduled = true; 4705 mHandler.postDelayed(mWriteRunner, WRITE_DELAY); 4706 } 4707 } 4708 scheduleFastWriteLocked()4709 private void scheduleFastWriteLocked() { 4710 if (!mFastWriteScheduled) { 4711 mWriteScheduled = true; 4712 mFastWriteScheduled = true; 4713 mHandler.removeCallbacks(mWriteRunner); 4714 mHandler.postDelayed(mWriteRunner, 10*1000); 4715 } 4716 } 4717 4718 /** 4719 * Get the state of an op for a uid. 4720 * 4721 * @param code The code of the op 4722 * @param uid The uid the of the package 4723 * @param packageName The package name for which to get the state for 4724 * @param attributionTag The attribution tag 4725 * @param isAttributionTagValid Whether the given attribution tag is valid 4726 * @param bypass When to bypass certain op restrictions (can be null if edit == false) 4727 * @param edit Iff {@code true} create the {@link Op} object if not yet created 4728 * 4729 * @return The {@link Op state} of the op 4730 */ getOpLocked(int code, int uid, @NonNull String packageName, @Nullable String attributionTag, boolean isAttributionTagValid, @Nullable RestrictionBypass bypass, boolean edit)4731 private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName, 4732 @Nullable String attributionTag, boolean isAttributionTagValid, 4733 @Nullable RestrictionBypass bypass, boolean edit) { 4734 Ops ops = getOpsLocked(uid, packageName, attributionTag, isAttributionTagValid, bypass, 4735 edit); 4736 if (ops == null) { 4737 return null; 4738 } 4739 return getOpLocked(ops, code, uid, edit); 4740 } 4741 getOpLocked(Ops ops, int code, int uid, boolean edit)4742 private Op getOpLocked(Ops ops, int code, int uid, boolean edit) { 4743 Op op = ops.get(code); 4744 if (op == null) { 4745 if (!edit) { 4746 return null; 4747 } 4748 op = new Op(ops.uidState, ops.packageName, code, uid); 4749 ops.put(code, op); 4750 } 4751 if (edit) { 4752 scheduleWriteLocked(); 4753 } 4754 return op; 4755 } 4756 isOpRestrictedDueToSuspend(int code, String packageName, int uid)4757 private boolean isOpRestrictedDueToSuspend(int code, String packageName, int uid) { 4758 if (!ArrayUtils.contains(OPS_RESTRICTED_ON_SUSPEND, code)) { 4759 return false; 4760 } 4761 final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); 4762 return pmi.isPackageSuspended(packageName, UserHandle.getUserId(uid)); 4763 } 4764 isOpRestrictedLocked(int uid, int code, String packageName, String attributionTag, @Nullable RestrictionBypass appBypass)4765 private boolean isOpRestrictedLocked(int uid, int code, String packageName, 4766 String attributionTag, @Nullable RestrictionBypass appBypass) { 4767 int restrictionSetCount = mOpGlobalRestrictions.size(); 4768 4769 for (int i = 0; i < restrictionSetCount; i++) { 4770 ClientGlobalRestrictionState restrictionState = mOpGlobalRestrictions.valueAt(i); 4771 if (restrictionState.hasRestriction(code)) { 4772 return true; 4773 } 4774 } 4775 4776 int userHandle = UserHandle.getUserId(uid); 4777 restrictionSetCount = mOpUserRestrictions.size(); 4778 4779 for (int i = 0; i < restrictionSetCount; i++) { 4780 // For each client, check that the given op is not restricted, or that the given 4781 // package is exempt from the restriction. 4782 ClientUserRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); 4783 if (restrictionState.hasRestriction(code, packageName, attributionTag, userHandle)) { 4784 RestrictionBypass opBypass = opAllowSystemBypassRestriction(code); 4785 if (opBypass != null) { 4786 // If we are the system, bypass user restrictions for certain codes 4787 synchronized (this) { 4788 if (opBypass.isPrivileged && appBypass != null && appBypass.isPrivileged) { 4789 return false; 4790 } 4791 if (opBypass.isRecordAudioRestrictionExcept && appBypass != null 4792 && appBypass.isRecordAudioRestrictionExcept) { 4793 return false; 4794 } 4795 } 4796 } 4797 return true; 4798 } 4799 } 4800 return false; 4801 } 4802 readState()4803 void readState() { 4804 int oldVersion = NO_VERSION; 4805 synchronized (mFile) { 4806 synchronized (this) { 4807 FileInputStream stream; 4808 try { 4809 stream = mFile.openRead(); 4810 } catch (FileNotFoundException e) { 4811 Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty"); 4812 return; 4813 } 4814 boolean success = false; 4815 mUidStates.clear(); 4816 try { 4817 TypedXmlPullParser parser = Xml.resolvePullParser(stream); 4818 int type; 4819 while ((type = parser.next()) != XmlPullParser.START_TAG 4820 && type != XmlPullParser.END_DOCUMENT) { 4821 ; 4822 } 4823 4824 if (type != XmlPullParser.START_TAG) { 4825 throw new IllegalStateException("no start tag found"); 4826 } 4827 4828 oldVersion = parser.getAttributeInt(null, "v", NO_VERSION); 4829 4830 int outerDepth = parser.getDepth(); 4831 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 4832 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 4833 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 4834 continue; 4835 } 4836 4837 String tagName = parser.getName(); 4838 if (tagName.equals("pkg")) { 4839 readPackage(parser); 4840 } else if (tagName.equals("uid")) { 4841 readUidOps(parser); 4842 } else { 4843 Slog.w(TAG, "Unknown element under <app-ops>: " 4844 + parser.getName()); 4845 XmlUtils.skipCurrentTag(parser); 4846 } 4847 } 4848 success = true; 4849 } catch (IllegalStateException e) { 4850 Slog.w(TAG, "Failed parsing " + e); 4851 } catch (NullPointerException e) { 4852 Slog.w(TAG, "Failed parsing " + e); 4853 } catch (NumberFormatException e) { 4854 Slog.w(TAG, "Failed parsing " + e); 4855 } catch (XmlPullParserException e) { 4856 Slog.w(TAG, "Failed parsing " + e); 4857 } catch (IOException e) { 4858 Slog.w(TAG, "Failed parsing " + e); 4859 } catch (IndexOutOfBoundsException e) { 4860 Slog.w(TAG, "Failed parsing " + e); 4861 } finally { 4862 if (!success) { 4863 mUidStates.clear(); 4864 } 4865 try { 4866 stream.close(); 4867 } catch (IOException e) { 4868 } 4869 } 4870 } 4871 } 4872 synchronized (this) { 4873 upgradeLocked(oldVersion); 4874 } 4875 } 4876 upgradeRunAnyInBackgroundLocked()4877 private void upgradeRunAnyInBackgroundLocked() { 4878 for (int i = 0; i < mUidStates.size(); i++) { 4879 final UidState uidState = mUidStates.valueAt(i); 4880 if (uidState == null) { 4881 continue; 4882 } 4883 if (uidState.opModes != null) { 4884 final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND); 4885 if (idx >= 0) { 4886 uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, 4887 uidState.opModes.valueAt(idx)); 4888 } 4889 } 4890 if (uidState.pkgOps == null) { 4891 continue; 4892 } 4893 boolean changed = false; 4894 for (int j = 0; j < uidState.pkgOps.size(); j++) { 4895 Ops ops = uidState.pkgOps.valueAt(j); 4896 if (ops != null) { 4897 final Op op = ops.get(AppOpsManager.OP_RUN_IN_BACKGROUND); 4898 if (op != null && op.mode != AppOpsManager.opToDefaultMode(op.op)) { 4899 final Op copy = new Op(op.uidState, op.packageName, 4900 AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uidState.uid); 4901 copy.mode = op.mode; 4902 ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy); 4903 changed = true; 4904 } 4905 } 4906 } 4907 if (changed) { 4908 uidState.evalForegroundOps(mOpModeWatchers); 4909 } 4910 } 4911 } 4912 upgradeLocked(int oldVersion)4913 private void upgradeLocked(int oldVersion) { 4914 if (oldVersion >= CURRENT_VERSION) { 4915 return; 4916 } 4917 Slog.d(TAG, "Upgrading app-ops xml from version " + oldVersion + " to " + CURRENT_VERSION); 4918 switch (oldVersion) { 4919 case NO_VERSION: 4920 upgradeRunAnyInBackgroundLocked(); 4921 // fall through 4922 case 1: 4923 // for future upgrades 4924 } 4925 scheduleFastWriteLocked(); 4926 } 4927 readUidOps(TypedXmlPullParser parser)4928 private void readUidOps(TypedXmlPullParser parser) throws NumberFormatException, 4929 XmlPullParserException, IOException { 4930 final int uid = parser.getAttributeInt(null, "n"); 4931 int outerDepth = parser.getDepth(); 4932 int type; 4933 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 4934 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 4935 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 4936 continue; 4937 } 4938 4939 String tagName = parser.getName(); 4940 if (tagName.equals("op")) { 4941 final int code = parser.getAttributeInt(null, "n"); 4942 final int mode = parser.getAttributeInt(null, "m"); 4943 setUidMode(code, uid, mode); 4944 } else { 4945 Slog.w(TAG, "Unknown element under <uid-ops>: " 4946 + parser.getName()); 4947 XmlUtils.skipCurrentTag(parser); 4948 } 4949 } 4950 } 4951 readPackage(TypedXmlPullParser parser)4952 private void readPackage(TypedXmlPullParser parser) 4953 throws NumberFormatException, XmlPullParserException, IOException { 4954 String pkgName = parser.getAttributeValue(null, "n"); 4955 int outerDepth = parser.getDepth(); 4956 int type; 4957 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 4958 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 4959 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 4960 continue; 4961 } 4962 4963 String tagName = parser.getName(); 4964 if (tagName.equals("uid")) { 4965 readUid(parser, pkgName); 4966 } else { 4967 Slog.w(TAG, "Unknown element under <pkg>: " 4968 + parser.getName()); 4969 XmlUtils.skipCurrentTag(parser); 4970 } 4971 } 4972 } 4973 readUid(TypedXmlPullParser parser, String pkgName)4974 private void readUid(TypedXmlPullParser parser, String pkgName) 4975 throws NumberFormatException, XmlPullParserException, IOException { 4976 int uid = parser.getAttributeInt(null, "n"); 4977 final UidState uidState = getUidStateLocked(uid, true); 4978 int outerDepth = parser.getDepth(); 4979 int type; 4980 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 4981 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 4982 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 4983 continue; 4984 } 4985 String tagName = parser.getName(); 4986 if (tagName.equals("op")) { 4987 readOp(parser, uidState, pkgName); 4988 } else { 4989 Slog.w(TAG, "Unknown element under <pkg>: " 4990 + parser.getName()); 4991 XmlUtils.skipCurrentTag(parser); 4992 } 4993 } 4994 uidState.evalForegroundOps(mOpModeWatchers); 4995 } 4996 readAttributionOp(TypedXmlPullParser parser, @NonNull Op parent, @Nullable String attribution)4997 private void readAttributionOp(TypedXmlPullParser parser, @NonNull Op parent, 4998 @Nullable String attribution) 4999 throws NumberFormatException, IOException, XmlPullParserException { 5000 final AttributedOp attributedOp = parent.getOrCreateAttribution(parent, attribution); 5001 5002 final long key = parser.getAttributeLong(null, "n"); 5003 final int uidState = extractUidStateFromKey(key); 5004 final int opFlags = extractFlagsFromKey(key); 5005 5006 final long accessTime = parser.getAttributeLong(null, "t", 0); 5007 final long rejectTime = parser.getAttributeLong(null, "r", 0); 5008 final long accessDuration = parser.getAttributeLong(null, "d", -1); 5009 final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp"); 5010 final int proxyUid = parser.getAttributeInt(null, "pu", Process.INVALID_UID); 5011 final String proxyAttributionTag = XmlUtils.readStringAttribute(parser, "pc"); 5012 5013 if (accessTime > 0) { 5014 attributedOp.accessed(accessTime, accessDuration, proxyUid, proxyPkg, 5015 proxyAttributionTag, uidState, opFlags); 5016 } 5017 if (rejectTime > 0) { 5018 attributedOp.rejected(rejectTime, uidState, opFlags); 5019 } 5020 } 5021 readOp(TypedXmlPullParser parser, @NonNull UidState uidState, @NonNull String pkgName)5022 private void readOp(TypedXmlPullParser parser, 5023 @NonNull UidState uidState, @NonNull String pkgName) 5024 throws NumberFormatException, XmlPullParserException, IOException { 5025 int opCode = parser.getAttributeInt(null, "n"); 5026 Op op = new Op(uidState, pkgName, opCode, uidState.uid); 5027 5028 final int mode = parser.getAttributeInt(null, "m", AppOpsManager.opToDefaultMode(op.op)); 5029 op.mode = mode; 5030 5031 int outerDepth = parser.getDepth(); 5032 int type; 5033 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 5034 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 5035 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 5036 continue; 5037 } 5038 String tagName = parser.getName(); 5039 if (tagName.equals("st")) { 5040 readAttributionOp(parser, op, XmlUtils.readStringAttribute(parser, "id")); 5041 } else { 5042 Slog.w(TAG, "Unknown element under <op>: " 5043 + parser.getName()); 5044 XmlUtils.skipCurrentTag(parser); 5045 } 5046 } 5047 5048 if (uidState.pkgOps == null) { 5049 uidState.pkgOps = new ArrayMap<>(); 5050 } 5051 Ops ops = uidState.pkgOps.get(pkgName); 5052 if (ops == null) { 5053 ops = new Ops(pkgName, uidState); 5054 uidState.pkgOps.put(pkgName, ops); 5055 } 5056 ops.put(op.op, op); 5057 } 5058 writeState()5059 void writeState() { 5060 synchronized (mFile) { 5061 FileOutputStream stream; 5062 try { 5063 stream = mFile.startWrite(); 5064 } catch (IOException e) { 5065 Slog.w(TAG, "Failed to write state: " + e); 5066 return; 5067 } 5068 5069 List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null); 5070 5071 try { 5072 TypedXmlSerializer out = Xml.resolveSerializer(stream); 5073 out.startDocument(null, true); 5074 out.startTag(null, "app-ops"); 5075 out.attributeInt(null, "v", CURRENT_VERSION); 5076 5077 SparseArray<SparseIntArray> uidStatesClone; 5078 synchronized (this) { 5079 uidStatesClone = new SparseArray<>(mUidStates.size()); 5080 5081 final int uidStateCount = mUidStates.size(); 5082 for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) { 5083 UidState uidState = mUidStates.valueAt(uidStateNum); 5084 int uid = mUidStates.keyAt(uidStateNum); 5085 5086 SparseIntArray opModes = uidState.opModes; 5087 if (opModes != null && opModes.size() > 0) { 5088 uidStatesClone.put(uid, new SparseIntArray(opModes.size())); 5089 5090 final int opCount = opModes.size(); 5091 for (int opCountNum = 0; opCountNum < opCount; opCountNum++) { 5092 uidStatesClone.get(uid).put( 5093 opModes.keyAt(opCountNum), 5094 opModes.valueAt(opCountNum)); 5095 } 5096 } 5097 } 5098 } 5099 5100 final int uidStateCount = uidStatesClone.size(); 5101 for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) { 5102 SparseIntArray opModes = uidStatesClone.valueAt(uidStateNum); 5103 if (opModes != null && opModes.size() > 0) { 5104 out.startTag(null, "uid"); 5105 out.attributeInt(null, "n", uidStatesClone.keyAt(uidStateNum)); 5106 final int opCount = opModes.size(); 5107 for (int opCountNum = 0; opCountNum < opCount; opCountNum++) { 5108 final int op = opModes.keyAt(opCountNum); 5109 final int mode = opModes.valueAt(opCountNum); 5110 out.startTag(null, "op"); 5111 out.attributeInt(null, "n", op); 5112 out.attributeInt(null, "m", mode); 5113 out.endTag(null, "op"); 5114 } 5115 out.endTag(null, "uid"); 5116 } 5117 } 5118 5119 if (allOps != null) { 5120 String lastPkg = null; 5121 for (int i=0; i<allOps.size(); i++) { 5122 AppOpsManager.PackageOps pkg = allOps.get(i); 5123 if (!Objects.equals(pkg.getPackageName(), lastPkg)) { 5124 if (lastPkg != null) { 5125 out.endTag(null, "pkg"); 5126 } 5127 lastPkg = pkg.getPackageName(); 5128 if (lastPkg != null) { 5129 out.startTag(null, "pkg"); 5130 out.attribute(null, "n", lastPkg); 5131 } 5132 } 5133 out.startTag(null, "uid"); 5134 out.attributeInt(null, "n", pkg.getUid()); 5135 List<AppOpsManager.OpEntry> ops = pkg.getOps(); 5136 for (int j=0; j<ops.size(); j++) { 5137 AppOpsManager.OpEntry op = ops.get(j); 5138 out.startTag(null, "op"); 5139 out.attributeInt(null, "n", op.getOp()); 5140 if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) { 5141 out.attributeInt(null, "m", op.getMode()); 5142 } 5143 5144 for (String attributionTag : op.getAttributedOpEntries().keySet()) { 5145 final AttributedOpEntry attribution = 5146 op.getAttributedOpEntries().get(attributionTag); 5147 5148 final ArraySet<Long> keys = attribution.collectKeys(); 5149 5150 final int keyCount = keys.size(); 5151 for (int k = 0; k < keyCount; k++) { 5152 final long key = keys.valueAt(k); 5153 5154 final int uidState = AppOpsManager.extractUidStateFromKey(key); 5155 final int flags = AppOpsManager.extractFlagsFromKey(key); 5156 5157 final long accessTime = attribution.getLastAccessTime(uidState, 5158 uidState, flags); 5159 final long rejectTime = attribution.getLastRejectTime(uidState, 5160 uidState, flags); 5161 final long accessDuration = attribution.getLastDuration( 5162 uidState, uidState, flags); 5163 // Proxy information for rejections is not backed up 5164 final OpEventProxyInfo proxy = attribution.getLastProxyInfo( 5165 uidState, uidState, flags); 5166 5167 if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0 5168 && proxy == null) { 5169 continue; 5170 } 5171 5172 String proxyPkg = null; 5173 String proxyAttributionTag = null; 5174 int proxyUid = Process.INVALID_UID; 5175 if (proxy != null) { 5176 proxyPkg = proxy.getPackageName(); 5177 proxyAttributionTag = proxy.getAttributionTag(); 5178 proxyUid = proxy.getUid(); 5179 } 5180 5181 out.startTag(null, "st"); 5182 if (attributionTag != null) { 5183 out.attribute(null, "id", attributionTag); 5184 } 5185 out.attributeLong(null, "n", key); 5186 if (accessTime > 0) { 5187 out.attributeLong(null, "t", accessTime); 5188 } 5189 if (rejectTime > 0) { 5190 out.attributeLong(null, "r", rejectTime); 5191 } 5192 if (accessDuration > 0) { 5193 out.attributeLong(null, "d", accessDuration); 5194 } 5195 if (proxyPkg != null) { 5196 out.attribute(null, "pp", proxyPkg); 5197 } 5198 if (proxyAttributionTag != null) { 5199 out.attribute(null, "pc", proxyAttributionTag); 5200 } 5201 if (proxyUid >= 0) { 5202 out.attributeInt(null, "pu", proxyUid); 5203 } 5204 out.endTag(null, "st"); 5205 } 5206 } 5207 5208 out.endTag(null, "op"); 5209 } 5210 out.endTag(null, "uid"); 5211 } 5212 if (lastPkg != null) { 5213 out.endTag(null, "pkg"); 5214 } 5215 } 5216 5217 out.endTag(null, "app-ops"); 5218 out.endDocument(); 5219 mFile.finishWrite(stream); 5220 } catch (IOException e) { 5221 Slog.w(TAG, "Failed to write state, restoring backup.", e); 5222 mFile.failWrite(stream); 5223 } 5224 } 5225 mHistoricalRegistry.writeAndClearDiscreteHistory(); 5226 } 5227 5228 static class Shell extends ShellCommand { 5229 final IAppOpsService mInterface; 5230 final AppOpsService mInternal; 5231 5232 int userId = UserHandle.USER_SYSTEM; 5233 String packageName; 5234 String attributionTag; 5235 String opStr; 5236 String modeStr; 5237 int op; 5238 int mode; 5239 int packageUid; 5240 int nonpackageUid; 5241 final static Binder sBinder = new Binder(); 5242 IBinder mToken; 5243 boolean targetsUid; 5244 Shell(IAppOpsService iface, AppOpsService internal)5245 Shell(IAppOpsService iface, AppOpsService internal) { 5246 mInterface = iface; 5247 mInternal = internal; 5248 mToken = AppOpsManager.getClientId(); 5249 } 5250 5251 @Override onCommand(String cmd)5252 public int onCommand(String cmd) { 5253 return onShellCommand(this, cmd); 5254 } 5255 5256 @Override onHelp()5257 public void onHelp() { 5258 PrintWriter pw = getOutPrintWriter(); 5259 dumpCommandHelp(pw); 5260 } 5261 strOpToOp(String op, PrintWriter err)5262 static private int strOpToOp(String op, PrintWriter err) { 5263 try { 5264 return AppOpsManager.strOpToOp(op); 5265 } catch (IllegalArgumentException e) { 5266 } 5267 try { 5268 return Integer.parseInt(op); 5269 } catch (NumberFormatException e) { 5270 } 5271 try { 5272 return AppOpsManager.strDebugOpToOp(op); 5273 } catch (IllegalArgumentException e) { 5274 err.println("Error: " + e.getMessage()); 5275 return -1; 5276 } 5277 } 5278 strModeToMode(String modeStr, PrintWriter err)5279 static int strModeToMode(String modeStr, PrintWriter err) { 5280 for (int i = AppOpsManager.MODE_NAMES.length - 1; i >= 0; i--) { 5281 if (AppOpsManager.MODE_NAMES[i].equals(modeStr)) { 5282 return i; 5283 } 5284 } 5285 try { 5286 return Integer.parseInt(modeStr); 5287 } catch (NumberFormatException e) { 5288 } 5289 err.println("Error: Mode " + modeStr + " is not valid"); 5290 return -1; 5291 } 5292 parseUserOpMode(int defMode, PrintWriter err)5293 int parseUserOpMode(int defMode, PrintWriter err) throws RemoteException { 5294 userId = UserHandle.USER_CURRENT; 5295 opStr = null; 5296 modeStr = null; 5297 for (String argument; (argument = getNextArg()) != null;) { 5298 if ("--user".equals(argument)) { 5299 userId = UserHandle.parseUserArg(getNextArgRequired()); 5300 } else { 5301 if (opStr == null) { 5302 opStr = argument; 5303 } else if (modeStr == null) { 5304 modeStr = argument; 5305 break; 5306 } 5307 } 5308 } 5309 if (opStr == null) { 5310 err.println("Error: Operation not specified."); 5311 return -1; 5312 } 5313 op = strOpToOp(opStr, err); 5314 if (op < 0) { 5315 return -1; 5316 } 5317 if (modeStr != null) { 5318 if ((mode=strModeToMode(modeStr, err)) < 0) { 5319 return -1; 5320 } 5321 } else { 5322 mode = defMode; 5323 } 5324 return 0; 5325 } 5326 parseUserPackageOp(boolean reqOp, PrintWriter err)5327 int parseUserPackageOp(boolean reqOp, PrintWriter err) throws RemoteException { 5328 userId = UserHandle.USER_CURRENT; 5329 packageName = null; 5330 opStr = null; 5331 for (String argument; (argument = getNextArg()) != null;) { 5332 if ("--user".equals(argument)) { 5333 userId = UserHandle.parseUserArg(getNextArgRequired()); 5334 } else if ("--uid".equals(argument)) { 5335 targetsUid = true; 5336 } else if ("--attribution".equals(argument)) { 5337 attributionTag = getNextArgRequired(); 5338 } else { 5339 if (packageName == null) { 5340 packageName = argument; 5341 } else if (opStr == null) { 5342 opStr = argument; 5343 break; 5344 } 5345 } 5346 } 5347 if (packageName == null) { 5348 err.println("Error: Package name not specified."); 5349 return -1; 5350 } else if (opStr == null && reqOp) { 5351 err.println("Error: Operation not specified."); 5352 return -1; 5353 } 5354 if (opStr != null) { 5355 op = strOpToOp(opStr, err); 5356 if (op < 0) { 5357 return -1; 5358 } 5359 } else { 5360 op = AppOpsManager.OP_NONE; 5361 } 5362 if (userId == UserHandle.USER_CURRENT) { 5363 userId = ActivityManager.getCurrentUser(); 5364 } 5365 nonpackageUid = -1; 5366 try { 5367 nonpackageUid = Integer.parseInt(packageName); 5368 } catch (NumberFormatException e) { 5369 } 5370 if (nonpackageUid == -1 && packageName.length() > 1 && packageName.charAt(0) == 'u' 5371 && packageName.indexOf('.') < 0) { 5372 int i = 1; 5373 while (i < packageName.length() && packageName.charAt(i) >= '0' 5374 && packageName.charAt(i) <= '9') { 5375 i++; 5376 } 5377 if (i > 1 && i < packageName.length()) { 5378 String userStr = packageName.substring(1, i); 5379 try { 5380 int user = Integer.parseInt(userStr); 5381 char type = packageName.charAt(i); 5382 i++; 5383 int startTypeVal = i; 5384 while (i < packageName.length() && packageName.charAt(i) >= '0' 5385 && packageName.charAt(i) <= '9') { 5386 i++; 5387 } 5388 if (i > startTypeVal) { 5389 String typeValStr = packageName.substring(startTypeVal, i); 5390 try { 5391 int typeVal = Integer.parseInt(typeValStr); 5392 if (type == 'a') { 5393 nonpackageUid = UserHandle.getUid(user, 5394 typeVal + Process.FIRST_APPLICATION_UID); 5395 } else if (type == 's') { 5396 nonpackageUid = UserHandle.getUid(user, typeVal); 5397 } 5398 } catch (NumberFormatException e) { 5399 } 5400 } 5401 } catch (NumberFormatException e) { 5402 } 5403 } 5404 } 5405 if (nonpackageUid != -1) { 5406 packageName = null; 5407 } else { 5408 packageUid = resolveUid(packageName); 5409 if (packageUid < 0) { 5410 packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, 5411 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); 5412 } 5413 if (packageUid < 0) { 5414 err.println("Error: No UID for " + packageName + " in user " + userId); 5415 return -1; 5416 } 5417 } 5418 return 0; 5419 } 5420 } 5421 onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)5422 @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, 5423 FileDescriptor err, String[] args, ShellCallback callback, 5424 ResultReceiver resultReceiver) { 5425 (new Shell(this, this)).exec(this, in, out, err, args, callback, resultReceiver); 5426 } 5427 dumpCommandHelp(PrintWriter pw)5428 static void dumpCommandHelp(PrintWriter pw) { 5429 pw.println("AppOps service (appops) commands:"); 5430 pw.println(" help"); 5431 pw.println(" Print this help text."); 5432 pw.println(" start [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> " 5433 + "<OP> "); 5434 pw.println(" Starts a given operation for a particular application."); 5435 pw.println(" stop [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> " 5436 + "<OP> "); 5437 pw.println(" Stops a given operation for a particular application."); 5438 pw.println(" set [--user <USER_ID>] <[--uid] PACKAGE | UID> <OP> <MODE>"); 5439 pw.println(" Set the mode for a particular application and operation."); 5440 pw.println(" get [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> " 5441 + "[<OP>]"); 5442 pw.println(" Return the mode for a particular application and optional operation."); 5443 pw.println(" query-op [--user <USER_ID>] <OP> [<MODE>]"); 5444 pw.println(" Print all packages that currently have the given op in the given mode."); 5445 pw.println(" reset [--user <USER_ID>] [<PACKAGE>]"); 5446 pw.println(" Reset the given application or all applications to default modes."); 5447 pw.println(" write-settings"); 5448 pw.println(" Immediately write pending changes to storage."); 5449 pw.println(" read-settings"); 5450 pw.println(" Read the last written settings, replacing current state in RAM."); 5451 pw.println(" options:"); 5452 pw.println(" <PACKAGE> an Android package name or its UID if prefixed by --uid"); 5453 pw.println(" <OP> an AppOps operation."); 5454 pw.println(" <MODE> one of allow, ignore, deny, or default"); 5455 pw.println(" <USER_ID> the user id under which the package is installed. If --user is"); 5456 pw.println(" not specified, the current user is assumed."); 5457 } 5458 onShellCommand(Shell shell, String cmd)5459 static int onShellCommand(Shell shell, String cmd) { 5460 if (cmd == null) { 5461 return shell.handleDefaultCommands(cmd); 5462 } 5463 PrintWriter pw = shell.getOutPrintWriter(); 5464 PrintWriter err = shell.getErrPrintWriter(); 5465 try { 5466 switch (cmd) { 5467 case "set": { 5468 int res = shell.parseUserPackageOp(true, err); 5469 if (res < 0) { 5470 return res; 5471 } 5472 String modeStr = shell.getNextArg(); 5473 if (modeStr == null) { 5474 err.println("Error: Mode not specified."); 5475 return -1; 5476 } 5477 5478 final int mode = shell.strModeToMode(modeStr, err); 5479 if (mode < 0) { 5480 return -1; 5481 } 5482 5483 if (!shell.targetsUid && shell.packageName != null) { 5484 shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName, 5485 mode); 5486 } else if (shell.targetsUid && shell.packageName != null) { 5487 try { 5488 final int uid = shell.mInternal.mContext.getPackageManager() 5489 .getPackageUidAsUser(shell.packageName, shell.userId); 5490 shell.mInterface.setUidMode(shell.op, uid, mode); 5491 } catch (PackageManager.NameNotFoundException e) { 5492 return -1; 5493 } 5494 } else { 5495 shell.mInterface.setUidMode(shell.op, shell.nonpackageUid, mode); 5496 } 5497 return 0; 5498 } 5499 case "get": { 5500 int res = shell.parseUserPackageOp(false, err); 5501 if (res < 0) { 5502 return res; 5503 } 5504 5505 List<AppOpsManager.PackageOps> ops = new ArrayList<>(); 5506 if (shell.packageName != null) { 5507 // Uid mode overrides package mode, so make sure it's also reported 5508 List<AppOpsManager.PackageOps> r = shell.mInterface.getUidOps( 5509 shell.packageUid, 5510 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); 5511 if (r != null) { 5512 ops.addAll(r); 5513 } 5514 r = shell.mInterface.getOpsForPackage( 5515 shell.packageUid, shell.packageName, 5516 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); 5517 if (r != null) { 5518 ops.addAll(r); 5519 } 5520 } else { 5521 ops = shell.mInterface.getUidOps( 5522 shell.nonpackageUid, 5523 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); 5524 } 5525 if (ops == null || ops.size() <= 0) { 5526 pw.println("No operations."); 5527 if (shell.op > AppOpsManager.OP_NONE && shell.op < AppOpsManager._NUM_OP) { 5528 pw.println("Default mode: " + AppOpsManager.modeToName( 5529 AppOpsManager.opToDefaultMode(shell.op))); 5530 } 5531 return 0; 5532 } 5533 final long now = System.currentTimeMillis(); 5534 for (int i=0; i<ops.size(); i++) { 5535 AppOpsManager.PackageOps packageOps = ops.get(i); 5536 if (packageOps.getPackageName() == null) { 5537 pw.print("Uid mode: "); 5538 } 5539 List<AppOpsManager.OpEntry> entries = packageOps.getOps(); 5540 for (int j=0; j<entries.size(); j++) { 5541 AppOpsManager.OpEntry ent = entries.get(j); 5542 pw.print(AppOpsManager.opToName(ent.getOp())); 5543 pw.print(": "); 5544 pw.print(AppOpsManager.modeToName(ent.getMode())); 5545 if (shell.attributionTag == null) { 5546 if (ent.getLastAccessTime(OP_FLAGS_ALL) != -1) { 5547 pw.print("; time="); 5548 TimeUtils.formatDuration( 5549 now - ent.getLastAccessTime(OP_FLAGS_ALL), pw); 5550 pw.print(" ago"); 5551 } 5552 if (ent.getLastRejectTime(OP_FLAGS_ALL) != -1) { 5553 pw.print("; rejectTime="); 5554 TimeUtils.formatDuration( 5555 now - ent.getLastRejectTime(OP_FLAGS_ALL), pw); 5556 pw.print(" ago"); 5557 } 5558 if (ent.isRunning()) { 5559 pw.print(" (running)"); 5560 } else if (ent.getLastDuration(OP_FLAGS_ALL) != -1) { 5561 pw.print("; duration="); 5562 TimeUtils.formatDuration(ent.getLastDuration(OP_FLAGS_ALL), pw); 5563 } 5564 } else { 5565 final AppOpsManager.AttributedOpEntry attributionEnt = 5566 ent.getAttributedOpEntries().get(shell.attributionTag); 5567 if (attributionEnt != null) { 5568 if (attributionEnt.getLastAccessTime(OP_FLAGS_ALL) != -1) { 5569 pw.print("; time="); 5570 TimeUtils.formatDuration( 5571 now - attributionEnt.getLastAccessTime( 5572 OP_FLAGS_ALL), pw); 5573 pw.print(" ago"); 5574 } 5575 if (attributionEnt.getLastRejectTime(OP_FLAGS_ALL) != -1) { 5576 pw.print("; rejectTime="); 5577 TimeUtils.formatDuration( 5578 now - attributionEnt.getLastRejectTime( 5579 OP_FLAGS_ALL), pw); 5580 pw.print(" ago"); 5581 } 5582 if (attributionEnt.isRunning()) { 5583 pw.print(" (running)"); 5584 } else if (attributionEnt.getLastDuration(OP_FLAGS_ALL) 5585 != -1) { 5586 pw.print("; duration="); 5587 TimeUtils.formatDuration( 5588 attributionEnt.getLastDuration(OP_FLAGS_ALL), pw); 5589 } 5590 } 5591 } 5592 pw.println(); 5593 } 5594 } 5595 return 0; 5596 } 5597 case "query-op": { 5598 int res = shell.parseUserOpMode(AppOpsManager.MODE_IGNORED, err); 5599 if (res < 0) { 5600 return res; 5601 } 5602 List<AppOpsManager.PackageOps> ops = shell.mInterface.getPackagesForOps( 5603 new int[] {shell.op}); 5604 if (ops == null || ops.size() <= 0) { 5605 pw.println("No operations."); 5606 return 0; 5607 } 5608 for (int i=0; i<ops.size(); i++) { 5609 final AppOpsManager.PackageOps pkg = ops.get(i); 5610 boolean hasMatch = false; 5611 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps(); 5612 for (int j=0; j<entries.size(); j++) { 5613 AppOpsManager.OpEntry ent = entries.get(j); 5614 if (ent.getOp() == shell.op && ent.getMode() == shell.mode) { 5615 hasMatch = true; 5616 break; 5617 } 5618 } 5619 if (hasMatch) { 5620 pw.println(pkg.getPackageName()); 5621 } 5622 } 5623 return 0; 5624 } 5625 case "reset": { 5626 String packageName = null; 5627 int userId = UserHandle.USER_CURRENT; 5628 for (String argument; (argument = shell.getNextArg()) != null;) { 5629 if ("--user".equals(argument)) { 5630 String userStr = shell.getNextArgRequired(); 5631 userId = UserHandle.parseUserArg(userStr); 5632 } else { 5633 if (packageName == null) { 5634 packageName = argument; 5635 } else { 5636 err.println("Error: Unsupported argument: " + argument); 5637 return -1; 5638 } 5639 } 5640 } 5641 5642 if (userId == UserHandle.USER_CURRENT) { 5643 userId = ActivityManager.getCurrentUser(); 5644 } 5645 5646 shell.mInterface.resetAllModes(userId, packageName); 5647 pw.print("Reset all modes for: "); 5648 if (userId == UserHandle.USER_ALL) { 5649 pw.print("all users"); 5650 } else { 5651 pw.print("user "); pw.print(userId); 5652 } 5653 pw.print(", "); 5654 if (packageName == null) { 5655 pw.println("all packages"); 5656 } else { 5657 pw.print("package "); pw.println(packageName); 5658 } 5659 return 0; 5660 } 5661 case "write-settings": { 5662 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(), 5663 Binder.getCallingUid(), -1); 5664 final long token = Binder.clearCallingIdentity(); 5665 try { 5666 synchronized (shell.mInternal) { 5667 shell.mInternal.mHandler.removeCallbacks(shell.mInternal.mWriteRunner); 5668 } 5669 shell.mInternal.writeState(); 5670 pw.println("Current settings written."); 5671 } finally { 5672 Binder.restoreCallingIdentity(token); 5673 } 5674 return 0; 5675 } 5676 case "read-settings": { 5677 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(), 5678 Binder.getCallingUid(), -1); 5679 final long token = Binder.clearCallingIdentity(); 5680 try { 5681 shell.mInternal.readState(); 5682 pw.println("Last settings read."); 5683 } finally { 5684 Binder.restoreCallingIdentity(token); 5685 } 5686 return 0; 5687 } 5688 case "start": { 5689 int res = shell.parseUserPackageOp(true, err); 5690 if (res < 0) { 5691 return res; 5692 } 5693 5694 if (shell.packageName != null) { 5695 shell.mInterface.startOperation(shell.mToken, shell.op, shell.packageUid, 5696 shell.packageName, shell.attributionTag, true, true, 5697 "appops start shell command", true, 5698 AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR, ATTRIBUTION_CHAIN_ID_NONE); 5699 } else { 5700 return -1; 5701 } 5702 return 0; 5703 } 5704 case "stop": { 5705 int res = shell.parseUserPackageOp(true, err); 5706 if (res < 0) { 5707 return res; 5708 } 5709 5710 if (shell.packageName != null) { 5711 shell.mInterface.finishOperation(shell.mToken, shell.op, shell.packageUid, 5712 shell.packageName, shell.attributionTag); 5713 } else { 5714 return -1; 5715 } 5716 return 0; 5717 } 5718 default: 5719 return shell.handleDefaultCommands(cmd); 5720 } 5721 } catch (RemoteException e) { 5722 pw.println("Remote exception: " + e); 5723 } 5724 return -1; 5725 } 5726 dumpHelp(PrintWriter pw)5727 private void dumpHelp(PrintWriter pw) { 5728 pw.println("AppOps service (appops) dump options:"); 5729 pw.println(" -h"); 5730 pw.println(" Print this help text."); 5731 pw.println(" --op [OP]"); 5732 pw.println(" Limit output to data associated with the given app op code."); 5733 pw.println(" --mode [MODE]"); 5734 pw.println(" Limit output to data associated with the given app op mode."); 5735 pw.println(" --package [PACKAGE]"); 5736 pw.println(" Limit output to data associated with the given package name."); 5737 pw.println(" --attributionTag [attributionTag]"); 5738 pw.println(" Limit output to data associated with the given attribution tag."); 5739 pw.println(" --include-discrete [n]"); 5740 pw.println(" Include discrete ops limited to n per dimension. Use zero for no limit."); 5741 pw.println(" --watchers"); 5742 pw.println(" Only output the watcher sections."); 5743 pw.println(" --history"); 5744 pw.println(" Only output history."); 5745 } 5746 dumpStatesLocked(@onNull PrintWriter pw, @Nullable String filterAttributionTag, @HistoricalOpsRequestFilter int filter, long nowElapsed, @NonNull Op op, long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix)5747 private void dumpStatesLocked(@NonNull PrintWriter pw, @Nullable String filterAttributionTag, 5748 @HistoricalOpsRequestFilter int filter, long nowElapsed, @NonNull Op op, long now, 5749 @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix) { 5750 final int numAttributions = op.mAttributions.size(); 5751 for (int i = 0; i < numAttributions; i++) { 5752 if ((filter & FILTER_BY_ATTRIBUTION_TAG) != 0 && !Objects.equals( 5753 op.mAttributions.keyAt(i), filterAttributionTag)) { 5754 continue; 5755 } 5756 5757 pw.print(prefix + op.mAttributions.keyAt(i) + "=[\n"); 5758 dumpStatesLocked(pw, nowElapsed, op, op.mAttributions.keyAt(i), now, sdf, date, 5759 prefix + " "); 5760 pw.print(prefix + "]\n"); 5761 } 5762 } 5763 dumpStatesLocked(@onNull PrintWriter pw, long nowElapsed, @NonNull Op op, @Nullable String attributionTag, long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix)5764 private void dumpStatesLocked(@NonNull PrintWriter pw, long nowElapsed, @NonNull Op op, 5765 @Nullable String attributionTag, long now, @NonNull SimpleDateFormat sdf, 5766 @NonNull Date date, @NonNull String prefix) { 5767 5768 final AttributedOpEntry entry = op.createSingleAttributionEntryLocked( 5769 attributionTag).getAttributedOpEntries().get(attributionTag); 5770 5771 final ArraySet<Long> keys = entry.collectKeys(); 5772 5773 final int keyCount = keys.size(); 5774 for (int k = 0; k < keyCount; k++) { 5775 final long key = keys.valueAt(k); 5776 5777 final int uidState = AppOpsManager.extractUidStateFromKey(key); 5778 final int flags = AppOpsManager.extractFlagsFromKey(key); 5779 5780 final long accessTime = entry.getLastAccessTime(uidState, uidState, flags); 5781 final long rejectTime = entry.getLastRejectTime(uidState, uidState, flags); 5782 final long accessDuration = entry.getLastDuration(uidState, uidState, flags); 5783 final OpEventProxyInfo proxy = entry.getLastProxyInfo(uidState, uidState, flags); 5784 5785 String proxyPkg = null; 5786 String proxyAttributionTag = null; 5787 int proxyUid = Process.INVALID_UID; 5788 if (proxy != null) { 5789 proxyPkg = proxy.getPackageName(); 5790 proxyAttributionTag = proxy.getAttributionTag(); 5791 proxyUid = proxy.getUid(); 5792 } 5793 5794 if (accessTime > 0) { 5795 pw.print(prefix); 5796 pw.print("Access: "); 5797 pw.print(AppOpsManager.keyToString(key)); 5798 pw.print(" "); 5799 date.setTime(accessTime); 5800 pw.print(sdf.format(date)); 5801 pw.print(" ("); 5802 TimeUtils.formatDuration(accessTime - now, pw); 5803 pw.print(")"); 5804 if (accessDuration > 0) { 5805 pw.print(" duration="); 5806 TimeUtils.formatDuration(accessDuration, pw); 5807 } 5808 if (proxyUid >= 0) { 5809 pw.print(" proxy["); 5810 pw.print("uid="); 5811 pw.print(proxyUid); 5812 pw.print(", pkg="); 5813 pw.print(proxyPkg); 5814 pw.print(", attributionTag="); 5815 pw.print(proxyAttributionTag); 5816 pw.print("]"); 5817 } 5818 pw.println(); 5819 } 5820 5821 if (rejectTime > 0) { 5822 pw.print(prefix); 5823 pw.print("Reject: "); 5824 pw.print(AppOpsManager.keyToString(key)); 5825 date.setTime(rejectTime); 5826 pw.print(sdf.format(date)); 5827 pw.print(" ("); 5828 TimeUtils.formatDuration(rejectTime - now, pw); 5829 pw.print(")"); 5830 if (proxyUid >= 0) { 5831 pw.print(" proxy["); 5832 pw.print("uid="); 5833 pw.print(proxyUid); 5834 pw.print(", pkg="); 5835 pw.print(proxyPkg); 5836 pw.print(", attributionTag="); 5837 pw.print(proxyAttributionTag); 5838 pw.print("]"); 5839 } 5840 pw.println(); 5841 } 5842 } 5843 5844 final AttributedOp attributedOp = op.mAttributions.get(attributionTag); 5845 if (attributedOp.isRunning()) { 5846 long earliestElapsedTime = Long.MAX_VALUE; 5847 long maxNumStarts = 0; 5848 int numInProgressEvents = attributedOp.mInProgressEvents.size(); 5849 for (int i = 0; i < numInProgressEvents; i++) { 5850 InProgressStartOpEvent event = attributedOp.mInProgressEvents.valueAt(i); 5851 5852 earliestElapsedTime = Math.min(earliestElapsedTime, event.getStartElapsedTime()); 5853 maxNumStarts = Math.max(maxNumStarts, event.numUnfinishedStarts); 5854 } 5855 5856 pw.print(prefix + "Running start at: "); 5857 TimeUtils.formatDuration(nowElapsed - earliestElapsedTime, pw); 5858 pw.println(); 5859 5860 if (maxNumStarts > 1) { 5861 pw.print(prefix + "startNesting="); 5862 pw.println(maxNumStarts); 5863 } 5864 } 5865 } 5866 5867 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)5868 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 5869 if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; 5870 5871 int dumpOp = OP_NONE; 5872 String dumpPackage = null; 5873 String dumpAttributionTag = null; 5874 int dumpUid = Process.INVALID_UID; 5875 int dumpMode = -1; 5876 boolean dumpWatchers = false; 5877 // TODO ntmyren: Remove the dumpHistory and dumpFilter 5878 boolean dumpHistory = false; 5879 boolean includeDiscreteOps = false; 5880 int nDiscreteOps = 10; 5881 @HistoricalOpsRequestFilter int dumpFilter = 0; 5882 5883 if (args != null) { 5884 for (int i = 0; i < args.length; i++) { 5885 String arg = args[i]; 5886 if ("-h".equals(arg)) { 5887 dumpHelp(pw); 5888 return; 5889 } else if ("-a".equals(arg)) { 5890 // dump all data 5891 } else if ("--op".equals(arg)) { 5892 i++; 5893 if (i >= args.length) { 5894 pw.println("No argument for --op option"); 5895 return; 5896 } 5897 dumpOp = Shell.strOpToOp(args[i], pw); 5898 dumpFilter |= FILTER_BY_OP_NAMES; 5899 if (dumpOp < 0) { 5900 return; 5901 } 5902 } else if ("--package".equals(arg)) { 5903 i++; 5904 if (i >= args.length) { 5905 pw.println("No argument for --package option"); 5906 return; 5907 } 5908 dumpPackage = args[i]; 5909 dumpFilter |= FILTER_BY_PACKAGE_NAME; 5910 try { 5911 dumpUid = AppGlobals.getPackageManager().getPackageUid(dumpPackage, 5912 PackageManager.MATCH_KNOWN_PACKAGES | PackageManager.MATCH_INSTANT, 5913 0); 5914 } catch (RemoteException e) { 5915 } 5916 if (dumpUid < 0) { 5917 pw.println("Unknown package: " + dumpPackage); 5918 return; 5919 } 5920 dumpUid = UserHandle.getAppId(dumpUid); 5921 dumpFilter |= FILTER_BY_UID; 5922 } else if ("--attributionTag".equals(arg)) { 5923 i++; 5924 if (i >= args.length) { 5925 pw.println("No argument for --attributionTag option"); 5926 return; 5927 } 5928 dumpAttributionTag = args[i]; 5929 dumpFilter |= FILTER_BY_ATTRIBUTION_TAG; 5930 } else if ("--mode".equals(arg)) { 5931 i++; 5932 if (i >= args.length) { 5933 pw.println("No argument for --mode option"); 5934 return; 5935 } 5936 dumpMode = Shell.strModeToMode(args[i], pw); 5937 if (dumpMode < 0) { 5938 return; 5939 } 5940 } else if ("--watchers".equals(arg)) { 5941 dumpWatchers = true; 5942 } else if ("--include-discrete".equals(arg)) { 5943 i++; 5944 if (i >= args.length) { 5945 pw.println("No argument for --include-discrete option"); 5946 return; 5947 } 5948 try { 5949 nDiscreteOps = Integer.valueOf(args[i]); 5950 } catch (NumberFormatException e) { 5951 pw.println("Wrong parameter: " + args[i]); 5952 return; 5953 } 5954 includeDiscreteOps = true; 5955 } else if ("--history".equals(arg)) { 5956 dumpHistory = true; 5957 } else if (arg.length() > 0 && arg.charAt(0) == '-') { 5958 pw.println("Unknown option: " + arg); 5959 return; 5960 } else { 5961 pw.println("Unknown command: " + arg); 5962 return; 5963 } 5964 } 5965 } 5966 5967 final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 5968 final Date date = new Date(); 5969 synchronized (this) { 5970 pw.println("Current AppOps Service state:"); 5971 if (!dumpHistory && !dumpWatchers) { 5972 mConstants.dump(pw); 5973 } 5974 pw.println(); 5975 final long now = System.currentTimeMillis(); 5976 final long nowElapsed = SystemClock.elapsedRealtime(); 5977 final long nowUptime = SystemClock.uptimeMillis(); 5978 boolean needSep = false; 5979 if (dumpFilter == 0 && dumpMode < 0 && mProfileOwners != null && !dumpWatchers 5980 && !dumpHistory) { 5981 pw.println(" Profile owners:"); 5982 for (int poi = 0; poi < mProfileOwners.size(); poi++) { 5983 pw.print(" User #"); 5984 pw.print(mProfileOwners.keyAt(poi)); 5985 pw.print(": "); 5986 UserHandle.formatUid(pw, mProfileOwners.valueAt(poi)); 5987 pw.println(); 5988 } 5989 pw.println(); 5990 } 5991 if (mOpModeWatchers.size() > 0 && !dumpHistory) { 5992 boolean printedHeader = false; 5993 for (int i=0; i<mOpModeWatchers.size(); i++) { 5994 if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) { 5995 continue; 5996 } 5997 boolean printedOpHeader = false; 5998 ArraySet<ModeCallback> callbacks = mOpModeWatchers.valueAt(i); 5999 for (int j=0; j<callbacks.size(); j++) { 6000 final ModeCallback cb = callbacks.valueAt(j); 6001 if (dumpPackage != null 6002 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 6003 continue; 6004 } 6005 needSep = true; 6006 if (!printedHeader) { 6007 pw.println(" Op mode watchers:"); 6008 printedHeader = true; 6009 } 6010 if (!printedOpHeader) { 6011 pw.print(" Op "); 6012 pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i))); 6013 pw.println(":"); 6014 printedOpHeader = true; 6015 } 6016 pw.print(" #"); pw.print(j); pw.print(": "); 6017 pw.println(cb); 6018 } 6019 } 6020 } 6021 if (mPackageModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) { 6022 boolean printedHeader = false; 6023 for (int i=0; i<mPackageModeWatchers.size(); i++) { 6024 if (dumpPackage != null && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) { 6025 continue; 6026 } 6027 needSep = true; 6028 if (!printedHeader) { 6029 pw.println(" Package mode watchers:"); 6030 printedHeader = true; 6031 } 6032 pw.print(" Pkg "); pw.print(mPackageModeWatchers.keyAt(i)); 6033 pw.println(":"); 6034 ArraySet<ModeCallback> callbacks = mPackageModeWatchers.valueAt(i); 6035 for (int j=0; j<callbacks.size(); j++) { 6036 pw.print(" #"); pw.print(j); pw.print(": "); 6037 pw.println(callbacks.valueAt(j)); 6038 } 6039 } 6040 } 6041 if (mModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) { 6042 boolean printedHeader = false; 6043 for (int i=0; i<mModeWatchers.size(); i++) { 6044 final ModeCallback cb = mModeWatchers.valueAt(i); 6045 if (dumpPackage != null 6046 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 6047 continue; 6048 } 6049 needSep = true; 6050 if (!printedHeader) { 6051 pw.println(" All op mode watchers:"); 6052 printedHeader = true; 6053 } 6054 pw.print(" "); 6055 pw.print(Integer.toHexString(System.identityHashCode(mModeWatchers.keyAt(i)))); 6056 pw.print(": "); pw.println(cb); 6057 } 6058 } 6059 if (mActiveWatchers.size() > 0 && dumpMode < 0) { 6060 needSep = true; 6061 boolean printedHeader = false; 6062 for (int watcherNum = 0; watcherNum < mActiveWatchers.size(); watcherNum++) { 6063 final SparseArray<ActiveCallback> activeWatchers = 6064 mActiveWatchers.valueAt(watcherNum); 6065 if (activeWatchers.size() <= 0) { 6066 continue; 6067 } 6068 final ActiveCallback cb = activeWatchers.valueAt(0); 6069 if (dumpOp >= 0 && activeWatchers.indexOfKey(dumpOp) < 0) { 6070 continue; 6071 } 6072 if (dumpPackage != null 6073 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 6074 continue; 6075 } 6076 if (!printedHeader) { 6077 pw.println(" All op active watchers:"); 6078 printedHeader = true; 6079 } 6080 pw.print(" "); 6081 pw.print(Integer.toHexString(System.identityHashCode( 6082 mActiveWatchers.keyAt(watcherNum)))); 6083 pw.println(" ->"); 6084 pw.print(" ["); 6085 final int opCount = activeWatchers.size(); 6086 for (int opNum = 0; opNum < opCount; opNum++) { 6087 if (opNum > 0) { 6088 pw.print(' '); 6089 } 6090 pw.print(AppOpsManager.opToName(activeWatchers.keyAt(opNum))); 6091 if (opNum < opCount - 1) { 6092 pw.print(','); 6093 } 6094 } 6095 pw.println("]"); 6096 pw.print(" "); 6097 pw.println(cb); 6098 } 6099 } 6100 if (mStartedWatchers.size() > 0 && dumpMode < 0) { 6101 needSep = true; 6102 boolean printedHeader = false; 6103 6104 final int watchersSize = mStartedWatchers.size(); 6105 for (int watcherNum = 0; watcherNum < watchersSize; watcherNum++) { 6106 final SparseArray<StartedCallback> startedWatchers = 6107 mStartedWatchers.valueAt(watcherNum); 6108 if (startedWatchers.size() <= 0) { 6109 continue; 6110 } 6111 6112 final StartedCallback cb = startedWatchers.valueAt(0); 6113 if (dumpOp >= 0 && startedWatchers.indexOfKey(dumpOp) < 0) { 6114 continue; 6115 } 6116 6117 if (dumpPackage != null 6118 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 6119 continue; 6120 } 6121 6122 if (!printedHeader) { 6123 pw.println(" All op started watchers:"); 6124 printedHeader = true; 6125 } 6126 6127 pw.print(" "); 6128 pw.print(Integer.toHexString(System.identityHashCode( 6129 mStartedWatchers.keyAt(watcherNum)))); 6130 pw.println(" ->"); 6131 6132 pw.print(" ["); 6133 final int opCount = startedWatchers.size(); 6134 for (int opNum = 0; opNum < opCount; opNum++) { 6135 if (opNum > 0) { 6136 pw.print(' '); 6137 } 6138 6139 pw.print(AppOpsManager.opToName(startedWatchers.keyAt(opNum))); 6140 if (opNum < opCount - 1) { 6141 pw.print(','); 6142 } 6143 } 6144 pw.println("]"); 6145 6146 pw.print(" "); 6147 pw.println(cb); 6148 } 6149 } 6150 if (mNotedWatchers.size() > 0 && dumpMode < 0) { 6151 needSep = true; 6152 boolean printedHeader = false; 6153 for (int watcherNum = 0; watcherNum < mNotedWatchers.size(); watcherNum++) { 6154 final SparseArray<NotedCallback> notedWatchers = 6155 mNotedWatchers.valueAt(watcherNum); 6156 if (notedWatchers.size() <= 0) { 6157 continue; 6158 } 6159 final NotedCallback cb = notedWatchers.valueAt(0); 6160 if (dumpOp >= 0 && notedWatchers.indexOfKey(dumpOp) < 0) { 6161 continue; 6162 } 6163 if (dumpPackage != null 6164 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 6165 continue; 6166 } 6167 if (!printedHeader) { 6168 pw.println(" All op noted watchers:"); 6169 printedHeader = true; 6170 } 6171 pw.print(" "); 6172 pw.print(Integer.toHexString(System.identityHashCode( 6173 mNotedWatchers.keyAt(watcherNum)))); 6174 pw.println(" ->"); 6175 pw.print(" ["); 6176 final int opCount = notedWatchers.size(); 6177 for (int opNum = 0; opNum < opCount; opNum++) { 6178 if (opNum > 0) { 6179 pw.print(' '); 6180 } 6181 pw.print(AppOpsManager.opToName(notedWatchers.keyAt(opNum))); 6182 if (opNum < opCount - 1) { 6183 pw.print(','); 6184 } 6185 } 6186 pw.println("]"); 6187 pw.print(" "); 6188 pw.println(cb); 6189 } 6190 } 6191 if (mAudioRestrictionManager.hasActiveRestrictions() && dumpOp < 0 6192 && dumpPackage != null && dumpMode < 0 && !dumpWatchers && !dumpWatchers) { 6193 needSep = mAudioRestrictionManager.dump(pw) | needSep ; 6194 } 6195 if (needSep) { 6196 pw.println(); 6197 } 6198 for (int i=0; i<mUidStates.size(); i++) { 6199 UidState uidState = mUidStates.valueAt(i); 6200 final SparseIntArray opModes = uidState.opModes; 6201 final ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 6202 6203 if (dumpWatchers || dumpHistory) { 6204 continue; 6205 } 6206 if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) { 6207 boolean hasOp = dumpOp < 0 || (uidState.opModes != null 6208 && uidState.opModes.indexOfKey(dumpOp) >= 0); 6209 boolean hasPackage = dumpPackage == null || dumpUid == mUidStates.keyAt(i); 6210 boolean hasMode = dumpMode < 0; 6211 if (!hasMode && opModes != null) { 6212 for (int opi = 0; !hasMode && opi < opModes.size(); opi++) { 6213 if (opModes.valueAt(opi) == dumpMode) { 6214 hasMode = true; 6215 } 6216 } 6217 } 6218 if (pkgOps != null) { 6219 for (int pkgi = 0; 6220 (!hasOp || !hasPackage || !hasMode) && pkgi < pkgOps.size(); 6221 pkgi++) { 6222 Ops ops = pkgOps.valueAt(pkgi); 6223 if (!hasOp && ops != null && ops.indexOfKey(dumpOp) >= 0) { 6224 hasOp = true; 6225 } 6226 if (!hasMode) { 6227 for (int opi = 0; !hasMode && opi < ops.size(); opi++) { 6228 if (ops.valueAt(opi).mode == dumpMode) { 6229 hasMode = true; 6230 } 6231 } 6232 } 6233 if (!hasPackage && dumpPackage.equals(ops.packageName)) { 6234 hasPackage = true; 6235 } 6236 } 6237 } 6238 if (uidState.foregroundOps != null && !hasOp) { 6239 if (uidState.foregroundOps.indexOfKey(dumpOp) > 0) { 6240 hasOp = true; 6241 } 6242 } 6243 if (!hasOp || !hasPackage || !hasMode) { 6244 continue; 6245 } 6246 } 6247 6248 pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":"); 6249 pw.print(" state="); 6250 pw.println(AppOpsManager.getUidStateName(uidState.state)); 6251 if (uidState.state != uidState.pendingState) { 6252 pw.print(" pendingState="); 6253 pw.println(AppOpsManager.getUidStateName(uidState.pendingState)); 6254 } 6255 pw.print(" capability="); 6256 ActivityManager.printCapabilitiesFull(pw, uidState.capability); 6257 pw.println(); 6258 if (uidState.capability != uidState.pendingCapability) { 6259 pw.print(" pendingCapability="); 6260 ActivityManager.printCapabilitiesFull(pw, uidState.pendingCapability); 6261 pw.println(); 6262 } 6263 pw.print(" appWidgetVisible="); 6264 pw.println(uidState.appWidgetVisible); 6265 if (uidState.appWidgetVisible != uidState.pendingAppWidgetVisible) { 6266 pw.print(" pendingAppWidgetVisible="); 6267 pw.println(uidState.pendingAppWidgetVisible); 6268 } 6269 if (uidState.pendingStateCommitTime != 0) { 6270 pw.print(" pendingStateCommitTime="); 6271 TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowElapsed, pw); 6272 pw.println(); 6273 } 6274 if (uidState.foregroundOps != null && (dumpMode < 0 6275 || dumpMode == AppOpsManager.MODE_FOREGROUND)) { 6276 pw.println(" foregroundOps:"); 6277 for (int j = 0; j < uidState.foregroundOps.size(); j++) { 6278 if (dumpOp >= 0 && dumpOp != uidState.foregroundOps.keyAt(j)) { 6279 continue; 6280 } 6281 pw.print(" "); 6282 pw.print(AppOpsManager.opToName(uidState.foregroundOps.keyAt(j))); 6283 pw.print(": "); 6284 pw.println(uidState.foregroundOps.valueAt(j) ? "WATCHER" : "SILENT"); 6285 } 6286 pw.print(" hasForegroundWatchers="); 6287 pw.println(uidState.hasForegroundWatchers); 6288 } 6289 needSep = true; 6290 6291 if (opModes != null) { 6292 final int opModeCount = opModes.size(); 6293 for (int j = 0; j < opModeCount; j++) { 6294 final int code = opModes.keyAt(j); 6295 final int mode = opModes.valueAt(j); 6296 if (dumpOp >= 0 && dumpOp != code) { 6297 continue; 6298 } 6299 if (dumpMode >= 0 && dumpMode != mode) { 6300 continue; 6301 } 6302 pw.print(" "); pw.print(AppOpsManager.opToName(code)); 6303 pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode)); 6304 } 6305 } 6306 6307 if (pkgOps == null) { 6308 continue; 6309 } 6310 6311 for (int pkgi = 0; pkgi < pkgOps.size(); pkgi++) { 6312 final Ops ops = pkgOps.valueAt(pkgi); 6313 if (dumpPackage != null && !dumpPackage.equals(ops.packageName)) { 6314 continue; 6315 } 6316 boolean printedPackage = false; 6317 for (int j=0; j<ops.size(); j++) { 6318 final Op op = ops.valueAt(j); 6319 final int opCode = op.op; 6320 if (dumpOp >= 0 && dumpOp != opCode) { 6321 continue; 6322 } 6323 if (dumpMode >= 0 && dumpMode != op.mode) { 6324 continue; 6325 } 6326 if (!printedPackage) { 6327 pw.print(" Package "); pw.print(ops.packageName); pw.println(":"); 6328 printedPackage = true; 6329 } 6330 pw.print(" "); pw.print(AppOpsManager.opToName(opCode)); 6331 pw.print(" ("); pw.print(AppOpsManager.modeToName(op.mode)); 6332 final int switchOp = AppOpsManager.opToSwitch(opCode); 6333 if (switchOp != opCode) { 6334 pw.print(" / switch "); 6335 pw.print(AppOpsManager.opToName(switchOp)); 6336 final Op switchObj = ops.get(switchOp); 6337 int mode = switchObj != null ? switchObj.mode 6338 : AppOpsManager.opToDefaultMode(switchOp); 6339 pw.print("="); pw.print(AppOpsManager.modeToName(mode)); 6340 } 6341 pw.println("): "); 6342 dumpStatesLocked(pw, dumpAttributionTag, dumpFilter, nowElapsed, op, now, 6343 sdf, date, " "); 6344 } 6345 } 6346 } 6347 if (needSep) { 6348 pw.println(); 6349 } 6350 6351 final int globalRestrictionCount = mOpGlobalRestrictions.size(); 6352 for (int i = 0; i < globalRestrictionCount; i++) { 6353 IBinder token = mOpGlobalRestrictions.keyAt(i); 6354 ClientGlobalRestrictionState restrictionState = mOpGlobalRestrictions.valueAt(i); 6355 ArraySet<Integer> restrictedOps = restrictionState.mRestrictedOps; 6356 6357 pw.println(" Global restrictions for token " + token + ":"); 6358 StringBuilder restrictedOpsValue = new StringBuilder(); 6359 restrictedOpsValue.append("["); 6360 final int restrictedOpCount = restrictedOps.size(); 6361 for (int j = 0; j < restrictedOpCount; j++) { 6362 if (restrictedOpsValue.length() > 1) { 6363 restrictedOpsValue.append(", "); 6364 } 6365 restrictedOpsValue.append(AppOpsManager.opToName(restrictedOps.valueAt(j))); 6366 } 6367 restrictedOpsValue.append("]"); 6368 pw.println(" Restricted ops: " + restrictedOpsValue); 6369 6370 } 6371 6372 final int userRestrictionCount = mOpUserRestrictions.size(); 6373 for (int i = 0; i < userRestrictionCount; i++) { 6374 IBinder token = mOpUserRestrictions.keyAt(i); 6375 ClientUserRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); 6376 boolean printedTokenHeader = false; 6377 6378 if (dumpMode >= 0 || dumpWatchers || dumpHistory) { 6379 continue; 6380 } 6381 6382 final int restrictionCount = restrictionState.perUserRestrictions != null 6383 ? restrictionState.perUserRestrictions.size() : 0; 6384 if (restrictionCount > 0 && dumpPackage == null) { 6385 boolean printedOpsHeader = false; 6386 for (int j = 0; j < restrictionCount; j++) { 6387 int userId = restrictionState.perUserRestrictions.keyAt(j); 6388 boolean[] restrictedOps = restrictionState.perUserRestrictions.valueAt(j); 6389 if (restrictedOps == null) { 6390 continue; 6391 } 6392 if (dumpOp >= 0 && (dumpOp >= restrictedOps.length 6393 || !restrictedOps[dumpOp])) { 6394 continue; 6395 } 6396 if (!printedTokenHeader) { 6397 pw.println(" User restrictions for token " + token + ":"); 6398 printedTokenHeader = true; 6399 } 6400 if (!printedOpsHeader) { 6401 pw.println(" Restricted ops:"); 6402 printedOpsHeader = true; 6403 } 6404 StringBuilder restrictedOpsValue = new StringBuilder(); 6405 restrictedOpsValue.append("["); 6406 final int restrictedOpCount = restrictedOps.length; 6407 for (int k = 0; k < restrictedOpCount; k++) { 6408 if (restrictedOps[k]) { 6409 if (restrictedOpsValue.length() > 1) { 6410 restrictedOpsValue.append(", "); 6411 } 6412 restrictedOpsValue.append(AppOpsManager.opToName(k)); 6413 } 6414 } 6415 restrictedOpsValue.append("]"); 6416 pw.print(" "); pw.print("user: "); pw.print(userId); 6417 pw.print(" restricted ops: "); pw.println(restrictedOpsValue); 6418 } 6419 } 6420 6421 final int excludedPackageCount = restrictionState.perUserExcludedPackageTags != null 6422 ? restrictionState.perUserExcludedPackageTags.size() : 0; 6423 if (excludedPackageCount > 0 && dumpOp < 0) { 6424 IndentingPrintWriter ipw = new IndentingPrintWriter(pw); 6425 ipw.increaseIndent(); 6426 boolean printedPackagesHeader = false; 6427 for (int j = 0; j < excludedPackageCount; j++) { 6428 int userId = restrictionState.perUserExcludedPackageTags.keyAt(j); 6429 PackageTagsList packageNames = 6430 restrictionState.perUserExcludedPackageTags.valueAt(j); 6431 if (packageNames == null) { 6432 continue; 6433 } 6434 boolean hasPackage; 6435 if (dumpPackage != null) { 6436 hasPackage = packageNames.includes(dumpPackage); 6437 } else { 6438 hasPackage = true; 6439 } 6440 if (!hasPackage) { 6441 continue; 6442 } 6443 if (!printedTokenHeader) { 6444 ipw.println("User restrictions for token " + token + ":"); 6445 printedTokenHeader = true; 6446 } 6447 6448 ipw.increaseIndent(); 6449 if (!printedPackagesHeader) { 6450 ipw.println("Excluded packages:"); 6451 printedPackagesHeader = true; 6452 } 6453 6454 ipw.increaseIndent(); 6455 ipw.print("user: "); 6456 ipw.print(userId); 6457 ipw.println(" packages: "); 6458 6459 ipw.increaseIndent(); 6460 packageNames.dump(ipw); 6461 6462 ipw.decreaseIndent(); 6463 ipw.decreaseIndent(); 6464 ipw.decreaseIndent(); 6465 } 6466 ipw.decreaseIndent(); 6467 } 6468 } 6469 } 6470 6471 // Must not hold the appops lock 6472 if (dumpHistory && !dumpWatchers) { 6473 mHistoricalRegistry.dump(" ", pw, dumpUid, dumpPackage, dumpAttributionTag, dumpOp, 6474 dumpFilter); 6475 } 6476 if (includeDiscreteOps) { 6477 pw.println("Discrete accesses: "); 6478 mHistoricalRegistry.dumpDiscreteData(pw, dumpUid, dumpPackage, dumpAttributionTag, 6479 dumpFilter, dumpOp, sdf, date, " ", nDiscreteOps); 6480 } 6481 } 6482 6483 @Override 6484 public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) { 6485 checkSystemUid("setUserRestrictions"); 6486 Objects.requireNonNull(restrictions); 6487 Objects.requireNonNull(token); 6488 for (int i = 0; i < AppOpsManager._NUM_OP; i++) { 6489 String restriction = AppOpsManager.opToRestriction(i); 6490 if (restriction != null) { 6491 setUserRestrictionNoCheck(i, restrictions.getBoolean(restriction, false), token, 6492 userHandle, null); 6493 } 6494 } 6495 } 6496 6497 @Override 6498 public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, 6499 PackageTagsList excludedPackageTags) { 6500 if (Binder.getCallingPid() != Process.myPid()) { 6501 mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS, 6502 Binder.getCallingPid(), Binder.getCallingUid(), null); 6503 } 6504 if (userHandle != UserHandle.getCallingUserId()) { 6505 if (mContext.checkCallingOrSelfPermission(Manifest.permission 6506 .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED 6507 && mContext.checkCallingOrSelfPermission(Manifest.permission 6508 .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) { 6509 throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or" 6510 + " INTERACT_ACROSS_USERS to interact cross user "); 6511 } 6512 } 6513 verifyIncomingOp(code); 6514 Objects.requireNonNull(token); 6515 setUserRestrictionNoCheck(code, restricted, token, userHandle, excludedPackageTags); 6516 } 6517 6518 private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token, 6519 int userHandle, PackageTagsList excludedPackageTags) { 6520 synchronized (AppOpsService.this) { 6521 ClientUserRestrictionState restrictionState = mOpUserRestrictions.get(token); 6522 6523 if (restrictionState == null) { 6524 try { 6525 restrictionState = new ClientUserRestrictionState(token); 6526 } catch (RemoteException e) { 6527 return; 6528 } 6529 mOpUserRestrictions.put(token, restrictionState); 6530 } 6531 6532 if (restrictionState.setRestriction(code, restricted, excludedPackageTags, 6533 userHandle)) { 6534 mHandler.sendMessage(PooledLambda.obtainMessage( 6535 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY)); 6536 mHandler.sendMessage(PooledLambda.obtainMessage( 6537 AppOpsService::updateStartedOpModeForUser, this, code, restricted, 6538 userHandle)); 6539 } 6540 6541 if (restrictionState.isDefault()) { 6542 mOpUserRestrictions.remove(token); 6543 restrictionState.destroy(); 6544 } 6545 } 6546 } 6547 6548 private void updateStartedOpModeForUser(int code, boolean restricted, int userId) { 6549 synchronized (AppOpsService.this) { 6550 int numUids = mUidStates.size(); 6551 for (int uidNum = 0; uidNum < numUids; uidNum++) { 6552 int uid = mUidStates.keyAt(uidNum); 6553 if (userId != UserHandle.USER_ALL && UserHandle.getUserId(uid) != userId) { 6554 continue; 6555 } 6556 updateStartedOpModeForUidLocked(code, restricted, uid); 6557 } 6558 } 6559 } 6560 6561 private void updateStartedOpModeForUidLocked(int code, boolean restricted, int uid) { 6562 UidState uidState = mUidStates.get(uid); 6563 if (uidState == null || uidState.pkgOps == null) { 6564 return; 6565 } 6566 6567 int numPkgOps = uidState.pkgOps.size(); 6568 for (int pkgNum = 0; pkgNum < numPkgOps; pkgNum++) { 6569 Ops ops = uidState.pkgOps.valueAt(pkgNum); 6570 Op op = ops != null ? ops.get(code) : null; 6571 if (op == null || (op.mode != MODE_ALLOWED && op.mode != MODE_FOREGROUND)) { 6572 continue; 6573 } 6574 int numAttrTags = op.mAttributions.size(); 6575 for (int attrNum = 0; attrNum < numAttrTags; attrNum++) { 6576 AttributedOp attrOp = op.mAttributions.valueAt(attrNum); 6577 if (restricted && attrOp.isRunning()) { 6578 attrOp.pause(); 6579 } else if (attrOp.isPaused()) { 6580 attrOp.resume(); 6581 } 6582 } 6583 } 6584 } 6585 6586 private void notifyWatchersOfChange(int code, int uid) { 6587 final ArraySet<ModeCallback> clonedCallbacks; 6588 synchronized (this) { 6589 ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code); 6590 if (callbacks == null) { 6591 return; 6592 } 6593 clonedCallbacks = new ArraySet<>(callbacks); 6594 } 6595 6596 notifyOpChanged(clonedCallbacks, code, uid, null); 6597 } 6598 6599 @Override 6600 public void removeUser(int userHandle) throws RemoteException { 6601 checkSystemUid("removeUser"); 6602 synchronized (AppOpsService.this) { 6603 final int tokenCount = mOpUserRestrictions.size(); 6604 for (int i = tokenCount - 1; i >= 0; i--) { 6605 ClientUserRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i); 6606 opRestrictions.removeUser(userHandle); 6607 } 6608 removeUidsForUserLocked(userHandle); 6609 } 6610 } 6611 6612 @Override 6613 public boolean isOperationActive(int code, int uid, String packageName) { 6614 if (Binder.getCallingUid() != uid) { 6615 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 6616 != PackageManager.PERMISSION_GRANTED) { 6617 return false; 6618 } 6619 } 6620 verifyIncomingOp(code); 6621 verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); 6622 6623 final String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); 6624 if (resolvedPackageName == null) { 6625 return false; 6626 } 6627 // TODO moltmann: Allow to check for attribution op activeness 6628 synchronized (AppOpsService.this) { 6629 Ops pkgOps = getOpsLocked(uid, resolvedPackageName, null, false, null, false); 6630 if (pkgOps == null) { 6631 return false; 6632 } 6633 6634 Op op = pkgOps.get(code); 6635 if (op == null) { 6636 return false; 6637 } 6638 6639 return op.isRunning(); 6640 } 6641 } 6642 6643 @Override 6644 public boolean isProxying(int op, @NonNull String proxyPackageName, 6645 @NonNull String proxyAttributionTag, int proxiedUid, 6646 @NonNull String proxiedPackageName) { 6647 Objects.requireNonNull(proxyPackageName); 6648 Objects.requireNonNull(proxiedPackageName); 6649 final long callingUid = Binder.getCallingUid(); 6650 final long identity = Binder.clearCallingIdentity(); 6651 try { 6652 final List<AppOpsManager.PackageOps> packageOps = getOpsForPackage(proxiedUid, 6653 proxiedPackageName, new int[] {op}); 6654 if (packageOps == null || packageOps.isEmpty()) { 6655 return false; 6656 } 6657 final List<OpEntry> opEntries = packageOps.get(0).getOps(); 6658 if (opEntries.isEmpty()) { 6659 return false; 6660 } 6661 final OpEntry opEntry = opEntries.get(0); 6662 if (!opEntry.isRunning()) { 6663 return false; 6664 } 6665 final OpEventProxyInfo proxyInfo = opEntry.getLastProxyInfo( 6666 OP_FLAG_TRUSTED_PROXIED | AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED); 6667 return proxyInfo != null && callingUid == proxyInfo.getUid() 6668 && proxyPackageName.equals(proxyInfo.getPackageName()) 6669 && Objects.equals(proxyAttributionTag, proxyInfo.getAttributionTag()); 6670 } finally { 6671 Binder.restoreCallingIdentity(identity); 6672 } 6673 } 6674 6675 @Override 6676 public void resetPackageOpsNoHistory(@NonNull String packageName) { 6677 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 6678 "resetPackageOpsNoHistory"); 6679 synchronized (AppOpsService.this) { 6680 final int uid = mPackageManagerInternal.getPackageUid(packageName, 0, 6681 UserHandle.getCallingUserId()); 6682 if (uid == Process.INVALID_UID) { 6683 return; 6684 } 6685 UidState uidState = mUidStates.get(uid); 6686 if (uidState == null || uidState.pkgOps == null) { 6687 return; 6688 } 6689 Ops removedOps = uidState.pkgOps.remove(packageName); 6690 if (removedOps != null) { 6691 scheduleFastWriteLocked(); 6692 } 6693 } 6694 } 6695 6696 @Override 6697 public void setHistoryParameters(@AppOpsManager.HistoricalMode int mode, 6698 long baseSnapshotInterval, int compressionStep) { 6699 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 6700 "setHistoryParameters"); 6701 // Must not hold the appops lock 6702 mHistoricalRegistry.setHistoryParameters(mode, baseSnapshotInterval, compressionStep); 6703 } 6704 6705 @Override 6706 public void offsetHistory(long offsetMillis) { 6707 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 6708 "offsetHistory"); 6709 // Must not hold the appops lock 6710 mHistoricalRegistry.offsetHistory(offsetMillis); 6711 mHistoricalRegistry.offsetDiscreteHistory(offsetMillis); 6712 } 6713 6714 @Override 6715 public void addHistoricalOps(HistoricalOps ops) { 6716 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 6717 "addHistoricalOps"); 6718 // Must not hold the appops lock 6719 mHistoricalRegistry.addHistoricalOps(ops); 6720 } 6721 6722 @Override 6723 public void resetHistoryParameters() { 6724 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 6725 "resetHistoryParameters"); 6726 // Must not hold the appops lock 6727 mHistoricalRegistry.resetHistoryParameters(); 6728 } 6729 6730 @Override 6731 public void clearHistory() { 6732 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 6733 "clearHistory"); 6734 // Must not hold the appops lock 6735 mHistoricalRegistry.clearAllHistory(); 6736 } 6737 6738 @Override 6739 public void rebootHistory(long offlineDurationMillis) { 6740 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 6741 "rebootHistory"); 6742 6743 Preconditions.checkArgument(offlineDurationMillis >= 0); 6744 6745 // Must not hold the appops lock 6746 mHistoricalRegistry.shutdown(); 6747 6748 if (offlineDurationMillis > 0) { 6749 SystemClock.sleep(offlineDurationMillis); 6750 } 6751 6752 mHistoricalRegistry = new HistoricalRegistry(mHistoricalRegistry); 6753 mHistoricalRegistry.systemReady(mContext.getContentResolver()); 6754 mHistoricalRegistry.persistPendingHistory(); 6755 } 6756 6757 /** 6758 * Report runtime access to AppOp together with message (including stack trace) 6759 * 6760 * @param packageName The package which reported the op 6761 * @param notedAppOp contains code of op and attributionTag provided by developer 6762 * @param message Message describing AppOp access (can be stack trace) 6763 * 6764 * @return Config for future sampling to reduce amount of reporting 6765 */ 6766 @Override 6767 public MessageSamplingConfig reportRuntimeAppOpAccessMessageAndGetConfig( 6768 String packageName, SyncNotedAppOp notedAppOp, String message) { 6769 int uid = Binder.getCallingUid(); 6770 Objects.requireNonNull(packageName); 6771 synchronized (this) { 6772 switchPackageIfBootTimeOrRarelyUsedLocked(packageName); 6773 if (!packageName.equals(mSampledPackage)) { 6774 return new MessageSamplingConfig(OP_NONE, 0, 6775 Instant.now().plus(1, ChronoUnit.HOURS).toEpochMilli()); 6776 } 6777 6778 Objects.requireNonNull(notedAppOp); 6779 Objects.requireNonNull(message); 6780 6781 reportRuntimeAppOpAccessMessageInternalLocked(uid, packageName, 6782 AppOpsManager.strOpToOp(notedAppOp.getOp()), 6783 notedAppOp.getAttributionTag(), message); 6784 6785 return new MessageSamplingConfig(mSampledAppOpCode, mAcceptableLeftDistance, 6786 Instant.now().plus(1, ChronoUnit.HOURS).toEpochMilli()); 6787 } 6788 } 6789 6790 /** 6791 * Report runtime access to AppOp together with message (entry point for reporting 6792 * asynchronous access) 6793 * @param uid Uid of the package which reported the op 6794 * @param packageName The package which reported the op 6795 * @param opCode Code of AppOp 6796 * @param attributionTag FeautreId of AppOp reported 6797 * @param message Message describing AppOp access (can be stack trace) 6798 */ 6799 private void reportRuntimeAppOpAccessMessageAsyncLocked(int uid, 6800 @NonNull String packageName, int opCode, @Nullable String attributionTag, 6801 @NonNull String message) { 6802 switchPackageIfBootTimeOrRarelyUsedLocked(packageName); 6803 if (!Objects.equals(mSampledPackage, packageName)) { 6804 return; 6805 } 6806 reportRuntimeAppOpAccessMessageInternalLocked(uid, packageName, opCode, attributionTag, 6807 message); 6808 } 6809 6810 /** 6811 * Decides whether reported message is within the range of watched AppOps and picks it for 6812 * reporting uniformly at random across all received messages. 6813 */ 6814 private void reportRuntimeAppOpAccessMessageInternalLocked(int uid, 6815 @NonNull String packageName, int opCode, @Nullable String attributionTag, 6816 @NonNull String message) { 6817 int newLeftDistance = AppOpsManager.leftCircularDistance(opCode, 6818 mSampledAppOpCode, _NUM_OP); 6819 6820 if (mAcceptableLeftDistance < newLeftDistance 6821 && mSamplingStrategy != SAMPLING_STRATEGY_UNIFORM_OPS) { 6822 return; 6823 } 6824 6825 if (mAcceptableLeftDistance > newLeftDistance 6826 && mSamplingStrategy != SAMPLING_STRATEGY_UNIFORM_OPS) { 6827 mAcceptableLeftDistance = newLeftDistance; 6828 mMessagesCollectedCount = 0.0f; 6829 } 6830 6831 mMessagesCollectedCount += 1.0f; 6832 if (ThreadLocalRandom.current().nextFloat() <= 1.0f / mMessagesCollectedCount) { 6833 mCollectedRuntimePermissionMessage = new RuntimeAppOpAccessMessage(uid, opCode, 6834 packageName, attributionTag, message, mSamplingStrategy); 6835 } 6836 return; 6837 } 6838 6839 /** Pulls current AppOps access report and resamples package and app op to watch */ 6840 @Override 6841 public @Nullable RuntimeAppOpAccessMessage collectRuntimeAppOpAccessMessage() { 6842 ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class); 6843 boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(Binder.getCallingUid()); 6844 boolean isCallerSystem = Binder.getCallingPid() == Process.myPid(); 6845 if (!isCallerSystem && !isCallerInstrumented) { 6846 return null; 6847 } 6848 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 6849 Binder.getCallingPid(), Binder.getCallingUid(), null); 6850 RuntimeAppOpAccessMessage result; 6851 synchronized (this) { 6852 result = mCollectedRuntimePermissionMessage; 6853 mCollectedRuntimePermissionMessage = null; 6854 } 6855 mHandler.sendMessage(PooledLambda.obtainMessage( 6856 AppOpsService::getPackageListAndResample, 6857 this)); 6858 return result; 6859 } 6860 6861 /** 6862 * Checks if package is in the list of rarely used package and starts watching the new package 6863 * to collect incoming message or if collection is happening in first minutes since boot. 6864 * @param packageName 6865 */ 6866 private void switchPackageIfBootTimeOrRarelyUsedLocked(@NonNull String packageName) { 6867 if (mSampledPackage == null) { 6868 if (ThreadLocalRandom.current().nextFloat() < 0.5f) { 6869 mSamplingStrategy = SAMPLING_STRATEGY_BOOT_TIME_SAMPLING; 6870 resampleAppOpForPackageLocked(packageName, true); 6871 } 6872 } else if (mRarelyUsedPackages.contains(packageName)) { 6873 mRarelyUsedPackages.remove(packageName); 6874 if (ThreadLocalRandom.current().nextFloat() < 0.5f) { 6875 mSamplingStrategy = SAMPLING_STRATEGY_RARELY_USED; 6876 resampleAppOpForPackageLocked(packageName, true); 6877 } 6878 } 6879 } 6880 6881 /** Obtains package list and resamples package and appop to watch. */ 6882 private List<String> getPackageListAndResample() { 6883 List<String> packageNames = getPackageNamesForSampling(); 6884 synchronized (this) { 6885 resamplePackageAndAppOpLocked(packageNames); 6886 } 6887 return packageNames; 6888 } 6889 6890 /** Resamples package and appop to watch from the list provided. */ 6891 private void resamplePackageAndAppOpLocked(@NonNull List<String> packageNames) { 6892 if (!packageNames.isEmpty()) { 6893 if (ThreadLocalRandom.current().nextFloat() < 0.5f) { 6894 mSamplingStrategy = SAMPLING_STRATEGY_UNIFORM; 6895 resampleAppOpForPackageLocked(packageNames.get( 6896 ThreadLocalRandom.current().nextInt(packageNames.size())), true); 6897 } else { 6898 mSamplingStrategy = SAMPLING_STRATEGY_UNIFORM_OPS; 6899 resampleAppOpForPackageLocked(packageNames.get( 6900 ThreadLocalRandom.current().nextInt(packageNames.size())), false); 6901 } 6902 } 6903 } 6904 6905 /** Resamples appop for the chosen package and initializes sampling state */ 6906 private void resampleAppOpForPackageLocked(@NonNull String packageName, boolean pickOp) { 6907 mMessagesCollectedCount = 0.0f; 6908 mSampledAppOpCode = pickOp ? ThreadLocalRandom.current().nextInt(_NUM_OP) : OP_NONE; 6909 mAcceptableLeftDistance = _NUM_OP - 1; 6910 mSampledPackage = packageName; 6911 } 6912 6913 /** 6914 * Creates list of rarely used packages - packages which were not used over last week or 6915 * which declared but did not use permissions over last week. 6916 * */ 6917 private void initializeRarelyUsedPackagesList(@NonNull ArraySet<String> candidates) { 6918 AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); 6919 List<String> runtimeAppOpsList = getRuntimeAppOpsList(); 6920 AppOpsManager.HistoricalOpsRequest histOpsRequest = 6921 new AppOpsManager.HistoricalOpsRequest.Builder( 6922 Math.max(Instant.now().minus(7, ChronoUnit.DAYS).toEpochMilli(), 0), 6923 Long.MAX_VALUE).setOpNames(runtimeAppOpsList).setFlags( 6924 OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED).build(); 6925 appOps.getHistoricalOps(histOpsRequest, AsyncTask.THREAD_POOL_EXECUTOR, 6926 new Consumer<HistoricalOps>() { 6927 @Override 6928 public void accept(HistoricalOps histOps) { 6929 int uidCount = histOps.getUidCount(); 6930 for (int uidIdx = 0; uidIdx < uidCount; uidIdx++) { 6931 final AppOpsManager.HistoricalUidOps uidOps = histOps.getUidOpsAt( 6932 uidIdx); 6933 int pkgCount = uidOps.getPackageCount(); 6934 for (int pkgIdx = 0; pkgIdx < pkgCount; pkgIdx++) { 6935 String packageName = uidOps.getPackageOpsAt( 6936 pkgIdx).getPackageName(); 6937 if (!candidates.contains(packageName)) { 6938 continue; 6939 } 6940 AppOpsManager.HistoricalPackageOps packageOps = 6941 uidOps.getPackageOpsAt(pkgIdx); 6942 if (packageOps.getOpCount() != 0) { 6943 candidates.remove(packageName); 6944 } 6945 } 6946 } 6947 synchronized (this) { 6948 int numPkgs = mRarelyUsedPackages.size(); 6949 for (int i = 0; i < numPkgs; i++) { 6950 candidates.add(mRarelyUsedPackages.valueAt(i)); 6951 } 6952 mRarelyUsedPackages = candidates; 6953 } 6954 } 6955 }); 6956 } 6957 6958 /** List of app ops related to runtime permissions */ 6959 private List<String> getRuntimeAppOpsList() { 6960 ArrayList<String> result = new ArrayList(); 6961 for (int i = 0; i < _NUM_OP; i++) { 6962 if (shouldCollectNotes(i)) { 6963 result.add(opToPublicName(i)); 6964 } 6965 } 6966 return result; 6967 } 6968 6969 /** Returns list of packages to be used for package sampling */ 6970 private @NonNull List<String> getPackageNamesForSampling() { 6971 List<String> packageNames = new ArrayList<>(); 6972 PackageManagerInternal packageManagerInternal = LocalServices.getService( 6973 PackageManagerInternal.class); 6974 PackageList packages = packageManagerInternal.getPackageList(); 6975 for (String packageName : packages.getPackageNames()) { 6976 PackageInfo pkg = packageManagerInternal.getPackageInfo(packageName, 6977 PackageManager.GET_PERMISSIONS, Process.myUid(), mContext.getUserId()); 6978 if (isSamplingTarget(pkg)) { 6979 packageNames.add(pkg.packageName); 6980 } 6981 } 6982 return packageNames; 6983 } 6984 6985 /** Checks whether package should be included in sampling pool */ 6986 private boolean isSamplingTarget(@Nullable PackageInfo pkg) { 6987 if (pkg == null) { 6988 return false; 6989 } 6990 String[] requestedPermissions = pkg.requestedPermissions; 6991 if (requestedPermissions == null) { 6992 return false; 6993 } 6994 for (String permission : requestedPermissions) { 6995 PermissionInfo permissionInfo; 6996 try { 6997 permissionInfo = mContext.getPackageManager().getPermissionInfo(permission, 0); 6998 } catch (PackageManager.NameNotFoundException ignored) { 6999 continue; 7000 } 7001 if (permissionInfo.getProtection() == PROTECTION_DANGEROUS) { 7002 return true; 7003 } 7004 } 7005 return false; 7006 } 7007 7008 private void removeUidsForUserLocked(int userHandle) { 7009 for (int i = mUidStates.size() - 1; i >= 0; --i) { 7010 final int uid = mUidStates.keyAt(i); 7011 if (UserHandle.getUserId(uid) == userHandle) { 7012 mUidStates.removeAt(i); 7013 } 7014 } 7015 } 7016 7017 private void checkSystemUid(String function) { 7018 int uid = Binder.getCallingUid(); 7019 if (uid != Process.SYSTEM_UID) { 7020 throw new SecurityException(function + " must by called by the system"); 7021 } 7022 } 7023 7024 private static int resolveUid(String packageName) { 7025 if (packageName == null) { 7026 return -1; 7027 } 7028 switch (packageName) { 7029 case "root": 7030 return Process.ROOT_UID; 7031 case "shell": 7032 case "dumpstate": 7033 return Process.SHELL_UID; 7034 case "media": 7035 return Process.MEDIA_UID; 7036 case "audioserver": 7037 return Process.AUDIOSERVER_UID; 7038 case "cameraserver": 7039 return Process.CAMERASERVER_UID; 7040 } 7041 return -1; 7042 } 7043 7044 private static String[] getPackagesForUid(int uid) { 7045 String[] packageNames = null; 7046 7047 // Very early during boot the package manager is not yet or not yet fully started. At this 7048 // time there are no packages yet. 7049 if (AppGlobals.getPackageManager() != null) { 7050 try { 7051 packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid); 7052 } catch (RemoteException e) { 7053 /* ignore - local call */ 7054 } 7055 } 7056 if (packageNames == null) { 7057 return EmptyArray.STRING; 7058 } 7059 return packageNames; 7060 } 7061 7062 private final class ClientUserRestrictionState implements DeathRecipient { 7063 private final IBinder token; 7064 SparseArray<boolean[]> perUserRestrictions; 7065 SparseArray<PackageTagsList> perUserExcludedPackageTags; 7066 7067 ClientUserRestrictionState(IBinder token) 7068 throws RemoteException { 7069 token.linkToDeath(this, 0); 7070 this.token = token; 7071 } 7072 7073 public boolean setRestriction(int code, boolean restricted, 7074 PackageTagsList excludedPackageTags, int userId) { 7075 boolean changed = false; 7076 7077 if (perUserRestrictions == null && restricted) { 7078 perUserRestrictions = new SparseArray<>(); 7079 } 7080 7081 int[] users; 7082 if (userId == UserHandle.USER_ALL) { 7083 // TODO(b/162888972): this call is returning all users, not just live ones - we 7084 // need to either fix the method called, or rename the variable 7085 List<UserInfo> liveUsers = UserManager.get(mContext).getUsers(); 7086 7087 users = new int[liveUsers.size()]; 7088 for (int i = 0; i < liveUsers.size(); i++) { 7089 users[i] = liveUsers.get(i).id; 7090 } 7091 } else { 7092 users = new int[]{userId}; 7093 } 7094 7095 if (perUserRestrictions != null) { 7096 int numUsers = users.length; 7097 7098 for (int i = 0; i < numUsers; i++) { 7099 int thisUserId = users[i]; 7100 7101 boolean[] userRestrictions = perUserRestrictions.get(thisUserId); 7102 if (userRestrictions == null && restricted) { 7103 userRestrictions = new boolean[AppOpsManager._NUM_OP]; 7104 perUserRestrictions.put(thisUserId, userRestrictions); 7105 } 7106 if (userRestrictions != null && userRestrictions[code] != restricted) { 7107 userRestrictions[code] = restricted; 7108 if (!restricted && isDefault(userRestrictions)) { 7109 perUserRestrictions.remove(thisUserId); 7110 userRestrictions = null; 7111 } 7112 changed = true; 7113 } 7114 7115 if (userRestrictions != null) { 7116 final boolean noExcludedPackages = 7117 excludedPackageTags == null || excludedPackageTags.isEmpty(); 7118 if (perUserExcludedPackageTags == null && !noExcludedPackages) { 7119 perUserExcludedPackageTags = new SparseArray<>(); 7120 } 7121 if (perUserExcludedPackageTags != null) { 7122 if (noExcludedPackages) { 7123 perUserExcludedPackageTags.remove(thisUserId); 7124 if (perUserExcludedPackageTags.size() <= 0) { 7125 perUserExcludedPackageTags = null; 7126 } 7127 } else { 7128 perUserExcludedPackageTags.put(thisUserId, excludedPackageTags); 7129 } 7130 changed = true; 7131 } 7132 } 7133 } 7134 } 7135 7136 return changed; 7137 } 7138 7139 public boolean hasRestriction(int restriction, String packageName, String attributionTag, 7140 int userId) { 7141 if (perUserRestrictions == null) { 7142 return false; 7143 } 7144 boolean[] restrictions = perUserRestrictions.get(userId); 7145 if (restrictions == null) { 7146 return false; 7147 } 7148 if (!restrictions[restriction]) { 7149 return false; 7150 } 7151 if (perUserExcludedPackageTags == null) { 7152 return true; 7153 } 7154 PackageTagsList perUserExclusions = perUserExcludedPackageTags.get(userId); 7155 if (perUserExclusions == null) { 7156 return true; 7157 } 7158 7159 return !perUserExclusions.contains(packageName, attributionTag); 7160 } 7161 7162 public void removeUser(int userId) { 7163 if (perUserExcludedPackageTags != null) { 7164 perUserExcludedPackageTags.remove(userId); 7165 if (perUserExcludedPackageTags.size() <= 0) { 7166 perUserExcludedPackageTags = null; 7167 } 7168 } 7169 if (perUserRestrictions != null) { 7170 perUserRestrictions.remove(userId); 7171 if (perUserRestrictions.size() <= 0) { 7172 perUserRestrictions = null; 7173 } 7174 } 7175 } 7176 7177 public boolean isDefault() { 7178 return perUserRestrictions == null || perUserRestrictions.size() <= 0; 7179 } 7180 7181 @Override 7182 public void binderDied() { 7183 synchronized (AppOpsService.this) { 7184 mOpUserRestrictions.remove(token); 7185 if (perUserRestrictions == null) { 7186 return; 7187 } 7188 final int userCount = perUserRestrictions.size(); 7189 for (int i = 0; i < userCount; i++) { 7190 final boolean[] restrictions = perUserRestrictions.valueAt(i); 7191 final int restrictionCount = restrictions.length; 7192 for (int j = 0; j < restrictionCount; j++) { 7193 if (restrictions[j]) { 7194 final int changedCode = j; 7195 mHandler.post(() -> notifyWatchersOfChange(changedCode, UID_ANY)); 7196 } 7197 } 7198 } 7199 destroy(); 7200 } 7201 } 7202 7203 public void destroy() { 7204 token.unlinkToDeath(this, 0); 7205 } 7206 7207 private boolean isDefault(boolean[] array) { 7208 if (ArrayUtils.isEmpty(array)) { 7209 return true; 7210 } 7211 for (boolean value : array) { 7212 if (value) { 7213 return false; 7214 } 7215 } 7216 return true; 7217 } 7218 } 7219 7220 private final class ClientGlobalRestrictionState implements DeathRecipient { 7221 final IBinder mToken; 7222 final ArraySet<Integer> mRestrictedOps = new ArraySet<>(); 7223 7224 ClientGlobalRestrictionState(IBinder token) 7225 throws RemoteException { 7226 token.linkToDeath(this, 0); 7227 this.mToken = token; 7228 } 7229 7230 boolean setRestriction(int code, boolean restricted) { 7231 if (restricted) { 7232 return mRestrictedOps.add(code); 7233 } else { 7234 return mRestrictedOps.remove(code); 7235 } 7236 } 7237 7238 boolean hasRestriction(int code) { 7239 return mRestrictedOps.contains(code); 7240 } 7241 7242 boolean isDefault() { 7243 return mRestrictedOps.isEmpty(); 7244 } 7245 7246 @Override 7247 public void binderDied() { 7248 destroy(); 7249 } 7250 7251 void destroy() { 7252 mToken.unlinkToDeath(this, 0); 7253 } 7254 } 7255 7256 private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal { 7257 @Override public void setDeviceAndProfileOwners(SparseIntArray owners) { 7258 synchronized (AppOpsService.this) { 7259 mProfileOwners = owners; 7260 } 7261 } 7262 7263 @Override 7264 public void updateAppWidgetVisibility(SparseArray<String> uidPackageNames, 7265 boolean visible) { 7266 AppOpsService.this.updateAppWidgetVisibility(uidPackageNames, visible); 7267 } 7268 7269 @Override 7270 public void setUidModeFromPermissionPolicy(int code, int uid, int mode, 7271 @Nullable IAppOpsCallback callback) { 7272 setUidMode(code, uid, mode, callback); 7273 } 7274 7275 @Override 7276 public void setModeFromPermissionPolicy(int code, int uid, @NonNull String packageName, 7277 int mode, @Nullable IAppOpsCallback callback) { 7278 setMode(code, uid, packageName, mode, callback); 7279 } 7280 7281 7282 @Override 7283 public void setGlobalRestriction(int code, boolean restricted, IBinder token) { 7284 if (Binder.getCallingPid() != Process.myPid()) { 7285 // TODO instead of this enforcement put in AppOpsManagerInternal 7286 throw new SecurityException("Only the system can set global restrictions"); 7287 } 7288 7289 synchronized (AppOpsService.this) { 7290 ClientGlobalRestrictionState restrictionState = mOpGlobalRestrictions.get(token); 7291 7292 if (restrictionState == null) { 7293 try { 7294 restrictionState = new ClientGlobalRestrictionState(token); 7295 } catch (RemoteException e) { 7296 return; 7297 } 7298 mOpGlobalRestrictions.put(token, restrictionState); 7299 } 7300 7301 if (restrictionState.setRestriction(code, restricted)) { 7302 mHandler.sendMessage(PooledLambda.obtainMessage( 7303 AppOpsService::notifyWatchersOfChange, AppOpsService.this, code, 7304 UID_ANY)); 7305 mHandler.sendMessage(PooledLambda.obtainMessage( 7306 AppOpsService::updateStartedOpModeForUser, AppOpsService.this, 7307 code, restricted, UserHandle.USER_ALL)); 7308 } 7309 7310 if (restrictionState.isDefault()) { 7311 mOpGlobalRestrictions.remove(token); 7312 restrictionState.destroy(); 7313 } 7314 } 7315 } 7316 7317 @Override 7318 public int getOpRestrictionCount(int code, UserHandle user, String pkg, 7319 String attributionTag) { 7320 int number = 0; 7321 synchronized (AppOpsService.this) { 7322 int numRestrictions = mOpUserRestrictions.size(); 7323 for (int i = 0; i < numRestrictions; i++) { 7324 if (mOpUserRestrictions.valueAt(i) 7325 .hasRestriction(code, pkg, attributionTag, user.getIdentifier())) { 7326 number++; 7327 } 7328 } 7329 7330 numRestrictions = mOpGlobalRestrictions.size(); 7331 for (int i = 0; i < numRestrictions; i++) { 7332 if (mOpGlobalRestrictions.valueAt(i).hasRestriction(code)) { 7333 number++; 7334 } 7335 } 7336 } 7337 7338 return number; 7339 } 7340 } 7341 7342 /** 7343 * Async task for writing note op stack trace, op code, package name and version to file 7344 * More specifically, writes all the collected ops from {@link #mNoteOpCallerStacktraces} 7345 */ 7346 private void writeNoteOps() { 7347 synchronized (this) { 7348 mWriteNoteOpsScheduled = false; 7349 } 7350 synchronized (mNoteOpCallerStacktracesFile) { 7351 try (FileWriter writer = new FileWriter(mNoteOpCallerStacktracesFile)) { 7352 int numTraces = mNoteOpCallerStacktraces.size(); 7353 for (int i = 0; i < numTraces; i++) { 7354 // Writing json formatted string into file 7355 writer.write(mNoteOpCallerStacktraces.valueAt(i).asJson()); 7356 // Comma separation, so we can wrap the entire log as a JSON object 7357 // when all results are collected 7358 writer.write(","); 7359 } 7360 } catch (IOException e) { 7361 Slog.w(TAG, "Failed to load opsValidation file for FileWriter", e); 7362 } 7363 } 7364 } 7365 7366 /** 7367 * This class represents a NoteOp Trace object amd contains the necessary fields that will 7368 * be written to file to use for permissions data validation in JSON format 7369 */ 7370 @Immutable 7371 static class NoteOpTrace { 7372 static final String STACKTRACE = "stackTrace"; 7373 static final String OP = "op"; 7374 static final String PACKAGENAME = "packageName"; 7375 static final String VERSION = "version"; 7376 7377 private final @NonNull String mStackTrace; 7378 private final int mOp; 7379 private final @Nullable String mPackageName; 7380 private final long mVersion; 7381 7382 /** 7383 * Initialize a NoteOp object using a JSON object containing the necessary fields 7384 * 7385 * @param jsonTrace JSON object represented as a string 7386 * 7387 * @return NoteOpTrace object initialized with JSON fields 7388 */ 7389 static NoteOpTrace fromJson(String jsonTrace) { 7390 try { 7391 // Re-add closing bracket which acted as a delimiter by the reader 7392 JSONObject obj = new JSONObject(jsonTrace.concat("}")); 7393 return new NoteOpTrace(obj.getString(STACKTRACE), obj.getInt(OP), 7394 obj.getString(PACKAGENAME), obj.getLong(VERSION)); 7395 } catch (JSONException e) { 7396 // Swallow error, only meant for logging ops, should not affect flow of the code 7397 Slog.e(TAG, "Error constructing NoteOpTrace object " 7398 + "JSON trace format incorrect", e); 7399 return null; 7400 } 7401 } 7402 7403 NoteOpTrace(String stackTrace, int op, String packageName, long version) { 7404 mStackTrace = stackTrace; 7405 mOp = op; 7406 mPackageName = packageName; 7407 mVersion = version; 7408 } 7409 7410 @Override 7411 public boolean equals(Object o) { 7412 if (this == o) return true; 7413 if (o == null || getClass() != o.getClass()) return false; 7414 NoteOpTrace that = (NoteOpTrace) o; 7415 return mOp == that.mOp 7416 && mVersion == that.mVersion 7417 && mStackTrace.equals(that.mStackTrace) 7418 && Objects.equals(mPackageName, that.mPackageName); 7419 } 7420 7421 @Override 7422 public int hashCode() { 7423 return Objects.hash(mStackTrace, mOp, mPackageName, mVersion); 7424 } 7425 7426 /** 7427 * The object is formatted as a JSON object and returned as a String 7428 * 7429 * @return JSON formatted string 7430 */ 7431 public String asJson() { 7432 return "{" 7433 + "\"" + STACKTRACE + "\":\"" + mStackTrace.replace("\n", "\\n") 7434 + '\"' + ",\"" + OP + "\":" + mOp 7435 + ",\"" + PACKAGENAME + "\":\"" + mPackageName + '\"' 7436 + ",\"" + VERSION + "\":" + mVersion 7437 + '}'; 7438 } 7439 } 7440 7441 /** 7442 * Collects noteOps, noteProxyOps and startOps from AppOpsManager and writes it into a file 7443 * which will be used for permissions data validation, the given parameters to this method 7444 * will be logged in json format 7445 * 7446 * @param stackTrace stacktrace from the most recent call in AppOpsManager 7447 * @param op op code 7448 * @param packageName package making call 7449 * @param version android version for this call 7450 */ 7451 @Override 7452 public void collectNoteOpCallsForValidation(String stackTrace, int op, String packageName, 7453 long version) { 7454 if (!AppOpsManager.NOTE_OP_COLLECTION_ENABLED) { 7455 return; 7456 } 7457 7458 Objects.requireNonNull(stackTrace); 7459 Preconditions.checkArgument(op >= 0); 7460 Preconditions.checkArgument(op < AppOpsManager._NUM_OP); 7461 Objects.requireNonNull(version); 7462 7463 NoteOpTrace noteOpTrace = new NoteOpTrace(stackTrace, op, packageName, version); 7464 7465 boolean noteOpSetWasChanged; 7466 synchronized (this) { 7467 noteOpSetWasChanged = mNoteOpCallerStacktraces.add(noteOpTrace); 7468 if (noteOpSetWasChanged && !mWriteNoteOpsScheduled) { 7469 mWriteNoteOpsScheduled = true; 7470 mHandler.postDelayed(PooledLambda.obtainRunnable((that) -> { 7471 AsyncTask.execute(() -> { 7472 that.writeNoteOps(); 7473 }); 7474 }, this), 2500); 7475 } 7476 } 7477 } 7478 7479 @Immutable 7480 private final class CheckOpsDelegateDispatcher { 7481 private final @Nullable CheckOpsDelegate mPolicy; 7482 private final @Nullable CheckOpsDelegate mCheckOpsDelegate; 7483 7484 CheckOpsDelegateDispatcher(@Nullable CheckOpsDelegate policy, 7485 @Nullable CheckOpsDelegate checkOpsDelegate) { 7486 mPolicy = policy; 7487 mCheckOpsDelegate = checkOpsDelegate; 7488 } 7489 7490 public @NonNull CheckOpsDelegate getCheckOpsDelegate() { 7491 return mCheckOpsDelegate; 7492 } 7493 7494 public int checkOperation(int code, int uid, String packageName, 7495 @Nullable String attributionTag, boolean raw) { 7496 if (mPolicy != null) { 7497 if (mCheckOpsDelegate != null) { 7498 return mPolicy.checkOperation(code, uid, packageName, attributionTag, raw, 7499 this::checkDelegateOperationImpl); 7500 } else { 7501 return mPolicy.checkOperation(code, uid, packageName, attributionTag, raw, 7502 AppOpsService.this::checkOperationImpl); 7503 } 7504 } else if (mCheckOpsDelegate != null) { 7505 return checkDelegateOperationImpl(code, uid, packageName, attributionTag, raw); 7506 } 7507 return checkOperationImpl(code, uid, packageName, attributionTag, raw); 7508 } 7509 7510 private int checkDelegateOperationImpl(int code, int uid, String packageName, 7511 @Nullable String attributionTag, boolean raw) { 7512 return mCheckOpsDelegate.checkOperation(code, uid, packageName, attributionTag, raw, 7513 AppOpsService.this::checkOperationImpl); 7514 } 7515 7516 public int checkAudioOperation(int code, int usage, int uid, String packageName) { 7517 if (mPolicy != null) { 7518 if (mCheckOpsDelegate != null) { 7519 return mPolicy.checkAudioOperation(code, usage, uid, packageName, 7520 this::checkDelegateAudioOperationImpl); 7521 } else { 7522 return mPolicy.checkAudioOperation(code, usage, uid, packageName, 7523 AppOpsService.this::checkAudioOperationImpl); 7524 } 7525 } else if (mCheckOpsDelegate != null) { 7526 return checkDelegateAudioOperationImpl(code, usage, uid, packageName); 7527 } 7528 return checkAudioOperationImpl(code, usage, uid, packageName); 7529 } 7530 7531 private int checkDelegateAudioOperationImpl(int code, int usage, int uid, 7532 String packageName) { 7533 return mCheckOpsDelegate.checkAudioOperation(code, usage, uid, packageName, 7534 AppOpsService.this::checkAudioOperationImpl); 7535 } 7536 7537 public SyncNotedAppOp noteOperation(int code, int uid, String packageName, 7538 String attributionTag, boolean shouldCollectAsyncNotedOp, String message, 7539 boolean shouldCollectMessage) { 7540 if (mPolicy != null) { 7541 if (mCheckOpsDelegate != null) { 7542 return mPolicy.noteOperation(code, uid, packageName, attributionTag, 7543 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 7544 this::noteDelegateOperationImpl); 7545 } else { 7546 return mPolicy.noteOperation(code, uid, packageName, attributionTag, 7547 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 7548 AppOpsService.this::noteOperationImpl); 7549 } 7550 } else if (mCheckOpsDelegate != null) { 7551 return noteDelegateOperationImpl(code, uid, packageName, 7552 attributionTag, shouldCollectAsyncNotedOp, message, shouldCollectMessage); 7553 } 7554 return noteOperationImpl(code, uid, packageName, attributionTag, 7555 shouldCollectAsyncNotedOp, message, shouldCollectMessage); 7556 } 7557 7558 private SyncNotedAppOp noteDelegateOperationImpl(int code, int uid, 7559 @Nullable String packageName, @Nullable String featureId, 7560 boolean shouldCollectAsyncNotedOp, @Nullable String message, 7561 boolean shouldCollectMessage) { 7562 return mCheckOpsDelegate.noteOperation(code, uid, packageName, featureId, 7563 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 7564 AppOpsService.this::noteOperationImpl); 7565 } 7566 7567 public SyncNotedAppOp noteProxyOperation(int code, AttributionSource attributionSource, 7568 boolean shouldCollectAsyncNotedOp, @Nullable String message, 7569 boolean shouldCollectMessage, boolean skipProxyOperation) { 7570 if (mPolicy != null) { 7571 if (mCheckOpsDelegate != null) { 7572 return mPolicy.noteProxyOperation(code, attributionSource, 7573 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 7574 skipProxyOperation, this::noteDelegateProxyOperationImpl); 7575 } else { 7576 return mPolicy.noteProxyOperation(code, attributionSource, 7577 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 7578 skipProxyOperation, AppOpsService.this::noteProxyOperationImpl); 7579 } 7580 } else if (mCheckOpsDelegate != null) { 7581 return noteDelegateProxyOperationImpl(code, 7582 attributionSource, shouldCollectAsyncNotedOp, message, 7583 shouldCollectMessage, skipProxyOperation); 7584 } 7585 return noteProxyOperationImpl(code, attributionSource, shouldCollectAsyncNotedOp, 7586 message, shouldCollectMessage,skipProxyOperation); 7587 } 7588 7589 private SyncNotedAppOp noteDelegateProxyOperationImpl(int code, 7590 @NonNull AttributionSource attributionSource, boolean shouldCollectAsyncNotedOp, 7591 @Nullable String message, boolean shouldCollectMessage, 7592 boolean skipProxyOperation) { 7593 return mCheckOpsDelegate.noteProxyOperation(code, attributionSource, 7594 shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, 7595 AppOpsService.this::noteProxyOperationImpl); 7596 } 7597 7598 public SyncNotedAppOp startOperation(IBinder token, int code, int uid, 7599 @Nullable String packageName, @NonNull String attributionTag, 7600 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, 7601 @Nullable String message, boolean shouldCollectMessage, 7602 @AttributionFlags int attributionFlags, int attributionChainId) { 7603 if (mPolicy != null) { 7604 if (mCheckOpsDelegate != null) { 7605 return mPolicy.startOperation(token, code, uid, packageName, 7606 attributionTag, startIfModeDefault, shouldCollectAsyncNotedOp, message, 7607 shouldCollectMessage, attributionFlags, attributionChainId, 7608 this::startDelegateOperationImpl); 7609 } else { 7610 return mPolicy.startOperation(token, code, uid, packageName, attributionTag, 7611 startIfModeDefault, shouldCollectAsyncNotedOp, message, 7612 shouldCollectMessage, attributionFlags, attributionChainId, 7613 AppOpsService.this::startOperationImpl); 7614 } 7615 } else if (mCheckOpsDelegate != null) { 7616 return startDelegateOperationImpl(token, code, uid, packageName, attributionTag, 7617 startIfModeDefault, shouldCollectAsyncNotedOp, message, 7618 shouldCollectMessage, attributionFlags, attributionChainId); 7619 } 7620 return startOperationImpl(token, code, uid, packageName, attributionTag, 7621 startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, 7622 attributionFlags, attributionChainId); 7623 } 7624 7625 private SyncNotedAppOp startDelegateOperationImpl(IBinder token, int code, int uid, 7626 @Nullable String packageName, @Nullable String attributionTag, 7627 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, 7628 boolean shouldCollectMessage, @AttributionFlags int attributionFlags, 7629 int attributionChainId) { 7630 return mCheckOpsDelegate.startOperation(token, code, uid, packageName, attributionTag, 7631 startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, 7632 attributionFlags, attributionChainId, AppOpsService.this::startOperationImpl); 7633 } 7634 7635 public SyncNotedAppOp startProxyOperation(int code, 7636 @NonNull AttributionSource attributionSource, boolean startIfModeDefault, 7637 boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, 7638 boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, 7639 @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { 7640 if (mPolicy != null) { 7641 if (mCheckOpsDelegate != null) { 7642 return mPolicy.startProxyOperation(code, attributionSource, 7643 startIfModeDefault, shouldCollectAsyncNotedOp, message, 7644 shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, 7645 proxiedAttributionFlags, attributionChainId, 7646 this::startDelegateProxyOperationImpl); 7647 } else { 7648 return mPolicy.startProxyOperation(code, attributionSource, 7649 startIfModeDefault, shouldCollectAsyncNotedOp, message, 7650 shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, 7651 proxiedAttributionFlags, attributionChainId, 7652 AppOpsService.this::startProxyOperationImpl); 7653 } 7654 } else if (mCheckOpsDelegate != null) { 7655 return startDelegateProxyOperationImpl(code, attributionSource, 7656 startIfModeDefault, shouldCollectAsyncNotedOp, message, 7657 shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, 7658 proxiedAttributionFlags, attributionChainId); 7659 } 7660 return startProxyOperationImpl(code, attributionSource, startIfModeDefault, 7661 shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, 7662 proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); 7663 } 7664 7665 private SyncNotedAppOp startDelegateProxyOperationImpl(int code, 7666 @NonNull AttributionSource attributionSource, boolean startIfModeDefault, 7667 boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, 7668 boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, 7669 @AttributionFlags int proxiedAttributionFlsgs, int attributionChainId) { 7670 return mCheckOpsDelegate.startProxyOperation(code, attributionSource, 7671 startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, 7672 skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlsgs, 7673 attributionChainId, AppOpsService.this::startProxyOperationImpl); 7674 } 7675 7676 public void finishOperation(IBinder clientId, int code, int uid, String packageName, 7677 String attributionTag) { 7678 if (mPolicy != null) { 7679 if (mCheckOpsDelegate != null) { 7680 mPolicy.finishOperation(clientId, code, uid, packageName, attributionTag, 7681 this::finishDelegateOperationImpl); 7682 } else { 7683 mPolicy.finishOperation(clientId, code, uid, packageName, attributionTag, 7684 AppOpsService.this::finishOperationImpl); 7685 } 7686 } else if (mCheckOpsDelegate != null) { 7687 finishDelegateOperationImpl(clientId, code, uid, packageName, attributionTag); 7688 } else { 7689 finishOperationImpl(clientId, code, uid, packageName, attributionTag); 7690 } 7691 } 7692 7693 private void finishDelegateOperationImpl(IBinder clientId, int code, int uid, 7694 String packageName, String attributionTag) { 7695 mCheckOpsDelegate.finishOperation(clientId, code, uid, packageName, attributionTag, 7696 AppOpsService.this::finishOperationImpl); 7697 } 7698 7699 public void finishProxyOperation(int code, 7700 @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { 7701 if (mPolicy != null) { 7702 if (mCheckOpsDelegate != null) { 7703 mPolicy.finishProxyOperation(code, attributionSource, 7704 skipProxyOperation, this::finishDelegateProxyOperationImpl); 7705 } else { 7706 mPolicy.finishProxyOperation(code, attributionSource, 7707 skipProxyOperation, AppOpsService.this::finishProxyOperationImpl); 7708 } 7709 } else if (mCheckOpsDelegate != null) { 7710 finishDelegateProxyOperationImpl(code, attributionSource, skipProxyOperation); 7711 } else { 7712 finishProxyOperationImpl(code, attributionSource, skipProxyOperation); 7713 } 7714 } 7715 7716 private Void finishDelegateProxyOperationImpl(int code, 7717 @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { 7718 mCheckOpsDelegate.finishProxyOperation(code, attributionSource, skipProxyOperation, 7719 AppOpsService.this::finishProxyOperationImpl); 7720 return null; 7721 } 7722 } 7723 } 7724