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