• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.database;
18 
19 import static java.util.Objects.requireNonNull;
20 
21 import android.annotation.BytesLong;
22 import android.annotation.IntRange;
23 import android.compat.annotation.UnsupportedAppUsage;
24 import android.content.res.Resources;
25 import android.database.sqlite.SQLiteClosable;
26 import android.database.sqlite.SQLiteException;
27 import android.os.Parcel;
28 import android.os.Parcelable;
29 import android.ravenwood.annotation.RavenwoodKeepWholeClass;
30 import android.ravenwood.annotation.RavenwoodRedirect;
31 import android.ravenwood.annotation.RavenwoodRedirectionClass;
32 import android.ravenwood.annotation.RavenwoodThrow;
33 
34 import dalvik.annotation.optimization.FastNative;
35 import dalvik.system.CloseGuard;
36 
37 /**
38  * A buffer containing multiple cursor rows.
39  * <p>
40  * A {@link CursorWindow} is read-write when initially created and used locally.
41  * When sent to a remote process (by writing it to a {@link Parcel}), the remote process
42  * receives a read-only view of the cursor window.  Typically the cursor window
43  * will be allocated by the producer, filled with data, and then sent to the
44  * consumer for reading.
45  * </p>
46  */
47 @RavenwoodKeepWholeClass
48 @RavenwoodRedirectionClass("CursorWindow_ravenwood")
49 public class CursorWindow extends SQLiteClosable implements Parcelable {
50     private static final String STATS_TAG = "CursorWindowStats";
51 
52     // This static member will be evaluated when first used.
53     @UnsupportedAppUsage
54     private static int sCursorWindowSize = -1;
55 
56     /**
57      * The native CursorWindow object pointer.  (FOR INTERNAL USE ONLY)
58      * @hide
59      */
60     @UnsupportedAppUsage
61     public long mWindowPtr;
62 
63     private int mStartPos;
64     private final String mName;
65 
66     private final CloseGuard mCloseGuard;
67 
68     // May throw CursorWindowAllocationException
69     @RavenwoodRedirect
nativeCreate(String name, int cursorWindowSize)70     private static native long nativeCreate(String name, int cursorWindowSize);
71 
72     // May throw CursorWindowAllocationException
73     @RavenwoodRedirect
nativeCreateFromParcel(Parcel parcel)74     private static native long nativeCreateFromParcel(Parcel parcel);
75     @RavenwoodRedirect
nativeDispose(long windowPtr)76     private static native void nativeDispose(long windowPtr);
77     @RavenwoodRedirect
nativeWriteToParcel(long windowPtr, Parcel parcel)78     private static native void nativeWriteToParcel(long windowPtr, Parcel parcel);
79 
80     @RavenwoodRedirect
nativeGetName(long windowPtr)81     private static native String nativeGetName(long windowPtr);
82     @RavenwoodRedirect
nativeGetBlob(long windowPtr, int row, int column)83     private static native byte[] nativeGetBlob(long windowPtr, int row, int column);
84     @RavenwoodRedirect
nativeGetString(long windowPtr, int row, int column)85     private static native String nativeGetString(long windowPtr, int row, int column);
86     @RavenwoodThrow
nativeCopyStringToBuffer(long windowPtr, int row, int column, CharArrayBuffer buffer)87     private static native void nativeCopyStringToBuffer(long windowPtr, int row, int column,
88             CharArrayBuffer buffer);
89     @RavenwoodRedirect
nativePutBlob(long windowPtr, byte[] value, int row, int column)90     private static native boolean nativePutBlob(long windowPtr, byte[] value, int row, int column);
91     @RavenwoodRedirect
nativePutString(long windowPtr, String value, int row, int column)92     private static native boolean nativePutString(long windowPtr, String value,
93             int row, int column);
94 
95     // Below native methods don't do unconstrained work, so are FastNative for performance
96 
97     @FastNative
98     @RavenwoodThrow
nativeClear(long windowPtr)99     private static native void nativeClear(long windowPtr);
100 
101     @FastNative
102     @RavenwoodRedirect
nativeGetNumRows(long windowPtr)103     private static native int nativeGetNumRows(long windowPtr);
104     @FastNative
105     @RavenwoodRedirect
nativeSetNumColumns(long windowPtr, int columnNum)106     private static native boolean nativeSetNumColumns(long windowPtr, int columnNum);
107     @FastNative
108     @RavenwoodRedirect
nativeAllocRow(long windowPtr)109     private static native boolean nativeAllocRow(long windowPtr);
110     @FastNative
111     @RavenwoodThrow
nativeFreeLastRow(long windowPtr)112     private static native void nativeFreeLastRow(long windowPtr);
113 
114     @FastNative
115     @RavenwoodRedirect
nativeGetType(long windowPtr, int row, int column)116     private static native int nativeGetType(long windowPtr, int row, int column);
117     @FastNative
118     @RavenwoodRedirect
nativeGetLong(long windowPtr, int row, int column)119     private static native long nativeGetLong(long windowPtr, int row, int column);
120     @FastNative
121     @RavenwoodRedirect
nativeGetDouble(long windowPtr, int row, int column)122     private static native double nativeGetDouble(long windowPtr, int row, int column);
123 
124     @FastNative
125     @RavenwoodRedirect
nativePutLong(long windowPtr, long value, int row, int column)126     private static native boolean nativePutLong(long windowPtr, long value, int row, int column);
127     @FastNative
128     @RavenwoodRedirect
nativePutDouble(long windowPtr, double value, int row, int column)129     private static native boolean nativePutDouble(long windowPtr, double value, int row, int column);
130     @FastNative
131     @RavenwoodThrow
nativePutNull(long windowPtr, int row, int column)132     private static native boolean nativePutNull(long windowPtr, int row, int column);
133 
134 
135     /**
136      * Creates a new empty cursor window and gives it a name.
137      * <p>
138      * The cursor initially has no rows or columns.  Call {@link #setNumColumns(int)} to
139      * set the number of columns before adding any rows to the cursor.
140      * </p>
141      *
142      * @param name The name of the cursor window, or null if none.
143      */
CursorWindow(String name)144     public CursorWindow(String name) {
145         this(name, getCursorWindowSize());
146     }
147 
148     /**
149      * Creates a new empty cursor window and gives it a name.
150      * <p>
151      * The cursor initially has no rows or columns.  Call {@link #setNumColumns(int)} to
152      * set the number of columns before adding any rows to the cursor.
153      * </p>
154      *
155      * @param name The name of the cursor window, or null if none.
156      * @param windowSizeBytes Size of cursor window in bytes.
157      * @throws IllegalArgumentException if {@code windowSizeBytes} is less than 0
158      * @throws AssertionError if created window pointer is 0
159      * <p><strong>Note:</strong> Memory is dynamically allocated as data rows are added to the
160      * window. Depending on the amount of data stored, the actual amount of memory allocated can be
161      * lower than specified size, but cannot exceed it.
162      */
CursorWindow(String name, @BytesLong long windowSizeBytes)163     public CursorWindow(String name, @BytesLong long windowSizeBytes) {
164         if (windowSizeBytes < 0) {
165             throw new IllegalArgumentException("Window size cannot be less than 0");
166         }
167         mStartPos = 0;
168         mName = name != null && name.length() != 0 ? name : "<unnamed>";
169         mWindowPtr = nativeCreate(mName, (int) windowSizeBytes);
170         if (mWindowPtr == 0) {
171             throw new AssertionError(); // Not possible, the native code won't return it.
172         }
173         mCloseGuard = createCloseGuard();
174     }
175 
176     /**
177      * Creates a new empty cursor window.
178      * <p>
179      * The cursor initially has no rows or columns.  Call {@link #setNumColumns(int)} to
180      * set the number of columns before adding any rows to the cursor.
181      * </p>
182      *
183      * @param localWindow True if this window will be used in this process only,
184      * false if it might be sent to another processes.  This argument is ignored.
185      *
186      * @deprecated There is no longer a distinction between local and remote
187      * cursor windows.  Use the {@link #CursorWindow(String)} constructor instead.
188      */
189     @Deprecated
CursorWindow(boolean localWindow)190     public CursorWindow(boolean localWindow) {
191         this((String)null);
192     }
193 
CursorWindow(Parcel source)194     private CursorWindow(Parcel source) {
195         mStartPos = source.readInt();
196         mWindowPtr = nativeCreateFromParcel(source);
197         if (mWindowPtr == 0) {
198             throw new AssertionError(); // Not possible, the native code won't return it.
199         }
200         mName = nativeGetName(mWindowPtr);
201         mCloseGuard = createCloseGuard();
202     }
203 
204     @android.ravenwood.annotation.RavenwoodReplace
createCloseGuard()205     private CloseGuard createCloseGuard() {
206         final CloseGuard closeGuard = CloseGuard.get();
207         closeGuard.open("CursorWindow.close");
208         return closeGuard;
209     }
210 
createCloseGuard$ravenwood()211     private CloseGuard createCloseGuard$ravenwood() {
212         return null;
213     }
214 
215     @Override
finalize()216     protected void finalize() throws Throwable {
217         try {
218             if (mCloseGuard != null) {
219                 mCloseGuard.warnIfOpen();
220             }
221             dispose();
222         } finally {
223             super.finalize();
224         }
225     }
226 
dispose()227     private void dispose() {
228         if (mCloseGuard != null) {
229             mCloseGuard.close();
230         }
231         if (mWindowPtr != 0) {
232             nativeDispose(mWindowPtr);
233             mWindowPtr = 0;
234         }
235     }
236 
237     /**
238      * Gets the name of this cursor window, never null.
239      * @hide
240      */
getName()241     public String getName() {
242         return mName;
243     }
244 
245     /**
246      * Clears out the existing contents of the window, making it safe to reuse
247      * for new data.
248      * <p>
249      * The start position ({@link #getStartPosition()}), number of rows ({@link #getNumRows()}),
250      * and number of columns in the cursor are all reset to zero.
251      * </p>
252      */
clear()253     public void clear() {
254         acquireReference();
255         try {
256             mStartPos = 0;
257             nativeClear(mWindowPtr);
258         } finally {
259             releaseReference();
260         }
261     }
262 
263     /**
264      * Gets the start position of this cursor window.
265      * <p>
266      * The start position is the zero-based index of the first row that this window contains
267      * relative to the entire result set of the {@link Cursor}.
268      * </p>
269      *
270      * @return The zero-based start position.
271      */
getStartPosition()272     public @IntRange(from = 0) int getStartPosition() {
273         return mStartPos;
274     }
275 
276     /**
277      * Sets the start position of this cursor window.
278      * <p>
279      * The start position is the zero-based index of the first row that this window contains
280      * relative to the entire result set of the {@link Cursor}.
281      * </p>
282      *
283      * @param pos The new zero-based start position.
284      */
setStartPosition(@ntRangefrom = 0) int pos)285     public void setStartPosition(@IntRange(from = 0) int pos) {
286         mStartPos = pos;
287     }
288 
289     /**
290      * Gets the number of rows in this window.
291      *
292      * @return The number of rows in this cursor window.
293      */
getNumRows()294     public @IntRange(from = 0) int getNumRows() {
295         acquireReference();
296         try {
297             return nativeGetNumRows(mWindowPtr);
298         } finally {
299             releaseReference();
300         }
301     }
302 
303     /**
304      * Sets the number of columns in this window.
305      * <p>
306      * This method must be called before any rows are added to the window, otherwise
307      * it will fail to set the number of columns if it differs from the current number
308      * of columns.
309      * </p>
310      *
311      * @param columnNum The new number of columns.
312      * @return True if successful.
313      */
setNumColumns(@ntRangefrom = 0) int columnNum)314     public boolean setNumColumns(@IntRange(from = 0) int columnNum) {
315         acquireReference();
316         try {
317             return nativeSetNumColumns(mWindowPtr, columnNum);
318         } finally {
319             releaseReference();
320         }
321     }
322 
323     /**
324      * Allocates a new row at the end of this cursor window.
325      *
326      * @return True if successful, false if the cursor window is out of memory.
327      */
allocRow()328     public boolean allocRow(){
329         acquireReference();
330         try {
331             return nativeAllocRow(mWindowPtr);
332         } finally {
333             releaseReference();
334         }
335     }
336 
337     /**
338      * Frees the last row in this cursor window.
339      */
freeLastRow()340     public void freeLastRow(){
341         acquireReference();
342         try {
343             nativeFreeLastRow(mWindowPtr);
344         } finally {
345             releaseReference();
346         }
347     }
348 
349     /**
350      * Returns true if the field at the specified row and column index
351      * has type {@link Cursor#FIELD_TYPE_NULL}.
352      *
353      * @param row The zero-based row index.
354      * @param column The zero-based column index.
355      * @return True if the field has type {@link Cursor#FIELD_TYPE_NULL}.
356      * @deprecated Use {@link #getType(int, int)} instead.
357      */
358     @Deprecated
isNull(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)359     public boolean isNull(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
360         return getType(row, column) == Cursor.FIELD_TYPE_NULL;
361     }
362 
363     /**
364      * Returns true if the field at the specified row and column index
365      * has type {@link Cursor#FIELD_TYPE_BLOB} or {@link Cursor#FIELD_TYPE_NULL}.
366      *
367      * @param row The zero-based row index.
368      * @param column The zero-based column index.
369      * @return True if the field has type {@link Cursor#FIELD_TYPE_BLOB} or
370      * {@link Cursor#FIELD_TYPE_NULL}.
371      * @deprecated Use {@link #getType(int, int)} instead.
372      */
373     @Deprecated
isBlob(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)374     public boolean isBlob(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
375         int type = getType(row, column);
376         return type == Cursor.FIELD_TYPE_BLOB || type == Cursor.FIELD_TYPE_NULL;
377     }
378 
379     /**
380      * Returns true if the field at the specified row and column index
381      * has type {@link Cursor#FIELD_TYPE_INTEGER}.
382      *
383      * @param row The zero-based row index.
384      * @param column The zero-based column index.
385      * @return True if the field has type {@link Cursor#FIELD_TYPE_INTEGER}.
386      * @deprecated Use {@link #getType(int, int)} instead.
387      */
388     @Deprecated
isLong(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)389     public boolean isLong(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
390         return getType(row, column) == Cursor.FIELD_TYPE_INTEGER;
391     }
392 
393     /**
394      * Returns true if the field at the specified row and column index
395      * has type {@link Cursor#FIELD_TYPE_FLOAT}.
396      *
397      * @param row The zero-based row index.
398      * @param column The zero-based column index.
399      * @return True if the field has type {@link Cursor#FIELD_TYPE_FLOAT}.
400      * @deprecated Use {@link #getType(int, int)} instead.
401      */
402     @Deprecated
isFloat(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)403     public boolean isFloat(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
404         return getType(row, column) == Cursor.FIELD_TYPE_FLOAT;
405     }
406 
407     /**
408      * Returns true if the field at the specified row and column index
409      * has type {@link Cursor#FIELD_TYPE_STRING} or {@link Cursor#FIELD_TYPE_NULL}.
410      *
411      * @param row The zero-based row index.
412      * @param column The zero-based column index.
413      * @return True if the field has type {@link Cursor#FIELD_TYPE_STRING}
414      * or {@link Cursor#FIELD_TYPE_NULL}.
415      * @deprecated Use {@link #getType(int, int)} instead.
416      */
417     @Deprecated
isString(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)418     public boolean isString(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
419         int type = getType(row, column);
420         return type == Cursor.FIELD_TYPE_STRING || type == Cursor.FIELD_TYPE_NULL;
421     }
422 
423     /**
424      * Returns the type of the field at the specified row and column index.
425      *
426      * @param row The zero-based row index.
427      * @param column The zero-based column index.
428      * @return The field type.
429      */
getType(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)430     public @Cursor.FieldType int getType(@IntRange(from = 0) int row,
431             @IntRange(from = 0) int column) {
432         acquireReference();
433         try {
434             return nativeGetType(mWindowPtr, row - mStartPos, column);
435         } finally {
436             releaseReference();
437         }
438     }
439 
440     /**
441      * Gets the value of the field at the specified row and column index as a byte array.
442      * <p>
443      * The result is determined as follows:
444      * <ul>
445      * <li>If the field is of type {@link Cursor#FIELD_TYPE_NULL}, then the result
446      * is <code>null</code>.</li>
447      * <li>If the field is of type {@link Cursor#FIELD_TYPE_BLOB}, then the result
448      * is the blob value.</li>
449      * <li>If the field is of type {@link Cursor#FIELD_TYPE_STRING}, then the result
450      * is the array of bytes that make up the internal representation of the
451      * string value.</li>
452      * <li>If the field is of type {@link Cursor#FIELD_TYPE_INTEGER} or
453      * {@link Cursor#FIELD_TYPE_FLOAT}, then a {@link SQLiteException} is thrown.</li>
454      * </ul>
455      * </p>
456      *
457      * @param row The zero-based row index.
458      * @param column The zero-based column index.
459      * @return The value of the field as a byte array.
460      */
getBlob(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)461     public byte[] getBlob(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
462         acquireReference();
463         try {
464             return nativeGetBlob(mWindowPtr, row - mStartPos, column);
465         } finally {
466             releaseReference();
467         }
468     }
469 
470     /**
471      * Gets the value of the field at the specified row and column index as a string.
472      * <p>
473      * The result is determined as follows:
474      * <ul>
475      * <li>If the field is of type {@link Cursor#FIELD_TYPE_NULL}, then the result
476      * is <code>null</code>.</li>
477      * <li>If the field is of type {@link Cursor#FIELD_TYPE_STRING}, then the result
478      * is the string value.</li>
479      * <li>If the field is of type {@link Cursor#FIELD_TYPE_INTEGER}, then the result
480      * is a string representation of the integer in decimal, obtained by formatting the
481      * value with the <code>printf</code> family of functions using
482      * format specifier <code>%lld</code>.</li>
483      * <li>If the field is of type {@link Cursor#FIELD_TYPE_FLOAT}, then the result
484      * is a string representation of the floating-point value in decimal, obtained by
485      * formatting the value with the <code>printf</code> family of functions using
486      * format specifier <code>%g</code>.</li>
487      * <li>If the field is of type {@link Cursor#FIELD_TYPE_BLOB}, then a
488      * {@link SQLiteException} is thrown.</li>
489      * </ul>
490      * </p>
491      *
492      * @param row The zero-based row index.
493      * @param column The zero-based column index.
494      * @return The value of the field as a string.
495      */
getString(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)496     public String getString(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
497         acquireReference();
498         try {
499             return nativeGetString(mWindowPtr, row - mStartPos, column);
500         } finally {
501             releaseReference();
502         }
503     }
504 
505     /**
506      * Copies the text of the field at the specified row and column index into
507      * a {@link CharArrayBuffer}.
508      * <p>
509      * The buffer is populated as follows:
510      * <ul>
511      * <li>If the buffer is too small for the value to be copied, then it is
512      * automatically resized.</li>
513      * <li>If the field is of type {@link Cursor#FIELD_TYPE_NULL}, then the buffer
514      * is set to an empty string.</li>
515      * <li>If the field is of type {@link Cursor#FIELD_TYPE_STRING}, then the buffer
516      * is set to the contents of the string.</li>
517      * <li>If the field is of type {@link Cursor#FIELD_TYPE_INTEGER}, then the buffer
518      * is set to a string representation of the integer in decimal, obtained by formatting the
519      * value with the <code>printf</code> family of functions using
520      * format specifier <code>%lld</code>.</li>
521      * <li>If the field is of type {@link Cursor#FIELD_TYPE_FLOAT}, then the buffer is
522      * set to a string representation of the floating-point value in decimal, obtained by
523      * formatting the value with the <code>printf</code> family of functions using
524      * format specifier <code>%g</code>.</li>
525      * <li>If the field is of type {@link Cursor#FIELD_TYPE_BLOB}, then a
526      * {@link SQLiteException} is thrown.</li>
527      * </ul>
528      * </p>
529      *
530      * @param row The zero-based row index.
531      * @param column The zero-based column index.
532      * @param buffer The {@link CharArrayBuffer} to hold the string.  It is automatically
533      * resized if the requested string is larger than the buffer's current capacity.
534       */
copyStringToBuffer(@ntRangefrom = 0) int row, @IntRange(from = 0) int column, CharArrayBuffer buffer)535     public void copyStringToBuffer(@IntRange(from = 0) int row, @IntRange(from = 0) int column,
536             CharArrayBuffer buffer) {
537         if (buffer == null) {
538             throw new IllegalArgumentException("CharArrayBuffer should not be null");
539         }
540         acquireReference();
541         try {
542             nativeCopyStringToBuffer(mWindowPtr, row - mStartPos, column, buffer);
543         } finally {
544             releaseReference();
545         }
546     }
547 
548     /**
549      * Gets the value of the field at the specified row and column index as a <code>long</code>.
550      * <p>
551      * The result is determined as follows:
552      * <ul>
553      * <li>If the field is of type {@link Cursor#FIELD_TYPE_NULL}, then the result
554      * is <code>0L</code>.</li>
555      * <li>If the field is of type {@link Cursor#FIELD_TYPE_STRING}, then the result
556      * is the value obtained by parsing the string value with <code>strtoll</code>.
557      * <li>If the field is of type {@link Cursor#FIELD_TYPE_INTEGER}, then the result
558      * is the <code>long</code> value.</li>
559      * <li>If the field is of type {@link Cursor#FIELD_TYPE_FLOAT}, then the result
560      * is the floating-point value converted to a <code>long</code>.</li>
561      * <li>If the field is of type {@link Cursor#FIELD_TYPE_BLOB}, then a
562      * {@link SQLiteException} is thrown.</li>
563      * </ul>
564      * </p>
565      *
566      * @param row The zero-based row index.
567      * @param column The zero-based column index.
568      * @return The value of the field as a <code>long</code>.
569      */
getLong(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)570     public long getLong(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
571         acquireReference();
572         try {
573             return nativeGetLong(mWindowPtr, row - mStartPos, column);
574         } finally {
575             releaseReference();
576         }
577     }
578 
579     /**
580      * Gets the value of the field at the specified row and column index as a
581      * <code>double</code>.
582      * <p>
583      * The result is determined as follows:
584      * <ul>
585      * <li>If the field is of type {@link Cursor#FIELD_TYPE_NULL}, then the result
586      * is <code>0.0</code>.</li>
587      * <li>If the field is of type {@link Cursor#FIELD_TYPE_STRING}, then the result
588      * is the value obtained by parsing the string value with <code>strtod</code>.
589      * <li>If the field is of type {@link Cursor#FIELD_TYPE_INTEGER}, then the result
590      * is the integer value converted to a <code>double</code>.</li>
591      * <li>If the field is of type {@link Cursor#FIELD_TYPE_FLOAT}, then the result
592      * is the <code>double</code> value.</li>
593      * <li>If the field is of type {@link Cursor#FIELD_TYPE_BLOB}, then a
594      * {@link SQLiteException} is thrown.</li>
595      * </ul>
596      * </p>
597      *
598      * @param row The zero-based row index.
599      * @param column The zero-based column index.
600      * @return The value of the field as a <code>double</code>.
601      */
getDouble(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)602     public double getDouble(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
603         acquireReference();
604         try {
605             return nativeGetDouble(mWindowPtr, row - mStartPos, column);
606         } finally {
607             releaseReference();
608         }
609     }
610 
611     /**
612      * Gets the value of the field at the specified row and column index as a
613      * <code>short</code>.
614      * <p>
615      * The result is determined by invoking {@link #getLong} and converting the
616      * result to <code>short</code>.
617      * </p>
618      *
619      * @param row The zero-based row index.
620      * @param column The zero-based column index.
621      * @return The value of the field as a <code>short</code>.
622      */
getShort(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)623     public short getShort(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
624         return (short) getLong(row, column);
625     }
626 
627     /**
628      * Gets the value of the field at the specified row and column index as an
629      * <code>int</code>.
630      * <p>
631      * The result is determined by invoking {@link #getLong} and converting the
632      * result to <code>int</code>.
633      * </p>
634      *
635      * @param row The zero-based row index.
636      * @param column The zero-based column index.
637      * @return The value of the field as an <code>int</code>.
638      */
getInt(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)639     public int getInt(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
640         return (int) getLong(row, column);
641     }
642 
643     /**
644      * Gets the value of the field at the specified row and column index as a
645      * <code>float</code>.
646      * <p>
647      * The result is determined by invoking {@link #getDouble} and converting the
648      * result to <code>float</code>.
649      * </p>
650      *
651      * @param row The zero-based row index.
652      * @param column The zero-based column index.
653      * @return The value of the field as an <code>float</code>.
654      */
getFloat(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)655     public float getFloat(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
656         return (float) getDouble(row, column);
657     }
658 
659     /**
660      * Copies a byte array into the field at the specified row and column index.
661      *
662      * @param value The value to store.
663      * @param row The zero-based row index.
664      * @param column The zero-based column index.
665      * @return True if successful.
666      */
putBlob(byte[] value, @IntRange(from = 0) int row, @IntRange(from = 0) int column)667     public boolean putBlob(byte[] value,
668             @IntRange(from = 0) int row, @IntRange(from = 0) int column) {
669         requireNonNull(value);
670         acquireReference();
671         try {
672             return nativePutBlob(mWindowPtr, value, row - mStartPos, column);
673         } finally {
674             releaseReference();
675         }
676     }
677 
678     /**
679      * Copies a string into the field at the specified row and column index.
680      *
681      * @param value The value to store.
682      * @param row The zero-based row index.
683      * @param column The zero-based column index.
684      * @return True if successful.
685      */
putString(String value, @IntRange(from = 0) int row, @IntRange(from = 0) int column)686     public boolean putString(String value,
687             @IntRange(from = 0) int row, @IntRange(from = 0) int column) {
688         requireNonNull(value);
689         acquireReference();
690         try {
691             return nativePutString(mWindowPtr, value, row - mStartPos, column);
692         } finally {
693             releaseReference();
694         }
695     }
696 
697     /**
698      * Puts a long integer into the field at the specified row and column index.
699      *
700      * @param value The value to store.
701      * @param row The zero-based row index.
702      * @param column The zero-based column index.
703      * @return True if successful.
704      */
putLong(long value, @IntRange(from = 0) int row, @IntRange(from = 0) int column)705     public boolean putLong(long value,
706             @IntRange(from = 0) int row, @IntRange(from = 0) int column) {
707         acquireReference();
708         try {
709             return nativePutLong(mWindowPtr, value, row - mStartPos, column);
710         } finally {
711             releaseReference();
712         }
713     }
714 
715     /**
716      * Puts a double-precision floating point value into the field at the
717      * specified row and column index.
718      *
719      * @param value The value to store.
720      * @param row The zero-based row index.
721      * @param column The zero-based column index.
722      * @return True if successful.
723      */
putDouble(double value, @IntRange(from = 0) int row, @IntRange(from = 0) int column)724     public boolean putDouble(double value,
725             @IntRange(from = 0) int row, @IntRange(from = 0) int column) {
726         acquireReference();
727         try {
728             return nativePutDouble(mWindowPtr, value, row - mStartPos, column);
729         } finally {
730             releaseReference();
731         }
732     }
733 
734     /**
735      * Puts a null value into the field at the specified row and column index.
736      *
737      * @param row The zero-based row index.
738      * @param column The zero-based column index.
739      * @return True if successful.
740      */
putNull(@ntRangefrom = 0) int row, @IntRange(from = 0) int column)741     public boolean putNull(@IntRange(from = 0) int row, @IntRange(from = 0) int column) {
742         acquireReference();
743         try {
744             return nativePutNull(mWindowPtr, row - mStartPos, column);
745         } finally {
746             releaseReference();
747         }
748     }
749 
750     public static final @android.annotation.NonNull Parcelable.Creator<CursorWindow> CREATOR
751             = new Parcelable.Creator<CursorWindow>() {
752         public CursorWindow createFromParcel(Parcel source) {
753             return new CursorWindow(source);
754         }
755 
756         public CursorWindow[] newArray(int size) {
757             return new CursorWindow[size];
758         }
759     };
760 
newFromParcel(Parcel p)761     public static CursorWindow newFromParcel(Parcel p) {
762         return CREATOR.createFromParcel(p);
763     }
764 
describeContents()765     public int describeContents() {
766         return 0;
767     }
768 
writeToParcel(Parcel dest, int flags)769     public void writeToParcel(Parcel dest, int flags) {
770         acquireReference();
771         try {
772             dest.writeInt(mStartPos);
773             nativeWriteToParcel(mWindowPtr, dest);
774         } finally {
775             releaseReference();
776         }
777 
778         if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
779             releaseReference();
780         }
781     }
782 
783     @Override
onAllReferencesReleased()784     protected void onAllReferencesReleased() {
785         dispose();
786     }
787 
788     @android.ravenwood.annotation.RavenwoodReplace
getCursorWindowSize()789     private static int getCursorWindowSize() {
790         if (sCursorWindowSize < 0) {
791             // The cursor window size. resource xml file specifies the value in kB.
792             // convert it to bytes here by multiplying with 1024.
793             sCursorWindowSize = Resources.getSystem().getInteger(
794                     com.android.internal.R.integer.config_cursorWindowSize) * 1024;
795         }
796         return sCursorWindowSize;
797     }
798 
getCursorWindowSize$ravenwood()799     private static int getCursorWindowSize$ravenwood() {
800         return 1024;
801     }
802 
803     @Override
toString()804     public String toString() {
805         return getName() + " {" + Long.toHexString(mWindowPtr) + "}";
806     }
807 }
808