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