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