PageRenderTime 77ms CodeModel.GetById 39ms RepoModel.GetById 0ms app.codeStats 1ms

/services/core/java/com/android/server/content/ContentService.java

https://gitlab.com/amardeep434/android_frameworks_base_n
Java | 1180 lines | 919 code | 100 blank | 161 comment | 175 complexity | 5de753690aedcbf14b964c0bac2f35c7 MD5 | raw file
  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. package com.android.server.content;
  17. import android.Manifest;
  18. import android.accounts.Account;
  19. import android.app.ActivityManager;
  20. import android.content.ComponentName;
  21. import android.content.ContentResolver;
  22. import android.content.Context;
  23. import android.content.IContentService;
  24. import android.content.Intent;
  25. import android.content.ISyncStatusObserver;
  26. import android.content.PeriodicSync;
  27. import android.content.SyncAdapterType;
  28. import android.content.SyncInfo;
  29. import android.content.SyncRequest;
  30. import android.content.SyncStatusInfo;
  31. import android.content.pm.PackageManager;
  32. import android.content.pm.PackageManagerInternal;
  33. import android.database.IContentObserver;
  34. import android.database.sqlite.SQLiteException;
  35. import android.net.Uri;
  36. import android.os.Binder;
  37. import android.os.Bundle;
  38. import android.os.IBinder;
  39. import android.os.Parcel;
  40. import android.os.RemoteException;
  41. import android.os.ServiceManager;
  42. import android.os.SystemProperties;
  43. import android.os.UserHandle;
  44. import android.text.TextUtils;
  45. import android.util.Log;
  46. import android.util.Slog;
  47. import android.util.SparseIntArray;
  48. import com.android.server.LocalServices;
  49. import java.io.FileDescriptor;
  50. import java.io.PrintWriter;
  51. import java.security.InvalidParameterException;
  52. import java.util.ArrayList;
  53. import java.util.Collections;
  54. import java.util.Comparator;
  55. import java.util.List;
  56. /**
  57. * {@hide}
  58. */
  59. public final class ContentService extends IContentService.Stub {
  60. private static final String TAG = "ContentService";
  61. private Context mContext;
  62. private boolean mFactoryTest;
  63. private final ObserverNode mRootNode = new ObserverNode("");
  64. private SyncManager mSyncManager = null;
  65. private final Object mSyncManagerLock = new Object();
  66. private SyncManager getSyncManager() {
  67. if (SystemProperties.getBoolean("config.disable_network", false)) {
  68. return null;
  69. }
  70. synchronized(mSyncManagerLock) {
  71. try {
  72. // Try to create the SyncManager, return null if it fails (e.g. the disk is full).
  73. if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest);
  74. } catch (SQLiteException e) {
  75. Log.e(TAG, "Can't create SyncManager", e);
  76. }
  77. return mSyncManager;
  78. }
  79. }
  80. @Override
  81. protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
  82. mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP,
  83. "caller doesn't have the DUMP permission");
  84. // This makes it so that future permission checks will be in the context of this
  85. // process rather than the caller's process. We will restore this before returning.
  86. long identityToken = clearCallingIdentity();
  87. try {
  88. if (mSyncManager == null) {
  89. pw.println("No SyncManager created! (Disk full?)");
  90. } else {
  91. mSyncManager.dump(fd, pw);
  92. }
  93. pw.println();
  94. pw.println("Observer tree:");
  95. synchronized (mRootNode) {
  96. int[] counts = new int[2];
  97. final SparseIntArray pidCounts = new SparseIntArray();
  98. mRootNode.dumpLocked(fd, pw, args, "", " ", counts, pidCounts);
  99. pw.println();
  100. ArrayList<Integer> sorted = new ArrayList<Integer>();
  101. for (int i=0; i<pidCounts.size(); i++) {
  102. sorted.add(pidCounts.keyAt(i));
  103. }
  104. Collections.sort(sorted, new Comparator<Integer>() {
  105. @Override
  106. public int compare(Integer lhs, Integer rhs) {
  107. int lc = pidCounts.get(lhs);
  108. int rc = pidCounts.get(rhs);
  109. if (lc < rc) {
  110. return 1;
  111. } else if (lc > rc) {
  112. return -1;
  113. }
  114. return 0;
  115. }
  116. });
  117. for (int i=0; i<sorted.size(); i++) {
  118. int pid = sorted.get(i);
  119. pw.print(" pid "); pw.print(pid); pw.print(": ");
  120. pw.print(pidCounts.get(pid)); pw.println(" observers");
  121. }
  122. pw.println();
  123. pw.print(" Total number of nodes: "); pw.println(counts[0]);
  124. pw.print(" Total number of observers: "); pw.println(counts[1]);
  125. }
  126. } finally {
  127. restoreCallingIdentity(identityToken);
  128. }
  129. }
  130. @Override
  131. public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
  132. throws RemoteException {
  133. try {
  134. return super.onTransact(code, data, reply, flags);
  135. } catch (RuntimeException e) {
  136. // The content service only throws security exceptions, so let's
  137. // log all others.
  138. if (!(e instanceof SecurityException)) {
  139. Slog.wtf(TAG, "Content Service Crash", e);
  140. }
  141. throw e;
  142. }
  143. }
  144. /*package*/ ContentService(Context context, boolean factoryTest) {
  145. mContext = context;
  146. mFactoryTest = factoryTest;
  147. // Let the package manager query for the sync adapters for a given authority
  148. // as we grant default permissions to sync adapters for specific authorities.
  149. PackageManagerInternal packageManagerInternal = LocalServices.getService(
  150. PackageManagerInternal.class);
  151. packageManagerInternal.setSyncAdapterPackagesprovider(
  152. new PackageManagerInternal.SyncAdapterPackagesProvider() {
  153. @Override
  154. public String[] getPackages(String authority, int userId) {
  155. return getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
  156. }
  157. });
  158. }
  159. public void systemReady() {
  160. getSyncManager();
  161. }
  162. /**
  163. * Register a content observer tied to a specific user's view of the provider.
  164. * @param userHandle the user whose view of the provider is to be observed. May be
  165. * the calling user without requiring any permission, otherwise the caller needs to
  166. * hold the INTERACT_ACROSS_USERS_FULL permission or hold a read uri grant to the uri.
  167. * Pseudousers USER_ALL and USER_CURRENT are properly handled; all other pseudousers
  168. * are forbidden.
  169. */
  170. @Override
  171. public void registerContentObserver(Uri uri, boolean notifyForDescendants,
  172. IContentObserver observer, int userHandle) {
  173. if (observer == null || uri == null) {
  174. throw new IllegalArgumentException("You must pass a valid uri and observer");
  175. }
  176. final int uid = Binder.getCallingUid();
  177. final int pid = Binder.getCallingPid();
  178. final int callingUserHandle = UserHandle.getCallingUserId();
  179. // Registering an observer for any user other than the calling user requires uri grant or
  180. // cross user permission
  181. if (callingUserHandle != userHandle &&
  182. mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
  183. != PackageManager.PERMISSION_GRANTED) {
  184. enforceCrossUserPermission(userHandle,
  185. "no permission to observe other users' provider view");
  186. }
  187. if (userHandle < 0) {
  188. if (userHandle == UserHandle.USER_CURRENT) {
  189. userHandle = ActivityManager.getCurrentUser();
  190. } else if (userHandle != UserHandle.USER_ALL) {
  191. throw new InvalidParameterException("Bad user handle for registerContentObserver: "
  192. + userHandle);
  193. }
  194. }
  195. synchronized (mRootNode) {
  196. mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
  197. uid, pid, userHandle);
  198. if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
  199. " with notifyForDescendants " + notifyForDescendants);
  200. }
  201. }
  202. public void registerContentObserver(Uri uri, boolean notifyForDescendants,
  203. IContentObserver observer) {
  204. registerContentObserver(uri, notifyForDescendants, observer,
  205. UserHandle.getCallingUserId());
  206. }
  207. public void unregisterContentObserver(IContentObserver observer) {
  208. if (observer == null) {
  209. throw new IllegalArgumentException("You must pass a valid observer");
  210. }
  211. synchronized (mRootNode) {
  212. mRootNode.removeObserverLocked(observer);
  213. if (false) Log.v(TAG, "Unregistered observer " + observer);
  214. }
  215. }
  216. /**
  217. * Notify observers of a particular user's view of the provider.
  218. * @param userHandle the user whose view of the provider is to be notified. May be
  219. * the calling user without requiring any permission, otherwise the caller needs to
  220. * hold the INTERACT_ACROSS_USERS_FULL permission or hold a write uri grant to the uri.
  221. * Pseudousers USER_ALL and USER_CURRENT are properly interpreted; no other pseudousers are
  222. * allowed.
  223. */
  224. @Override
  225. public void notifyChange(Uri uri, IContentObserver observer,
  226. boolean observerWantsSelfNotifications, boolean syncToNetwork,
  227. int userHandle) {
  228. if (Log.isLoggable(TAG, Log.VERBOSE)) {
  229. Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle
  230. + " from observer " + observer + ", syncToNetwork " + syncToNetwork);
  231. }
  232. final int uid = Binder.getCallingUid();
  233. final int pid = Binder.getCallingPid();
  234. final int callingUserHandle = UserHandle.getCallingUserId();
  235. // Notify for any user other than the caller requires uri grant or cross user permission
  236. if (callingUserHandle != userHandle &&
  237. mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
  238. != PackageManager.PERMISSION_GRANTED) {
  239. enforceCrossUserPermission(userHandle, "no permission to notify other users");
  240. }
  241. // We passed the permission check; resolve pseudouser targets as appropriate
  242. if (userHandle < 0) {
  243. if (userHandle == UserHandle.USER_CURRENT) {
  244. userHandle = ActivityManager.getCurrentUser();
  245. } else if (userHandle != UserHandle.USER_ALL) {
  246. throw new InvalidParameterException("Bad user handle for notifyChange: "
  247. + userHandle);
  248. }
  249. }
  250. // This makes it so that future permission checks will be in the context of this
  251. // process rather than the caller's process. We will restore this before returning.
  252. long identityToken = clearCallingIdentity();
  253. try {
  254. ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
  255. synchronized (mRootNode) {
  256. mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
  257. userHandle, calls);
  258. }
  259. final int numCalls = calls.size();
  260. for (int i=0; i<numCalls; i++) {
  261. ObserverCall oc = calls.get(i);
  262. try {
  263. oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
  264. if (Log.isLoggable(TAG, Log.VERBOSE)) {
  265. Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri);
  266. }
  267. } catch (RemoteException ex) {
  268. synchronized (mRootNode) {
  269. Log.w(TAG, "Found dead observer, removing");
  270. IBinder binder = oc.mObserver.asBinder();
  271. final ArrayList<ObserverNode.ObserverEntry> list
  272. = oc.mNode.mObservers;
  273. int numList = list.size();
  274. for (int j=0; j<numList; j++) {
  275. ObserverNode.ObserverEntry oe = list.get(j);
  276. if (oe.observer.asBinder() == binder) {
  277. list.remove(j);
  278. j--;
  279. numList--;
  280. }
  281. }
  282. }
  283. }
  284. }
  285. if (syncToNetwork) {
  286. SyncManager syncManager = getSyncManager();
  287. if (syncManager != null) {
  288. syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, uid,
  289. uri.getAuthority());
  290. }
  291. }
  292. } finally {
  293. restoreCallingIdentity(identityToken);
  294. }
  295. }
  296. public void notifyChange(Uri uri, IContentObserver observer,
  297. boolean observerWantsSelfNotifications, boolean syncToNetwork) {
  298. notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork,
  299. UserHandle.getCallingUserId());
  300. }
  301. /**
  302. * Hide this class since it is not part of api,
  303. * but current unittest framework requires it to be public
  304. * @hide
  305. *
  306. */
  307. public static final class ObserverCall {
  308. final ObserverNode mNode;
  309. final IContentObserver mObserver;
  310. final boolean mSelfChange;
  311. ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange) {
  312. mNode = node;
  313. mObserver = observer;
  314. mSelfChange = selfChange;
  315. }
  316. }
  317. public void requestSync(Account account, String authority, Bundle extras) {
  318. ContentResolver.validateSyncExtrasBundle(extras);
  319. int userId = UserHandle.getCallingUserId();
  320. int uId = Binder.getCallingUid();
  321. // This makes it so that future permission checks will be in the context of this
  322. // process rather than the caller's process. We will restore this before returning.
  323. long identityToken = clearCallingIdentity();
  324. try {
  325. SyncManager syncManager = getSyncManager();
  326. if (syncManager != null) {
  327. syncManager.scheduleSync(account, userId, uId, authority, extras,
  328. 0 /* no delay */, 0 /* no delay */,
  329. false /* onlyThoseWithUnkownSyncableState */);
  330. }
  331. } finally {
  332. restoreCallingIdentity(identityToken);
  333. }
  334. }
  335. /**
  336. * Request a sync with a generic {@link android.content.SyncRequest} object. This will be
  337. * either:
  338. * periodic OR one-off sync.
  339. * and
  340. * anonymous OR provider sync.
  341. * Depending on the request, we enqueue to suit in the SyncManager.
  342. * @param request The request object. Validation of this object is done by its builder.
  343. */
  344. public void sync(SyncRequest request) {
  345. syncAsUser(request, UserHandle.getCallingUserId());
  346. }
  347. /**
  348. * If the user id supplied is different to the calling user, the caller must hold the
  349. * INTERACT_ACROSS_USERS_FULL permission.
  350. */
  351. public void syncAsUser(SyncRequest request, int userId) {
  352. enforceCrossUserPermission(userId, "no permission to request sync as user: " + userId);
  353. int callerUid = Binder.getCallingUid();
  354. // This makes it so that future permission checks will be in the context of this
  355. // process rather than the caller's process. We will restore this before returning.
  356. long identityToken = clearCallingIdentity();
  357. try {
  358. SyncManager syncManager = getSyncManager();
  359. if (syncManager == null) {
  360. return;
  361. }
  362. Bundle extras = request.getBundle();
  363. long flextime = request.getSyncFlexTime();
  364. long runAtTime = request.getSyncRunTime();
  365. if (request.isPeriodic()) {
  366. mContext.enforceCallingOrSelfPermission(
  367. Manifest.permission.WRITE_SYNC_SETTINGS,
  368. "no permission to write the sync settings");
  369. SyncStorageEngine.EndPoint info;
  370. info = new SyncStorageEngine.EndPoint(
  371. request.getAccount(), request.getProvider(), userId);
  372. if (runAtTime < 60) {
  373. Slog.w(TAG, "Requested poll frequency of " + runAtTime
  374. + " seconds being rounded up to 60 seconds.");
  375. runAtTime = 60;
  376. }
  377. // Schedule periodic sync.
  378. getSyncManager().getSyncStorageEngine()
  379. .updateOrAddPeriodicSync(info, runAtTime, flextime, extras);
  380. } else {
  381. long beforeRuntimeMillis = (flextime) * 1000;
  382. long runtimeMillis = runAtTime * 1000;
  383. syncManager.scheduleSync(
  384. request.getAccount(), userId, callerUid, request.getProvider(), extras,
  385. beforeRuntimeMillis, runtimeMillis,
  386. false /* onlyThoseWithUnknownSyncableState */);
  387. }
  388. } finally {
  389. restoreCallingIdentity(identityToken);
  390. }
  391. }
  392. /**
  393. * Clear all scheduled sync operations that match the uri and cancel the active sync
  394. * if they match the authority and account, if they are present.
  395. *
  396. * @param account filter the pending and active syncs to cancel using this account, or null.
  397. * @param authority filter the pending and active syncs to cancel using this authority, or
  398. * null.
  399. * @param cname cancel syncs running on this service, or null for provider/account.
  400. */
  401. @Override
  402. public void cancelSync(Account account, String authority, ComponentName cname) {
  403. cancelSyncAsUser(account, authority, cname, UserHandle.getCallingUserId());
  404. }
  405. /**
  406. * Clear all scheduled sync operations that match the uri and cancel the active sync
  407. * if they match the authority and account, if they are present.
  408. *
  409. * <p> If the user id supplied is different to the calling user, the caller must hold the
  410. * INTERACT_ACROSS_USERS_FULL permission.
  411. *
  412. * @param account filter the pending and active syncs to cancel using this account, or null.
  413. * @param authority filter the pending and active syncs to cancel using this authority, or
  414. * null.
  415. * @param userId the user id for which to cancel sync operations.
  416. * @param cname cancel syncs running on this service, or null for provider/account.
  417. */
  418. @Override
  419. public void cancelSyncAsUser(Account account, String authority, ComponentName cname,
  420. int userId) {
  421. if (authority != null && authority.length() == 0) {
  422. throw new IllegalArgumentException("Authority must be non-empty");
  423. }
  424. enforceCrossUserPermission(userId,
  425. "no permission to modify the sync settings for user " + userId);
  426. // This makes it so that future permission checks will be in the context of this
  427. // process rather than the caller's process. We will restore this before returning.
  428. long identityToken = clearCallingIdentity();
  429. try {
  430. SyncManager syncManager = getSyncManager();
  431. if (syncManager != null) {
  432. SyncStorageEngine.EndPoint info;
  433. if (cname == null) {
  434. info = new SyncStorageEngine.EndPoint(account, authority, userId);
  435. } else {
  436. info = new SyncStorageEngine.EndPoint(cname, userId);
  437. }
  438. syncManager.clearScheduledSyncOperations(info);
  439. syncManager.cancelActiveSync(info, null /* all syncs for this adapter */);
  440. }
  441. } finally {
  442. restoreCallingIdentity(identityToken);
  443. }
  444. }
  445. public void cancelRequest(SyncRequest request) {
  446. SyncManager syncManager = getSyncManager();
  447. if (syncManager == null) return;
  448. int userId = UserHandle.getCallingUserId();
  449. long identityToken = clearCallingIdentity();
  450. try {
  451. SyncStorageEngine.EndPoint info;
  452. Bundle extras = new Bundle(request.getBundle());
  453. Account account = request.getAccount();
  454. String provider = request.getProvider();
  455. info = new SyncStorageEngine.EndPoint(account, provider, userId);
  456. if (request.isPeriodic()) {
  457. // Remove periodic sync.
  458. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  459. "no permission to write the sync settings");
  460. getSyncManager().getSyncStorageEngine().removePeriodicSync(info, extras);
  461. }
  462. // Cancel active syncs and clear pending syncs from the queue.
  463. syncManager.cancelScheduledSyncOperation(info, extras);
  464. syncManager.cancelActiveSync(info, extras);
  465. } finally {
  466. restoreCallingIdentity(identityToken);
  467. }
  468. }
  469. /**
  470. * Get information about the SyncAdapters that are known to the system.
  471. * @return an array of SyncAdapters that have registered with the system
  472. */
  473. @Override
  474. public SyncAdapterType[] getSyncAdapterTypes() {
  475. return getSyncAdapterTypesAsUser(UserHandle.getCallingUserId());
  476. }
  477. /**
  478. * Get information about the SyncAdapters that are known to the system for a particular user.
  479. *
  480. * <p> If the user id supplied is different to the calling user, the caller must hold the
  481. * INTERACT_ACROSS_USERS_FULL permission.
  482. *
  483. * @return an array of SyncAdapters that have registered with the system
  484. */
  485. @Override
  486. public SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) {
  487. enforceCrossUserPermission(userId,
  488. "no permission to read sync settings for user " + userId);
  489. // This makes it so that future permission checks will be in the context of this
  490. // process rather than the caller's process. We will restore this before returning.
  491. final long identityToken = clearCallingIdentity();
  492. try {
  493. SyncManager syncManager = getSyncManager();
  494. return syncManager.getSyncAdapterTypes(userId);
  495. } finally {
  496. restoreCallingIdentity(identityToken);
  497. }
  498. }
  499. @Override
  500. public String[] getSyncAdapterPackagesForAuthorityAsUser(String authority, int userId) {
  501. enforceCrossUserPermission(userId,
  502. "no permission to read sync settings for user " + userId);
  503. // This makes it so that future permission checks will be in the context of this
  504. // process rather than the caller's process. We will restore this before returning.
  505. final long identityToken = clearCallingIdentity();
  506. try {
  507. SyncManager syncManager = getSyncManager();
  508. return syncManager.getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
  509. } finally {
  510. restoreCallingIdentity(identityToken);
  511. }
  512. }
  513. @Override
  514. public boolean getSyncAutomatically(Account account, String providerName) {
  515. return getSyncAutomaticallyAsUser(account, providerName, UserHandle.getCallingUserId());
  516. }
  517. /**
  518. * If the user id supplied is different to the calling user, the caller must hold the
  519. * INTERACT_ACROSS_USERS_FULL permission.
  520. */
  521. @Override
  522. public boolean getSyncAutomaticallyAsUser(Account account, String providerName, int userId) {
  523. enforceCrossUserPermission(userId,
  524. "no permission to read the sync settings for user " + userId);
  525. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  526. "no permission to read the sync settings");
  527. long identityToken = clearCallingIdentity();
  528. try {
  529. SyncManager syncManager = getSyncManager();
  530. if (syncManager != null) {
  531. return syncManager.getSyncStorageEngine()
  532. .getSyncAutomatically(account, userId, providerName);
  533. }
  534. } finally {
  535. restoreCallingIdentity(identityToken);
  536. }
  537. return false;
  538. }
  539. @Override
  540. public void setSyncAutomatically(Account account, String providerName, boolean sync) {
  541. setSyncAutomaticallyAsUser(account, providerName, sync, UserHandle.getCallingUserId());
  542. }
  543. @Override
  544. public void setSyncAutomaticallyAsUser(Account account, String providerName, boolean sync,
  545. int userId) {
  546. if (TextUtils.isEmpty(providerName)) {
  547. throw new IllegalArgumentException("Authority must be non-empty");
  548. }
  549. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  550. "no permission to write the sync settings");
  551. enforceCrossUserPermission(userId,
  552. "no permission to modify the sync settings for user " + userId);
  553. long identityToken = clearCallingIdentity();
  554. try {
  555. SyncManager syncManager = getSyncManager();
  556. if (syncManager != null) {
  557. syncManager.getSyncStorageEngine().setSyncAutomatically(account, userId,
  558. providerName, sync);
  559. }
  560. } finally {
  561. restoreCallingIdentity(identityToken);
  562. }
  563. }
  564. /** Old API. Schedule periodic sync with default flex time. */
  565. @Override
  566. public void addPeriodicSync(Account account, String authority, Bundle extras,
  567. long pollFrequency) {
  568. if (account == null) {
  569. throw new IllegalArgumentException("Account must not be null");
  570. }
  571. if (TextUtils.isEmpty(authority)) {
  572. throw new IllegalArgumentException("Authority must not be empty.");
  573. }
  574. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  575. "no permission to write the sync settings");
  576. int userId = UserHandle.getCallingUserId();
  577. if (pollFrequency < 60) {
  578. Slog.w(TAG, "Requested poll frequency of " + pollFrequency
  579. + " seconds being rounded up to 60 seconds.");
  580. pollFrequency = 60;
  581. }
  582. long defaultFlex = SyncStorageEngine.calculateDefaultFlexTime(pollFrequency);
  583. long identityToken = clearCallingIdentity();
  584. try {
  585. SyncStorageEngine.EndPoint info =
  586. new SyncStorageEngine.EndPoint(account, authority, userId);
  587. getSyncManager().getSyncStorageEngine()
  588. .updateOrAddPeriodicSync(info,
  589. pollFrequency,
  590. defaultFlex,
  591. extras);
  592. } finally {
  593. restoreCallingIdentity(identityToken);
  594. }
  595. }
  596. public void removePeriodicSync(Account account, String authority, Bundle extras) {
  597. if (account == null) {
  598. throw new IllegalArgumentException("Account must not be null");
  599. }
  600. if (TextUtils.isEmpty(authority)) {
  601. throw new IllegalArgumentException("Authority must not be empty");
  602. }
  603. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  604. "no permission to write the sync settings");
  605. int userId = UserHandle.getCallingUserId();
  606. long identityToken = clearCallingIdentity();
  607. try {
  608. getSyncManager().getSyncStorageEngine()
  609. .removePeriodicSync(
  610. new SyncStorageEngine.EndPoint(account, authority, userId),
  611. extras);
  612. } finally {
  613. restoreCallingIdentity(identityToken);
  614. }
  615. }
  616. public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName,
  617. ComponentName cname) {
  618. if (account == null) {
  619. throw new IllegalArgumentException("Account must not be null");
  620. }
  621. if (TextUtils.isEmpty(providerName)) {
  622. throw new IllegalArgumentException("Authority must not be empty");
  623. }
  624. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  625. "no permission to read the sync settings");
  626. int userId = UserHandle.getCallingUserId();
  627. long identityToken = clearCallingIdentity();
  628. try {
  629. return getSyncManager().getSyncStorageEngine().getPeriodicSyncs(
  630. new SyncStorageEngine.EndPoint(account, providerName, userId));
  631. } finally {
  632. restoreCallingIdentity(identityToken);
  633. }
  634. }
  635. public int getIsSyncable(Account account, String providerName) {
  636. return getIsSyncableAsUser(account, providerName, UserHandle.getCallingUserId());
  637. }
  638. /**
  639. * If the user id supplied is different to the calling user, the caller must hold the
  640. * INTERACT_ACROSS_USERS_FULL permission.
  641. */
  642. public int getIsSyncableAsUser(Account account, String providerName, int userId) {
  643. enforceCrossUserPermission(userId,
  644. "no permission to read the sync settings for user " + userId);
  645. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  646. "no permission to read the sync settings");
  647. long identityToken = clearCallingIdentity();
  648. try {
  649. SyncManager syncManager = getSyncManager();
  650. if (syncManager != null) {
  651. return syncManager.getIsSyncable(
  652. account, userId, providerName);
  653. }
  654. } finally {
  655. restoreCallingIdentity(identityToken);
  656. }
  657. return -1;
  658. }
  659. public void setIsSyncable(Account account, String providerName, int syncable) {
  660. if (TextUtils.isEmpty(providerName)) {
  661. throw new IllegalArgumentException("Authority must not be empty");
  662. }
  663. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  664. "no permission to write the sync settings");
  665. int userId = UserHandle.getCallingUserId();
  666. long identityToken = clearCallingIdentity();
  667. try {
  668. SyncManager syncManager = getSyncManager();
  669. if (syncManager != null) {
  670. syncManager.getSyncStorageEngine().setIsSyncable(
  671. account, userId, providerName, syncable);
  672. }
  673. } finally {
  674. restoreCallingIdentity(identityToken);
  675. }
  676. }
  677. @Override
  678. public boolean getMasterSyncAutomatically() {
  679. return getMasterSyncAutomaticallyAsUser(UserHandle.getCallingUserId());
  680. }
  681. /**
  682. * If the user id supplied is different to the calling user, the caller must hold the
  683. * INTERACT_ACROSS_USERS_FULL permission.
  684. */
  685. @Override
  686. public boolean getMasterSyncAutomaticallyAsUser(int userId) {
  687. enforceCrossUserPermission(userId,
  688. "no permission to read the sync settings for user " + userId);
  689. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  690. "no permission to read the sync settings");
  691. long identityToken = clearCallingIdentity();
  692. try {
  693. SyncManager syncManager = getSyncManager();
  694. if (syncManager != null) {
  695. return syncManager.getSyncStorageEngine().getMasterSyncAutomatically(userId);
  696. }
  697. } finally {
  698. restoreCallingIdentity(identityToken);
  699. }
  700. return false;
  701. }
  702. @Override
  703. public void setMasterSyncAutomatically(boolean flag) {
  704. setMasterSyncAutomaticallyAsUser(flag, UserHandle.getCallingUserId());
  705. }
  706. @Override
  707. public void setMasterSyncAutomaticallyAsUser(boolean flag, int userId) {
  708. enforceCrossUserPermission(userId,
  709. "no permission to set the sync status for user " + userId);
  710. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  711. "no permission to write the sync settings");
  712. long identityToken = clearCallingIdentity();
  713. try {
  714. SyncManager syncManager = getSyncManager();
  715. if (syncManager != null) {
  716. syncManager.getSyncStorageEngine().setMasterSyncAutomatically(flag, userId);
  717. }
  718. } finally {
  719. restoreCallingIdentity(identityToken);
  720. }
  721. }
  722. public boolean isSyncActive(Account account, String authority, ComponentName cname) {
  723. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  724. "no permission to read the sync stats");
  725. int userId = UserHandle.getCallingUserId();
  726. int callingUid = Binder.getCallingUid();
  727. long identityToken = clearCallingIdentity();
  728. try {
  729. SyncManager syncManager = getSyncManager();
  730. if (syncManager == null) {
  731. return false;
  732. }
  733. return syncManager.getSyncStorageEngine().isSyncActive(
  734. new SyncStorageEngine.EndPoint(account, authority, userId));
  735. } finally {
  736. restoreCallingIdentity(identityToken);
  737. }
  738. }
  739. public List<SyncInfo> getCurrentSyncs() {
  740. return getCurrentSyncsAsUser(UserHandle.getCallingUserId());
  741. }
  742. /**
  743. * If the user id supplied is different to the calling user, the caller must hold the
  744. * INTERACT_ACROSS_USERS_FULL permission.
  745. */
  746. public List<SyncInfo> getCurrentSyncsAsUser(int userId) {
  747. enforceCrossUserPermission(userId,
  748. "no permission to read the sync settings for user " + userId);
  749. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  750. "no permission to read the sync stats");
  751. final boolean canAccessAccounts =
  752. mContext.checkCallingOrSelfPermission(Manifest.permission.GET_ACCOUNTS)
  753. == PackageManager.PERMISSION_GRANTED;
  754. long identityToken = clearCallingIdentity();
  755. try {
  756. return getSyncManager().getSyncStorageEngine()
  757. .getCurrentSyncsCopy(userId, canAccessAccounts);
  758. } finally {
  759. restoreCallingIdentity(identityToken);
  760. }
  761. }
  762. public SyncStatusInfo getSyncStatus(Account account, String authority, ComponentName cname) {
  763. return getSyncStatusAsUser(account, authority, cname, UserHandle.getCallingUserId());
  764. }
  765. /**
  766. * If the user id supplied is different to the calling user, the caller must hold the
  767. * INTERACT_ACROSS_USERS_FULL permission.
  768. */
  769. public SyncStatusInfo getSyncStatusAsUser(Account account, String authority,
  770. ComponentName cname, int userId) {
  771. if (TextUtils.isEmpty(authority)) {
  772. throw new IllegalArgumentException("Authority must not be empty");
  773. }
  774. enforceCrossUserPermission(userId,
  775. "no permission to read the sync stats for user " + userId);
  776. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  777. "no permission to read the sync stats");
  778. int callerUid = Binder.getCallingUid();
  779. long identityToken = clearCallingIdentity();
  780. try {
  781. SyncManager syncManager = getSyncManager();
  782. if (syncManager == null) {
  783. return null;
  784. }
  785. SyncStorageEngine.EndPoint info;
  786. if (!(account == null || authority == null)) {
  787. info = new SyncStorageEngine.EndPoint(account, authority, userId);
  788. } else {
  789. throw new IllegalArgumentException("Must call sync status with valid authority");
  790. }
  791. return syncManager.getSyncStorageEngine().getStatusByAuthority(info);
  792. } finally {
  793. restoreCallingIdentity(identityToken);
  794. }
  795. }
  796. public boolean isSyncPending(Account account, String authority, ComponentName cname) {
  797. return isSyncPendingAsUser(account, authority, cname, UserHandle.getCallingUserId());
  798. }
  799. @Override
  800. public boolean isSyncPendingAsUser(Account account, String authority, ComponentName cname,
  801. int userId) {
  802. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  803. "no permission to read the sync stats");
  804. enforceCrossUserPermission(userId,
  805. "no permission to retrieve the sync settings for user " + userId);
  806. int callerUid = Binder.getCallingUid();
  807. long identityToken = clearCallingIdentity();
  808. SyncManager syncManager = getSyncManager();
  809. if (syncManager == null) return false;
  810. try {
  811. SyncStorageEngine.EndPoint info;
  812. if (!(account == null || authority == null)) {
  813. info = new SyncStorageEngine.EndPoint(account, authority, userId);
  814. } else {
  815. throw new IllegalArgumentException("Invalid authority specified");
  816. }
  817. return syncManager.getSyncStorageEngine().isSyncPending(info);
  818. } finally {
  819. restoreCallingIdentity(identityToken);
  820. }
  821. }
  822. public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
  823. long identityToken = clearCallingIdentity();
  824. try {
  825. SyncManager syncManager = getSyncManager();
  826. if (syncManager != null && callback != null) {
  827. syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback);
  828. }
  829. } finally {
  830. restoreCallingIdentity(identityToken);
  831. }
  832. }
  833. public void removeStatusChangeListener(ISyncStatusObserver callback) {
  834. long identityToken = clearCallingIdentity();
  835. try {
  836. SyncManager syncManager = getSyncManager();
  837. if (syncManager != null && callback != null) {
  838. syncManager.getSyncStorageEngine().removeStatusChangeListener(callback);
  839. }
  840. } finally {
  841. restoreCallingIdentity(identityToken);
  842. }
  843. }
  844. public static ContentService main(Context context, boolean factoryTest) {
  845. ContentService service = new ContentService(context, factoryTest);
  846. ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
  847. return service;
  848. }
  849. /**
  850. * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL
  851. * permission, if the userHandle is not for the caller.
  852. *
  853. * @param userHandle the user handle of the user we want to act on behalf of.
  854. * @param message the message to log on security exception.
  855. */
  856. private void enforceCrossUserPermission(int userHandle, String message) {
  857. final int callingUser = UserHandle.getCallingUserId();
  858. if (callingUser != userHandle) {
  859. mContext.enforceCallingOrSelfPermission(
  860. Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
  861. }
  862. }
  863. /**
  864. * Hide this class since it is not part of api,
  865. * but current unittest framework requires it to be public
  866. * @hide
  867. */
  868. public static final class ObserverNode {
  869. private class ObserverEntry implements IBinder.DeathRecipient {
  870. public final IContentObserver observer;
  871. public final int uid;
  872. public final int pid;
  873. public final boolean notifyForDescendants;
  874. private final int userHandle;
  875. private final Object observersLock;
  876. public ObserverEntry(IContentObserver o, boolean n, Object observersLock,
  877. int _uid, int _pid, int _userHandle) {
  878. this.observersLock = observersLock;
  879. observer = o;
  880. uid = _uid;
  881. pid = _pid;
  882. userHandle = _userHandle;
  883. notifyForDescendants = n;
  884. try {
  885. observer.asBinder().linkToDeath(this, 0);
  886. } catch (RemoteException e) {
  887. binderDied();
  888. }
  889. }
  890. public void binderDied() {
  891. synchronized (observersLock) {
  892. removeObserverLocked(observer);
  893. }
  894. }
  895. public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
  896. String name, String prefix, SparseIntArray pidCounts) {
  897. pidCounts.put(pid, pidCounts.get(pid)+1);
  898. pw.print(prefix); pw.print(name); pw.print(": pid=");
  899. pw.print(pid); pw.print(" uid=");
  900. pw.print(uid); pw.print(" user=");
  901. pw.print(userHandle); pw.print(" target=");
  902. pw.println(Integer.toHexString(System.identityHashCode(
  903. observer != null ? observer.asBinder() : null)));
  904. }
  905. }
  906. public static final int INSERT_TYPE = 0;
  907. public static final int UPDATE_TYPE = 1;
  908. public static final int DELETE_TYPE = 2;
  909. private String mName;
  910. private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>();
  911. private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>();
  912. public ObserverNode(String name) {
  913. mName = name;
  914. }
  915. public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
  916. String name, String prefix, int[] counts, SparseIntArray pidCounts) {
  917. String innerName = null;
  918. if (mObservers.size() > 0) {
  919. if ("".equals(name)) {
  920. innerName = mName;
  921. } else {
  922. innerName = name + "/" + mName;
  923. }
  924. for (int i=0; i<mObservers.size(); i++) {
  925. counts[1]++;
  926. mObservers.get(i).dumpLocked(fd, pw, args, innerName, prefix,
  927. pidCounts);
  928. }
  929. }
  930. if (mChildren.size() > 0) {
  931. if (innerName == null) {
  932. if ("".equals(name)) {
  933. innerName = mName;
  934. } else {
  935. innerName = name + "/" + mName;
  936. }
  937. }
  938. for (int i=0; i<mChildren.size(); i++) {
  939. counts[0]++;
  940. mChildren.get(i).dumpLocked(fd, pw, args, innerName, prefix,
  941. counts, pidCounts);
  942. }
  943. }
  944. }
  945. private String getUriSegment(Uri uri, int index) {
  946. if (uri != null) {
  947. if (index == 0) {
  948. return uri.getAuthority();
  949. } else {
  950. return uri.getPathSegments().get(index - 1);
  951. }
  952. } else {
  953. return null;
  954. }
  955. }
  956. private int countUriSegments(Uri uri) {
  957. if (uri == null) {
  958. return 0;
  959. }
  960. return uri.getPathSegments().size() + 1;
  961. }
  962. // Invariant: userHandle is either a hard user number or is USER_ALL
  963. public void addObserverLocked(Uri uri, IContentObserver observer,
  964. boolean notifyForDescendants, Object observersLock,
  965. int uid, int pid, int userHandle) {
  966. addObserverLocked(uri, 0, observer, notifyForDescendants, observersLock,
  967. uid, pid, userHandle);
  968. }
  969. private void addObserverLocked(Uri uri, int index, IContentObserver observer,
  970. boolean notifyForDescendants, Object observersLock,
  971. int uid, int pid, int userHandle) {
  972. // If this is the leaf node add the observer
  973. if (index == countUriSegments(uri)) {
  974. mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,
  975. uid, pid, userHandle));
  976. return;
  977. }
  978. // Look to see if the proper child already exists
  979. String segment = getUriSegment(uri, index);
  980. if (segment == null) {
  981. throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer");
  982. }
  983. int N = mChildren.size();
  984. for (int i = 0; i < N; i++) {
  985. ObserverNode node = mChildren.get(i);
  986. if (node.mName.equals(segment)) {
  987. node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
  988. observersLock, uid, pid, userHandle);
  989. return;
  990. }
  991. }
  992. // No child found, create one
  993. ObserverNode node = new ObserverNode(segment);
  994. mChildren.add(node);
  995. node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
  996. observersLock, uid, pid, userHandle);
  997. }
  998. public boolean removeObserverLocked(IContentObserver observer) {
  999. int size = mChildren.size();
  1000. for (int i = 0; i < size; i++) {
  1001. boolean empty = mChildren.get(i).removeObserverLocked(observer);
  1002. if (empty) {
  1003. mChildren.remove(i);
  1004. i--;
  1005. size--;
  1006. }
  1007. }
  1008. IBinder observerBinder = observer.asBinder();
  1009. size = mObservers.size();
  1010. for (int i = 0; i < size; i++) {
  1011. ObserverEntry entry = mObservers.get(i);
  1012. if (entry.observer.asBinder() == observerBinder) {
  1013. mObservers.remove(i);
  1014. // We no longer need to listen for death notifications. Remove it.
  1015. observerBinder.unlinkToDeath(entry, 0);
  1016. break;
  1017. }
  1018. }
  1019. if (mChildren.size() == 0 && mObservers.size() == 0) {
  1020. return true;
  1021. }
  1022. return false;
  1023. }
  1024. private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
  1025. boolean observerWantsSelfNotifications, int targetUserHandle,
  1026. ArrayList<ObserverCall> calls) {
  1027. int N = mObservers.size();
  1028. IBinder observerBinder = observer == null ? null : observer.asBinder();
  1029. for (int i = 0; i < N; i++) {
  1030. ObserverEntry entry = mObservers.get(i);
  1031. // Don't notify the observer if it sent the notification and isn't interested
  1032. // in self notifications
  1033. boolean selfChange = (entry.observer.asBinder() == observerBinder);
  1034. if (selfChange && !observerWantsSelfNotifications) {
  1035. continue;
  1036. }
  1037. // Does this observer match the target user?
  1038. if (targetUserHandle == UserHandle.USER_ALL
  1039. || entry.userHandle == UserHandle.USER_ALL
  1040. || targetUserHandle == entry.userHandle) {
  1041. // Make sure the observer is interested in the notification
  1042. if (leaf || (!leaf && entry.notifyForDescendants)) {
  1043. calls.add(new ObserverCall(this, entry.observer, selfChange));
  1044. }
  1045. }
  1046. }
  1047. }
  1048. /**
  1049. * targetUserHandle is either a hard user handle or is USER_ALL
  1050. */
  1051. public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
  1052. boolean observerWantsSelfNotifications, int targetUserHandle,
  1053. ArrayList<ObserverCall> calls) {
  1054. String segment = null;
  1055. int segmentCount = countUriSegments(uri);
  1056. if (index >= segmentCount) {
  1057. // This is the leaf node, notify all observers
  1058. collectMyObserversLocked(true, observer, observerWantsSelfNotifications,
  1059. targetUserHandle, calls);
  1060. } else if (index < segmentCount){
  1061. segment = getUriSegment(uri, index);
  1062. // Notify any observers at this level who are interested in descendants
  1063. collectMyObserversLocked(false, observer, observerWantsSelfNotifications,
  1064. targetUserHandle, calls);
  1065. }
  1066. int N = mChildren.size();
  1067. for (int i = 0; i < N; i++) {
  1068. ObserverNode node = mChildren.get(i);
  1069. if (segment == null || node.mName.equals(segment)) {
  1070. // We found the child,
  1071. node.collectObserversLocked(uri, index + 1,
  1072. observer, observerWantsSelfNotifications, targetUserHandle, calls);
  1073. if (segment != null) {
  1074. break;
  1075. }
  1076. }
  1077. }
  1078. }
  1079. }
  1080. }