ContentService.java revision 86de0590b94bcce27e3038c27464bed510bb564a
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.content;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
197a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackbornimport android.accounts.Account;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.IContentObserver;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteException;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
231b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport android.os.Binder;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
26231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Parcel;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
301b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport android.util.SparseIntArray;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.Manifest;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
361b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport java.util.Collections;
371b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackbornimport java.util.Comparator;
38c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintanaimport java.util.List;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
43231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornpublic final class ContentService extends IContentService.Stub {
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "ContentService";
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mContext;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mFactoryTest;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final ObserverNode mRootNode = new ObserverNode("");
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private SyncManager mSyncManager = null;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Object mSyncManagerLock = new Object();
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private SyncManager getSyncManager() {
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mSyncManagerLock) {
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Try to create the SyncManager, return null if it fails (e.g. the disk is full).
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest);
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (SQLiteException e) {
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "Can't create SyncManager", e);
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSyncManager;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP,
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "caller doesn't have the DUMP permission");
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This makes it so that future permission checks will be in the context of this
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // process rather than the caller's process. We will restore this before returning.
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identityToken = clearCallingIdentity();
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mSyncManager == null) {
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("No SyncManager created!  (Disk full?)");
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSyncManager.dump(fd, pw);
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
771b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            pw.println();
781b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            pw.println("Observer tree:");
791b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            synchronized (mRootNode) {
801b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                int[] counts = new int[2];
811b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                final SparseIntArray pidCounts = new SparseIntArray();
821b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                mRootNode.dumpLocked(fd, pw, args, "", "  ", counts, pidCounts);
831b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                pw.println();
841b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                ArrayList<Integer> sorted = new ArrayList<Integer>();
851b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                for (int i=0; i<pidCounts.size(); i++) {
861b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    sorted.add(pidCounts.keyAt(i));
871b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                }
881b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                Collections.sort(sorted, new Comparator<Integer>() {
891b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    @Override
901b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    public int compare(Integer lhs, Integer rhs) {
911b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        int lc = pidCounts.get(lhs);
921b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        int rc = pidCounts.get(rhs);
931b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        if (lc < rc) {
941b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                            return 1;
951b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        } else if (lc > rc) {
961b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                            return -1;
971b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        }
981b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        return 0;
991b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    }
1001b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn
1011b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                });
1021b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                for (int i=0; i<sorted.size(); i++) {
1031b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    int pid = sorted.get(i);
1041b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    pw.print("  pid "); pw.print(pid); pw.print(": ");
1051b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                            pw.print(pidCounts.get(pid)); pw.println(" observers");
1061b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                }
1071b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                pw.println();
1081b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                pw.print(" Total number of nodes: "); pw.println(counts[0]);
1091b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                pw.print(" Total number of observers: "); pw.println(counts[1]);
1101b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            }
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            restoreCallingIdentity(identityToken);
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
116231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    @Override
117231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
118231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            throws RemoteException {
119231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
120231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return super.onTransact(code, data, reply, flags);
121231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (RuntimeException e) {
122231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // The content service only throws security exceptions, so let's
123231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // log all others.
124231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (!(e instanceof SecurityException)) {
125231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.e(TAG, "Content Service Crash", e);
126231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            throw e;
128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
129231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*package*/ ContentService(Context context, boolean factoryTest) {
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFactoryTest = factoryTest;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        getSyncManager();
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void registerContentObserver(Uri uri, boolean notifyForDescendents,
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IContentObserver observer) {
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer == null || uri == null) {
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("You must pass a valid uri and observer");
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mRootNode) {
1431b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            mRootNode.addObserverLocked(uri, observer, notifyForDescendents, mRootNode,
1441b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    Binder.getCallingUid(), Binder.getCallingPid());
14543a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato            if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " with notifyForDescendents " + notifyForDescendents);
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterContentObserver(IContentObserver observer) {
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer == null) {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("You must pass a valid observer");
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mRootNode) {
155002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana            mRootNode.removeObserverLocked(observer);
15643a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato            if (false) Log.v(TAG, "Unregistered observer " + observer);
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void notifyChange(Uri uri, IContentObserver observer,
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean observerWantsSelfNotifications, boolean syncToNetwork) {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Log.isLoggable(TAG, Log.VERBOSE)) {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.v(TAG, "Notifying update of " + uri + " from observer " + observer
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", syncToNetwork " + syncToNetwork);
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This makes it so that future permission checks will be in the context of this
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // process rather than the caller's process. We will restore this before returning.
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identityToken = clearCallingIdentity();
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mRootNode) {
172002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana                mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        calls);
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int numCalls = calls.size();
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<numCalls; i++) {
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ObserverCall oc = calls.get(i);
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
17986de0590b94bcce27e3038c27464bed510bb564aJeff Brown                    oc.mObserver.onChange(oc.mSelfChange);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri);
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException ex) {
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (mRootNode) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.w(TAG, "Found dead observer, removing");
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        IBinder binder = oc.mObserver.asBinder();
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final ArrayList<ObserverNode.ObserverEntry> list
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                = oc.mNode.mObservers;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int numList = list.size();
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        for (int j=0; j<numList; j++) {
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            ObserverNode.ObserverEntry oe = list.get(j);
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (oe.observer.asBinder() == binder) {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                list.remove(j);
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                j--;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                numList--;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (syncToNetwork) {
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                SyncManager syncManager = getSyncManager();
203ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                if (syncManager != null) {
204ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    syncManager.scheduleLocalSync(null /* all accounts */, uri.getAuthority());
205ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                }
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            restoreCallingIdentity(identityToken);
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Hide this class since it is not part of api,
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but current unittest framework requires it to be public
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final class ObserverCall {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ObserverNode mNode;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IContentObserver mObserver;
22186de0590b94bcce27e3038c27464bed510bb564aJeff Brown        final boolean mSelfChange;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22386de0590b94bcce27e3038c27464bed510bb564aJeff Brown        ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange) {
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNode = node;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mObserver = observer;
22686de0590b94bcce27e3038c27464bed510bb564aJeff Brown            mSelfChange = selfChange;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
230ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void requestSync(Account account, String authority, Bundle extras) {
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentResolver.validateSyncExtrasBundle(extras);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This makes it so that future permission checks will be in the context of this
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // process rather than the caller's process. We will restore this before returning.
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identityToken = clearCallingIdentity();
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SyncManager syncManager = getSyncManager();
237ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (syncManager != null) {
2384a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana                syncManager.scheduleSync(account, authority, extras, 0 /* no delay */,
2394a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana                        false /* onlyThoseWithUnkownSyncableState */);
240ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            }
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            restoreCallingIdentity(identityToken);
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clear all scheduled sync operations that match the uri and cancel the active sync
248ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * if they match the authority and account, if they are present.
249ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param account filter the pending and active syncs to cancel using this account
250ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param authority filter the pending and active syncs to cancel using this authority
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
252ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void cancelSync(Account account, String authority) {
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This makes it so that future permission checks will be in the context of this
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // process rather than the caller's process. We will restore this before returning.
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identityToken = clearCallingIdentity();
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SyncManager syncManager = getSyncManager();
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (syncManager != null) {
259ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.clearScheduledSyncOperations(account, authority);
260ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.cancelActiveSync(account, authority);
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            restoreCallingIdentity(identityToken);
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
267ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
268ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * Get information about the SyncAdapters that are known to the system.
269ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @return an array of SyncAdapters that have registered with the system
270ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
271ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public SyncAdapterType[] getSyncAdapterTypes() {
272ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        // This makes it so that future permission checks will be in the context of this
273ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        // process rather than the caller's process. We will restore this before returning.
274ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        long identityToken = clearCallingIdentity();
275ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
276ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            SyncManager syncManager = getSyncManager();
277ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            return syncManager.getSyncAdapterTypes();
278ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        } finally {
279ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            restoreCallingIdentity(identityToken);
280ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
281ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
282b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
283ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean getSyncAutomatically(Account account, String providerName) {
284231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
285231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync settings");
286231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
287231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
288231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
289231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
290ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                return syncManager.getSyncStorageEngine().getSyncAutomatically(
291ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        account, providerName);
292231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
293231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
294231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
295231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
296231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
297231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
298231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
299ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void setSyncAutomatically(Account account, String providerName, boolean sync) {
300231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
301231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to write the sync settings");
302231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
303231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
304231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
305231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
306ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.getSyncStorageEngine().setSyncAutomatically(
307ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        account, providerName, sync);
308231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
309231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
310231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
311231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
312231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
313231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
314c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public void addPeriodicSync(Account account, String authority, Bundle extras,
315c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            long pollFrequency) {
316c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
317c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                "no permission to write the sync settings");
318c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        long identityToken = clearCallingIdentity();
319c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
320c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            getSyncManager().getSyncStorageEngine().addPeriodicSync(
321c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    account, authority, extras, pollFrequency);
322c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } finally {
323c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            restoreCallingIdentity(identityToken);
324c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
325c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
326c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
327c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public void removePeriodicSync(Account account, String authority, Bundle extras) {
328c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
329c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                "no permission to write the sync settings");
330c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        long identityToken = clearCallingIdentity();
331c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
332c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            getSyncManager().getSyncStorageEngine().removePeriodicSync(account, authority, extras);
333c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } finally {
334c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            restoreCallingIdentity(identityToken);
335c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
336c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
337c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
338c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName) {
339c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
340c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                "no permission to read the sync settings");
341c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        long identityToken = clearCallingIdentity();
342c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
343c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return getSyncManager().getSyncStorageEngine().getPeriodicSyncs(
344c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    account, providerName);
345c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } finally {
346c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            restoreCallingIdentity(identityToken);
347c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
348c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
349c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
3505e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    public int getIsSyncable(Account account, String providerName) {
3515e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
3525e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                "no permission to read the sync settings");
3535e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        long identityToken = clearCallingIdentity();
3545e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        try {
3555e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            SyncManager syncManager = getSyncManager();
3565e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            if (syncManager != null) {
3575e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                return syncManager.getSyncStorageEngine().getIsSyncable(
3585e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                        account, providerName);
3595e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            }
3605e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        } finally {
3615e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            restoreCallingIdentity(identityToken);
3625e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
3635e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        return -1;
3645e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
3655e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
3665e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    public void setIsSyncable(Account account, String providerName, int syncable) {
3675e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
3685e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                "no permission to write the sync settings");
3695e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        long identityToken = clearCallingIdentity();
3705e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        try {
3715e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            SyncManager syncManager = getSyncManager();
3725e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            if (syncManager != null) {
3735e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                syncManager.getSyncStorageEngine().setIsSyncable(
3745e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                        account, providerName, syncable);
3755e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            }
3765e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        } finally {
3775e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            restoreCallingIdentity(identityToken);
3785e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
3795e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
3805e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
381ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean getMasterSyncAutomatically() {
382231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
383231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync settings");
384231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
385231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
386231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
387231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
388ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                return syncManager.getSyncStorageEngine().getMasterSyncAutomatically();
389231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
390231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
391231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
392231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
393231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
394231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
395b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
396ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void setMasterSyncAutomatically(boolean flag) {
397231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
398231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to write the sync settings");
399231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
400231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
401231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
402231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
403ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.getSyncStorageEngine().setMasterSyncAutomatically(flag);
404231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
405231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
406231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
407231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
408231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
409231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
4107a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public boolean isSyncActive(Account account, String authority) {
411231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
412231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync stats");
413231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
414231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
415231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
416231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
417231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return syncManager.getSyncStorageEngine().isSyncActive(
418231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        account, authority);
419231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
420231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
421231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
422231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
423231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
424231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
425b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
426c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana    public List<SyncInfo> getCurrentSyncs() {
427231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
428231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync stats");
429231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
430231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
431c6a69559cb62bd20166c0c9684e64c60d779da38Fred Quintana            return getSyncManager().getSyncStorageEngine().getCurrentSyncs();
432231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
433231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
434231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
435231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
436b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
437ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public SyncStatusInfo getSyncStatus(Account account, String authority) {
438231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
439231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync stats");
440231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
441231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
442231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
443231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
444b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                return syncManager.getSyncStorageEngine().getStatusByAccountAndAuthority(
445b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                    account, authority);
446231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
447231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
448231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
449231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
450231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return null;
451231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
452b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
453ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean isSyncPending(Account account, String authority) {
454231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
455231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync stats");
456231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
457231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
458231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
459231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
460ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                return syncManager.getSyncStorageEngine().isSyncPending(account, authority);
461231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
462231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
463231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
464231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
465231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
466231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
467b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
468231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
469231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
470231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
471231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
4721b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana            if (syncManager != null && callback != null) {
473ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback);
474231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
475231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
476231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
477231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
478231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
479b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
480231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void removeStatusChangeListener(ISyncStatusObserver callback) {
481231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
482231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
483231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
4841b487ec44b6b5594914d52fa427bec4f29a60541Fred Quintana            if (syncManager != null && callback != null) {
485ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.getSyncStorageEngine().removeStatusChangeListener(callback);
486231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
487231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
488231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
489231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
490231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
491b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static IContentService main(Context context, boolean factoryTest) {
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentService service = new ContentService(context, factoryTest);
494231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return service;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Hide this class since it is not part of api,
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but current unittest framework requires it to be public
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final class ObserverNode {
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private class ObserverEntry implements IBinder.DeathRecipient {
505002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana            public final IContentObserver observer;
5061b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            public final int uid;
5071b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            public final int pid;
508002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana            public final boolean notifyForDescendents;
509002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana            private final Object observersLock;
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5111b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            public ObserverEntry(IContentObserver o, boolean n, Object observersLock,
5121b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    int _uid, int _pid) {
513002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana                this.observersLock = observersLock;
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                observer = o;
5151b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                uid = _uid;
5161b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                pid = _pid;
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notifyForDescendents = n;
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    observer.asBinder().linkToDeath(this, 0);
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    binderDied();
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void binderDied() {
526002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana                synchronized (observersLock) {
527002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana                    removeObserverLocked(observer);
528002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana                }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5301b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn
5311b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
5321b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    String name, String prefix, SparseIntArray pidCounts) {
5331b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                pidCounts.put(pid, pidCounts.get(pid)+1);
5341b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                pw.print(prefix); pw.print(name); pw.print(": pid=");
5351b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        pw.print(pid); pw.print(" uid=");
5361b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        pw.print(uid); pw.print(" target=");
5371b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        pw.println(Integer.toHexString(System.identityHashCode(
5381b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                                observer != null ? observer.asBinder() : null)));
5391b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            }
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int INSERT_TYPE = 0;
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int UPDATE_TYPE = 1;
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int DELETE_TYPE = 2;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private String mName;
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>();
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>();
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ObserverNode(String name) {
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mName = name;
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5541b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn        public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
5551b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                String name, String prefix, int[] counts, SparseIntArray pidCounts) {
5561b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            String innerName = null;
5571b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            if (mObservers.size() > 0) {
5581b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                if ("".equals(name)) {
5591b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    innerName = mName;
5601b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                } else {
5611b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    innerName = name + "/" + mName;
5621b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                }
5631b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                for (int i=0; i<mObservers.size(); i++) {
5641b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    counts[1]++;
5651b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    mObservers.get(i).dumpLocked(fd, pw, args, innerName, prefix,
5661b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                            pidCounts);
5671b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                }
5681b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            }
5691b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            if (mChildren.size() > 0) {
5701b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                if (innerName == null) {
5711b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    if ("".equals(name)) {
5721b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        innerName = mName;
5731b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    } else {
5741b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        innerName = name + "/" + mName;
5751b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    }
5761b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                }
5771b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                for (int i=0; i<mChildren.size(); i++) {
5781b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    counts[0]++;
5791b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    mChildren.get(i).dumpLocked(fd, pw, args, innerName, prefix,
5801b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                            counts, pidCounts);
5811b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                }
5821b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            }
5831b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn        }
5841b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private String getUriSegment(Uri uri, int index) {
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (uri != null) {
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (index == 0) {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return uri.getAuthority();
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return uri.getPathSegments().get(index - 1);
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int countUriSegments(Uri uri) {
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (uri == null) {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return uri.getPathSegments().size() + 1;
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
604002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana        public void addObserverLocked(Uri uri, IContentObserver observer,
6051b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                boolean notifyForDescendents, Object observersLock, int uid, int pid) {
6061b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            addObserverLocked(uri, 0, observer, notifyForDescendents, observersLock, uid, pid);
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
609002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana        private void addObserverLocked(Uri uri, int index, IContentObserver observer,
6101b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                boolean notifyForDescendents, Object observersLock, int uid, int pid) {
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If this is the leaf node add the observer
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (index == countUriSegments(uri)) {
6131b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                mObservers.add(new ObserverEntry(observer, notifyForDescendents, observersLock,
6141b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                        uid, pid));
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Look to see if the proper child already exists
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String segment = getUriSegment(uri, index);
620f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam            if (segment == null) {
621f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam                throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer");
622f51266471cb6c3e824435ae6e416012a62266d52Anthony Newnam            }
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mChildren.size();
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < N; i++) {
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ObserverNode node = mChildren.get(i);
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (node.mName.equals(segment)) {
6271b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    node.addObserverLocked(uri, index + 1, observer, notifyForDescendents,
6281b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                            observersLock, uid, pid);
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return;
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // No child found, create one
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ObserverNode node = new ObserverNode(segment);
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mChildren.add(node);
6361b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn            node.addObserverLocked(uri, index + 1, observer, notifyForDescendents,
6371b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn                    observersLock, uid, pid);
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
640002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana        public boolean removeObserverLocked(IContentObserver observer) {
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mChildren.size();
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
643002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana                boolean empty = mChildren.get(i).removeObserverLocked(observer);
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (empty) {
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mChildren.remove(i);
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i--;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IBinder observerBinder = observer.asBinder();
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size = mObservers.size();
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ObserverEntry entry = mObservers.get(i);
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (entry.observer.asBinder() == observerBinder) {
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mObservers.remove(i);
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We no longer need to listen for death notifications. Remove it.
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    observerBinder.unlinkToDeath(entry, 0);
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mChildren.size() == 0 && mObservers.size() == 0) {
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
669002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana        private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
67086de0590b94bcce27e3038c27464bed510bb564aJeff Brown                boolean observerWantsSelfNotifications, ArrayList<ObserverCall> calls) {
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mObservers.size();
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IBinder observerBinder = observer == null ? null : observer.asBinder();
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < N; i++) {
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ObserverEntry entry = mObservers.get(i);
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Don't notify the observer if it sent the notification and isn't interesed
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // in self notifications
67886de0590b94bcce27e3038c27464bed510bb564aJeff Brown                boolean selfChange = (entry.observer.asBinder() == observerBinder);
67986de0590b94bcce27e3038c27464bed510bb564aJeff Brown                if (selfChange && !observerWantsSelfNotifications) {
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Make sure the observer is interested in the notification
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (leaf || (!leaf && entry.notifyForDescendents)) {
68586de0590b94bcce27e3038c27464bed510bb564aJeff Brown                    calls.add(new ObserverCall(this, entry.observer, selfChange));
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
690002ffad599964653186c01f8e07fadc82dc0aceeFred Quintana        public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
69186de0590b94bcce27e3038c27464bed510bb564aJeff Brown                boolean observerWantsSelfNotifications, ArrayList<ObserverCall> calls) {
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String segment = null;
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int segmentCount = countUriSegments(uri);
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (index >= segmentCount) {
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // This is the leaf node, notify all observers
69686de0590b94bcce27e3038c27464bed510bb564aJeff Brown                collectMyObserversLocked(true, observer, observerWantsSelfNotifications, calls);
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (index < segmentCount){
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                segment = getUriSegment(uri, index);
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Notify any observers at this level who are interested in descendents
70086de0590b94bcce27e3038c27464bed510bb564aJeff Brown                collectMyObserversLocked(false, observer, observerWantsSelfNotifications, calls);
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mChildren.size();
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < N; i++) {
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ObserverNode node = mChildren.get(i);
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (segment == null || node.mName.equals(segment)) {
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We found the child,
70886de0590b94bcce27e3038c27464bed510bb564aJeff Brown                    node.collectObserversLocked(uri, index + 1,
70986de0590b94bcce27e3038c27464bed510bb564aJeff Brown                            observer, observerWantsSelfNotifications, calls);
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (segment != null) {
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
718