19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.content; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 197a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackbornimport android.accounts.Account; 2016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tateimport android.app.ActivityManager; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.IContentObserver; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteException; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 241b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport android.os.Binder; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 27231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Parcel; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 30f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 321b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport android.util.SparseIntArray; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.Manifest; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 3716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tateimport java.security.InvalidParameterException; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 391b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport java.util.Collections; 401b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport java.util.Comparator; 41c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintanaimport java.util.List; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 46231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornpublic final class ContentService extends IContentService.Stub { 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "ContentService"; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mContext; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mFactoryTest; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ObserverNode mRootNode = new ObserverNode(""); 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SyncManager mSyncManager = null; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Object mSyncManagerLock = new Object(); 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SyncManager getSyncManager() { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(mSyncManagerLock) { 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Try to create the SyncManager, return null if it fails (e.g. the disk is full). 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest); 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLiteException e) { 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Can't create SyncManager", e); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSyncManager; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP, 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "caller doesn't have the DUMP permission"); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSyncManager == null) { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println("No SyncManager created! (Disk full?)"); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSyncManager.dump(fd, pw); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 801b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(); 811b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println("Observer tree:"); 821b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn synchronized (mRootNode) { 831b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int[] counts = new int[2]; 841b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn final SparseIntArray pidCounts = new SparseIntArray(); 851b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn mRootNode.dumpLocked(fd, pw, args, "", " ", counts, pidCounts); 861b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(); 871b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn ArrayList<Integer> sorted = new ArrayList<Integer>(); 881b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<pidCounts.size(); i++) { 891b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn sorted.add(pidCounts.keyAt(i)); 901b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 911b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn Collections.sort(sorted, new Comparator<Integer>() { 921b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn @Override 931b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public int compare(Integer lhs, Integer rhs) { 941b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int lc = pidCounts.get(lhs); 951b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int rc = pidCounts.get(rhs); 961b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (lc < rc) { 971b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn return 1; 981b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } else if (lc > rc) { 991b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn return -1; 1001b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1011b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn return 0; 1021b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1031b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn 1041b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn }); 1051b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<sorted.size(); i++) { 1061b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int pid = sorted.get(i); 1071b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(" pid "); pw.print(pid); pw.print(": "); 1081b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(pidCounts.get(pid)); pw.println(" observers"); 1091b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1101b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(); 1111b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(" Total number of nodes: "); pw.println(counts[0]); 1121b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(" Total number of observers: "); pw.println(counts[1]); 1131b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 119231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn @Override 120231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 121231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn throws RemoteException { 122231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 123231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return super.onTransact(code, data, reply, flags); 124231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } catch (RuntimeException e) { 125231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn // The content service only throws security exceptions, so let's 126231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn // log all others. 127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (!(e instanceof SecurityException)) { 128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn Log.e(TAG, "Content Service Crash", e); 129231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn throw e; 131231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 132231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 133231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /*package*/ ContentService(Context context, boolean factoryTest) { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFactoryTest = factoryTest; 13726ff6626fc4ee0ae46f01ad309b366921da589feKenny Root } 13826ff6626fc4ee0ae46f01ad309b366921da589feKenny Root 13926ff6626fc4ee0ae46f01ad309b366921da589feKenny Root public void systemReady() { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getSyncManager(); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate /** 14416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * Register a content observer tied to a specific user's view of the provider. 14516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * @param userHandle the user whose view of the provider is to be observed. May be 14616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * the calling user without requiring any permission, otherwise the caller needs to 14716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and 14816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * USER_CURRENT are properly handled; all other pseudousers are forbidden. 14916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate */ 15016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate @Override 15116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public void registerContentObserver(Uri uri, boolean notifyForDescendants, 15216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate IContentObserver observer, int userHandle) { 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (observer == null || uri == null) { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("You must pass a valid uri and observer"); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 15716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate final int callingUser = UserHandle.getCallingUserId(); 15816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (callingUser != userHandle) { 15916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, 16016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate "no permission to observe other users' provider view"); 16116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 16216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 16316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle < 0) { 16416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle == UserHandle.USER_CURRENT) { 16516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle = ActivityManager.getCurrentUser(); 16616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } else if (userHandle != UserHandle.USER_ALL) { 16716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate throw new InvalidParameterException("Bad user handle for registerContentObserver: " 16816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate + userHandle); 16916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 17016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 17116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 17316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode, 17416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate Binder.getCallingUid(), Binder.getCallingPid(), userHandle); 17543a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri + 17616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate " with notifyForDescendants " + notifyForDescendants); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public void registerContentObserver(Uri uri, boolean notifyForDescendants, 18116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate IContentObserver observer) { 18216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate registerContentObserver(uri, notifyForDescendants, observer, 18316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate UserHandle.getCallingUserId()); 18416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 18516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void unregisterContentObserver(IContentObserver observer) { 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (observer == null) { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("You must pass a valid observer"); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 191002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana mRootNode.removeObserverLocked(observer); 19243a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato if (false) Log.v(TAG, "Unregistered observer " + observer); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate /** 19716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * Notify observers of a particular user's view of the provider. 19816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * @param userHandle the user whose view of the provider is to be notified. May be 19916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * the calling user without requiring any permission, otherwise the caller needs to 20016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and 20116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * USER_CURRENT are properly interpreted; no other pseudousers are allowed. 20216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate */ 20316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate @Override 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void notifyChange(Uri uri, IContentObserver observer, 20516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, boolean syncToNetwork, 20616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int userHandle) { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Log.isLoggable(TAG, Log.VERBOSE)) { 20816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle 20916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate + " from observer " + observer + ", syncToNetwork " + syncToNetwork); 21016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 21116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 21216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Notify for any user other than the caller's own requires permission. 21316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate final int callingUserHandle = UserHandle.getCallingUserId(); 21416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle != callingUserHandle) { 21516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, 21616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate "no permission to notify other users"); 21716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 21816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 21916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // We passed the permission check; resolve pseudouser targets as appropriate 22016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle < 0) { 22116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle == UserHandle.USER_CURRENT) { 22216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle = ActivityManager.getCurrentUser(); 22316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } else if (userHandle != UserHandle.USER_ALL) { 22416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate throw new InvalidParameterException("Bad user handle for notifyChange: " 22516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate + userHandle); 22616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 235002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications, 23616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle, calls); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numCalls = calls.size(); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<numCalls; i++) { 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverCall oc = calls.get(i); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 242655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown oc.mObserver.onChange(oc.mSelfChange, uri); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Log.isLoggable(TAG, Log.VERBOSE)) { 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException ex) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Found dead observer, removing"); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder binder = oc.mObserver.asBinder(); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<ObserverNode.ObserverEntry> list 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = oc.mNode.mObservers; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numList = list.size(); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j=0; j<numList; j++) { 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode.ObserverEntry oe = list.get(j); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oe.observer.asBinder() == binder) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list.remove(j); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project j--; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numList--; 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (syncToNetwork) { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncManager syncManager = getSyncManager(); 266ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana if (syncManager != null) { 26716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, 26804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani uri.getAuthority()); 269ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public void notifyChange(Uri uri, IContentObserver observer, 27716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, boolean syncToNetwork) { 27816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork, 27916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate UserHandle.getCallingUserId()); 28016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 28116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Hide this class since it is not part of api, 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but current unittest framework requires it to be public 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final class ObserverCall { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ObserverNode mNode; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IContentObserver mObserver; 29186de0590b94bcce27e3038c27464bed510bb564aJeff Brown final boolean mSelfChange; 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29386de0590b94bcce27e3038c27464bed510bb564aJeff Brown ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange) { 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNode = node; 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mObserver = observer; 29686de0590b94bcce27e3038c27464bed510bb564aJeff Brown mSelfChange = selfChange; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 300ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void requestSync(Account account, String authority, Bundle extras) { 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver.validateSyncExtrasBundle(extras); 302f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 30304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncManager syncManager = getSyncManager(); 309ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana if (syncManager != null) { 31004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani syncManager.scheduleSync(account, userId, authority, extras, 0 /* no delay */, 3114a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana false /* onlyThoseWithUnkownSyncableState */); 312ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Clear all scheduled sync operations that match the uri and cancel the active sync 320ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * if they match the authority and account, if they are present. 321ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * @param account filter the pending and active syncs to cancel using this account 322ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * @param authority filter the pending and active syncs to cancel using this authority 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 324ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void cancelSync(Account account, String authority) { 325f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 32604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncManager syncManager = getSyncManager(); 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (syncManager != null) { 33304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani syncManager.clearScheduledSyncOperations(account, userId, authority); 33404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani syncManager.cancelActiveSync(account, userId, authority); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 341ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana /** 342ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * Get information about the SyncAdapters that are known to the system. 343ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * @return an array of SyncAdapters that have registered with the system 344ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana */ 345ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public SyncAdapterType[] getSyncAdapterTypes() { 346ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana // This makes it so that future permission checks will be in the context of this 347ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana // process rather than the caller's process. We will restore this before returning. 3486ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey final int userId = UserHandle.getCallingUserId(); 3496ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey final long identityToken = clearCallingIdentity(); 350ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana try { 351ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana SyncManager syncManager = getSyncManager(); 3526ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey return syncManager.getSyncAdapterTypes(userId); 353ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } finally { 354ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana restoreCallingIdentity(identityToken); 355ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 356ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 357b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 358ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public boolean getSyncAutomatically(Account account, String providerName) { 359231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 360231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync settings"); 361f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 36204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 363231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 364231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 365231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 366231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 367ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana return syncManager.getSyncStorageEngine().getSyncAutomatically( 36804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName); 369231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 370231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 373231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 374231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 375231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 376ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void setSyncAutomatically(Account account, String providerName, boolean sync) { 377231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 378231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to write the sync settings"); 379f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 38004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 381231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 382231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 383231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 384231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 385ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana syncManager.getSyncStorageEngine().setSyncAutomatically( 38604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName, sync); 387231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 388231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 389231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 390231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 391231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 392231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 393c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana public void addPeriodicSync(Account account, String authority, Bundle extras, 394c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long pollFrequency) { 395c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 396c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana "no permission to write the sync settings"); 397f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 39804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 399c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long identityToken = clearCallingIdentity(); 400c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana try { 401c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana getSyncManager().getSyncStorageEngine().addPeriodicSync( 40204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, authority, extras, pollFrequency); 403c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } finally { 404c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana restoreCallingIdentity(identityToken); 405c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 406c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 407c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana 408c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana public void removePeriodicSync(Account account, String authority, Bundle extras) { 409c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 410c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana "no permission to write the sync settings"); 411f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 41204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 413c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long identityToken = clearCallingIdentity(); 414c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana try { 41504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani getSyncManager().getSyncStorageEngine().removePeriodicSync(account, userId, authority, 41604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani extras); 417c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } finally { 418c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana restoreCallingIdentity(identityToken); 419c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 420c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 421c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana 422c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName) { 423c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 424c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana "no permission to read the sync settings"); 425f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 42604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 427c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long identityToken = clearCallingIdentity(); 428c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana try { 429c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana return getSyncManager().getSyncStorageEngine().getPeriodicSyncs( 43004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName); 431c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } finally { 432c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana restoreCallingIdentity(identityToken); 433c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 434c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 435c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana 4365e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana public int getIsSyncable(Account account, String providerName) { 4375e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 4385e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana "no permission to read the sync settings"); 439f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 44004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 4415e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana long identityToken = clearCallingIdentity(); 4425e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana try { 4435e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana SyncManager syncManager = getSyncManager(); 4445e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana if (syncManager != null) { 4455e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana return syncManager.getSyncStorageEngine().getIsSyncable( 44604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName); 4475e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4485e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } finally { 4495e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana restoreCallingIdentity(identityToken); 4505e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4515e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana return -1; 4525e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4535e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana 4545e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana public void setIsSyncable(Account account, String providerName, int syncable) { 4555e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 4565e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana "no permission to write the sync settings"); 457f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 45804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 4595e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana long identityToken = clearCallingIdentity(); 4605e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana try { 4615e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana SyncManager syncManager = getSyncManager(); 4625e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana if (syncManager != null) { 4635e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana syncManager.getSyncStorageEngine().setIsSyncable( 46404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName, syncable); 4655e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4665e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } finally { 4675e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana restoreCallingIdentity(identityToken); 4685e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4695e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4705e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana 471ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public boolean getMasterSyncAutomatically() { 472231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 473231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync settings"); 474f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 47504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 476231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 477231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 478231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 479231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 48004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani return syncManager.getSyncStorageEngine().getMasterSyncAutomatically(userId); 481231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 482231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 483231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 484231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 485231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 486231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 487b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 488ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void setMasterSyncAutomatically(boolean flag) { 489231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 490231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to write the sync settings"); 491f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 49204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 493231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 494231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 495231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 496231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 49704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani syncManager.getSyncStorageEngine().setMasterSyncAutomatically(flag, userId); 498231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 499231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 500231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 501231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 502231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 503231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 5047a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn public boolean isSyncActive(Account account, String authority) { 505231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 506231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync stats"); 507f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 50804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 509231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 510231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 511231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 512231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 513231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return syncManager.getSyncStorageEngine().isSyncActive( 51404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, authority); 515231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 516231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 517231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 518231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 519231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 520231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 521b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 522c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana public List<SyncInfo> getCurrentSyncs() { 523231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 524231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync stats"); 525f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 52604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 527231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 528231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 52904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani return getSyncManager().getSyncStorageEngine().getCurrentSyncs(userId); 530231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 531231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 532231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 533231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 534b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 535ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public SyncStatusInfo getSyncStatus(Account account, String authority) { 536231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 537231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync stats"); 538f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 53904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 540231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 541231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 542231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 543231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 544b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache return syncManager.getSyncStorageEngine().getStatusByAccountAndAuthority( 54504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, authority); 546231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 547231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 548231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 549231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 550231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return null; 551231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 552b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 553ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public boolean isSyncPending(Account account, String authority) { 554231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 555231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync stats"); 556f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 55704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 558231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 559231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 560231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 561231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 56204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani return syncManager.getSyncStorageEngine().isSyncPending(account, userId, authority); 563231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 564231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 565231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 566231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 567231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 568231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 569b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 570231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public void addStatusChangeListener(int mask, ISyncStatusObserver callback) { 571231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 572231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 573231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 5741b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana if (syncManager != null && callback != null) { 575ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback); 576231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 577231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 578231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 579231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 580231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 581b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 582231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public void removeStatusChangeListener(ISyncStatusObserver callback) { 583231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 584231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 585231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 5861b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana if (syncManager != null && callback != null) { 587ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana syncManager.getSyncStorageEngine().removeStatusChangeListener(callback); 588231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 589231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 590231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 591231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 592231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 593b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 59426ff6626fc4ee0ae46f01ad309b366921da589feKenny Root public static ContentService main(Context context, boolean factoryTest) { 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentService service = new ContentService(context, factoryTest); 596231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service); 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return service; 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Hide this class since it is not part of api, 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but current unittest framework requires it to be public 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final class ObserverNode { 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class ObserverEntry implements IBinder.DeathRecipient { 607002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public final IContentObserver observer; 6081b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public final int uid; 6091b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public final int pid; 61016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public final boolean notifyForDescendants; 61116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate private final int userHandle; 612002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana private final Object observersLock; 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6141b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public ObserverEntry(IContentObserver o, boolean n, Object observersLock, 61516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int _uid, int _pid, int _userHandle) { 616002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana this.observersLock = observersLock; 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project observer = o; 6181b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn uid = _uid; 6191b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pid = _pid; 62016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle = _userHandle; 62116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate notifyForDescendants = n; 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project observer.asBinder().linkToDeath(this, 0); 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException e) { 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binderDied(); 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void binderDied() { 630002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana synchronized (observersLock) { 631002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana removeObserverLocked(observer); 632002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana } 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6341b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn 6351b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, 6361b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn String name, String prefix, SparseIntArray pidCounts) { 6371b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pidCounts.put(pid, pidCounts.get(pid)+1); 6381b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(prefix); pw.print(name); pw.print(": pid="); 6391b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(pid); pw.print(" uid="); 64016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate pw.print(uid); pw.print(" user="); 64116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate pw.print(userHandle); pw.print(" target="); 6421b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(Integer.toHexString(System.identityHashCode( 6431b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn observer != null ? observer.asBinder() : null))); 6441b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int INSERT_TYPE = 0; 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int UPDATE_TYPE = 1; 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int DELETE_TYPE = 2; 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mName; 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>(); 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>(); 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ObserverNode(String name) { 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName = name; 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6591b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, 6601b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn String name, String prefix, int[] counts, SparseIntArray pidCounts) { 6611b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn String innerName = null; 6621b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (mObservers.size() > 0) { 6631b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if ("".equals(name)) { 6641b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = mName; 6651b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } else { 6661b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = name + "/" + mName; 6671b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6681b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<mObservers.size(); i++) { 6691b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn counts[1]++; 6701b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn mObservers.get(i).dumpLocked(fd, pw, args, innerName, prefix, 6711b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pidCounts); 6721b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6731b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6741b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (mChildren.size() > 0) { 6751b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (innerName == null) { 6761b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if ("".equals(name)) { 6771b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = mName; 6781b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } else { 6791b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = name + "/" + mName; 6801b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6811b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6821b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<mChildren.size(); i++) { 6831b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn counts[0]++; 6841b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn mChildren.get(i).dumpLocked(fd, pw, args, innerName, prefix, 6851b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn counts, pidCounts); 6861b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6871b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6881b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6891b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String getUriSegment(Uri uri, int index) { 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uri != null) { 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index == 0) { 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return uri.getAuthority(); 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return uri.getPathSegments().get(index - 1); 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int countUriSegments(Uri uri) { 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uri == null) { 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return uri.getPathSegments().size() + 1; 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 70916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Invariant: userHandle is either a hard user number or is USER_ALL 710002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public void addObserverLocked(Uri uri, IContentObserver observer, 71116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean notifyForDescendants, Object observersLock, 71216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int uid, int pid, int userHandle) { 71316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate addObserverLocked(uri, 0, observer, notifyForDescendants, observersLock, 71416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate uid, pid, userHandle); 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 717002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana private void addObserverLocked(Uri uri, int index, IContentObserver observer, 71816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean notifyForDescendants, Object observersLock, 71916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int uid, int pid, int userHandle) { 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If this is the leaf node add the observer 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index == countUriSegments(uri)) { 72216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock, 72316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate uid, pid, userHandle)); 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Look to see if the proper child already exists 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String segment = getUriSegment(uri, index); 729f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam if (segment == null) { 730f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer"); 731f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam } 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = mChildren.size(); 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode node = mChildren.get(i); 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (node.mName.equals(segment)) { 73616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate node.addObserverLocked(uri, index + 1, observer, notifyForDescendants, 73716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate observersLock, uid, pid, userHandle); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No child found, create one 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode node = new ObserverNode(segment); 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildren.add(node); 74516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate node.addObserverLocked(uri, index + 1, observer, notifyForDescendants, 74616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate observersLock, uid, pid, userHandle); 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public boolean removeObserverLocked(IContentObserver observer) { 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = mChildren.size(); 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 752002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana boolean empty = mChildren.get(i).removeObserverLocked(observer); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (empty) { 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildren.remove(i); 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i--; 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size--; 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder observerBinder = observer.asBinder(); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size = mObservers.size(); 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverEntry entry = mObservers.get(i); 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (entry.observer.asBinder() == observerBinder) { 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mObservers.remove(i); 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We no longer need to listen for death notifications. Remove it. 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project observerBinder.unlinkToDeath(entry, 0); 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mChildren.size() == 0 && mObservers.size() == 0) { 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 778002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana private void collectMyObserversLocked(boolean leaf, IContentObserver observer, 77916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, int targetUserHandle, 78016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate ArrayList<ObserverCall> calls) { 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = mObservers.size(); 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder observerBinder = observer == null ? null : observer.asBinder(); 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverEntry entry = mObservers.get(i); 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 78616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Don't notify the observer if it sent the notification and isn't interested 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // in self notifications 78886de0590b94bcce27e3038c27464bed510bb564aJeff Brown boolean selfChange = (entry.observer.asBinder() == observerBinder); 78986de0590b94bcce27e3038c27464bed510bb564aJeff Brown if (selfChange && !observerWantsSelfNotifications) { 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 79316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Does this observer match the target user? 79416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (targetUserHandle == UserHandle.USER_ALL 79516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate || entry.userHandle == UserHandle.USER_ALL 79616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate || targetUserHandle == entry.userHandle) { 79716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Make sure the observer is interested in the notification 79816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (leaf || (!leaf && entry.notifyForDescendants)) { 79916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate calls.add(new ObserverCall(this, entry.observer, selfChange)); 80016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 80516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate /** 80616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * targetUserHandle is either a hard user handle or is USER_ALL 80716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate */ 808002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public void collectObserversLocked(Uri uri, int index, IContentObserver observer, 80916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, int targetUserHandle, 81016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate ArrayList<ObserverCall> calls) { 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String segment = null; 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int segmentCount = countUriSegments(uri); 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index >= segmentCount) { 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is the leaf node, notify all observers 81516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate collectMyObserversLocked(true, observer, observerWantsSelfNotifications, 81616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate targetUserHandle, calls); 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (index < segmentCount){ 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project segment = getUriSegment(uri, index); 81916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Notify any observers at this level who are interested in descendants 82016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate collectMyObserversLocked(false, observer, observerWantsSelfNotifications, 82116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate targetUserHandle, calls); 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = mChildren.size(); 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode node = mChildren.get(i); 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (segment == null || node.mName.equals(segment)) { 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We found the child, 82986de0590b94bcce27e3038c27464bed510bb564aJeff Brown node.collectObserversLocked(uri, index + 1, 83016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate observer, observerWantsSelfNotifications, targetUserHandle, calls); 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (segment != null) { 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 839