ContentService.java revision 6009459405bbaa42054c9746c6339b48962c7753
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 177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeypackage com.android.server.content; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 197a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.Manifest; 207a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackbornimport android.accounts.Account; 2116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tateimport android.app.ActivityManager; 227a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.ContentResolver; 237a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.Context; 247a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.IContentService; 257a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.ISyncStatusObserver; 267a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.PeriodicSync; 277a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.SyncAdapterType; 287a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.SyncInfo; 297a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.SyncStatusInfo; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.IContentObserver; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteException; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 331b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport android.os.Binder; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 36231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Parcel; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 39f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle; 406009459405bbaa42054c9746c6339b48962c7753Jeff Sharkeyimport android.text.format.DateUtils; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 426009459405bbaa42054c9746c6339b48962c7753Jeff Sharkeyimport android.util.Slog; 431b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport android.util.SparseIntArray; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 4716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tateimport java.security.InvalidParameterException; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 491b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport java.util.Collections; 501b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport java.util.Comparator; 51c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintanaimport java.util.List; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 56231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornpublic final class ContentService extends IContentService.Stub { 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "ContentService"; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mContext; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mFactoryTest; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ObserverNode mRootNode = new ObserverNode(""); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SyncManager mSyncManager = null; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Object mSyncManagerLock = new Object(); 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SyncManager getSyncManager() { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(mSyncManagerLock) { 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Try to create the SyncManager, return null if it fails (e.g. the disk is full). 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest); 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLiteException e) { 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Can't create SyncManager", e); 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSyncManager; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP, 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "caller doesn't have the DUMP permission"); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSyncManager == null) { 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println("No SyncManager created! (Disk full?)"); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSyncManager.dump(fd, pw); 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 901b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(); 911b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println("Observer tree:"); 921b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn synchronized (mRootNode) { 931b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int[] counts = new int[2]; 941b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn final SparseIntArray pidCounts = new SparseIntArray(); 951b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn mRootNode.dumpLocked(fd, pw, args, "", " ", counts, pidCounts); 961b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(); 971b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn ArrayList<Integer> sorted = new ArrayList<Integer>(); 981b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<pidCounts.size(); i++) { 991b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn sorted.add(pidCounts.keyAt(i)); 1001b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1011b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn Collections.sort(sorted, new Comparator<Integer>() { 1021b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn @Override 1031b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public int compare(Integer lhs, Integer rhs) { 1041b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int lc = pidCounts.get(lhs); 1051b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int rc = pidCounts.get(rhs); 1061b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (lc < rc) { 1071b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn return 1; 1081b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } else if (lc > rc) { 1091b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn return -1; 1101b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1111b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn return 0; 1121b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1131b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn 1141b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn }); 1151b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<sorted.size(); i++) { 1161b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int pid = sorted.get(i); 1171b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(" pid "); pw.print(pid); pw.print(": "); 1181b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(pidCounts.get(pid)); pw.println(" observers"); 1191b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1201b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(); 1211b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(" Total number of nodes: "); pw.println(counts[0]); 1221b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(" Total number of observers: "); pw.println(counts[1]); 1231b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 129231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn @Override 130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 131231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn throws RemoteException { 132231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 133231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return super.onTransact(code, data, reply, flags); 134231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } catch (RuntimeException e) { 135231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn // The content service only throws security exceptions, so let's 136231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn // log all others. 137231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (!(e instanceof SecurityException)) { 138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn Log.e(TAG, "Content Service Crash", e); 139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 140231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn throw e; 141231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /*package*/ ContentService(Context context, boolean factoryTest) { 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFactoryTest = factoryTest; 14726ff6626fc4ee0ae46f01ad309b366921da589feKenny Root } 14826ff6626fc4ee0ae46f01ad309b366921da589feKenny Root 14926ff6626fc4ee0ae46f01ad309b366921da589feKenny Root public void systemReady() { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getSyncManager(); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate /** 15416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * Register a content observer tied to a specific user's view of the provider. 15516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * @param userHandle the user whose view of the provider is to be observed. May be 15616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * the calling user without requiring any permission, otherwise the caller needs to 15716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and 15816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * USER_CURRENT are properly handled; all other pseudousers are forbidden. 15916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate */ 16016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate @Override 16116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public void registerContentObserver(Uri uri, boolean notifyForDescendants, 16216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate IContentObserver observer, int userHandle) { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (observer == null || uri == null) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("You must pass a valid uri and observer"); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 16716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate final int callingUser = UserHandle.getCallingUserId(); 16816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (callingUser != userHandle) { 16916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, 17016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate "no permission to observe other users' provider view"); 17116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 17216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 17316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle < 0) { 17416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle == UserHandle.USER_CURRENT) { 17516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle = ActivityManager.getCurrentUser(); 17616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } else if (userHandle != UserHandle.USER_ALL) { 17716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate throw new InvalidParameterException("Bad user handle for registerContentObserver: " 17816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate + userHandle); 17916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 18016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 18116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 18316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode, 18416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate Binder.getCallingUid(), Binder.getCallingPid(), userHandle); 18543a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri + 18616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate " with notifyForDescendants " + notifyForDescendants); 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public void registerContentObserver(Uri uri, boolean notifyForDescendants, 19116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate IContentObserver observer) { 19216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate registerContentObserver(uri, notifyForDescendants, observer, 19316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate UserHandle.getCallingUserId()); 19416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 19516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void unregisterContentObserver(IContentObserver observer) { 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (observer == null) { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("You must pass a valid observer"); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 201002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana mRootNode.removeObserverLocked(observer); 20243a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato if (false) Log.v(TAG, "Unregistered observer " + observer); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate /** 20716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * Notify observers of a particular user's view of the provider. 20816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * @param userHandle the user whose view of the provider is to be notified. May be 20916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * the calling user without requiring any permission, otherwise the caller needs to 21016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and 21116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * USER_CURRENT are properly interpreted; no other pseudousers are allowed. 21216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate */ 21316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate @Override 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void notifyChange(Uri uri, IContentObserver observer, 21516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, boolean syncToNetwork, 21616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int userHandle) { 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Log.isLoggable(TAG, Log.VERBOSE)) { 21816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle 21916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate + " from observer " + observer + ", syncToNetwork " + syncToNetwork); 22016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 22116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 22216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Notify for any user other than the caller's own requires permission. 22316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate final int callingUserHandle = UserHandle.getCallingUserId(); 22416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle != callingUserHandle) { 22516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, 22616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate "no permission to notify other users"); 22716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 22816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 22916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // We passed the permission check; resolve pseudouser targets as appropriate 23016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle < 0) { 23116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle == UserHandle.USER_CURRENT) { 23216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle = ActivityManager.getCurrentUser(); 23316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } else if (userHandle != UserHandle.USER_ALL) { 23416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate throw new InvalidParameterException("Bad user handle for notifyChange: " 23516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate + userHandle); 23616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 23957286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert final int uid = Binder.getCallingUid(); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 246002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications, 24716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle, calls); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numCalls = calls.size(); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<numCalls; i++) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverCall oc = calls.get(i); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 253655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown oc.mObserver.onChange(oc.mSelfChange, uri); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Log.isLoggable(TAG, Log.VERBOSE)) { 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri); 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException ex) { 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Found dead observer, removing"); 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder binder = oc.mObserver.asBinder(); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<ObserverNode.ObserverEntry> list 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = oc.mNode.mObservers; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numList = list.size(); 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j=0; j<numList; j++) { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode.ObserverEntry oe = list.get(j); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oe.observer.asBinder() == binder) { 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list.remove(j); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project j--; 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numList--; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (syncToNetwork) { 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncManager syncManager = getSyncManager(); 277ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana if (syncManager != null) { 27857286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, uid, 27904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani uri.getAuthority()); 280ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public void notifyChange(Uri uri, IContentObserver observer, 28816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, boolean syncToNetwork) { 28916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork, 29016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate UserHandle.getCallingUserId()); 29116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 29216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Hide this class since it is not part of api, 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but current unittest framework requires it to be public 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final class ObserverCall { 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ObserverNode mNode; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IContentObserver mObserver; 30286de0590b94bcce27e3038c27464bed510bb564aJeff Brown final boolean mSelfChange; 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30486de0590b94bcce27e3038c27464bed510bb564aJeff Brown ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange) { 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNode = node; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mObserver = observer; 30786de0590b94bcce27e3038c27464bed510bb564aJeff Brown mSelfChange = selfChange; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 311ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void requestSync(Account account, String authority, Bundle extras) { 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver.validateSyncExtrasBundle(extras); 313f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 31457286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert int uId = Binder.getCallingUid(); 31504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncManager syncManager = getSyncManager(); 321ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana if (syncManager != null) { 32257286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert syncManager.scheduleSync(account, userId, uId, authority, extras, 0 /* no delay */, 3234a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana false /* onlyThoseWithUnkownSyncableState */); 324ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Clear all scheduled sync operations that match the uri and cancel the active sync 332ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * if they match the authority and account, if they are present. 333ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * @param account filter the pending and active syncs to cancel using this account 334ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * @param authority filter the pending and active syncs to cancel using this authority 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 336ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void cancelSync(Account account, String authority) { 337f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 33804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncManager syncManager = getSyncManager(); 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (syncManager != null) { 34504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani syncManager.clearScheduledSyncOperations(account, userId, authority); 34604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani syncManager.cancelActiveSync(account, userId, authority); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 353ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana /** 354ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * Get information about the SyncAdapters that are known to the system. 355ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * @return an array of SyncAdapters that have registered with the system 356ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana */ 357ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public SyncAdapterType[] getSyncAdapterTypes() { 358ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana // This makes it so that future permission checks will be in the context of this 359ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana // process rather than the caller's process. We will restore this before returning. 3606ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey final int userId = UserHandle.getCallingUserId(); 3616ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey final long identityToken = clearCallingIdentity(); 362ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana try { 363ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana SyncManager syncManager = getSyncManager(); 3646ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey return syncManager.getSyncAdapterTypes(userId); 365ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } finally { 366ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana restoreCallingIdentity(identityToken); 367ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 368ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 369b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 370ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public boolean getSyncAutomatically(Account account, String providerName) { 371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync settings"); 373f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 37404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 375231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 376231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 377231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 378231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 379ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana return syncManager.getSyncStorageEngine().getSyncAutomatically( 38004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName); 381231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 382231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 383231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 384231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 385231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 386231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 387231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 388ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void setSyncAutomatically(Account account, String providerName, boolean sync) { 389231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 390231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to write the sync settings"); 391f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 39204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 393231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 394231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 395231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 396231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 397ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana syncManager.getSyncStorageEngine().setSyncAutomatically( 39804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName, sync); 399231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 400231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 401231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 402231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 403231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 404231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 405c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana public void addPeriodicSync(Account account, String authority, Bundle extras, 406c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long pollFrequency) { 407c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 408c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana "no permission to write the sync settings"); 409f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 41004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 4116009459405bbaa42054c9746c6339b48962c7753Jeff Sharkey if (pollFrequency <= DateUtils.MINUTE_IN_MILLIS) { 4126009459405bbaa42054c9746c6339b48962c7753Jeff Sharkey Slog.w(TAG, "Requested poll frequency of " + pollFrequency 4136009459405bbaa42054c9746c6339b48962c7753Jeff Sharkey + "ms being rounded up to 60 seconds."); 4146009459405bbaa42054c9746c6339b48962c7753Jeff Sharkey pollFrequency = DateUtils.MINUTE_IN_MILLIS; 4156009459405bbaa42054c9746c6339b48962c7753Jeff Sharkey } 4166009459405bbaa42054c9746c6339b48962c7753Jeff Sharkey 417c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long identityToken = clearCallingIdentity(); 418c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana try { 419c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana getSyncManager().getSyncStorageEngine().addPeriodicSync( 42004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, authority, extras, pollFrequency); 421c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } finally { 422c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana restoreCallingIdentity(identityToken); 423c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 424c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 425c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana 426c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana public void removePeriodicSync(Account account, String authority, Bundle extras) { 427c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 428c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana "no permission to write the sync settings"); 429f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 43004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 431c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long identityToken = clearCallingIdentity(); 432c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana try { 43304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani getSyncManager().getSyncStorageEngine().removePeriodicSync(account, userId, authority, 43404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani extras); 435c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } finally { 436c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana restoreCallingIdentity(identityToken); 437c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 438c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 439c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana 440c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName) { 441c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 442c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana "no permission to read the sync settings"); 443f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 44404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 445c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long identityToken = clearCallingIdentity(); 446c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana try { 447c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana return getSyncManager().getSyncStorageEngine().getPeriodicSyncs( 44804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName); 449c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } finally { 450c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana restoreCallingIdentity(identityToken); 451c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 452c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 453c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana 4545e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana public int getIsSyncable(Account account, String providerName) { 4555e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 4565e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana "no permission to read 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 return syncManager.getSyncStorageEngine().getIsSyncable( 46404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName); 4655e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4665e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } finally { 4675e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana restoreCallingIdentity(identityToken); 4685e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4695e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana return -1; 4705e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4715e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana 4725e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana public void setIsSyncable(Account account, String providerName, int syncable) { 4735e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 4745e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana "no permission to write the sync settings"); 475f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 47604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 4775e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana long identityToken = clearCallingIdentity(); 4785e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana try { 4795e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana SyncManager syncManager = getSyncManager(); 4805e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana if (syncManager != null) { 4815e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana syncManager.getSyncStorageEngine().setIsSyncable( 48204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName, syncable); 4835e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4845e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } finally { 4855e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana restoreCallingIdentity(identityToken); 4865e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4875e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 4885e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana 489ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public boolean getMasterSyncAutomatically() { 490231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 491231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync settings"); 492f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 49304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 494231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 495231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 496231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 497231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 49804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani return syncManager.getSyncStorageEngine().getMasterSyncAutomatically(userId); 499231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 500231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 501231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 502231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 503231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 504231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 505b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 506ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void setMasterSyncAutomatically(boolean flag) { 507231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 508231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to write the sync settings"); 509f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 51004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 511231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 512231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 513231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 514231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 51504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani syncManager.getSyncStorageEngine().setMasterSyncAutomatically(flag, userId); 516231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 517231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 518231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 519231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 520231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 521231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 5227a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn public boolean isSyncActive(Account account, String authority) { 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 { 529231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 530231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 531231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return syncManager.getSyncStorageEngine().isSyncActive( 53204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, authority); 533231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 534231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 535231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 536231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 537231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 538231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 539b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 540c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana public List<SyncInfo> getCurrentSyncs() { 541231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 542231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync stats"); 543f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 54404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 545231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 546231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 54704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani return getSyncManager().getSyncStorageEngine().getCurrentSyncs(userId); 548231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 549231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 550231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 551231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 552b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 553ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public SyncStatusInfo getSyncStatus(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) { 562b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache return syncManager.getSyncStorageEngine().getStatusByAccountAndAuthority( 56304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, authority); 564231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 565231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 566231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 567231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 568231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return null; 569231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 570b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 571ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public boolean isSyncPending(Account account, String authority) { 572231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 573231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync stats"); 574f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 57504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 576231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 577231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 578231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 579231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 58004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani return syncManager.getSyncStorageEngine().isSyncPending(account, userId, authority); 581231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 582231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 583231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 584231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 585231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 586231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 587b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 588231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public void addStatusChangeListener(int mask, ISyncStatusObserver callback) { 589231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 590231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 591231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 5921b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana if (syncManager != null && callback != null) { 593ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback); 594231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 595231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 596231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 597231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 598231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 599b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 600231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public void removeStatusChangeListener(ISyncStatusObserver callback) { 601231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 602231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 603231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 6041b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana if (syncManager != null && callback != null) { 605ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana syncManager.getSyncStorageEngine().removeStatusChangeListener(callback); 606231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 607231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 608231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 609231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 610231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 611b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 61226ff6626fc4ee0ae46f01ad309b366921da589feKenny Root public static ContentService main(Context context, boolean factoryTest) { 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentService service = new ContentService(context, factoryTest); 614231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service); 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return service; 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Hide this class since it is not part of api, 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but current unittest framework requires it to be public 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final class ObserverNode { 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class ObserverEntry implements IBinder.DeathRecipient { 625002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public final IContentObserver observer; 6261b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public final int uid; 6271b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public final int pid; 62816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public final boolean notifyForDescendants; 62916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate private final int userHandle; 630002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana private final Object observersLock; 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6321b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public ObserverEntry(IContentObserver o, boolean n, Object observersLock, 63316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int _uid, int _pid, int _userHandle) { 634002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana this.observersLock = observersLock; 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project observer = o; 6361b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn uid = _uid; 6371b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pid = _pid; 63816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle = _userHandle; 63916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate notifyForDescendants = n; 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project observer.asBinder().linkToDeath(this, 0); 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException e) { 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binderDied(); 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void binderDied() { 648002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana synchronized (observersLock) { 649002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana removeObserverLocked(observer); 650002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana } 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6521b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn 6531b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, 6541b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn String name, String prefix, SparseIntArray pidCounts) { 6551b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pidCounts.put(pid, pidCounts.get(pid)+1); 6561b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(prefix); pw.print(name); pw.print(": pid="); 6571b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(pid); pw.print(" uid="); 65816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate pw.print(uid); pw.print(" user="); 65916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate pw.print(userHandle); pw.print(" target="); 6601b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(Integer.toHexString(System.identityHashCode( 6611b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn observer != null ? observer.asBinder() : null))); 6621b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int INSERT_TYPE = 0; 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int UPDATE_TYPE = 1; 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int DELETE_TYPE = 2; 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mName; 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>(); 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>(); 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ObserverNode(String name) { 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName = name; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6771b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, 6781b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn String name, String prefix, int[] counts, SparseIntArray pidCounts) { 6791b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn String innerName = null; 6801b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (mObservers.size() > 0) { 6811b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if ("".equals(name)) { 6821b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = mName; 6831b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } else { 6841b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = name + "/" + mName; 6851b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6861b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<mObservers.size(); i++) { 6871b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn counts[1]++; 6881b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn mObservers.get(i).dumpLocked(fd, pw, args, innerName, prefix, 6891b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pidCounts); 6901b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6911b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6921b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (mChildren.size() > 0) { 6931b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (innerName == null) { 6941b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if ("".equals(name)) { 6951b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = mName; 6961b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } else { 6971b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = name + "/" + mName; 6981b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 6991b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 7001b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<mChildren.size(); i++) { 7011b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn counts[0]++; 7021b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn mChildren.get(i).dumpLocked(fd, pw, args, innerName, prefix, 7031b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn counts, pidCounts); 7041b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 7051b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 7061b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 7071b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String getUriSegment(Uri uri, int index) { 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uri != null) { 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index == 0) { 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return uri.getAuthority(); 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return uri.getPathSegments().get(index - 1); 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int countUriSegments(Uri uri) { 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uri == null) { 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return uri.getPathSegments().size() + 1; 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 72716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Invariant: userHandle is either a hard user number or is USER_ALL 728002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public void addObserverLocked(Uri uri, IContentObserver observer, 72916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean notifyForDescendants, Object observersLock, 73016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int uid, int pid, int userHandle) { 73116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate addObserverLocked(uri, 0, observer, notifyForDescendants, observersLock, 73216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate uid, pid, userHandle); 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 735002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana private void addObserverLocked(Uri uri, int index, IContentObserver observer, 73616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean notifyForDescendants, Object observersLock, 73716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int uid, int pid, int userHandle) { 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If this is the leaf node add the observer 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index == countUriSegments(uri)) { 74016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock, 74116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate uid, pid, userHandle)); 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Look to see if the proper child already exists 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String segment = getUriSegment(uri, index); 747f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam if (segment == null) { 748f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer"); 749f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam } 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = mChildren.size(); 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode node = mChildren.get(i); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (node.mName.equals(segment)) { 75416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate node.addObserverLocked(uri, index + 1, observer, notifyForDescendants, 75516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate observersLock, uid, pid, userHandle); 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No child found, create one 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode node = new ObserverNode(segment); 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildren.add(node); 76316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate node.addObserverLocked(uri, index + 1, observer, notifyForDescendants, 76416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate observersLock, uid, pid, userHandle); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 767002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public boolean removeObserverLocked(IContentObserver observer) { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = mChildren.size(); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 770002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana boolean empty = mChildren.get(i).removeObserverLocked(observer); 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (empty) { 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildren.remove(i); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i--; 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size--; 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder observerBinder = observer.asBinder(); 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size = mObservers.size(); 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverEntry entry = mObservers.get(i); 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (entry.observer.asBinder() == observerBinder) { 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mObservers.remove(i); 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We no longer need to listen for death notifications. Remove it. 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project observerBinder.unlinkToDeath(entry, 0); 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mChildren.size() == 0 && mObservers.size() == 0) { 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 796002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana private void collectMyObserversLocked(boolean leaf, IContentObserver observer, 79716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, int targetUserHandle, 79816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate ArrayList<ObserverCall> calls) { 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = mObservers.size(); 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder observerBinder = observer == null ? null : observer.asBinder(); 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverEntry entry = mObservers.get(i); 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 80416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Don't notify the observer if it sent the notification and isn't interested 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // in self notifications 80686de0590b94bcce27e3038c27464bed510bb564aJeff Brown boolean selfChange = (entry.observer.asBinder() == observerBinder); 80786de0590b94bcce27e3038c27464bed510bb564aJeff Brown if (selfChange && !observerWantsSelfNotifications) { 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 81116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Does this observer match the target user? 81216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (targetUserHandle == UserHandle.USER_ALL 81316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate || entry.userHandle == UserHandle.USER_ALL 81416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate || targetUserHandle == entry.userHandle) { 81516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Make sure the observer is interested in the notification 81616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (leaf || (!leaf && entry.notifyForDescendants)) { 81716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate calls.add(new ObserverCall(this, entry.observer, selfChange)); 81816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 82316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate /** 82416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * targetUserHandle is either a hard user handle or is USER_ALL 82516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate */ 826002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public void collectObserversLocked(Uri uri, int index, IContentObserver observer, 82716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, int targetUserHandle, 82816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate ArrayList<ObserverCall> calls) { 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String segment = null; 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int segmentCount = countUriSegments(uri); 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index >= segmentCount) { 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is the leaf node, notify all observers 83316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate collectMyObserversLocked(true, observer, observerWantsSelfNotifications, 83416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate targetUserHandle, calls); 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (index < segmentCount){ 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project segment = getUriSegment(uri, index); 83716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Notify any observers at this level who are interested in descendants 83816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate collectMyObserversLocked(false, observer, observerWantsSelfNotifications, 83916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate targetUserHandle, calls); 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = mChildren.size(); 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode node = mChildren.get(i); 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (segment == null || node.mName.equals(segment)) { 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We found the child, 84786de0590b94bcce27e3038c27464bed510bb564aJeff Brown node.collectObserversLocked(uri, index + 1, 84816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate observer, observerWantsSelfNotifications, targetUserHandle, calls); 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (segment != null) { 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 857