ContentService.java revision b752098e8d12d6e7925d97458078dbb896ca8a05
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;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
25231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Parcel;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.Manifest;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
39231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornpublic final class ContentService extends IContentService.Stub {
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "ContentService";
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mContext;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mFactoryTest;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final ObserverNode mRootNode = new ObserverNode("");
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private SyncManager mSyncManager = null;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Object mSyncManagerLock = new Object();
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private SyncManager getSyncManager() {
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mSyncManagerLock) {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Try to create the SyncManager, return null if it fails (e.g. the disk is full).
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest);
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (SQLiteException e) {
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "Can't create SyncManager", e);
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mSyncManager;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP,
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "caller doesn't have the DUMP permission");
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This makes it so that future permission checks will be in the context of this
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // process rather than the caller's process. We will restore this before returning.
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identityToken = clearCallingIdentity();
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mSyncManager == null) {
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("No SyncManager created!  (Disk full?)");
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSyncManager.dump(fd, pw);
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            restoreCallingIdentity(identityToken);
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
78231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    @Override
79231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
80231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            throws RemoteException {
81231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
82231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return super.onTransact(code, data, reply, flags);
83231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (RuntimeException e) {
84231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // The content service only throws security exceptions, so let's
85231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // log all others.
86231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (!(e instanceof SecurityException)) {
87231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.e(TAG, "Content Service Crash", e);
88231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
89231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            throw e;
90231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
91231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
92231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*package*/ ContentService(Context context, boolean factoryTest) {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFactoryTest = factoryTest;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        getSyncManager();
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void registerContentObserver(Uri uri, boolean notifyForDescendents,
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IContentObserver observer) {
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer == null || uri == null) {
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("You must pass a valid uri and observer");
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mRootNode) {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRootNode.addObserver(uri, observer, notifyForDescendents);
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGV) Log.v(TAG, "Registered observer " + observer + " at " + uri +
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " with notifyForDescendents " + notifyForDescendents);
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterContentObserver(IContentObserver observer) {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer == null) {
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("You must pass a valid observer");
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mRootNode) {
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRootNode.removeObserver(observer);
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGV) Log.v(TAG, "Unregistered observer " + observer);
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void notifyChange(Uri uri, IContentObserver observer,
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean observerWantsSelfNotifications, boolean syncToNetwork) {
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Log.isLoggable(TAG, Log.VERBOSE)) {
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.v(TAG, "Notifying update of " + uri + " from observer " + observer
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", syncToNetwork " + syncToNetwork);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This makes it so that future permission checks will be in the context of this
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // process rather than the caller's process. We will restore this before returning.
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identityToken = clearCallingIdentity();
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mRootNode) {
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRootNode.collectObservers(uri, 0, observer, observerWantsSelfNotifications,
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        calls);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int numCalls = calls.size();
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<numCalls; i++) {
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ObserverCall oc = calls.get(i);
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    oc.mObserver.onChange(oc.mSelfNotify);
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri);
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException ex) {
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (mRootNode) {
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.w(TAG, "Found dead observer, removing");
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        IBinder binder = oc.mObserver.asBinder();
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final ArrayList<ObserverNode.ObserverEntry> list
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                = oc.mNode.mObservers;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int numList = list.size();
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        for (int j=0; j<numList; j++) {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            ObserverNode.ObserverEntry oe = list.get(j);
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (oe.observer.asBinder() == binder) {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                list.remove(j);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                j--;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                numList--;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (syncToNetwork) {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                SyncManager syncManager = getSyncManager();
164ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                if (syncManager != null) {
165ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    syncManager.scheduleLocalSync(null /* all accounts */, uri.getAuthority());
166ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            restoreCallingIdentity(identityToken);
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Hide this class since it is not part of api,
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but current unittest framework requires it to be public
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final class ObserverCall {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ObserverNode mNode;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IContentObserver mObserver;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean mSelfNotify;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ObserverCall(ObserverNode node, IContentObserver observer,
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean selfNotify) {
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNode = node;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mObserver = observer;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSelfNotify = selfNotify;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
192ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void requestSync(Account account, String authority, Bundle extras) {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentResolver.validateSyncExtrasBundle(extras);
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This makes it so that future permission checks will be in the context of this
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // process rather than the caller's process. We will restore this before returning.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identityToken = clearCallingIdentity();
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SyncManager syncManager = getSyncManager();
199ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (syncManager != null) {
2004a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana                syncManager.scheduleSync(account, authority, extras, 0 /* no delay */,
2014a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana                        false /* onlyThoseWithUnkownSyncableState */);
202ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            }
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            restoreCallingIdentity(identityToken);
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clear all scheduled sync operations that match the uri and cancel the active sync
210ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * if they match the authority and account, if they are present.
211ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param account filter the pending and active syncs to cancel using this account
212ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @param authority filter the pending and active syncs to cancel using this authority
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
214ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void cancelSync(Account account, String authority) {
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This makes it so that future permission checks will be in the context of this
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // process rather than the caller's process. We will restore this before returning.
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identityToken = clearCallingIdentity();
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SyncManager syncManager = getSyncManager();
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (syncManager != null) {
221ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.clearScheduledSyncOperations(account, authority);
222ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.cancelActiveSync(account, authority);
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            restoreCallingIdentity(identityToken);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    /**
230ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * Get information about the SyncAdapters that are known to the system.
231ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     * @return an array of SyncAdapters that have registered with the system
232ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana     */
233ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public SyncAdapterType[] getSyncAdapterTypes() {
234ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        // This makes it so that future permission checks will be in the context of this
235ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        // process rather than the caller's process. We will restore this before returning.
236ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        long identityToken = clearCallingIdentity();
237ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        try {
238ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            SyncManager syncManager = getSyncManager();
239ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            return syncManager.getSyncAdapterTypes();
240ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        } finally {
241ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            restoreCallingIdentity(identityToken);
242ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        }
243ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    }
244b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
245ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean getSyncAutomatically(Account account, String providerName) {
246231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
247231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync settings");
248231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
249231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
250231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
251231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
252ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                return syncManager.getSyncStorageEngine().getSyncAutomatically(
253ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        account, providerName);
254231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
255231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
256231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
257231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
258231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
259231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
260231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
261ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void setSyncAutomatically(Account account, String providerName, boolean sync) {
262231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
263231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to write the sync settings");
264231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
265231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
266231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
267231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
268ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.getSyncStorageEngine().setSyncAutomatically(
269ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        account, providerName, sync);
270231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
271231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
272231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
273231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
274231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
275231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
2765e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    public int getIsSyncable(Account account, String providerName) {
2775e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
2785e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                "no permission to read the sync settings");
2795e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        long identityToken = clearCallingIdentity();
2805e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        try {
2815e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            SyncManager syncManager = getSyncManager();
2825e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            if (syncManager != null) {
2835e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                return syncManager.getSyncStorageEngine().getIsSyncable(
2845e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                        account, providerName);
2855e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            }
2865e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        } finally {
2875e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            restoreCallingIdentity(identityToken);
2885e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
2895e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        return -1;
2905e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
2915e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
2925e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    public void setIsSyncable(Account account, String providerName, int syncable) {
2935e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
2945e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                "no permission to write the sync settings");
2955e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        long identityToken = clearCallingIdentity();
2965e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        try {
2975e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            SyncManager syncManager = getSyncManager();
2985e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            if (syncManager != null) {
2995e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                syncManager.getSyncStorageEngine().setIsSyncable(
3005e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                        account, providerName, syncable);
3015e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            }
3025e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        } finally {
3035e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            restoreCallingIdentity(identityToken);
3045e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
3055e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
3065e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
307ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean getMasterSyncAutomatically() {
308231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
309231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync settings");
310231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
311231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
312231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
313231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
314ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                return syncManager.getSyncStorageEngine().getMasterSyncAutomatically();
315231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
316231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
317231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
318231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
319231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
320231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
321b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
322ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void setMasterSyncAutomatically(boolean flag) {
323231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
324231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to write the sync settings");
325231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
326231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
327231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
328231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
329ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.getSyncStorageEngine().setMasterSyncAutomatically(flag);
330231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
331231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
332231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
333231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
334231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
335231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
3367a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public boolean isSyncActive(Account account, String authority) {
337231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
338231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync stats");
339231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
340231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
341231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
342231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
343231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return syncManager.getSyncStorageEngine().isSyncActive(
344231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        account, authority);
345231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
346231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
347231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
348231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
349231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
350231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
351b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
352231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ActiveSyncInfo getActiveSync() {
353231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
354231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync stats");
355231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
356231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
357231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
358231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
359231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return syncManager.getSyncStorageEngine().getActiveSync();
360231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
361231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
362231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
363231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
364231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return null;
365231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
366b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
367ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public SyncStatusInfo getSyncStatus(Account account, String authority) {
368231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
369231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync stats");
370231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
373231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
374b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                return syncManager.getSyncStorageEngine().getStatusByAccountAndAuthority(
375b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                    account, authority);
376231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
377231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
378231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
379231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
380231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return null;
381231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
382b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
383ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean isSyncPending(Account account, String authority) {
384231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
385231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                "no permission to read the sync stats");
386231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
387231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
388231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
389231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
390ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                return syncManager.getSyncStorageEngine().isSyncPending(account, authority);
391231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
392231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
393231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
394231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
395231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
396231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
397b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
398231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
399231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
400231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
401231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
402231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
403ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback);
404231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
405231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
406231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
407231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
408231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
409b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
410231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void removeStatusChangeListener(ISyncStatusObserver callback) {
411231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long identityToken = clearCallingIdentity();
412231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
413231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncManager syncManager = getSyncManager();
414231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (syncManager != null) {
415ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                syncManager.getSyncStorageEngine().removeStatusChangeListener(callback);
416231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
417231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
418231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            restoreCallingIdentity(identityToken);
419231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
420231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
421b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static IContentService main(Context context, boolean factoryTest) {
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentService service = new ContentService(context, factoryTest);
424231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return service;
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Hide this class since it is not part of api,
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but current unittest framework requires it to be public
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final class ObserverNode {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private class ObserverEntry implements IBinder.DeathRecipient {
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public IContentObserver observer;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public boolean notifyForDescendents;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public ObserverEntry(IContentObserver o, boolean n) {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                observer = o;
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notifyForDescendents = n;
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    observer.asBinder().linkToDeath(this, 0);
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    binderDied();
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void binderDied() {
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeObserver(observer);
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int INSERT_TYPE = 0;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int UPDATE_TYPE = 1;
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int DELETE_TYPE = 2;
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private String mName;
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>();
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>();
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ObserverNode(String name) {
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mName = name;
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private String getUriSegment(Uri uri, int index) {
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (uri != null) {
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (index == 0) {
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return uri.getAuthority();
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return uri.getPathSegments().get(index - 1);
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int countUriSegments(Uri uri) {
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (uri == null) {
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return uri.getPathSegments().size() + 1;
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void addObserver(Uri uri, IContentObserver observer, boolean notifyForDescendents) {
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            addObserver(uri, 0, observer, notifyForDescendents);
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void addObserver(Uri uri, int index, IContentObserver observer,
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean notifyForDescendents) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If this is the leaf node add the observer
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (index == countUriSegments(uri)) {
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mObservers.add(new ObserverEntry(observer, notifyForDescendents));
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Look to see if the proper child already exists
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String segment = getUriSegment(uri, index);
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mChildren.size();
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < N; i++) {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ObserverNode node = mChildren.get(i);
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (node.mName.equals(segment)) {
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    node.addObserver(uri, index + 1, observer, notifyForDescendents);
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return;
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // No child found, create one
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ObserverNode node = new ObserverNode(segment);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mChildren.add(node);
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            node.addObserver(uri, index + 1, observer, notifyForDescendents);
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean removeObserver(IContentObserver observer) {
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mChildren.size();
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean empty = mChildren.get(i).removeObserver(observer);
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (empty) {
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mChildren.remove(i);
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i--;
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IBinder observerBinder = observer.asBinder();
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size = mObservers.size();
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ObserverEntry entry = mObservers.get(i);
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (entry.observer.asBinder() == observerBinder) {
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mObservers.remove(i);
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We no longer need to listen for death notifications. Remove it.
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    observerBinder.unlinkToDeath(entry, 0);
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mChildren.size() == 0 && mObservers.size() == 0) {
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void collectMyObservers(Uri uri,
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean leaf, IContentObserver observer, boolean selfNotify,
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ArrayList<ObserverCall> calls)
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mObservers.size();
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IBinder observerBinder = observer == null ? null : observer.asBinder();
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < N; i++) {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ObserverEntry entry = mObservers.get(i);
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Don't notify the observer if it sent the notification and isn't interesed
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // in self notifications
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (entry.observer.asBinder() == observerBinder && !selfNotify) {
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Make sure the observer is interested in the notification
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (leaf || (!leaf && entry.notifyForDescendents)) {
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    calls.add(new ObserverCall(this, entry.observer, selfNotify));
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void collectObservers(Uri uri, int index, IContentObserver observer,
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean selfNotify, ArrayList<ObserverCall> calls) {
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String segment = null;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int segmentCount = countUriSegments(uri);
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (index >= segmentCount) {
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // This is the leaf node, notify all observers
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                collectMyObservers(uri, true, observer, selfNotify, calls);
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (index < segmentCount){
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                segment = getUriSegment(uri, index);
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Notify any observers at this level who are interested in descendents
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                collectMyObservers(uri, false, observer, selfNotify, calls);
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mChildren.size();
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < N; i++) {
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ObserverNode node = mChildren.get(i);
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (segment == null || node.mName.equals(segment)) {
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We found the child,
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    node.collectObservers(uri, index + 1, observer, selfNotify, calls);
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (segment != null) {
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
592