19439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/* 29439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Copyright (C) 2006 The Android Open Source Project 39439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 49439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 59439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * you may not use this file except in compliance with the License. 69439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * You may obtain a copy of the License at 79439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 89439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * http://www.apache.org/licenses/LICENSE-2.0 99439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Unless required by applicable law or agreed to in writing, software 119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * See the License for the specific language governing permissions and 149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * limitations under the License. 159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellypackage android.database; 189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport dalvik.system.CloseGuard; 209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.content.res.Resources; 229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.database.sqlite.SQLiteClosable; 239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.database.sqlite.SQLiteException; 249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.os.Binder; 259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.os.Parcel; 269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.os.Parcelable; 279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.os.Process; 289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.util.Log; 299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.util.SparseIntArray; 309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.util.LongSparseArray; 319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/** 339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * A buffer containing multiple cursor rows. 349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * <p> 359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * A {@link CursorWindow} is read-write when initially created and used locally. 3605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * When sent to a remote process (by writing it to a {@link Parcel}), the remote process 3705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * receives a read-only view of the cursor window. Typically the cursor window 389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * will be allocated by the producer, filled with data, and then sent to the 399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * consumer for reading. 409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * </p> 413998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun */ 423998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejunpublic class CursorWindow extends SQLiteClosable implements Parcelable { 439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static final String STATS_TAG = "CursorWindowStats"; 449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 4505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun // This static member will be evaluated when first used. 469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static int sCursorWindowSize = -1; 479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 4805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun /** 499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * The native CursorWindow object pointer. (FOR INTERNAL USE ONLY) 509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @hide 512e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly */ 529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public long mWindowPtr; 533998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun 543998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun private int mStartPos; 553998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun private final String mName; 563998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun 573998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun private final CloseGuard mCloseGuard = CloseGuard.get(); 583998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun 593998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun private static native long nativeCreate(String name, int cursorWindowSize); 603998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun private static native long nativeCreateFromParcel(Parcel parcel); 619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native void nativeDispose(long windowPtr); 629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native void nativeWriteToParcel(long windowPtr, Parcel parcel); 639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native void nativeClear(long windowPtr); 659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native int nativeGetNumRows(long windowPtr); 679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native boolean nativeSetNumColumns(long windowPtr, int columnNum); 689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native boolean nativeAllocRow(long windowPtr); 699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native void nativeFreeLastRow(long windowPtr); 709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native int nativeGetType(long windowPtr, int row, int column); 729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native byte[] nativeGetBlob(long windowPtr, int row, int column); 739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native String nativeGetString(long windowPtr, int row, int column); 749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native long nativeGetLong(long windowPtr, int row, int column); 759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native double nativeGetDouble(long windowPtr, int row, int column); 769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native void nativeCopyStringToBuffer(long windowPtr, int row, int column, 779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly CharArrayBuffer buffer); 789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native boolean nativePutBlob(long windowPtr, byte[] value, int row, int column); 809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native boolean nativePutString(long windowPtr, String value, int row, int column); 819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native boolean nativePutLong(long windowPtr, long value, int row, int column); 829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native boolean nativePutDouble(long windowPtr, double value, int row, int column); 839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native boolean nativePutNull(long windowPtr, int row, int column); 849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private static native String nativeGetName(long windowPtr); 869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Creates a new empty cursor window and gives it a name. 899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * <p> 909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * The cursor initially has no rows or columns. Call {@link #setNumColumns(int)} to 919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * set the number of columns before adding any rows to the cursor. 929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * </p> 939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param name The name of the cursor window, or null if none. 959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public CursorWindow(String name) { 979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mStartPos = 0; 989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mName = name != null && name.length() != 0 ? name : "<unnamed>"; 999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly if (sCursorWindowSize < 0) { 1009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** The cursor window size. resource xml file specifies the value in kB. 1019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * convert it to bytes here by multiplying with 1024. 1029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 1039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly sCursorWindowSize = Resources.getSystem().getInteger( 1049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly com.android.internal.R.integer.config_cursorWindowSize) * 1024; 1059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mWindowPtr = nativeCreate(mName, sCursorWindowSize); 1079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly if (mWindowPtr == 0) { 1089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly throw new CursorWindowAllocationException("Cursor window allocation of " + 1099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly (sCursorWindowSize / 1024) + " kb failed. " + printStats()); 1109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mCloseGuard.open("close"); 1129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly recordNewWindow(Binder.getCallingPid(), mWindowPtr); 1139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 1169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Creates a new empty cursor window. 1179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * <p> 1189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * The cursor initially has no rows or columns. Call {@link #setNumColumns(int)} to 1199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * set the number of columns before adding any rows to the cursor. 1209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * </p> 1219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 1229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param localWindow True if this window will be used in this process only, 1239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * false if it might be sent to another processes. This argument is ignored. 1249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 1259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @deprecated There is no longer a distinction between local and remote 1269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * cursor windows. Use the {@link #CursorWindow(String)} constructor instead. 1279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 1289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly @Deprecated 1299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public CursorWindow(boolean localWindow) { 1309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly this((String)null); 1319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private CursorWindow(Parcel source) { 1349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mStartPos = source.readInt(); 1359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mWindowPtr = nativeCreateFromParcel(source); 1369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly if (mWindowPtr == 0) { 1379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly throw new CursorWindowAllocationException("Cursor window could not be " 1389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly + "created from binder."); 1399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mName = nativeGetName(mWindowPtr); 1419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mCloseGuard.open("close"); 1429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly @Override 1459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly protected void finalize() throws Throwable { 1469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly try { 1479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly if (mCloseGuard != null) { 1489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mCloseGuard.warnIfOpen(); 1499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly dispose(); 1519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } finally { 1529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly super.finalize(); 1539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly private void dispose() { 1579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly if (mCloseGuard != null) { 1589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mCloseGuard.close(); 1599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly if (mWindowPtr != 0) { 1619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly recordClosingOfWindow(mWindowPtr); 1629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly nativeDispose(mWindowPtr); 1639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mWindowPtr = 0; 1649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 1689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Gets the name of this cursor window, never null. 1699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @hide 1709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 1719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public String getName() { 1729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly return mName; 1739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 1769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Clears out the existing contents of the window, making it safe to reuse 1779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * for new data. 1789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * <p> 1799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * The start position ({@link #getStartPosition()}), number of rows ({@link #getNumRows()}), 1809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * and number of columns in the cursor are all reset to zero. 1819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * </p> 1829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 1839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public void clear() { 1849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly acquireReference(); 1859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly try { 1869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mStartPos = 0; 1879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly nativeClear(mWindowPtr); 1889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } finally { 1899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly releaseReference(); 1909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 1929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 1939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 1949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Gets the start position of this cursor window. 1959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * <p> 1969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * The start position is the zero-based index of the first row that this window contains 1979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * relative to the entire result set of the {@link Cursor}. 1989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * </p> 1999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 2009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @return The zero-based start position. 2019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 2029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public int getStartPosition() { 2039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly return mStartPos; 2049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 2059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 2069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 2079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Sets the start position of this cursor window. 2089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * <p> 2099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * The start position is the zero-based index of the first row that this window contains 2109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * relative to the entire result set of the {@link Cursor}. 2119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * </p> 2129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 2139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param pos The new zero-based start position. 2149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 2159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public void setStartPosition(int pos) { 2169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly mStartPos = pos; 2179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 2189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 2199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 2209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Gets the number of rows in this window. 2219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 2229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @return The number of rows in this cursor window. 2239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 2249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public int getNumRows() { 2259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly acquireReference(); 2269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly try { 2279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly return nativeGetNumRows(mWindowPtr); 2289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } finally { 2299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly releaseReference(); 2309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 2319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 2329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 2339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 2349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Sets the number of columns in this window. 2359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * <p> 2369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * This method must be called before any rows are added to the window, otherwise 2379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * it will fail to set the number of columns if it differs from the current number 2389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * of columns. 2399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * </p> 2409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 2419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param columnNum The new number of columns. 2429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @return True if successful. 2439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 2449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public boolean setNumColumns(int columnNum) { 2459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly acquireReference(); 2469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly try { 2479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly return nativeSetNumColumns(mWindowPtr, columnNum); 2489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } finally { 2499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly releaseReference(); 2509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 2519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 2529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 2539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 2549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Allocates a new row at the end of this cursor window. 2559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 2569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @return True if successful, false if the cursor window is out of memory. 2579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 2589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public boolean allocRow(){ 2599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly acquireReference(); 2609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly try { 2619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly return nativeAllocRow(mWindowPtr); 2629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } finally { 2639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly releaseReference(); 2649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 2659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 2669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 2679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 2689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Frees the last row in this cursor window. 2699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 2709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public void freeLastRow(){ 2719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly acquireReference(); 2729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly try { 2739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly nativeFreeLastRow(mWindowPtr); 2749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } finally { 2759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly releaseReference(); 2769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 2779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 2789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 2799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 2809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Returns true if the field at the specified row and column index 2819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * has type {@link Cursor#FIELD_TYPE_NULL}. 2829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 2839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param row The zero-based row index. 2849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param column The zero-based column index. 2859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @return True if the field has type {@link Cursor#FIELD_TYPE_NULL}. 2869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @deprecated Use {@link #getType(int, int)} instead. 2879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 2889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly @Deprecated 2899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public boolean isNull(int row, int column) { 2909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly return getType(row, column) == Cursor.FIELD_TYPE_NULL; 2919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 2929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 2939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 2949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Returns true if the field at the specified row and column index 2959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * has type {@link Cursor#FIELD_TYPE_BLOB} or {@link Cursor#FIELD_TYPE_NULL}. 2969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 2979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param row The zero-based row index. 2989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param column The zero-based column index. 2999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @return True if the field has type {@link Cursor#FIELD_TYPE_BLOB} or 3009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * {@link Cursor#FIELD_TYPE_NULL}. 3019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @deprecated Use {@link #getType(int, int)} instead. 3029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 3039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly @Deprecated 3049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public boolean isBlob(int row, int column) { 3059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly int type = getType(row, column); 3069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly return type == Cursor.FIELD_TYPE_BLOB || type == Cursor.FIELD_TYPE_NULL; 3079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 3089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 3099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 3109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Returns true if the field at the specified row and column index 3119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * has type {@link Cursor#FIELD_TYPE_INTEGER}. 3129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 3139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param row The zero-based row index. 3149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @param column The zero-based column index. 3159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @return True if the field has type {@link Cursor#FIELD_TYPE_INTEGER}. 3169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * @deprecated Use {@link #getType(int, int)} instead. 3179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */ 3189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly @Deprecated 3199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly public boolean isLong(int row, int column) { 3209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly return getType(row, column) == Cursor.FIELD_TYPE_INTEGER; 3219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly } 3229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly 3239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly /** 3243998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun * Returns true if the field at the specified row and column index 3253998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun * has type {@link Cursor#FIELD_TYPE_FLOAT}. 3269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * 327 * @param row The zero-based row index. 328 * @param column The zero-based column index. 329 * @return True if the field has type {@link Cursor#FIELD_TYPE_FLOAT}. 330 * @deprecated Use {@link #getType(int, int)} instead. 331 */ 332 @Deprecated 333 public boolean isFloat(int row, int column) { 334 return getType(row, column) == Cursor.FIELD_TYPE_FLOAT; 335 } 336 337 /** 338 * Returns true if the field at the specified row and column index 339 * has type {@link Cursor#FIELD_TYPE_STRING} or {@link Cursor#FIELD_TYPE_NULL}. 340 * 341 * @param row The zero-based row index. 342 * @param column The zero-based column index. 343 * @return True if the field has type {@link Cursor#FIELD_TYPE_STRING} 344 * or {@link Cursor#FIELD_TYPE_NULL}. 345 * @deprecated Use {@link #getType(int, int)} instead. 346 */ 347 @Deprecated 348 public boolean isString(int row, int column) { 349 int type = getType(row, column); 350 return type == Cursor.FIELD_TYPE_STRING || type == Cursor.FIELD_TYPE_NULL; 351 } 352 353 /** 354 * Returns the type of the field at the specified row and column index. 355 * <p> 356 * The returned field types are: 357 * <ul> 358 * <li>{@link Cursor#FIELD_TYPE_NULL}</li> 359 * <li>{@link Cursor#FIELD_TYPE_INTEGER}</li> 360 * <li>{@link Cursor#FIELD_TYPE_FLOAT}</li> 361 * <li>{@link Cursor#FIELD_TYPE_STRING}</li> 362 * <li>{@link Cursor#FIELD_TYPE_BLOB}</li> 363 * </ul> 364 * </p> 365 * 366 * @param row The zero-based row index. 367 * @param column The zero-based column index. 368 * @return The field type. 369 */ 370 public int getType(int row, int column) { 371 acquireReference(); 372 try { 373 return nativeGetType(mWindowPtr, row - mStartPos, column); 374 } finally { 375 releaseReference(); 376 } 377 } 378 379 /** 380 * Gets the value of the field at the specified row and column index as a byte array. 381 * <p> 382 * The result is determined as follows: 383 * <ul> 384 * <li>If the field is of type {@link Cursor#FIELD_TYPE_NULL}, then the result 385 * is <code>null</code>.</li> 386 * <li>If the field is of type {@link Cursor#FIELD_TYPE_BLOB}, then the result 387 * is the blob value.</li> 388 * <li>If the field is of type {@link Cursor#FIELD_TYPE_STRING}, then the result 389 * is the array of bytes that make up the internal representation of the 390 * string value.</li> 391 * <li>If the field is of type {@link Cursor#FIELD_TYPE_INTEGER} or 392 * {@link Cursor#FIELD_TYPE_FLOAT}, then a {@link SQLiteException} is thrown.</li> 393 * </ul> 394 * </p> 395 * 396 * @param row The zero-based row index. 397 * @param column The zero-based column index. 398 * @return The value of the field as a byte array. 399 */ 400 public byte[] getBlob(int row, int column) { 401 acquireReference(); 402 try { 403 return nativeGetBlob(mWindowPtr, row - mStartPos, column); 404 } finally { 405 releaseReference(); 406 } 407 } 408 409 /** 410 * Gets the value of the field at the specified row and column index as a string. 411 * <p> 412 * The result is determined as follows: 413 * <ul> 414 * <li>If the field is of type {@link Cursor#FIELD_TYPE_NULL}, then the result 415 * is <code>null</code>.</li> 416 * <li>If the field is of type {@link Cursor#FIELD_TYPE_STRING}, then the result 417 * is the string value.</li> 418 * <li>If the field is of type {@link Cursor#FIELD_TYPE_INTEGER}, then the result 419 * is a string representation of the integer in decimal, obtained by formatting the 420 * value with the <code>printf</code> family of functions using 421 * format specifier <code>%lld</code>.</li> 422 * <li>If the field is of type {@link Cursor#FIELD_TYPE_FLOAT}, then the result 423 * is a string representation of the floating-point value in decimal, obtained by 424 * formatting the value with the <code>printf</code> family of functions using 425 * format specifier <code>%g</code>.</li> 426 * <li>If the field is of type {@link Cursor#FIELD_TYPE_BLOB}, then a 427 * {@link SQLiteException} is thrown.</li> 428 * </ul> 429 * </p> 430 * 431 * @param row The zero-based row index. 432 * @param column The zero-based column index. 433 * @return The value of the field as a string. 434 */ 435 public String getString(int row, int column) { 436 acquireReference(); 437 try { 438 return nativeGetString(mWindowPtr, row - mStartPos, column); 439 } finally { 440 releaseReference(); 441 } 442 } 443 444 /** 445 * Copies the text of the field at the specified row and column index into 446 * a {@link CharArrayBuffer}. 447 * <p> 448 * The buffer is populated as follows: 449 * <ul> 450 * <li>If the buffer is too small for the value to be copied, then it is 451 * automatically resized.</li> 452 * <li>If the field is of type {@link Cursor#FIELD_TYPE_NULL}, then the buffer 453 * is set to an empty string.</li> 454 * <li>If the field is of type {@link Cursor#FIELD_TYPE_STRING}, then the buffer 455 * is set to the contents of the string.</li> 456 * <li>If the field is of type {@link Cursor#FIELD_TYPE_INTEGER}, then the buffer 457 * is set to a string representation of the integer in decimal, obtained by formatting the 458 * value with the <code>printf</code> family of functions using 459 * format specifier <code>%lld</code>.</li> 460 * <li>If the field is of type {@link Cursor#FIELD_TYPE_FLOAT}, then the buffer is 461 * set to a string representation of the floating-point value in decimal, obtained by 462 * formatting the value with the <code>printf</code> family of functions using 463 * format specifier <code>%g</code>.</li> 464 * <li>If the field is of type {@link Cursor#FIELD_TYPE_BLOB}, then a 465 * {@link SQLiteException} is thrown.</li> 466 * </ul> 467 * </p> 468 * 469 * @param row The zero-based row index. 470 * @param column The zero-based column index. 471 * @param buffer The {@link CharArrayBuffer} to hold the string. It is automatically 472 * resized if the requested string is larger than the buffer's current capacity. 473 */ 474 public void copyStringToBuffer(int row, int column, CharArrayBuffer buffer) { 475 if (buffer == null) { 476 throw new IllegalArgumentException("CharArrayBuffer should not be null"); 477 } 478 acquireReference(); 479 try { 480 nativeCopyStringToBuffer(mWindowPtr, row - mStartPos, column, buffer); 481 } finally { 482 releaseReference(); 483 } 484 } 485 486 /** 487 * Gets the value of the field at the specified row and column index as a <code>long</code>. 488 * <p> 489 * The result is determined as follows: 490 * <ul> 491 * <li>If the field is of type {@link Cursor#FIELD_TYPE_NULL}, then the result 492 * is <code>0L</code>.</li> 493 * <li>If the field is of type {@link Cursor#FIELD_TYPE_STRING}, then the result 494 * is the value obtained by parsing the string value with <code>strtoll</code>. 495 * <li>If the field is of type {@link Cursor#FIELD_TYPE_INTEGER}, then the result 496 * is the <code>long</code> value.</li> 497 * <li>If the field is of type {@link Cursor#FIELD_TYPE_FLOAT}, then the result 498 * is the floating-point value converted to a <code>long</code>.</li> 499 * <li>If the field is of type {@link Cursor#FIELD_TYPE_BLOB}, then a 500 * {@link SQLiteException} is thrown.</li> 501 * </ul> 502 * </p> 503 * 504 * @param row The zero-based row index. 505 * @param column The zero-based column index. 506 * @return The value of the field as a <code>long</code>. 507 */ 508 public long getLong(int row, int column) { 509 acquireReference(); 510 try { 511 return nativeGetLong(mWindowPtr, row - mStartPos, column); 512 } finally { 513 releaseReference(); 514 } 515 } 516 517 /** 518 * Gets the value of the field at the specified row and column index as a 519 * <code>double</code>. 520 * <p> 521 * The result is determined as follows: 522 * <ul> 523 * <li>If the field is of type {@link Cursor#FIELD_TYPE_NULL}, then the result 524 * is <code>0.0</code>.</li> 525 * <li>If the field is of type {@link Cursor#FIELD_TYPE_STRING}, then the result 526 * is the value obtained by parsing the string value with <code>strtod</code>. 527 * <li>If the field is of type {@link Cursor#FIELD_TYPE_INTEGER}, then the result 528 * is the integer value converted to a <code>double</code>.</li> 529 * <li>If the field is of type {@link Cursor#FIELD_TYPE_FLOAT}, then the result 530 * is the <code>double</code> value.</li> 531 * <li>If the field is of type {@link Cursor#FIELD_TYPE_BLOB}, then a 532 * {@link SQLiteException} is thrown.</li> 533 * </ul> 534 * </p> 535 * 536 * @param row The zero-based row index. 537 * @param column The zero-based column index. 538 * @return The value of the field as a <code>double</code>. 539 */ 540 public double getDouble(int row, int column) { 541 acquireReference(); 542 try { 543 return nativeGetDouble(mWindowPtr, row - mStartPos, column); 544 } finally { 545 releaseReference(); 546 } 547 } 548 549 /** 550 * Gets the value of the field at the specified row and column index as a 551 * <code>short</code>. 552 * <p> 553 * The result is determined by invoking {@link #getLong} and converting the 554 * result to <code>short</code>. 555 * </p> 556 * 557 * @param row The zero-based row index. 558 * @param column The zero-based column index. 559 * @return The value of the field as a <code>short</code>. 560 */ 561 public short getShort(int row, int column) { 562 return (short) getLong(row, column); 563 } 564 565 /** 566 * Gets the value of the field at the specified row and column index as an 567 * <code>int</code>. 568 * <p> 569 * The result is determined by invoking {@link #getLong} and converting the 570 * result to <code>int</code>. 571 * </p> 572 * 573 * @param row The zero-based row index. 574 * @param column The zero-based column index. 575 * @return The value of the field as an <code>int</code>. 576 */ 577 public int getInt(int row, int column) { 578 return (int) getLong(row, column); 579 } 580 581 /** 582 * Gets the value of the field at the specified row and column index as a 583 * <code>float</code>. 584 * <p> 585 * The result is determined by invoking {@link #getDouble} and converting the 586 * result to <code>float</code>. 587 * </p> 588 * 589 * @param row The zero-based row index. 590 * @param column The zero-based column index. 591 * @return The value of the field as an <code>float</code>. 592 */ 593 public float getFloat(int row, int column) { 594 return (float) getDouble(row, column); 595 } 596 597 /** 598 * Copies a byte array into the field at the specified row and column index. 599 * 600 * @param value The value to store. 601 * @param row The zero-based row index. 602 * @param column The zero-based column index. 603 * @return True if successful. 604 */ 605 public boolean putBlob(byte[] value, int row, int column) { 606 acquireReference(); 607 try { 608 return nativePutBlob(mWindowPtr, value, row - mStartPos, column); 609 } finally { 610 releaseReference(); 611 } 612 } 613 614 /** 615 * Copies a string into the field at the specified row and column index. 616 * 617 * @param value The value to store. 618 * @param row The zero-based row index. 619 * @param column The zero-based column index. 620 * @return True if successful. 621 */ 622 public boolean putString(String value, int row, int column) { 623 acquireReference(); 624 try { 625 return nativePutString(mWindowPtr, value, row - mStartPos, column); 626 } finally { 627 releaseReference(); 628 } 629 } 630 631 /** 632 * Puts a long integer into the field at the specified row and column index. 633 * 634 * @param value The value to store. 635 * @param row The zero-based row index. 636 * @param column The zero-based column index. 637 * @return True if successful. 638 */ 639 public boolean putLong(long value, int row, int column) { 640 acquireReference(); 641 try { 642 return nativePutLong(mWindowPtr, value, row - mStartPos, column); 643 } finally { 644 releaseReference(); 645 } 646 } 647 648 /** 649 * Puts a double-precision floating point value into the field at the 650 * specified row and column index. 651 * 652 * @param value The value to store. 653 * @param row The zero-based row index. 654 * @param column The zero-based column index. 655 * @return True if successful. 656 */ 657 public boolean putDouble(double value, int row, int column) { 658 acquireReference(); 659 try { 660 return nativePutDouble(mWindowPtr, value, row - mStartPos, column); 661 } finally { 662 releaseReference(); 663 } 664 } 665 666 /** 667 * Puts a null value into the field at the specified row and column index. 668 * 669 * @param row The zero-based row index. 670 * @param column The zero-based column index. 671 * @return True if successful. 672 */ 673 public boolean putNull(int row, int column) { 674 acquireReference(); 675 try { 676 return nativePutNull(mWindowPtr, row - mStartPos, column); 677 } finally { 678 releaseReference(); 679 } 680 } 681 682 public static final Parcelable.Creator<CursorWindow> CREATOR 683 = new Parcelable.Creator<CursorWindow>() { 684 public CursorWindow createFromParcel(Parcel source) { 685 return new CursorWindow(source); 686 } 687 688 public CursorWindow[] newArray(int size) { 689 return new CursorWindow[size]; 690 } 691 }; 692 693 public static CursorWindow newFromParcel(Parcel p) { 694 return CREATOR.createFromParcel(p); 695 } 696 697 public int describeContents() { 698 return 0; 699 } 700 701 public void writeToParcel(Parcel dest, int flags) { 702 acquireReference(); 703 try { 704 dest.writeInt(mStartPos); 705 nativeWriteToParcel(mWindowPtr, dest); 706 } finally { 707 releaseReference(); 708 } 709 710 if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) { 711 releaseReference(); 712 } 713 } 714 715 @Override 716 protected void onAllReferencesReleased() { 717 dispose(); 718 } 719 720 private static final LongSparseArray<Integer> sWindowToPidMap = new LongSparseArray<Integer>(); 721 722 private void recordNewWindow(int pid, long window) { 723 synchronized (sWindowToPidMap) { 724 sWindowToPidMap.put(window, pid); 725 if (Log.isLoggable(STATS_TAG, Log.VERBOSE)) { 726 Log.i(STATS_TAG, "Created a new Cursor. " + printStats()); 727 } 728 } 729 } 730 731 private void recordClosingOfWindow(long window) { 732 synchronized (sWindowToPidMap) { 733 if (sWindowToPidMap.size() == 0) { 734 // this means we are not in the ContentProvider. 735 return; 736 } 737 sWindowToPidMap.delete(window); 738 } 739 } 740 741 private String printStats() { 742 StringBuilder buff = new StringBuilder(); 743 int myPid = Process.myPid(); 744 int total = 0; 745 SparseIntArray pidCounts = new SparseIntArray(); 746 synchronized (sWindowToPidMap) { 747 int size = sWindowToPidMap.size(); 748 if (size == 0) { 749 // this means we are not in the ContentProvider. 750 return ""; 751 } 752 for (int indx = 0; indx < size; indx++) { 753 int pid = sWindowToPidMap.valueAt(indx); 754 int value = pidCounts.get(pid); 755 pidCounts.put(pid, ++value); 756 } 757 } 758 int numPids = pidCounts.size(); 759 for (int i = 0; i < numPids;i++) { 760 buff.append(" (# cursors opened by "); 761 int pid = pidCounts.keyAt(i); 762 if (pid == myPid) { 763 buff.append("this proc="); 764 } else { 765 buff.append("pid " + pid + "="); 766 } 767 int num = pidCounts.get(pid); 768 buff.append(num + ")"); 769 total += num; 770 } 771 // limit the returned string size to 1000 772 String s = (buff.length() > 980) ? buff.substring(0, 980) : buff.toString(); 773 return "# Open Cursors=" + total + s; 774 } 775 776 @Override 777 public String toString() { 778 return getName() + " {" + Long.toHexString(mWindowPtr) + "}"; 779 } 780} 781