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 2644 synchronized (this) { 2645 final Ops ops = getOpsLocked(uid, packageName, attributionTag, 2646 pvr.isAttributionTagValid, pvr.bypass, /* edit */ true); 2647 if (ops == null) { 2648 scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags, 2649 AppOpsManager.MODE_IGNORED); 2650 if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid 2651 + " package " + packageName + "flags: " + 2652 AppOpsManager.flagsToString(flags)); 2653 return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, 2654 packageName); 2655 } 2656 final Op op = getOpLocked(ops, code, uid, true); 2657 final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag); 2658 if (attributedOp.isRunning()) { 2659 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName + " code " 2660 + code + " startTime of in progress event=" 2661 + attributedOp.mInProgressEvents.valueAt(0).getStartTime()); 2662 } 2663 2664 final int switchCode = AppOpsManager.opToSwitch(code); 2665 final UidState uidState = ops.uidState; 2666 if (isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass, false)) { 2667 attributedOp.rejected(uidState.getState(), flags); 2668 scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags, 2669 AppOpsManager.MODE_IGNORED); 2670 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag, 2671 packageName); 2672 } 2673 // If there is a non-default per UID policy (we set UID op mode only if 2674 // non-default) it takes over, otherwise use the per package policy. 2675 if (uidState.getUidMode(switchCode) != AppOpsManager.opToDefaultMode(switchCode)) { 2676 final int uidMode = uidState.evalMode(code, uidState.getUidMode(switchCode)); 2677 if (uidMode != AppOpsManager.MODE_ALLOWED) { 2678 if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code " 2679 + switchCode + " (" + code + ") uid " + uid + " package " 2680 + packageName + " flags: " + AppOpsManager.flagsToString(flags)); 2681 attributedOp.rejected(uidState.getState(), flags); 2682 scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags, 2683 uidMode); 2684 return new SyncNotedAppOp(uidMode, code, attributionTag, packageName); 2685 } 2686 } else { 2687 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, uid, true) 2688 : op; 2689 final int mode = switchOp.uidState.evalMode(switchOp.op, switchOp.getMode()); 2690 if (mode != AppOpsManager.MODE_ALLOWED) { 2691 if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code " 2692 + switchCode + " (" + code + ") uid " + uid + " package " 2693 + packageName + " flags: " + AppOpsManager.flagsToString(flags)); 2694 attributedOp.rejected(uidState.getState(), flags); 2695 scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags, 2696 mode); 2697 return new SyncNotedAppOp(mode, code, attributionTag, packageName); 2698 } 2699 } 2700 if (DEBUG) { 2701 Slog.d(TAG, 2702 "noteOperation: allowing code " + code + " uid " + uid + " package " 2703 + packageName + (attributionTag == null ? "" 2704 : "." + attributionTag) + " flags: " 2705 + AppOpsManager.flagsToString(flags)); 2706 } 2707 scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags, 2708 AppOpsManager.MODE_ALLOWED); 2709 attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag, 2710 uidState.getState(), 2711 flags); 2712 2713 if (shouldCollectAsyncNotedOp) { 2714 collectAsyncNotedOp(uid, packageName, code, attributionTag, flags, message, 2715 shouldCollectMessage); 2716 } 2717 2718 return new SyncNotedAppOp(AppOpsManager.MODE_ALLOWED, code, attributionTag, 2719 packageName); 2720 } 2721 } 2722 2723 // TODO moltmann: Allow watching for attribution ops 2724 @Override startWatchingActive(int[] ops, IAppOpsActiveCallback callback)2725 public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) { 2726 int watchedUid = Process.INVALID_UID; 2727 final int callingUid = Binder.getCallingUid(); 2728 final int callingPid = Binder.getCallingPid(); 2729 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 2730 != PackageManager.PERMISSION_GRANTED) { 2731 watchedUid = callingUid; 2732 } 2733 if (ops != null) { 2734 Preconditions.checkArrayElementsInRange(ops, 0, 2735 AppOpsManager._NUM_OP - 1, "Invalid op code in: " + Arrays.toString(ops)); 2736 } 2737 if (callback == null) { 2738 return; 2739 } 2740 synchronized (this) { 2741 SparseArray<ActiveCallback> callbacks = mActiveWatchers.get(callback.asBinder()); 2742 if (callbacks == null) { 2743 callbacks = new SparseArray<>(); 2744 mActiveWatchers.put(callback.asBinder(), callbacks); 2745 } 2746 final ActiveCallback activeCallback = new ActiveCallback(callback, watchedUid, 2747 callingUid, callingPid); 2748 for (int op : ops) { 2749 callbacks.put(op, activeCallback); 2750 } 2751 } 2752 } 2753 2754 @Override stopWatchingActive(IAppOpsActiveCallback callback)2755 public void stopWatchingActive(IAppOpsActiveCallback callback) { 2756 if (callback == null) { 2757 return; 2758 } 2759 synchronized (this) { 2760 final SparseArray<ActiveCallback> activeCallbacks = 2761 mActiveWatchers.remove(callback.asBinder()); 2762 if (activeCallbacks == null) { 2763 return; 2764 } 2765 final int callbackCount = activeCallbacks.size(); 2766 for (int i = 0; i < callbackCount; i++) { 2767 activeCallbacks.valueAt(i).destroy(); 2768 } 2769 } 2770 } 2771 2772 @Override startWatchingStarted(int[] ops, @NonNull IAppOpsStartedCallback callback)2773 public void startWatchingStarted(int[] ops, @NonNull IAppOpsStartedCallback callback) { 2774 int watchedUid = Process.INVALID_UID; 2775 final int callingUid = Binder.getCallingUid(); 2776 final int callingPid = Binder.getCallingPid(); 2777 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 2778 != PackageManager.PERMISSION_GRANTED) { 2779 watchedUid = callingUid; 2780 } 2781 2782 Preconditions.checkArgument(!ArrayUtils.isEmpty(ops), "Ops cannot be null or empty"); 2783 Preconditions.checkArrayElementsInRange(ops, 0, AppOpsManager._NUM_OP - 1, 2784 "Invalid op code in: " + Arrays.toString(ops)); 2785 Objects.requireNonNull(callback, "Callback cannot be null"); 2786 2787 synchronized (this) { 2788 SparseArray<StartedCallback> callbacks = mStartedWatchers.get(callback.asBinder()); 2789 if (callbacks == null) { 2790 callbacks = new SparseArray<>(); 2791 mStartedWatchers.put(callback.asBinder(), callbacks); 2792 } 2793 2794 final StartedCallback startedCallback = new StartedCallback(callback, watchedUid, 2795 callingUid, callingPid); 2796 for (int op : ops) { 2797 callbacks.put(op, startedCallback); 2798 } 2799 } 2800 } 2801 2802 @Override stopWatchingStarted(IAppOpsStartedCallback callback)2803 public void stopWatchingStarted(IAppOpsStartedCallback callback) { 2804 Objects.requireNonNull(callback, "Callback cannot be null"); 2805 2806 synchronized (this) { 2807 final SparseArray<StartedCallback> startedCallbacks = 2808 mStartedWatchers.remove(callback.asBinder()); 2809 if (startedCallbacks == null) { 2810 return; 2811 } 2812 2813 final int callbackCount = startedCallbacks.size(); 2814 for (int i = 0; i < callbackCount; i++) { 2815 startedCallbacks.valueAt(i).destroy(); 2816 } 2817 } 2818 } 2819 2820 @Override startWatchingNoted(@onNull int[] ops, @NonNull IAppOpsNotedCallback callback)2821 public void startWatchingNoted(@NonNull int[] ops, @NonNull IAppOpsNotedCallback callback) { 2822 int watchedUid = Process.INVALID_UID; 2823 final int callingUid = Binder.getCallingUid(); 2824 final int callingPid = Binder.getCallingPid(); 2825 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 2826 != PackageManager.PERMISSION_GRANTED) { 2827 watchedUid = callingUid; 2828 } 2829 Preconditions.checkArgument(!ArrayUtils.isEmpty(ops), "Ops cannot be null or empty"); 2830 Preconditions.checkArrayElementsInRange(ops, 0, AppOpsManager._NUM_OP - 1, 2831 "Invalid op code in: " + Arrays.toString(ops)); 2832 Objects.requireNonNull(callback, "Callback cannot be null"); 2833 synchronized (this) { 2834 SparseArray<NotedCallback> callbacks = mNotedWatchers.get(callback.asBinder()); 2835 if (callbacks == null) { 2836 callbacks = new SparseArray<>(); 2837 mNotedWatchers.put(callback.asBinder(), callbacks); 2838 } 2839 final NotedCallback notedCallback = new NotedCallback(callback, watchedUid, 2840 callingUid, callingPid); 2841 for (int op : ops) { 2842 callbacks.put(op, notedCallback); 2843 } 2844 } 2845 } 2846 2847 @Override stopWatchingNoted(IAppOpsNotedCallback callback)2848 public void stopWatchingNoted(IAppOpsNotedCallback callback) { 2849 Objects.requireNonNull(callback, "Callback cannot be null"); 2850 synchronized (this) { 2851 final SparseArray<NotedCallback> notedCallbacks = 2852 mNotedWatchers.remove(callback.asBinder()); 2853 if (notedCallbacks == null) { 2854 return; 2855 } 2856 final int callbackCount = notedCallbacks.size(); 2857 for (int i = 0; i < callbackCount; i++) { 2858 notedCallbacks.valueAt(i).destroy(); 2859 } 2860 } 2861 } 2862 2863 /** 2864 * Collect an {@link AsyncNotedAppOp}. 2865 * 2866 * @param uid The uid the op was noted for 2867 * @param packageName The package the op was noted for 2868 * @param opCode The code of the op noted 2869 * @param attributionTag attribution tag the op was noted for 2870 * @param message The message for the op noting 2871 */ collectAsyncNotedOp(int uid, @NonNull String packageName, int opCode, @Nullable String attributionTag, @OpFlags int flags, @NonNull String message, boolean shouldCollectMessage)2872 private void collectAsyncNotedOp(int uid, @NonNull String packageName, int opCode, 2873 @Nullable String attributionTag, @OpFlags int flags, @NonNull String message, 2874 boolean shouldCollectMessage) { 2875 Objects.requireNonNull(message); 2876 2877 int callingUid = Binder.getCallingUid(); 2878 2879 final long token = Binder.clearCallingIdentity(); 2880 try { 2881 synchronized (this) { 2882 Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid); 2883 2884 RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key); 2885 AsyncNotedAppOp asyncNotedOp = new AsyncNotedAppOp(opCode, callingUid, 2886 attributionTag, message, System.currentTimeMillis()); 2887 final boolean[] wasNoteForwarded = {false}; 2888 2889 if ((flags & (OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED)) != 0 2890 && shouldCollectMessage) { 2891 reportRuntimeAppOpAccessMessageAsyncLocked(uid, packageName, opCode, 2892 attributionTag, message); 2893 } 2894 2895 if (callbacks != null) { 2896 callbacks.broadcast((cb) -> { 2897 try { 2898 cb.opNoted(asyncNotedOp); 2899 wasNoteForwarded[0] = true; 2900 } catch (RemoteException e) { 2901 Slog.e(TAG, 2902 "Could not forward noteOp of " + opCode + " to " + packageName 2903 + "/" + uid + "(" + attributionTag + ")", e); 2904 } 2905 }); 2906 } 2907 2908 if (!wasNoteForwarded[0]) { 2909 ArrayList<AsyncNotedAppOp> unforwardedOps = mUnforwardedAsyncNotedOps.get(key); 2910 if (unforwardedOps == null) { 2911 unforwardedOps = new ArrayList<>(1); 2912 mUnforwardedAsyncNotedOps.put(key, unforwardedOps); 2913 } 2914 2915 unforwardedOps.add(asyncNotedOp); 2916 if (unforwardedOps.size() > MAX_UNFORWARDED_OPS) { 2917 unforwardedOps.remove(0); 2918 } 2919 } 2920 } 2921 } finally { 2922 Binder.restoreCallingIdentity(token); 2923 } 2924 } 2925 2926 /** 2927 * Compute a key to be used in {@link #mAsyncOpWatchers} and {@link #mUnforwardedAsyncNotedOps} 2928 * 2929 * @param packageName The package name of the app 2930 * @param uid The uid of the app 2931 * 2932 * @return They key uniquely identifying the app 2933 */ getAsyncNotedOpsKey(@onNull String packageName, int uid)2934 private @NonNull Pair<String, Integer> getAsyncNotedOpsKey(@NonNull String packageName, 2935 int uid) { 2936 return new Pair<>(packageName, uid); 2937 } 2938 2939 @Override startWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback)2940 public void startWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback) { 2941 Objects.requireNonNull(packageName); 2942 Objects.requireNonNull(callback); 2943 2944 int uid = Binder.getCallingUid(); 2945 Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid); 2946 2947 verifyAndGetBypass(uid, packageName, null); 2948 2949 synchronized (this) { 2950 RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key); 2951 if (callbacks == null) { 2952 callbacks = new RemoteCallbackList<IAppOpsAsyncNotedCallback>() { 2953 @Override 2954 public void onCallbackDied(IAppOpsAsyncNotedCallback callback) { 2955 synchronized (AppOpsService.this) { 2956 if (getRegisteredCallbackCount() == 0) { 2957 mAsyncOpWatchers.remove(key); 2958 } 2959 } 2960 } 2961 }; 2962 mAsyncOpWatchers.put(key, callbacks); 2963 } 2964 2965 callbacks.register(callback); 2966 } 2967 } 2968 2969 @Override stopWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback)2970 public void stopWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback) { 2971 Objects.requireNonNull(packageName); 2972 Objects.requireNonNull(callback); 2973 2974 int uid = Binder.getCallingUid(); 2975 Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid); 2976 2977 verifyAndGetBypass(uid, packageName, null); 2978 2979 synchronized (this) { 2980 RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key); 2981 if (callbacks != null) { 2982 callbacks.unregister(callback); 2983 if (callbacks.getRegisteredCallbackCount() == 0) { 2984 mAsyncOpWatchers.remove(key); 2985 } 2986 } 2987 } 2988 } 2989 2990 @Override extractAsyncOps(String packageName)2991 public List<AsyncNotedAppOp> extractAsyncOps(String packageName) { 2992 Objects.requireNonNull(packageName); 2993 2994 int uid = Binder.getCallingUid(); 2995 2996 verifyAndGetBypass(uid, packageName, null); 2997 2998 synchronized (this) { 2999 return mUnforwardedAsyncNotedOps.remove(getAsyncNotedOpsKey(packageName, uid)); 3000 } 3001 } 3002 3003 @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)3004 public SyncNotedAppOp startOperation(IBinder token, int code, int uid, 3005 @Nullable String packageName, @Nullable String attributionTag, 3006 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, 3007 String message, boolean shouldCollectMessage, @AttributionFlags int attributionFlags, 3008 int attributionChainId) { 3009 return mCheckOpsDelegateDispatcher.startOperation(token, code, uid, packageName, 3010 attributionTag, startIfModeDefault, shouldCollectAsyncNotedOp, message, 3011 shouldCollectMessage, attributionFlags, attributionChainId); 3012 } 3013 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)3014 private SyncNotedAppOp startOperationImpl(@NonNull IBinder clientId, int code, int uid, 3015 @Nullable String packageName, @Nullable String attributionTag, 3016 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @NonNull String message, 3017 boolean shouldCollectMessage, @AttributionFlags int attributionFlags, 3018 int attributionChainId) { 3019 verifyIncomingUid(uid); 3020 verifyIncomingOp(code); 3021 if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) { 3022 return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, 3023 packageName); 3024 } 3025 3026 String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); 3027 if (resolvedPackageName == null) { 3028 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag, 3029 packageName); 3030 } 3031 3032 // As a special case for OP_RECORD_AUDIO_HOTWORD, OP_RECEIVE_AMBIENT_TRIGGER_AUDIO and 3033 // OP_RECORD_AUDIO_SANDBOXED which we use only for attribution purposes and not as a check, 3034 // also make sure that the caller is allowed to access the data gated by OP_RECORD_AUDIO. 3035 // 3036 // TODO: Revert this change before Android 12. 3037 int result = MODE_DEFAULT; 3038 if (code == OP_RECORD_AUDIO_HOTWORD || code == OP_RECEIVE_AMBIENT_TRIGGER_AUDIO 3039 || code == OP_RECORD_AUDIO_SANDBOXED) { 3040 result = checkOperation(OP_RECORD_AUDIO, uid, packageName); 3041 // Check result 3042 if (result != AppOpsManager.MODE_ALLOWED) { 3043 return new SyncNotedAppOp(result, code, attributionTag, packageName); 3044 } 3045 } 3046 // As a special case for OP_CAMERA_SANDBOXED. 3047 if (code == OP_CAMERA_SANDBOXED) { 3048 result = checkOperation(OP_CAMERA, uid, packageName); 3049 // Check result 3050 if (result != AppOpsManager.MODE_ALLOWED) { 3051 return new SyncNotedAppOp(result, code, attributionTag, packageName); 3052 } 3053 } 3054 3055 return startOperationUnchecked(clientId, code, uid, packageName, attributionTag, 3056 Process.INVALID_UID, null, null, OP_FLAG_SELF, startIfModeDefault, 3057 shouldCollectAsyncNotedOp, message, shouldCollectMessage, attributionFlags, 3058 attributionChainId, /*dryRun*/ false); 3059 } 3060 3061 @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)3062 public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code, 3063 @NonNull AttributionSource attributionSource, boolean startIfModeDefault, 3064 boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, 3065 boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, 3066 @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { 3067 return mCheckOpsDelegateDispatcher.startProxyOperation(clientId, code, attributionSource, 3068 startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, 3069 skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, 3070 attributionChainId); 3071 } 3072 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)3073 private SyncNotedAppOp startProxyOperationImpl(@NonNull IBinder clientId, int code, 3074 @NonNull AttributionSource attributionSource, 3075 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, 3076 boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags 3077 int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, 3078 int attributionChainId) { 3079 final int proxyUid = attributionSource.getUid(); 3080 final String proxyPackageName = attributionSource.getPackageName(); 3081 final String proxyAttributionTag = attributionSource.getAttributionTag(); 3082 final int proxiedUid = attributionSource.getNextUid(); 3083 final String proxiedPackageName = attributionSource.getNextPackageName(); 3084 final String proxiedAttributionTag = attributionSource.getNextAttributionTag(); 3085 3086 verifyIncomingProxyUid(attributionSource); 3087 verifyIncomingOp(code); 3088 if (!isIncomingPackageValid(proxyPackageName, UserHandle.getUserId(proxyUid)) 3089 || !isIncomingPackageValid(proxiedPackageName, UserHandle.getUserId(proxiedUid))) { 3090 return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, proxiedAttributionTag, 3091 proxiedPackageName); 3092 } 3093 3094 boolean isCallerTrusted = isCallerAndAttributionTrusted(attributionSource); 3095 skipProxyOperation = isCallerTrusted && skipProxyOperation; 3096 3097 String resolvedProxyPackageName = AppOpsManager.resolvePackageName(proxyUid, 3098 proxyPackageName); 3099 if (resolvedProxyPackageName == null) { 3100 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, proxiedAttributionTag, 3101 proxiedPackageName); 3102 } 3103 3104 final boolean isChainTrusted = isCallerTrusted 3105 && attributionChainId != ATTRIBUTION_CHAIN_ID_NONE 3106 && ((proxyAttributionFlags & ATTRIBUTION_FLAG_TRUSTED) != 0 3107 || (proxiedAttributionFlags & ATTRIBUTION_FLAG_TRUSTED) != 0); 3108 final boolean isSelfBlame = Binder.getCallingUid() == proxiedUid; 3109 final boolean isProxyTrusted = mContext.checkPermission( 3110 Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid) 3111 == PackageManager.PERMISSION_GRANTED || isSelfBlame 3112 || isChainTrusted; 3113 3114 String resolvedProxiedPackageName = AppOpsManager.resolvePackageName(proxiedUid, 3115 proxiedPackageName); 3116 if (resolvedProxiedPackageName == null) { 3117 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, proxiedAttributionTag, 3118 proxiedPackageName); 3119 } 3120 3121 final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED 3122 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED; 3123 3124 if (!skipProxyOperation) { 3125 // Test if the proxied operation will succeed before starting the proxy operation 3126 final SyncNotedAppOp testProxiedOp = startOperationUnchecked(clientId, code, 3127 proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag, proxyUid, 3128 resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault, 3129 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 3130 proxiedAttributionFlags, attributionChainId, /*dryRun*/ true); 3131 if (!shouldStartForMode(testProxiedOp.getOpMode(), startIfModeDefault)) { 3132 return testProxiedOp; 3133 } 3134 3135 final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY 3136 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY; 3137 3138 final SyncNotedAppOp proxyAppOp = startOperationUnchecked(clientId, code, proxyUid, 3139 resolvedProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null, 3140 proxyFlags, startIfModeDefault, !isProxyTrusted, "proxy " + message, 3141 shouldCollectMessage, proxyAttributionFlags, attributionChainId, 3142 /*dryRun*/ false); 3143 if (!shouldStartForMode(proxyAppOp.getOpMode(), startIfModeDefault)) { 3144 return proxyAppOp; 3145 } 3146 } 3147 3148 return startOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName, 3149 proxiedAttributionTag, proxyUid, resolvedProxyPackageName, proxyAttributionTag, 3150 proxiedFlags, startIfModeDefault, shouldCollectAsyncNotedOp, message, 3151 shouldCollectMessage, proxiedAttributionFlags, attributionChainId, 3152 /*dryRun*/ false); 3153 } 3154 shouldStartForMode(int mode, boolean startIfModeDefault)3155 private boolean shouldStartForMode(int mode, boolean startIfModeDefault) { 3156 return (mode == MODE_ALLOWED || (mode == MODE_DEFAULT && startIfModeDefault)); 3157 } 3158 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)3159 private SyncNotedAppOp startOperationUnchecked(IBinder clientId, int code, int uid, 3160 @NonNull String packageName, @Nullable String attributionTag, int proxyUid, 3161 String proxyPackageName, @Nullable String proxyAttributionTag, @OpFlags int flags, 3162 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @Nullable String message, 3163 boolean shouldCollectMessage, @AttributionFlags int attributionFlags, 3164 int attributionChainId, boolean dryRun) { 3165 PackageVerificationResult pvr; 3166 try { 3167 pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName); 3168 if (!pvr.isAttributionTagValid) { 3169 attributionTag = null; 3170 } 3171 } catch (SecurityException e) { 3172 if (Process.isIsolated(uid)) { 3173 Slog.e(TAG, "Cannot startOperation: isolated process"); 3174 } else { 3175 Slog.e(TAG, "Cannot startOperation", e); 3176 } 3177 return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, 3178 packageName); 3179 } 3180 3181 boolean isRestricted = false; 3182 int startType = START_TYPE_FAILED; 3183 synchronized (this) { 3184 final Ops ops = getOpsLocked(uid, packageName, attributionTag, 3185 pvr.isAttributionTagValid, pvr.bypass, /* edit */ true); 3186 if (ops == null) { 3187 if (!dryRun) { 3188 scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag, 3189 flags, AppOpsManager.MODE_IGNORED, startType, attributionFlags, 3190 attributionChainId); 3191 } 3192 if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid 3193 + " package " + packageName + " flags: " 3194 + AppOpsManager.flagsToString(flags)); 3195 return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, 3196 packageName); 3197 } 3198 final Op op = getOpLocked(ops, code, uid, true); 3199 final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag); 3200 final UidState uidState = ops.uidState; 3201 isRestricted = isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass, 3202 false); 3203 final int switchCode = AppOpsManager.opToSwitch(code); 3204 // If there is a non-default per UID policy (we set UID op mode only if 3205 // non-default) it takes over, otherwise use the per package policy. 3206 if (uidState.getUidMode(switchCode) != AppOpsManager.opToDefaultMode(switchCode)) { 3207 final int uidMode = uidState.evalMode(code, uidState.getUidMode(switchCode)); 3208 if (!shouldStartForMode(uidMode, startIfModeDefault)) { 3209 if (DEBUG) { 3210 Slog.d(TAG, "startOperation: uid reject #" + uidMode + " for code " 3211 + switchCode + " (" + code + ") uid " + uid + " package " 3212 + packageName + " flags: " + AppOpsManager.flagsToString(flags)); 3213 } 3214 if (!dryRun) { 3215 attributedOp.rejected(uidState.getState(), flags); 3216 scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag, 3217 flags, uidMode, startType, attributionFlags, attributionChainId); 3218 } 3219 return new SyncNotedAppOp(uidMode, code, attributionTag, packageName); 3220 } 3221 } else { 3222 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, uid, true) 3223 : op; 3224 final int mode = switchOp.uidState.evalMode(switchOp.op, switchOp.getMode()); 3225 if (mode != AppOpsManager.MODE_ALLOWED 3226 && (!startIfModeDefault || mode != MODE_DEFAULT)) { 3227 if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code " 3228 + switchCode + " (" + code + ") uid " + uid + " package " 3229 + packageName + " flags: " + AppOpsManager.flagsToString(flags)); 3230 if (!dryRun) { 3231 attributedOp.rejected(uidState.getState(), flags); 3232 scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag, 3233 flags, mode, startType, attributionFlags, attributionChainId); 3234 } 3235 return new SyncNotedAppOp(mode, code, attributionTag, packageName); 3236 } 3237 } 3238 if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid 3239 + " package " + packageName + " restricted: " + isRestricted 3240 + " flags: " + AppOpsManager.flagsToString(flags)); 3241 if (!dryRun) { 3242 try { 3243 if (isRestricted) { 3244 attributedOp.createPaused(clientId, proxyUid, proxyPackageName, 3245 proxyAttributionTag, uidState.getState(), flags, 3246 attributionFlags, attributionChainId); 3247 } else { 3248 attributedOp.started(clientId, proxyUid, proxyPackageName, 3249 proxyAttributionTag, uidState.getState(), flags, 3250 attributionFlags, attributionChainId); 3251 startType = START_TYPE_STARTED; 3252 } 3253 } catch (RemoteException e) { 3254 throw new RuntimeException(e); 3255 } 3256 scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag, flags, 3257 isRestricted ? MODE_IGNORED : MODE_ALLOWED, startType, attributionFlags, 3258 attributionChainId); 3259 } 3260 } 3261 3262 if (shouldCollectAsyncNotedOp && !dryRun && !isRestricted) { 3263 collectAsyncNotedOp(uid, packageName, code, attributionTag, AppOpsManager.OP_FLAG_SELF, 3264 message, shouldCollectMessage); 3265 } 3266 3267 return new SyncNotedAppOp(isRestricted ? MODE_IGNORED : MODE_ALLOWED, code, attributionTag, 3268 packageName); 3269 } 3270 3271 @Override finishOperation(IBinder clientId, int code, int uid, String packageName, String attributionTag)3272 public void finishOperation(IBinder clientId, int code, int uid, String packageName, 3273 String attributionTag) { 3274 mCheckOpsDelegateDispatcher.finishOperation(clientId, code, uid, packageName, 3275 attributionTag); 3276 } 3277 finishOperationImpl(IBinder clientId, int code, int uid, String packageName, String attributionTag)3278 private void finishOperationImpl(IBinder clientId, int code, int uid, String packageName, 3279 String attributionTag) { 3280 verifyIncomingUid(uid); 3281 verifyIncomingOp(code); 3282 if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) { 3283 return; 3284 } 3285 3286 String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); 3287 if (resolvedPackageName == null) { 3288 return; 3289 } 3290 3291 finishOperationUnchecked(clientId, code, uid, resolvedPackageName, attributionTag); 3292 } 3293 3294 @Override finishProxyOperation(@onNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean skipProxyOperation)3295 public void finishProxyOperation(@NonNull IBinder clientId, int code, 3296 @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { 3297 mCheckOpsDelegateDispatcher.finishProxyOperation(clientId, code, attributionSource, 3298 skipProxyOperation); 3299 } 3300 finishProxyOperationImpl(IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean skipProxyOperation)3301 private Void finishProxyOperationImpl(IBinder clientId, int code, 3302 @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { 3303 final int proxyUid = attributionSource.getUid(); 3304 final String proxyPackageName = attributionSource.getPackageName(); 3305 final String proxyAttributionTag = attributionSource.getAttributionTag(); 3306 final int proxiedUid = attributionSource.getNextUid(); 3307 final String proxiedPackageName = attributionSource.getNextPackageName(); 3308 final String proxiedAttributionTag = attributionSource.getNextAttributionTag(); 3309 3310 skipProxyOperation = skipProxyOperation 3311 && isCallerAndAttributionTrusted(attributionSource); 3312 3313 verifyIncomingProxyUid(attributionSource); 3314 verifyIncomingOp(code); 3315 if (!isIncomingPackageValid(proxyPackageName, UserHandle.getUserId(proxyUid)) 3316 || !isIncomingPackageValid(proxiedPackageName, UserHandle.getUserId(proxiedUid))) { 3317 return null; 3318 } 3319 3320 String resolvedProxyPackageName = AppOpsManager.resolvePackageName(proxyUid, 3321 proxyPackageName); 3322 if (resolvedProxyPackageName == null) { 3323 return null; 3324 } 3325 3326 if (!skipProxyOperation) { 3327 finishOperationUnchecked(clientId, code, proxyUid, resolvedProxyPackageName, 3328 proxyAttributionTag); 3329 } 3330 3331 String resolvedProxiedPackageName = AppOpsManager.resolvePackageName(proxiedUid, 3332 proxiedPackageName); 3333 if (resolvedProxiedPackageName == null) { 3334 return null; 3335 } 3336 3337 finishOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName, 3338 proxiedAttributionTag); 3339 3340 return null; 3341 } 3342 finishOperationUnchecked(IBinder clientId, int code, int uid, String packageName, String attributionTag)3343 private void finishOperationUnchecked(IBinder clientId, int code, int uid, String packageName, 3344 String attributionTag) { 3345 PackageVerificationResult pvr; 3346 try { 3347 pvr = verifyAndGetBypass(uid, packageName, attributionTag); 3348 if (!pvr.isAttributionTagValid) { 3349 attributionTag = null; 3350 } 3351 } catch (SecurityException e) { 3352 if (Process.isIsolated(uid)) { 3353 Slog.e(TAG, "Cannot finishOperation: isolated process"); 3354 } else { 3355 Slog.e(TAG, "Cannot finishOperation", e); 3356 } 3357 return; 3358 } 3359 3360 synchronized (this) { 3361 Op op = getOpLocked(code, uid, packageName, attributionTag, pvr.isAttributionTagValid, 3362 pvr.bypass, /* edit */ true); 3363 if (op == null) { 3364 Slog.e(TAG, "Operation not found: uid=" + uid + " pkg=" + packageName + "(" 3365 + attributionTag + ") op=" + AppOpsManager.opToName(code)); 3366 return; 3367 } 3368 final AttributedOp attributedOp = op.mAttributions.get(attributionTag); 3369 if (attributedOp == null) { 3370 Slog.e(TAG, "Attribution not found: uid=" + uid + " pkg=" + packageName + "(" 3371 + attributionTag + ") op=" + AppOpsManager.opToName(code)); 3372 return; 3373 } 3374 3375 if (attributedOp.isRunning() || attributedOp.isPaused()) { 3376 attributedOp.finished(clientId); 3377 } else { 3378 Slog.e(TAG, "Operation not started: uid=" + uid + " pkg=" + packageName + "(" 3379 + attributionTag + ") op=" + AppOpsManager.opToName(code)); 3380 } 3381 } 3382 } 3383 scheduleOpActiveChangedIfNeededLocked(int code, int uid, @NonNull String packageName, @Nullable String attributionTag, boolean active, @AttributionFlags int attributionFlags, int attributionChainId)3384 void scheduleOpActiveChangedIfNeededLocked(int code, int uid, @NonNull 3385 String packageName, @Nullable String attributionTag, boolean active, @AttributionFlags 3386 int attributionFlags, int attributionChainId) { 3387 ArraySet<ActiveCallback> dispatchedCallbacks = null; 3388 final int callbackListCount = mActiveWatchers.size(); 3389 for (int i = 0; i < callbackListCount; i++) { 3390 final SparseArray<ActiveCallback> callbacks = mActiveWatchers.valueAt(i); 3391 ActiveCallback callback = callbacks.get(code); 3392 if (callback != null) { 3393 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 3394 continue; 3395 } 3396 if (dispatchedCallbacks == null) { 3397 dispatchedCallbacks = new ArraySet<>(); 3398 } 3399 dispatchedCallbacks.add(callback); 3400 } 3401 } 3402 if (dispatchedCallbacks == null) { 3403 return; 3404 } 3405 mHandler.sendMessage(PooledLambda.obtainMessage( 3406 AppOpsService::notifyOpActiveChanged, 3407 this, dispatchedCallbacks, code, uid, packageName, attributionTag, active, 3408 attributionFlags, attributionChainId)); 3409 } 3410 notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks, int code, int uid, @NonNull String packageName, @Nullable String attributionTag, boolean active, @AttributionFlags int attributionFlags, int attributionChainId)3411 private void notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks, 3412 int code, int uid, @NonNull String packageName, @Nullable String attributionTag, 3413 boolean active, @AttributionFlags int attributionFlags, int attributionChainId) { 3414 // There are features watching for mode changes such as window manager 3415 // and location manager which are in our process. The callbacks in these 3416 // features may require permissions our remote caller does not have. 3417 final long identity = Binder.clearCallingIdentity(); 3418 try { 3419 final int callbackCount = callbacks.size(); 3420 for (int i = 0; i < callbackCount; i++) { 3421 final ActiveCallback callback = callbacks.valueAt(i); 3422 try { 3423 if (shouldIgnoreCallback(code, callback.mCallingPid, callback.mCallingUid)) { 3424 continue; 3425 } 3426 callback.mCallback.opActiveChanged(code, uid, packageName, attributionTag, 3427 active, attributionFlags, attributionChainId); 3428 } catch (RemoteException e) { 3429 /* do nothing */ 3430 } 3431 } 3432 } finally { 3433 Binder.restoreCallingIdentity(identity); 3434 } 3435 } 3436 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)3437 void scheduleOpStartedIfNeededLocked(int code, int uid, String pkgName, 3438 String attributionTag, @OpFlags int flags, @Mode int result, 3439 @AppOpsManager.OnOpStartedListener.StartedType int startedType, 3440 @AttributionFlags int attributionFlags, int attributionChainId) { 3441 ArraySet<StartedCallback> dispatchedCallbacks = null; 3442 final int callbackListCount = mStartedWatchers.size(); 3443 for (int i = 0; i < callbackListCount; i++) { 3444 final SparseArray<StartedCallback> callbacks = mStartedWatchers.valueAt(i); 3445 3446 StartedCallback callback = callbacks.get(code); 3447 if (callback != null) { 3448 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 3449 continue; 3450 } 3451 3452 if (dispatchedCallbacks == null) { 3453 dispatchedCallbacks = new ArraySet<>(); 3454 } 3455 dispatchedCallbacks.add(callback); 3456 } 3457 } 3458 3459 if (dispatchedCallbacks == null) { 3460 return; 3461 } 3462 3463 mHandler.sendMessage(PooledLambda.obtainMessage( 3464 AppOpsService::notifyOpStarted, 3465 this, dispatchedCallbacks, code, uid, pkgName, attributionTag, flags, 3466 result, startedType, attributionFlags, attributionChainId)); 3467 } 3468 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)3469 private void notifyOpStarted(ArraySet<StartedCallback> callbacks, 3470 int code, int uid, String packageName, String attributionTag, @OpFlags int flags, 3471 @Mode int result, @AppOpsManager.OnOpStartedListener.StartedType int startedType, 3472 @AttributionFlags int attributionFlags, int attributionChainId) { 3473 final long identity = Binder.clearCallingIdentity(); 3474 try { 3475 final int callbackCount = callbacks.size(); 3476 for (int i = 0; i < callbackCount; i++) { 3477 final StartedCallback callback = callbacks.valueAt(i); 3478 try { 3479 if (shouldIgnoreCallback(code, callback.mCallingPid, callback.mCallingUid)) { 3480 continue; 3481 } 3482 callback.mCallback.opStarted(code, uid, packageName, attributionTag, flags, 3483 result, startedType, attributionFlags, attributionChainId); 3484 } catch (RemoteException e) { 3485 /* do nothing */ 3486 } 3487 } 3488 } finally { 3489 Binder.restoreCallingIdentity(identity); 3490 } 3491 } 3492 scheduleOpNotedIfNeededLocked(int code, int uid, String packageName, String attributionTag, @OpFlags int flags, @Mode int result)3493 private void scheduleOpNotedIfNeededLocked(int code, int uid, String packageName, 3494 String attributionTag, @OpFlags int flags, @Mode int result) { 3495 ArraySet<NotedCallback> dispatchedCallbacks = null; 3496 final int callbackListCount = mNotedWatchers.size(); 3497 for (int i = 0; i < callbackListCount; i++) { 3498 final SparseArray<NotedCallback> callbacks = mNotedWatchers.valueAt(i); 3499 final NotedCallback callback = callbacks.get(code); 3500 if (callback != null) { 3501 if (callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) { 3502 continue; 3503 } 3504 if (dispatchedCallbacks == null) { 3505 dispatchedCallbacks = new ArraySet<>(); 3506 } 3507 dispatchedCallbacks.add(callback); 3508 } 3509 } 3510 if (dispatchedCallbacks == null) { 3511 return; 3512 } 3513 mHandler.sendMessage(PooledLambda.obtainMessage( 3514 AppOpsService::notifyOpChecked, 3515 this, dispatchedCallbacks, code, uid, packageName, attributionTag, flags, 3516 result)); 3517 } 3518 notifyOpChecked(ArraySet<NotedCallback> callbacks, int code, int uid, String packageName, String attributionTag, @OpFlags int flags, @Mode int result)3519 private void notifyOpChecked(ArraySet<NotedCallback> callbacks, 3520 int code, int uid, String packageName, String attributionTag, @OpFlags int flags, 3521 @Mode int result) { 3522 // There are features watching for checks in our process. The callbacks in 3523 // these features may require permissions our remote caller does not have. 3524 final long identity = Binder.clearCallingIdentity(); 3525 try { 3526 final int callbackCount = callbacks.size(); 3527 for (int i = 0; i < callbackCount; i++) { 3528 final NotedCallback callback = callbacks.valueAt(i); 3529 try { 3530 if (shouldIgnoreCallback(code, callback.mCallingPid, callback.mCallingUid)) { 3531 continue; 3532 } 3533 callback.mCallback.opNoted(code, uid, packageName, attributionTag, flags, 3534 result); 3535 } catch (RemoteException e) { 3536 /* do nothing */ 3537 } 3538 } 3539 } finally { 3540 Binder.restoreCallingIdentity(identity); 3541 } 3542 } 3543 3544 @Override permissionToOpCode(String permission)3545 public int permissionToOpCode(String permission) { 3546 if (permission == null) { 3547 return AppOpsManager.OP_NONE; 3548 } 3549 return AppOpsManager.permissionToOpCode(permission); 3550 } 3551 3552 @Override shouldCollectNotes(int opCode)3553 public boolean shouldCollectNotes(int opCode) { 3554 Preconditions.checkArgumentInRange(opCode, 0, _NUM_OP - 1, "opCode"); 3555 3556 if (AppOpsManager.shouldForceCollectNoteForOp(opCode)) { 3557 return true; 3558 } 3559 3560 String perm = AppOpsManager.opToPermission(opCode); 3561 if (perm == null) { 3562 return false; 3563 } 3564 3565 PermissionInfo permInfo; 3566 try { 3567 permInfo = mContext.getPackageManager().getPermissionInfo(perm, 0); 3568 } catch (PackageManager.NameNotFoundException e) { 3569 return false; 3570 } 3571 3572 return permInfo.getProtection() == PROTECTION_DANGEROUS 3573 || (permInfo.getProtectionFlags() & PROTECTION_FLAG_APPOP) != 0; 3574 } 3575 verifyIncomingProxyUid(@onNull AttributionSource attributionSource)3576 private void verifyIncomingProxyUid(@NonNull AttributionSource attributionSource) { 3577 if (attributionSource.getUid() == Binder.getCallingUid()) { 3578 return; 3579 } 3580 if (Binder.getCallingPid() == Process.myPid()) { 3581 return; 3582 } 3583 if (attributionSource.isTrusted(mContext)) { 3584 return; 3585 } 3586 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 3587 Binder.getCallingPid(), Binder.getCallingUid(), null); 3588 } 3589 verifyIncomingUid(int uid)3590 private void verifyIncomingUid(int uid) { 3591 if (uid == Binder.getCallingUid()) { 3592 return; 3593 } 3594 if (Binder.getCallingPid() == Process.myPid()) { 3595 return; 3596 } 3597 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 3598 Binder.getCallingPid(), Binder.getCallingUid(), null); 3599 } 3600 shouldIgnoreCallback(int op, int watcherPid, int watcherUid)3601 private boolean shouldIgnoreCallback(int op, int watcherPid, int watcherUid) { 3602 // If it's a restricted read op, ignore it if watcher doesn't have manage ops permission, 3603 // as watcher should not use this to signal if the value is changed. 3604 return opRestrictsRead(op) && mContext.checkPermission(Manifest.permission.MANAGE_APPOPS, 3605 watcherPid, watcherUid) != PackageManager.PERMISSION_GRANTED; 3606 } 3607 verifyIncomingOp(int op)3608 private void verifyIncomingOp(int op) { 3609 if (op >= 0 && op < AppOpsManager._NUM_OP) { 3610 // Enforce manage appops permission if it's a restricted read op. 3611 if (opRestrictsRead(op)) { 3612 mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS, 3613 Binder.getCallingPid(), Binder.getCallingUid(), "verifyIncomingOp"); 3614 } 3615 return; 3616 } 3617 throw new IllegalArgumentException("Bad operation #" + op); 3618 } 3619 isIncomingPackageValid(@ullable String packageName, @UserIdInt int userId)3620 private boolean isIncomingPackageValid(@Nullable String packageName, @UserIdInt int userId) { 3621 final int callingUid = Binder.getCallingUid(); 3622 // Handle the special UIDs that don't have actual packages (audioserver, cameraserver, etc). 3623 if (packageName == null || isSpecialPackage(callingUid, packageName)) { 3624 return true; 3625 } 3626 3627 // If the package doesn't exist, #verifyAndGetBypass would throw a SecurityException in 3628 // the end. Although that exception would be caught and return, we could make it return 3629 // early. 3630 if (!isPackageExisted(packageName)) { 3631 return false; 3632 } 3633 3634 if (getPackageManagerInternal().filterAppAccess(packageName, callingUid, userId)) { 3635 Slog.w(TAG, packageName + " not found from " + callingUid); 3636 return false; 3637 } 3638 3639 return true; 3640 } 3641 isSpecialPackage(int callingUid, @Nullable String packageName)3642 private boolean isSpecialPackage(int callingUid, @Nullable String packageName) { 3643 final String resolvedPackage = AppOpsManager.resolvePackageName(callingUid, packageName); 3644 return callingUid == Process.SYSTEM_UID 3645 || resolveUid(resolvedPackage) != Process.INVALID_UID; 3646 } 3647 isCallerAndAttributionTrusted(@onNull AttributionSource attributionSource)3648 private boolean isCallerAndAttributionTrusted(@NonNull AttributionSource attributionSource) { 3649 if (attributionSource.getUid() != Binder.getCallingUid() 3650 && attributionSource.isTrusted(mContext)) { 3651 return true; 3652 } 3653 return mContext.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 3654 Binder.getCallingPid(), Binder.getCallingUid(), null) 3655 == PackageManager.PERMISSION_GRANTED; 3656 } 3657 getUidStateLocked(int uid, boolean edit)3658 private @Nullable UidState getUidStateLocked(int uid, boolean edit) { 3659 UidState uidState = mUidStates.get(uid); 3660 if (uidState == null) { 3661 if (!edit) { 3662 return null; 3663 } 3664 uidState = new UidState(uid); 3665 mUidStates.put(uid, uidState); 3666 } 3667 3668 return uidState; 3669 } 3670 updateAppWidgetVisibility(SparseArray<String> uidPackageNames, boolean visible)3671 private void updateAppWidgetVisibility(SparseArray<String> uidPackageNames, boolean visible) { 3672 synchronized (this) { 3673 getUidStateTracker().updateAppWidgetVisibility(uidPackageNames, visible); 3674 } 3675 } 3676 3677 /** 3678 * @return {@link PackageManagerInternal} 3679 */ getPackageManagerInternal()3680 private @NonNull PackageManagerInternal getPackageManagerInternal() { 3681 if (mPackageManagerInternal == null) { 3682 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); 3683 } 3684 if (mPackageManagerInternal == null) { 3685 throw new IllegalStateException("PackageManagerInternal not loaded"); 3686 } 3687 3688 return mPackageManagerInternal; 3689 } 3690 3691 /** 3692 * @return {@link PackageManagerLocal} 3693 */ getPackageManagerLocal()3694 private @NonNull PackageManagerLocal getPackageManagerLocal() { 3695 if (mPackageManagerLocal == null) { 3696 mPackageManagerLocal = LocalManagerRegistry.getManager(PackageManagerLocal.class); 3697 } 3698 if (mPackageManagerLocal == null) { 3699 throw new IllegalStateException("PackageManagerLocal not loaded"); 3700 } 3701 3702 return mPackageManagerLocal; 3703 } 3704 3705 /** 3706 * @return {@link UserManagerInternal} 3707 */ getUserManagerInternal()3708 private @NonNull UserManagerInternal getUserManagerInternal() { 3709 if (mUserManagerInternal == null) { 3710 mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); 3711 } 3712 if (mUserManagerInternal == null) { 3713 throw new IllegalStateException("UserManagerInternal not loaded"); 3714 } 3715 3716 return mUserManagerInternal; 3717 } 3718 3719 /** 3720 * Create a restriction description matching the properties of the package. 3721 * 3722 * @param pkg The package to create the restriction description for 3723 * 3724 * @return The restriction matching the package 3725 */ getBypassforPackage(@onNull PackageState packageState)3726 private RestrictionBypass getBypassforPackage(@NonNull PackageState packageState) { 3727 return new RestrictionBypass(packageState.getAppId() == Process.SYSTEM_UID, 3728 packageState.isPrivileged(), mContext.checkPermission( 3729 android.Manifest.permission.EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS, -1, 3730 packageState.getAppId()) == PackageManager.PERMISSION_GRANTED); 3731 } 3732 3733 /** 3734 * @see #verifyAndGetBypass(int, String, String, String, boolean) 3735 */ verifyAndGetBypass(int uid, String packageName, @Nullable String attributionTag)3736 private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName, 3737 @Nullable String attributionTag) { 3738 return verifyAndGetBypass(uid, packageName, attributionTag, null); 3739 } 3740 3741 /** 3742 * @see #verifyAndGetBypass(int, String, String, String, boolean) 3743 */ verifyAndGetBypass(int uid, String packageName, @Nullable String attributionTag, @Nullable String proxyPackageName)3744 private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName, 3745 @Nullable String attributionTag, @Nullable String proxyPackageName) { 3746 return verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName, false); 3747 } 3748 3749 /** 3750 * Verify that package belongs to uid and return the {@link RestrictionBypass bypass 3751 * description} for the package, along with a boolean indicating whether the attribution tag is 3752 * valid. 3753 * 3754 * @param uid The uid the package belongs to 3755 * @param packageName The package the might belong to the uid 3756 * @param attributionTag attribution tag or {@code null} if no need to verify 3757 * @param proxyPackageName The proxy package, from which the attribution tag is to be pulled 3758 * @param suppressErrorLogs Whether to print to logcat about nonmatching parameters 3759 * 3760 * @return PackageVerificationResult containing {@link RestrictionBypass} and whether the 3761 * attribution tag is valid 3762 */ verifyAndGetBypass(int uid, String packageName, @Nullable String attributionTag, @Nullable String proxyPackageName, boolean suppressErrorLogs)3763 private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName, 3764 @Nullable String attributionTag, @Nullable String proxyPackageName, 3765 boolean suppressErrorLogs) { 3766 if (uid == Process.ROOT_UID) { 3767 // For backwards compatibility, don't check package name for root UID. 3768 return new PackageVerificationResult(null, 3769 /* isAttributionTagValid */ true); 3770 } 3771 if (Process.isSdkSandboxUid(uid)) { 3772 // SDK sandbox processes run in their own UID range, but their associated 3773 // UID for checks should always be the UID of the package implementing SDK sandbox 3774 // service. 3775 // TODO: We will need to modify the callers of this function instead, so 3776 // modifications and checks against the app ops state are done with the 3777 // correct UID. 3778 try { 3779 final PackageManager pm = mContext.getPackageManager(); 3780 final String supplementalPackageName = pm.getSdkSandboxPackageName(); 3781 if (Objects.equals(packageName, supplementalPackageName)) { 3782 uid = pm.getPackageUidAsUser(supplementalPackageName, 3783 PackageManager.PackageInfoFlags.of(0), UserHandle.getUserId(uid)); 3784 } 3785 } catch (PackageManager.NameNotFoundException e) { 3786 // Shouldn't happen for the supplemental package 3787 e.printStackTrace(); 3788 } 3789 } 3790 3791 3792 // Do not check if uid/packageName/attributionTag is already known. 3793 synchronized (this) { 3794 UidState uidState = mUidStates.get(uid); 3795 if (uidState != null && !uidState.pkgOps.isEmpty()) { 3796 Ops ops = uidState.pkgOps.get(packageName); 3797 3798 if (ops != null && (attributionTag == null || ops.knownAttributionTags.contains( 3799 attributionTag)) && ops.bypass != null) { 3800 return new PackageVerificationResult(ops.bypass, 3801 ops.validAttributionTags.contains(attributionTag)); 3802 } 3803 } 3804 } 3805 3806 int callingUid = Binder.getCallingUid(); 3807 3808 // Allow any attribution tag for resolvable uids 3809 int pkgUid; 3810 if (Objects.equals(packageName, "com.android.shell")) { 3811 // Special case for the shell which is a package but should be able 3812 // to bypass app attribution tag restrictions. 3813 pkgUid = Process.SHELL_UID; 3814 } else { 3815 pkgUid = resolveUid(packageName); 3816 } 3817 if (pkgUid != Process.INVALID_UID) { 3818 if (pkgUid != UserHandle.getAppId(uid)) { 3819 if (!suppressErrorLogs) { 3820 Slog.e(TAG, "Bad call made by uid " + callingUid + ". " 3821 + "Package \"" + packageName + "\" does not belong to uid " + uid 3822 + "."); 3823 } 3824 String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not"; 3825 throw new SecurityException("Specified package \"" + packageName + "\" under uid " 3826 + UserHandle.getAppId(uid) + otherUidMessage); 3827 } 3828 return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED, 3829 /* isAttributionTagValid */ true); 3830 } 3831 3832 int userId = UserHandle.getUserId(uid); 3833 RestrictionBypass bypass = null; 3834 boolean isAttributionTagValid = false; 3835 3836 final long ident = Binder.clearCallingIdentity(); 3837 try { 3838 PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); 3839 var pkgState = pmInt.getPackageStateInternal(packageName); 3840 var pkg = pkgState == null ? null : pkgState.getAndroidPackage(); 3841 if (pkg != null) { 3842 isAttributionTagValid = isAttributionInPackage(pkg, attributionTag); 3843 pkgUid = UserHandle.getUid(userId, pkgState.getAppId()); 3844 bypass = getBypassforPackage(pkgState); 3845 } 3846 if (!isAttributionTagValid) { 3847 AndroidPackage proxyPkg = proxyPackageName != null 3848 ? pmInt.getPackage(proxyPackageName) : null; 3849 // Re-check in proxy. 3850 isAttributionTagValid = isAttributionInPackage(proxyPkg, attributionTag); 3851 String msg; 3852 if (pkg != null && isAttributionTagValid) { 3853 msg = "attributionTag " + attributionTag + " declared in manifest of the proxy" 3854 + " package " + proxyPackageName + ", this is not advised"; 3855 } else if (pkg != null) { 3856 msg = "attributionTag " + attributionTag + " not declared in manifest of " 3857 + packageName; 3858 } else { 3859 msg = "package " + packageName + " not found, can't check for " 3860 + "attributionTag " + attributionTag; 3861 } 3862 3863 try { 3864 if (!mPlatformCompat.isChangeEnabledByPackageName( 3865 SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, packageName, 3866 userId) || !mPlatformCompat.isChangeEnabledByUid( 3867 SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, 3868 callingUid)) { 3869 // Do not override tags if overriding is not enabled for this package 3870 isAttributionTagValid = true; 3871 } 3872 Slog.e(TAG, msg); 3873 } catch (RemoteException neverHappens) { 3874 } 3875 } 3876 } finally { 3877 Binder.restoreCallingIdentity(ident); 3878 } 3879 3880 if (pkgUid != uid) { 3881 if (!suppressErrorLogs) { 3882 Slog.e(TAG, "Bad call made by uid " + callingUid + ". " 3883 + "Package \"" + packageName + "\" does not belong to uid " + uid + "."); 3884 } 3885 String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not"; 3886 throw new SecurityException("Specified package \"" + packageName + "\" under uid " + uid 3887 + otherUidMessage); 3888 } 3889 3890 return new PackageVerificationResult(bypass, isAttributionTagValid); 3891 } 3892 isAttributionInPackage(@ullable AndroidPackage pkg, @Nullable String attributionTag)3893 private boolean isAttributionInPackage(@Nullable AndroidPackage pkg, 3894 @Nullable String attributionTag) { 3895 if (pkg == null) { 3896 return false; 3897 } else if (attributionTag == null) { 3898 return true; 3899 } 3900 if (pkg.getAttributions() != null) { 3901 int numAttributions = pkg.getAttributions().size(); 3902 for (int i = 0; i < numAttributions; i++) { 3903 if (pkg.getAttributions().get(i).getTag().equals(attributionTag)) { 3904 return true; 3905 } 3906 } 3907 } 3908 3909 return false; 3910 } 3911 3912 /** 3913 * Get (and potentially create) ops. 3914 * 3915 * @param uid The uid the package belongs to 3916 * @param packageName The name of the package 3917 * @param attributionTag attribution tag 3918 * @param isAttributionTagValid whether the given attribution tag is valid 3919 * @param bypass When to bypass certain op restrictions (can be null if edit == false) 3920 * @param edit If an ops does not exist, create the ops? 3921 3922 * @return The ops 3923 */ getOpsLocked(int uid, String packageName, @Nullable String attributionTag, boolean isAttributionTagValid, @Nullable RestrictionBypass bypass, boolean edit)3924 private Ops getOpsLocked(int uid, String packageName, @Nullable String attributionTag, 3925 boolean isAttributionTagValid, @Nullable RestrictionBypass bypass, boolean edit) { 3926 UidState uidState = getUidStateLocked(uid, edit); 3927 if (uidState == null) { 3928 return null; 3929 } 3930 3931 Ops ops = uidState.pkgOps.get(packageName); 3932 if (ops == null) { 3933 if (!edit) { 3934 return null; 3935 } 3936 ops = new Ops(packageName, uidState); 3937 uidState.pkgOps.put(packageName, ops); 3938 } 3939 3940 if (edit) { 3941 if (bypass != null) { 3942 ops.bypass = bypass; 3943 } 3944 3945 if (attributionTag != null) { 3946 ops.knownAttributionTags.add(attributionTag); 3947 if (isAttributionTagValid) { 3948 ops.validAttributionTags.add(attributionTag); 3949 } else { 3950 ops.validAttributionTags.remove(attributionTag); 3951 } 3952 } 3953 } 3954 3955 return ops; 3956 } 3957 scheduleWriteLocked()3958 private void scheduleWriteLocked() { 3959 if (!mWriteScheduled) { 3960 mWriteScheduled = true; 3961 mHandler.postDelayed(mWriteRunner, WRITE_DELAY); 3962 } 3963 } 3964 scheduleFastWriteLocked()3965 private void scheduleFastWriteLocked() { 3966 if (!mFastWriteScheduled) { 3967 mWriteScheduled = true; 3968 mFastWriteScheduled = true; 3969 mHandler.removeCallbacks(mWriteRunner); 3970 mHandler.postDelayed(mWriteRunner, 10*1000); 3971 } 3972 } 3973 3974 /** 3975 * Get the state of an op for a uid. 3976 * 3977 * @param code The code of the op 3978 * @param uid The uid the of the package 3979 * @param packageName The package name for which to get the state for 3980 * @param attributionTag The attribution tag 3981 * @param isAttributionTagValid Whether the given attribution tag is valid 3982 * @param bypass When to bypass certain op restrictions (can be null if edit == false) 3983 * @param edit Iff {@code true} create the {@link Op} object if not yet created 3984 * 3985 * @return The {@link Op state} of the op 3986 */ getOpLocked(int code, int uid, @NonNull String packageName, @Nullable String attributionTag, boolean isAttributionTagValid, @Nullable RestrictionBypass bypass, boolean edit)3987 private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName, 3988 @Nullable String attributionTag, boolean isAttributionTagValid, 3989 @Nullable RestrictionBypass bypass, boolean edit) { 3990 Ops ops = getOpsLocked(uid, packageName, attributionTag, isAttributionTagValid, bypass, 3991 edit); 3992 if (ops == null) { 3993 return null; 3994 } 3995 return getOpLocked(ops, code, uid, edit); 3996 } 3997 getOpLocked(Ops ops, int code, int uid, boolean edit)3998 private Op getOpLocked(Ops ops, int code, int uid, boolean edit) { 3999 Op op = ops.get(code); 4000 if (op == null) { 4001 if (!edit) { 4002 return null; 4003 } 4004 op = new Op(ops.uidState, ops.packageName, code, uid); 4005 ops.put(code, op); 4006 } 4007 if (edit) { 4008 scheduleWriteLocked(); 4009 } 4010 return op; 4011 } 4012 isOpRestrictedDueToSuspend(int code, String packageName, int uid)4013 private boolean isOpRestrictedDueToSuspend(int code, String packageName, int uid) { 4014 if (!ArrayUtils.contains(OPS_RESTRICTED_ON_SUSPEND, code)) { 4015 return false; 4016 } 4017 final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); 4018 return pmi.isPackageSuspended(packageName, UserHandle.getUserId(uid)); 4019 } 4020 isOpRestrictedLocked(int uid, int code, String packageName, String attributionTag, @Nullable RestrictionBypass appBypass, boolean isCheckOp)4021 private boolean isOpRestrictedLocked(int uid, int code, String packageName, 4022 String attributionTag, @Nullable RestrictionBypass appBypass, boolean isCheckOp) { 4023 int restrictionSetCount = mOpGlobalRestrictions.size(); 4024 4025 for (int i = 0; i < restrictionSetCount; i++) { 4026 ClientGlobalRestrictionState restrictionState = mOpGlobalRestrictions.valueAt(i); 4027 if (restrictionState.hasRestriction(code)) { 4028 return true; 4029 } 4030 } 4031 4032 int userHandle = UserHandle.getUserId(uid); 4033 restrictionSetCount = mOpUserRestrictions.size(); 4034 4035 for (int i = 0; i < restrictionSetCount; i++) { 4036 // For each client, check that the given op is not restricted, or that the given 4037 // package is exempt from the restriction. 4038 ClientUserRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); 4039 if (restrictionState.hasRestriction(code, packageName, attributionTag, userHandle, 4040 isCheckOp)) { 4041 RestrictionBypass opBypass = opAllowSystemBypassRestriction(code); 4042 if (opBypass != null) { 4043 // If we are the system, bypass user restrictions for certain codes 4044 synchronized (this) { 4045 if (opBypass.isSystemUid && appBypass != null && appBypass.isSystemUid) { 4046 return false; 4047 } 4048 if (opBypass.isPrivileged && appBypass != null && appBypass.isPrivileged) { 4049 return false; 4050 } 4051 if (opBypass.isRecordAudioRestrictionExcept && appBypass != null 4052 && appBypass.isRecordAudioRestrictionExcept) { 4053 return false; 4054 } 4055 } 4056 } 4057 return true; 4058 } 4059 } 4060 return false; 4061 } 4062 4063 /** 4064 * Read recent accesses from persistence (mRecentAccessesFile). 4065 * If there is no mRecentAccessesFile yet, we'll need migrate from mStorageFile: first read from 4066 * mStorageFile, then all subsequent reads/writes will use mRecentAccessesFile. 4067 * If neither file exists, there's nothing to migrate. 4068 */ readRecentAccesses()4069 private void readRecentAccesses() { 4070 if (!mRecentAccessesFile.exists()) { 4071 readRecentAccesses(mStorageFile); 4072 } else { 4073 readRecentAccesses(mRecentAccessesFile); 4074 } 4075 } 4076 readRecentAccesses(AtomicFile file)4077 private void readRecentAccesses(AtomicFile file) { 4078 synchronized (file) { 4079 synchronized (this) { 4080 FileInputStream stream; 4081 try { 4082 stream = file.openRead(); 4083 } catch (FileNotFoundException e) { 4084 Slog.i(TAG, "No existing app ops " + file.getBaseFile() + "; starting empty"); 4085 return; 4086 } 4087 boolean success = false; 4088 mUidStates.clear(); 4089 mAppOpsCheckingService.clearAllModes(); 4090 try { 4091 TypedXmlPullParser parser = Xml.resolvePullParser(stream); 4092 int type; 4093 while ((type = parser.next()) != XmlPullParser.START_TAG 4094 && type != XmlPullParser.END_DOCUMENT) { 4095 // Parse next until we reach the start or end 4096 } 4097 4098 if (type != XmlPullParser.START_TAG) { 4099 throw new IllegalStateException("no start tag found"); 4100 } 4101 4102 int outerDepth = parser.getDepth(); 4103 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 4104 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 4105 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 4106 continue; 4107 } 4108 4109 String tagName = parser.getName(); 4110 if (tagName.equals("pkg")) { 4111 readPackage(parser); 4112 } else if (tagName.equals("uid")) { 4113 // uid tag may be present during migration, don't print warning. 4114 XmlUtils.skipCurrentTag(parser); 4115 } else { 4116 Slog.w(TAG, "Unknown element under <app-ops>: " 4117 + parser.getName()); 4118 XmlUtils.skipCurrentTag(parser); 4119 } 4120 } 4121 4122 success = true; 4123 } catch (IllegalStateException e) { 4124 Slog.w(TAG, "Failed parsing " + e); 4125 } catch (NullPointerException e) { 4126 Slog.w(TAG, "Failed parsing " + e); 4127 } catch (NumberFormatException e) { 4128 Slog.w(TAG, "Failed parsing " + e); 4129 } catch (XmlPullParserException e) { 4130 Slog.w(TAG, "Failed parsing " + e); 4131 } catch (IOException e) { 4132 Slog.w(TAG, "Failed parsing " + e); 4133 } catch (IndexOutOfBoundsException e) { 4134 Slog.w(TAG, "Failed parsing " + e); 4135 } finally { 4136 if (!success) { 4137 mUidStates.clear(); 4138 mAppOpsCheckingService.clearAllModes(); 4139 } 4140 try { 4141 stream.close(); 4142 } catch (IOException e) { 4143 } 4144 } 4145 } 4146 } 4147 } 4148 readPackage(TypedXmlPullParser parser)4149 private void readPackage(TypedXmlPullParser parser) 4150 throws NumberFormatException, XmlPullParserException, IOException { 4151 String pkgName = parser.getAttributeValue(null, "n"); 4152 int outerDepth = parser.getDepth(); 4153 int type; 4154 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 4155 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 4156 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 4157 continue; 4158 } 4159 4160 String tagName = parser.getName(); 4161 if (tagName.equals("uid")) { 4162 readUid(parser, pkgName); 4163 } else { 4164 Slog.w(TAG, "Unknown element under <pkg>: " 4165 + parser.getName()); 4166 XmlUtils.skipCurrentTag(parser); 4167 } 4168 } 4169 } 4170 readUid(TypedXmlPullParser parser, String pkgName)4171 private void readUid(TypedXmlPullParser parser, String pkgName) 4172 throws NumberFormatException, XmlPullParserException, IOException { 4173 int uid = parser.getAttributeInt(null, "n"); 4174 final UidState uidState = getUidStateLocked(uid, true); 4175 int outerDepth = parser.getDepth(); 4176 int type; 4177 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 4178 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 4179 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 4180 continue; 4181 } 4182 String tagName = parser.getName(); 4183 if (tagName.equals("op")) { 4184 readOp(parser, uidState, pkgName); 4185 } else { 4186 Slog.w(TAG, "Unknown element under <pkg>: " 4187 + parser.getName()); 4188 XmlUtils.skipCurrentTag(parser); 4189 } 4190 } 4191 } 4192 readAttributionOp(TypedXmlPullParser parser, @NonNull Op parent, @Nullable String attribution)4193 private void readAttributionOp(TypedXmlPullParser parser, @NonNull Op parent, 4194 @Nullable String attribution) 4195 throws NumberFormatException, IOException, XmlPullParserException { 4196 final AttributedOp attributedOp = parent.getOrCreateAttribution(parent, attribution); 4197 4198 final long key = parser.getAttributeLong(null, "n"); 4199 final int uidState = extractUidStateFromKey(key); 4200 final int opFlags = extractFlagsFromKey(key); 4201 4202 final long accessTime = parser.getAttributeLong(null, "t", 0); 4203 final long rejectTime = parser.getAttributeLong(null, "r", 0); 4204 final long accessDuration = parser.getAttributeLong(null, "d", -1); 4205 final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp"); 4206 final int proxyUid = parser.getAttributeInt(null, "pu", Process.INVALID_UID); 4207 final String proxyAttributionTag = XmlUtils.readStringAttribute(parser, "pc"); 4208 4209 if (accessTime > 0) { 4210 attributedOp.accessed(accessTime, accessDuration, proxyUid, proxyPkg, 4211 proxyAttributionTag, uidState, opFlags); 4212 } 4213 if (rejectTime > 0) { 4214 attributedOp.rejected(rejectTime, uidState, opFlags); 4215 } 4216 } 4217 readOp(TypedXmlPullParser parser, @NonNull UidState uidState, @NonNull String pkgName)4218 private void readOp(TypedXmlPullParser parser, 4219 @NonNull UidState uidState, @NonNull String pkgName) 4220 throws NumberFormatException, XmlPullParserException, IOException { 4221 int opCode = parser.getAttributeInt(null, "n"); 4222 Op op = new Op(uidState, pkgName, opCode, uidState.uid); 4223 4224 int outerDepth = parser.getDepth(); 4225 int type; 4226 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 4227 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 4228 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 4229 continue; 4230 } 4231 String tagName = parser.getName(); 4232 if (tagName.equals("st")) { 4233 readAttributionOp(parser, op, XmlUtils.readStringAttribute(parser, "id")); 4234 } else { 4235 Slog.w(TAG, "Unknown element under <op>: " 4236 + parser.getName()); 4237 XmlUtils.skipCurrentTag(parser); 4238 } 4239 } 4240 4241 Ops ops = uidState.pkgOps.get(pkgName); 4242 if (ops == null) { 4243 ops = new Ops(pkgName, uidState); 4244 uidState.pkgOps.put(pkgName, ops); 4245 } 4246 ops.put(op.op, op); 4247 } 4248 4249 @VisibleForTesting writeRecentAccesses()4250 void writeRecentAccesses() { 4251 synchronized (mRecentAccessesFile) { 4252 FileOutputStream stream; 4253 try { 4254 stream = mRecentAccessesFile.startWrite(); 4255 } catch (IOException e) { 4256 Slog.w(TAG, "Failed to write state: " + e); 4257 return; 4258 } 4259 4260 List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null); 4261 4262 try { 4263 TypedXmlSerializer out = Xml.resolveSerializer(stream); 4264 out.startDocument(null, true); 4265 out.startTag(null, "app-ops"); 4266 out.attributeInt(null, "v", CURRENT_VERSION); 4267 4268 if (allOps != null) { 4269 String lastPkg = null; 4270 for (int i=0; i<allOps.size(); i++) { 4271 AppOpsManager.PackageOps pkg = allOps.get(i); 4272 if (!Objects.equals(pkg.getPackageName(), lastPkg)) { 4273 if (lastPkg != null) { 4274 out.endTag(null, "pkg"); 4275 } 4276 lastPkg = pkg.getPackageName(); 4277 if (lastPkg != null) { 4278 out.startTag(null, "pkg"); 4279 out.attribute(null, "n", lastPkg); 4280 } 4281 } 4282 out.startTag(null, "uid"); 4283 out.attributeInt(null, "n", pkg.getUid()); 4284 List<AppOpsManager.OpEntry> ops = pkg.getOps(); 4285 for (int j=0; j<ops.size(); j++) { 4286 AppOpsManager.OpEntry op = ops.get(j); 4287 out.startTag(null, "op"); 4288 out.attributeInt(null, "n", op.getOp()); 4289 if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) { 4290 out.attributeInt(null, "m", op.getMode()); 4291 } 4292 4293 for (String attributionTag : op.getAttributedOpEntries().keySet()) { 4294 final AttributedOpEntry attribution = 4295 op.getAttributedOpEntries().get(attributionTag); 4296 4297 final ArraySet<Long> keys = attribution.collectKeys(); 4298 4299 final int keyCount = keys.size(); 4300 for (int k = 0; k < keyCount; k++) { 4301 final long key = keys.valueAt(k); 4302 4303 final int uidState = AppOpsManager.extractUidStateFromKey(key); 4304 final int flags = AppOpsManager.extractFlagsFromKey(key); 4305 4306 final long accessTime = attribution.getLastAccessTime(uidState, 4307 uidState, flags); 4308 final long rejectTime = attribution.getLastRejectTime(uidState, 4309 uidState, flags); 4310 final long accessDuration = attribution.getLastDuration( 4311 uidState, uidState, flags); 4312 // Proxy information for rejections is not backed up 4313 final OpEventProxyInfo proxy = attribution.getLastProxyInfo( 4314 uidState, uidState, flags); 4315 4316 if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0 4317 && proxy == null) { 4318 continue; 4319 } 4320 4321 String proxyPkg = null; 4322 String proxyAttributionTag = null; 4323 int proxyUid = Process.INVALID_UID; 4324 if (proxy != null) { 4325 proxyPkg = proxy.getPackageName(); 4326 proxyAttributionTag = proxy.getAttributionTag(); 4327 proxyUid = proxy.getUid(); 4328 } 4329 4330 out.startTag(null, "st"); 4331 if (attributionTag != null) { 4332 out.attribute(null, "id", attributionTag); 4333 } 4334 out.attributeLong(null, "n", key); 4335 if (accessTime > 0) { 4336 out.attributeLong(null, "t", accessTime); 4337 } 4338 if (rejectTime > 0) { 4339 out.attributeLong(null, "r", rejectTime); 4340 } 4341 if (accessDuration > 0) { 4342 out.attributeLong(null, "d", accessDuration); 4343 } 4344 if (proxyPkg != null) { 4345 out.attribute(null, "pp", proxyPkg); 4346 } 4347 if (proxyAttributionTag != null) { 4348 out.attribute(null, "pc", proxyAttributionTag); 4349 } 4350 if (proxyUid >= 0) { 4351 out.attributeInt(null, "pu", proxyUid); 4352 } 4353 out.endTag(null, "st"); 4354 } 4355 } 4356 4357 out.endTag(null, "op"); 4358 } 4359 out.endTag(null, "uid"); 4360 } 4361 if (lastPkg != null) { 4362 out.endTag(null, "pkg"); 4363 } 4364 } 4365 4366 out.endTag(null, "app-ops"); 4367 out.endDocument(); 4368 mRecentAccessesFile.finishWrite(stream); 4369 } catch (IOException e) { 4370 Slog.w(TAG, "Failed to write state, restoring backup.", e); 4371 mRecentAccessesFile.failWrite(stream); 4372 } 4373 } 4374 mHistoricalRegistry.writeAndClearDiscreteHistory(); 4375 } 4376 4377 static class Shell extends ShellCommand { 4378 final IAppOpsService mInterface; 4379 final AppOpsService mInternal; 4380 4381 int userId = UserHandle.USER_SYSTEM; 4382 String packageName; 4383 String attributionTag; 4384 String opStr; 4385 String modeStr; 4386 int op; 4387 int mode; 4388 int packageUid; 4389 int nonpackageUid; 4390 final static Binder sBinder = new Binder(); 4391 IBinder mToken; 4392 boolean targetsUid; 4393 Shell(IAppOpsService iface, AppOpsService internal)4394 Shell(IAppOpsService iface, AppOpsService internal) { 4395 mInterface = iface; 4396 mInternal = internal; 4397 mToken = AppOpsManager.getClientId(); 4398 } 4399 4400 @Override onCommand(String cmd)4401 public int onCommand(String cmd) { 4402 return onShellCommand(this, cmd); 4403 } 4404 4405 @Override onHelp()4406 public void onHelp() { 4407 PrintWriter pw = getOutPrintWriter(); 4408 dumpCommandHelp(pw); 4409 } 4410 strOpToOp(String op, PrintWriter err)4411 static private int strOpToOp(String op, PrintWriter err) { 4412 try { 4413 return AppOpsManager.strOpToOp(op); 4414 } catch (IllegalArgumentException e) { 4415 } 4416 try { 4417 return Integer.parseInt(op); 4418 } catch (NumberFormatException e) { 4419 } 4420 try { 4421 return AppOpsManager.strDebugOpToOp(op); 4422 } catch (IllegalArgumentException e) { 4423 err.println("Error: " + e.getMessage()); 4424 return -1; 4425 } 4426 } 4427 strModeToMode(String modeStr, PrintWriter err)4428 static int strModeToMode(String modeStr, PrintWriter err) { 4429 for (int i = AppOpsManager.MODE_NAMES.length - 1; i >= 0; i--) { 4430 if (AppOpsManager.MODE_NAMES[i].equals(modeStr)) { 4431 return i; 4432 } 4433 } 4434 try { 4435 return Integer.parseInt(modeStr); 4436 } catch (NumberFormatException e) { 4437 } 4438 err.println("Error: Mode " + modeStr + " is not valid"); 4439 return -1; 4440 } 4441 parseUserOpMode(int defMode, PrintWriter err)4442 int parseUserOpMode(int defMode, PrintWriter err) throws RemoteException { 4443 userId = UserHandle.USER_CURRENT; 4444 opStr = null; 4445 modeStr = null; 4446 for (String argument; (argument = getNextArg()) != null;) { 4447 if ("--user".equals(argument)) { 4448 userId = UserHandle.parseUserArg(getNextArgRequired()); 4449 } else { 4450 if (opStr == null) { 4451 opStr = argument; 4452 } else if (modeStr == null) { 4453 modeStr = argument; 4454 break; 4455 } 4456 } 4457 } 4458 if (opStr == null) { 4459 err.println("Error: Operation not specified."); 4460 return -1; 4461 } 4462 op = strOpToOp(opStr, err); 4463 if (op < 0) { 4464 return -1; 4465 } 4466 if (modeStr != null) { 4467 if ((mode=strModeToMode(modeStr, err)) < 0) { 4468 return -1; 4469 } 4470 } else { 4471 mode = defMode; 4472 } 4473 return 0; 4474 } 4475 parseUserPackageOp(boolean reqOp, PrintWriter err)4476 int parseUserPackageOp(boolean reqOp, PrintWriter err) throws RemoteException { 4477 userId = UserHandle.USER_CURRENT; 4478 packageName = null; 4479 opStr = null; 4480 for (String argument; (argument = getNextArg()) != null;) { 4481 if ("--user".equals(argument)) { 4482 userId = UserHandle.parseUserArg(getNextArgRequired()); 4483 } else if ("--uid".equals(argument)) { 4484 targetsUid = true; 4485 } else if ("--attribution".equals(argument)) { 4486 attributionTag = getNextArgRequired(); 4487 } else { 4488 if (packageName == null) { 4489 packageName = argument; 4490 } else if (opStr == null) { 4491 opStr = argument; 4492 break; 4493 } 4494 } 4495 } 4496 if (packageName == null) { 4497 err.println("Error: Package name not specified."); 4498 return -1; 4499 } else if (opStr == null && reqOp) { 4500 err.println("Error: Operation not specified."); 4501 return -1; 4502 } 4503 if (opStr != null) { 4504 op = strOpToOp(opStr, err); 4505 if (op < 0) { 4506 return -1; 4507 } 4508 } else { 4509 op = AppOpsManager.OP_NONE; 4510 } 4511 if (userId == UserHandle.USER_CURRENT) { 4512 userId = ActivityManager.getCurrentUser(); 4513 } 4514 nonpackageUid = -1; 4515 try { 4516 nonpackageUid = Integer.parseInt(packageName); 4517 } catch (NumberFormatException e) { 4518 } 4519 if (nonpackageUid == -1 && packageName.length() > 1 && packageName.charAt(0) == 'u' 4520 && packageName.indexOf('.') < 0) { 4521 int i = 1; 4522 while (i < packageName.length() && packageName.charAt(i) >= '0' 4523 && packageName.charAt(i) <= '9') { 4524 i++; 4525 } 4526 if (i > 1 && i < packageName.length()) { 4527 String userStr = packageName.substring(1, i); 4528 try { 4529 int user = Integer.parseInt(userStr); 4530 char type = packageName.charAt(i); 4531 i++; 4532 int startTypeVal = i; 4533 while (i < packageName.length() && packageName.charAt(i) >= '0' 4534 && packageName.charAt(i) <= '9') { 4535 i++; 4536 } 4537 if (i > startTypeVal) { 4538 String typeValStr = packageName.substring(startTypeVal, i); 4539 try { 4540 int typeVal = Integer.parseInt(typeValStr); 4541 if (type == 'a') { 4542 nonpackageUid = UserHandle.getUid(user, 4543 typeVal + Process.FIRST_APPLICATION_UID); 4544 } else if (type == 's') { 4545 nonpackageUid = UserHandle.getUid(user, typeVal); 4546 } 4547 } catch (NumberFormatException e) { 4548 } 4549 } 4550 } catch (NumberFormatException e) { 4551 } 4552 } 4553 } 4554 if (nonpackageUid != -1) { 4555 packageName = null; 4556 } else { 4557 packageUid = resolveUid(packageName); 4558 if (packageUid < 0) { 4559 packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, 4560 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); 4561 } 4562 if (packageUid < 0) { 4563 err.println("Error: No UID for " + packageName + " in user " + userId); 4564 return -1; 4565 } 4566 } 4567 return 0; 4568 } 4569 } 4570 onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)4571 @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, 4572 FileDescriptor err, String[] args, ShellCallback callback, 4573 ResultReceiver resultReceiver) { 4574 (new Shell(this, this)).exec(this, in, out, err, args, callback, resultReceiver); 4575 } 4576 dumpCommandHelp(PrintWriter pw)4577 static void dumpCommandHelp(PrintWriter pw) { 4578 pw.println("AppOps service (appops) commands:"); 4579 pw.println(" help"); 4580 pw.println(" Print this help text."); 4581 pw.println(" start [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> " 4582 + "<OP> "); 4583 pw.println(" Starts a given operation for a particular application."); 4584 pw.println(" stop [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> " 4585 + "<OP> "); 4586 pw.println(" Stops a given operation for a particular application."); 4587 pw.println(" set [--user <USER_ID>] <[--uid] PACKAGE | UID> <OP> <MODE>"); 4588 pw.println(" Set the mode for a particular application and operation."); 4589 pw.println(" get [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> " 4590 + "[<OP>]"); 4591 pw.println(" Return the mode for a particular application and optional operation."); 4592 pw.println(" query-op [--user <USER_ID>] <OP> [<MODE>]"); 4593 pw.println(" Print all packages that currently have the given op in the given mode."); 4594 pw.println(" reset [--user <USER_ID>] [<PACKAGE>]"); 4595 pw.println(" Reset the given application or all applications to default modes."); 4596 pw.println(" write-settings"); 4597 pw.println(" Immediately write pending changes to storage."); 4598 pw.println(" read-settings"); 4599 pw.println(" Read the last written settings, replacing current state in RAM."); 4600 pw.println(" options:"); 4601 pw.println(" <PACKAGE> an Android package name or its UID if prefixed by --uid"); 4602 pw.println(" <OP> an AppOps operation."); 4603 pw.println(" <MODE> one of allow, ignore, deny, or default"); 4604 pw.println(" <USER_ID> the user id under which the package is installed. If --user is"); 4605 pw.println(" not specified, the current user is assumed."); 4606 } 4607 onShellCommand(Shell shell, String cmd)4608 static int onShellCommand(Shell shell, String cmd) { 4609 if (cmd == null) { 4610 return shell.handleDefaultCommands(cmd); 4611 } 4612 PrintWriter pw = shell.getOutPrintWriter(); 4613 PrintWriter err = shell.getErrPrintWriter(); 4614 try { 4615 switch (cmd) { 4616 case "set": { 4617 int res = shell.parseUserPackageOp(true, err); 4618 if (res < 0) { 4619 return res; 4620 } 4621 String modeStr = shell.getNextArg(); 4622 if (modeStr == null) { 4623 err.println("Error: Mode not specified."); 4624 return -1; 4625 } 4626 4627 final int mode = shell.strModeToMode(modeStr, err); 4628 if (mode < 0) { 4629 return -1; 4630 } 4631 4632 if (!shell.targetsUid && shell.packageName != null) { 4633 shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName, 4634 mode); 4635 } else if (shell.targetsUid && shell.packageName != null) { 4636 try { 4637 final int uid = shell.mInternal.mContext.getPackageManager() 4638 .getPackageUidAsUser(shell.packageName, shell.userId); 4639 shell.mInterface.setUidMode(shell.op, uid, mode); 4640 } catch (PackageManager.NameNotFoundException e) { 4641 return -1; 4642 } 4643 } else { 4644 shell.mInterface.setUidMode(shell.op, shell.nonpackageUid, mode); 4645 } 4646 return 0; 4647 } 4648 case "get": { 4649 int res = shell.parseUserPackageOp(false, err); 4650 if (res < 0) { 4651 return res; 4652 } 4653 4654 List<AppOpsManager.PackageOps> ops = new ArrayList<>(); 4655 if (shell.packageName != null) { 4656 // Uid mode overrides package mode, so make sure it's also reported 4657 List<AppOpsManager.PackageOps> r = shell.mInterface.getUidOps( 4658 shell.packageUid, 4659 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); 4660 if (r != null) { 4661 ops.addAll(r); 4662 } 4663 r = shell.mInterface.getOpsForPackage( 4664 shell.packageUid, shell.packageName, 4665 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); 4666 if (r != null) { 4667 ops.addAll(r); 4668 } 4669 } else { 4670 ops = shell.mInterface.getUidOps( 4671 shell.nonpackageUid, 4672 shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null); 4673 } 4674 if (ops == null || ops.size() <= 0) { 4675 pw.println("No operations."); 4676 if (shell.op > AppOpsManager.OP_NONE && shell.op < AppOpsManager._NUM_OP) { 4677 pw.println("Default mode: " + AppOpsManager.modeToName( 4678 AppOpsManager.opToDefaultMode(shell.op))); 4679 } 4680 return 0; 4681 } 4682 final long now = System.currentTimeMillis(); 4683 for (int i=0; i<ops.size(); i++) { 4684 AppOpsManager.PackageOps packageOps = ops.get(i); 4685 if (packageOps.getPackageName() == null) { 4686 pw.print("Uid mode: "); 4687 } 4688 List<AppOpsManager.OpEntry> entries = packageOps.getOps(); 4689 for (int j=0; j<entries.size(); j++) { 4690 AppOpsManager.OpEntry ent = entries.get(j); 4691 pw.print(AppOpsManager.opToName(ent.getOp())); 4692 pw.print(": "); 4693 pw.print(AppOpsManager.modeToName(ent.getMode())); 4694 if (shell.attributionTag == null) { 4695 if (ent.getLastAccessTime(OP_FLAGS_ALL) != -1) { 4696 pw.print("; time="); 4697 TimeUtils.formatDuration( 4698 now - ent.getLastAccessTime(OP_FLAGS_ALL), pw); 4699 pw.print(" ago"); 4700 } 4701 if (ent.getLastRejectTime(OP_FLAGS_ALL) != -1) { 4702 pw.print("; rejectTime="); 4703 TimeUtils.formatDuration( 4704 now - ent.getLastRejectTime(OP_FLAGS_ALL), pw); 4705 pw.print(" ago"); 4706 } 4707 if (ent.isRunning()) { 4708 pw.print(" (running)"); 4709 } else if (ent.getLastDuration(OP_FLAGS_ALL) != -1) { 4710 pw.print("; duration="); 4711 TimeUtils.formatDuration(ent.getLastDuration(OP_FLAGS_ALL), pw); 4712 } 4713 } else { 4714 final AppOpsManager.AttributedOpEntry attributionEnt = 4715 ent.getAttributedOpEntries().get(shell.attributionTag); 4716 if (attributionEnt != null) { 4717 if (attributionEnt.getLastAccessTime(OP_FLAGS_ALL) != -1) { 4718 pw.print("; time="); 4719 TimeUtils.formatDuration( 4720 now - attributionEnt.getLastAccessTime( 4721 OP_FLAGS_ALL), pw); 4722 pw.print(" ago"); 4723 } 4724 if (attributionEnt.getLastRejectTime(OP_FLAGS_ALL) != -1) { 4725 pw.print("; rejectTime="); 4726 TimeUtils.formatDuration( 4727 now - attributionEnt.getLastRejectTime( 4728 OP_FLAGS_ALL), pw); 4729 pw.print(" ago"); 4730 } 4731 if (attributionEnt.isRunning()) { 4732 pw.print(" (running)"); 4733 } else if (attributionEnt.getLastDuration(OP_FLAGS_ALL) 4734 != -1) { 4735 pw.print("; duration="); 4736 TimeUtils.formatDuration( 4737 attributionEnt.getLastDuration(OP_FLAGS_ALL), pw); 4738 } 4739 } 4740 } 4741 pw.println(); 4742 } 4743 } 4744 return 0; 4745 } 4746 case "query-op": { 4747 int res = shell.parseUserOpMode(AppOpsManager.MODE_IGNORED, err); 4748 if (res < 0) { 4749 return res; 4750 } 4751 List<AppOpsManager.PackageOps> ops = shell.mInterface.getPackagesForOps( 4752 new int[] {shell.op}); 4753 if (ops == null || ops.size() <= 0) { 4754 pw.println("No operations."); 4755 return 0; 4756 } 4757 for (int i=0; i<ops.size(); i++) { 4758 final AppOpsManager.PackageOps pkg = ops.get(i); 4759 boolean hasMatch = false; 4760 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps(); 4761 for (int j=0; j<entries.size(); j++) { 4762 AppOpsManager.OpEntry ent = entries.get(j); 4763 if (ent.getOp() == shell.op && ent.getMode() == shell.mode) { 4764 hasMatch = true; 4765 break; 4766 } 4767 } 4768 if (hasMatch) { 4769 pw.println(pkg.getPackageName()); 4770 } 4771 } 4772 return 0; 4773 } 4774 case "reset": { 4775 String packageName = null; 4776 int userId = UserHandle.USER_CURRENT; 4777 for (String argument; (argument = shell.getNextArg()) != null;) { 4778 if ("--user".equals(argument)) { 4779 String userStr = shell.getNextArgRequired(); 4780 userId = UserHandle.parseUserArg(userStr); 4781 } else { 4782 if (packageName == null) { 4783 packageName = argument; 4784 } else { 4785 err.println("Error: Unsupported argument: " + argument); 4786 return -1; 4787 } 4788 } 4789 } 4790 4791 if (userId == UserHandle.USER_CURRENT) { 4792 userId = ActivityManager.getCurrentUser(); 4793 } 4794 4795 shell.mInterface.resetAllModes(userId, packageName); 4796 pw.print("Reset all modes for: "); 4797 if (userId == UserHandle.USER_ALL) { 4798 pw.print("all users"); 4799 } else { 4800 pw.print("user "); pw.print(userId); 4801 } 4802 pw.print(", "); 4803 if (packageName == null) { 4804 pw.println("all packages"); 4805 } else { 4806 pw.print("package "); pw.println(packageName); 4807 } 4808 return 0; 4809 } 4810 case "write-settings": { 4811 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(), 4812 Binder.getCallingUid(), -1); 4813 final long token = Binder.clearCallingIdentity(); 4814 try { 4815 synchronized (shell.mInternal) { 4816 shell.mInternal.mHandler.removeCallbacks(shell.mInternal.mWriteRunner); 4817 } 4818 shell.mInternal.writeRecentAccesses(); 4819 shell.mInternal.mAppOpsCheckingService.writeState(); 4820 pw.println("Current settings written."); 4821 } finally { 4822 Binder.restoreCallingIdentity(token); 4823 } 4824 return 0; 4825 } 4826 case "read-settings": { 4827 shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(), 4828 Binder.getCallingUid(), -1); 4829 final long token = Binder.clearCallingIdentity(); 4830 try { 4831 shell.mInternal.readRecentAccesses(); 4832 shell.mInternal.mAppOpsCheckingService.readState(); 4833 pw.println("Last settings read."); 4834 } finally { 4835 Binder.restoreCallingIdentity(token); 4836 } 4837 return 0; 4838 } 4839 case "start": { 4840 int res = shell.parseUserPackageOp(true, err); 4841 if (res < 0) { 4842 return res; 4843 } 4844 4845 if (shell.packageName != null) { 4846 shell.mInterface.startOperation(shell.mToken, shell.op, shell.packageUid, 4847 shell.packageName, shell.attributionTag, true, true, 4848 "appops start shell command", true, 4849 AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR, ATTRIBUTION_CHAIN_ID_NONE); 4850 } else { 4851 return -1; 4852 } 4853 return 0; 4854 } 4855 case "stop": { 4856 int res = shell.parseUserPackageOp(true, err); 4857 if (res < 0) { 4858 return res; 4859 } 4860 4861 if (shell.packageName != null) { 4862 shell.mInterface.finishOperation(shell.mToken, shell.op, shell.packageUid, 4863 shell.packageName, shell.attributionTag); 4864 } else { 4865 return -1; 4866 } 4867 return 0; 4868 } 4869 default: 4870 return shell.handleDefaultCommands(cmd); 4871 } 4872 } catch (RemoteException e) { 4873 pw.println("Remote exception: " + e); 4874 } 4875 return -1; 4876 } 4877 dumpHelp(PrintWriter pw)4878 private void dumpHelp(PrintWriter pw) { 4879 pw.println("AppOps service (appops) dump options:"); 4880 pw.println(" -h"); 4881 pw.println(" Print this help text."); 4882 pw.println(" --op [OP]"); 4883 pw.println(" Limit output to data associated with the given app op code."); 4884 pw.println(" --mode [MODE]"); 4885 pw.println(" Limit output to data associated with the given app op mode."); 4886 pw.println(" --package [PACKAGE]"); 4887 pw.println(" Limit output to data associated with the given package name."); 4888 pw.println(" --attributionTag [attributionTag]"); 4889 pw.println(" Limit output to data associated with the given attribution tag."); 4890 pw.println(" --include-discrete [n]"); 4891 pw.println(" Include discrete ops limited to n per dimension. Use zero for no limit."); 4892 pw.println(" --watchers"); 4893 pw.println(" Only output the watcher sections."); 4894 pw.println(" --history"); 4895 pw.println(" Only output history."); 4896 pw.println(" --uid-state-changes"); 4897 pw.println(" Include logs about uid state changes."); 4898 } 4899 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)4900 private void dumpStatesLocked(@NonNull PrintWriter pw, @Nullable String filterAttributionTag, 4901 @HistoricalOpsRequestFilter int filter, long nowElapsed, @NonNull Op op, long now, 4902 @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix) { 4903 final int numAttributions = op.mAttributions.size(); 4904 for (int i = 0; i < numAttributions; i++) { 4905 if ((filter & FILTER_BY_ATTRIBUTION_TAG) != 0 && !Objects.equals( 4906 op.mAttributions.keyAt(i), filterAttributionTag)) { 4907 continue; 4908 } 4909 4910 pw.print(prefix + op.mAttributions.keyAt(i) + "=[\n"); 4911 dumpStatesLocked(pw, nowElapsed, op, op.mAttributions.keyAt(i), now, sdf, date, 4912 prefix + " "); 4913 pw.print(prefix + "]\n"); 4914 } 4915 } 4916 dumpStatesLocked(@onNull PrintWriter pw, long nowElapsed, @NonNull Op op, @Nullable String attributionTag, long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix)4917 private void dumpStatesLocked(@NonNull PrintWriter pw, long nowElapsed, @NonNull Op op, 4918 @Nullable String attributionTag, long now, @NonNull SimpleDateFormat sdf, 4919 @NonNull Date date, @NonNull String prefix) { 4920 4921 final AttributedOpEntry entry = op.createSingleAttributionEntryLocked( 4922 attributionTag).getAttributedOpEntries().get(attributionTag); 4923 4924 final ArraySet<Long> keys = entry.collectKeys(); 4925 4926 final int keyCount = keys.size(); 4927 for (int k = 0; k < keyCount; k++) { 4928 final long key = keys.valueAt(k); 4929 4930 final int uidState = AppOpsManager.extractUidStateFromKey(key); 4931 final int flags = AppOpsManager.extractFlagsFromKey(key); 4932 4933 final long accessTime = entry.getLastAccessTime(uidState, uidState, flags); 4934 final long rejectTime = entry.getLastRejectTime(uidState, uidState, flags); 4935 final long accessDuration = entry.getLastDuration(uidState, uidState, flags); 4936 final OpEventProxyInfo proxy = entry.getLastProxyInfo(uidState, uidState, flags); 4937 4938 String proxyPkg = null; 4939 String proxyAttributionTag = null; 4940 int proxyUid = Process.INVALID_UID; 4941 if (proxy != null) { 4942 proxyPkg = proxy.getPackageName(); 4943 proxyAttributionTag = proxy.getAttributionTag(); 4944 proxyUid = proxy.getUid(); 4945 } 4946 4947 if (accessTime > 0) { 4948 pw.print(prefix); 4949 pw.print("Access: "); 4950 pw.print(AppOpsManager.keyToString(key)); 4951 pw.print(" "); 4952 date.setTime(accessTime); 4953 pw.print(sdf.format(date)); 4954 pw.print(" ("); 4955 TimeUtils.formatDuration(accessTime - now, pw); 4956 pw.print(")"); 4957 if (accessDuration > 0) { 4958 pw.print(" duration="); 4959 TimeUtils.formatDuration(accessDuration, pw); 4960 } 4961 if (proxyUid >= 0) { 4962 pw.print(" proxy["); 4963 pw.print("uid="); 4964 pw.print(proxyUid); 4965 pw.print(", pkg="); 4966 pw.print(proxyPkg); 4967 pw.print(", attributionTag="); 4968 pw.print(proxyAttributionTag); 4969 pw.print("]"); 4970 } 4971 pw.println(); 4972 } 4973 4974 if (rejectTime > 0) { 4975 pw.print(prefix); 4976 pw.print("Reject: "); 4977 pw.print(AppOpsManager.keyToString(key)); 4978 date.setTime(rejectTime); 4979 pw.print(sdf.format(date)); 4980 pw.print(" ("); 4981 TimeUtils.formatDuration(rejectTime - now, pw); 4982 pw.print(")"); 4983 if (proxyUid >= 0) { 4984 pw.print(" proxy["); 4985 pw.print("uid="); 4986 pw.print(proxyUid); 4987 pw.print(", pkg="); 4988 pw.print(proxyPkg); 4989 pw.print(", attributionTag="); 4990 pw.print(proxyAttributionTag); 4991 pw.print("]"); 4992 } 4993 pw.println(); 4994 } 4995 } 4996 4997 final AttributedOp attributedOp = op.mAttributions.get(attributionTag); 4998 if (attributedOp.isRunning()) { 4999 long earliestElapsedTime = Long.MAX_VALUE; 5000 long maxNumStarts = 0; 5001 int numInProgressEvents = attributedOp.mInProgressEvents.size(); 5002 for (int i = 0; i < numInProgressEvents; i++) { 5003 AttributedOp.InProgressStartOpEvent event = 5004 attributedOp.mInProgressEvents.valueAt(i); 5005 5006 earliestElapsedTime = Math.min(earliestElapsedTime, event.getStartElapsedTime()); 5007 maxNumStarts = Math.max(maxNumStarts, event.mNumUnfinishedStarts); 5008 } 5009 5010 pw.print(prefix + "Running start at: "); 5011 TimeUtils.formatDuration(nowElapsed - earliestElapsedTime, pw); 5012 pw.println(); 5013 5014 if (maxNumStarts > 1) { 5015 pw.print(prefix + "startNesting="); 5016 pw.println(maxNumStarts); 5017 } 5018 } 5019 } 5020 5021 @NeverCompile // Avoid size overhead of debugging code. 5022 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)5023 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 5024 if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; 5025 5026 int dumpOp = OP_NONE; 5027 String dumpPackage = null; 5028 String dumpAttributionTag = null; 5029 int dumpUid = Process.INVALID_UID; 5030 int dumpMode = -1; 5031 boolean dumpWatchers = false; 5032 // TODO ntmyren: Remove the dumpHistory and dumpFilter 5033 boolean dumpHistory = false; 5034 boolean includeDiscreteOps = false; 5035 boolean dumpUidStateChangeLogs = false; 5036 int nDiscreteOps = 10; 5037 @HistoricalOpsRequestFilter int dumpFilter = 0; 5038 boolean dumpAll = false; 5039 5040 if (args != null) { 5041 for (int i = 0; i < args.length; i++) { 5042 String arg = args[i]; 5043 if ("-h".equals(arg)) { 5044 dumpHelp(pw); 5045 return; 5046 } else if ("-a".equals(arg)) { 5047 // dump all data 5048 dumpAll = true; 5049 } else if ("--op".equals(arg)) { 5050 i++; 5051 if (i >= args.length) { 5052 pw.println("No argument for --op option"); 5053 return; 5054 } 5055 dumpOp = Shell.strOpToOp(args[i], pw); 5056 dumpFilter |= FILTER_BY_OP_NAMES; 5057 if (dumpOp < 0) { 5058 return; 5059 } 5060 } else if ("--package".equals(arg)) { 5061 i++; 5062 if (i >= args.length) { 5063 pw.println("No argument for --package option"); 5064 return; 5065 } 5066 dumpPackage = args[i]; 5067 dumpFilter |= FILTER_BY_PACKAGE_NAME; 5068 try { 5069 dumpUid = AppGlobals.getPackageManager().getPackageUid(dumpPackage, 5070 PackageManager.MATCH_KNOWN_PACKAGES | PackageManager.MATCH_INSTANT, 5071 0); 5072 } catch (RemoteException e) { 5073 } 5074 if (dumpUid < 0) { 5075 pw.println("Unknown package: " + dumpPackage); 5076 return; 5077 } 5078 dumpUid = UserHandle.getAppId(dumpUid); 5079 dumpFilter |= FILTER_BY_UID; 5080 } else if ("--attributionTag".equals(arg)) { 5081 i++; 5082 if (i >= args.length) { 5083 pw.println("No argument for --attributionTag option"); 5084 return; 5085 } 5086 dumpAttributionTag = args[i]; 5087 dumpFilter |= FILTER_BY_ATTRIBUTION_TAG; 5088 } else if ("--mode".equals(arg)) { 5089 i++; 5090 if (i >= args.length) { 5091 pw.println("No argument for --mode option"); 5092 return; 5093 } 5094 dumpMode = Shell.strModeToMode(args[i], pw); 5095 if (dumpMode < 0) { 5096 return; 5097 } 5098 } else if ("--watchers".equals(arg)) { 5099 dumpWatchers = true; 5100 } else if ("--include-discrete".equals(arg)) { 5101 i++; 5102 if (i >= args.length) { 5103 pw.println("No argument for --include-discrete option"); 5104 return; 5105 } 5106 try { 5107 nDiscreteOps = Integer.valueOf(args[i]); 5108 } catch (NumberFormatException e) { 5109 pw.println("Wrong parameter: " + args[i]); 5110 return; 5111 } 5112 includeDiscreteOps = true; 5113 } else if ("--history".equals(arg)) { 5114 dumpHistory = true; 5115 } else if (arg.length() > 0 && arg.charAt(0) == '-') { 5116 pw.println("Unknown option: " + arg); 5117 return; 5118 } else if ("--uid-state-changes".equals(arg)) { 5119 dumpUidStateChangeLogs = true; 5120 } else { 5121 pw.println("Unknown command: " + arg); 5122 return; 5123 } 5124 } 5125 } 5126 5127 final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 5128 final Date date = new Date(); 5129 synchronized (this) { 5130 pw.println("Current AppOps Service state:"); 5131 if (!dumpHistory && !dumpWatchers) { 5132 mConstants.dump(pw); 5133 } 5134 pw.println(); 5135 final long now = System.currentTimeMillis(); 5136 final long nowElapsed = SystemClock.elapsedRealtime(); 5137 final long nowUptime = SystemClock.uptimeMillis(); 5138 boolean needSep = false; 5139 if (dumpFilter == 0 && dumpMode < 0 && mProfileOwners != null && !dumpWatchers 5140 && !dumpHistory) { 5141 pw.println(" Profile owners:"); 5142 for (int poi = 0; poi < mProfileOwners.size(); poi++) { 5143 pw.print(" User #"); 5144 pw.print(mProfileOwners.keyAt(poi)); 5145 pw.print(": "); 5146 UserHandle.formatUid(pw, mProfileOwners.valueAt(poi)); 5147 pw.println(); 5148 } 5149 pw.println(); 5150 } 5151 5152 if (!dumpHistory) { 5153 needSep |= mAppOpsCheckingService.dumpListeners(dumpOp, dumpUid, dumpPackage, pw); 5154 } 5155 5156 if (mModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) { 5157 boolean printedHeader = false; 5158 for (int i = 0; i < mModeWatchers.size(); i++) { 5159 final ModeCallback cb = mModeWatchers.valueAt(i); 5160 if (dumpPackage != null 5161 && dumpUid != UserHandle.getAppId(cb.getWatchingUid())) { 5162 continue; 5163 } 5164 needSep = true; 5165 if (!printedHeader) { 5166 pw.println(" All op mode watchers:"); 5167 printedHeader = true; 5168 } 5169 pw.print(" "); 5170 pw.print(Integer.toHexString(System.identityHashCode(mModeWatchers.keyAt(i)))); 5171 pw.print(": "); pw.println(cb); 5172 } 5173 } 5174 if (mActiveWatchers.size() > 0 && dumpMode < 0) { 5175 needSep = true; 5176 boolean printedHeader = false; 5177 for (int watcherNum = 0; watcherNum < mActiveWatchers.size(); watcherNum++) { 5178 final SparseArray<ActiveCallback> activeWatchers = 5179 mActiveWatchers.valueAt(watcherNum); 5180 if (activeWatchers.size() <= 0) { 5181 continue; 5182 } 5183 final ActiveCallback cb = activeWatchers.valueAt(0); 5184 if (dumpOp >= 0 && activeWatchers.indexOfKey(dumpOp) < 0) { 5185 continue; 5186 } 5187 if (dumpPackage != null 5188 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 5189 continue; 5190 } 5191 if (!printedHeader) { 5192 pw.println(" All op active watchers:"); 5193 printedHeader = true; 5194 } 5195 pw.print(" "); 5196 pw.print(Integer.toHexString(System.identityHashCode( 5197 mActiveWatchers.keyAt(watcherNum)))); 5198 pw.println(" ->"); 5199 pw.print(" ["); 5200 final int opCount = activeWatchers.size(); 5201 for (int opNum = 0; opNum < opCount; opNum++) { 5202 if (opNum > 0) { 5203 pw.print(' '); 5204 } 5205 pw.print(AppOpsManager.opToName(activeWatchers.keyAt(opNum))); 5206 if (opNum < opCount - 1) { 5207 pw.print(','); 5208 } 5209 } 5210 pw.println("]"); 5211 pw.print(" "); 5212 pw.println(cb); 5213 } 5214 } 5215 if (mStartedWatchers.size() > 0 && dumpMode < 0) { 5216 needSep = true; 5217 boolean printedHeader = false; 5218 5219 final int watchersSize = mStartedWatchers.size(); 5220 for (int watcherNum = 0; watcherNum < watchersSize; watcherNum++) { 5221 final SparseArray<StartedCallback> startedWatchers = 5222 mStartedWatchers.valueAt(watcherNum); 5223 if (startedWatchers.size() <= 0) { 5224 continue; 5225 } 5226 5227 final StartedCallback cb = startedWatchers.valueAt(0); 5228 if (dumpOp >= 0 && startedWatchers.indexOfKey(dumpOp) < 0) { 5229 continue; 5230 } 5231 5232 if (dumpPackage != null 5233 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 5234 continue; 5235 } 5236 5237 if (!printedHeader) { 5238 pw.println(" All op started watchers:"); 5239 printedHeader = true; 5240 } 5241 5242 pw.print(" "); 5243 pw.print(Integer.toHexString(System.identityHashCode( 5244 mStartedWatchers.keyAt(watcherNum)))); 5245 pw.println(" ->"); 5246 5247 pw.print(" ["); 5248 final int opCount = startedWatchers.size(); 5249 for (int opNum = 0; opNum < opCount; opNum++) { 5250 if (opNum > 0) { 5251 pw.print(' '); 5252 } 5253 5254 pw.print(AppOpsManager.opToName(startedWatchers.keyAt(opNum))); 5255 if (opNum < opCount - 1) { 5256 pw.print(','); 5257 } 5258 } 5259 pw.println("]"); 5260 5261 pw.print(" "); 5262 pw.println(cb); 5263 } 5264 } 5265 if (mNotedWatchers.size() > 0 && dumpMode < 0) { 5266 needSep = true; 5267 boolean printedHeader = false; 5268 for (int watcherNum = 0; watcherNum < mNotedWatchers.size(); watcherNum++) { 5269 final SparseArray<NotedCallback> notedWatchers = 5270 mNotedWatchers.valueAt(watcherNum); 5271 if (notedWatchers.size() <= 0) { 5272 continue; 5273 } 5274 final NotedCallback cb = notedWatchers.valueAt(0); 5275 if (dumpOp >= 0 && notedWatchers.indexOfKey(dumpOp) < 0) { 5276 continue; 5277 } 5278 if (dumpPackage != null 5279 && dumpUid != UserHandle.getAppId(cb.mWatchingUid)) { 5280 continue; 5281 } 5282 if (!printedHeader) { 5283 pw.println(" All op noted watchers:"); 5284 printedHeader = true; 5285 } 5286 pw.print(" "); 5287 pw.print(Integer.toHexString(System.identityHashCode( 5288 mNotedWatchers.keyAt(watcherNum)))); 5289 pw.println(" ->"); 5290 pw.print(" ["); 5291 final int opCount = notedWatchers.size(); 5292 for (int opNum = 0; opNum < opCount; opNum++) { 5293 if (opNum > 0) { 5294 pw.print(' '); 5295 } 5296 pw.print(AppOpsManager.opToName(notedWatchers.keyAt(opNum))); 5297 if (opNum < opCount - 1) { 5298 pw.print(','); 5299 } 5300 } 5301 pw.println("]"); 5302 pw.print(" "); 5303 pw.println(cb); 5304 } 5305 } 5306 if (mAudioRestrictionManager.hasActiveRestrictions() && dumpOp < 0 5307 && dumpPackage != null && dumpMode < 0 && !dumpWatchers) { 5308 needSep = mAudioRestrictionManager.dump(pw) || needSep; 5309 } 5310 if (needSep) { 5311 pw.println(); 5312 } 5313 for (int i=0; i<mUidStates.size(); i++) { 5314 UidState uidState = mUidStates.valueAt(i); 5315 final SparseIntArray opModes = uidState.getNonDefaultUidModes(); 5316 final ArrayMap<String, Ops> pkgOps = uidState.pkgOps; 5317 5318 if (dumpWatchers || dumpHistory) { 5319 continue; 5320 } 5321 if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) { 5322 boolean hasOp = dumpOp < 0 || (opModes != null 5323 && opModes.indexOfKey(dumpOp) >= 0); 5324 boolean hasPackage = dumpPackage == null || dumpUid == mUidStates.keyAt(i); 5325 boolean hasMode = dumpMode < 0; 5326 if (!hasMode && opModes != null) { 5327 for (int opi = 0; !hasMode && opi < opModes.size(); opi++) { 5328 if (opModes.valueAt(opi) == dumpMode) { 5329 hasMode = true; 5330 } 5331 } 5332 } 5333 if (pkgOps != null) { 5334 for (int pkgi = 0; 5335 (!hasOp || !hasPackage || !hasMode) && pkgi < pkgOps.size(); 5336 pkgi++) { 5337 Ops ops = pkgOps.valueAt(pkgi); 5338 if (!hasOp && ops != null && ops.indexOfKey(dumpOp) >= 0) { 5339 hasOp = true; 5340 } 5341 if (!hasMode) { 5342 for (int opi = 0; !hasMode && opi < ops.size(); opi++) { 5343 if (ops.valueAt(opi).getMode() == dumpMode) { 5344 hasMode = true; 5345 } 5346 } 5347 } 5348 if (!hasPackage && dumpPackage.equals(ops.packageName)) { 5349 hasPackage = true; 5350 } 5351 } 5352 } 5353 if (uidState.foregroundOps != null && !hasOp) { 5354 if (uidState.foregroundOps.indexOfKey(dumpOp) > 0) { 5355 hasOp = true; 5356 } 5357 } 5358 if (!hasOp || !hasPackage || !hasMode) { 5359 continue; 5360 } 5361 } 5362 5363 pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":"); 5364 uidState.dump(pw, nowElapsed); 5365 if (uidState.foregroundOps != null && (dumpMode < 0 5366 || dumpMode == AppOpsManager.MODE_FOREGROUND)) { 5367 pw.println(" foregroundOps:"); 5368 for (int j = 0; j < uidState.foregroundOps.size(); j++) { 5369 if (dumpOp >= 0 && dumpOp != uidState.foregroundOps.keyAt(j)) { 5370 continue; 5371 } 5372 pw.print(" "); 5373 pw.print(AppOpsManager.opToName(uidState.foregroundOps.keyAt(j))); 5374 pw.print(": "); 5375 pw.println(uidState.foregroundOps.valueAt(j) ? "WATCHER" : "SILENT"); 5376 } 5377 pw.print(" hasForegroundWatchers="); 5378 pw.println(uidState.hasForegroundWatchers); 5379 } 5380 needSep = true; 5381 5382 if (opModes != null) { 5383 final int opModeCount = opModes.size(); 5384 for (int j = 0; j < opModeCount; j++) { 5385 final int code = opModes.keyAt(j); 5386 final int mode = opModes.valueAt(j); 5387 if (dumpOp >= 0 && dumpOp != code) { 5388 continue; 5389 } 5390 if (dumpMode >= 0 && dumpMode != mode) { 5391 continue; 5392 } 5393 pw.print(" "); pw.print(AppOpsManager.opToName(code)); 5394 pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode)); 5395 } 5396 } 5397 5398 if (pkgOps == null) { 5399 continue; 5400 } 5401 5402 for (int pkgi = 0; pkgi < pkgOps.size(); pkgi++) { 5403 final Ops ops = pkgOps.valueAt(pkgi); 5404 if (dumpPackage != null && !dumpPackage.equals(ops.packageName)) { 5405 continue; 5406 } 5407 boolean printedPackage = false; 5408 for (int j=0; j<ops.size(); j++) { 5409 final Op op = ops.valueAt(j); 5410 final int opCode = op.op; 5411 if (dumpOp >= 0 && dumpOp != opCode) { 5412 continue; 5413 } 5414 if (dumpMode >= 0 && dumpMode != op.getMode()) { 5415 continue; 5416 } 5417 if (!printedPackage) { 5418 pw.print(" Package "); pw.print(ops.packageName); pw.println(":"); 5419 printedPackage = true; 5420 } 5421 pw.print(" "); pw.print(AppOpsManager.opToName(opCode)); 5422 pw.print(" ("); pw.print(AppOpsManager.modeToName(op.getMode())); 5423 final int switchOp = AppOpsManager.opToSwitch(opCode); 5424 if (switchOp != opCode) { 5425 pw.print(" / switch "); 5426 pw.print(AppOpsManager.opToName(switchOp)); 5427 final Op switchObj = ops.get(switchOp); 5428 int mode = switchObj == null 5429 ? AppOpsManager.opToDefaultMode(switchOp) : switchObj.getMode(); 5430 pw.print("="); pw.print(AppOpsManager.modeToName(mode)); 5431 } 5432 pw.println("): "); 5433 dumpStatesLocked(pw, dumpAttributionTag, dumpFilter, nowElapsed, op, now, 5434 sdf, date, " "); 5435 } 5436 } 5437 } 5438 if (needSep) { 5439 pw.println(); 5440 } 5441 5442 boolean showUserRestrictions = !(dumpMode < 0 && !dumpWatchers && !dumpHistory); 5443 mAppOpsRestrictions.dumpRestrictions(pw, dumpOp, dumpPackage, showUserRestrictions); 5444 5445 if (!dumpHistory && !dumpWatchers) { 5446 pw.println(); 5447 if (mCheckOpsDelegateDispatcher.mPolicy != null 5448 && mCheckOpsDelegateDispatcher.mPolicy instanceof AppOpsPolicy) { 5449 AppOpsPolicy policy = (AppOpsPolicy) mCheckOpsDelegateDispatcher.mPolicy; 5450 policy.dumpTags(pw); 5451 } else { 5452 pw.println(" AppOps policy not set."); 5453 } 5454 } 5455 5456 if (dumpAll || dumpUidStateChangeLogs) { 5457 pw.println(); 5458 pw.println("Uid State Changes Event Log:"); 5459 getUidStateTracker().dumpEvents(pw); 5460 } 5461 } 5462 5463 // Must not hold the appops lock 5464 if (dumpHistory && !dumpWatchers) { 5465 mHistoricalRegistry.dump(" ", pw, dumpUid, dumpPackage, dumpAttributionTag, dumpOp, 5466 dumpFilter); 5467 } 5468 if (includeDiscreteOps) { 5469 pw.println("Discrete accesses: "); 5470 mHistoricalRegistry.dumpDiscreteData(pw, dumpUid, dumpPackage, dumpAttributionTag, 5471 dumpFilter, dumpOp, sdf, date, " ", nDiscreteOps); 5472 } 5473 } 5474 5475 @Override 5476 public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) { 5477 checkSystemUid("setUserRestrictions"); 5478 Objects.requireNonNull(restrictions); 5479 Objects.requireNonNull(token); 5480 for (int i = 0; i < AppOpsManager._NUM_OP; i++) { 5481 String restriction = AppOpsManager.opToRestriction(i); 5482 if (restriction != null) { 5483 setUserRestrictionNoCheck(i, restrictions.getBoolean(restriction, false), token, 5484 userHandle, null); 5485 } 5486 } 5487 } 5488 5489 @Override 5490 public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, 5491 PackageTagsList excludedPackageTags) { 5492 if (Binder.getCallingPid() != Process.myPid()) { 5493 mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS, 5494 Binder.getCallingPid(), Binder.getCallingUid(), null); 5495 } 5496 if (userHandle != UserHandle.getCallingUserId()) { 5497 if (mContext.checkCallingOrSelfPermission(Manifest.permission 5498 .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED 5499 && mContext.checkCallingOrSelfPermission(Manifest.permission 5500 .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) { 5501 throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or" 5502 + " INTERACT_ACROSS_USERS to interact cross user "); 5503 } 5504 } 5505 verifyIncomingOp(code); 5506 Objects.requireNonNull(token); 5507 setUserRestrictionNoCheck(code, restricted, token, userHandle, excludedPackageTags); 5508 } 5509 5510 private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token, 5511 int userHandle, PackageTagsList excludedPackageTags) { 5512 synchronized (AppOpsService.this) { 5513 ClientUserRestrictionState restrictionState = mOpUserRestrictions.get(token); 5514 5515 if (restrictionState == null) { 5516 try { 5517 restrictionState = new ClientUserRestrictionState(token); 5518 } catch (RemoteException e) { 5519 return; 5520 } 5521 mOpUserRestrictions.put(token, restrictionState); 5522 } 5523 5524 if (restrictionState.setRestriction(code, restricted, excludedPackageTags, 5525 userHandle)) { 5526 mHandler.sendMessage(PooledLambda.obtainMessage( 5527 AppOpsService::notifyWatchersOfChange, this, code, UID_ANY)); 5528 mHandler.sendMessage(PooledLambda.obtainMessage( 5529 AppOpsService::updateStartedOpModeForUser, this, code, restricted, 5530 userHandle)); 5531 } 5532 5533 if (restrictionState.isDefault()) { 5534 mOpUserRestrictions.remove(token); 5535 restrictionState.destroy(); 5536 } 5537 } 5538 } 5539 5540 private void updateStartedOpModeForUser(int code, boolean restricted, int userId) { 5541 synchronized (AppOpsService.this) { 5542 int numUids = mUidStates.size(); 5543 for (int uidNum = 0; uidNum < numUids; uidNum++) { 5544 int uid = mUidStates.keyAt(uidNum); 5545 if (userId != UserHandle.USER_ALL && UserHandle.getUserId(uid) != userId) { 5546 continue; 5547 } 5548 updateStartedOpModeForUidLocked(code, restricted, uid); 5549 } 5550 } 5551 } 5552 5553 private void updateStartedOpModeForUidLocked(int code, boolean restricted, int uid) { 5554 UidState uidState = mUidStates.get(uid); 5555 if (uidState == null) { 5556 return; 5557 } 5558 5559 int numPkgOps = uidState.pkgOps.size(); 5560 for (int pkgNum = 0; pkgNum < numPkgOps; pkgNum++) { 5561 Ops ops = uidState.pkgOps.valueAt(pkgNum); 5562 Op op = ops != null ? ops.get(code) : null; 5563 if (op == null || (op.getMode() != MODE_ALLOWED && op.getMode() != MODE_FOREGROUND)) { 5564 continue; 5565 } 5566 int numAttrTags = op.mAttributions.size(); 5567 for (int attrNum = 0; attrNum < numAttrTags; attrNum++) { 5568 AttributedOp attrOp = op.mAttributions.valueAt(attrNum); 5569 if (restricted && attrOp.isRunning()) { 5570 attrOp.pause(); 5571 } else if (attrOp.isPaused()) { 5572 attrOp.resume(); 5573 } 5574 } 5575 } 5576 } 5577 5578 private void notifyWatchersOfChange(int code, int uid) { 5579 final ArraySet<OnOpModeChangedListener> modeChangedListenerSet; 5580 synchronized (this) { 5581 modeChangedListenerSet = mAppOpsCheckingService.getOpModeChangedListeners(code); 5582 if (modeChangedListenerSet == null) { 5583 return; 5584 } 5585 } 5586 5587 notifyOpChanged(modeChangedListenerSet, code, uid, null); 5588 } 5589 5590 @Override 5591 public void removeUser(int userHandle) throws RemoteException { 5592 checkSystemUid("removeUser"); 5593 synchronized (AppOpsService.this) { 5594 final int tokenCount = mOpUserRestrictions.size(); 5595 for (int i = tokenCount - 1; i >= 0; i--) { 5596 ClientUserRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i); 5597 opRestrictions.removeUser(userHandle); 5598 } 5599 removeUidsForUserLocked(userHandle); 5600 } 5601 } 5602 5603 @Override 5604 public boolean isOperationActive(int code, int uid, String packageName) { 5605 if (Binder.getCallingUid() != uid) { 5606 if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) 5607 != PackageManager.PERMISSION_GRANTED) { 5608 return false; 5609 } 5610 } 5611 verifyIncomingOp(code); 5612 if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) { 5613 return false; 5614 } 5615 5616 final String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); 5617 if (resolvedPackageName == null) { 5618 return false; 5619 } 5620 // TODO moltmann: Allow to check for attribution op activeness 5621 synchronized (AppOpsService.this) { 5622 Ops pkgOps = getOpsLocked(uid, resolvedPackageName, null, false, null, false); 5623 if (pkgOps == null) { 5624 return false; 5625 } 5626 5627 Op op = pkgOps.get(code); 5628 if (op == null) { 5629 return false; 5630 } 5631 5632 return op.isRunning(); 5633 } 5634 } 5635 5636 @Override 5637 public boolean isProxying(int op, @NonNull String proxyPackageName, 5638 @NonNull String proxyAttributionTag, int proxiedUid, 5639 @NonNull String proxiedPackageName) { 5640 Objects.requireNonNull(proxyPackageName); 5641 Objects.requireNonNull(proxiedPackageName); 5642 final long callingUid = Binder.getCallingUid(); 5643 final long identity = Binder.clearCallingIdentity(); 5644 try { 5645 final List<AppOpsManager.PackageOps> packageOps = getOpsForPackage(proxiedUid, 5646 proxiedPackageName, new int[] {op}); 5647 if (packageOps == null || packageOps.isEmpty()) { 5648 return false; 5649 } 5650 final List<OpEntry> opEntries = packageOps.get(0).getOps(); 5651 if (opEntries.isEmpty()) { 5652 return false; 5653 } 5654 final OpEntry opEntry = opEntries.get(0); 5655 if (!opEntry.isRunning()) { 5656 return false; 5657 } 5658 final OpEventProxyInfo proxyInfo = opEntry.getLastProxyInfo( 5659 OP_FLAG_TRUSTED_PROXIED | AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED); 5660 return proxyInfo != null && callingUid == proxyInfo.getUid() 5661 && proxyPackageName.equals(proxyInfo.getPackageName()) 5662 && Objects.equals(proxyAttributionTag, proxyInfo.getAttributionTag()); 5663 } finally { 5664 Binder.restoreCallingIdentity(identity); 5665 } 5666 } 5667 5668 @Override 5669 public void resetPackageOpsNoHistory(@NonNull String packageName) { 5670 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 5671 "resetPackageOpsNoHistory"); 5672 synchronized (AppOpsService.this) { 5673 final int uid = mPackageManagerInternal.getPackageUid(packageName, 0, 5674 UserHandle.getCallingUserId()); 5675 if (uid == Process.INVALID_UID) { 5676 return; 5677 } 5678 UidState uidState = mUidStates.get(uid); 5679 if (uidState == null) { 5680 return; 5681 } 5682 Ops removedOps = uidState.pkgOps.remove(packageName); 5683 mAppOpsCheckingService.removePackage(packageName, UserHandle.getUserId(uid)); 5684 if (removedOps != null) { 5685 scheduleFastWriteLocked(); 5686 } 5687 } 5688 } 5689 5690 @Override 5691 public void setHistoryParameters(@AppOpsManager.HistoricalMode int mode, 5692 long baseSnapshotInterval, int compressionStep) { 5693 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 5694 "setHistoryParameters"); 5695 // Must not hold the appops lock 5696 mHistoricalRegistry.setHistoryParameters(mode, baseSnapshotInterval, compressionStep); 5697 } 5698 5699 @Override 5700 public void offsetHistory(long offsetMillis) { 5701 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 5702 "offsetHistory"); 5703 // Must not hold the appops lock 5704 mHistoricalRegistry.offsetHistory(offsetMillis); 5705 mHistoricalRegistry.offsetDiscreteHistory(offsetMillis); 5706 } 5707 5708 @Override 5709 public void addHistoricalOps(HistoricalOps ops) { 5710 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 5711 "addHistoricalOps"); 5712 // Must not hold the appops lock 5713 mHistoricalRegistry.addHistoricalOps(ops); 5714 } 5715 5716 @Override 5717 public void resetHistoryParameters() { 5718 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 5719 "resetHistoryParameters"); 5720 // Must not hold the appops lock 5721 mHistoricalRegistry.resetHistoryParameters(); 5722 } 5723 5724 @Override 5725 public void clearHistory() { 5726 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 5727 "clearHistory"); 5728 // Must not hold the appops lock 5729 mHistoricalRegistry.clearAllHistory(); 5730 } 5731 5732 @Override 5733 public void rebootHistory(long offlineDurationMillis) { 5734 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS, 5735 "rebootHistory"); 5736 5737 Preconditions.checkArgument(offlineDurationMillis >= 0); 5738 5739 // Must not hold the appops lock 5740 mHistoricalRegistry.shutdown(); 5741 5742 if (offlineDurationMillis > 0) { 5743 SystemClock.sleep(offlineDurationMillis); 5744 } 5745 5746 mHistoricalRegistry = new HistoricalRegistry(mHistoricalRegistry); 5747 mHistoricalRegistry.systemReady(mContext.getContentResolver()); 5748 mHistoricalRegistry.persistPendingHistory(); 5749 } 5750 5751 /** 5752 * Report runtime access to AppOp together with message (including stack trace) 5753 * 5754 * @param packageName The package which reported the op 5755 * @param notedAppOp contains code of op and attributionTag provided by developer 5756 * @param message Message describing AppOp access (can be stack trace) 5757 * 5758 * @return Config for future sampling to reduce amount of reporting 5759 */ 5760 @Override 5761 public MessageSamplingConfig reportRuntimeAppOpAccessMessageAndGetConfig( 5762 String packageName, SyncNotedAppOp notedAppOp, String message) { 5763 int uid = Binder.getCallingUid(); 5764 Objects.requireNonNull(packageName); 5765 synchronized (this) { 5766 switchPackageIfBootTimeOrRarelyUsedLocked(packageName); 5767 if (!packageName.equals(mSampledPackage)) { 5768 return new MessageSamplingConfig(OP_NONE, 0, 5769 Instant.now().plus(1, ChronoUnit.HOURS).toEpochMilli()); 5770 } 5771 5772 Objects.requireNonNull(notedAppOp); 5773 Objects.requireNonNull(message); 5774 5775 reportRuntimeAppOpAccessMessageInternalLocked(uid, packageName, 5776 AppOpsManager.strOpToOp(notedAppOp.getOp()), 5777 notedAppOp.getAttributionTag(), message); 5778 5779 return new MessageSamplingConfig(mSampledAppOpCode, mAcceptableLeftDistance, 5780 Instant.now().plus(1, ChronoUnit.HOURS).toEpochMilli()); 5781 } 5782 } 5783 5784 /** 5785 * Report runtime access to AppOp together with message (entry point for reporting 5786 * asynchronous access) 5787 * @param uid Uid of the package which reported the op 5788 * @param packageName The package which reported the op 5789 * @param opCode Code of AppOp 5790 * @param attributionTag FeautreId of AppOp reported 5791 * @param message Message describing AppOp access (can be stack trace) 5792 */ 5793 private void reportRuntimeAppOpAccessMessageAsyncLocked(int uid, 5794 @NonNull String packageName, int opCode, @Nullable String attributionTag, 5795 @NonNull String message) { 5796 switchPackageIfBootTimeOrRarelyUsedLocked(packageName); 5797 if (!Objects.equals(mSampledPackage, packageName)) { 5798 return; 5799 } 5800 reportRuntimeAppOpAccessMessageInternalLocked(uid, packageName, opCode, attributionTag, 5801 message); 5802 } 5803 5804 /** 5805 * Decides whether reported message is within the range of watched AppOps and picks it for 5806 * reporting uniformly at random across all received messages. 5807 */ 5808 private void reportRuntimeAppOpAccessMessageInternalLocked(int uid, 5809 @NonNull String packageName, int opCode, @Nullable String attributionTag, 5810 @NonNull String message) { 5811 int newLeftDistance = AppOpsManager.leftCircularDistance(opCode, 5812 mSampledAppOpCode, _NUM_OP); 5813 5814 if (mAcceptableLeftDistance < newLeftDistance 5815 && mSamplingStrategy != SAMPLING_STRATEGY_UNIFORM_OPS) { 5816 return; 5817 } 5818 5819 if (mAcceptableLeftDistance > newLeftDistance 5820 && mSamplingStrategy != SAMPLING_STRATEGY_UNIFORM_OPS) { 5821 mAcceptableLeftDistance = newLeftDistance; 5822 mMessagesCollectedCount = 0.0f; 5823 } 5824 5825 mMessagesCollectedCount += 1.0f; 5826 if (ThreadLocalRandom.current().nextFloat() <= 1.0f / mMessagesCollectedCount) { 5827 mCollectedRuntimePermissionMessage = new RuntimeAppOpAccessMessage(uid, opCode, 5828 packageName, attributionTag, message, mSamplingStrategy); 5829 } 5830 return; 5831 } 5832 5833 /** Pulls current AppOps access report and resamples package and app op to watch */ 5834 @Override 5835 public @Nullable RuntimeAppOpAccessMessage collectRuntimeAppOpAccessMessage() { 5836 ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class); 5837 boolean isCallerInstrumented = 5838 ami.getInstrumentationSourceUid(Binder.getCallingUid()) != Process.INVALID_UID; 5839 boolean isCallerSystem = Binder.getCallingPid() == Process.myPid(); 5840 if (!isCallerSystem && !isCallerInstrumented) { 5841 return null; 5842 } 5843 mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 5844 Binder.getCallingPid(), Binder.getCallingUid(), null); 5845 RuntimeAppOpAccessMessage result; 5846 synchronized (this) { 5847 result = mCollectedRuntimePermissionMessage; 5848 mCollectedRuntimePermissionMessage = null; 5849 } 5850 mHandler.sendMessage(PooledLambda.obtainMessage( 5851 AppOpsService::getPackageListAndResample, 5852 this)); 5853 return result; 5854 } 5855 5856 /** 5857 * Checks if package is in the list of rarely used package and starts watching the new package 5858 * to collect incoming message or if collection is happening in first minutes since boot. 5859 * @param packageName 5860 */ 5861 private void switchPackageIfBootTimeOrRarelyUsedLocked(@NonNull String packageName) { 5862 if (mSampledPackage == null) { 5863 if (ThreadLocalRandom.current().nextFloat() < 0.5f) { 5864 mSamplingStrategy = SAMPLING_STRATEGY_BOOT_TIME_SAMPLING; 5865 resampleAppOpForPackageLocked(packageName, true); 5866 } 5867 } else if (mRarelyUsedPackages.contains(packageName)) { 5868 mRarelyUsedPackages.remove(packageName); 5869 if (ThreadLocalRandom.current().nextFloat() < 0.5f) { 5870 mSamplingStrategy = SAMPLING_STRATEGY_RARELY_USED; 5871 resampleAppOpForPackageLocked(packageName, true); 5872 } 5873 } 5874 } 5875 5876 /** Obtains package list and resamples package and appop to watch. */ 5877 private List<String> getPackageListAndResample() { 5878 List<String> packageNames = getPackageNamesForSampling(); 5879 synchronized (this) { 5880 resamplePackageAndAppOpLocked(packageNames); 5881 } 5882 return packageNames; 5883 } 5884 5885 /** Resamples package and appop to watch from the list provided. */ 5886 private void resamplePackageAndAppOpLocked(@NonNull List<String> packageNames) { 5887 if (!packageNames.isEmpty()) { 5888 if (ThreadLocalRandom.current().nextFloat() < 0.5f) { 5889 mSamplingStrategy = SAMPLING_STRATEGY_UNIFORM; 5890 resampleAppOpForPackageLocked(packageNames.get( 5891 ThreadLocalRandom.current().nextInt(packageNames.size())), true); 5892 } else { 5893 mSamplingStrategy = SAMPLING_STRATEGY_UNIFORM_OPS; 5894 resampleAppOpForPackageLocked(packageNames.get( 5895 ThreadLocalRandom.current().nextInt(packageNames.size())), false); 5896 } 5897 } 5898 } 5899 5900 /** Resamples appop for the chosen package and initializes sampling state */ 5901 private void resampleAppOpForPackageLocked(@NonNull String packageName, boolean pickOp) { 5902 mMessagesCollectedCount = 0.0f; 5903 mSampledAppOpCode = pickOp ? ThreadLocalRandom.current().nextInt(_NUM_OP) : OP_NONE; 5904 mAcceptableLeftDistance = _NUM_OP - 1; 5905 mSampledPackage = packageName; 5906 } 5907 5908 /** 5909 * Creates list of rarely used packages - packages which were not used over last week or 5910 * which declared but did not use permissions over last week. 5911 * */ 5912 private void initializeRarelyUsedPackagesList(@NonNull ArraySet<String> candidates) { 5913 AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); 5914 List<String> runtimeAppOpsList = getRuntimeAppOpsList(); 5915 AppOpsManager.HistoricalOpsRequest histOpsRequest = 5916 new AppOpsManager.HistoricalOpsRequest.Builder( 5917 Math.max(Instant.now().minus(7, ChronoUnit.DAYS).toEpochMilli(), 0), 5918 Long.MAX_VALUE).setOpNames(runtimeAppOpsList).setFlags( 5919 OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED).build(); 5920 appOps.getHistoricalOps(histOpsRequest, AsyncTask.THREAD_POOL_EXECUTOR, 5921 new Consumer<HistoricalOps>() { 5922 @Override 5923 public void accept(HistoricalOps histOps) { 5924 int uidCount = histOps.getUidCount(); 5925 for (int uidIdx = 0; uidIdx < uidCount; uidIdx++) { 5926 final AppOpsManager.HistoricalUidOps uidOps = histOps.getUidOpsAt( 5927 uidIdx); 5928 int pkgCount = uidOps.getPackageCount(); 5929 for (int pkgIdx = 0; pkgIdx < pkgCount; pkgIdx++) { 5930 String packageName = uidOps.getPackageOpsAt( 5931 pkgIdx).getPackageName(); 5932 if (!candidates.contains(packageName)) { 5933 continue; 5934 } 5935 AppOpsManager.HistoricalPackageOps packageOps = 5936 uidOps.getPackageOpsAt(pkgIdx); 5937 if (packageOps.getOpCount() != 0) { 5938 candidates.remove(packageName); 5939 } 5940 } 5941 } 5942 synchronized (this) { 5943 int numPkgs = mRarelyUsedPackages.size(); 5944 for (int i = 0; i < numPkgs; i++) { 5945 candidates.add(mRarelyUsedPackages.valueAt(i)); 5946 } 5947 mRarelyUsedPackages = candidates; 5948 } 5949 } 5950 }); 5951 } 5952 5953 /** List of app ops related to runtime permissions */ 5954 private List<String> getRuntimeAppOpsList() { 5955 ArrayList<String> result = new ArrayList(); 5956 for (int i = 0; i < _NUM_OP; i++) { 5957 if (shouldCollectNotes(i)) { 5958 result.add(opToPublicName(i)); 5959 } 5960 } 5961 return result; 5962 } 5963 5964 /** Returns list of packages to be used for package sampling */ 5965 private @NonNull List<String> getPackageNamesForSampling() { 5966 List<String> packageNames = new ArrayList<>(); 5967 PackageManagerInternal packageManagerInternal = LocalServices.getService( 5968 PackageManagerInternal.class); 5969 PackageList packages = packageManagerInternal.getPackageList(); 5970 for (String packageName : packages.getPackageNames()) { 5971 PackageInfo pkg = packageManagerInternal.getPackageInfo(packageName, 5972 PackageManager.GET_PERMISSIONS, Process.myUid(), mContext.getUserId()); 5973 if (isSamplingTarget(pkg)) { 5974 packageNames.add(pkg.packageName); 5975 } 5976 } 5977 return packageNames; 5978 } 5979 5980 /** Checks whether package should be included in sampling pool */ 5981 private boolean isSamplingTarget(@Nullable PackageInfo pkg) { 5982 if (pkg == null) { 5983 return false; 5984 } 5985 String[] requestedPermissions = pkg.requestedPermissions; 5986 if (requestedPermissions == null) { 5987 return false; 5988 } 5989 for (String permission : requestedPermissions) { 5990 PermissionInfo permissionInfo; 5991 try { 5992 permissionInfo = mContext.getPackageManager().getPermissionInfo(permission, 0); 5993 } catch (PackageManager.NameNotFoundException ignored) { 5994 continue; 5995 } 5996 if (permissionInfo.getProtection() == PROTECTION_DANGEROUS) { 5997 return true; 5998 } 5999 } 6000 return false; 6001 } 6002 6003 @GuardedBy("this") 6004 private void removeUidsForUserLocked(int userHandle) { 6005 for (int i = mUidStates.size() - 1; i >= 0; --i) { 6006 final int uid = mUidStates.keyAt(i); 6007 if (UserHandle.getUserId(uid) == userHandle) { 6008 mUidStates.valueAt(i).clear(); 6009 mUidStates.removeAt(i); 6010 } 6011 } 6012 } 6013 6014 private void checkSystemUid(String function) { 6015 int uid = Binder.getCallingUid(); 6016 if (uid != Process.SYSTEM_UID) { 6017 throw new SecurityException(function + " must by called by the system"); 6018 } 6019 } 6020 6021 private static int resolveUid(String packageName) { 6022 if (packageName == null) { 6023 return Process.INVALID_UID; 6024 } 6025 switch (packageName) { 6026 case "root": 6027 return Process.ROOT_UID; 6028 case "shell": 6029 case "dumpstate": 6030 return Process.SHELL_UID; 6031 case "media": 6032 return Process.MEDIA_UID; 6033 case "audioserver": 6034 return Process.AUDIOSERVER_UID; 6035 case "cameraserver": 6036 return Process.CAMERASERVER_UID; 6037 } 6038 return Process.INVALID_UID; 6039 } 6040 6041 private static String[] getPackagesForUid(int uid) { 6042 String[] packageNames = null; 6043 6044 // Very early during boot the package manager is not yet or not yet fully started. At this 6045 // time there are no packages yet. 6046 if (AppGlobals.getPackageManager() != null) { 6047 try { 6048 packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid); 6049 } catch (RemoteException e) { 6050 /* ignore - local call */ 6051 } 6052 } 6053 if (packageNames == null) { 6054 return EmptyArray.STRING; 6055 } 6056 return packageNames; 6057 } 6058 6059 private final class ClientUserRestrictionState implements DeathRecipient { 6060 private final IBinder token; 6061 6062 ClientUserRestrictionState(IBinder token) 6063 throws RemoteException { 6064 token.linkToDeath(this, 0); 6065 this.token = token; 6066 } 6067 6068 public boolean setRestriction(int code, boolean restricted, 6069 PackageTagsList excludedPackageTags, int userId) { 6070 return mAppOpsRestrictions.setUserRestriction(token, userId, code, 6071 restricted, excludedPackageTags); 6072 } 6073 6074 public boolean hasRestriction(int code, String packageName, String attributionTag, 6075 int userId, boolean isCheckOp) { 6076 return mAppOpsRestrictions.getUserRestriction(token, userId, code, packageName, 6077 attributionTag, isCheckOp); 6078 } 6079 6080 public void removeUser(int userId) { 6081 mAppOpsRestrictions.clearUserRestrictions(token, userId); 6082 } 6083 6084 public boolean isDefault() { 6085 return !mAppOpsRestrictions.hasUserRestrictions(token); 6086 } 6087 6088 @Override 6089 public void binderDied() { 6090 synchronized (AppOpsService.this) { 6091 mAppOpsRestrictions.clearUserRestrictions(token); 6092 mOpUserRestrictions.remove(token); 6093 destroy(); 6094 } 6095 } 6096 6097 public void destroy() { 6098 token.unlinkToDeath(this, 0); 6099 } 6100 } 6101 6102 private final class ClientGlobalRestrictionState implements DeathRecipient { 6103 final IBinder mToken; 6104 6105 ClientGlobalRestrictionState(IBinder token) 6106 throws RemoteException { 6107 token.linkToDeath(this, 0); 6108 this.mToken = token; 6109 } 6110 6111 boolean setRestriction(int code, boolean restricted) { 6112 return mAppOpsRestrictions.setGlobalRestriction(mToken, code, restricted); 6113 } 6114 6115 boolean hasRestriction(int code) { 6116 return mAppOpsRestrictions.getGlobalRestriction(mToken, code); 6117 } 6118 6119 boolean isDefault() { 6120 return !mAppOpsRestrictions.hasGlobalRestrictions(mToken); 6121 } 6122 6123 @Override 6124 public void binderDied() { 6125 mAppOpsRestrictions.clearGlobalRestrictions(mToken); 6126 mOpGlobalRestrictions.remove(mToken); 6127 destroy(); 6128 } 6129 6130 void destroy() { 6131 mToken.unlinkToDeath(this, 0); 6132 } 6133 } 6134 6135 private final class AppOpsManagerLocalImpl implements AppOpsManagerLocal { 6136 @Override 6137 public boolean isUidInForeground(int uid) { 6138 synchronized (AppOpsService.this) { 6139 return mUidStateTracker.isUidInForeground(uid); 6140 } 6141 } 6142 } 6143 6144 private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal { 6145 @Override public void setDeviceAndProfileOwners(SparseIntArray owners) { 6146 synchronized (AppOpsService.this) { 6147 mProfileOwners = owners; 6148 } 6149 } 6150 6151 @Override 6152 public void updateAppWidgetVisibility(SparseArray<String> uidPackageNames, 6153 boolean visible) { 6154 AppOpsService.this.updateAppWidgetVisibility(uidPackageNames, visible); 6155 } 6156 6157 @Override 6158 public void setUidModeFromPermissionPolicy(int code, int uid, int mode, 6159 @Nullable IAppOpsCallback callback) { 6160 setUidMode(code, uid, mode, callback); 6161 } 6162 6163 @Override 6164 public void setModeFromPermissionPolicy(int code, int uid, @NonNull String packageName, 6165 int mode, @Nullable IAppOpsCallback callback) { 6166 setMode(code, uid, packageName, mode, callback); 6167 } 6168 6169 6170 @Override 6171 public void setGlobalRestriction(int code, boolean restricted, IBinder token) { 6172 if (Binder.getCallingPid() != Process.myPid()) { 6173 // TODO instead of this enforcement put in AppOpsManagerInternal 6174 throw new SecurityException("Only the system can set global restrictions"); 6175 } 6176 6177 synchronized (AppOpsService.this) { 6178 ClientGlobalRestrictionState restrictionState = mOpGlobalRestrictions.get(token); 6179 6180 if (restrictionState == null) { 6181 try { 6182 restrictionState = new ClientGlobalRestrictionState(token); 6183 } catch (RemoteException e) { 6184 return; 6185 } 6186 mOpGlobalRestrictions.put(token, restrictionState); 6187 } 6188 6189 if (restrictionState.setRestriction(code, restricted)) { 6190 mHandler.sendMessage(PooledLambda.obtainMessage( 6191 AppOpsService::notifyWatchersOfChange, AppOpsService.this, code, 6192 UID_ANY)); 6193 mHandler.sendMessage(PooledLambda.obtainMessage( 6194 AppOpsService::updateStartedOpModeForUser, AppOpsService.this, 6195 code, restricted, UserHandle.USER_ALL)); 6196 } 6197 6198 if (restrictionState.isDefault()) { 6199 mOpGlobalRestrictions.remove(token); 6200 restrictionState.destroy(); 6201 } 6202 } 6203 } 6204 6205 @Override 6206 public int getOpRestrictionCount(int code, UserHandle user, String pkg, 6207 String attributionTag) { 6208 int number = 0; 6209 synchronized (AppOpsService.this) { 6210 int numRestrictions = mOpUserRestrictions.size(); 6211 for (int i = 0; i < numRestrictions; i++) { 6212 if (mOpUserRestrictions.valueAt(i) 6213 .hasRestriction(code, pkg, attributionTag, user.getIdentifier(), 6214 false)) { 6215 number++; 6216 } 6217 } 6218 6219 numRestrictions = mOpGlobalRestrictions.size(); 6220 for (int i = 0; i < numRestrictions; i++) { 6221 if (mOpGlobalRestrictions.valueAt(i).hasRestriction(code)) { 6222 number++; 6223 } 6224 } 6225 } 6226 6227 return number; 6228 } 6229 } 6230 6231 /** 6232 * Async task for writing note op stack trace, op code, package name and version to file 6233 * More specifically, writes all the collected ops from {@link #mNoteOpCallerStacktraces} 6234 */ 6235 private void writeNoteOps() { 6236 synchronized (this) { 6237 mWriteNoteOpsScheduled = false; 6238 } 6239 synchronized (mNoteOpCallerStacktracesFile) { 6240 try (FileWriter writer = new FileWriter(mNoteOpCallerStacktracesFile)) { 6241 int numTraces = mNoteOpCallerStacktraces.size(); 6242 for (int i = 0; i < numTraces; i++) { 6243 // Writing json formatted string into file 6244 writer.write(mNoteOpCallerStacktraces.valueAt(i).asJson()); 6245 // Comma separation, so we can wrap the entire log as a JSON object 6246 // when all results are collected 6247 writer.write(","); 6248 } 6249 } catch (IOException e) { 6250 Slog.w(TAG, "Failed to load opsValidation file for FileWriter", e); 6251 } 6252 } 6253 } 6254 6255 /** 6256 * This class represents a NoteOp Trace object amd contains the necessary fields that will 6257 * be written to file to use for permissions data validation in JSON format 6258 */ 6259 @Immutable 6260 static class NoteOpTrace { 6261 static final String STACKTRACE = "stackTrace"; 6262 static final String OP = "op"; 6263 static final String PACKAGENAME = "packageName"; 6264 static final String VERSION = "version"; 6265 6266 private final @NonNull String mStackTrace; 6267 private final int mOp; 6268 private final @Nullable String mPackageName; 6269 private final long mVersion; 6270 6271 /** 6272 * Initialize a NoteOp object using a JSON object containing the necessary fields 6273 * 6274 * @param jsonTrace JSON object represented as a string 6275 * 6276 * @return NoteOpTrace object initialized with JSON fields 6277 */ 6278 static NoteOpTrace fromJson(String jsonTrace) { 6279 try { 6280 // Re-add closing bracket which acted as a delimiter by the reader 6281 JSONObject obj = new JSONObject(jsonTrace.concat("}")); 6282 return new NoteOpTrace(obj.getString(STACKTRACE), obj.getInt(OP), 6283 obj.getString(PACKAGENAME), obj.getLong(VERSION)); 6284 } catch (JSONException e) { 6285 // Swallow error, only meant for logging ops, should not affect flow of the code 6286 Slog.e(TAG, "Error constructing NoteOpTrace object " 6287 + "JSON trace format incorrect", e); 6288 return null; 6289 } 6290 } 6291 6292 NoteOpTrace(String stackTrace, int op, String packageName, long version) { 6293 mStackTrace = stackTrace; 6294 mOp = op; 6295 mPackageName = packageName; 6296 mVersion = version; 6297 } 6298 6299 @Override 6300 public boolean equals(Object o) { 6301 if (this == o) return true; 6302 if (o == null || getClass() != o.getClass()) return false; 6303 NoteOpTrace that = (NoteOpTrace) o; 6304 return mOp == that.mOp 6305 && mVersion == that.mVersion 6306 && mStackTrace.equals(that.mStackTrace) 6307 && Objects.equals(mPackageName, that.mPackageName); 6308 } 6309 6310 @Override 6311 public int hashCode() { 6312 return Objects.hash(mStackTrace, mOp, mPackageName, mVersion); 6313 } 6314 6315 /** 6316 * The object is formatted as a JSON object and returned as a String 6317 * 6318 * @return JSON formatted string 6319 */ 6320 public String asJson() { 6321 return "{" 6322 + "\"" + STACKTRACE + "\":\"" + mStackTrace.replace("\n", "\\n") 6323 + '\"' + ",\"" + OP + "\":" + mOp 6324 + ",\"" + PACKAGENAME + "\":\"" + mPackageName + '\"' 6325 + ",\"" + VERSION + "\":" + mVersion 6326 + '}'; 6327 } 6328 } 6329 6330 /** 6331 * Collects noteOps, noteProxyOps and startOps from AppOpsManager and writes it into a file 6332 * which will be used for permissions data validation, the given parameters to this method 6333 * will be logged in json format 6334 * 6335 * @param stackTrace stacktrace from the most recent call in AppOpsManager 6336 * @param op op code 6337 * @param packageName package making call 6338 * @param version android version for this call 6339 */ 6340 @Override 6341 public void collectNoteOpCallsForValidation(String stackTrace, int op, String packageName, 6342 long version) { 6343 if (!AppOpsManager.NOTE_OP_COLLECTION_ENABLED) { 6344 return; 6345 } 6346 6347 Objects.requireNonNull(stackTrace); 6348 Preconditions.checkArgument(op >= 0); 6349 Preconditions.checkArgument(op < AppOpsManager._NUM_OP); 6350 6351 NoteOpTrace noteOpTrace = new NoteOpTrace(stackTrace, op, packageName, version); 6352 6353 boolean noteOpSetWasChanged; 6354 synchronized (this) { 6355 noteOpSetWasChanged = mNoteOpCallerStacktraces.add(noteOpTrace); 6356 if (noteOpSetWasChanged && !mWriteNoteOpsScheduled) { 6357 mWriteNoteOpsScheduled = true; 6358 mHandler.postDelayed(PooledLambda.obtainRunnable((that) -> { 6359 AsyncTask.execute(() -> { 6360 that.writeNoteOps(); 6361 }); 6362 }, this), 2500); 6363 } 6364 } 6365 } 6366 6367 @Immutable 6368 private final class CheckOpsDelegateDispatcher { 6369 private final @Nullable CheckOpsDelegate mPolicy; 6370 private final @Nullable CheckOpsDelegate mCheckOpsDelegate; 6371 6372 CheckOpsDelegateDispatcher(@Nullable CheckOpsDelegate policy, 6373 @Nullable CheckOpsDelegate checkOpsDelegate) { 6374 mPolicy = policy; 6375 mCheckOpsDelegate = checkOpsDelegate; 6376 } 6377 6378 public @NonNull CheckOpsDelegate getCheckOpsDelegate() { 6379 return mCheckOpsDelegate; 6380 } 6381 6382 public int checkOperation(int code, int uid, String packageName, 6383 @Nullable String attributionTag, boolean raw) { 6384 if (mPolicy != null) { 6385 if (mCheckOpsDelegate != null) { 6386 return mPolicy.checkOperation(code, uid, packageName, attributionTag, raw, 6387 this::checkDelegateOperationImpl); 6388 } else { 6389 return mPolicy.checkOperation(code, uid, packageName, attributionTag, raw, 6390 AppOpsService.this::checkOperationImpl); 6391 } 6392 } else if (mCheckOpsDelegate != null) { 6393 return checkDelegateOperationImpl(code, uid, packageName, attributionTag, raw); 6394 } 6395 return checkOperationImpl(code, uid, packageName, attributionTag, raw); 6396 } 6397 6398 private int checkDelegateOperationImpl(int code, int uid, String packageName, 6399 @Nullable String attributionTag, boolean raw) { 6400 return mCheckOpsDelegate.checkOperation(code, uid, packageName, attributionTag, raw, 6401 AppOpsService.this::checkOperationImpl); 6402 } 6403 6404 public int checkAudioOperation(int code, int usage, int uid, String packageName) { 6405 if (mPolicy != null) { 6406 if (mCheckOpsDelegate != null) { 6407 return mPolicy.checkAudioOperation(code, usage, uid, packageName, 6408 this::checkDelegateAudioOperationImpl); 6409 } else { 6410 return mPolicy.checkAudioOperation(code, usage, uid, packageName, 6411 AppOpsService.this::checkAudioOperationImpl); 6412 } 6413 } else if (mCheckOpsDelegate != null) { 6414 return checkDelegateAudioOperationImpl(code, usage, uid, packageName); 6415 } 6416 return checkAudioOperationImpl(code, usage, uid, packageName); 6417 } 6418 6419 private int checkDelegateAudioOperationImpl(int code, int usage, int uid, 6420 String packageName) { 6421 return mCheckOpsDelegate.checkAudioOperation(code, usage, uid, packageName, 6422 AppOpsService.this::checkAudioOperationImpl); 6423 } 6424 6425 public SyncNotedAppOp noteOperation(int code, int uid, String packageName, 6426 String attributionTag, boolean shouldCollectAsyncNotedOp, String message, 6427 boolean shouldCollectMessage) { 6428 if (mPolicy != null) { 6429 if (mCheckOpsDelegate != null) { 6430 return mPolicy.noteOperation(code, uid, packageName, attributionTag, 6431 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 6432 this::noteDelegateOperationImpl); 6433 } else { 6434 return mPolicy.noteOperation(code, uid, packageName, attributionTag, 6435 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 6436 AppOpsService.this::noteOperationImpl); 6437 } 6438 } else if (mCheckOpsDelegate != null) { 6439 return noteDelegateOperationImpl(code, uid, packageName, 6440 attributionTag, shouldCollectAsyncNotedOp, message, shouldCollectMessage); 6441 } 6442 return noteOperationImpl(code, uid, packageName, attributionTag, 6443 shouldCollectAsyncNotedOp, message, shouldCollectMessage); 6444 } 6445 6446 private SyncNotedAppOp noteDelegateOperationImpl(int code, int uid, 6447 @Nullable String packageName, @Nullable String featureId, 6448 boolean shouldCollectAsyncNotedOp, @Nullable String message, 6449 boolean shouldCollectMessage) { 6450 return mCheckOpsDelegate.noteOperation(code, uid, packageName, featureId, 6451 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 6452 AppOpsService.this::noteOperationImpl); 6453 } 6454 6455 public SyncNotedAppOp noteProxyOperation(int code, AttributionSource attributionSource, 6456 boolean shouldCollectAsyncNotedOp, @Nullable String message, 6457 boolean shouldCollectMessage, boolean skipProxyOperation) { 6458 if (mPolicy != null) { 6459 if (mCheckOpsDelegate != null) { 6460 return mPolicy.noteProxyOperation(code, attributionSource, 6461 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 6462 skipProxyOperation, this::noteDelegateProxyOperationImpl); 6463 } else { 6464 return mPolicy.noteProxyOperation(code, attributionSource, 6465 shouldCollectAsyncNotedOp, message, shouldCollectMessage, 6466 skipProxyOperation, AppOpsService.this::noteProxyOperationImpl); 6467 } 6468 } else if (mCheckOpsDelegate != null) { 6469 return noteDelegateProxyOperationImpl(code, 6470 attributionSource, shouldCollectAsyncNotedOp, message, 6471 shouldCollectMessage, skipProxyOperation); 6472 } 6473 return noteProxyOperationImpl(code, attributionSource, shouldCollectAsyncNotedOp, 6474 message, shouldCollectMessage,skipProxyOperation); 6475 } 6476 6477 private SyncNotedAppOp noteDelegateProxyOperationImpl(int code, 6478 @NonNull AttributionSource attributionSource, boolean shouldCollectAsyncNotedOp, 6479 @Nullable String message, boolean shouldCollectMessage, 6480 boolean skipProxyOperation) { 6481 return mCheckOpsDelegate.noteProxyOperation(code, attributionSource, 6482 shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, 6483 AppOpsService.this::noteProxyOperationImpl); 6484 } 6485 6486 public SyncNotedAppOp startOperation(IBinder token, int code, int uid, 6487 @Nullable String packageName, @NonNull String attributionTag, 6488 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, 6489 @Nullable String message, boolean shouldCollectMessage, 6490 @AttributionFlags int attributionFlags, int attributionChainId) { 6491 if (mPolicy != null) { 6492 if (mCheckOpsDelegate != null) { 6493 return mPolicy.startOperation(token, code, uid, packageName, 6494 attributionTag, startIfModeDefault, shouldCollectAsyncNotedOp, message, 6495 shouldCollectMessage, attributionFlags, attributionChainId, 6496 this::startDelegateOperationImpl); 6497 } else { 6498 return mPolicy.startOperation(token, code, uid, packageName, attributionTag, 6499 startIfModeDefault, shouldCollectAsyncNotedOp, message, 6500 shouldCollectMessage, attributionFlags, attributionChainId, 6501 AppOpsService.this::startOperationImpl); 6502 } 6503 } else if (mCheckOpsDelegate != null) { 6504 return startDelegateOperationImpl(token, code, uid, packageName, attributionTag, 6505 startIfModeDefault, shouldCollectAsyncNotedOp, message, 6506 shouldCollectMessage, attributionFlags, attributionChainId); 6507 } 6508 return startOperationImpl(token, code, uid, packageName, attributionTag, 6509 startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, 6510 attributionFlags, attributionChainId); 6511 } 6512 6513 private SyncNotedAppOp startDelegateOperationImpl(IBinder token, int code, int uid, 6514 @Nullable String packageName, @Nullable String attributionTag, 6515 boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, 6516 boolean shouldCollectMessage, @AttributionFlags int attributionFlags, 6517 int attributionChainId) { 6518 return mCheckOpsDelegate.startOperation(token, code, uid, packageName, attributionTag, 6519 startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, 6520 attributionFlags, attributionChainId, AppOpsService.this::startOperationImpl); 6521 } 6522 6523 public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code, 6524 @NonNull AttributionSource attributionSource, boolean startIfModeDefault, 6525 boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, 6526 boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, 6527 @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { 6528 if (mPolicy != null) { 6529 if (mCheckOpsDelegate != null) { 6530 return mPolicy.startProxyOperation(clientId, code, attributionSource, 6531 startIfModeDefault, shouldCollectAsyncNotedOp, message, 6532 shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, 6533 proxiedAttributionFlags, attributionChainId, 6534 this::startDelegateProxyOperationImpl); 6535 } else { 6536 return mPolicy.startProxyOperation(clientId, code, attributionSource, 6537 startIfModeDefault, shouldCollectAsyncNotedOp, message, 6538 shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, 6539 proxiedAttributionFlags, attributionChainId, 6540 AppOpsService.this::startProxyOperationImpl); 6541 } 6542 } else if (mCheckOpsDelegate != null) { 6543 return startDelegateProxyOperationImpl(clientId, code, attributionSource, 6544 startIfModeDefault, shouldCollectAsyncNotedOp, message, 6545 shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, 6546 proxiedAttributionFlags, attributionChainId); 6547 } 6548 return startProxyOperationImpl(clientId, code, attributionSource, startIfModeDefault, 6549 shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, 6550 proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); 6551 } 6552 6553 private SyncNotedAppOp startDelegateProxyOperationImpl(@NonNull IBinder clientId, int code, 6554 @NonNull AttributionSource attributionSource, boolean startIfModeDefault, 6555 boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, 6556 boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, 6557 @AttributionFlags int proxiedAttributionFlsgs, int attributionChainId) { 6558 return mCheckOpsDelegate.startProxyOperation(clientId, code, attributionSource, 6559 startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, 6560 skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlsgs, 6561 attributionChainId, AppOpsService.this::startProxyOperationImpl); 6562 } 6563 6564 public void finishOperation(IBinder clientId, int code, int uid, String packageName, 6565 String attributionTag) { 6566 if (mPolicy != null) { 6567 if (mCheckOpsDelegate != null) { 6568 mPolicy.finishOperation(clientId, code, uid, packageName, attributionTag, 6569 this::finishDelegateOperationImpl); 6570 } else { 6571 mPolicy.finishOperation(clientId, code, uid, packageName, attributionTag, 6572 AppOpsService.this::finishOperationImpl); 6573 } 6574 } else if (mCheckOpsDelegate != null) { 6575 finishDelegateOperationImpl(clientId, code, uid, packageName, attributionTag); 6576 } else { 6577 finishOperationImpl(clientId, code, uid, packageName, attributionTag); 6578 } 6579 } 6580 6581 private void finishDelegateOperationImpl(IBinder clientId, int code, int uid, 6582 String packageName, String attributionTag) { 6583 mCheckOpsDelegate.finishOperation(clientId, code, uid, packageName, attributionTag, 6584 AppOpsService.this::finishOperationImpl); 6585 } 6586 6587 public void finishProxyOperation(@NonNull IBinder clientId, int code, 6588 @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { 6589 if (mPolicy != null) { 6590 if (mCheckOpsDelegate != null) { 6591 mPolicy.finishProxyOperation(clientId, code, attributionSource, 6592 skipProxyOperation, this::finishDelegateProxyOperationImpl); 6593 } else { 6594 mPolicy.finishProxyOperation(clientId, code, attributionSource, 6595 skipProxyOperation, AppOpsService.this::finishProxyOperationImpl); 6596 } 6597 } else if (mCheckOpsDelegate != null) { 6598 finishDelegateProxyOperationImpl(clientId, code, attributionSource, 6599 skipProxyOperation); 6600 } else { 6601 finishProxyOperationImpl(clientId, code, attributionSource, skipProxyOperation); 6602 } 6603 } 6604 6605 private Void finishDelegateProxyOperationImpl(@NonNull IBinder clientId, int code, 6606 @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { 6607 mCheckOpsDelegate.finishProxyOperation(clientId, code, attributionSource, 6608 skipProxyOperation, AppOpsService.this::finishProxyOperationImpl); 6609 return null; 6610 } 6611 } 6612 } 6613