PageRenderTime 102ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/core/java/android/content/ContentService.java

https://github.com/PapaDocta/android_frameworks_base
Java | 630 lines | 515 code | 53 blank | 62 comment | 93 complexity | 14b850dbf82ba493ca1ea077f72ecfd8 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 android.content;
  17. import android.accounts.Account;
  18. import android.database.IContentObserver;
  19. import android.database.sqlite.SQLiteException;
  20. import android.net.Uri;
  21. import android.os.Bundle;
  22. import android.os.IBinder;
  23. import android.os.Parcel;
  24. import android.os.RemoteException;
  25. import android.os.ServiceManager;
  26. import android.util.Config;
  27. import android.util.Log;
  28. import android.Manifest;
  29. import java.io.FileDescriptor;
  30. import java.io.PrintWriter;
  31. import java.util.ArrayList;
  32. import java.util.List;
  33. /**
  34. * {@hide}
  35. */
  36. public final class ContentService extends IContentService.Stub {
  37. private static final String TAG = "ContentService";
  38. private Context mContext;
  39. private boolean mFactoryTest;
  40. private final ObserverNode mRootNode = new ObserverNode("");
  41. private SyncManager mSyncManager = null;
  42. private final Object mSyncManagerLock = new Object();
  43. private SyncManager getSyncManager() {
  44. synchronized(mSyncManagerLock) {
  45. try {
  46. // Try to create the SyncManager, return null if it fails (e.g. the disk is full).
  47. if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest);
  48. } catch (SQLiteException e) {
  49. Log.e(TAG, "Can't create SyncManager", e);
  50. }
  51. return mSyncManager;
  52. }
  53. }
  54. @Override
  55. protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
  56. mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP,
  57. "caller doesn't have the DUMP permission");
  58. // This makes it so that future permission checks will be in the context of this
  59. // process rather than the caller's process. We will restore this before returning.
  60. long identityToken = clearCallingIdentity();
  61. try {
  62. if (mSyncManager == null) {
  63. pw.println("No SyncManager created! (Disk full?)");
  64. } else {
  65. mSyncManager.dump(fd, pw);
  66. }
  67. } finally {
  68. restoreCallingIdentity(identityToken);
  69. }
  70. }
  71. @Override
  72. public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
  73. throws RemoteException {
  74. try {
  75. return super.onTransact(code, data, reply, flags);
  76. } catch (RuntimeException e) {
  77. // The content service only throws security exceptions, so let's
  78. // log all others.
  79. if (!(e instanceof SecurityException)) {
  80. Log.e(TAG, "Content Service Crash", e);
  81. }
  82. throw e;
  83. }
  84. }
  85. /*package*/ ContentService(Context context, boolean factoryTest) {
  86. mContext = context;
  87. mFactoryTest = factoryTest;
  88. getSyncManager();
  89. }
  90. public void registerContentObserver(Uri uri, boolean notifyForDescendents,
  91. IContentObserver observer) {
  92. if (observer == null || uri == null) {
  93. throw new IllegalArgumentException("You must pass a valid uri and observer");
  94. }
  95. synchronized (mRootNode) {
  96. mRootNode.addObserverLocked(uri, observer, notifyForDescendents, mRootNode);
  97. if (Config.LOGV) Log.v(TAG, "Registered observer " + observer + " at " + uri +
  98. " with notifyForDescendents " + notifyForDescendents);
  99. }
  100. }
  101. public void unregisterContentObserver(IContentObserver observer) {
  102. if (observer == null) {
  103. throw new IllegalArgumentException("You must pass a valid observer");
  104. }
  105. synchronized (mRootNode) {
  106. mRootNode.removeObserverLocked(observer);
  107. if (Config.LOGV) Log.v(TAG, "Unregistered observer " + observer);
  108. }
  109. }
  110. public void notifyChange(Uri uri, IContentObserver observer,
  111. boolean observerWantsSelfNotifications, boolean syncToNetwork) {
  112. if (Log.isLoggable(TAG, Log.VERBOSE)) {
  113. Log.v(TAG, "Notifying update of " + uri + " from observer " + observer
  114. + ", syncToNetwork " + syncToNetwork);
  115. }
  116. // This makes it so that future permission checks will be in the context of this
  117. // process rather than the caller's process. We will restore this before returning.
  118. long identityToken = clearCallingIdentity();
  119. try {
  120. ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
  121. synchronized (mRootNode) {
  122. mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
  123. calls);
  124. }
  125. final int numCalls = calls.size();
  126. for (int i=0; i<numCalls; i++) {
  127. ObserverCall oc = calls.get(i);
  128. try {
  129. oc.mObserver.onChange(oc.mSelfNotify);
  130. if (Log.isLoggable(TAG, Log.VERBOSE)) {
  131. Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri);
  132. }
  133. } catch (RemoteException ex) {
  134. synchronized (mRootNode) {
  135. Log.w(TAG, "Found dead observer, removing");
  136. IBinder binder = oc.mObserver.asBinder();
  137. final ArrayList<ObserverNode.ObserverEntry> list
  138. = oc.mNode.mObservers;
  139. int numList = list.size();
  140. for (int j=0; j<numList; j++) {
  141. ObserverNode.ObserverEntry oe = list.get(j);
  142. if (oe.observer.asBinder() == binder) {
  143. list.remove(j);
  144. j--;
  145. numList--;
  146. }
  147. }
  148. }
  149. }
  150. }
  151. if (syncToNetwork) {
  152. SyncManager syncManager = getSyncManager();
  153. if (syncManager != null) {
  154. syncManager.scheduleLocalSync(null /* all accounts */, uri.getAuthority());
  155. }
  156. }
  157. } finally {
  158. restoreCallingIdentity(identityToken);
  159. }
  160. }
  161. /**
  162. * Hide this class since it is not part of api,
  163. * but current unittest framework requires it to be public
  164. * @hide
  165. *
  166. */
  167. public static final class ObserverCall {
  168. final ObserverNode mNode;
  169. final IContentObserver mObserver;
  170. final boolean mSelfNotify;
  171. ObserverCall(ObserverNode node, IContentObserver observer,
  172. boolean selfNotify) {
  173. mNode = node;
  174. mObserver = observer;
  175. mSelfNotify = selfNotify;
  176. }
  177. }
  178. public void requestSync(Account account, String authority, Bundle extras) {
  179. ContentResolver.validateSyncExtrasBundle(extras);
  180. // This makes it so that future permission checks will be in the context of this
  181. // process rather than the caller's process. We will restore this before returning.
  182. long identityToken = clearCallingIdentity();
  183. try {
  184. SyncManager syncManager = getSyncManager();
  185. if (syncManager != null) {
  186. syncManager.scheduleSync(account, authority, extras, 0 /* no delay */,
  187. false /* onlyThoseWithUnkownSyncableState */);
  188. }
  189. } finally {
  190. restoreCallingIdentity(identityToken);
  191. }
  192. }
  193. /**
  194. * Clear all scheduled sync operations that match the uri and cancel the active sync
  195. * if they match the authority and account, if they are present.
  196. * @param account filter the pending and active syncs to cancel using this account
  197. * @param authority filter the pending and active syncs to cancel using this authority
  198. */
  199. public void cancelSync(Account account, String authority) {
  200. // This makes it so that future permission checks will be in the context of this
  201. // process rather than the caller's process. We will restore this before returning.
  202. long identityToken = clearCallingIdentity();
  203. try {
  204. SyncManager syncManager = getSyncManager();
  205. if (syncManager != null) {
  206. syncManager.clearScheduledSyncOperations(account, authority);
  207. syncManager.cancelActiveSync(account, authority);
  208. }
  209. } finally {
  210. restoreCallingIdentity(identityToken);
  211. }
  212. }
  213. /**
  214. * Get information about the SyncAdapters that are known to the system.
  215. * @return an array of SyncAdapters that have registered with the system
  216. */
  217. public SyncAdapterType[] getSyncAdapterTypes() {
  218. // This makes it so that future permission checks will be in the context of this
  219. // process rather than the caller's process. We will restore this before returning.
  220. long identityToken = clearCallingIdentity();
  221. try {
  222. SyncManager syncManager = getSyncManager();
  223. return syncManager.getSyncAdapterTypes();
  224. } finally {
  225. restoreCallingIdentity(identityToken);
  226. }
  227. }
  228. public boolean getSyncAutomatically(Account account, String providerName) {
  229. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  230. "no permission to read the sync settings");
  231. long identityToken = clearCallingIdentity();
  232. try {
  233. SyncManager syncManager = getSyncManager();
  234. if (syncManager != null) {
  235. return syncManager.getSyncStorageEngine().getSyncAutomatically(
  236. account, providerName);
  237. }
  238. } finally {
  239. restoreCallingIdentity(identityToken);
  240. }
  241. return false;
  242. }
  243. public void setSyncAutomatically(Account account, String providerName, boolean sync) {
  244. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  245. "no permission to write the sync settings");
  246. long identityToken = clearCallingIdentity();
  247. try {
  248. SyncManager syncManager = getSyncManager();
  249. if (syncManager != null) {
  250. syncManager.getSyncStorageEngine().setSyncAutomatically(
  251. account, providerName, sync);
  252. }
  253. } finally {
  254. restoreCallingIdentity(identityToken);
  255. }
  256. }
  257. public void addPeriodicSync(Account account, String authority, Bundle extras,
  258. long pollFrequency) {
  259. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  260. "no permission to write the sync settings");
  261. long identityToken = clearCallingIdentity();
  262. try {
  263. getSyncManager().getSyncStorageEngine().addPeriodicSync(
  264. account, authority, extras, pollFrequency);
  265. } finally {
  266. restoreCallingIdentity(identityToken);
  267. }
  268. }
  269. public void removePeriodicSync(Account account, String authority, Bundle extras) {
  270. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  271. "no permission to write the sync settings");
  272. long identityToken = clearCallingIdentity();
  273. try {
  274. getSyncManager().getSyncStorageEngine().removePeriodicSync(account, authority, extras);
  275. } finally {
  276. restoreCallingIdentity(identityToken);
  277. }
  278. }
  279. public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName) {
  280. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  281. "no permission to read the sync settings");
  282. long identityToken = clearCallingIdentity();
  283. try {
  284. return getSyncManager().getSyncStorageEngine().getPeriodicSyncs(
  285. account, providerName);
  286. } finally {
  287. restoreCallingIdentity(identityToken);
  288. }
  289. }
  290. public int getIsSyncable(Account account, String providerName) {
  291. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  292. "no permission to read the sync settings");
  293. long identityToken = clearCallingIdentity();
  294. try {
  295. SyncManager syncManager = getSyncManager();
  296. if (syncManager != null) {
  297. return syncManager.getSyncStorageEngine().getIsSyncable(
  298. account, providerName);
  299. }
  300. } finally {
  301. restoreCallingIdentity(identityToken);
  302. }
  303. return -1;
  304. }
  305. public void setIsSyncable(Account account, String providerName, int syncable) {
  306. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  307. "no permission to write the sync settings");
  308. long identityToken = clearCallingIdentity();
  309. try {
  310. SyncManager syncManager = getSyncManager();
  311. if (syncManager != null) {
  312. syncManager.getSyncStorageEngine().setIsSyncable(
  313. account, providerName, syncable);
  314. }
  315. } finally {
  316. restoreCallingIdentity(identityToken);
  317. }
  318. }
  319. public boolean getMasterSyncAutomatically() {
  320. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  321. "no permission to read the sync settings");
  322. long identityToken = clearCallingIdentity();
  323. try {
  324. SyncManager syncManager = getSyncManager();
  325. if (syncManager != null) {
  326. return syncManager.getSyncStorageEngine().getMasterSyncAutomatically();
  327. }
  328. } finally {
  329. restoreCallingIdentity(identityToken);
  330. }
  331. return false;
  332. }
  333. public void setMasterSyncAutomatically(boolean flag) {
  334. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  335. "no permission to write the sync settings");
  336. long identityToken = clearCallingIdentity();
  337. try {
  338. SyncManager syncManager = getSyncManager();
  339. if (syncManager != null) {
  340. syncManager.getSyncStorageEngine().setMasterSyncAutomatically(flag);
  341. }
  342. } finally {
  343. restoreCallingIdentity(identityToken);
  344. }
  345. }
  346. public boolean isSyncActive(Account account, String authority) {
  347. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  348. "no permission to read the sync stats");
  349. long identityToken = clearCallingIdentity();
  350. try {
  351. SyncManager syncManager = getSyncManager();
  352. if (syncManager != null) {
  353. return syncManager.getSyncStorageEngine().isSyncActive(
  354. account, authority);
  355. }
  356. } finally {
  357. restoreCallingIdentity(identityToken);
  358. }
  359. return false;
  360. }
  361. public SyncInfo getCurrentSync() {
  362. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  363. "no permission to read the sync stats");
  364. long identityToken = clearCallingIdentity();
  365. try {
  366. SyncManager syncManager = getSyncManager();
  367. if (syncManager != null) {
  368. return syncManager.getSyncStorageEngine().getCurrentSync();
  369. }
  370. } finally {
  371. restoreCallingIdentity(identityToken);
  372. }
  373. return null;
  374. }
  375. public SyncStatusInfo getSyncStatus(Account account, String authority) {
  376. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  377. "no permission to read the sync stats");
  378. long identityToken = clearCallingIdentity();
  379. try {
  380. SyncManager syncManager = getSyncManager();
  381. if (syncManager != null) {
  382. return syncManager.getSyncStorageEngine().getStatusByAccountAndAuthority(
  383. account, authority);
  384. }
  385. } finally {
  386. restoreCallingIdentity(identityToken);
  387. }
  388. return null;
  389. }
  390. public boolean isSyncPending(Account account, String authority) {
  391. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  392. "no permission to read the sync stats");
  393. long identityToken = clearCallingIdentity();
  394. try {
  395. SyncManager syncManager = getSyncManager();
  396. if (syncManager != null) {
  397. return syncManager.getSyncStorageEngine().isSyncPending(account, authority);
  398. }
  399. } finally {
  400. restoreCallingIdentity(identityToken);
  401. }
  402. return false;
  403. }
  404. public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
  405. long identityToken = clearCallingIdentity();
  406. try {
  407. SyncManager syncManager = getSyncManager();
  408. if (syncManager != null && callback != null) {
  409. syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback);
  410. }
  411. } finally {
  412. restoreCallingIdentity(identityToken);
  413. }
  414. }
  415. public void removeStatusChangeListener(ISyncStatusObserver callback) {
  416. long identityToken = clearCallingIdentity();
  417. try {
  418. SyncManager syncManager = getSyncManager();
  419. if (syncManager != null && callback != null) {
  420. syncManager.getSyncStorageEngine().removeStatusChangeListener(callback);
  421. }
  422. } finally {
  423. restoreCallingIdentity(identityToken);
  424. }
  425. }
  426. public static IContentService main(Context context, boolean factoryTest) {
  427. ContentService service = new ContentService(context, factoryTest);
  428. ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
  429. return service;
  430. }
  431. /**
  432. * Hide this class since it is not part of api,
  433. * but current unittest framework requires it to be public
  434. * @hide
  435. */
  436. public static final class ObserverNode {
  437. private class ObserverEntry implements IBinder.DeathRecipient {
  438. public final IContentObserver observer;
  439. public final boolean notifyForDescendents;
  440. private final Object observersLock;
  441. public ObserverEntry(IContentObserver o, boolean n, Object observersLock) {
  442. this.observersLock = observersLock;
  443. observer = o;
  444. notifyForDescendents = n;
  445. try {
  446. observer.asBinder().linkToDeath(this, 0);
  447. } catch (RemoteException e) {
  448. binderDied();
  449. }
  450. }
  451. public void binderDied() {
  452. synchronized (observersLock) {
  453. removeObserverLocked(observer);
  454. }
  455. }
  456. }
  457. public static final int INSERT_TYPE = 0;
  458. public static final int UPDATE_TYPE = 1;
  459. public static final int DELETE_TYPE = 2;
  460. private String mName;
  461. private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>();
  462. private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>();
  463. public ObserverNode(String name) {
  464. mName = name;
  465. }
  466. private String getUriSegment(Uri uri, int index) {
  467. if (uri != null) {
  468. if (index == 0) {
  469. return uri.getAuthority();
  470. } else {
  471. return uri.getPathSegments().get(index - 1);
  472. }
  473. } else {
  474. return null;
  475. }
  476. }
  477. private int countUriSegments(Uri uri) {
  478. if (uri == null) {
  479. return 0;
  480. }
  481. return uri.getPathSegments().size() + 1;
  482. }
  483. public void addObserverLocked(Uri uri, IContentObserver observer,
  484. boolean notifyForDescendents, Object observersLock) {
  485. addObserverLocked(uri, 0, observer, notifyForDescendents, observersLock);
  486. }
  487. private void addObserverLocked(Uri uri, int index, IContentObserver observer,
  488. boolean notifyForDescendents, Object observersLock) {
  489. // If this is the leaf node add the observer
  490. if (index == countUriSegments(uri)) {
  491. mObservers.add(new ObserverEntry(observer, notifyForDescendents, observersLock));
  492. return;
  493. }
  494. // Look to see if the proper child already exists
  495. String segment = getUriSegment(uri, index);
  496. int N = mChildren.size();
  497. for (int i = 0; i < N; i++) {
  498. ObserverNode node = mChildren.get(i);
  499. if (node.mName.equals(segment)) {
  500. node.addObserverLocked(uri, index + 1, observer, notifyForDescendents, observersLock);
  501. return;
  502. }
  503. }
  504. // No child found, create one
  505. ObserverNode node = new ObserverNode(segment);
  506. mChildren.add(node);
  507. node.addObserverLocked(uri, index + 1, observer, notifyForDescendents, observersLock);
  508. }
  509. public boolean removeObserverLocked(IContentObserver observer) {
  510. int size = mChildren.size();
  511. for (int i = 0; i < size; i++) {
  512. boolean empty = mChildren.get(i).removeObserverLocked(observer);
  513. if (empty) {
  514. mChildren.remove(i);
  515. i--;
  516. size--;
  517. }
  518. }
  519. IBinder observerBinder = observer.asBinder();
  520. size = mObservers.size();
  521. for (int i = 0; i < size; i++) {
  522. ObserverEntry entry = mObservers.get(i);
  523. if (entry.observer.asBinder() == observerBinder) {
  524. mObservers.remove(i);
  525. // We no longer need to listen for death notifications. Remove it.
  526. observerBinder.unlinkToDeath(entry, 0);
  527. break;
  528. }
  529. }
  530. if (mChildren.size() == 0 && mObservers.size() == 0) {
  531. return true;
  532. }
  533. return false;
  534. }
  535. private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
  536. boolean selfNotify, ArrayList<ObserverCall> calls) {
  537. int N = mObservers.size();
  538. IBinder observerBinder = observer == null ? null : observer.asBinder();
  539. for (int i = 0; i < N; i++) {
  540. ObserverEntry entry = mObservers.get(i);
  541. // Don't notify the observer if it sent the notification and isn't interesed
  542. // in self notifications
  543. if (entry.observer.asBinder() == observerBinder && !selfNotify) {
  544. continue;
  545. }
  546. // Make sure the observer is interested in the notification
  547. if (leaf || (!leaf && entry.notifyForDescendents)) {
  548. calls.add(new ObserverCall(this, entry.observer, selfNotify));
  549. }
  550. }
  551. }
  552. public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
  553. boolean selfNotify, ArrayList<ObserverCall> calls) {
  554. String segment = null;
  555. int segmentCount = countUriSegments(uri);
  556. if (index >= segmentCount) {
  557. // This is the leaf node, notify all observers
  558. collectMyObserversLocked(true, observer, selfNotify, calls);
  559. } else if (index < segmentCount){
  560. segment = getUriSegment(uri, index);
  561. // Notify any observers at this level who are interested in descendents
  562. collectMyObserversLocked(false, observer, selfNotify, calls);
  563. }
  564. int N = mChildren.size();
  565. for (int i = 0; i < N; i++) {
  566. ObserverNode node = mChildren.get(i);
  567. if (segment == null || node.mName.equals(segment)) {
  568. // We found the child,
  569. node.collectObserversLocked(uri, index + 1, observer, selfNotify, calls);
  570. if (segment != null) {
  571. break;
  572. }
  573. }
  574. }
  575. }
  576. }
  577. }