PageRenderTime 101ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/frameworks/base/core/java/android/content/ContentService.java

https://gitlab.com/brian0218/rk3188_r-box_android4.2.2_sdk
Java | 838 lines | 675 code | 80 blank | 83 comment | 131 complexity | ff48343e8f227b126c42101eade50c2a 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.app.ActivityManager;
  19. import android.database.IContentObserver;
  20. import android.database.sqlite.SQLiteException;
  21. import android.net.Uri;
  22. import android.os.Binder;
  23. import android.os.Bundle;
  24. import android.os.IBinder;
  25. import android.os.Parcel;
  26. import android.os.RemoteException;
  27. import android.os.ServiceManager;
  28. import android.os.UserHandle;
  29. import android.util.Log;
  30. import android.util.SparseIntArray;
  31. import android.Manifest;
  32. import java.io.FileDescriptor;
  33. import java.io.PrintWriter;
  34. import java.security.InvalidParameterException;
  35. import java.util.ArrayList;
  36. import java.util.Collections;
  37. import java.util.Comparator;
  38. import java.util.List;
  39. /**
  40. * {@hide}
  41. */
  42. public final class ContentService extends IContentService.Stub {
  43. private static final String TAG = "ContentService";
  44. private Context mContext;
  45. private boolean mFactoryTest;
  46. private final ObserverNode mRootNode = new ObserverNode("");
  47. private SyncManager mSyncManager = null;
  48. private final Object mSyncManagerLock = new Object();
  49. private SyncManager getSyncManager() {
  50. synchronized(mSyncManagerLock) {
  51. try {
  52. // Try to create the SyncManager, return null if it fails (e.g. the disk is full).
  53. if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest);
  54. } catch (SQLiteException e) {
  55. Log.e(TAG, "Can't create SyncManager", e);
  56. }
  57. return mSyncManager;
  58. }
  59. }
  60. @Override
  61. protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
  62. mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP,
  63. "caller doesn't have the DUMP permission");
  64. // This makes it so that future permission checks will be in the context of this
  65. // process rather than the caller's process. We will restore this before returning.
  66. long identityToken = clearCallingIdentity();
  67. try {
  68. if (mSyncManager == null) {
  69. pw.println("No SyncManager created! (Disk full?)");
  70. } else {
  71. mSyncManager.dump(fd, pw);
  72. }
  73. pw.println();
  74. pw.println("Observer tree:");
  75. synchronized (mRootNode) {
  76. int[] counts = new int[2];
  77. final SparseIntArray pidCounts = new SparseIntArray();
  78. mRootNode.dumpLocked(fd, pw, args, "", " ", counts, pidCounts);
  79. pw.println();
  80. ArrayList<Integer> sorted = new ArrayList<Integer>();
  81. for (int i=0; i<pidCounts.size(); i++) {
  82. sorted.add(pidCounts.keyAt(i));
  83. }
  84. Collections.sort(sorted, new Comparator<Integer>() {
  85. @Override
  86. public int compare(Integer lhs, Integer rhs) {
  87. int lc = pidCounts.get(lhs);
  88. int rc = pidCounts.get(rhs);
  89. if (lc < rc) {
  90. return 1;
  91. } else if (lc > rc) {
  92. return -1;
  93. }
  94. return 0;
  95. }
  96. });
  97. for (int i=0; i<sorted.size(); i++) {
  98. int pid = sorted.get(i);
  99. pw.print(" pid "); pw.print(pid); pw.print(": ");
  100. pw.print(pidCounts.get(pid)); pw.println(" observers");
  101. }
  102. pw.println();
  103. pw.print(" Total number of nodes: "); pw.println(counts[0]);
  104. pw.print(" Total number of observers: "); pw.println(counts[1]);
  105. }
  106. } finally {
  107. restoreCallingIdentity(identityToken);
  108. }
  109. }
  110. @Override
  111. public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
  112. throws RemoteException {
  113. try {
  114. return super.onTransact(code, data, reply, flags);
  115. } catch (RuntimeException e) {
  116. // The content service only throws security exceptions, so let's
  117. // log all others.
  118. if (!(e instanceof SecurityException)) {
  119. Log.e(TAG, "Content Service Crash", e);
  120. }
  121. throw e;
  122. }
  123. }
  124. /*package*/ ContentService(Context context, boolean factoryTest) {
  125. mContext = context;
  126. mFactoryTest = factoryTest;
  127. }
  128. public void systemReady() {
  129. getSyncManager();
  130. }
  131. /**
  132. * Register a content observer tied to a specific user's view of the provider.
  133. * @param userHandle the user whose view of the provider is to be observed. May be
  134. * the calling user without requiring any permission, otherwise the caller needs to
  135. * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and
  136. * USER_CURRENT are properly handled; all other pseudousers are forbidden.
  137. */
  138. @Override
  139. public void registerContentObserver(Uri uri, boolean notifyForDescendants,
  140. IContentObserver observer, int userHandle) {
  141. if (observer == null || uri == null) {
  142. throw new IllegalArgumentException("You must pass a valid uri and observer");
  143. }
  144. final int callingUser = UserHandle.getCallingUserId();
  145. if (callingUser != userHandle) {
  146. mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
  147. "no permission to observe other users' provider view");
  148. }
  149. if (userHandle < 0) {
  150. if (userHandle == UserHandle.USER_CURRENT) {
  151. userHandle = ActivityManager.getCurrentUser();
  152. } else if (userHandle != UserHandle.USER_ALL) {
  153. throw new InvalidParameterException("Bad user handle for registerContentObserver: "
  154. + userHandle);
  155. }
  156. }
  157. synchronized (mRootNode) {
  158. mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
  159. Binder.getCallingUid(), Binder.getCallingPid(), userHandle);
  160. if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
  161. " with notifyForDescendants " + notifyForDescendants);
  162. }
  163. }
  164. public void registerContentObserver(Uri uri, boolean notifyForDescendants,
  165. IContentObserver observer) {
  166. registerContentObserver(uri, notifyForDescendants, observer,
  167. UserHandle.getCallingUserId());
  168. }
  169. public void unregisterContentObserver(IContentObserver observer) {
  170. if (observer == null) {
  171. throw new IllegalArgumentException("You must pass a valid observer");
  172. }
  173. synchronized (mRootNode) {
  174. mRootNode.removeObserverLocked(observer);
  175. if (false) Log.v(TAG, "Unregistered observer " + observer);
  176. }
  177. }
  178. /**
  179. * Notify observers of a particular user's view of the provider.
  180. * @param userHandle the user whose view of the provider is to be notified. May be
  181. * the calling user without requiring any permission, otherwise the caller needs to
  182. * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and
  183. * USER_CURRENT are properly interpreted; no other pseudousers are allowed.
  184. */
  185. @Override
  186. public void notifyChange(Uri uri, IContentObserver observer,
  187. boolean observerWantsSelfNotifications, boolean syncToNetwork,
  188. int userHandle) {
  189. if (Log.isLoggable(TAG, Log.VERBOSE)) {
  190. Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle
  191. + " from observer " + observer + ", syncToNetwork " + syncToNetwork);
  192. }
  193. // Notify for any user other than the caller's own requires permission.
  194. final int callingUserHandle = UserHandle.getCallingUserId();
  195. if (userHandle != callingUserHandle) {
  196. mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
  197. "no permission to notify other users");
  198. }
  199. // We passed the permission check; resolve pseudouser targets as appropriate
  200. if (userHandle < 0) {
  201. if (userHandle == UserHandle.USER_CURRENT) {
  202. userHandle = ActivityManager.getCurrentUser();
  203. } else if (userHandle != UserHandle.USER_ALL) {
  204. throw new InvalidParameterException("Bad user handle for notifyChange: "
  205. + userHandle);
  206. }
  207. }
  208. // This makes it so that future permission checks will be in the context of this
  209. // process rather than the caller's process. We will restore this before returning.
  210. long identityToken = clearCallingIdentity();
  211. try {
  212. ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
  213. synchronized (mRootNode) {
  214. mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
  215. userHandle, calls);
  216. }
  217. final int numCalls = calls.size();
  218. for (int i=0; i<numCalls; i++) {
  219. ObserverCall oc = calls.get(i);
  220. try {
  221. oc.mObserver.onChange(oc.mSelfChange, uri);
  222. if (Log.isLoggable(TAG, Log.VERBOSE)) {
  223. Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri);
  224. }
  225. } catch (RemoteException ex) {
  226. synchronized (mRootNode) {
  227. Log.w(TAG, "Found dead observer, removing");
  228. IBinder binder = oc.mObserver.asBinder();
  229. final ArrayList<ObserverNode.ObserverEntry> list
  230. = oc.mNode.mObservers;
  231. int numList = list.size();
  232. for (int j=0; j<numList; j++) {
  233. ObserverNode.ObserverEntry oe = list.get(j);
  234. if (oe.observer.asBinder() == binder) {
  235. list.remove(j);
  236. j--;
  237. numList--;
  238. }
  239. }
  240. }
  241. }
  242. }
  243. if (syncToNetwork) {
  244. SyncManager syncManager = getSyncManager();
  245. if (syncManager != null) {
  246. syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle,
  247. uri.getAuthority());
  248. }
  249. }
  250. } finally {
  251. restoreCallingIdentity(identityToken);
  252. }
  253. }
  254. public void notifyChange(Uri uri, IContentObserver observer,
  255. boolean observerWantsSelfNotifications, boolean syncToNetwork) {
  256. notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork,
  257. UserHandle.getCallingUserId());
  258. }
  259. /**
  260. * Hide this class since it is not part of api,
  261. * but current unittest framework requires it to be public
  262. * @hide
  263. *
  264. */
  265. public static final class ObserverCall {
  266. final ObserverNode mNode;
  267. final IContentObserver mObserver;
  268. final boolean mSelfChange;
  269. ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange) {
  270. mNode = node;
  271. mObserver = observer;
  272. mSelfChange = selfChange;
  273. }
  274. }
  275. public void requestSync(Account account, String authority, Bundle extras) {
  276. ContentResolver.validateSyncExtrasBundle(extras);
  277. int userId = UserHandle.getCallingUserId();
  278. // This makes it so that future permission checks will be in the context of this
  279. // process rather than the caller's process. We will restore this before returning.
  280. long identityToken = clearCallingIdentity();
  281. try {
  282. SyncManager syncManager = getSyncManager();
  283. if (syncManager != null) {
  284. syncManager.scheduleSync(account, userId, authority, extras, 0 /* no delay */,
  285. false /* onlyThoseWithUnkownSyncableState */);
  286. }
  287. } finally {
  288. restoreCallingIdentity(identityToken);
  289. }
  290. }
  291. /**
  292. * Clear all scheduled sync operations that match the uri and cancel the active sync
  293. * if they match the authority and account, if they are present.
  294. * @param account filter the pending and active syncs to cancel using this account
  295. * @param authority filter the pending and active syncs to cancel using this authority
  296. */
  297. public void cancelSync(Account account, String authority) {
  298. int userId = UserHandle.getCallingUserId();
  299. // This makes it so that future permission checks will be in the context of this
  300. // process rather than the caller's process. We will restore this before returning.
  301. long identityToken = clearCallingIdentity();
  302. try {
  303. SyncManager syncManager = getSyncManager();
  304. if (syncManager != null) {
  305. syncManager.clearScheduledSyncOperations(account, userId, authority);
  306. syncManager.cancelActiveSync(account, userId, authority);
  307. }
  308. } finally {
  309. restoreCallingIdentity(identityToken);
  310. }
  311. }
  312. /**
  313. * Get information about the SyncAdapters that are known to the system.
  314. * @return an array of SyncAdapters that have registered with the system
  315. */
  316. public SyncAdapterType[] getSyncAdapterTypes() {
  317. // This makes it so that future permission checks will be in the context of this
  318. // process rather than the caller's process. We will restore this before returning.
  319. final int userId = UserHandle.getCallingUserId();
  320. final long identityToken = clearCallingIdentity();
  321. try {
  322. SyncManager syncManager = getSyncManager();
  323. return syncManager.getSyncAdapterTypes(userId);
  324. } finally {
  325. restoreCallingIdentity(identityToken);
  326. }
  327. }
  328. public boolean getSyncAutomatically(Account account, String providerName) {
  329. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  330. "no permission to read the sync settings");
  331. int userId = UserHandle.getCallingUserId();
  332. long identityToken = clearCallingIdentity();
  333. try {
  334. SyncManager syncManager = getSyncManager();
  335. if (syncManager != null) {
  336. return syncManager.getSyncStorageEngine().getSyncAutomatically(
  337. account, userId, providerName);
  338. }
  339. } finally {
  340. restoreCallingIdentity(identityToken);
  341. }
  342. return false;
  343. }
  344. public void setSyncAutomatically(Account account, String providerName, boolean sync) {
  345. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  346. "no permission to write the sync settings");
  347. int userId = UserHandle.getCallingUserId();
  348. long identityToken = clearCallingIdentity();
  349. try {
  350. SyncManager syncManager = getSyncManager();
  351. if (syncManager != null) {
  352. syncManager.getSyncStorageEngine().setSyncAutomatically(
  353. account, userId, providerName, sync);
  354. }
  355. } finally {
  356. restoreCallingIdentity(identityToken);
  357. }
  358. }
  359. public void addPeriodicSync(Account account, String authority, Bundle extras,
  360. long pollFrequency) {
  361. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  362. "no permission to write the sync settings");
  363. int userId = UserHandle.getCallingUserId();
  364. long identityToken = clearCallingIdentity();
  365. try {
  366. getSyncManager().getSyncStorageEngine().addPeriodicSync(
  367. account, userId, authority, extras, pollFrequency);
  368. } finally {
  369. restoreCallingIdentity(identityToken);
  370. }
  371. }
  372. public void removePeriodicSync(Account account, String authority, Bundle extras) {
  373. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  374. "no permission to write the sync settings");
  375. int userId = UserHandle.getCallingUserId();
  376. long identityToken = clearCallingIdentity();
  377. try {
  378. getSyncManager().getSyncStorageEngine().removePeriodicSync(account, userId, authority,
  379. extras);
  380. } finally {
  381. restoreCallingIdentity(identityToken);
  382. }
  383. }
  384. public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName) {
  385. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  386. "no permission to read the sync settings");
  387. int userId = UserHandle.getCallingUserId();
  388. long identityToken = clearCallingIdentity();
  389. try {
  390. return getSyncManager().getSyncStorageEngine().getPeriodicSyncs(
  391. account, userId, providerName);
  392. } finally {
  393. restoreCallingIdentity(identityToken);
  394. }
  395. }
  396. public int getIsSyncable(Account account, String providerName) {
  397. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  398. "no permission to read the sync settings");
  399. int userId = UserHandle.getCallingUserId();
  400. long identityToken = clearCallingIdentity();
  401. try {
  402. SyncManager syncManager = getSyncManager();
  403. if (syncManager != null) {
  404. return syncManager.getSyncStorageEngine().getIsSyncable(
  405. account, userId, providerName);
  406. }
  407. } finally {
  408. restoreCallingIdentity(identityToken);
  409. }
  410. return -1;
  411. }
  412. public void setIsSyncable(Account account, String providerName, int syncable) {
  413. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  414. "no permission to write the sync settings");
  415. int userId = UserHandle.getCallingUserId();
  416. long identityToken = clearCallingIdentity();
  417. try {
  418. SyncManager syncManager = getSyncManager();
  419. if (syncManager != null) {
  420. syncManager.getSyncStorageEngine().setIsSyncable(
  421. account, userId, providerName, syncable);
  422. }
  423. } finally {
  424. restoreCallingIdentity(identityToken);
  425. }
  426. }
  427. public boolean getMasterSyncAutomatically() {
  428. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
  429. "no permission to read the sync settings");
  430. int userId = UserHandle.getCallingUserId();
  431. long identityToken = clearCallingIdentity();
  432. try {
  433. SyncManager syncManager = getSyncManager();
  434. if (syncManager != null) {
  435. return syncManager.getSyncStorageEngine().getMasterSyncAutomatically(userId);
  436. }
  437. } finally {
  438. restoreCallingIdentity(identityToken);
  439. }
  440. return false;
  441. }
  442. public void setMasterSyncAutomatically(boolean flag) {
  443. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
  444. "no permission to write the sync settings");
  445. int userId = UserHandle.getCallingUserId();
  446. long identityToken = clearCallingIdentity();
  447. try {
  448. SyncManager syncManager = getSyncManager();
  449. if (syncManager != null) {
  450. syncManager.getSyncStorageEngine().setMasterSyncAutomatically(flag, userId);
  451. }
  452. } finally {
  453. restoreCallingIdentity(identityToken);
  454. }
  455. }
  456. public boolean isSyncActive(Account account, String authority) {
  457. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  458. "no permission to read the sync stats");
  459. int userId = UserHandle.getCallingUserId();
  460. long identityToken = clearCallingIdentity();
  461. try {
  462. SyncManager syncManager = getSyncManager();
  463. if (syncManager != null) {
  464. return syncManager.getSyncStorageEngine().isSyncActive(
  465. account, userId, authority);
  466. }
  467. } finally {
  468. restoreCallingIdentity(identityToken);
  469. }
  470. return false;
  471. }
  472. public List<SyncInfo> getCurrentSyncs() {
  473. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  474. "no permission to read the sync stats");
  475. int userId = UserHandle.getCallingUserId();
  476. long identityToken = clearCallingIdentity();
  477. try {
  478. return getSyncManager().getSyncStorageEngine().getCurrentSyncs(userId);
  479. } finally {
  480. restoreCallingIdentity(identityToken);
  481. }
  482. }
  483. public SyncStatusInfo getSyncStatus(Account account, String authority) {
  484. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  485. "no permission to read the sync stats");
  486. int userId = UserHandle.getCallingUserId();
  487. long identityToken = clearCallingIdentity();
  488. try {
  489. SyncManager syncManager = getSyncManager();
  490. if (syncManager != null) {
  491. return syncManager.getSyncStorageEngine().getStatusByAccountAndAuthority(
  492. account, userId, authority);
  493. }
  494. } finally {
  495. restoreCallingIdentity(identityToken);
  496. }
  497. return null;
  498. }
  499. public boolean isSyncPending(Account account, String authority) {
  500. mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
  501. "no permission to read the sync stats");
  502. int userId = UserHandle.getCallingUserId();
  503. long identityToken = clearCallingIdentity();
  504. try {
  505. SyncManager syncManager = getSyncManager();
  506. if (syncManager != null) {
  507. return syncManager.getSyncStorageEngine().isSyncPending(account, userId, authority);
  508. }
  509. } finally {
  510. restoreCallingIdentity(identityToken);
  511. }
  512. return false;
  513. }
  514. public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
  515. long identityToken = clearCallingIdentity();
  516. try {
  517. SyncManager syncManager = getSyncManager();
  518. if (syncManager != null && callback != null) {
  519. syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback);
  520. }
  521. } finally {
  522. restoreCallingIdentity(identityToken);
  523. }
  524. }
  525. public void removeStatusChangeListener(ISyncStatusObserver callback) {
  526. long identityToken = clearCallingIdentity();
  527. try {
  528. SyncManager syncManager = getSyncManager();
  529. if (syncManager != null && callback != null) {
  530. syncManager.getSyncStorageEngine().removeStatusChangeListener(callback);
  531. }
  532. } finally {
  533. restoreCallingIdentity(identityToken);
  534. }
  535. }
  536. public static ContentService main(Context context, boolean factoryTest) {
  537. ContentService service = new ContentService(context, factoryTest);
  538. ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
  539. return service;
  540. }
  541. /**
  542. * Hide this class since it is not part of api,
  543. * but current unittest framework requires it to be public
  544. * @hide
  545. */
  546. public static final class ObserverNode {
  547. private class ObserverEntry implements IBinder.DeathRecipient {
  548. public final IContentObserver observer;
  549. public final int uid;
  550. public final int pid;
  551. public final boolean notifyForDescendants;
  552. private final int userHandle;
  553. private final Object observersLock;
  554. public ObserverEntry(IContentObserver o, boolean n, Object observersLock,
  555. int _uid, int _pid, int _userHandle) {
  556. this.observersLock = observersLock;
  557. observer = o;
  558. uid = _uid;
  559. pid = _pid;
  560. userHandle = _userHandle;
  561. notifyForDescendants = n;
  562. try {
  563. observer.asBinder().linkToDeath(this, 0);
  564. } catch (RemoteException e) {
  565. binderDied();
  566. }
  567. }
  568. public void binderDied() {
  569. synchronized (observersLock) {
  570. removeObserverLocked(observer);
  571. }
  572. }
  573. public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
  574. String name, String prefix, SparseIntArray pidCounts) {
  575. pidCounts.put(pid, pidCounts.get(pid)+1);
  576. pw.print(prefix); pw.print(name); pw.print(": pid=");
  577. pw.print(pid); pw.print(" uid=");
  578. pw.print(uid); pw.print(" user=");
  579. pw.print(userHandle); pw.print(" target=");
  580. pw.println(Integer.toHexString(System.identityHashCode(
  581. observer != null ? observer.asBinder() : null)));
  582. }
  583. }
  584. public static final int INSERT_TYPE = 0;
  585. public static final int UPDATE_TYPE = 1;
  586. public static final int DELETE_TYPE = 2;
  587. private String mName;
  588. private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>();
  589. private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>();
  590. public ObserverNode(String name) {
  591. mName = name;
  592. }
  593. public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
  594. String name, String prefix, int[] counts, SparseIntArray pidCounts) {
  595. String innerName = null;
  596. if (mObservers.size() > 0) {
  597. if ("".equals(name)) {
  598. innerName = mName;
  599. } else {
  600. innerName = name + "/" + mName;
  601. }
  602. for (int i=0; i<mObservers.size(); i++) {
  603. counts[1]++;
  604. mObservers.get(i).dumpLocked(fd, pw, args, innerName, prefix,
  605. pidCounts);
  606. }
  607. }
  608. if (mChildren.size() > 0) {
  609. if (innerName == null) {
  610. if ("".equals(name)) {
  611. innerName = mName;
  612. } else {
  613. innerName = name + "/" + mName;
  614. }
  615. }
  616. for (int i=0; i<mChildren.size(); i++) {
  617. counts[0]++;
  618. mChildren.get(i).dumpLocked(fd, pw, args, innerName, prefix,
  619. counts, pidCounts);
  620. }
  621. }
  622. }
  623. private String getUriSegment(Uri uri, int index) {
  624. if (uri != null) {
  625. if (index == 0) {
  626. return uri.getAuthority();
  627. } else {
  628. return uri.getPathSegments().get(index - 1);
  629. }
  630. } else {
  631. return null;
  632. }
  633. }
  634. private int countUriSegments(Uri uri) {
  635. if (uri == null) {
  636. return 0;
  637. }
  638. return uri.getPathSegments().size() + 1;
  639. }
  640. // Invariant: userHandle is either a hard user number or is USER_ALL
  641. public void addObserverLocked(Uri uri, IContentObserver observer,
  642. boolean notifyForDescendants, Object observersLock,
  643. int uid, int pid, int userHandle) {
  644. addObserverLocked(uri, 0, observer, notifyForDescendants, observersLock,
  645. uid, pid, userHandle);
  646. }
  647. private void addObserverLocked(Uri uri, int index, IContentObserver observer,
  648. boolean notifyForDescendants, Object observersLock,
  649. int uid, int pid, int userHandle) {
  650. // If this is the leaf node add the observer
  651. if (index == countUriSegments(uri)) {
  652. mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,
  653. uid, pid, userHandle));
  654. return;
  655. }
  656. // Look to see if the proper child already exists
  657. String segment = getUriSegment(uri, index);
  658. if (segment == null) {
  659. throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer");
  660. }
  661. int N = mChildren.size();
  662. for (int i = 0; i < N; i++) {
  663. ObserverNode node = mChildren.get(i);
  664. if (node.mName.equals(segment)) {
  665. node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
  666. observersLock, uid, pid, userHandle);
  667. return;
  668. }
  669. }
  670. // No child found, create one
  671. ObserverNode node = new ObserverNode(segment);
  672. mChildren.add(node);
  673. node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
  674. observersLock, uid, pid, userHandle);
  675. }
  676. public boolean removeObserverLocked(IContentObserver observer) {
  677. int size = mChildren.size();
  678. for (int i = 0; i < size; i++) {
  679. boolean empty = mChildren.get(i).removeObserverLocked(observer);
  680. if (empty) {
  681. mChildren.remove(i);
  682. i--;
  683. size--;
  684. }
  685. }
  686. IBinder observerBinder = observer.asBinder();
  687. size = mObservers.size();
  688. for (int i = 0; i < size; i++) {
  689. ObserverEntry entry = mObservers.get(i);
  690. if (entry.observer.asBinder() == observerBinder) {
  691. mObservers.remove(i);
  692. // We no longer need to listen for death notifications. Remove it.
  693. observerBinder.unlinkToDeath(entry, 0);
  694. break;
  695. }
  696. }
  697. if (mChildren.size() == 0 && mObservers.size() == 0) {
  698. return true;
  699. }
  700. return false;
  701. }
  702. private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
  703. boolean observerWantsSelfNotifications, int targetUserHandle,
  704. ArrayList<ObserverCall> calls) {
  705. int N = mObservers.size();
  706. IBinder observerBinder = observer == null ? null : observer.asBinder();
  707. for (int i = 0; i < N; i++) {
  708. ObserverEntry entry = mObservers.get(i);
  709. // Don't notify the observer if it sent the notification and isn't interested
  710. // in self notifications
  711. boolean selfChange = (entry.observer.asBinder() == observerBinder);
  712. if (selfChange && !observerWantsSelfNotifications) {
  713. continue;
  714. }
  715. // Does this observer match the target user?
  716. if (targetUserHandle == UserHandle.USER_ALL
  717. || entry.userHandle == UserHandle.USER_ALL
  718. || targetUserHandle == entry.userHandle) {
  719. // Make sure the observer is interested in the notification
  720. if (leaf || (!leaf && entry.notifyForDescendants)) {
  721. calls.add(new ObserverCall(this, entry.observer, selfChange));
  722. }
  723. }
  724. }
  725. }
  726. /**
  727. * targetUserHandle is either a hard user handle or is USER_ALL
  728. */
  729. public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
  730. boolean observerWantsSelfNotifications, int targetUserHandle,
  731. ArrayList<ObserverCall> calls) {
  732. String segment = null;
  733. int segmentCount = countUriSegments(uri);
  734. if (index >= segmentCount) {
  735. // This is the leaf node, notify all observers
  736. collectMyObserversLocked(true, observer, observerWantsSelfNotifications,
  737. targetUserHandle, calls);
  738. } else if (index < segmentCount){
  739. segment = getUriSegment(uri, index);
  740. // Notify any observers at this level who are interested in descendants
  741. collectMyObserversLocked(false, observer, observerWantsSelfNotifications,
  742. targetUserHandle, calls);
  743. }
  744. int N = mChildren.size();
  745. for (int i = 0; i < N; i++) {
  746. ObserverNode node = mChildren.get(i);
  747. if (segment == null || node.mName.equals(segment)) {
  748. // We found the child,
  749. node.collectObserversLocked(uri, index + 1,
  750. observer, observerWantsSelfNotifications, targetUserHandle, calls);
  751. if (segment != null) {
  752. break;
  753. }
  754. }
  755. }
  756. }
  757. }
  758. }