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