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