blob: cc5d3b16ff082202f34047ebf6a73654942379d1 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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
17package android.database;
18
Sudheer Shankaa07b0522019-01-26 10:40:42 -080019import android.annotation.NonNull;
Mathew Inwood41b31942018-08-10 16:00:53 +010020import android.annotation.UnsupportedAppUsage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import android.content.ContentResolver;
22import android.net.Uri;
Mathew Inwood8c854f82018-09-14 12:35:36 +010023import android.os.Build;
Makoto Onuki25897162010-04-29 11:26:20 -070024import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026
Sudheer Shankaa07b0522019-01-26 10:40:42 -080027import com.android.internal.util.Preconditions;
28
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import java.lang.ref.WeakReference;
Fyodor Kupolov848485b2017-07-28 15:46:17 -070030import java.util.Arrays;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import java.util.HashMap;
Sudheer Shankaa07b0522019-01-26 10:40:42 -080032import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import java.util.Map;
34
35
36/**
37 * This is an abstract cursor class that handles a lot of the common code
38 * that all cursors need to deal with and is provided for convenience reasons.
39 */
40public abstract class AbstractCursor implements CrossProcessCursor {
41 private static final String TAG = "Cursor";
42
Jeff Brownfb5a4962012-03-14 17:38:59 -070043 /**
Jeff Brown46705132015-04-09 18:32:35 -070044 * @removed This field should not be used.
Jeff Brownfb5a4962012-03-14 17:38:59 -070045 */
Jeff Brownfb5a4962012-03-14 17:38:59 -070046 protected HashMap<Long, Map<String, Object>> mUpdatedRows;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047
Jeff Brownfb5a4962012-03-14 17:38:59 -070048 /**
Jeff Brown46705132015-04-09 18:32:35 -070049 * @removed This field should not be used.
Jeff Brownfb5a4962012-03-14 17:38:59 -070050 */
51 protected int mRowIdColumnIndex;
52
53 /**
Jeff Brown46705132015-04-09 18:32:35 -070054 * @removed This field should not be used.
Jeff Brownfb5a4962012-03-14 17:38:59 -070055 */
56 protected Long mCurrentRowID;
57
Jeff Brown8faab362015-04-09 18:52:52 -070058 /**
59 * @deprecated Use {@link #getPosition()} instead.
60 */
61 @Deprecated
Jeff Brown46705132015-04-09 18:32:35 -070062 protected int mPos;
Jeff Brown8faab362015-04-09 18:52:52 -070063
64 /**
65 * @deprecated Use {@link #isClosed()} instead.
66 */
67 @Deprecated
Jeff Brownfb5a4962012-03-14 17:38:59 -070068 protected boolean mClosed;
Jeff Brown8faab362015-04-09 18:52:52 -070069
70 /**
71 * @deprecated Do not use.
72 */
73 @Deprecated
Jeff Brownfb5a4962012-03-14 17:38:59 -070074 protected ContentResolver mContentResolver;
Jeff Brown8faab362015-04-09 18:52:52 -070075
Mathew Inwood41b31942018-08-10 16:00:53 +010076 @UnsupportedAppUsage
Jeff Brownfb5a4962012-03-14 17:38:59 -070077 private Uri mNotifyUri;
Sudheer Shankaa07b0522019-01-26 10:40:42 -080078 private List<Uri> mNotifyUris;
Jeff Brownfb5a4962012-03-14 17:38:59 -070079
80 private final Object mSelfObserverLock = new Object();
81 private ContentObserver mSelfObserver;
82 private boolean mSelfObserverRegistered;
83
Jeff Brown7873d5b2012-05-09 14:32:14 -070084 private final DataSetObservable mDataSetObservable = new DataSetObservable();
85 private final ContentObservable mContentObservable = new ContentObservable();
Jeff Brownfb5a4962012-03-14 17:38:59 -070086
Mathew Inwood8c854f82018-09-14 12:35:36 +010087 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jeff Brownfb5a4962012-03-14 17:38:59 -070088 private Bundle mExtras = Bundle.EMPTY;
Makoto Onuki630f6b12011-08-30 18:02:37 -070089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 /* -------------------------------------------------------- */
91 /* These need to be implemented by subclasses */
Jeff Brown8faab362015-04-09 18:52:52 -070092 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 abstract public int getCount();
94
Jeff Brown8faab362015-04-09 18:52:52 -070095 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 abstract public String[] getColumnNames();
97
Jeff Brown8faab362015-04-09 18:52:52 -070098 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 abstract public String getString(int column);
Jeff Brown8faab362015-04-09 18:52:52 -0700100 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 abstract public short getShort(int column);
Jeff Brown8faab362015-04-09 18:52:52 -0700102 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 abstract public int getInt(int column);
Jeff Brown8faab362015-04-09 18:52:52 -0700104 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 abstract public long getLong(int column);
Jeff Brown8faab362015-04-09 18:52:52 -0700106 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 abstract public float getFloat(int column);
Jeff Brown8faab362015-04-09 18:52:52 -0700108 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 abstract public double getDouble(int column);
Jeff Brown8faab362015-04-09 18:52:52 -0700110 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 abstract public boolean isNull(int column);
112
Jeff Brown8faab362015-04-09 18:52:52 -0700113 @Override
Vasu Nori8b0dd7d2010-05-18 11:54:31 -0700114 public int getType(int column) {
Jeff Brown80e7b802011-10-12 17:42:41 -0700115 // Reflects the assumption that all commonly used field types (meaning everything
116 // but blobs) are convertible to strings so it should be safe to call
117 // getString to retrieve them.
118 return FIELD_TYPE_STRING;
Vasu Nori8b0dd7d2010-05-18 11:54:31 -0700119 }
120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 // TODO implement getBlob in all cursor types
Jeff Brown8faab362015-04-09 18:52:52 -0700122 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 public byte[] getBlob(int column) {
124 throw new UnsupportedOperationException("getBlob is not supported");
125 }
126 /* -------------------------------------------------------- */
127 /* Methods that may optionally be implemented by subclasses */
128
129 /**
Jeff Brown7ce74522011-10-07 13:29:37 -0700130 * If the cursor is backed by a {@link CursorWindow}, returns a pre-filled
131 * window with the contents of the cursor, otherwise null.
132 *
133 * @return The pre-filled window that backs this cursor, or null if none.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 */
Jeff Brown8faab362015-04-09 18:52:52 -0700135 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 public CursorWindow getWindow() {
137 return null;
138 }
139
Jeff Brown8faab362015-04-09 18:52:52 -0700140 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 public int getColumnCount() {
142 return getColumnNames().length;
143 }
Makoto Onuki630f6b12011-08-30 18:02:37 -0700144
Jeff Brown8faab362015-04-09 18:52:52 -0700145 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 public void deactivate() {
Jeff Brownd2183652011-10-09 12:39:53 -0700147 onDeactivateOrClose();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 }
Makoto Onuki630f6b12011-08-30 18:02:37 -0700149
Jeff Brownd2183652011-10-09 12:39:53 -0700150 /** @hide */
151 protected void onDeactivateOrClose() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 if (mSelfObserver != null) {
153 mContentResolver.unregisterContentObserver(mSelfObserver);
154 mSelfObserverRegistered = false;
155 }
156 mDataSetObservable.notifyInvalidated();
157 }
Vasu Nori20f549f2010-04-15 11:25:51 -0700158
Jeff Brown8faab362015-04-09 18:52:52 -0700159 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 public boolean requery() {
161 if (mSelfObserver != null && mSelfObserverRegistered == false) {
Sudheer Shankaa07b0522019-01-26 10:40:42 -0800162 final int size = mNotifyUris.size();
163 for (int i = 0; i < size; ++i) {
164 final Uri notifyUri = mNotifyUris.get(i);
165 mContentResolver.registerContentObserver(notifyUri, true, mSelfObserver);
166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 mSelfObserverRegistered = true;
168 }
169 mDataSetObservable.notifyChanged();
170 return true;
171 }
172
Jeff Brown8faab362015-04-09 18:52:52 -0700173 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 public boolean isClosed() {
175 return mClosed;
176 }
Makoto Onuki630f6b12011-08-30 18:02:37 -0700177
Jeff Brown8faab362015-04-09 18:52:52 -0700178 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 public void close() {
180 mClosed = true;
181 mContentObservable.unregisterAll();
Jeff Brownd2183652011-10-09 12:39:53 -0700182 onDeactivateOrClose();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 }
184
185 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 * This function is called every time the cursor is successfully scrolled
187 * to a new position, giving the subclass a chance to update any state it
188 * may have. If it returns false the move function will also do so and the
189 * cursor will scroll to the beforeFirst position.
190 *
191 * @param oldPosition the position that we're moving from
192 * @param newPosition the position that we're moving to
193 * @return true if the move is successful, false otherwise
194 */
Jeff Brown8faab362015-04-09 18:52:52 -0700195 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 public boolean onMove(int oldPosition, int newPosition) {
197 return true;
198 }
199
Makoto Onuki630f6b12011-08-30 18:02:37 -0700200
Jeff Brown8faab362015-04-09 18:52:52 -0700201 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
203 // Default implementation, uses getString
204 String result = getString(columnIndex);
205 if (result != null) {
206 char[] data = buffer.data;
207 if (data == null || data.length < result.length()) {
208 buffer.data = result.toCharArray();
209 } else {
210 result.getChars(0, result.length(), data, 0);
211 }
212 buffer.sizeCopied = result.length();
Dmitri Plotnikov9480efe2011-02-16 12:03:10 -0800213 } else {
214 buffer.sizeCopied = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 }
216 }
Makoto Onuki630f6b12011-08-30 18:02:37 -0700217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 /* -------------------------------------------------------- */
219 /* Implementation */
220 public AbstractCursor() {
221 mPos = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 }
223
Jeff Brown8faab362015-04-09 18:52:52 -0700224 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 public final int getPosition() {
226 return mPos;
227 }
228
Jeff Brown8faab362015-04-09 18:52:52 -0700229 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 public final boolean moveToPosition(int position) {
231 // Make sure position isn't past the end of the cursor
232 final int count = getCount();
233 if (position >= count) {
234 mPos = count;
235 return false;
236 }
237
238 // Make sure position isn't before the beginning of the cursor
239 if (position < 0) {
240 mPos = -1;
241 return false;
242 }
243
244 // Check for no-op moves, and skip the rest of the work for them
245 if (position == mPos) {
246 return true;
247 }
248
249 boolean result = onMove(mPos, position);
250 if (result == false) {
251 mPos = -1;
252 } else {
253 mPos = position;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 }
255
256 return result;
257 }
Makoto Onuki630f6b12011-08-30 18:02:37 -0700258
Jeff Brown80e7b802011-10-12 17:42:41 -0700259 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 public void fillWindow(int position, CursorWindow window) {
Jeff Brown80e7b802011-10-12 17:42:41 -0700261 DatabaseUtils.cursorFillWindow(this, position, window);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 }
263
Jeff Brown8faab362015-04-09 18:52:52 -0700264 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 public final boolean move(int offset) {
266 return moveToPosition(mPos + offset);
267 }
268
Jeff Brown8faab362015-04-09 18:52:52 -0700269 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 public final boolean moveToFirst() {
271 return moveToPosition(0);
272 }
273
Jeff Brown8faab362015-04-09 18:52:52 -0700274 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 public final boolean moveToLast() {
276 return moveToPosition(getCount() - 1);
277 }
278
Jeff Brown8faab362015-04-09 18:52:52 -0700279 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 public final boolean moveToNext() {
281 return moveToPosition(mPos + 1);
282 }
283
Jeff Brown8faab362015-04-09 18:52:52 -0700284 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 public final boolean moveToPrevious() {
286 return moveToPosition(mPos - 1);
287 }
288
Jeff Brown8faab362015-04-09 18:52:52 -0700289 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 public final boolean isFirst() {
291 return mPos == 0 && getCount() != 0;
292 }
293
Jeff Brown8faab362015-04-09 18:52:52 -0700294 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 public final boolean isLast() {
296 int cnt = getCount();
297 return mPos == (cnt - 1) && cnt != 0;
298 }
299
Jeff Brown8faab362015-04-09 18:52:52 -0700300 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 public final boolean isBeforeFirst() {
302 if (getCount() == 0) {
303 return true;
304 }
305 return mPos == -1;
306 }
307
Jeff Brown8faab362015-04-09 18:52:52 -0700308 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309 public final boolean isAfterLast() {
310 if (getCount() == 0) {
311 return true;
312 }
313 return mPos == getCount();
314 }
315
Jeff Brown8faab362015-04-09 18:52:52 -0700316 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 public int getColumnIndex(String columnName) {
318 // Hack according to bug 903852
319 final int periodIndex = columnName.lastIndexOf('.');
320 if (periodIndex != -1) {
321 Exception e = new Exception();
322 Log.e(TAG, "requesting column name with table name -- " + columnName, e);
323 columnName = columnName.substring(periodIndex + 1);
324 }
325
326 String columnNames[] = getColumnNames();
327 int length = columnNames.length;
328 for (int i = 0; i < length; i++) {
329 if (columnNames[i].equalsIgnoreCase(columnName)) {
330 return i;
331 }
332 }
333
Joe Onorato43a17652011-04-06 19:22:23 -0700334 if (false) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 if (getCount() > 0) {
336 Log.w("AbstractCursor", "Unknown column " + columnName);
337 }
338 }
339 return -1;
340 }
341
Jeff Brown8faab362015-04-09 18:52:52 -0700342 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343 public int getColumnIndexOrThrow(String columnName) {
344 final int index = getColumnIndex(columnName);
345 if (index < 0) {
Fyodor Kupolov848485b2017-07-28 15:46:17 -0700346 String availableColumns = "";
347 try {
348 availableColumns = Arrays.toString(getColumnNames());
349 } catch (Exception e) {
350 Log.d(TAG, "Cannot collect column names for debug purposes", e);
351 }
352 throw new IllegalArgumentException("column '" + columnName
353 + "' does not exist. Available columns: " + availableColumns);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 }
355 return index;
356 }
357
Jeff Brown8faab362015-04-09 18:52:52 -0700358 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 public String getColumnName(int columnIndex) {
360 return getColumnNames()[columnIndex];
361 }
362
Jeff Brown8faab362015-04-09 18:52:52 -0700363 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 public void registerContentObserver(ContentObserver observer) {
365 mContentObservable.registerObserver(observer);
366 }
367
Jeff Brown8faab362015-04-09 18:52:52 -0700368 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 public void unregisterContentObserver(ContentObserver observer) {
370 // cursor will unregister all observers when it close
371 if (!mClosed) {
372 mContentObservable.unregisterObserver(observer);
373 }
374 }
Makoto Onuki630f6b12011-08-30 18:02:37 -0700375
Jeff Brown8faab362015-04-09 18:52:52 -0700376 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 public void registerDataSetObserver(DataSetObserver observer) {
378 mDataSetObservable.registerObserver(observer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 }
380
Jeff Brown8faab362015-04-09 18:52:52 -0700381 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 public void unregisterDataSetObserver(DataSetObserver observer) {
383 mDataSetObservable.unregisterObserver(observer);
384 }
385
386 /**
387 * Subclasses must call this method when they finish committing updates to notify all
388 * observers.
389 *
390 * @param selfChange
391 */
392 protected void onChange(boolean selfChange) {
393 synchronized (mSelfObserverLock) {
Jeff Brown655e66b2012-01-23 15:51:41 -0800394 mContentObservable.dispatchChange(selfChange, null);
Sudheer Shankaa07b0522019-01-26 10:40:42 -0800395 if (mNotifyUris != null && selfChange) {
396 final int size = mNotifyUris.size();
397 for (int i = 0; i < size; ++i) {
398 final Uri notifyUri = mNotifyUris.get(i);
399 mContentResolver.notifyChange(notifyUri, mSelfObserver);
400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 }
402 }
403 }
404
405 /**
406 * Specifies a content URI to watch for changes.
407 *
408 * @param cr The content resolver from the caller's context.
409 * @param notifyUri The URI to watch for changes. This can be a
410 * specific row URI, or a base URI for a whole class of content.
411 */
Jeff Brown8faab362015-04-09 18:52:52 -0700412 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
Sudheer Shankaa07b0522019-01-26 10:40:42 -0800414 setNotificationUris(cr, Arrays.asList(notifyUri));
415 }
416
417 @Override
418 public void setNotificationUris(@NonNull ContentResolver cr, @NonNull List<Uri> notifyUris) {
419 Preconditions.checkNotNull(cr);
420 Preconditions.checkNotNull(notifyUris);
421
Anton Hanssond79473f2019-04-30 16:57:10 +0100422 setNotificationUris(cr, notifyUris, cr.getUserId(), true);
Christopher Tateafccaa82012-10-03 17:41:51 -0700423 }
424
Anton Hanssond79473f2019-04-30 16:57:10 +0100425 /**
426 * Set the notification uri but with an observer for a particular user's view. Also allows
427 * disabling the use of a self observer, which is sensible if either
428 * a) the cursor's owner calls {@link #onChange(boolean)} whenever the content changes, or
429 * b) the cursor is known not to have any content observers.
430 * @hide
431 */
432 public void setNotificationUris(ContentResolver cr, List<Uri> notifyUris, int userHandle,
433 boolean registerSelfObserver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 synchronized (mSelfObserverLock) {
Sudheer Shankaa07b0522019-01-26 10:40:42 -0800435 mNotifyUris = notifyUris;
436 mNotifyUri = mNotifyUris.get(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 mContentResolver = cr;
438 if (mSelfObserver != null) {
439 mContentResolver.unregisterContentObserver(mSelfObserver);
Anton Hanssond79473f2019-04-30 16:57:10 +0100440 mSelfObserverRegistered = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 }
Anton Hanssond79473f2019-04-30 16:57:10 +0100442 if (registerSelfObserver) {
443 mSelfObserver = new SelfContentObserver(this);
444 final int size = mNotifyUris.size();
445 for (int i = 0; i < size; ++i) {
446 final Uri notifyUri = mNotifyUris.get(i);
447 mContentResolver.registerContentObserver(
448 notifyUri, true, mSelfObserver, userHandle);
449 }
450 mSelfObserverRegistered = true;
Sudheer Shankaa07b0522019-01-26 10:40:42 -0800451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 }
453 }
454
Jeff Brown4e0951e2015-04-09 18:28:24 -0700455 @Override
Makoto Onuki90bf7c72010-09-15 10:13:07 -0700456 public Uri getNotificationUri() {
Dianne Hackbornc87c92e2013-05-14 13:44:29 -0700457 synchronized (mSelfObserverLock) {
458 return mNotifyUri;
459 }
Makoto Onuki90bf7c72010-09-15 10:13:07 -0700460 }
461
Jeff Brown4e0951e2015-04-09 18:28:24 -0700462 @Override
Sudheer Shankaa07b0522019-01-26 10:40:42 -0800463 public List<Uri> getNotificationUris() {
464 synchronized (mSelfObserverLock) {
465 return mNotifyUris;
466 }
467 }
468
469 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 public boolean getWantsAllOnMoveCalls() {
471 return false;
472 }
473
Jeff Brown4e0951e2015-04-09 18:28:24 -0700474 @Override
Makoto Onuki630f6b12011-08-30 18:02:37 -0700475 public void setExtras(Bundle extras) {
476 mExtras = (extras == null) ? Bundle.EMPTY : extras;
477 }
478
Jeff Brown4e0951e2015-04-09 18:28:24 -0700479 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 public Bundle getExtras() {
Makoto Onuki630f6b12011-08-30 18:02:37 -0700481 return mExtras;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 }
483
Jeff Brown4e0951e2015-04-09 18:28:24 -0700484 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485 public Bundle respond(Bundle extras) {
486 return Bundle.EMPTY;
487 }
488
489 /**
Jeff Hamiltonf1a4a0a2010-06-30 15:10:24 -0500490 * @deprecated Always returns false since Cursors do not support updating rows
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491 */
Jeff Hamiltonf1a4a0a2010-06-30 15:10:24 -0500492 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493 protected boolean isFieldUpdated(int columnIndex) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 return false;
495 }
496
497 /**
Jeff Hamiltonf1a4a0a2010-06-30 15:10:24 -0500498 * @deprecated Always returns null since Cursors do not support updating rows
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 */
Jeff Hamiltonf1a4a0a2010-06-30 15:10:24 -0500500 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 protected Object getUpdatedField(int columnIndex) {
Jeff Hamiltonf1a4a0a2010-06-30 15:10:24 -0500502 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 }
504
505 /**
506 * This function throws CursorIndexOutOfBoundsException if
507 * the cursor position is out of bounds. Subclass implementations of
508 * the get functions should call this before attempting
509 * to retrieve data.
510 *
511 * @throws CursorIndexOutOfBoundsException
512 */
513 protected void checkPosition() {
514 if (-1 == mPos || getCount() == mPos) {
515 throw new CursorIndexOutOfBoundsException(mPos, getCount());
516 }
517 }
518
519 @Override
520 protected void finalize() {
521 if (mSelfObserver != null && mSelfObserverRegistered == true) {
522 mContentResolver.unregisterContentObserver(mSelfObserver);
523 }
Catherine Liu3f824c02012-06-11 16:38:17 -0500524 try {
525 if (!mClosed) close();
526 } catch(Exception e) { }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527 }
528
529 /**
530 * Cursors use this class to track changes others make to their URI.
531 */
532 protected static class SelfContentObserver extends ContentObserver {
533 WeakReference<AbstractCursor> mCursor;
534
535 public SelfContentObserver(AbstractCursor cursor) {
536 super(null);
537 mCursor = new WeakReference<AbstractCursor>(cursor);
538 }
539
540 @Override
541 public boolean deliverSelfNotifications() {
542 return false;
543 }
544
545 @Override
546 public void onChange(boolean selfChange) {
547 AbstractCursor cursor = mCursor.get();
548 if (cursor != null) {
549 cursor.onChange(false);
550 }
551 }
552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553}