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