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