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