19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 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.database;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brownimport android.net.Uri;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
2386de0590b94bcce27e3038c27464bed510bb564aJeff Brown * Receives call backs for changes to content.
2486de0590b94bcce27e3038c27464bed510bb564aJeff Brown * Must be implemented by objects which are added to a {@link ContentObservable}.
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class ContentObserver {
2786de0590b94bcce27e3038c27464bed510bb564aJeff Brown    private final Object mLock = new Object();
2886de0590b94bcce27e3038c27464bed510bb564aJeff Brown    private Transport mTransport; // guarded by mLock
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3086de0590b94bcce27e3038c27464bed510bb564aJeff Brown    Handler mHandler;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3386de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * Creates a content observer.
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3586de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * @param handler The handler to run {@link #onChange} on, or null if none.
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ContentObserver(Handler handler) {
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = handler;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets access to the binder transport object. Not for public consumption.
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public IContentObserver getContentObserver() {
4786de0590b94bcce27e3038c27464bed510bb564aJeff Brown        synchronized (mLock) {
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mTransport == null) {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTransport = new Transport(this);
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mTransport;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets access to the binder transport object, and unlinks the transport object
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from the ContentObserver. Not for public consumption.
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public IContentObserver releaseContentObserver() {
6286de0590b94bcce27e3038c27464bed510bb564aJeff Brown        synchronized (mLock) {
6386de0590b94bcce27e3038c27464bed510bb564aJeff Brown            final Transport oldTransport = mTransport;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (oldTransport != null) {
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                oldTransport.releaseContentObserver();
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTransport = null;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return oldTransport;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7386de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * Returns true if this observer is interested receiving self-change notifications.
7486de0590b94bcce27e3038c27464bed510bb564aJeff Brown     *
7586de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * Subclasses should override this method to indicate whether the observer
7686de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * is interested in receiving notifications for changes that it made to the
7786de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * content itself.
7886de0590b94bcce27e3038c27464bed510bb564aJeff Brown     *
7986de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * @return True if self-change notifications should be delivered to the observer.
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean deliverSelfNotifications() {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8686de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * This method is called when a content change occurs.
87655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * <p>
88655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * Subclasses should override this method to handle content changes.
89655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * </p>
9086de0590b94bcce27e3038c27464bed510bb564aJeff Brown     *
9186de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * @param selfChange True if this is a self-change notification.
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9386de0590b94bcce27e3038c27464bed510bb564aJeff Brown    public void onChange(boolean selfChange) {
9486de0590b94bcce27e3038c27464bed510bb564aJeff Brown        // Do nothing.  Subclass should override.
9586de0590b94bcce27e3038c27464bed510bb564aJeff Brown    }
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9786de0590b94bcce27e3038c27464bed510bb564aJeff Brown    /**
98655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * This method is called when a content change occurs.
99655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * Includes the changed content Uri when available.
100655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * <p>
101655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * Subclasses should override this method to handle content changes.
102655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * To ensure correct operation on older versions of the framework that
103655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * did not provide a Uri argument, applications should also implement
104655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * the {@link #onChange(boolean)} overload of this method whenever they
105655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * implement the {@link #onChange(boolean, Uri)} overload.
106655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * </p><p>
107655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * Example implementation:
108655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * <pre><code>
109655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * // Implement the onChange(boolean) method to delegate the change notification to
110655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * // the onChange(boolean, Uri) method to ensure correct operation on older versions
111655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * // of the framework that did not have the onChange(boolean, Uri) method.
112655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * {@literal @Override}
113655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * public void onChange(boolean selfChange) {
114655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     *     onChange(selfChange, null);
115655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * }
116655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     *
117655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * // Implement the onChange(boolean, Uri) method to take advantage of the new Uri argument.
118655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * {@literal @Override}
119655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * public void onChange(boolean selfChange, Uri uri) {
120655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     *     // Handle change.
121655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * }
122655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * </code></pre>
123655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * </p>
12486de0590b94bcce27e3038c27464bed510bb564aJeff Brown     *
125655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * @param selfChange True if this is a self-change notification.
126655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * @param uri The Uri of the changed content, or null if unknown.
127655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     */
128655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown    public void onChange(boolean selfChange, Uri uri) {
129655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown        onChange(selfChange);
130655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown    }
131655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown
132655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown    /**
133655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * Dispatches a change notification to the observer.
134655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * <p>
13586de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * If a {@link Handler} was supplied to the {@link ContentObserver} constructor,
13686de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * then a call to the {@link #onChange} method is posted to the handler's message queue.
13786de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * Otherwise, the {@link #onChange} method is invoked immediately on this thread.
138655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * </p>
13986de0590b94bcce27e3038c27464bed510bb564aJeff Brown     *
14086de0590b94bcce27e3038c27464bed510bb564aJeff Brown     * @param selfChange True if this is a self-change notification.
141655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     *
142655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * @deprecated Use {@link #dispatchChange(boolean, Uri)} instead.
14386de0590b94bcce27e3038c27464bed510bb564aJeff Brown     */
144655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown    @Deprecated
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final void dispatchChange(boolean selfChange) {
146655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown        dispatchChange(selfChange, null);
147655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown    }
148655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown
149655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown    /**
150655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * Dispatches a change notification to the observer.
151655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * Includes the changed content Uri when available.
152655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * <p>
153655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * If a {@link Handler} was supplied to the {@link ContentObserver} constructor,
154655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * then a call to the {@link #onChange} method is posted to the handler's message queue.
155655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * Otherwise, the {@link #onChange} method is invoked immediately on this thread.
156655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * </p>
157655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     *
158655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * @param selfChange True if this is a self-change notification.
159655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     * @param uri The Uri of the changed content, or null if unknown.
160655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown     */
161655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown    public final void dispatchChange(boolean selfChange, Uri uri) {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mHandler == null) {
163655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown            onChange(selfChange, uri);
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
165655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown            mHandler.post(new NotificationRunnable(selfChange, uri));
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16886de0590b94bcce27e3038c27464bed510bb564aJeff Brown
16986de0590b94bcce27e3038c27464bed510bb564aJeff Brown    private final class NotificationRunnable implements Runnable {
170655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown        private final boolean mSelfChange;
171655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown        private final Uri mUri;
17286de0590b94bcce27e3038c27464bed510bb564aJeff Brown
173655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown        public NotificationRunnable(boolean selfChange, Uri uri) {
174655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown            mSelfChange = selfChange;
175655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown            mUri = uri;
17686de0590b94bcce27e3038c27464bed510bb564aJeff Brown        }
17786de0590b94bcce27e3038c27464bed510bb564aJeff Brown
17886de0590b94bcce27e3038c27464bed510bb564aJeff Brown        @Override
17986de0590b94bcce27e3038c27464bed510bb564aJeff Brown        public void run() {
180655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown            ContentObserver.this.onChange(mSelfChange, mUri);
18186de0590b94bcce27e3038c27464bed510bb564aJeff Brown        }
18286de0590b94bcce27e3038c27464bed510bb564aJeff Brown    }
18386de0590b94bcce27e3038c27464bed510bb564aJeff Brown
18486de0590b94bcce27e3038c27464bed510bb564aJeff Brown    private static final class Transport extends IContentObserver.Stub {
18586de0590b94bcce27e3038c27464bed510bb564aJeff Brown        private ContentObserver mContentObserver;
18686de0590b94bcce27e3038c27464bed510bb564aJeff Brown
18786de0590b94bcce27e3038c27464bed510bb564aJeff Brown        public Transport(ContentObserver contentObserver) {
18886de0590b94bcce27e3038c27464bed510bb564aJeff Brown            mContentObserver = contentObserver;
18986de0590b94bcce27e3038c27464bed510bb564aJeff Brown        }
19086de0590b94bcce27e3038c27464bed510bb564aJeff Brown
19186de0590b94bcce27e3038c27464bed510bb564aJeff Brown        @Override
192655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown        public void onChange(boolean selfChange, Uri uri) {
19386de0590b94bcce27e3038c27464bed510bb564aJeff Brown            ContentObserver contentObserver = mContentObserver;
19486de0590b94bcce27e3038c27464bed510bb564aJeff Brown            if (contentObserver != null) {
195655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown                contentObserver.dispatchChange(selfChange, uri);
19686de0590b94bcce27e3038c27464bed510bb564aJeff Brown            }
19786de0590b94bcce27e3038c27464bed510bb564aJeff Brown        }
19886de0590b94bcce27e3038c27464bed510bb564aJeff Brown
19986de0590b94bcce27e3038c27464bed510bb564aJeff Brown        public void releaseContentObserver() {
20086de0590b94bcce27e3038c27464bed510bb564aJeff Brown            mContentObserver = null;
20186de0590b94bcce27e3038c27464bed510bb564aJeff Brown        }
20286de0590b94bcce27e3038c27464bed510bb564aJeff Brown    }
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
204