Home | History | Annotate | Download | only in database
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.database;
     18 
     19 import android.annotation.UnsupportedAppUsage;
     20 import android.net.Uri;
     21 import android.os.Handler;
     22 import android.os.UserHandle;
     23 
     24 /**
     25  * Receives call backs for changes to content.
     26  * Must be implemented by objects which are added to a {@link ContentObservable}.
     27  */
     28 public abstract class ContentObserver {
     29     private final Object mLock = new Object();
     30     private Transport mTransport; // guarded by mLock
     31 
     32     Handler mHandler;
     33 
     34     /**
     35      * Creates a content observer.
     36      *
     37      * @param handler The handler to run {@link #onChange} on, or null if none.
     38      */
     39     public ContentObserver(Handler handler) {
     40         mHandler = handler;
     41     }
     42 
     43     /**
     44      * Gets access to the binder transport object. Not for public consumption.
     45      *
     46      * {@hide}
     47      */
     48     public IContentObserver getContentObserver() {
     49         synchronized (mLock) {
     50             if (mTransport == null) {
     51                 mTransport = new Transport(this);
     52             }
     53             return mTransport;
     54         }
     55     }
     56 
     57     /**
     58      * Gets access to the binder transport object, and unlinks the transport object
     59      * from the ContentObserver. Not for public consumption.
     60      *
     61      * {@hide}
     62      */
     63     @UnsupportedAppUsage
     64     public IContentObserver releaseContentObserver() {
     65         synchronized (mLock) {
     66             final Transport oldTransport = mTransport;
     67             if (oldTransport != null) {
     68                 oldTransport.releaseContentObserver();
     69                 mTransport = null;
     70             }
     71             return oldTransport;
     72         }
     73     }
     74 
     75     /**
     76      * Returns true if this observer is interested receiving self-change notifications.
     77      *
     78      * Subclasses should override this method to indicate whether the observer
     79      * is interested in receiving notifications for changes that it made to the
     80      * content itself.
     81      *
     82      * @return True if self-change notifications should be delivered to the observer.
     83      */
     84     public boolean deliverSelfNotifications() {
     85         return false;
     86     }
     87 
     88     /**
     89      * This method is called when a content change occurs.
     90      * <p>
     91      * Subclasses should override this method to handle content changes.
     92      * </p>
     93      *
     94      * @param selfChange True if this is a self-change notification.
     95      */
     96     public void onChange(boolean selfChange) {
     97         // Do nothing.  Subclass should override.
     98     }
     99 
    100     /**
    101      * This method is called when a content change occurs.
    102      * Includes the changed content Uri when available.
    103      * <p>
    104      * Subclasses should override this method to handle content changes.
    105      * To ensure correct operation on older versions of the framework that
    106      * did not provide a Uri argument, applications should also implement
    107      * the {@link #onChange(boolean)} overload of this method whenever they
    108      * implement the {@link #onChange(boolean, Uri)} overload.
    109      * </p><p>
    110      * Example implementation:
    111      * <pre><code>
    112      * // Implement the onChange(boolean) method to delegate the change notification to
    113      * // the onChange(boolean, Uri) method to ensure correct operation on older versions
    114      * // of the framework that did not have the onChange(boolean, Uri) method.
    115      * {@literal @Override}
    116      * public void onChange(boolean selfChange) {
    117      *     onChange(selfChange, null);
    118      * }
    119      *
    120      * // Implement the onChange(boolean, Uri) method to take advantage of the new Uri argument.
    121      * {@literal @Override}
    122      * public void onChange(boolean selfChange, Uri uri) {
    123      *     // Handle change.
    124      * }
    125      * </code></pre>
    126      * </p>
    127      *
    128      * @param selfChange True if this is a self-change notification.
    129      * @param uri The Uri of the changed content, or null if unknown.
    130      */
    131     public void onChange(boolean selfChange, Uri uri) {
    132         onChange(selfChange);
    133     }
    134 
    135     /**
    136      * Dispatches a change notification to the observer. Includes the changed
    137      * content Uri when available and also the user whose content changed.
    138      *
    139      * @param selfChange True if this is a self-change notification.
    140      * @param uri The Uri of the changed content, or null if unknown.
    141      * @param userId The user whose content changed. Can be either a specific
    142      *         user or {@link UserHandle#USER_ALL}.
    143      *
    144      * @hide
    145      */
    146     public void onChange(boolean selfChange, Uri uri, int userId) {
    147         onChange(selfChange, uri);
    148     }
    149 
    150     /**
    151      * Dispatches a change notification to the observer.
    152      * <p>
    153      * If a {@link Handler} was supplied to the {@link ContentObserver} constructor,
    154      * then a call to the {@link #onChange} method is posted to the handler's message queue.
    155      * Otherwise, the {@link #onChange} method is invoked immediately on this thread.
    156      * </p>
    157      *
    158      * @param selfChange True if this is a self-change notification.
    159      *
    160      * @deprecated Use {@link #dispatchChange(boolean, Uri)} instead.
    161      */
    162     @Deprecated
    163     public final void dispatchChange(boolean selfChange) {
    164         dispatchChange(selfChange, null);
    165     }
    166 
    167     /**
    168      * Dispatches a change notification to the observer.
    169      * Includes the changed content Uri when available.
    170      * <p>
    171      * If a {@link Handler} was supplied to the {@link ContentObserver} constructor,
    172      * then a call to the {@link #onChange} method is posted to the handler's message queue.
    173      * Otherwise, the {@link #onChange} method is invoked immediately on this thread.
    174      * </p>
    175      *
    176      * @param selfChange True if this is a self-change notification.
    177      * @param uri The Uri of the changed content, or null if unknown.
    178      */
    179     public final void dispatchChange(boolean selfChange, Uri uri) {
    180         dispatchChange(selfChange, uri, UserHandle.getCallingUserId());
    181     }
    182 
    183     /**
    184      * Dispatches a change notification to the observer. Includes the changed
    185      * content Uri when available and also the user whose content changed.
    186      * <p>
    187      * If a {@link Handler} was supplied to the {@link ContentObserver} constructor,
    188      * then a call to the {@link #onChange} method is posted to the handler's message queue.
    189      * Otherwise, the {@link #onChange} method is invoked immediately on this thread.
    190      * </p>
    191      *
    192      * @param selfChange True if this is a self-change notification.
    193      * @param uri The Uri of the changed content, or null if unknown.
    194      * @param userId The user whose content changed.
    195      */
    196     private void dispatchChange(boolean selfChange, Uri uri, int userId) {
    197         if (mHandler == null) {
    198             onChange(selfChange, uri, userId);
    199         } else {
    200             mHandler.post(new NotificationRunnable(selfChange, uri, userId));
    201         }
    202     }
    203 
    204 
    205     private final class NotificationRunnable implements Runnable {
    206         private final boolean mSelfChange;
    207         private final Uri mUri;
    208         private final int mUserId;
    209 
    210         public NotificationRunnable(boolean selfChange, Uri uri, int userId) {
    211             mSelfChange = selfChange;
    212             mUri = uri;
    213             mUserId = userId;
    214         }
    215 
    216         @Override
    217         public void run() {
    218             ContentObserver.this.onChange(mSelfChange, mUri, mUserId);
    219         }
    220     }
    221 
    222     private static final class Transport extends IContentObserver.Stub {
    223         private ContentObserver mContentObserver;
    224 
    225         public Transport(ContentObserver contentObserver) {
    226             mContentObserver = contentObserver;
    227         }
    228 
    229         @Override
    230         public void onChange(boolean selfChange, Uri uri, int userId) {
    231             ContentObserver contentObserver = mContentObserver;
    232             if (contentObserver != null) {
    233                 contentObserver.dispatchChange(selfChange, uri, userId);
    234             }
    235         }
    236 
    237         public void releaseContentObserver() {
    238             mContentObserver = null;
    239         }
    240     }
    241 }
    242