1 /* 2 * Copyright (C) 2006 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.content; 18 19 import static android.content.PermissionChecker.PERMISSION_GRANTED; 20 21 import android.Manifest; 22 import android.accounts.Account; 23 import android.accounts.AccountManagerInternal; 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.annotation.RequiresPermission; 27 import android.annotation.UserIdInt; 28 import android.app.ActivityManager; 29 import android.app.ActivityManager.RestrictionLevel; 30 import android.app.ActivityManagerInternal; 31 import android.app.AppGlobals; 32 import android.app.AppOpsManager; 33 import android.app.compat.CompatChanges; 34 import android.app.job.JobInfo; 35 import android.compat.annotation.ChangeId; 36 import android.compat.annotation.EnabledAfter; 37 import android.content.BroadcastReceiver; 38 import android.content.ComponentName; 39 import android.content.ContentResolver; 40 import android.content.ContentResolver.SyncExemption; 41 import android.content.Context; 42 import android.content.IContentService; 43 import android.content.ISyncStatusObserver; 44 import android.content.Intent; 45 import android.content.IntentFilter; 46 import android.content.PeriodicSync; 47 import android.content.SyncAdapterType; 48 import android.content.SyncInfo; 49 import android.content.SyncRequest; 50 import android.content.SyncStatusInfo; 51 import android.content.pm.PackageManager; 52 import android.content.pm.ProviderInfo; 53 import android.database.IContentObserver; 54 import android.net.Uri; 55 import android.os.AppBackgroundRestrictionsInfo; 56 import android.os.Binder; 57 import android.os.Build; 58 import android.os.Bundle; 59 import android.os.FactoryTest; 60 import android.os.IBinder; 61 import android.os.Process; 62 import android.os.RemoteException; 63 import android.os.ResultReceiver; 64 import android.os.ShellCallback; 65 import android.os.UserHandle; 66 import android.text.TextUtils; 67 import android.text.format.DateUtils; 68 import android.util.ArrayMap; 69 import android.util.ArraySet; 70 import android.util.Log; 71 import android.util.Pair; 72 import android.util.Slog; 73 import android.util.SparseArray; 74 import android.util.SparseIntArray; 75 76 import com.android.internal.annotations.GuardedBy; 77 import com.android.internal.annotations.VisibleForTesting; 78 import com.android.internal.os.BackgroundThread; 79 import com.android.internal.os.BinderDeathDispatcher; 80 import com.android.internal.util.ArrayUtils; 81 import com.android.internal.util.DumpUtils; 82 import com.android.internal.util.FrameworkStatsLog; 83 import com.android.internal.util.IndentingPrintWriter; 84 import com.android.server.LocalServices; 85 import com.android.server.SystemService; 86 import com.android.server.pm.permission.LegacyPermissionManagerInternal; 87 88 import java.io.FileDescriptor; 89 import java.io.PrintWriter; 90 import java.util.ArrayList; 91 import java.util.Arrays; 92 import java.util.Collections; 93 import java.util.Comparator; 94 import java.util.List; 95 import java.util.Objects; 96 97 /** 98 * {@hide} 99 */ 100 public final class ContentService extends IContentService.Stub { 101 static final String TAG = "ContentService"; 102 static final boolean DEBUG = false; 103 104 /** Do a WTF if a single observer is registered more than this times. */ 105 private static final int TOO_MANY_OBSERVERS_THRESHOLD = 1000; 106 107 /** 108 * Delay to apply to content change notifications dispatched to apps running 109 * in the background. This is used to help prevent stampeding when the user 110 * is performing CPU/RAM intensive foreground tasks, such as when capturing 111 * burst photos. 112 */ 113 private static final long BACKGROUND_OBSERVER_DELAY = 10 * DateUtils.SECOND_IN_MILLIS; 114 115 /** 116 * Enables checking for account access for the calling uid on all sync-related APIs. 117 */ 118 @ChangeId 119 @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.S_V2) 120 public static final long ACCOUNT_ACCESS_CHECK_CHANGE_ID = 201794303L; 121 122 /** 123 * Enables checking for authority access for the calling uid on all sync-related APIs. 124 */ 125 @ChangeId 126 @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.TIRAMISU) 127 public static final long AUTHORITY_ACCESS_CHECK_CHANGE_ID = 207133734L; 128 129 public static class Lifecycle extends SystemService { 130 private ContentService mService; 131 Lifecycle(Context context)132 public Lifecycle(Context context) { 133 super(context); 134 } 135 136 @Override onStart()137 public void onStart() { 138 final boolean factoryTest = (FactoryTest 139 .getMode() == FactoryTest.FACTORY_TEST_LOW_LEVEL); 140 mService = new ContentService(getContext(), factoryTest); 141 publishBinderService(ContentResolver.CONTENT_SERVICE_NAME, mService); 142 } 143 144 @Override onBootPhase(int phase)145 public void onBootPhase(int phase) { 146 mService.onBootPhase(phase); 147 } 148 149 @Override onUserStarting(@onNull TargetUser user)150 public void onUserStarting(@NonNull TargetUser user) { 151 mService.onStartUser(user.getUserIdentifier()); 152 } 153 154 @Override onUserUnlocking(@onNull TargetUser user)155 public void onUserUnlocking(@NonNull TargetUser user) { 156 mService.onUnlockUser(user.getUserIdentifier()); 157 } 158 159 @Override onUserStopping(@onNull TargetUser user)160 public void onUserStopping(@NonNull TargetUser user) { 161 mService.onStopUser(user.getUserIdentifier()); 162 } 163 164 @Override onUserStopped(@onNull TargetUser user)165 public void onUserStopped(@NonNull TargetUser user) { 166 synchronized (mService.mCache) { 167 mService.mCache.remove(user.getUserIdentifier()); 168 } 169 } 170 } 171 172 private Context mContext; 173 private boolean mFactoryTest; 174 175 private final ObserverNode mRootNode = new ObserverNode(""); 176 177 private SyncManager mSyncManager = null; 178 private final Object mSyncManagerLock = new Object(); 179 180 private final AccountManagerInternal mAccountManagerInternal; 181 182 private static final BinderDeathDispatcher<IContentObserver> sObserverDeathDispatcher = 183 new BinderDeathDispatcher<>(); 184 185 @GuardedBy("sObserverLeakDetectedUid") 186 private static final ArraySet<Integer> sObserverLeakDetectedUid = new ArraySet<>(0); 187 188 /** 189 * Map from userId to providerPackageName to [clientPackageName, uri] to 190 * value. This structure is carefully optimized to keep invalidation logic 191 * as cheap as possible. 192 */ 193 @GuardedBy("mCache") 194 private final SparseArray<ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>>> 195 mCache = new SparseArray<>(); 196 197 private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() { 198 @Override 199 public void onReceive(Context context, Intent intent) { 200 synchronized (mCache) { 201 if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) { 202 mCache.clear(); 203 } else { 204 final Uri data = intent.getData(); 205 if (data != null) { 206 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 207 UserHandle.USER_NULL); 208 final String packageName = data.getSchemeSpecificPart(); 209 invalidateCacheLocked(userId, packageName, null); 210 } 211 } 212 } 213 } 214 }; 215 getSyncManager()216 private SyncManager getSyncManager() { 217 synchronized(mSyncManagerLock) { 218 if (mSyncManager == null) { 219 mSyncManager = new SyncManager(mContext, mFactoryTest); 220 } 221 return mSyncManager; 222 } 223 } 224 onStartUser(int userHandle)225 void onStartUser(int userHandle) { 226 if (mSyncManager != null) mSyncManager.onStartUser(userHandle); 227 } 228 onUnlockUser(int userHandle)229 void onUnlockUser(int userHandle) { 230 if (mSyncManager != null) mSyncManager.onUnlockUser(userHandle); 231 } 232 onStopUser(int userHandle)233 void onStopUser(int userHandle) { 234 if (mSyncManager != null) mSyncManager.onStopUser(userHandle); 235 } 236 237 @Override dump(FileDescriptor fd, PrintWriter pw_, String[] args)238 protected synchronized void dump(FileDescriptor fd, PrintWriter pw_, String[] args) { 239 if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw_)) return; 240 final IndentingPrintWriter pw = new IndentingPrintWriter(pw_, " "); 241 242 final boolean dumpAll = ArrayUtils.contains(args, "-a"); 243 244 // This makes it so that future permission checks will be in the context of this 245 // process rather than the caller's process. We will restore this before returning. 246 final long identityToken = clearCallingIdentity(); 247 try { 248 if (mSyncManager == null) { 249 pw.println("SyncManager not available yet"); 250 } else { 251 mSyncManager.dump(fd, pw, dumpAll); 252 } 253 pw.println(); 254 pw.println("Observer tree:"); 255 synchronized (mRootNode) { 256 int[] counts = new int[2]; 257 final SparseIntArray pidCounts = new SparseIntArray(); 258 mRootNode.dumpLocked(fd, pw, args, "", " ", counts, pidCounts); 259 pw.println(); 260 ArrayList<Integer> sorted = new ArrayList<Integer>(); 261 for (int i=0; i<pidCounts.size(); i++) { 262 sorted.add(pidCounts.keyAt(i)); 263 } 264 Collections.sort(sorted, new Comparator<Integer>() { 265 @Override 266 public int compare(Integer lhs, Integer rhs) { 267 int lc = pidCounts.get(lhs); 268 int rc = pidCounts.get(rhs); 269 if (lc < rc) { 270 return 1; 271 } else if (lc > rc) { 272 return -1; 273 } 274 return 0; 275 } 276 277 }); 278 for (int i=0; i<sorted.size(); i++) { 279 int pid = sorted.get(i); 280 pw.print(" pid "); pw.print(pid); pw.print(": "); 281 pw.print(pidCounts.get(pid)); pw.println(" observers"); 282 } 283 pw.println(); 284 pw.increaseIndent(); 285 pw.print("Total number of nodes: "); pw.println(counts[0]); 286 pw.print("Total number of observers: "); pw.println(counts[1]); 287 288 sObserverDeathDispatcher.dump(pw); 289 pw.decreaseIndent(); 290 } 291 synchronized (sObserverLeakDetectedUid) { 292 pw.println(); 293 pw.print("Observer leaking UIDs: "); 294 pw.println(sObserverLeakDetectedUid.toString()); 295 } 296 297 synchronized (mCache) { 298 pw.println(); 299 pw.println("Cached content:"); 300 pw.increaseIndent(); 301 for (int i = 0; i < mCache.size(); i++) { 302 pw.println("User " + mCache.keyAt(i) + ":"); 303 pw.increaseIndent(); 304 pw.println(mCache.valueAt(i)); 305 pw.decreaseIndent(); 306 } 307 pw.decreaseIndent(); 308 } 309 } finally { 310 restoreCallingIdentity(identityToken); 311 } 312 } 313 ContentService(Context context, boolean factoryTest)314 /*package*/ ContentService(Context context, boolean factoryTest) { 315 mContext = context; 316 mFactoryTest = factoryTest; 317 318 // Let the package manager query for the sync adapters for a given authority 319 // as we grant default permissions to sync adapters for specific authorities. 320 final LegacyPermissionManagerInternal permissionManagerInternal = 321 LocalServices.getService(LegacyPermissionManagerInternal.class); 322 permissionManagerInternal.setSyncAdapterPackagesProvider((authority, userId) -> { 323 return getSyncAdapterPackagesForAuthorityAsUser(authority, userId); 324 }); 325 326 final IntentFilter packageFilter = new IntentFilter(); 327 packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 328 packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 329 packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 330 packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); 331 packageFilter.addDataScheme("package"); 332 mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL, 333 packageFilter, null, null); 334 335 final IntentFilter localeFilter = new IntentFilter(); 336 localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED); 337 mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL, 338 localeFilter, null, null); 339 340 mAccountManagerInternal = LocalServices.getService(AccountManagerInternal.class); 341 } 342 onBootPhase(int phase)343 void onBootPhase(int phase) { 344 switch (phase) { 345 case SystemService.PHASE_ACTIVITY_MANAGER_READY: 346 getSyncManager(); 347 break; 348 } 349 if (mSyncManager != null) { 350 mSyncManager.onBootPhase(phase); 351 } 352 } 353 354 /** 355 * Register a content observer tied to a specific user's view of the provider. 356 * @param userHandle the user whose view of the provider is to be observed. May be 357 * the calling user without requiring any permission, otherwise the caller needs to 358 * hold the INTERACT_ACROSS_USERS_FULL permission or hold a read uri grant to the uri. 359 * Pseudousers USER_ALL and USER_CURRENT are properly handled; all other pseudousers 360 * are forbidden. 361 */ 362 @Override registerContentObserver(Uri uri, boolean notifyForDescendants, IContentObserver observer, int userHandle, int targetSdkVersion)363 public void registerContentObserver(Uri uri, boolean notifyForDescendants, 364 IContentObserver observer, int userHandle, int targetSdkVersion) { 365 if (observer == null || uri == null) { 366 throw new IllegalArgumentException("You must pass a valid uri and observer"); 367 } 368 369 final int uid = Binder.getCallingUid(); 370 final int pid = Binder.getCallingPid(); 371 372 userHandle = handleIncomingUser(uri, pid, uid, 373 Intent.FLAG_GRANT_READ_URI_PERMISSION, true, userHandle); 374 375 final String msg = LocalServices.getService(ActivityManagerInternal.class) 376 .checkContentProviderAccess(uri.getAuthority(), userHandle); 377 if (msg != null) { 378 if (targetSdkVersion >= Build.VERSION_CODES.O) { 379 throw new SecurityException(msg); 380 } else { 381 if (msg.startsWith("Failed to find provider")) { 382 // Sigh, we need to quietly let apps targeting older API 383 // levels notify on non-existent providers. 384 } else { 385 Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg); 386 return; 387 } 388 } 389 } 390 391 synchronized (mRootNode) { 392 mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode, 393 uid, pid, userHandle); 394 if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri + 395 " with notifyForDescendants " + notifyForDescendants); 396 } 397 } 398 registerContentObserver(Uri uri, boolean notifyForDescendants, IContentObserver observer)399 public void registerContentObserver(Uri uri, boolean notifyForDescendants, 400 IContentObserver observer) { 401 registerContentObserver(uri, notifyForDescendants, observer, 402 UserHandle.getCallingUserId(), Build.VERSION_CODES.CUR_DEVELOPMENT); 403 } 404 405 @Override unregisterContentObserver(IContentObserver observer)406 public void unregisterContentObserver(IContentObserver observer) { 407 if (observer == null) { 408 throw new IllegalArgumentException("You must pass a valid observer"); 409 } 410 synchronized (mRootNode) { 411 mRootNode.removeObserverLocked(observer); 412 if (false) Log.v(TAG, "Unregistered observer " + observer); 413 } 414 } 415 416 /** 417 * Notify observers of a particular user's view of the provider. 418 * @param userHandle the user whose view of the provider is to be notified. May be 419 * the calling user without requiring any permission, otherwise the caller needs to 420 * hold the INTERACT_ACROSS_USERS_FULL permission or hold a write uri grant to the uri. 421 * Pseudousers USER_ALL and USER_CURRENT are properly interpreted; no other pseudousers are 422 * allowed. 423 */ 424 @Override notifyChange(Uri[] uris, IContentObserver observer, boolean observerWantsSelfNotifications, int flags, int userId, int targetSdkVersion, String callingPackage)425 public void notifyChange(Uri[] uris, IContentObserver observer, 426 boolean observerWantsSelfNotifications, int flags, int userId, 427 int targetSdkVersion, String callingPackage) { 428 if (DEBUG) { 429 Slog.d(TAG, "Notifying update of " + Arrays.toString(uris) + " for user " + userId 430 + ", observer " + observer + ", flags " + Integer.toHexString(flags)); 431 } 432 433 final int callingUid = Binder.getCallingUid(); 434 final int callingPid = Binder.getCallingPid(); 435 final int callingUserId = UserHandle.getCallingUserId(); 436 437 // Set of notification events that we need to dispatch 438 final ObserverCollector collector = new ObserverCollector(); 439 440 // Set of content provider authorities that we've validated the caller 441 // has access to, mapped to the package name hosting that provider 442 final ArrayMap<Pair<String, Integer>, String> validatedProviders = new ArrayMap<>(); 443 444 for (Uri uri : uris) { 445 // Validate that calling app has access to this provider 446 final int resolvedUserId = handleIncomingUser(uri, callingPid, callingUid, 447 Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true, userId); 448 final Pair<String, Integer> provider = Pair.create(uri.getAuthority(), resolvedUserId); 449 if (!validatedProviders.containsKey(provider)) { 450 final String msg = LocalServices.getService(ActivityManagerInternal.class) 451 .checkContentProviderAccess(uri.getAuthority(), resolvedUserId); 452 if (msg != null) { 453 if (targetSdkVersion >= Build.VERSION_CODES.O) { 454 throw new SecurityException(msg); 455 } else { 456 if (msg.startsWith("Failed to find provider")) { 457 // Sigh, we need to quietly let apps targeting older API 458 // levels notify on non-existent providers. 459 } else { 460 Log.w(TAG, "Ignoring notify for " + uri + " from " 461 + callingUid + ": " + msg); 462 continue; 463 } 464 } 465 } 466 467 // Remember that we've validated this access 468 final String packageName = getProviderPackageName(uri, resolvedUserId); 469 validatedProviders.put(provider, packageName); 470 } 471 472 // No concerns raised above, so caller has access; let's collect the 473 // notifications that should be dispatched 474 synchronized (mRootNode) { 475 final int segmentCount = ObserverNode.countUriSegments(uri); 476 mRootNode.collectObserversLocked(uri, segmentCount, 0, observer, 477 observerWantsSelfNotifications, flags, resolvedUserId, collector); 478 } 479 } 480 481 final long token = clearCallingIdentity(); 482 try { 483 // Actually dispatch all the notifications we collected 484 collector.dispatch(); 485 486 final SyncManager syncManager = getSyncManager(); 487 for (int i = 0; i < validatedProviders.size(); i++) { 488 final String authority = validatedProviders.keyAt(i).first; 489 final int resolvedUserId = validatedProviders.keyAt(i).second; 490 final String packageName = validatedProviders.valueAt(i); 491 492 // Kick off sync adapters for any authorities we touched 493 if ((flags & ContentResolver.NOTIFY_SYNC_TO_NETWORK) != 0) { 494 syncManager.scheduleLocalSync(null /* all accounts */, callingUserId, 495 callingUid, 496 authority, getSyncExemptionForCaller(callingUid), 497 callingUid, callingPid, callingPackage); 498 } 499 500 // Invalidate caches for any authorities we touched 501 synchronized (mCache) { 502 for (Uri uri : uris) { 503 if (Objects.equals(uri.getAuthority(), authority)) { 504 invalidateCacheLocked(resolvedUserId, packageName, uri); 505 } 506 } 507 } 508 } 509 } finally { 510 Binder.restoreCallingIdentity(token); 511 } 512 } 513 checkUriPermission(Uri uri, int pid, int uid, int modeFlags, int userHandle)514 private int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, int userHandle) { 515 try { 516 return ActivityManager.getService().checkUriPermission( 517 uri, pid, uid, modeFlags, userHandle, null); 518 } catch (RemoteException e) { 519 return PackageManager.PERMISSION_DENIED; 520 } 521 } 522 523 /** 524 * Collection of detected change notifications that should be delivered. 525 * <p> 526 * To help reduce Binder transaction overhead, this class clusters together 527 * multiple {@link Uri} where all other arguments are identical. 528 */ 529 @VisibleForTesting 530 public static class ObserverCollector { 531 private final ArrayMap<Key, List<Uri>> collected = new ArrayMap<>(); 532 533 private static class Key { 534 final IContentObserver observer; 535 final int uid; 536 final boolean selfChange; 537 final int flags; 538 final int userId; 539 Key(IContentObserver observer, int uid, boolean selfChange, int flags, int userId)540 Key(IContentObserver observer, int uid, boolean selfChange, int flags, int userId) { 541 this.observer = observer; 542 this.uid = uid; 543 this.selfChange = selfChange; 544 this.flags = flags; 545 this.userId = userId; 546 } 547 548 @Override equals(Object o)549 public boolean equals(Object o) { 550 if (!(o instanceof Key)) { 551 return false; 552 } 553 final Key other = (Key) o; 554 return Objects.equals(observer, other.observer) 555 && (uid == other.uid) 556 && (selfChange == other.selfChange) 557 && (flags == other.flags) 558 && (userId == other.userId); 559 } 560 561 @Override hashCode()562 public int hashCode() { 563 return Objects.hash(observer, uid, selfChange, flags, userId); 564 } 565 } 566 collect(IContentObserver observer, int uid, boolean selfChange, Uri uri, int flags, int userId)567 public void collect(IContentObserver observer, int uid, boolean selfChange, Uri uri, 568 int flags, int userId) { 569 final Key key = new Key(observer, uid, selfChange, flags, userId); 570 List<Uri> value = collected.get(key); 571 if (value == null) { 572 value = new ArrayList<>(); 573 collected.put(key, value); 574 } 575 value.add(uri); 576 } 577 dispatch()578 public void dispatch() { 579 for (int i = 0; i < collected.size(); i++) { 580 final Key key = collected.keyAt(i); 581 final List<Uri> value = collected.valueAt(i); 582 583 final Runnable task = () -> { 584 try { 585 key.observer.onChangeEtc(key.selfChange, 586 value.toArray(new Uri[value.size()]), key.flags, key.userId); 587 } catch (RemoteException ignored) { 588 } 589 }; 590 591 // Immediately dispatch notifications to foreground apps that 592 // are important to the user; all other background observers are 593 // delayed to avoid stampeding 594 final boolean noDelay = (key.flags & ContentResolver.NOTIFY_NO_DELAY) != 0; 595 final int procState = LocalServices.getService(ActivityManagerInternal.class) 596 .getUidProcessState(key.uid); 597 if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND || noDelay) { 598 task.run(); 599 } else { 600 BackgroundThread.getHandler().postDelayed(task, BACKGROUND_OBSERVER_DELAY); 601 } 602 } 603 } 604 } 605 606 @Override requestSync(Account account, String authority, Bundle extras, String callingPackage)607 public void requestSync(Account account, String authority, Bundle extras, 608 String callingPackage) { 609 Bundle.setDefusable(extras, true); 610 ContentResolver.validateSyncExtrasBundle(extras); 611 int userId = UserHandle.getCallingUserId(); 612 final int callingUid = Binder.getCallingUid(); 613 final int callingPid = Binder.getCallingPid(); 614 615 if (!hasAccountAccess(true, account, callingUid)) { 616 return; 617 } 618 if (!hasAuthorityAccess(authority, callingUid, userId)) { 619 return; 620 } 621 622 validateExtras(callingUid, extras); 623 final int syncExemption = getSyncExemptionAndCleanUpExtrasForCaller(callingUid, extras); 624 625 // This makes it so that future permission checks will be in the context of this 626 // process rather than the caller's process. We will restore this before returning. 627 final long identityToken = clearCallingIdentity(); 628 try { 629 getSyncManager().scheduleSync(account, userId, callingUid, authority, extras, 630 SyncStorageEngine.AuthorityInfo.UNDEFINED, 631 syncExemption, callingUid, callingPid, callingPackage); 632 } finally { 633 restoreCallingIdentity(identityToken); 634 } 635 } 636 637 /** 638 * Request a sync with a generic {@link android.content.SyncRequest} object. This will be 639 * either: 640 * periodic OR one-off sync. 641 * and 642 * anonymous OR provider sync. 643 * Depending on the request, we enqueue to suit in the SyncManager. 644 * @param request The request object. Validation of this object is done by its builder. 645 */ 646 @Override sync(SyncRequest request, String callingPackage)647 public void sync(SyncRequest request, String callingPackage) { 648 syncAsUser(request, UserHandle.getCallingUserId(), callingPackage); 649 } 650 clampPeriod(long period)651 private long clampPeriod(long period) { 652 long minPeriod = JobInfo.getMinPeriodMillis() / 1000; 653 if (period < minPeriod) { 654 Slog.w(TAG, "Requested poll frequency of " + period 655 + " seconds being rounded up to " + minPeriod + "s."); 656 period = minPeriod; 657 } 658 return period; 659 } 660 661 /** 662 * If the user id supplied is different to the calling user, the caller must hold the 663 * INTERACT_ACROSS_USERS_FULL permission. 664 */ 665 @Override syncAsUser(SyncRequest request, int userId, String callingPackage)666 public void syncAsUser(SyncRequest request, int userId, String callingPackage) { 667 enforceCrossUserPermission(userId, "no permission to request sync as user: " + userId); 668 669 final int callingUid = Binder.getCallingUid(); 670 final int callingPid = Binder.getCallingPid(); 671 if (!hasAccountAccess(true, request.getAccount(), callingUid)) { 672 return; 673 } 674 if (!hasAuthorityAccess(request.getProvider(), callingUid, userId)) { 675 return; 676 } 677 678 final Bundle extras = request.getBundle(); 679 validateExtras(callingUid, extras); 680 final int syncExemption = getSyncExemptionAndCleanUpExtrasForCaller(callingUid, extras); 681 682 // This makes it so that future permission checks will be in the context of this 683 // process rather than the caller's process. We will restore this before returning. 684 final long identityToken = clearCallingIdentity(); 685 try { 686 long flextime = request.getSyncFlexTime(); 687 long runAtTime = request.getSyncRunTime(); 688 if (request.isPeriodic()) { 689 mContext.enforceCallingOrSelfPermission( 690 Manifest.permission.WRITE_SYNC_SETTINGS, 691 "no permission to write the sync settings"); 692 SyncStorageEngine.EndPoint info; 693 info = new SyncStorageEngine.EndPoint( 694 request.getAccount(), request.getProvider(), userId); 695 696 runAtTime = clampPeriod(runAtTime); 697 // Schedule periodic sync. 698 getSyncManager().updateOrAddPeriodicSync(info, runAtTime, 699 flextime, extras); 700 } else { 701 getSyncManager().scheduleSync( 702 request.getAccount(), userId, callingUid, request.getProvider(), extras, 703 SyncStorageEngine.AuthorityInfo.UNDEFINED, 704 syncExemption, callingUid, callingPid, callingPackage); 705 } 706 } finally { 707 restoreCallingIdentity(identityToken); 708 } 709 } 710 711 /** 712 * Clear all scheduled sync operations that match the uri and cancel the active sync 713 * if they match the authority and account, if they are present. 714 * 715 * @param account filter the pending and active syncs to cancel using this account, or null. 716 * @param authority filter the pending and active syncs to cancel using this authority, or 717 * null. 718 * @param cname cancel syncs running on this service, or null for provider/account. 719 */ 720 @Override cancelSync(Account account, String authority, ComponentName cname)721 public void cancelSync(Account account, String authority, ComponentName cname) { 722 cancelSyncAsUser(account, authority, cname, UserHandle.getCallingUserId()); 723 } 724 725 /** 726 * Clear all scheduled sync operations that match the uri and cancel the active sync 727 * if they match the authority and account, if they are present. 728 * 729 * <p> If the user id supplied is different to the calling user, the caller must hold the 730 * INTERACT_ACROSS_USERS_FULL permission. 731 * 732 * @param account filter the pending and active syncs to cancel using this account, or null. 733 * @param authority filter the pending and active syncs to cancel using this authority, or 734 * null. 735 * @param userId the user id for which to cancel sync operations. 736 * @param cname cancel syncs running on this service, or null for provider/account. 737 */ 738 @Override cancelSyncAsUser(Account account, String authority, ComponentName cname, int userId)739 public void cancelSyncAsUser(Account account, String authority, ComponentName cname, 740 int userId) { 741 if (authority != null && authority.length() == 0) { 742 throw new IllegalArgumentException("Authority must be non-empty"); 743 } 744 enforceCrossUserPermission(userId, 745 "no permission to modify the sync settings for user " + userId); 746 747 if (cname != null) { 748 Slog.e(TAG, "cname not null."); 749 return; 750 } 751 752 // This makes it so that future permission checks will be in the context of this 753 // process rather than the caller's process. We will restore this before returning. 754 final long identityToken = clearCallingIdentity(); 755 try { 756 SyncStorageEngine.EndPoint info; 757 info = new SyncStorageEngine.EndPoint(account, authority, userId); 758 getSyncManager().clearScheduledSyncOperations(info); 759 getSyncManager().cancelActiveSync(info, null /* all syncs for this adapter */, "API"); 760 } finally { 761 restoreCallingIdentity(identityToken); 762 } 763 } 764 765 @Override cancelRequest(SyncRequest request)766 public void cancelRequest(SyncRequest request) { 767 if (request.isPeriodic()) { 768 mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 769 "no permission to write the sync settings"); 770 } 771 772 final int callingUid = Binder.getCallingUid(); 773 Bundle extras = new Bundle(request.getBundle()); 774 validateExtras(callingUid, extras); 775 776 int userId = UserHandle.getCallingUserId(); 777 final long identityToken = clearCallingIdentity(); 778 try { 779 SyncStorageEngine.EndPoint info; 780 781 Account account = request.getAccount(); 782 String provider = request.getProvider(); 783 info = new SyncStorageEngine.EndPoint(account, provider, userId); 784 if (request.isPeriodic()) { 785 // Remove periodic sync. 786 getSyncManager().removePeriodicSync(info, extras, 787 "cancelRequest() by uid=" + callingUid); 788 } 789 // Cancel active syncs and clear pending syncs from the queue. 790 getSyncManager().cancelScheduledSyncOperation(info, extras); 791 getSyncManager().cancelActiveSync(info, extras, "API"); 792 } finally { 793 restoreCallingIdentity(identityToken); 794 } 795 } 796 797 /** 798 * Get information about the SyncAdapters that are known to the system. 799 * @return an array of SyncAdapters that have registered with the system 800 */ 801 @Override getSyncAdapterTypes()802 public SyncAdapterType[] getSyncAdapterTypes() { 803 return getSyncAdapterTypesAsUser(UserHandle.getCallingUserId()); 804 } 805 806 /** 807 * Get information about the SyncAdapters that are known to the system for a particular user. 808 * 809 * <p> If the user id supplied is different to the calling user, the caller must hold the 810 * INTERACT_ACROSS_USERS_FULL permission. 811 * 812 * @return an array of SyncAdapters that have registered with the system 813 */ 814 @Override getSyncAdapterTypesAsUser(int userId)815 public SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) { 816 enforceCrossUserPermission(userId, 817 "no permission to read sync settings for user " + userId); 818 819 // This makes it so that future permission checks will be in the context of this 820 // process rather than the caller's process. We will restore this before returning. 821 final int callingUid = Binder.getCallingUid(); 822 final long identityToken = clearCallingIdentity(); 823 try { 824 return getSyncManager().getSyncAdapterTypes(callingUid, userId); 825 } finally { 826 restoreCallingIdentity(identityToken); 827 } 828 } 829 830 @Override getSyncAdapterPackagesForAuthorityAsUser(String authority, int userId)831 public String[] getSyncAdapterPackagesForAuthorityAsUser(String authority, int userId) { 832 enforceCrossUserPermission(userId, 833 "no permission to read sync settings for user " + userId); 834 835 // This makes it so that future permission checks will be in the context of this 836 // process rather than the caller's process. We will restore this before returning. 837 final int callingUid = Binder.getCallingUid(); 838 final long identityToken = clearCallingIdentity(); 839 try { 840 return getSyncManager().getSyncAdapterPackagesForAuthorityAsUser(authority, callingUid, 841 userId); 842 } finally { 843 restoreCallingIdentity(identityToken); 844 } 845 } 846 847 @Override 848 @Nullable getSyncAdapterPackageAsUser(@onNull String accountType, @NonNull String authority, @UserIdInt int userId)849 public String getSyncAdapterPackageAsUser(@NonNull String accountType, 850 @NonNull String authority, @UserIdInt int userId) { 851 enforceCrossUserPermission(userId, 852 "no permission to read sync settings for user " + userId); 853 854 final int callingUid = Binder.getCallingUid(); 855 final long identityToken = clearCallingIdentity(); 856 try { 857 return getSyncManager().getSyncAdapterPackageAsUser(accountType, authority, 858 callingUid, userId); 859 } finally { 860 restoreCallingIdentity(identityToken); 861 } 862 } 863 864 @Override getSyncAutomatically(Account account, String providerName)865 public boolean getSyncAutomatically(Account account, String providerName) { 866 return getSyncAutomaticallyAsUser(account, providerName, UserHandle.getCallingUserId()); 867 } 868 869 /** 870 * If the user id supplied is different to the calling user, the caller must hold the 871 * INTERACT_ACROSS_USERS_FULL permission. 872 */ 873 @Override getSyncAutomaticallyAsUser(Account account, String providerName, int userId)874 public boolean getSyncAutomaticallyAsUser(Account account, String providerName, int userId) { 875 enforceCrossUserPermission(userId, 876 "no permission to read the sync settings for user " + userId); 877 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 878 "no permission to read the sync settings"); 879 880 final int callingUid = Binder.getCallingUid(); 881 if (!hasAccountAccess(true, account, callingUid)) { 882 return false; 883 } 884 if (!hasAuthorityAccess(providerName, callingUid, userId)) { 885 return false; 886 } 887 888 final long identityToken = clearCallingIdentity(); 889 try { 890 return getSyncManager().getSyncStorageEngine() 891 .getSyncAutomatically(account, userId, providerName); 892 } finally { 893 restoreCallingIdentity(identityToken); 894 } 895 } 896 897 @Override setSyncAutomatically(Account account, String providerName, boolean sync)898 public void setSyncAutomatically(Account account, String providerName, boolean sync) { 899 setSyncAutomaticallyAsUser(account, providerName, sync, UserHandle.getCallingUserId()); 900 } 901 902 @Override setSyncAutomaticallyAsUser(Account account, String providerName, boolean sync, int userId)903 public void setSyncAutomaticallyAsUser(Account account, String providerName, boolean sync, 904 int userId) { 905 if (TextUtils.isEmpty(providerName)) { 906 throw new IllegalArgumentException("Authority must be non-empty"); 907 } 908 mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 909 "no permission to write the sync settings"); 910 enforceCrossUserPermission(userId, 911 "no permission to modify the sync settings for user " + userId); 912 913 final int callingUid = Binder.getCallingUid(); 914 final int callingPid = Binder.getCallingPid(); 915 if (!hasAccountAccess(true, account, callingUid)) { 916 return; 917 } 918 if (!hasAuthorityAccess(providerName, callingUid, userId)) { 919 return; 920 } 921 922 final int syncExemptionFlag = getSyncExemptionForCaller(callingUid); 923 924 final long identityToken = clearCallingIdentity(); 925 try { 926 getSyncManager().getSyncStorageEngine().setSyncAutomatically(account, userId, 927 providerName, sync, syncExemptionFlag, callingUid, callingPid); 928 } finally { 929 restoreCallingIdentity(identityToken); 930 } 931 } 932 933 /** Old API. Schedule periodic sync with default flexMillis time. */ 934 @Override addPeriodicSync(Account account, String authority, Bundle extras, long pollFrequency)935 public void addPeriodicSync(Account account, String authority, Bundle extras, 936 long pollFrequency) { 937 Bundle.setDefusable(extras, true); 938 if (account == null) { 939 throw new IllegalArgumentException("Account must not be null"); 940 } 941 if (TextUtils.isEmpty(authority)) { 942 throw new IllegalArgumentException("Authority must not be empty."); 943 } 944 mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 945 "no permission to write the sync settings"); 946 947 final int callingUid = Binder.getCallingUid(); 948 final int userId = UserHandle.getCallingUserId(); 949 if (!hasAccountAccess(true, account, callingUid)) { 950 return; 951 } 952 if (!hasAuthorityAccess(authority, callingUid, userId)) { 953 return; 954 } 955 956 validateExtras(callingUid, extras); 957 958 pollFrequency = clampPeriod(pollFrequency); 959 long defaultFlex = SyncStorageEngine.calculateDefaultFlexTime(pollFrequency); 960 961 final long identityToken = clearCallingIdentity(); 962 try { 963 SyncStorageEngine.EndPoint info = 964 new SyncStorageEngine.EndPoint(account, authority, userId); 965 getSyncManager().updateOrAddPeriodicSync(info, pollFrequency, 966 defaultFlex, extras); 967 } finally { 968 restoreCallingIdentity(identityToken); 969 } 970 } 971 972 @Override removePeriodicSync(Account account, String authority, Bundle extras)973 public void removePeriodicSync(Account account, String authority, Bundle extras) { 974 Bundle.setDefusable(extras, true); 975 if (account == null) { 976 throw new IllegalArgumentException("Account must not be null"); 977 } 978 if (TextUtils.isEmpty(authority)) { 979 throw new IllegalArgumentException("Authority must not be empty"); 980 } 981 mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 982 "no permission to write the sync settings"); 983 984 final int callingUid = Binder.getCallingUid(); 985 final int userId = UserHandle.getCallingUserId(); 986 if (!hasAccountAccess(true, account, callingUid)) { 987 return; 988 } 989 if (!hasAuthorityAccess(authority, callingUid, userId)) { 990 return; 991 } 992 993 validateExtras(callingUid, extras); 994 995 final long identityToken = clearCallingIdentity(); 996 try { 997 getSyncManager().removePeriodicSync( 998 new SyncStorageEngine.EndPoint(account, authority, userId), 999 extras, "removePeriodicSync() by uid=" + callingUid); 1000 } finally { 1001 restoreCallingIdentity(identityToken); 1002 } 1003 } 1004 1005 @Override getPeriodicSyncs(Account account, String providerName, ComponentName cname)1006 public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName, 1007 ComponentName cname) { 1008 if (account == null) { 1009 throw new IllegalArgumentException("Account must not be null"); 1010 } 1011 if (TextUtils.isEmpty(providerName)) { 1012 throw new IllegalArgumentException("Authority must not be empty"); 1013 } 1014 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 1015 "no permission to read the sync settings"); 1016 1017 final int callingUid = Binder.getCallingUid(); 1018 final int userId = UserHandle.getCallingUserId(); 1019 if (!hasAccountAccess(true, account, callingUid)) { 1020 return new ArrayList<>(); // return a new empty list for consistent behavior 1021 } 1022 if (!hasAuthorityAccess(providerName, callingUid, userId)) { 1023 return new ArrayList<>(); 1024 } 1025 1026 final long identityToken = clearCallingIdentity(); 1027 try { 1028 return getSyncManager().getPeriodicSyncs( 1029 new SyncStorageEngine.EndPoint(account, providerName, userId)); 1030 } finally { 1031 restoreCallingIdentity(identityToken); 1032 } 1033 } 1034 1035 @Override getIsSyncable(Account account, String providerName)1036 public int getIsSyncable(Account account, String providerName) { 1037 return getIsSyncableAsUser(account, providerName, UserHandle.getCallingUserId()); 1038 } 1039 1040 /** 1041 * If the user id supplied is different to the calling user, the caller must hold the 1042 * INTERACT_ACROSS_USERS_FULL permission. 1043 */ 1044 @Override getIsSyncableAsUser(Account account, String providerName, int userId)1045 public int getIsSyncableAsUser(Account account, String providerName, int userId) { 1046 enforceCrossUserPermission(userId, 1047 "no permission to read the sync settings for user " + userId); 1048 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 1049 "no permission to read the sync settings"); 1050 1051 final int callingUid = Binder.getCallingUid(); 1052 if (!hasAccountAccess(true, account, callingUid)) { 1053 return SyncStorageEngine.AuthorityInfo.NOT_SYNCABLE; // to keep behavior consistent 1054 } 1055 if (!hasAuthorityAccess(providerName, callingUid, userId)) { 1056 return SyncStorageEngine.AuthorityInfo.NOT_SYNCABLE; 1057 } 1058 1059 final long identityToken = clearCallingIdentity(); 1060 try { 1061 return getSyncManager().computeSyncable(account, userId, providerName, false); 1062 } finally { 1063 restoreCallingIdentity(identityToken); 1064 } 1065 } 1066 1067 @Override setIsSyncable(Account account, String providerName, int syncable)1068 public void setIsSyncable(Account account, String providerName, int syncable) { 1069 setIsSyncableAsUser(account, providerName, syncable, UserHandle.getCallingUserId()); 1070 } 1071 1072 /** 1073 * @hide 1074 */ 1075 @Override setIsSyncableAsUser(Account account, String providerName, int syncable, int userId)1076 public void setIsSyncableAsUser(Account account, String providerName, int syncable, 1077 int userId) { 1078 if (TextUtils.isEmpty(providerName)) { 1079 throw new IllegalArgumentException("Authority must not be empty"); 1080 } 1081 enforceCrossUserPermission(userId, 1082 "no permission to set the sync settings for user " + userId); 1083 mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 1084 "no permission to write the sync settings"); 1085 1086 syncable = normalizeSyncable(syncable); 1087 final int callingUid = Binder.getCallingUid(); 1088 final int callingPid = Binder.getCallingPid(); 1089 if (!hasAccountAccess(true, account, callingUid)) { 1090 return; 1091 } 1092 if (!hasAuthorityAccess(providerName, callingUid, userId)) { 1093 return; 1094 } 1095 1096 final long identityToken = clearCallingIdentity(); 1097 try { 1098 getSyncManager().getSyncStorageEngine().setIsSyncable( 1099 account, userId, providerName, syncable, callingUid, callingPid); 1100 } finally { 1101 restoreCallingIdentity(identityToken); 1102 } 1103 } 1104 1105 @Override getMasterSyncAutomatically()1106 public boolean getMasterSyncAutomatically() { 1107 return getMasterSyncAutomaticallyAsUser(UserHandle.getCallingUserId()); 1108 } 1109 1110 /** 1111 * If the user id supplied is different to the calling user, the caller must hold the 1112 * INTERACT_ACROSS_USERS_FULL permission. 1113 */ 1114 @Override getMasterSyncAutomaticallyAsUser(int userId)1115 public boolean getMasterSyncAutomaticallyAsUser(int userId) { 1116 enforceCrossUserPermission(userId, 1117 "no permission to read the sync settings for user " + userId); 1118 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 1119 "no permission to read the sync settings"); 1120 1121 final long identityToken = clearCallingIdentity(); 1122 try { 1123 return getSyncManager().getSyncStorageEngine().getMasterSyncAutomatically(userId); 1124 } finally { 1125 restoreCallingIdentity(identityToken); 1126 } 1127 } 1128 1129 @Override setMasterSyncAutomatically(boolean flag)1130 public void setMasterSyncAutomatically(boolean flag) { 1131 setMasterSyncAutomaticallyAsUser(flag, UserHandle.getCallingUserId()); 1132 } 1133 1134 @Override setMasterSyncAutomaticallyAsUser(boolean flag, int userId)1135 public void setMasterSyncAutomaticallyAsUser(boolean flag, int userId) { 1136 enforceCrossUserPermission(userId, 1137 "no permission to set the sync status for user " + userId); 1138 mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 1139 "no permission to write the sync settings"); 1140 1141 final int callingUid = Binder.getCallingUid(); 1142 final int callingPid = Binder.getCallingPid(); 1143 1144 final long identityToken = clearCallingIdentity(); 1145 try { 1146 getSyncManager().getSyncStorageEngine().setMasterSyncAutomatically(flag, userId, 1147 getSyncExemptionForCaller(callingUid), callingUid, callingPid); 1148 } finally { 1149 restoreCallingIdentity(identityToken); 1150 } 1151 } 1152 1153 @Override isSyncActive(Account account, String authority, ComponentName cname)1154 public boolean isSyncActive(Account account, String authority, ComponentName cname) { 1155 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 1156 "no permission to read the sync stats"); 1157 1158 final int callingUid = Binder.getCallingUid(); 1159 final int userId = UserHandle.getCallingUserId(); 1160 if (!hasAccountAccess(true, account, callingUid)) { 1161 return false; 1162 } 1163 if (!hasAuthorityAccess(authority, callingUid, userId)) { 1164 return false; 1165 } 1166 1167 final long identityToken = clearCallingIdentity(); 1168 try { 1169 return getSyncManager().getSyncStorageEngine().isSyncActive( 1170 new SyncStorageEngine.EndPoint(account, authority, userId)); 1171 } finally { 1172 restoreCallingIdentity(identityToken); 1173 } 1174 } 1175 1176 @Override getCurrentSyncs()1177 public List<SyncInfo> getCurrentSyncs() { 1178 return getCurrentSyncsAsUser(UserHandle.getCallingUserId()); 1179 } 1180 1181 /** 1182 * If the user id supplied is different to the calling user, the caller must hold the 1183 * INTERACT_ACROSS_USERS_FULL permission. 1184 */ 1185 @Override getCurrentSyncsAsUser(int userId)1186 public List<SyncInfo> getCurrentSyncsAsUser(int userId) { 1187 enforceCrossUserPermission(userId, 1188 "no permission to read the sync settings for user " + userId); 1189 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 1190 "no permission to read the sync stats"); 1191 1192 final boolean canAccessAccounts = 1193 mContext.checkCallingOrSelfPermission(Manifest.permission.GET_ACCOUNTS) 1194 == PackageManager.PERMISSION_GRANTED; 1195 final List<SyncInfo> results; 1196 final int callingUid = Binder.getCallingUid(); 1197 final long identityToken = clearCallingIdentity(); 1198 try { 1199 results = getSyncManager().getSyncStorageEngine() 1200 .getCurrentSyncsCopy(userId, canAccessAccounts); 1201 } finally { 1202 restoreCallingIdentity(identityToken); 1203 } 1204 results.removeIf(i -> !hasAuthorityAccess(i.authority, callingUid, userId)); 1205 return results; 1206 } 1207 1208 @Override getSyncStatus(Account account, String authority, ComponentName cname)1209 public SyncStatusInfo getSyncStatus(Account account, String authority, ComponentName cname) { 1210 return getSyncStatusAsUser(account, authority, cname, UserHandle.getCallingUserId()); 1211 } 1212 1213 /** 1214 * If the user id supplied is different to the calling user, the caller must hold the 1215 * INTERACT_ACROSS_USERS_FULL permission. 1216 */ 1217 @Override 1218 @Nullable getSyncStatusAsUser(Account account, String authority, ComponentName cname, int userId)1219 public SyncStatusInfo getSyncStatusAsUser(Account account, String authority, 1220 ComponentName cname, int userId) { 1221 if (TextUtils.isEmpty(authority)) { 1222 throw new IllegalArgumentException("Authority must not be empty"); 1223 } 1224 1225 enforceCrossUserPermission(userId, 1226 "no permission to read the sync stats for user " + userId); 1227 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 1228 "no permission to read the sync stats"); 1229 1230 final int callingUid = Binder.getCallingUid(); 1231 if (!hasAccountAccess(true, account, callingUid)) { 1232 return null; 1233 } 1234 if (!hasAuthorityAccess(authority, callingUid, userId)) { 1235 return null; 1236 } 1237 1238 final long identityToken = clearCallingIdentity(); 1239 try { 1240 SyncStorageEngine.EndPoint info; 1241 if (!(account == null || authority == null)) { 1242 info = new SyncStorageEngine.EndPoint(account, authority, userId); 1243 } else { 1244 throw new IllegalArgumentException("Must call sync status with valid authority"); 1245 } 1246 return getSyncManager().getSyncStorageEngine().getStatusByAuthority(info); 1247 } finally { 1248 restoreCallingIdentity(identityToken); 1249 } 1250 } 1251 1252 @Override isSyncPending(Account account, String authority, ComponentName cname)1253 public boolean isSyncPending(Account account, String authority, ComponentName cname) { 1254 return isSyncPendingAsUser(account, authority, cname, UserHandle.getCallingUserId()); 1255 } 1256 1257 @Override isSyncPendingAsUser(Account account, String authority, ComponentName cname, int userId)1258 public boolean isSyncPendingAsUser(Account account, String authority, ComponentName cname, 1259 int userId) { 1260 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 1261 "no permission to read the sync stats"); 1262 enforceCrossUserPermission(userId, 1263 "no permission to retrieve the sync settings for user " + userId); 1264 1265 final int callingUid = Binder.getCallingUid(); 1266 if (!hasAccountAccess(true, account, callingUid)) { 1267 return false; 1268 } 1269 if (!hasAuthorityAccess(authority, callingUid, userId)) { 1270 return false; 1271 } 1272 1273 final long identityToken = clearCallingIdentity(); 1274 try { 1275 SyncStorageEngine.EndPoint info; 1276 if (!(account == null || authority == null)) { 1277 info = new SyncStorageEngine.EndPoint(account, authority, userId); 1278 } else { 1279 throw new IllegalArgumentException("Invalid authority specified"); 1280 } 1281 return getSyncManager().getSyncStorageEngine().isSyncPending(info); 1282 } finally { 1283 restoreCallingIdentity(identityToken); 1284 } 1285 } 1286 1287 @Override addStatusChangeListener(int mask, ISyncStatusObserver callback)1288 public void addStatusChangeListener(int mask, ISyncStatusObserver callback) { 1289 final int callingUid = Binder.getCallingUid(); 1290 final long identityToken = clearCallingIdentity(); 1291 try { 1292 if (callback != null) { 1293 getSyncManager().getSyncStorageEngine().addStatusChangeListener( 1294 mask, callingUid, callback); 1295 } 1296 } finally { 1297 restoreCallingIdentity(identityToken); 1298 } 1299 } 1300 1301 @Override removeStatusChangeListener(ISyncStatusObserver callback)1302 public void removeStatusChangeListener(ISyncStatusObserver callback) { 1303 final long identityToken = clearCallingIdentity(); 1304 try { 1305 if (callback != null) { 1306 getSyncManager().getSyncStorageEngine().removeStatusChangeListener(callback); 1307 } 1308 } finally { 1309 restoreCallingIdentity(identityToken); 1310 } 1311 } 1312 getProviderPackageName(Uri uri, int userId)1313 private @Nullable String getProviderPackageName(Uri uri, int userId) { 1314 final ProviderInfo pi = mContext.getPackageManager().resolveContentProviderAsUser( 1315 uri.getAuthority(), 0, userId); 1316 return (pi != null) ? pi.packageName : null; 1317 } 1318 1319 @GuardedBy("mCache") findOrCreateCacheLocked(int userId, String providerPackageName)1320 private ArrayMap<Pair<String, Uri>, Bundle> findOrCreateCacheLocked(int userId, 1321 String providerPackageName) { 1322 ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>> userCache = mCache.get(userId); 1323 if (userCache == null) { 1324 userCache = new ArrayMap<>(); 1325 mCache.put(userId, userCache); 1326 } 1327 ArrayMap<Pair<String, Uri>, Bundle> packageCache = userCache.get(providerPackageName); 1328 if (packageCache == null) { 1329 packageCache = new ArrayMap<>(); 1330 userCache.put(providerPackageName, packageCache); 1331 } 1332 return packageCache; 1333 } 1334 1335 @GuardedBy("mCache") invalidateCacheLocked(int userId, String providerPackageName, Uri uri)1336 private void invalidateCacheLocked(int userId, String providerPackageName, Uri uri) { 1337 ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>> userCache = mCache.get(userId); 1338 if (userCache == null) return; 1339 1340 ArrayMap<Pair<String, Uri>, Bundle> packageCache = userCache.get(providerPackageName); 1341 if (packageCache == null) return; 1342 1343 if (uri != null) { 1344 for (int i = 0; i < packageCache.size();) { 1345 final Pair<String, Uri> key = packageCache.keyAt(i); 1346 if (key.second != null && key.second.toString().startsWith(uri.toString())) { 1347 if (DEBUG) Slog.d(TAG, "Invalidating cache for key " + key); 1348 packageCache.removeAt(i); 1349 } else { 1350 i++; 1351 } 1352 } 1353 } else { 1354 if (DEBUG) Slog.d(TAG, "Invalidating cache for package " + providerPackageName); 1355 packageCache.clear(); 1356 } 1357 } 1358 1359 @Override 1360 @RequiresPermission(android.Manifest.permission.CACHE_CONTENT) putCache(String packageName, Uri key, Bundle value, int userId)1361 public void putCache(String packageName, Uri key, Bundle value, int userId) { 1362 Bundle.setDefusable(value, true); 1363 enforceNonFullCrossUserPermission(userId, TAG); 1364 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG); 1365 mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(), 1366 packageName); 1367 1368 final String providerPackageName = getProviderPackageName(key, userId); 1369 final Pair<String, Uri> fullKey = Pair.create(packageName, key); 1370 1371 synchronized (mCache) { 1372 final ArrayMap<Pair<String, Uri>, Bundle> cache = findOrCreateCacheLocked(userId, 1373 providerPackageName); 1374 if (value != null) { 1375 cache.put(fullKey, value); 1376 } else { 1377 cache.remove(fullKey); 1378 } 1379 } 1380 } 1381 1382 @Override 1383 @RequiresPermission(android.Manifest.permission.CACHE_CONTENT) getCache(String packageName, Uri key, int userId)1384 public Bundle getCache(String packageName, Uri key, int userId) { 1385 enforceNonFullCrossUserPermission(userId, TAG); 1386 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG); 1387 mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(), 1388 packageName); 1389 1390 final String providerPackageName = getProviderPackageName(key, userId); 1391 final Pair<String, Uri> fullKey = Pair.create(packageName, key); 1392 1393 synchronized (mCache) { 1394 final ArrayMap<Pair<String, Uri>, Bundle> cache = findOrCreateCacheLocked(userId, 1395 providerPackageName); 1396 return cache.get(fullKey); 1397 } 1398 } 1399 handleIncomingUser(Uri uri, int pid, int uid, int modeFlags, boolean allowNonFull, int userId)1400 private int handleIncomingUser(Uri uri, int pid, int uid, int modeFlags, boolean allowNonFull, 1401 int userId) { 1402 if (userId == UserHandle.USER_CURRENT) { 1403 userId = ActivityManager.getCurrentUser(); 1404 } 1405 1406 if (userId == UserHandle.USER_ALL) { 1407 mContext.enforceCallingOrSelfPermission( 1408 Manifest.permission.INTERACT_ACROSS_USERS_FULL, "No access to " + uri); 1409 } else if (userId < 0) { 1410 throw new IllegalArgumentException("Invalid user: " + userId); 1411 } else if (userId != UserHandle.getCallingUserId()) { 1412 if (checkUriPermission(uri, pid, uid, modeFlags, 1413 userId) != PackageManager.PERMISSION_GRANTED) { 1414 boolean allow = false; 1415 if (mContext.checkCallingOrSelfPermission( 1416 Manifest.permission.INTERACT_ACROSS_USERS_FULL) 1417 == PackageManager.PERMISSION_GRANTED) { 1418 allow = true; 1419 } else if (allowNonFull && mContext.checkCallingOrSelfPermission( 1420 Manifest.permission.INTERACT_ACROSS_USERS) 1421 == PackageManager.PERMISSION_GRANTED) { 1422 allow = true; 1423 } 1424 if (!allow) { 1425 final String permissions = allowNonFull 1426 ? (Manifest.permission.INTERACT_ACROSS_USERS_FULL + " or " + 1427 Manifest.permission.INTERACT_ACROSS_USERS) 1428 : Manifest.permission.INTERACT_ACROSS_USERS_FULL; 1429 throw new SecurityException("No access to " + uri + ": neither user " + uid 1430 + " nor current process has " + permissions); 1431 } 1432 } 1433 } 1434 1435 return userId; 1436 } 1437 1438 /** 1439 * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL 1440 * permission, if the userHandle is not for the caller. 1441 * 1442 * @param userHandle the user handle of the user we want to act on behalf of. 1443 * @param message the message to log on security exception. 1444 */ enforceCrossUserPermission(int userHandle, String message)1445 private void enforceCrossUserPermission(int userHandle, String message) { 1446 final int callingUser = UserHandle.getCallingUserId(); 1447 if (callingUser != userHandle) { 1448 mContext.enforceCallingOrSelfPermission( 1449 Manifest.permission.INTERACT_ACROSS_USERS_FULL, message); 1450 } 1451 } 1452 1453 /** 1454 * Checks if the request is from the system or an app that has {@code INTERACT_ACROSS_USERS} or 1455 * {@code INTERACT_ACROSS_USERS_FULL} permission, if the {@code userHandle} is not for the 1456 * caller. 1457 * 1458 * @param userHandle the user handle of the user we want to act on behalf of. 1459 * @param message the message to log on security exception. 1460 */ enforceNonFullCrossUserPermission(int userHandle, String message)1461 private void enforceNonFullCrossUserPermission(int userHandle, String message) { 1462 final int callingUser = UserHandle.getCallingUserId(); 1463 if (callingUser == userHandle) { 1464 return; 1465 } 1466 1467 int interactAcrossUsersState = mContext.checkCallingOrSelfPermission( 1468 Manifest.permission.INTERACT_ACROSS_USERS); 1469 if (interactAcrossUsersState == PERMISSION_GRANTED) { 1470 return; 1471 } 1472 1473 mContext.enforceCallingOrSelfPermission( 1474 Manifest.permission.INTERACT_ACROSS_USERS_FULL, message); 1475 } 1476 1477 /** 1478 * Checks to see if the given account is accessible by the provided uid. 1479 * 1480 * @param checkCompatFlag whether to check if the ACCOUNT_ACCESS_CHECK_CHANGE_ID flag is enabled 1481 * @param account the account trying to be accessed 1482 * @param uid the uid trying to access the account 1483 * @return {@code true} if the account is accessible by the given uid, {@code false} otherwise 1484 */ hasAccountAccess(boolean checkCompatFlag, Account account, int uid)1485 private boolean hasAccountAccess(boolean checkCompatFlag, Account account, int uid) { 1486 if (account == null) { 1487 // If the account is null, it means to check for all accounts hence skip the check here. 1488 return true; 1489 } 1490 if (checkCompatFlag 1491 && !CompatChanges.isChangeEnabled(ACCOUNT_ACCESS_CHECK_CHANGE_ID, uid)) { 1492 return true; 1493 } 1494 1495 final long identityToken = clearCallingIdentity(); 1496 try { 1497 return mAccountManagerInternal.hasAccountAccess(account, uid); 1498 } finally { 1499 restoreCallingIdentity(identityToken); 1500 } 1501 } 1502 1503 /** 1504 * Checks to see if the given authority is accessible by the caller. 1505 * 1506 * @param authority the authority to be accessed 1507 * @param uid the uid trying to access the authority 1508 * @param userId the user id for which to access the authority 1509 * @return {@code true} if the authority is accessible by the caller, {@code false} otherwise 1510 */ hasAuthorityAccess(@ullable String authority, int uid, @UserIdInt int userId)1511 private boolean hasAuthorityAccess(@Nullable String authority, int uid, @UserIdInt int userId) { 1512 if (TextUtils.isEmpty(authority)) { 1513 return true; 1514 } 1515 if (!CompatChanges.isChangeEnabled(AUTHORITY_ACCESS_CHECK_CHANGE_ID, uid)) { 1516 return true; 1517 } 1518 // Since #getSyncAdapterPackagesForAuthorityAsUser would filter out the packages 1519 // that aren't visible to the callers, using this to check if the given authority 1520 // is accessible by the callers. 1521 final String[] syncAdapterPackages = 1522 getSyncAdapterPackagesForAuthorityAsUser(authority, userId); 1523 return !ArrayUtils.isEmpty(syncAdapterPackages); 1524 } 1525 1526 normalizeSyncable(int syncable)1527 private static int normalizeSyncable(int syncable) { 1528 if (syncable > 0) { 1529 return SyncStorageEngine.AuthorityInfo.SYNCABLE; 1530 } else if (syncable == 0) { 1531 return SyncStorageEngine.AuthorityInfo.NOT_SYNCABLE; 1532 } 1533 return SyncStorageEngine.AuthorityInfo.UNDEFINED; 1534 } 1535 validateExtras(int callingUid, Bundle extras)1536 private void validateExtras(int callingUid, Bundle extras) { 1537 if (extras.containsKey(ContentResolver.SYNC_VIRTUAL_EXTRAS_EXEMPTION_FLAG)) { 1538 switch (callingUid) { 1539 case Process.ROOT_UID: 1540 case Process.SHELL_UID: 1541 case Process.SYSTEM_UID: 1542 break; // Okay 1543 default: 1544 final String msg = "Invalid extras specified."; 1545 Log.w(TAG, msg + " requestsync -f/-F needs to run on 'adb shell'"); 1546 throw new SecurityException(msg); 1547 } 1548 } 1549 } 1550 1551 @SyncExemption getSyncExemptionForCaller(int callingUid)1552 private int getSyncExemptionForCaller(int callingUid) { 1553 return getSyncExemptionAndCleanUpExtrasForCaller(callingUid, null); 1554 } 1555 1556 @SyncExemption getSyncExemptionAndCleanUpExtrasForCaller(int callingUid, Bundle extras)1557 private int getSyncExemptionAndCleanUpExtrasForCaller(int callingUid, Bundle extras) { 1558 if (extras != null) { 1559 final int exemption = 1560 extras.getInt(ContentResolver.SYNC_VIRTUAL_EXTRAS_EXEMPTION_FLAG, -1); 1561 1562 // Need to remove the virtual extra. 1563 extras.remove(ContentResolver.SYNC_VIRTUAL_EXTRAS_EXEMPTION_FLAG); 1564 if (exemption != -1) { 1565 return exemption; 1566 } 1567 } 1568 final ActivityManagerInternal ami = 1569 LocalServices.getService(ActivityManagerInternal.class); 1570 if (ami == null) { 1571 return ContentResolver.SYNC_EXEMPTION_NONE; 1572 } 1573 final int procState = ami.getUidProcessState(callingUid); 1574 final boolean isUidActive = ami.isUidActive(callingUid); 1575 1576 // Providers bound by a TOP app will get PROCESS_STATE_BOUND_TOP, so include those as well 1577 if (procState <= ActivityManager.PROCESS_STATE_TOP 1578 || procState == ActivityManager.PROCESS_STATE_BOUND_TOP) { 1579 return ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP; 1580 } 1581 if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND || isUidActive) { 1582 FrameworkStatsLog.write(FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED, 1583 callingUid, getProcStateForStatsd(procState), isUidActive, 1584 getRestrictionLevelForStatsd(ami.getRestrictionLevel(callingUid))); 1585 return ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET; 1586 } 1587 return ContentResolver.SYNC_EXEMPTION_NONE; 1588 } 1589 getProcStateForStatsd(int procState)1590 private int getProcStateForStatsd(int procState) { 1591 switch (procState) { 1592 case ActivityManager.PROCESS_STATE_UNKNOWN: 1593 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__UNKNOWN; 1594 case ActivityManager.PROCESS_STATE_PERSISTENT: 1595 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__PERSISTENT; 1596 case ActivityManager.PROCESS_STATE_PERSISTENT_UI: 1597 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__PERSISTENT_UI; 1598 case ActivityManager.PROCESS_STATE_TOP: 1599 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__TOP; 1600 case ActivityManager.PROCESS_STATE_BOUND_TOP: 1601 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__BOUND_TOP; 1602 case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE: 1603 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__FOREGROUND_SERVICE; 1604 case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE: 1605 return FrameworkStatsLog 1606 .SYNC_EXEMPTION_OCCURRED__PROC_STATE__BOUND_FOREGROUND_SERVICE; 1607 case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND: 1608 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__IMPORTANT_FOREGROUND; 1609 case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND: 1610 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__IMPORTANT_BACKGROUND; 1611 case ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND: 1612 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__TRANSIENT_BACKGROUND; 1613 case ActivityManager.PROCESS_STATE_BACKUP: 1614 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__BACKUP; 1615 case ActivityManager.PROCESS_STATE_SERVICE: 1616 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__SERVICE; 1617 case ActivityManager.PROCESS_STATE_RECEIVER: 1618 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__RECEIVER; 1619 case ActivityManager.PROCESS_STATE_TOP_SLEEPING: 1620 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__TOP_SLEEPING; 1621 case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT: 1622 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__HEAVY_WEIGHT; 1623 case ActivityManager.PROCESS_STATE_LAST_ACTIVITY: 1624 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__LAST_ACTIVITY; 1625 case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY: 1626 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__CACHED_ACTIVITY; 1627 case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: 1628 return FrameworkStatsLog 1629 .SYNC_EXEMPTION_OCCURRED__PROC_STATE__CACHED_ACTIVITY_CLIENT; 1630 case ActivityManager.PROCESS_STATE_CACHED_RECENT: 1631 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__CACHED_RECENT; 1632 case ActivityManager.PROCESS_STATE_CACHED_EMPTY: 1633 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__CACHED_EMPTY; 1634 default: 1635 return FrameworkStatsLog.SYNC_EXEMPTION_OCCURRED__PROC_STATE__UNKNOWN; 1636 } 1637 } 1638 getRestrictionLevelForStatsd(@estrictionLevel int level)1639 private int getRestrictionLevelForStatsd(@RestrictionLevel int level) { 1640 switch (level) { 1641 case ActivityManager.RESTRICTION_LEVEL_UNKNOWN: 1642 return AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN; 1643 case ActivityManager.RESTRICTION_LEVEL_UNRESTRICTED: 1644 return AppBackgroundRestrictionsInfo.LEVEL_UNRESTRICTED; 1645 case ActivityManager.RESTRICTION_LEVEL_EXEMPTED: 1646 return AppBackgroundRestrictionsInfo.LEVEL_EXEMPTED; 1647 case ActivityManager.RESTRICTION_LEVEL_ADAPTIVE_BUCKET: 1648 return AppBackgroundRestrictionsInfo.LEVEL_ADAPTIVE_BUCKET; 1649 case ActivityManager.RESTRICTION_LEVEL_RESTRICTED_BUCKET: 1650 return AppBackgroundRestrictionsInfo.LEVEL_RESTRICTED_BUCKET; 1651 case ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED: 1652 return AppBackgroundRestrictionsInfo.LEVEL_BACKGROUND_RESTRICTED; 1653 case ActivityManager.RESTRICTION_LEVEL_HIBERNATION: 1654 return AppBackgroundRestrictionsInfo.LEVEL_HIBERNATION; 1655 default: 1656 return AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN; 1657 } 1658 } 1659 1660 /** {@hide} */ 1661 @VisibleForTesting 1662 public static final class ObserverNode { 1663 private class ObserverEntry implements IBinder.DeathRecipient { 1664 public final IContentObserver observer; 1665 public final int uid; 1666 public final int pid; 1667 public final boolean notifyForDescendants; 1668 private final int userHandle; 1669 private final Object observersLock; 1670 ObserverEntry(IContentObserver o, boolean n, Object observersLock, int _uid, int _pid, int _userHandle, Uri uri)1671 public ObserverEntry(IContentObserver o, boolean n, Object observersLock, 1672 int _uid, int _pid, int _userHandle, Uri uri) { 1673 this.observersLock = observersLock; 1674 observer = o; 1675 uid = _uid; 1676 pid = _pid; 1677 userHandle = _userHandle; 1678 notifyForDescendants = n; 1679 1680 final int entries = sObserverDeathDispatcher.linkToDeath(observer, this); 1681 if (entries == -1) { 1682 binderDied(); 1683 } else if (entries == TOO_MANY_OBSERVERS_THRESHOLD) { 1684 boolean alreadyDetected; 1685 1686 synchronized (sObserverLeakDetectedUid) { 1687 alreadyDetected = sObserverLeakDetectedUid.contains(uid); 1688 if (!alreadyDetected) { 1689 sObserverLeakDetectedUid.add(uid); 1690 } 1691 } 1692 if (!alreadyDetected) { 1693 String caller = null; 1694 try { 1695 caller = ArrayUtils.firstOrNull(AppGlobals.getPackageManager() 1696 .getPackagesForUid(uid)); 1697 } catch (RemoteException ignore) { 1698 } 1699 Slog.wtf(TAG, "Observer registered too many times. Leak? cpid=" + pid 1700 + " cuid=" + uid 1701 + " cpkg=" + caller 1702 + " url=" + uri); 1703 } 1704 } 1705 1706 } 1707 1708 @Override binderDied()1709 public void binderDied() { 1710 synchronized (observersLock) { 1711 removeObserverLocked(observer); 1712 } 1713 } 1714 dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, String name, String prefix, SparseIntArray pidCounts)1715 public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, 1716 String name, String prefix, SparseIntArray pidCounts) { 1717 pidCounts.put(pid, pidCounts.get(pid)+1); 1718 pw.print(prefix); pw.print(name); pw.print(": pid="); 1719 pw.print(pid); pw.print(" uid="); 1720 pw.print(uid); pw.print(" user="); 1721 pw.print(userHandle); pw.print(" target="); 1722 pw.println(Integer.toHexString(System.identityHashCode( 1723 observer != null ? observer.asBinder() : null))); 1724 } 1725 } 1726 1727 private String mName; 1728 private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>(); 1729 private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>(); 1730 ObserverNode(String name)1731 public ObserverNode(String name) { 1732 mName = name; 1733 } 1734 dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, String name, String prefix, int[] counts, SparseIntArray pidCounts)1735 public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, 1736 String name, String prefix, int[] counts, SparseIntArray pidCounts) { 1737 String innerName = null; 1738 if (mObservers.size() > 0) { 1739 if ("".equals(name)) { 1740 innerName = mName; 1741 } else { 1742 innerName = name + "/" + mName; 1743 } 1744 for (int i=0; i<mObservers.size(); i++) { 1745 counts[1]++; 1746 mObservers.get(i).dumpLocked(fd, pw, args, innerName, prefix, 1747 pidCounts); 1748 } 1749 } 1750 if (mChildren.size() > 0) { 1751 if (innerName == null) { 1752 if ("".equals(name)) { 1753 innerName = mName; 1754 } else { 1755 innerName = name + "/" + mName; 1756 } 1757 } 1758 for (int i=0; i<mChildren.size(); i++) { 1759 counts[0]++; 1760 mChildren.get(i).dumpLocked(fd, pw, args, innerName, prefix, 1761 counts, pidCounts); 1762 } 1763 } 1764 } 1765 getUriSegment(Uri uri, int index)1766 public static String getUriSegment(Uri uri, int index) { 1767 if (uri != null) { 1768 if (index == 0) { 1769 return uri.getAuthority(); 1770 } else { 1771 return uri.getPathSegments().get(index - 1); 1772 } 1773 } else { 1774 return null; 1775 } 1776 } 1777 countUriSegments(Uri uri)1778 public static int countUriSegments(Uri uri) { 1779 if (uri == null) { 1780 return 0; 1781 } 1782 return uri.getPathSegments().size() + 1; 1783 } 1784 1785 // Invariant: userHandle is either a hard user number or is USER_ALL addObserverLocked(Uri uri, IContentObserver observer, boolean notifyForDescendants, Object observersLock, int uid, int pid, int userHandle)1786 public void addObserverLocked(Uri uri, IContentObserver observer, 1787 boolean notifyForDescendants, Object observersLock, 1788 int uid, int pid, int userHandle) { 1789 addObserverLocked(uri, 0, observer, notifyForDescendants, observersLock, 1790 uid, pid, userHandle); 1791 } 1792 addObserverLocked(Uri uri, int index, IContentObserver observer, boolean notifyForDescendants, Object observersLock, int uid, int pid, int userHandle)1793 private void addObserverLocked(Uri uri, int index, IContentObserver observer, 1794 boolean notifyForDescendants, Object observersLock, 1795 int uid, int pid, int userHandle) { 1796 // If this is the leaf node add the observer 1797 if (index == countUriSegments(uri)) { 1798 mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock, 1799 uid, pid, userHandle, uri)); 1800 return; 1801 } 1802 1803 // Look to see if the proper child already exists 1804 String segment = getUriSegment(uri, index); 1805 if (segment == null) { 1806 throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer"); 1807 } 1808 int N = mChildren.size(); 1809 for (int i = 0; i < N; i++) { 1810 ObserverNode node = mChildren.get(i); 1811 if (node.mName.equals(segment)) { 1812 node.addObserverLocked(uri, index + 1, observer, notifyForDescendants, 1813 observersLock, uid, pid, userHandle); 1814 return; 1815 } 1816 } 1817 1818 // No child found, create one 1819 ObserverNode node = new ObserverNode(segment); 1820 mChildren.add(node); 1821 node.addObserverLocked(uri, index + 1, observer, notifyForDescendants, 1822 observersLock, uid, pid, userHandle); 1823 } 1824 removeObserverLocked(IContentObserver observer)1825 public boolean removeObserverLocked(IContentObserver observer) { 1826 int size = mChildren.size(); 1827 for (int i = 0; i < size; i++) { 1828 boolean empty = mChildren.get(i).removeObserverLocked(observer); 1829 if (empty) { 1830 mChildren.remove(i); 1831 i--; 1832 size--; 1833 } 1834 } 1835 1836 IBinder observerBinder = observer.asBinder(); 1837 size = mObservers.size(); 1838 for (int i = 0; i < size; i++) { 1839 ObserverEntry entry = mObservers.get(i); 1840 if (entry.observer.asBinder() == observerBinder) { 1841 mObservers.remove(i); 1842 // We no longer need to listen for death notifications. Remove it. 1843 sObserverDeathDispatcher.unlinkToDeath(observer, entry); 1844 break; 1845 } 1846 } 1847 1848 if (mChildren.size() == 0 && mObservers.size() == 0) { 1849 return true; 1850 } 1851 return false; 1852 } 1853 collectMyObserversLocked(Uri uri, boolean leaf, IContentObserver observer, boolean observerWantsSelfNotifications, int flags, int targetUserHandle, ObserverCollector collector)1854 private void collectMyObserversLocked(Uri uri, boolean leaf, IContentObserver observer, 1855 boolean observerWantsSelfNotifications, int flags, 1856 int targetUserHandle, ObserverCollector collector) { 1857 int N = mObservers.size(); 1858 IBinder observerBinder = observer == null ? null : observer.asBinder(); 1859 for (int i = 0; i < N; i++) { 1860 ObserverEntry entry = mObservers.get(i); 1861 1862 // Don't notify the observer if it sent the notification and isn't interested 1863 // in self notifications 1864 boolean selfChange = (entry.observer.asBinder() == observerBinder); 1865 if (selfChange && !observerWantsSelfNotifications) { 1866 continue; 1867 } 1868 1869 // Does this observer match the target user? 1870 if (targetUserHandle == UserHandle.USER_ALL 1871 || entry.userHandle == UserHandle.USER_ALL 1872 || targetUserHandle == entry.userHandle) { 1873 // Make sure the observer is interested in the notification 1874 if (leaf) { 1875 // If we are at the leaf: we always report, unless the sender has asked 1876 // to skip observers that are notifying for descendants (since they will 1877 // be sending another more specific URI for them). 1878 if ((flags&ContentResolver.NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS) != 0 1879 && entry.notifyForDescendants) { 1880 if (DEBUG) Slog.d(TAG, "Skipping " + entry.observer 1881 + ": skip notify for descendants"); 1882 continue; 1883 } 1884 } else { 1885 // If we are not at the leaf: we report if the observer says it wants 1886 // to be notified for all descendants. 1887 if (!entry.notifyForDescendants) { 1888 if (DEBUG) Slog.d(TAG, "Skipping " + entry.observer 1889 + ": not monitor descendants"); 1890 continue; 1891 } 1892 } 1893 if (DEBUG) Slog.d(TAG, "Reporting to " + entry.observer + ": leaf=" + leaf 1894 + " flags=" + Integer.toHexString(flags) 1895 + " desc=" + entry.notifyForDescendants); 1896 collector.collect(entry.observer, entry.uid, selfChange, uri, flags, 1897 targetUserHandle); 1898 } 1899 } 1900 } 1901 1902 @VisibleForTesting collectObserversLocked(Uri uri, int index, IContentObserver observer, boolean observerWantsSelfNotifications, int flags, int targetUserHandle, ObserverCollector collector)1903 public void collectObserversLocked(Uri uri, int index, 1904 IContentObserver observer, boolean observerWantsSelfNotifications, int flags, 1905 int targetUserHandle, ObserverCollector collector) { 1906 collectObserversLocked(uri, countUriSegments(uri), index, observer, 1907 observerWantsSelfNotifications, flags, targetUserHandle, collector); 1908 } 1909 1910 /** 1911 * targetUserHandle is either a hard user handle or is USER_ALL 1912 */ collectObserversLocked(Uri uri, int segmentCount, int index, IContentObserver observer, boolean observerWantsSelfNotifications, int flags, int targetUserHandle, ObserverCollector collector)1913 public void collectObserversLocked(Uri uri, int segmentCount, int index, 1914 IContentObserver observer, boolean observerWantsSelfNotifications, int flags, 1915 int targetUserHandle, ObserverCollector collector) { 1916 String segment = null; 1917 if (index >= segmentCount) { 1918 // This is the leaf node, notify all observers 1919 if (DEBUG) Slog.d(TAG, "Collecting leaf observers @ #" + index + ", node " + mName); 1920 collectMyObserversLocked(uri, true, observer, observerWantsSelfNotifications, 1921 flags, targetUserHandle, collector); 1922 } else if (index < segmentCount){ 1923 segment = getUriSegment(uri, index); 1924 if (DEBUG) Slog.d(TAG, "Collecting non-leaf observers @ #" + index + " / " 1925 + segment); 1926 // Notify any observers at this level who are interested in descendants 1927 collectMyObserversLocked(uri, false, observer, observerWantsSelfNotifications, 1928 flags, targetUserHandle, collector); 1929 } 1930 1931 int N = mChildren.size(); 1932 for (int i = 0; i < N; i++) { 1933 ObserverNode node = mChildren.get(i); 1934 if (segment == null || node.mName.equals(segment)) { 1935 // We found the child, 1936 node.collectObserversLocked(uri, segmentCount, index + 1, observer, 1937 observerWantsSelfNotifications, flags, targetUserHandle, collector); 1938 if (segment != null) { 1939 break; 1940 } 1941 } 1942 } 1943 } 1944 } 1945 enforceShell(String method)1946 private void enforceShell(String method) { 1947 final int callingUid = Binder.getCallingUid(); 1948 if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) { 1949 throw new SecurityException("Non-shell user attempted to call " + method); 1950 } 1951 } 1952 1953 @Override resetTodayStats()1954 public void resetTodayStats() { 1955 enforceShell("resetTodayStats"); 1956 1957 if (mSyncManager != null) { 1958 final long token = Binder.clearCallingIdentity(); 1959 try { 1960 mSyncManager.resetTodayStats(); 1961 } finally { 1962 Binder.restoreCallingIdentity(token); 1963 } 1964 } 1965 } 1966 1967 @Override onDbCorruption(String tag, String message, String stacktrace)1968 public void onDbCorruption(String tag, String message, String stacktrace) { 1969 Slog.e(tag, message); 1970 Slog.e(tag, "at " + stacktrace); 1971 1972 // TODO: Figure out a better way to report it. b/117886381 1973 Slog.wtf(tag, message); 1974 } 1975 1976 @Override onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)1977 public void onShellCommand(FileDescriptor in, FileDescriptor out, 1978 FileDescriptor err, String[] args, ShellCallback callback, 1979 ResultReceiver resultReceiver) { 1980 (new ContentShellCommand(this)).exec(this, in, out, err, args, callback, resultReceiver); 1981 } 1982 } 1983