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; 29fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williamsimport android.content.SyncRequest; 307a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.SyncStatusInfo; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.IContentObserver; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteException; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 341b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport android.os.Binder; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 37231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Parcel; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 40e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrillimport android.os.SystemProperties; 41f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle; 42632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williamsimport android.text.TextUtils; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 44fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williamsimport android.util.Pair; 456009459405bbaa42054c9746c6339b48962c7753Jeff Sharkeyimport android.util.Slog; 461b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport android.util.SparseIntArray; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 5016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tateimport java.security.InvalidParameterException; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 521b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport java.util.Collections; 531b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport java.util.Comparator; 54c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintanaimport java.util.List; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 59231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornpublic final class ContentService extends IContentService.Stub { 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "ContentService"; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mContext; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mFactoryTest; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ObserverNode mRootNode = new ObserverNode(""); 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SyncManager mSyncManager = null; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Object mSyncManagerLock = new Object(); 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SyncManager getSyncManager() { 68e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill if (SystemProperties.getBoolean("config.disable_network", false)) { 69e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill return null; 70e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill } 71e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(mSyncManagerLock) { 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Try to create the SyncManager, return null if it fails (e.g. the disk is full). 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest); 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SQLiteException e) { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Can't create SyncManager", e); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSyncManager; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP, 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "caller doesn't have the DUMP permission"); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSyncManager == null) { 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println("No SyncManager created! (Disk full?)"); 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSyncManager.dump(fd, pw); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 971b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(); 981b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println("Observer tree:"); 991b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn synchronized (mRootNode) { 1001b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int[] counts = new int[2]; 1011b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn final SparseIntArray pidCounts = new SparseIntArray(); 1021b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn mRootNode.dumpLocked(fd, pw, args, "", " ", counts, pidCounts); 1031b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(); 1041b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn ArrayList<Integer> sorted = new ArrayList<Integer>(); 1051b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<pidCounts.size(); i++) { 1061b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn sorted.add(pidCounts.keyAt(i)); 1071b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1081b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn Collections.sort(sorted, new Comparator<Integer>() { 1091b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn @Override 1101b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public int compare(Integer lhs, Integer rhs) { 1111b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int lc = pidCounts.get(lhs); 1121b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int rc = pidCounts.get(rhs); 1131b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (lc < rc) { 1141b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn return 1; 1151b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } else if (lc > rc) { 1161b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn return -1; 1171b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1181b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn return 0; 1191b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1201b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn 1211b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn }); 1221b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<sorted.size(); i++) { 1231b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn int pid = sorted.get(i); 1241b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(" pid "); pw.print(pid); pw.print(": "); 1251b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(pidCounts.get(pid)); pw.println(" observers"); 1261b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1271b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(); 1281b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(" Total number of nodes: "); pw.println(counts[0]); 1291b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(" Total number of observers: "); pw.println(counts[1]); 1301b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 136231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn @Override 137231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn throws RemoteException { 139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 140231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return super.onTransact(code, data, reply, flags); 141231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } catch (RuntimeException e) { 142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn // The content service only throws security exceptions, so let's 143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn // log all others. 144231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (!(e instanceof SecurityException)) { 145164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn Slog.wtf(TAG, "Content Service Crash", e); 146231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 147231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn throw e; 148231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 149231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 150231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /*package*/ ContentService(Context context, boolean factoryTest) { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFactoryTest = factoryTest; 15426ff6626fc4ee0ae46f01ad309b366921da589feKenny Root } 15526ff6626fc4ee0ae46f01ad309b366921da589feKenny Root 15626ff6626fc4ee0ae46f01ad309b366921da589feKenny Root public void systemReady() { 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getSyncManager(); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate /** 16116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * Register a content observer tied to a specific user's view of the provider. 16216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * @param userHandle the user whose view of the provider is to be observed. May be 16316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * the calling user without requiring any permission, otherwise the caller needs to 16416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and 16516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * USER_CURRENT are properly handled; all other pseudousers are forbidden. 16616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate */ 16716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate @Override 16816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public void registerContentObserver(Uri uri, boolean notifyForDescendants, 16916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate IContentObserver observer, int userHandle) { 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (observer == null || uri == null) { 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("You must pass a valid uri and observer"); 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 17416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate final int callingUser = UserHandle.getCallingUserId(); 17516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (callingUser != userHandle) { 17616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, 17716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate "no permission to observe other users' provider view"); 17816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 17916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 18016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle < 0) { 18116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle == UserHandle.USER_CURRENT) { 18216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle = ActivityManager.getCurrentUser(); 18316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } else if (userHandle != UserHandle.USER_ALL) { 18416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate throw new InvalidParameterException("Bad user handle for registerContentObserver: " 18516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate + userHandle); 18616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 18716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 18816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 19016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode, 19116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate Binder.getCallingUid(), Binder.getCallingPid(), userHandle); 19243a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri + 19316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate " with notifyForDescendants " + notifyForDescendants); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public void registerContentObserver(Uri uri, boolean notifyForDescendants, 19816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate IContentObserver observer) { 19916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate registerContentObserver(uri, notifyForDescendants, observer, 20016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate UserHandle.getCallingUserId()); 20116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 20216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void unregisterContentObserver(IContentObserver observer) { 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (observer == null) { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("You must pass a valid observer"); 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 208002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana mRootNode.removeObserverLocked(observer); 20943a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato if (false) Log.v(TAG, "Unregistered observer " + observer); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate /** 21416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * Notify observers of a particular user's view of the provider. 21516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * @param userHandle the user whose view of the provider is to be notified. May be 21616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * the calling user without requiring any permission, otherwise the caller needs to 21716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and 21816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * USER_CURRENT are properly interpreted; no other pseudousers are allowed. 21916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate */ 22016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate @Override 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void notifyChange(Uri uri, IContentObserver observer, 22216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, boolean syncToNetwork, 22316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int userHandle) { 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Log.isLoggable(TAG, Log.VERBOSE)) { 22516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle 22616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate + " from observer " + observer + ", syncToNetwork " + syncToNetwork); 22716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 22816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 22916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Notify for any user other than the caller's own requires permission. 23016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate final int callingUserHandle = UserHandle.getCallingUserId(); 23116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle != callingUserHandle) { 23216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, 23316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate "no permission to notify other users"); 23416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 23516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 23616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // We passed the permission check; resolve pseudouser targets as appropriate 23716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle < 0) { 23816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (userHandle == UserHandle.USER_CURRENT) { 23916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle = ActivityManager.getCurrentUser(); 24016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } else if (userHandle != UserHandle.USER_ALL) { 24116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate throw new InvalidParameterException("Bad user handle for notifyChange: " 24216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate + userHandle); 24316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 24657286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert final int uid = Binder.getCallingUid(); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 253002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications, 25416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle, calls); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numCalls = calls.size(); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<numCalls; i++) { 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverCall oc = calls.get(i); 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 260655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown oc.mObserver.onChange(oc.mSelfChange, uri); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Log.isLoggable(TAG, Log.VERBOSE)) { 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException ex) { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mRootNode) { 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Found dead observer, removing"); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder binder = oc.mObserver.asBinder(); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<ObserverNode.ObserverEntry> list 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = oc.mNode.mObservers; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numList = list.size(); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j=0; j<numList; j++) { 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode.ObserverEntry oe = list.get(j); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oe.observer.asBinder() == binder) { 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list.remove(j); 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project j--; 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numList--; 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (syncToNetwork) { 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncManager syncManager = getSyncManager(); 284ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana if (syncManager != null) { 28557286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, uid, 28604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani uri.getAuthority()); 287ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public void notifyChange(Uri uri, IContentObserver observer, 29516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, boolean syncToNetwork) { 29616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork, 29716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate UserHandle.getCallingUserId()); 29816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 29916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Hide this class since it is not part of api, 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but current unittest framework requires it to be public 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final class ObserverCall { 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ObserverNode mNode; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IContentObserver mObserver; 30986de0590b94bcce27e3038c27464bed510bb564aJeff Brown final boolean mSelfChange; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31186de0590b94bcce27e3038c27464bed510bb564aJeff Brown ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange) { 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNode = node; 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mObserver = observer; 31486de0590b94bcce27e3038c27464bed510bb564aJeff Brown mSelfChange = selfChange; 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 318fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 319ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void requestSync(Account account, String authority, Bundle extras) { 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver.validateSyncExtrasBundle(extras); 321f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 32257286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert int uId = Binder.getCallingUid(); 32304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncManager syncManager = getSyncManager(); 329ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana if (syncManager != null) { 330fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams syncManager.scheduleSync(account, userId, uId, authority, extras, 331fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams 0 /* no delay */, 0 /* no delay */, 3324a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana false /* onlyThoseWithUnkownSyncableState */); 333ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 340fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * Request a sync with a generic {@link android.content.SyncRequest} object. This will be 341fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * either: 342fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * periodic OR one-off sync. 343fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * and 344fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * anonymous OR provider sync. 345fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * Depending on the request, we enqueue to suit in the SyncManager. 346632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams * @param request The request object. Validation of this object is done by its builder. 347fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams */ 348fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 349fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams public void sync(SyncRequest request) { 350fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams Bundle extras = request.getBundle(); 351fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams long flextime = request.getSyncFlexTime(); 352fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams long runAtTime = request.getSyncRunTime(); 353fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams int userId = UserHandle.getCallingUserId(); 354fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams int uId = Binder.getCallingUid(); 355fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams 356fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // This makes it so that future permission checks will be in the context of this 357fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // process rather than the caller's process. We will restore this before returning. 358fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams long identityToken = clearCallingIdentity(); 359fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams try { 360fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams SyncManager syncManager = getSyncManager(); 361fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams if (syncManager != null) { 362fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams if (request.hasAuthority()) { 363fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // Sync Adapter registered with the system - old API. 3646222288bfbae46550b4914ef1eb12c69dc1f716cMatthew Williams final Account account = request.getAccount(); 3656222288bfbae46550b4914ef1eb12c69dc1f716cMatthew Williams final String provider = request.getProvider(); 366fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams if (request.isPeriodic()) { 367fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams mContext.enforceCallingOrSelfPermission( 368fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams Manifest.permission.WRITE_SYNC_SETTINGS, 369fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams "no permission to write the sync settings"); 370fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams if (runAtTime < 60) { 371fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams Slog.w(TAG, "Requested poll frequency of " + runAtTime 372fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams + " seconds being rounded up to 60 seconds."); 373fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams runAtTime = 60; 374fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams } 375fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams PeriodicSync syncToAdd = 376fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams new PeriodicSync(account, provider, extras, runAtTime, flextime); 377fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams getSyncManager().getSyncStorageEngine().addPeriodicSync(syncToAdd, userId); 378fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams } else { 379fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams long beforeRuntimeMillis = (flextime) * 1000; 380fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams long runtimeMillis = runAtTime * 1000; 381fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams syncManager.scheduleSync( 382fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams account, userId, uId, provider, extras, 383fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams beforeRuntimeMillis, runtimeMillis, 384fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams false /* onlyThoseWithUnknownSyncableState */); 385fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams } 386fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams } else { 3876222288bfbae46550b4914ef1eb12c69dc1f716cMatthew Williams Log.w(TAG, "Unrecognised sync parameters, doing nothing."); 388fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams } 389fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams } 390fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams } finally { 391fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams restoreCallingIdentity(identityToken); 392fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams } 393fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams } 394fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams 395fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams /** 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Clear all scheduled sync operations that match the uri and cancel the active sync 397ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * if they match the authority and account, if they are present. 398ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * @param account filter the pending and active syncs to cancel using this account 399ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * @param authority filter the pending and active syncs to cancel using this authority 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 401fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 402ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void cancelSync(Account account, String authority) { 403632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams if (authority != null && authority.length() == 0) { 404632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams throw new IllegalArgumentException("Authority must be non-empty"); 405632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams } 40604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 407632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This makes it so that future permission checks will be in the context of this 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // process rather than the caller's process. We will restore this before returning. 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identityToken = clearCallingIdentity(); 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SyncManager syncManager = getSyncManager(); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (syncManager != null) { 41404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani syncManager.clearScheduledSyncOperations(account, userId, authority); 41504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani syncManager.cancelActiveSync(account, userId, authority); 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restoreCallingIdentity(identityToken); 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 422ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana /** 423ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * Get information about the SyncAdapters that are known to the system. 424ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana * @return an array of SyncAdapters that have registered with the system 425ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana */ 426fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 427ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public SyncAdapterType[] getSyncAdapterTypes() { 428ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana // This makes it so that future permission checks will be in the context of this 429ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana // process rather than the caller's process. We will restore this before returning. 4306ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey final int userId = UserHandle.getCallingUserId(); 4316ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey final long identityToken = clearCallingIdentity(); 432ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana try { 433ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana SyncManager syncManager = getSyncManager(); 4346ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey return syncManager.getSyncAdapterTypes(userId); 435ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } finally { 436ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana restoreCallingIdentity(identityToken); 437ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 438ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana } 439b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 440fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 441ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public boolean getSyncAutomatically(Account account, String providerName) { 442231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 443231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync settings"); 44404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 445632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 446231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 447231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 448231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 449231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 450ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana return syncManager.getSyncStorageEngine().getSyncAutomatically( 45104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName); 452231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 453231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 454231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 455231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 456231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 457231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 458231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 459fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 460ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void setSyncAutomatically(Account account, String providerName, boolean sync) { 461632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams if (TextUtils.isEmpty(providerName)) { 462632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams throw new IllegalArgumentException("Authority must be non-empty"); 463632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams } 464231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 465231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to write the sync settings"); 46604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 467632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 468231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 469231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 470231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 471231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 472ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana syncManager.getSyncStorageEngine().setSyncAutomatically( 47304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName, sync); 474231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 475231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 476231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 477231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 478231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 479231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 480632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams /** Old API. Schedule periodic sync with default flex time. */ 481fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 482c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana public void addPeriodicSync(Account account, String authority, Bundle extras, 483c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long pollFrequency) { 484632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams if (account == null) { 485632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams throw new IllegalArgumentException("Account must not be null"); 486632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams } 487632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams if (TextUtils.isEmpty(authority)) { 488632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams throw new IllegalArgumentException("Authority must not be empty."); 489632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams } 490c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 491c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana "no permission to write the sync settings"); 49204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 493632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 49451366be80fb086ba11c385c27e545ebfa1997248Jeff Sharkey if (pollFrequency < 60) { 4956009459405bbaa42054c9746c6339b48962c7753Jeff Sharkey Slog.w(TAG, "Requested poll frequency of " + pollFrequency 49651366be80fb086ba11c385c27e545ebfa1997248Jeff Sharkey + " seconds being rounded up to 60 seconds."); 49751366be80fb086ba11c385c27e545ebfa1997248Jeff Sharkey pollFrequency = 60; 4986009459405bbaa42054c9746c6339b48962c7753Jeff Sharkey } 4996009459405bbaa42054c9746c6339b48962c7753Jeff Sharkey 500c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long identityToken = clearCallingIdentity(); 501c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana try { 502fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // Add default flex time to this sync. 503fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams PeriodicSync syncToAdd = 504fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams new PeriodicSync(account, authority, extras, 505fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams pollFrequency, 506fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams SyncStorageEngine.calculateDefaultFlexTime(pollFrequency)); 507fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams getSyncManager().getSyncStorageEngine().addPeriodicSync(syncToAdd, userId); 508c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } finally { 509c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana restoreCallingIdentity(identityToken); 510c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 511c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 512c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana 513fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 514c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana public void removePeriodicSync(Account account, String authority, Bundle extras) { 515632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams if (account == null) { 516632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams throw new IllegalArgumentException("Account must not be null"); 517632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams } 518632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams if (TextUtils.isEmpty(authority)) { 519632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams throw new IllegalArgumentException("Authority must not be empty"); 520632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams } 521c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 522c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana "no permission to write the sync settings"); 52304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 524632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 525c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long identityToken = clearCallingIdentity(); 526c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana try { 527fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams PeriodicSync syncToRemove = new PeriodicSync(account, authority, extras, 528fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams 0 /* Not read for removal */, 0 /* Not read for removal */); 529fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams getSyncManager().getSyncStorageEngine().removePeriodicSync(syncToRemove, userId); 530c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } finally { 531c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana restoreCallingIdentity(identityToken); 532c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 533c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 534c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana 535fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams /** 536fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * TODO: Implement. 537fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * @param request Sync to remove. 538fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams */ 539fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams public void removeSync(SyncRequest request) { 540fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams 541fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams } 542fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams 543fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 544c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName) { 545632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams if (account == null) { 546632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams throw new IllegalArgumentException("Account must not be null"); 547632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams } 548632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams if (TextUtils.isEmpty(providerName)) { 549632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams throw new IllegalArgumentException("Authority must not be empty"); 550632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams } 551c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 552c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana "no permission to read the sync settings"); 55304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 554632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 555c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana long identityToken = clearCallingIdentity(); 556c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana try { 557c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana return getSyncManager().getSyncStorageEngine().getPeriodicSyncs( 55804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName); 559c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } finally { 560c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana restoreCallingIdentity(identityToken); 561c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 562c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 563c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana 5645e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana public int getIsSyncable(Account account, String providerName) { 5655e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 5665e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana "no permission to read the sync settings"); 567f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 56804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 5695e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana long identityToken = clearCallingIdentity(); 5705e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana try { 5715e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana SyncManager syncManager = getSyncManager(); 5725e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana if (syncManager != null) { 5739422bdca314064fe82075b90cf529865c8053c44Amith Yamasani return syncManager.getIsSyncable( 57404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName); 5755e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 5765e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } finally { 5775e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana restoreCallingIdentity(identityToken); 5785e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 5795e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana return -1; 5805e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 5815e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana 582fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 5835e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana public void setIsSyncable(Account account, String providerName, int syncable) { 584632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams if (TextUtils.isEmpty(providerName)) { 585632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams throw new IllegalArgumentException("Authority must not be empty"); 586632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams } 5875e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 5885e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana "no permission to write the sync settings"); 58904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 590632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 5915e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana long identityToken = clearCallingIdentity(); 5925e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana try { 5935e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana SyncManager syncManager = getSyncManager(); 5945e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana if (syncManager != null) { 5955e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana syncManager.getSyncStorageEngine().setIsSyncable( 59604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, providerName, syncable); 5975e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 5985e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } finally { 5995e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana restoreCallingIdentity(identityToken); 6005e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 6015e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana } 6025e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana 603fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 604ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public boolean getMasterSyncAutomatically() { 605231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, 606231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync settings"); 60704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 608632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 609231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 610231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 611231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 612231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 61304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani return syncManager.getSyncStorageEngine().getMasterSyncAutomatically(userId); 614231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 615231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 616231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 617231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 618231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 619231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 620b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 621fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams @Override 622ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public void setMasterSyncAutomatically(boolean flag) { 623231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, 624231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to write the sync settings"); 62504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 626632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 627231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 628231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 629231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 630231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 63104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani syncManager.getSyncStorageEngine().setMasterSyncAutomatically(flag, userId); 632231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 633231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 634231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 635231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 636231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 637231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 6387a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn public boolean isSyncActive(Account account, String authority) { 639231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 640231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync stats"); 641f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn int userId = UserHandle.getCallingUserId(); 64204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 643231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 644231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 645231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 646231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 647231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return syncManager.getSyncStorageEngine().isSyncActive( 64804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, authority); 649231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 650231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 651231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 652231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 653231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 654231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 655b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 656c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana public List<SyncInfo> getCurrentSyncs() { 657231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 658231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync stats"); 65904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 660632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 661231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 662231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 66304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani return getSyncManager().getSyncStorageEngine().getCurrentSyncs(userId); 664231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 665231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 666231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 667231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 668b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 669ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public SyncStatusInfo getSyncStatus(Account account, String authority) { 670632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams if (TextUtils.isEmpty(authority)) { 671632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams throw new IllegalArgumentException("Authority must not be empty"); 672632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams } 673231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 674231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync stats"); 67504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 676632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 677231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 678231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 679231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 680231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 681b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache return syncManager.getSyncStorageEngine().getStatusByAccountAndAuthority( 68204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani account, userId, authority); 683231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 684231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 685231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 686231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 687231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return null; 688231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 689b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 690ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana public boolean isSyncPending(Account account, String authority) { 691231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, 692231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn "no permission to read the sync stats"); 69304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani 694632515b9d0960749ddb1636677d7f12f196d73f7Matthew Williams int userId = UserHandle.getCallingUserId(); 695231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 696231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 697231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 698231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn if (syncManager != null) { 69904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani return syncManager.getSyncStorageEngine().isSyncPending(account, userId, authority); 700231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 701231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 702231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 703231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 704231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return false; 705231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 706b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 707231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public void addStatusChangeListener(int mask, ISyncStatusObserver callback) { 708231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 709231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 710231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 7111b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana if (syncManager != null && callback != null) { 712ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback); 713231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 714231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 715231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 716231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 717231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 718b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 719231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public void removeStatusChangeListener(ISyncStatusObserver callback) { 720231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn long identityToken = clearCallingIdentity(); 721231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn try { 722231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn SyncManager syncManager = getSyncManager(); 7231b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana if (syncManager != null && callback != null) { 724ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana syncManager.getSyncStorageEngine().removeStatusChangeListener(callback); 725231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 726231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } finally { 727231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn restoreCallingIdentity(identityToken); 728231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 729231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 730b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache 73126ff6626fc4ee0ae46f01ad309b366921da589feKenny Root public static ContentService main(Context context, boolean factoryTest) { 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentService service = new ContentService(context, factoryTest); 733231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service); 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return service; 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Hide this class since it is not part of api, 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but current unittest framework requires it to be public 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final class ObserverNode { 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class ObserverEntry implements IBinder.DeathRecipient { 744002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public final IContentObserver observer; 7451b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public final int uid; 7461b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public final int pid; 74716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate public final boolean notifyForDescendants; 74816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate private final int userHandle; 749002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana private final Object observersLock; 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7511b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public ObserverEntry(IContentObserver o, boolean n, Object observersLock, 75216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int _uid, int _pid, int _userHandle) { 753002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana this.observersLock = observersLock; 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project observer = o; 7551b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn uid = _uid; 7561b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pid = _pid; 75716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate userHandle = _userHandle; 75816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate notifyForDescendants = n; 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project observer.asBinder().linkToDeath(this, 0); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException e) { 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binderDied(); 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void binderDied() { 767002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana synchronized (observersLock) { 768002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana removeObserverLocked(observer); 769002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7711b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn 7721b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, 7731b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn String name, String prefix, SparseIntArray pidCounts) { 7741b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pidCounts.put(pid, pidCounts.get(pid)+1); 7751b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(prefix); pw.print(name); pw.print(": pid="); 7761b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.print(pid); pw.print(" uid="); 77716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate pw.print(uid); pw.print(" user="); 77816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate pw.print(userHandle); pw.print(" target="); 7791b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pw.println(Integer.toHexString(System.identityHashCode( 7801b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn observer != null ? observer.asBinder() : null))); 7811b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int INSERT_TYPE = 0; 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int UPDATE_TYPE = 1; 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int DELETE_TYPE = 2; 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mName; 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>(); 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>(); 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ObserverNode(String name) { 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName = name; 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7961b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, 7971b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn String name, String prefix, int[] counts, SparseIntArray pidCounts) { 7981b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn String innerName = null; 7991b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (mObservers.size() > 0) { 8001b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if ("".equals(name)) { 8011b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = mName; 8021b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } else { 8031b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = name + "/" + mName; 8041b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 8051b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<mObservers.size(); i++) { 8061b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn counts[1]++; 8071b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn mObservers.get(i).dumpLocked(fd, pw, args, innerName, prefix, 8081b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn pidCounts); 8091b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 8101b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 8111b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (mChildren.size() > 0) { 8121b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if (innerName == null) { 8131b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn if ("".equals(name)) { 8141b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = mName; 8151b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } else { 8161b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn innerName = name + "/" + mName; 8171b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 8181b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 8191b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn for (int i=0; i<mChildren.size(); i++) { 8201b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn counts[0]++; 8211b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn mChildren.get(i).dumpLocked(fd, pw, args, innerName, prefix, 8221b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn counts, pidCounts); 8231b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 8241b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 8251b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn } 8261b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String getUriSegment(Uri uri, int index) { 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uri != null) { 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index == 0) { 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return uri.getAuthority(); 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return uri.getPathSegments().get(index - 1); 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int countUriSegments(Uri uri) { 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uri == null) { 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return uri.getPathSegments().size() + 1; 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 84616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Invariant: userHandle is either a hard user number or is USER_ALL 847002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public void addObserverLocked(Uri uri, IContentObserver observer, 84816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean notifyForDescendants, Object observersLock, 84916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int uid, int pid, int userHandle) { 85016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate addObserverLocked(uri, 0, observer, notifyForDescendants, observersLock, 85116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate uid, pid, userHandle); 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 854002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana private void addObserverLocked(Uri uri, int index, IContentObserver observer, 85516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean notifyForDescendants, Object observersLock, 85616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate int uid, int pid, int userHandle) { 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If this is the leaf node add the observer 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index == countUriSegments(uri)) { 85916aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock, 86016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate uid, pid, userHandle)); 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Look to see if the proper child already exists 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String segment = getUriSegment(uri, index); 866f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam if (segment == null) { 867f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer"); 868f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam } 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = mChildren.size(); 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode node = mChildren.get(i); 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (node.mName.equals(segment)) { 87316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate node.addObserverLocked(uri, index + 1, observer, notifyForDescendants, 87416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate observersLock, uid, pid, userHandle); 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No child found, create one 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode node = new ObserverNode(segment); 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildren.add(node); 88216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate node.addObserverLocked(uri, index + 1, observer, notifyForDescendants, 88316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate observersLock, uid, pid, userHandle); 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 886002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public boolean removeObserverLocked(IContentObserver observer) { 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = mChildren.size(); 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 889002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana boolean empty = mChildren.get(i).removeObserverLocked(observer); 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (empty) { 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildren.remove(i); 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i--; 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size--; 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder observerBinder = observer.asBinder(); 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size = mObservers.size(); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverEntry entry = mObservers.get(i); 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (entry.observer.asBinder() == observerBinder) { 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mObservers.remove(i); 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We no longer need to listen for death notifications. Remove it. 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project observerBinder.unlinkToDeath(entry, 0); 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mChildren.size() == 0 && mObservers.size() == 0) { 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 915002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana private void collectMyObserversLocked(boolean leaf, IContentObserver observer, 91616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, int targetUserHandle, 91716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate ArrayList<ObserverCall> calls) { 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = mObservers.size(); 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder observerBinder = observer == null ? null : observer.asBinder(); 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverEntry entry = mObservers.get(i); 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 92316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Don't notify the observer if it sent the notification and isn't interested 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // in self notifications 92586de0590b94bcce27e3038c27464bed510bb564aJeff Brown boolean selfChange = (entry.observer.asBinder() == observerBinder); 92686de0590b94bcce27e3038c27464bed510bb564aJeff Brown if (selfChange && !observerWantsSelfNotifications) { 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 93016aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Does this observer match the target user? 93116aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (targetUserHandle == UserHandle.USER_ALL 93216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate || entry.userHandle == UserHandle.USER_ALL 93316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate || targetUserHandle == entry.userHandle) { 93416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Make sure the observer is interested in the notification 93516aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate if (leaf || (!leaf && entry.notifyForDescendants)) { 93616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate calls.add(new ObserverCall(this, entry.observer, selfChange)); 93716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate } 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 94216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate /** 94316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate * targetUserHandle is either a hard user handle or is USER_ALL 94416aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate */ 945002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana public void collectObserversLocked(Uri uri, int index, IContentObserver observer, 94616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate boolean observerWantsSelfNotifications, int targetUserHandle, 94716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate ArrayList<ObserverCall> calls) { 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String segment = null; 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int segmentCount = countUriSegments(uri); 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index >= segmentCount) { 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is the leaf node, notify all observers 95216aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate collectMyObserversLocked(true, observer, observerWantsSelfNotifications, 95316aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate targetUserHandle, calls); 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (index < segmentCount){ 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project segment = getUriSegment(uri, index); 95616aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate // Notify any observers at this level who are interested in descendants 95716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate collectMyObserversLocked(false, observer, observerWantsSelfNotifications, 95816aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate targetUserHandle, calls); 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = mChildren.size(); 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ObserverNode node = mChildren.get(i); 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (segment == null || node.mName.equals(segment)) { 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We found the child, 96686de0590b94bcce27e3038c27464bed510bb564aJeff Brown node.collectObserversLocked(uri, index + 1, 96716aa9736175f5bbe924a6e5587a2ca47c2dd702bChristopher Tate observer, observerWantsSelfNotifications, targetUserHandle, calls); 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (segment != null) { 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 976