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