SQLite Android Bindings
Check-in [bd482c8af6]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the original versions of all the Android files imported and modified in this project. The versions imported are from commit e819e49b31dc0bc82dd617700299ad13ff6fd7f8 on the master branch of the git repository here: https://android.googlesource.com/platform/frameworks/base/
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | base
Files: files | file ages | folders
SHA1: bd482c8af619343fdd0e14ad9989139e7556b1d4
User & Date: dan 2017-11-27 20:06:31
Context
2017-11-27
20:21
Add script to import files from a git checkout. Leaf check-in: 51cdfe5c9a user: dan tags: base
20:06
Add the original versions of all the Android files imported and modified in this project. The versions imported are from commit e819e49b31dc0bc82dd617700299ad13ff6fd7f8 on the master branch of the git repository here: https://android.googlesource.com/platform/frameworks/base/ check-in: bd482c8af6 user: dan tags: base
19:22
Remove out of date "package.html" files. check-in: e9352bdf96 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to sqlite3/src/main/java/org/sqlite/database/DatabaseErrorHandler.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
           16  +
           17  +package android.database;
    20     18   
    21         -package org.sqlite.database;
    22         -
    23         -import org.sqlite.database.sqlite.SQLiteDatabase;
           19  +import android.database.sqlite.SQLiteDatabase;
    24     20   
    25     21   /**
    26         - * An interface to let the apps define the actions to take when the following errors are detected
    27         - *   database corruption
           22  + * An interface to let apps define an action to take when database corruption is detected.
    28     23    */
    29     24   public interface DatabaseErrorHandler {
    30     25   
    31     26       /**
    32         -     * defines the method to be invoked when database corruption is detected.
           27  +     * The method invoked when database corruption is detected.
    33     28        * @param dbObj the {@link SQLiteDatabase} object representing the database on which corruption
    34     29        * is detected.
    35     30        */
    36     31       void onCorruption(SQLiteDatabase dbObj);
    37     32   }

Changes to sqlite3/src/main/java/org/sqlite/database/DatabaseUtils.java.

    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16     16   
    17         -package org.sqlite.database;
           17  +package android.database;
    18     18   
    19     19   import android.content.ContentValues;
    20     20   import android.content.Context;
    21     21   import android.content.OperationApplicationException;
    22         -import org.sqlite.database.sqlite.SQLiteAbortException;
    23         -import org.sqlite.database.sqlite.SQLiteConstraintException;
    24         -import org.sqlite.database.sqlite.SQLiteDatabase;
    25         -import org.sqlite.database.sqlite.SQLiteDatabaseCorruptException;
    26         -import org.sqlite.database.sqlite.SQLiteDiskIOException;
    27         -import org.sqlite.database.sqlite.SQLiteException;
    28         -import org.sqlite.database.sqlite.SQLiteFullException;
    29         -import org.sqlite.database.sqlite.SQLiteProgram;
    30         -import org.sqlite.database.sqlite.SQLiteStatement;
    31         -
    32         -import android.database.CursorWindow;
           22  +import android.database.sqlite.SQLiteAbortException;
           23  +import android.database.sqlite.SQLiteConstraintException;
           24  +import android.database.sqlite.SQLiteDatabase;
           25  +import android.database.sqlite.SQLiteDatabaseCorruptException;
           26  +import android.database.sqlite.SQLiteDiskIOException;
           27  +import android.database.sqlite.SQLiteException;
           28  +import android.database.sqlite.SQLiteFullException;
           29  +import android.database.sqlite.SQLiteProgram;
           30  +import android.database.sqlite.SQLiteStatement;
    33     31   import android.os.OperationCanceledException;
    34     32   import android.os.Parcel;
    35     33   import android.os.ParcelFileDescriptor;
    36     34   import android.text.TextUtils;
    37     35   import android.util.Log;
    38     36   
    39         -import android.database.Cursor;
    40         -
    41         -import java.io.File;
    42     37   import java.io.FileNotFoundException;
    43     38   import java.io.PrintStream;
    44     39   import java.text.Collator;
    45     40   import java.util.HashMap;
    46     41   import java.util.Locale;
    47     42   import java.util.Map;
    48     43   
................................................................................
   129    124        * a parcel, to be used after receiving the result of a transaction.  This
   130    125        * will throw the exception for you if it had been written to the Parcel,
   131    126        * otherwise return and let you read the normal result data from the Parcel.
   132    127        * @param reply Parcel to read from
   133    128        * @see Parcel#writeNoException
   134    129        * @see Parcel#readException
   135    130        */
   136         -//    public static final void readExceptionFromParcel(Parcel reply) {
   137         -//        int code = reply.readExceptionCode();
   138         -//        if (code == 0) return;
   139         -//        String msg = reply.readString();
   140         -//        DatabaseUtils.readExceptionFromParcel(reply, msg, code);
   141         -//    }
   142         -//
   143         -//    public static void readExceptionWithFileNotFoundExceptionFromParcel(
   144         -//            Parcel reply) throws FileNotFoundException {
   145         -//        int code = reply.readExceptionCode();
   146         -//        if (code == 0) return;
   147         -//        String msg = reply.readString();
   148         -//        if (code == 1) {
   149         -//            throw new FileNotFoundException(msg);
   150         -//        } else {
   151         -//            DatabaseUtils.readExceptionFromParcel(reply, msg, code);
   152         -//        }
   153         -//    }
   154         -//
   155         -//    public static void readExceptionWithOperationApplicationExceptionFromParcel(
   156         -//            Parcel reply) throws OperationApplicationException {
   157         -//        int code = reply.readExceptionCode();
   158         -//        if (code == 0) return;
   159         -//        String msg = reply.readString();
   160         -//        if (code == 10) {
   161         -//            throw new OperationApplicationException(msg);
   162         -//        } else {
   163         -//            DatabaseUtils.readExceptionFromParcel(reply, msg, code);
   164         -//        }
   165         -//    }
          131  +    public static final void readExceptionFromParcel(Parcel reply) {
          132  +        int code = reply.readExceptionCode();
          133  +        if (code == 0) return;
          134  +        String msg = reply.readString();
          135  +        DatabaseUtils.readExceptionFromParcel(reply, msg, code);
          136  +    }
          137  +
          138  +    public static void readExceptionWithFileNotFoundExceptionFromParcel(
          139  +            Parcel reply) throws FileNotFoundException {
          140  +        int code = reply.readExceptionCode();
          141  +        if (code == 0) return;
          142  +        String msg = reply.readString();
          143  +        if (code == 1) {
          144  +            throw new FileNotFoundException(msg);
          145  +        } else {
          146  +            DatabaseUtils.readExceptionFromParcel(reply, msg, code);
          147  +        }
          148  +    }
          149  +
          150  +    public static void readExceptionWithOperationApplicationExceptionFromParcel(
          151  +            Parcel reply) throws OperationApplicationException {
          152  +        int code = reply.readExceptionCode();
          153  +        if (code == 0) return;
          154  +        String msg = reply.readString();
          155  +        if (code == 10) {
          156  +            throw new OperationApplicationException(msg);
          157  +        } else {
          158  +            DatabaseUtils.readExceptionFromParcel(reply, msg, code);
          159  +        }
          160  +    }
   166    161   
   167    162       private static final void readExceptionFromParcel(Parcel reply, String msg, int code) {
   168    163           switch (code) {
   169    164               case 2:
   170    165                   throw new IllegalArgumentException(msg);
   171    166               case 3:
   172    167                   throw new UnsupportedOperationException(msg);
................................................................................
  1362   1357        * @param dbVersion the version to set on the db
  1363   1358        * @param sqlStatements the statements to use to populate the db. This should be a single string
  1364   1359        *   of the form returned by sqlite3's <tt>.dump</tt> command (statements separated by
  1365   1360        *   semicolons)
  1366   1361        */
  1367   1362       static public void createDbFromSqlStatements(
  1368   1363               Context context, String dbName, int dbVersion, String sqlStatements) {
  1369         -
  1370         -        File f = context.getDatabasePath(dbName);
  1371         -        f.getParentFile().mkdirs();
  1372         -        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, null);
  1373         -
         1364  +        SQLiteDatabase db = context.openOrCreateDatabase(dbName, 0, null);
  1374   1365           // TODO: this is not quite safe since it assumes that all semicolons at the end of a line
  1375   1366           // terminate statements. It is possible that a text field contains ;\n. We will have to fix
  1376   1367           // this if that turns out to be a problem.
  1377   1368           String[] statements = TextUtils.split(sqlStatements, ";\n");
  1378   1369           for (String statement : statements) {
  1379   1370               if (TextUtils.isEmpty(statement)) continue;
  1380   1371               db.execSQL(statement);

Changes to sqlite3/src/main/java/org/sqlite/database/DefaultDatabaseErrorHandler.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20         -
    21         -package org.sqlite.database;
           16  +package android.database;
    22     17   
    23     18   import java.io.File;
    24     19   import java.util.List;
    25     20   
    26         -import org.sqlite.database.sqlite.SQLiteDatabase;
    27         -import org.sqlite.database.sqlite.SQLiteException;
           21  +import android.database.sqlite.SQLiteDatabase;
           22  +import android.database.sqlite.SQLiteException;
    28     23   import android.util.Log;
    29     24   import android.util.Pair;
    30     25   
    31     26   /**
    32         - * Default class used to define the actions to take when the database corruption is reported
           27  + * Default class used to define the action to take when database corruption is reported
    33     28    * by sqlite.
    34     29    * <p>
    35     30    * An application can specify an implementation of {@link DatabaseErrorHandler} on the
    36     31    * following:
    37     32    * <ul>
    38     33    *   <li>{@link SQLiteDatabase#openOrCreateDatabase(String,
    39         - *      org.sqlite.database.sqlite.SQLiteDatabase.CursorFactory, DatabaseErrorHandler)}</li>
           34  + *      android.database.sqlite.SQLiteDatabase.CursorFactory, DatabaseErrorHandler)}</li>
    40     35    *   <li>{@link SQLiteDatabase#openDatabase(String,
    41         - *      org.sqlite.database.sqlite.SQLiteDatabase.CursorFactory, int, DatabaseErrorHandler)}</li>
           36  + *      android.database.sqlite.SQLiteDatabase.CursorFactory, int, DatabaseErrorHandler)}</li>
    42     37    * </ul>
    43     38    * The specified {@link DatabaseErrorHandler} is used to handle database corruption errors, if they
    44     39    * occur.
    45     40    * <p>
    46         - * If null is specified for DatabaeErrorHandler param in the above calls, then this class is used
           41  + * If null is specified for the DatabaseErrorHandler param in the above calls, this class is used
    47     42    * as the default {@link DatabaseErrorHandler}.
    48     43    */
    49     44   public final class DefaultDatabaseErrorHandler implements DatabaseErrorHandler {
    50     45   
    51     46       private static final String TAG = "DefaultDatabaseErrorHandler";
    52     47   
    53     48       /**
................................................................................
    54     49        * defines the default method to be invoked when database corruption is detected.
    55     50        * @param dbObj the {@link SQLiteDatabase} object representing the database on which corruption
    56     51        * is detected.
    57     52        */
    58     53       public void onCorruption(SQLiteDatabase dbObj) {
    59     54           Log.e(TAG, "Corruption reported by sqlite on database: " + dbObj.getPath());
    60     55   
    61         -	// If this is a SEE build, do not delete any database files.
    62         -	//
    63         -	if( SQLiteDatabase.hasCodec() ) return;
    64         -
    65     56           // is the corruption detected even before database could be 'opened'?
    66     57           if (!dbObj.isOpen()) {
    67     58               // database files are not even openable. delete this database file.
    68     59               // NOTE if the database has attached databases, then any of them could be corrupt.
    69     60               // and not deleting all of them could cause corrupted database file to remain and 
    70     61               // make the application crash on database open operation. To avoid this problem,
    71     62               // the application should provide its own {@link DatabaseErrorHandler} impl class

Changes to sqlite3/src/main/java/org/sqlite/database/SQLException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database;
           17  +package android.database;
    22     18   
    23     19   /**
    24     20    * An exception that indicates there was an error with SQL parsing or execution.
    25     21    */
    26     22   public class SQLException extends RuntimeException {
    27     23       public SQLException() {
    28     24       }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/DatabaseObjectNotClosedException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * An exception that indicates that garbage-collector is finalizing a database object
    25     21    * that is not explicitly closed
    26     22    * @hide
    27     23    */
    28     24   public class DatabaseObjectNotClosedException extends RuntimeException {

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteAbortException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * An exception that indicates that the SQLite program was aborted.
    25     21    * This can happen either through a call to ABORT in a trigger,
    26     22    * or as the result of using the ABORT conflict clause.
    27     23    */
    28     24   public class SQLiteAbortException extends SQLiteException {
    29     25       public SQLiteAbortException() {}
    30     26   
    31     27       public SQLiteAbortException(String error) {
    32     28           super(error);
    33     29       }
    34     30   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteAccessPermException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * This exception class is used when sqlite can't access the database file
    25     21    * due to lack of permissions on the file.
    26     22    */
    27     23   public class SQLiteAccessPermException extends SQLiteException {
    28     24       public SQLiteAccessPermException() {}
    29     25   
    30     26       public SQLiteAccessPermException(String error) {
    31     27           super(error);
    32     28       }
    33     29   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * Thrown if the the bind or column parameter index is out of range
    25     21    */
    26     22   public class SQLiteBindOrColumnIndexOutOfRangeException extends SQLiteException {
    27     23       public SQLiteBindOrColumnIndexOutOfRangeException() {}
    28     24   
    29     25       public SQLiteBindOrColumnIndexOutOfRangeException(String error) {
    30     26           super(error);
    31     27       }
    32     28   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteBlobTooBigException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   public class SQLiteBlobTooBigException extends SQLiteException {
    24     20       public SQLiteBlobTooBigException() {}
    25     21   
    26     22       public SQLiteBlobTooBigException(String error) {
    27     23           super(error);
    28     24       }
    29     25   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteCantOpenDatabaseException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   public class SQLiteCantOpenDatabaseException extends SQLiteException {
    24     20       public SQLiteCantOpenDatabaseException() {}
    25     21   
    26     22       public SQLiteCantOpenDatabaseException(String error) {
    27     23           super(error);
    28     24       }
    29     25   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteClosable.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import java.io.Closeable;
    24     20   
    25     21   /**
    26     22    * An object created from a SQLiteDatabase that can be closed.
    27     23    *
    28     24    * This class implements a primitive reference counting scheme for database objects.

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnection.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23         -/* import dalvik.system.BlockGuard; */
    24         -import org.sqlite.database.sqlite.CloseGuard;
           19  +import dalvik.system.BlockGuard;
           20  +import dalvik.system.CloseGuard;
    25     21   
    26     22   import android.database.Cursor;
    27     23   import android.database.CursorWindow;
    28         -import org.sqlite.database.DatabaseUtils;
    29         -import org.sqlite.database.sqlite.SQLiteDebug.DbStats;
           24  +import android.database.DatabaseUtils;
           25  +import android.database.sqlite.SQLiteDebug.DbStats;
    30     26   import android.os.CancellationSignal;
    31     27   import android.os.OperationCanceledException;
    32     28   import android.os.ParcelFileDescriptor;
           29  +import android.os.SystemClock;
           30  +import android.os.Trace;
    33     31   import android.util.Log;
    34     32   import android.util.LruCache;
    35     33   import android.util.Printer;
    36     34   
    37     35   import java.text.SimpleDateFormat;
    38     36   import java.util.ArrayList;
    39     37   import java.util.Date;
................................................................................
    91     89   public final class SQLiteConnection implements CancellationSignal.OnCancelListener {
    92     90       private static final String TAG = "SQLiteConnection";
    93     91       private static final boolean DEBUG = false;
    94     92   
    95     93       private static final String[] EMPTY_STRING_ARRAY = new String[0];
    96     94       private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
    97     95   
    98         -    private static final Pattern TRIM_SQL_PATTERN = Pattern.compile("[\\s]*\\n+[\\s]*");
    99         -
   100     96       private final CloseGuard mCloseGuard = CloseGuard.get();
   101     97   
   102     98       private final SQLiteConnectionPool mPool;
   103     99       private final SQLiteDatabaseConfiguration mConfiguration;
   104    100       private final int mConnectionId;
   105    101       private final boolean mIsPrimaryConnection;
   106    102       private final boolean mIsReadOnlyConnection;
................................................................................
   151    147       private static native String nativeExecuteForString(long connectionPtr, long statementPtr);
   152    148       private static native int nativeExecuteForBlobFileDescriptor(
   153    149               long connectionPtr, long statementPtr);
   154    150       private static native int nativeExecuteForChangedRowCount(long connectionPtr, long statementPtr);
   155    151       private static native long nativeExecuteForLastInsertedRowId(
   156    152               long connectionPtr, long statementPtr);
   157    153       private static native long nativeExecuteForCursorWindow(
   158         -            long connectionPtr, long statementPtr, CursorWindow win,
          154  +            long connectionPtr, long statementPtr, long windowPtr,
   159    155               int startPos, int requiredPos, boolean countAllRows);
   160    156       private static native int nativeGetDbLookaside(long connectionPtr);
   161    157       private static native void nativeCancel(long connectionPtr);
   162    158       private static native void nativeResetCancel(long connectionPtr, boolean cancelable);
   163    159   
   164         -    private static native boolean nativeHasCodec();
   165         -    public static boolean hasCodec(){ return nativeHasCodec(); }
   166         -
   167    160       private SQLiteConnection(SQLiteConnectionPool pool,
   168    161               SQLiteDatabaseConfiguration configuration,
   169    162               int connectionId, boolean primaryConnection) {
   170    163           mPool = pool;
   171    164           mConfiguration = new SQLiteDatabaseConfiguration(configuration);
   172    165           mConnectionId = connectionId;
   173    166           mIsPrimaryConnection = primaryConnection;
................................................................................
   215    208       private void open() {
   216    209           mConnectionPtr = nativeOpen(mConfiguration.path, mConfiguration.openFlags,
   217    210                   mConfiguration.label,
   218    211                   SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME);
   219    212   
   220    213           setPageSize();
   221    214           setForeignKeyModeFromConfiguration();
          215  +        setWalModeFromConfiguration();
   222    216           setJournalSizeLimit();
   223         -	setAutoCheckpointInterval();
   224         -        setWalModeFromConfiguration();
          217  +        setAutoCheckpointInterval();
   225    218           setLocaleFromConfiguration();
   226    219   
   227    220           // Register custom functions.
   228    221           final int functionCount = mConfiguration.customFunctions.size();
   229    222           for (int i = 0; i < functionCount; i++) {
   230    223               SQLiteCustomFunction function = mConfiguration.customFunctions.get(i);
   231    224               nativeRegisterCustomFunction(mConnectionPtr, function);
................................................................................
   398    391               }
   399    392           } catch (RuntimeException ex) {
   400    393               throw new SQLiteException("Failed to change locale for db '" + mConfiguration.label
   401    394                       + "' to '" + newLocale + "'.", ex);
   402    395           }
   403    396       }
   404    397   
   405         -    public void enableLocalizedCollators(){
   406         -      if( nativeHasCodec() ){
   407         -	setLocaleFromConfiguration();
   408         -      }
   409         -    }
   410         -
   411    398       // Called by SQLiteConnectionPool only.
   412    399       void reconfigure(SQLiteDatabaseConfiguration configuration) {
   413    400           mOnlyAllowReadOnlyOperations = false;
   414    401   
   415    402           // Register custom functions.
   416    403           final int functionCount = configuration.customFunctions.size();
   417    404           for (int i = 0; i < functionCount; i++) {
................................................................................
   428    415                   & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
   429    416           boolean localeChanged = !configuration.locale.equals(mConfiguration.locale);
   430    417   
   431    418           // Update configuration parameters.
   432    419           mConfiguration.updateParametersFrom(configuration);
   433    420   
   434    421           // Update prepared statement cache size.
   435         -        /* mPreparedStatementCache.resize(configuration.maxSqlCacheSize); */
          422  +        mPreparedStatementCache.resize(configuration.maxSqlCacheSize);
   436    423   
   437    424           // Update foreign key mode.
   438    425           if (foreignKeyModeChanged) {
   439    426               setForeignKeyModeFromConfiguration();
   440    427           }
   441    428   
   442    429           // Update WAL.
................................................................................
   852    839                   try {
   853    840                       throwIfStatementForbidden(statement);
   854    841                       bindArguments(statement, bindArgs);
   855    842                       applyBlockGuardPolicy(statement);
   856    843                       attachCancellationSignal(cancellationSignal);
   857    844                       try {
   858    845                           final long result = nativeExecuteForCursorWindow(
   859         -                                mConnectionPtr, statement.mStatementPtr, window,
          846  +                                mConnectionPtr, statement.mStatementPtr, window.mWindowPtr,
   860    847                                   startPos, requiredPos, countAllRows);
   861    848                           actualPos = (int)(result >> 32);
   862    849                           countedRows = (int)result;
   863    850                           filledRows = window.getNumRows();
   864    851                           window.setStartPosition(actualPos);
   865    852                           return countedRows;
   866    853                       } finally {
................................................................................
  1045   1032                   || statementType == DatabaseUtils.STATEMENT_SELECT) {
  1046   1033               return true;
  1047   1034           }
  1048   1035           return false;
  1049   1036       }
  1050   1037   
  1051   1038       private void applyBlockGuardPolicy(PreparedStatement statement) {
  1052         -/*        if (!mConfiguration.isInMemoryDb()) {*/
  1053         -/*            if (statement.mReadOnly) {*/
  1054         -/*                BlockGuard.getThreadPolicy().onReadFromDisk();*/
  1055         -/*            } else {*/
  1056         -/*                BlockGuard.getThreadPolicy().onWriteToDisk();*/
  1057         -/*            }*/
  1058         -/*        }*/
         1039  +        if (!mConfiguration.isInMemoryDb()) {
         1040  +            if (statement.mReadOnly) {
         1041  +                BlockGuard.getThreadPolicy().onReadFromDisk();
         1042  +            } else {
         1043  +                BlockGuard.getThreadPolicy().onWriteToDisk();
         1044  +            }
         1045  +        }
  1059   1046       }
  1060   1047   
  1061   1048       /**
  1062   1049        * Dumps debugging information about this connection.
  1063   1050        *
  1064   1051        * @param printer The printer to receive the dump, not null.
  1065   1052        * @param verbose True to dump more verbose information.
................................................................................
  1212   1199       private void recyclePreparedStatement(PreparedStatement statement) {
  1213   1200           statement.mSql = null;
  1214   1201           statement.mPoolNext = mPreparedStatementPool;
  1215   1202           mPreparedStatementPool = statement;
  1216   1203       }
  1217   1204   
  1218   1205       private static String trimSqlForDisplay(String sql) {
  1219         -        return TRIM_SQL_PATTERN.matcher(sql).replaceAll(" ");
         1206  +        // Note: Creating and caching a regular expression is expensive at preload-time
         1207  +        //       and stops compile-time initialization. This pattern is only used when
         1208  +        //       dumping the connection, which is a rare (mainly error) case. So:
         1209  +        //       DO NOT CACHE.
         1210  +        return sql.replaceAll("[\\s]*\\n+[\\s]*", " ");
  1220   1211       }
  1221   1212   
  1222   1213       /**
  1223   1214        * Holder type for a prepared statement.
  1224   1215        *
  1225   1216        * Although this object holds a pointer to a native statement object, it
  1226   1217        * does not have a finalizer.  This is deliberate.  The {@link SQLiteConnection}
................................................................................
  1317   1308                   } else {
  1318   1309                       operation.mFinished = false;
  1319   1310                       operation.mException = null;
  1320   1311                       if (operation.mBindArgs != null) {
  1321   1312                           operation.mBindArgs.clear();
  1322   1313                       }
  1323   1314                   }
  1324         -                operation.mStartTime = System.currentTimeMillis();
         1315  +                operation.mStartWallTime = System.currentTimeMillis();
         1316  +                operation.mStartTime = SystemClock.uptimeMillis();
  1325   1317                   operation.mKind = kind;
  1326   1318                   operation.mSql = sql;
  1327   1319                   if (bindArgs != null) {
  1328   1320                       if (operation.mBindArgs == null) {
  1329   1321                           operation.mBindArgs = new ArrayList<Object>();
  1330   1322                       } else {
  1331   1323                           operation.mBindArgs.clear();
................................................................................
  1337   1329                               operation.mBindArgs.add(EMPTY_BYTE_ARRAY);
  1338   1330                           } else {
  1339   1331                               operation.mBindArgs.add(arg);
  1340   1332                           }
  1341   1333                       }
  1342   1334                   }
  1343   1335                   operation.mCookie = newOperationCookieLocked(index);
         1336  +                if (Trace.isTagEnabled(Trace.TRACE_TAG_DATABASE)) {
         1337  +                    Trace.asyncTraceBegin(Trace.TRACE_TAG_DATABASE, operation.getTraceMethodName(),
         1338  +                            operation.mCookie);
         1339  +                }
  1344   1340                   mIndex = index;
  1345   1341                   return operation.mCookie;
  1346   1342               }
  1347   1343           }
  1348   1344   
  1349   1345           public void failOperation(int cookie, Exception ex) {
  1350   1346               synchronized (mOperations) {
................................................................................
  1374   1370                   logOperationLocked(cookie, detail);
  1375   1371               }
  1376   1372           }
  1377   1373   
  1378   1374           private boolean endOperationDeferLogLocked(int cookie) {
  1379   1375               final Operation operation = getOperationLocked(cookie);
  1380   1376               if (operation != null) {
  1381         -                operation.mEndTime = System.currentTimeMillis();
         1377  +                if (Trace.isTagEnabled(Trace.TRACE_TAG_DATABASE)) {
         1378  +                    Trace.asyncTraceEnd(Trace.TRACE_TAG_DATABASE, operation.getTraceMethodName(),
         1379  +                            operation.mCookie);
         1380  +                }
         1381  +                operation.mEndTime = SystemClock.uptimeMillis();
  1382   1382                   operation.mFinished = true;
  1383   1383                   return SQLiteDebug.DEBUG_LOG_SLOW_QUERIES && SQLiteDebug.shouldLogSlowQuery(
  1384   1384                                   operation.mEndTime - operation.mStartTime);
  1385   1385               }
  1386   1386               return false;
  1387   1387           }
  1388   1388   
................................................................................
  1446   1446                       printer.println("    <none>");
  1447   1447                   }
  1448   1448               }
  1449   1449           }
  1450   1450       }
  1451   1451   
  1452   1452       private static final class Operation {
  1453         -        private static final SimpleDateFormat sDateFormat =
  1454         -                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
         1453  +        // Trim all SQL statements to 256 characters inside the trace marker.
         1454  +        // This limit gives plenty of context while leaving space for other
         1455  +        // entries in the trace buffer (and ensures atrace doesn't truncate the
         1456  +        // marker for us, potentially losing metadata in the process).
         1457  +        private static final int MAX_TRACE_METHOD_NAME_LEN = 256;
  1455   1458   
  1456         -        public long mStartTime;
  1457         -        public long mEndTime;
         1459  +        public long mStartWallTime; // in System.currentTimeMillis()
         1460  +        public long mStartTime; // in SystemClock.uptimeMillis();
         1461  +        public long mEndTime; // in SystemClock.uptimeMillis();
  1458   1462           public String mKind;
  1459   1463           public String mSql;
  1460   1464           public ArrayList<Object> mBindArgs;
  1461   1465           public boolean mFinished;
  1462   1466           public Exception mException;
  1463   1467           public int mCookie;
  1464   1468   
  1465   1469           public void describe(StringBuilder msg, boolean verbose) {
  1466   1470               msg.append(mKind);
  1467   1471               if (mFinished) {
  1468   1472                   msg.append(" took ").append(mEndTime - mStartTime).append("ms");
  1469   1473               } else {
  1470         -                msg.append(" started ").append(System.currentTimeMillis() - mStartTime)
         1474  +                msg.append(" started ").append(System.currentTimeMillis() - mStartWallTime)
  1471   1475                           .append("ms ago");
  1472   1476               }
  1473   1477               msg.append(" - ").append(getStatus());
  1474   1478               if (mSql != null) {
  1475   1479                   msg.append(", sql=\"").append(trimSqlForDisplay(mSql)).append("\"");
  1476   1480               }
  1477   1481               if (verbose && mBindArgs != null && mBindArgs.size() != 0) {
................................................................................
  1501   1505   
  1502   1506           private String getStatus() {
  1503   1507               if (!mFinished) {
  1504   1508                   return "running";
  1505   1509               }
  1506   1510               return mException != null ? "failed" : "succeeded";
  1507   1511           }
         1512  +
         1513  +        private String getTraceMethodName() {
         1514  +            String methodName = mKind + " " + mSql;
         1515  +            if (methodName.length() > MAX_TRACE_METHOD_NAME_LEN)
         1516  +                return methodName.substring(0, MAX_TRACE_METHOD_NAME_LEN);
         1517  +            return methodName;
         1518  +        }
  1508   1519   
  1509   1520           private String getFormattedStartTime() {
  1510         -            return sDateFormat.format(new Date(mStartTime));
         1521  +            // Note: SimpleDateFormat is not thread-safe, cannot be compile-time created, and is
         1522  +            //       relatively expensive to create during preloading. This method is only used
         1523  +            //       when dumping a connection, which is a rare (mainly error) case. So:
         1524  +            //       DO NOT CACHE.
         1525  +            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(mStartWallTime));
  1511   1526           }
  1512   1527       }
  1513   1528   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnectionPool.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23         -import org.sqlite.database.sqlite.CloseGuard;
           19  +import dalvik.system.CloseGuard;
    24     20   
    25         -import org.sqlite.database.sqlite.SQLiteDebug.DbStats;
           21  +import android.database.sqlite.SQLiteDebug.DbStats;
    26     22   import android.os.CancellationSignal;
    27     23   import android.os.OperationCanceledException;
    28     24   import android.os.SystemClock;
    29     25   import android.util.Log;
    30         -/* import android.util.PrefixPrinter; */
           26  +import android.util.PrefixPrinter;
    31     27   import android.util.Printer;
    32     28   
    33     29   import java.io.Closeable;
    34     30   import java.util.ArrayList;
    35     31   import java.util.Map;
    36     32   import java.util.WeakHashMap;
    37     33   import java.util.concurrent.atomic.AtomicBoolean;
................................................................................
   992    988           waiter.mSql = null;
   993    989           waiter.mAssignedConnection = null;
   994    990           waiter.mException = null;
   995    991           waiter.mNonce += 1;
   996    992           mConnectionWaiterPool = waiter;
   997    993       }
   998    994   
   999         -    public void enableLocalizedCollators() {
  1000         -      synchronized (mLock) {
  1001         -	if( !mAcquiredConnections.isEmpty() || mAvailablePrimaryConnection==null ) {
  1002         -	  throw new IllegalStateException(
  1003         -	      "Cannot enable localized collators while database is in use"
  1004         -	  );
  1005         -	}
  1006         -	mAvailablePrimaryConnection.enableLocalizedCollators();
  1007         -      }
  1008         -    }
  1009         -
  1010    995       /**
  1011    996        * Dumps debugging information about this connection pool.
  1012    997        *
  1013    998        * @param printer The printer to receive the dump, not null.
  1014    999        * @param verbose True to dump more verbose information.
  1015   1000        */
  1016   1001       public void dump(Printer printer, boolean verbose) {
  1017         -      /*
  1018         -        Printer indentedPrinter = Printer.create(printer, "    ");
         1002  +        Printer indentedPrinter = PrefixPrinter.create(printer, "    ");
  1019   1003           synchronized (mLock) {
  1020   1004               printer.println("Connection pool for " + mConfiguration.path + ":");
  1021   1005               printer.println("  Open: " + mIsOpen);
  1022   1006               printer.println("  Max connections: " + mMaxConnectionPoolSize);
  1023   1007   
  1024   1008               printer.println("  Available primary connection:");
  1025   1009               if (mAvailablePrimaryConnection != null) {
................................................................................
  1062   1046                               + ", priority=" + waiter.mPriority
  1063   1047                               + ", sql='" + waiter.mSql + "'");
  1064   1048                   }
  1065   1049               } else {
  1066   1050                   indentedPrinter.println("<none>");
  1067   1051               }
  1068   1052           }
  1069         -        */
  1070   1053       }
  1071   1054   
  1072   1055       @Override
  1073   1056       public String toString() {
  1074   1057           return "SQLiteConnectionPool: " + mConfiguration.path;
  1075   1058       }
  1076   1059   

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConstraintException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * An exception that indicates that an integrity constraint was violated.
    25     21    */
    26     22   public class SQLiteConstraintException extends SQLiteException {
    27     23       public SQLiteConstraintException() {}
    28     24   
    29     25       public SQLiteConstraintException(String error) {
    30     26           super(error);
    31     27       }
    32     28   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteCursor.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
    22         -
    23         -import org.sqlite.database.DatabaseUtils;
           17  +package android.database.sqlite;
    24     18   
    25     19   import android.database.AbstractWindowedCursor;
    26     20   import android.database.CursorWindow;
    27         -
           21  +import android.database.DatabaseUtils;
    28     22   import android.os.StrictMode;
    29     23   import android.util.Log;
    30     24   
    31     25   import java.util.HashMap;
    32     26   import java.util.Map;
    33     27   
    34     28   /**
................................................................................
    96     90        * @param editTable the name of the table used for this query
    97     91        * @param query the {@link SQLiteQuery} object associated with this cursor object.
    98     92        */
    99     93       public SQLiteCursor(SQLiteCursorDriver driver, String editTable, SQLiteQuery query) {
   100     94           if (query == null) {
   101     95               throw new IllegalArgumentException("query object cannot be null");
   102     96           }
   103         -        if (/* StrictMode.vmSqliteObjectLeaksEnabled() */ false ) {
           97  +        if (StrictMode.vmSqliteObjectLeaksEnabled()) {
   104     98               mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
   105     99           } else {
   106    100               mStackTrace = null;
   107    101           }
   108    102           mDriver = driver;
   109    103           mEditTable = editTable;
   110    104           mColumnNameMap = null;
................................................................................
   136    130       public int getCount() {
   137    131           if (mCount == NO_COUNT) {
   138    132               fillWindow(0);
   139    133           }
   140    134           return mCount;
   141    135       }
   142    136   
   143         -    /* 
   144         -    ** The AbstractWindowClass contains protected methods clearOrCreateWindow() and
   145         -    ** closeWindow(), which are used by the android.database.sqlite.* version of this
   146         -    ** class. But, since they are marked with "@hide", the following replacement 
   147         -    ** versions are required.
   148         -    */
   149         -    private void awc_clearOrCreateWindow(String name){
   150         -      CursorWindow win = getWindow();
   151         -      if( win==null ){
   152         -        win = new CursorWindow(name);
   153         -        setWindow(win);
   154         -      }else{
   155         -        win.clear();
   156         -      }
   157         -    }
   158         -    private void awc_closeWindow(){
   159         -      setWindow(null);
   160         -    }
   161         -
   162    137       private void fillWindow(int requiredPos) {
   163         -        awc_clearOrCreateWindow(getDatabase().getPath());
          138  +        clearOrCreateWindow(getDatabase().getPath());
   164    139   
   165    140           try {
   166    141               if (mCount == NO_COUNT) {
   167    142                   int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos, 0);
   168    143                   mCount = mQuery.fillWindow(mWindow, startPos, requiredPos, true);
   169    144                   mCursorWindowCapacity = mWindow.getNumRows();
   170    145                   if (Log.isLoggable(TAG, Log.DEBUG)) {
................................................................................
   176    151                   mQuery.fillWindow(mWindow, startPos, requiredPos, false);
   177    152               }
   178    153           } catch (RuntimeException ex) {
   179    154               // Close the cursor window if the query failed and therefore will
   180    155               // not produce any results.  This helps to avoid accidentally leaking
   181    156               // the cursor window if the client does not correctly handle exceptions
   182    157               // and fails to close the cursor.
   183         -            awc_closeWindow();
          158  +            closeWindow();
   184    159               throw ex;
   185    160           }
   186    161       }
   187    162   
   188    163       @Override
   189    164       public int getColumnIndex(String columnName) {
   190    165           // Create mColumnNameMap on demand
................................................................................
   280    255        * Release the native resources, if they haven't been released yet.
   281    256        */
   282    257       @Override
   283    258       protected void finalize() {
   284    259           try {
   285    260               // if the cursor hasn't been closed yet, close it first
   286    261               if (mWindow != null) {
   287         -                    /*
   288    262                   if (mStackTrace != null) {
   289    263                       String sql = mQuery.getSql();
   290    264                       int len = sql.length();
   291    265                       StrictMode.onSqliteObjectLeaked(
   292    266                           "Finalizing a Cursor that has not been deactivated or closed. " +
   293    267                           "database = " + mQuery.getDatabase().getLabel() +
   294    268                           ", table = " + mEditTable +
   295    269                           ", query = " + sql.substring(0, (len > 1000) ? 1000 : len),
   296    270                           mStackTrace);
   297    271                   }
   298         -                */
   299    272                   close();
   300    273               }
   301    274           } finally {
   302    275               super.finalize();
   303    276           }
   304    277       }
   305    278   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteCursorDriver.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import android.database.Cursor;
    24         -import org.sqlite.database.sqlite.SQLiteDatabase.CursorFactory;
           20  +import android.database.sqlite.SQLiteDatabase.CursorFactory;
    25     21   
    26     22   /**
    27     23    * A driver for SQLiteCursors that is used to create them and gets notified
    28     24    * by the cursors it creates on significant events in their lifetimes.
    29     25    */
    30     26   public interface SQLiteCursorDriver {
    31     27       /**

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteCustomFunction.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * Describes a custom SQL function.
    25     21    *
    26     22    * @hide
    27     23    */
    28     24   public final class SQLiteCustomFunction {

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatabase.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
           19  +import android.annotation.NonNull;
           20  +import android.annotation.Nullable;
    23     21   import android.content.ContentValues;
    24     22   import android.database.Cursor;
    25         -import org.sqlite.database.DatabaseErrorHandler;
    26         -import org.sqlite.database.DatabaseUtils;
    27         -import org.sqlite.database.DefaultDatabaseErrorHandler;
    28         -import org.sqlite.database.SQLException;
    29         -import org.sqlite.database.sqlite.SQLiteDebug.DbStats;
           23  +import android.database.DatabaseErrorHandler;
           24  +import android.database.DatabaseUtils;
           25  +import android.database.DefaultDatabaseErrorHandler;
           26  +import android.database.SQLException;
           27  +import android.database.sqlite.SQLiteDebug.DbStats;
    30     28   import android.os.CancellationSignal;
    31     29   import android.os.Looper;
    32     30   import android.os.OperationCanceledException;
    33     31   import android.text.TextUtils;
    34     32   import android.util.EventLog;
    35     33   import android.util.Log;
    36     34   import android.util.Pair;
    37     35   import android.util.Printer;
    38     36   
    39         -import org.sqlite.database.sqlite.CloseGuard;
           37  +import dalvik.system.CloseGuard;
    40     38   
    41     39   import java.io.File;
    42     40   import java.io.FileFilter;
    43     41   import java.util.ArrayList;
    44     42   import java.util.HashMap;
    45     43   import java.util.List;
    46     44   import java.util.Locale;
................................................................................
   738    736           deleted |= new File(file.getPath() + "-journal").delete();
   739    737           deleted |= new File(file.getPath() + "-shm").delete();
   740    738           deleted |= new File(file.getPath() + "-wal").delete();
   741    739   
   742    740           File dir = file.getParentFile();
   743    741           if (dir != null) {
   744    742               final String prefix = file.getName() + "-mj";
   745         -            final FileFilter filter = new FileFilter() {
          743  +            File[] files = dir.listFiles(new FileFilter() {
   746    744                   @Override
   747    745                   public boolean accept(File candidate) {
   748    746                       return candidate.getName().startsWith(prefix);
   749    747                   }
   750         -            };
   751         -            for (File masterJournal : dir.listFiles(filter)) {
   752         -                deleted |= masterJournal.delete();
          748  +            });
          749  +            if (files != null) {
          750  +                for (File masterJournal : files) {
          751  +                    deleted |= masterJournal.delete();
          752  +                }
   753    753               }
   754    754           }
   755    755           return deleted;
   756    756       }
   757    757   
   758    758       /**
   759    759        * Reopens the database in read-write mode.
................................................................................
  1367   1367       public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
  1368   1368               throws SQLException {
  1369   1369           return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
  1370   1370       }
  1371   1371   
  1372   1372       /**
  1373   1373        * Convenience method for replacing a row in the database.
         1374  +     * Inserts a new row if a row does not already exist.
  1374   1375        *
  1375   1376        * @param table the table in which to replace the row
  1376   1377        * @param nullColumnHack optional; may be <code>null</code>.
  1377   1378        *            SQL doesn't allow inserting a completely empty row without
  1378   1379        *            naming at least one column name.  If your provided <code>initialValues</code> is
  1379   1380        *            empty, no column names are known and an empty row can't be inserted.
  1380   1381        *            If not set to null, the <code>nullColumnHack</code> parameter
  1381   1382        *            provides the name of nullable column name to explicitly insert a NULL into
  1382   1383        *            in the case where your <code>initialValues</code> is empty.
  1383   1384        * @param initialValues this map contains the initial column values for
  1384         -     *   the row.
         1385  +     *   the row. The keys should be the column names and the values the column values.
  1385   1386        * @return the row ID of the newly inserted row, or -1 if an error occurred
  1386   1387        */
  1387   1388       public long replace(String table, String nullColumnHack, ContentValues initialValues) {
  1388   1389           try {
  1389   1390               return insertWithOnConflict(table, nullColumnHack, initialValues,
  1390   1391                       CONFLICT_REPLACE);
  1391   1392           } catch (SQLException e) {
................................................................................
  1392   1393               Log.e(TAG, "Error inserting " + initialValues, e);
  1393   1394               return -1;
  1394   1395           }
  1395   1396       }
  1396   1397   
  1397   1398       /**
  1398   1399        * Convenience method for replacing a row in the database.
         1400  +     * Inserts a new row if a row does not already exist.
  1399   1401        *
  1400   1402        * @param table the table in which to replace the row
  1401   1403        * @param nullColumnHack optional; may be <code>null</code>.
  1402   1404        *            SQL doesn't allow inserting a completely empty row without
  1403   1405        *            naming at least one column name.  If your provided <code>initialValues</code> is
  1404   1406        *            empty, no column names are known and an empty row can't be inserted.
  1405   1407        *            If not set to null, the <code>nullColumnHack</code> parameter
  1406   1408        *            provides the name of nullable column name to explicitly insert a NULL into
  1407   1409        *            in the case where your <code>initialValues</code> is empty.
  1408   1410        * @param initialValues this map contains the initial column values for
  1409         -     *   the row. The key
         1411  +     *   the row. The keys should be the column names and the values the column values.
  1410   1412        * @throws SQLException
  1411   1413        * @return the row ID of the newly inserted row, or -1 if an error occurred
  1412   1414        */
  1413   1415       public long replaceOrThrow(String table, String nullColumnHack,
  1414   1416               ContentValues initialValues) throws SQLException {
  1415   1417           return insertWithOnConflict(table, nullColumnHack, initialValues,
  1416   1418                   CONFLICT_REPLACE);
................................................................................
  1427   1429        *            If not set to null, the <code>nullColumnHack</code> parameter
  1428   1430        *            provides the name of nullable column name to explicitly insert a NULL into
  1429   1431        *            in the case where your <code>initialValues</code> is empty.
  1430   1432        * @param initialValues this map contains the initial column values for the
  1431   1433        *            row. The keys should be the column names and the values the
  1432   1434        *            column values
  1433   1435        * @param conflictAlgorithm for insert conflict resolver
  1434         -     * @return the row ID of the newly inserted row
  1435         -     * OR the primary key of the existing row if the input param 'conflictAlgorithm' =
  1436         -     * {@link #CONFLICT_IGNORE}
  1437         -     * OR -1 if any error
         1436  +     * @return the row ID of the newly inserted row OR <code>-1</code> if either the
         1437  +     *            input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
         1438  +     *            or an error occurred.
  1438   1439        */
  1439   1440       public long insertWithOnConflict(String table, String nullColumnHack,
  1440   1441               ContentValues initialValues, int conflictAlgorithm) {
  1441   1442           acquireReference();
  1442   1443           try {
  1443   1444               StringBuilder sql = new StringBuilder();
  1444   1445               sql.append("INSERT");
  1445   1446               sql.append(CONFLICT_VALUES[conflictAlgorithm]);
  1446   1447               sql.append(" INTO ");
  1447   1448               sql.append(table);
  1448   1449               sql.append('(');
  1449   1450   
  1450   1451               Object[] bindArgs = null;
  1451         -            int size = (initialValues != null && initialValues.size() > 0)
         1452  +            int size = (initialValues != null && !initialValues.isEmpty())
  1452   1453                       ? initialValues.size() : 0;
  1453   1454               if (size > 0) {
  1454   1455                   bindArgs = new Object[size];
  1455   1456                   int i = 0;
  1456   1457                   for (String colName : initialValues.keySet()) {
  1457   1458                       sql.append((i > 0) ? "," : "");
  1458   1459                       sql.append(colName);
................................................................................
  1536   1537        *            will be replaced by the values from whereArgs. The values
  1537   1538        *            will be bound as Strings.
  1538   1539        * @param conflictAlgorithm for update conflict resolver
  1539   1540        * @return the number of rows affected
  1540   1541        */
  1541   1542       public int updateWithOnConflict(String table, ContentValues values,
  1542   1543               String whereClause, String[] whereArgs, int conflictAlgorithm) {
  1543         -        if (values == null || values.size() == 0) {
         1544  +        if (values == null || values.isEmpty()) {
  1544   1545               throw new IllegalArgumentException("Empty values");
  1545   1546           }
  1546   1547   
  1547   1548           acquireReference();
  1548   1549           try {
  1549   1550               StringBuilder sql = new StringBuilder(120);
  1550   1551               sql.append("UPDATE ");
................................................................................
  1679   1680               } finally {
  1680   1681                   statement.close();
  1681   1682               }
  1682   1683           } finally {
  1683   1684               releaseReference();
  1684   1685           }
  1685   1686       }
         1687  +
         1688  +    /**
         1689  +     * Verifies that a SQL SELECT statement is valid by compiling it.
         1690  +     * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
         1691  +     *
         1692  +     * @param sql SQL to be validated
         1693  +     * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
         1694  +     * If the operation is canceled, then {@link OperationCanceledException} will be thrown
         1695  +     * when the query is executed.
         1696  +     * @throws SQLiteException if {@code sql} is invalid
         1697  +     */
         1698  +    public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) {
         1699  +        getThreadSession().prepare(sql,
         1700  +                getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
         1701  +    }
  1686   1702   
  1687   1703       /**
  1688   1704        * Returns true if the database is opened as read only.
  1689   1705        *
  1690   1706        * @return True if database is opened as read only.
  1691   1707        */
  1692   1708       public boolean isReadOnly() {
................................................................................
  1722   1738           }
  1723   1739       }
  1724   1740   
  1725   1741       /**
  1726   1742        * Returns true if the new version code is greater than the current database version.
  1727   1743        *
  1728   1744        * @param newVersion The new version code.
  1729         -     * @return True if the new version code is greater than the current database version. 
         1745  +     * @return True if the new version code is greater than the current database version.
  1730   1746        */
  1731   1747       public boolean needUpgrade(int newVersion) {
  1732   1748           return newVersion > getVersion();
  1733   1749       }
  1734   1750   
  1735   1751       /**
  1736   1752        * Gets the path to the database file.
................................................................................
  2190   2206        * This can be used to create a function that can be called from
  2191   2207        * sqlite3 database triggers.
  2192   2208        * @hide
  2193   2209        */
  2194   2210       public interface CustomFunction {
  2195   2211           public void callback(String[] args);
  2196   2212       }
  2197         -
  2198         -    public static boolean hasCodec() {
  2199         -      return SQLiteConnection.hasCodec();
  2200         -    }
  2201         -
  2202         -    public void enableLocalizedCollators() {
  2203         -      mConnectionPoolLocked.enableLocalizedCollators();
  2204         -    }
  2205   2213   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatabaseConfiguration.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import java.util.ArrayList;
    24     20   import java.util.Locale;
    25     21   import java.util.regex.Pattern;
    26     22   
    27     23   /**
    28     24    * Describes how to configure a database.
................................................................................
   157    153        * @return True if the database is in-memory.
   158    154        */
   159    155       public boolean isInMemoryDb() {
   160    156           return path.equalsIgnoreCase(MEMORY_DB_PATH);
   161    157       }
   162    158   
   163    159       private static String stripPathForLogs(String path) {
   164         -        /* Strip off all URI parameters. */
   165         -        int iIdx = path.indexOf('?');
   166         -        if( iIdx>=0 ){
   167         -            path = (String) path.subSequence(0, iIdx);
   168         -        }
   169         -
   170    160           if (path.indexOf('@') == -1) {
   171    161               return path;
   172    162           }
   173    163           return EMAIL_IN_DB_PATTERN.matcher(path).replaceAll("XX@YY");
   174    164       }
   175    165   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatabaseCorruptException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * An exception that indicates that the SQLite database file is corrupt.
    25     21    */
    26     22   public class SQLiteDatabaseCorruptException extends SQLiteException {
    27     23       public SQLiteDatabaseCorruptException() {}
    28     24   
    29     25       public SQLiteDatabaseCorruptException(String error) {
    30     26           super(error);
    31     27       }
    32     28   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatabaseLockedException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * Thrown if  the database engine was unable to acquire the
    25     21    * database locks it needs to do its job.  If the statement is a [COMMIT]
    26     22    * or occurs outside of an explicit transaction, then you can retry the
    27     23    * statement.  If the statement is not a [COMMIT] and occurs within a
    28     24    * explicit transaction then you should rollback the transaction before

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatatypeMismatchException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   public class SQLiteDatatypeMismatchException extends SQLiteException {
    24     20       public SQLiteDatatypeMismatchException() {}
    25     21   
    26     22       public SQLiteDatatypeMismatchException(String error) {
    27     23           super(error);
    28     24       }
    29     25   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDebug.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import java.util.ArrayList;
    24     20   
    25     21   import android.os.Build;
    26         -/* import android.os.SystemProperties; */
           22  +import android.os.SystemProperties;
    27     23   import android.util.Log;
    28     24   import android.util.Printer;
    29     25   
    30     26   /**
    31     27    * Provides debugging info about all SQLite databases running in the current process.
    32     28    *
    33     29    * {@hide}
................................................................................
    60     56       public static final boolean DEBUG_SQL_TIME =
    61     57               Log.isLoggable("SQLiteTime", Log.VERBOSE);
    62     58   
    63     59       /**
    64     60        * True to enable database performance testing instrumentation.
    65     61        * @hide
    66     62        */
    67         -    public static final boolean DEBUG_LOG_SLOW_QUERIES = false;
           63  +    public static final boolean DEBUG_LOG_SLOW_QUERIES = Build.IS_DEBUGGABLE;
    68     64   
    69     65       private SQLiteDebug() {
    70     66       }
    71     67   
    72     68       /**
    73     69        * Determines whether a query should be logged.
    74     70        *
................................................................................
    79     75        *
    80     76        * This value can be changed dynamically while the system is running.
    81     77        * For example, "adb shell setprop db.log.slow_query_threshold 200" will
    82     78        * log all queries that take 200ms or longer to run.
    83     79        * @hide
    84     80        */
    85     81       public static final boolean shouldLogSlowQuery(long elapsedTimeMillis) {
    86         -        int slowQueryMillis = 10000;
           82  +        int slowQueryMillis = SystemProperties.getInt("db.log.slow_query_threshold", -1);
    87     83           return slowQueryMillis >= 0 && elapsedTimeMillis >= slowQueryMillis;
    88     84       }
    89     85   
    90     86       /**
    91     87        * Contains statistics about the active pagers in the current process.
    92     88        *
    93     89        * @see #nativeGetPagerStats(PagerStats)

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDirectCursorDriver.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import android.database.Cursor;
    24         -import org.sqlite.database.sqlite.SQLiteDatabase.CursorFactory;
           20  +import android.database.sqlite.SQLiteDatabase.CursorFactory;
    25     21   import android.os.CancellationSignal;
    26     22   
    27     23   /**
    28     24    * A cursor driver that uses the given query directly.
    29     25    * 
    30     26    * @hide
    31     27    */

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDiskIOException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * An exception that indicates that an IO error occured while accessing the 
    25     21    * SQLite database file.
    26     22    */
    27     23   public class SQLiteDiskIOException extends SQLiteException {
    28     24       public SQLiteDiskIOException() {}
    29     25   
    30     26       public SQLiteDiskIOException(String error) {
    31     27           super(error);
    32     28       }
    33     29   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDoneException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * An exception that indicates that the SQLite program is done.
    25     21    * Thrown when an operation that expects a row (such as {@link
    26     22    * SQLiteStatement#simpleQueryForString} or {@link
    27     23    * SQLiteStatement#simpleQueryForLong}) does not get one.
    28     24    */

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
           16  +
           17  +package android.database.sqlite;
    20     18   
    21         -package org.sqlite.database.sqlite;
    22         -
    23         -import org.sqlite.database.SQLException;
           19  +import android.database.SQLException;
    24     20   
    25     21   /**
    26     22    * A SQLite exception that indicates there was an error with SQL parsing or execution.
    27     23    */
    28     24   public class SQLiteException extends SQLException {
    29     25       public SQLiteException() {
    30     26       }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteFullException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * An exception that indicates that the SQLite database is full.
    25     21    */
    26     22   public class SQLiteFullException extends SQLiteException {
    27     23       public SQLiteFullException() {}
    28     24   
    29     25       public SQLiteFullException(String error) {
    30     26           super(error);
    31     27       }
    32     28   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteGlobal.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import android.content.res.Resources;
    24     20   import android.os.StatFs;
    25         -/* import android.os.SystemProperties; */
           21  +import android.os.SystemProperties;
    26     22   
    27     23   /**
    28     24    * Provides access to SQLite functions that affect all database connection,
    29     25    * such as memory management.
    30     26    *
    31     27    * The native code associated with SQLiteGlobal is also sets global configuration options
    32     28    * using sqlite3_config() then calls sqlite3_initialize() to ensure that the SQLite
................................................................................
    61     57   
    62     58       /**
    63     59        * Gets the default page size to use when creating a database.
    64     60        */
    65     61       public static int getDefaultPageSize() {
    66     62           synchronized (sLock) {
    67     63               if (sDefaultPageSize == 0) {
           64  +                // If there is an issue accessing /data, something is so seriously
           65  +                // wrong that we just let the IllegalArgumentException propagate.
    68     66                   sDefaultPageSize = new StatFs("/data").getBlockSize();
    69     67               }
    70         -            return 1024;
           68  +            return SystemProperties.getInt("debug.sqlite.pagesize", sDefaultPageSize);
    71     69           }
    72     70       }
    73     71   
    74     72       /**
    75     73        * Gets the default journal mode when WAL is not in use.
    76     74        */
    77     75       public static String getDefaultJournalMode() {
    78         -        return "delete";
           76  +        return SystemProperties.get("debug.sqlite.journalmode",
           77  +                Resources.getSystem().getString(
           78  +                com.android.internal.R.string.db_default_journal_mode));
    79     79       }
    80     80   
    81     81       /**
    82     82        * Gets the journal size limit in bytes.
    83     83        */
    84     84       public static int getJournalSizeLimit() {
    85         -        return 10000;
           85  +        return SystemProperties.getInt("debug.sqlite.journalsizelimit",
           86  +                Resources.getSystem().getInteger(
           87  +                com.android.internal.R.integer.db_journal_size_limit));
    86     88       }
    87     89   
    88     90       /**
    89     91        * Gets the default database synchronization mode when WAL is not in use.
    90     92        */
    91     93       public static String getDefaultSyncMode() {
    92         -        return "normal";
           94  +        return SystemProperties.get("debug.sqlite.syncmode",
           95  +                Resources.getSystem().getString(
           96  +                com.android.internal.R.string.db_default_sync_mode));
    93     97       }
    94     98   
    95     99       /**
    96    100        * Gets the database synchronization mode when in WAL mode.
    97    101        */
    98    102       public static String getWALSyncMode() {
    99         -        return "normal";
          103  +        return SystemProperties.get("debug.sqlite.wal.syncmode",
          104  +                Resources.getSystem().getString(
          105  +                com.android.internal.R.string.db_wal_sync_mode));
   100    106       }
   101    107   
   102    108       /**
   103    109        * Gets the WAL auto-checkpoint integer in database pages.
   104    110        */
   105    111       public static int getWALAutoCheckpoint() {
   106         -        int value = 1000;
          112  +        int value = SystemProperties.getInt("debug.sqlite.wal.autocheckpoint",
          113  +                Resources.getSystem().getInteger(
          114  +                com.android.internal.R.integer.db_wal_autocheckpoint));
   107    115           return Math.max(1, value);
   108    116       }
   109    117   
   110    118       /**
   111    119        * Gets the connection pool size when in WAL mode.
   112    120        */
   113    121       public static int getWALConnectionPoolSize() {
   114         -        int value = 10;
          122  +        int value = SystemProperties.getInt("debug.sqlite.wal.poolsize",
          123  +                Resources.getSystem().getInteger(
          124  +                com.android.internal.R.integer.db_connection_pool_size));
   115    125           return Math.max(2, value);
   116    126       }
   117    127   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteMisuseException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * This error can occur if the application creates a SQLiteStatement object and allows multiple
    25     21    * threads in the application use it at the same time.
    26     22    * Sqlite returns this error if bind and execute methods on this object occur at the same time
    27     23    * from multiple threads, like so:
    28     24    *     thread # 1: in execute() method of the SQLiteStatement object

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteOpenHelper.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import android.content.Context;
    24         -import org.sqlite.database.DatabaseErrorHandler;
    25         -import org.sqlite.database.DefaultDatabaseErrorHandler;
    26         -import org.sqlite.database.sqlite.SQLiteDatabase.CursorFactory;
           20  +import android.database.DatabaseErrorHandler;
           21  +import android.database.sqlite.SQLiteDatabase.CursorFactory;
    27     22   import android.util.Log;
           23  +import java.io.File;
    28     24   
    29     25   /**
    30     26    * A helper class to manage database creation and version management.
    31     27    *
    32     28    * <p>You create a subclass implementing {@link #onCreate}, {@link #onUpgrade} and
    33     29    * optionally {@link #onOpen}, and this class takes care of opening the database
    34     30    * if it exists, creating it if it does not, and upgrading it as necessary.
................................................................................
    55     51       // wanted getWritableDatabase.
    56     52       private static final boolean DEBUG_STRICT_READONLY = false;
    57     53   
    58     54       private final Context mContext;
    59     55       private final String mName;
    60     56       private final CursorFactory mFactory;
    61     57       private final int mNewVersion;
           58  +    private final int mMinimumSupportedVersion;
    62     59   
    63     60       private SQLiteDatabase mDatabase;
    64     61       private boolean mIsInitializing;
    65     62       private boolean mEnableWriteAheadLogging;
    66     63       private final DatabaseErrorHandler mErrorHandler;
    67     64   
    68     65       /**
................................................................................
    97     94        *     {@link #onUpgrade} will be used to upgrade the database; if the database is
    98     95        *     newer, {@link #onDowngrade} will be used to downgrade the database
    99     96        * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
   100     97        * corruption, or null to use the default error handler.
   101     98        */
   102     99       public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
   103    100               DatabaseErrorHandler errorHandler) {
          101  +        this(context, name, factory, version, 0, errorHandler);
          102  +    }
          103  +
          104  +    /**
          105  +     * Same as {@link #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)}
          106  +     * but also accepts an integer minimumSupportedVersion as a convenience for upgrading very old
          107  +     * versions of this database that are no longer supported. If a database with older version that
          108  +     * minimumSupportedVersion is found, it is simply deleted and a new database is created with the
          109  +     * given name and version
          110  +     *
          111  +     * @param context to use to open or create the database
          112  +     * @param name the name of the database file, null for a temporary in-memory database
          113  +     * @param factory to use for creating cursor objects, null for default
          114  +     * @param version the required version of the database
          115  +     * @param minimumSupportedVersion the minimum version that is supported to be upgraded to
          116  +     *            {@code version} via {@link #onUpgrade}. If the current database version is lower
          117  +     *            than this, database is simply deleted and recreated with the version passed in
          118  +     *            {@code version}. {@link #onBeforeDelete} is called before deleting the database
          119  +     *            when this happens. This is 0 by default.
          120  +     * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
          121  +     *            corruption, or null to use the default error handler.
          122  +     * @see #onBeforeDelete(SQLiteDatabase)
          123  +     * @see #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)
          124  +     * @see #onUpgrade(SQLiteDatabase, int, int)
          125  +     * @hide
          126  +     */
          127  +    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
          128  +            int minimumSupportedVersion, DatabaseErrorHandler errorHandler) {
   104    129           if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
   105    130   
   106    131           mContext = context;
   107    132           mName = name;
   108    133           mFactory = factory;
   109    134           mNewVersion = version;
   110    135           mErrorHandler = errorHandler;
          136  +        mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
   111    137       }
   112    138   
   113    139       /**
   114    140        * Return the name of the SQLite database being opened, as given to
   115    141        * the constructor.
   116    142        */
   117    143       public String getDatabaseName() {
................................................................................
   221    247               } else {
   222    248                   try {
   223    249                       if (DEBUG_STRICT_READONLY && !writable) {
   224    250                           final String path = mContext.getDatabasePath(mName).getPath();
   225    251                           db = SQLiteDatabase.openDatabase(path, mFactory,
   226    252                                   SQLiteDatabase.OPEN_READONLY, mErrorHandler);
   227    253                       } else {
   228         -                        db = SQLiteDatabase.openOrCreateDatabase(
   229         -                                mName, mFactory, mErrorHandler
   230         -                        );
          254  +                        db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
          255  +                                Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
          256  +                                mFactory, mErrorHandler);
   231    257                       }
   232    258                   } catch (SQLiteException ex) {
   233    259                       if (writable) {
   234    260                           throw ex;
   235    261                       }
   236    262                       Log.e(TAG, "Couldn't open " + mName
   237    263                               + " for writing (will try read-only):", ex);
................................................................................
   246    272               final int version = db.getVersion();
   247    273               if (version != mNewVersion) {
   248    274                   if (db.isReadOnly()) {
   249    275                       throw new SQLiteException("Can't upgrade read-only database from version " +
   250    276                               db.getVersion() + " to " + mNewVersion + ": " + mName);
   251    277                   }
   252    278   
   253         -                db.beginTransaction();
   254         -                try {
   255         -                    if (version == 0) {
   256         -                        onCreate(db);
          279  +                if (version > 0 && version < mMinimumSupportedVersion) {
          280  +                    File databaseFile = new File(db.getPath());
          281  +                    onBeforeDelete(db);
          282  +                    db.close();
          283  +                    if (SQLiteDatabase.deleteDatabase(databaseFile)) {
          284  +                        mIsInitializing = false;
          285  +                        return getDatabaseLocked(writable);
   257    286                       } else {
   258         -                        if (version > mNewVersion) {
   259         -                            onDowngrade(db, version, mNewVersion);
   260         -                        } else {
   261         -                            onUpgrade(db, version, mNewVersion);
   262         -                        }
          287  +                        throw new IllegalStateException("Unable to delete obsolete database "
          288  +                                + mName + " with version " + version);
   263    289                       }
   264         -                    db.setVersion(mNewVersion);
   265         -                    db.setTransactionSuccessful();
   266         -                } finally {
   267         -                    db.endTransaction();
          290  +                } else {
          291  +                    db.beginTransaction();
          292  +                    try {
          293  +                        if (version == 0) {
          294  +                            onCreate(db);
          295  +                        } else {
          296  +                            if (version > mNewVersion) {
          297  +                                onDowngrade(db, version, mNewVersion);
          298  +                            } else {
          299  +                                onUpgrade(db, version, mNewVersion);
          300  +                            }
          301  +                        }
          302  +                        db.setVersion(mNewVersion);
          303  +                        db.setTransactionSuccessful();
          304  +                    } finally {
          305  +                        db.endTransaction();
          306  +                    }
   268    307                   }
   269    308               }
   270    309   
   271    310               onOpen(db);
   272    311   
   273    312               if (db.isReadOnly()) {
   274    313                   Log.w(TAG, "Opened " + mName + " in read-only mode");
................................................................................
   293    332           if (mDatabase != null && mDatabase.isOpen()) {
   294    333               mDatabase.close();
   295    334               mDatabase = null;
   296    335           }
   297    336       }
   298    337   
   299    338       /**
   300         -     * Called when the database connection is being configured, to enable features
   301         -     * such as write-ahead logging or foreign key support.
          339  +     * Called when the database connection is being configured, to enable features such as
          340  +     * write-ahead logging or foreign key support.
          341  +     * <p>
          342  +     * This method is called before {@link #onCreate}, {@link #onUpgrade}, {@link #onDowngrade}, or
          343  +     * {@link #onOpen} are called. It should not modify the database except to configure the
          344  +     * database connection as required.
          345  +     * </p>
   302    346        * <p>
   303         -     * This method is called before {@link #onCreate}, {@link #onUpgrade},
   304         -     * {@link #onDowngrade}, or {@link #onOpen} are called.  It should not modify
   305         -     * the database except to configure the database connection as required.
   306         -     * </p><p>
   307         -     * This method should only call methods that configure the parameters of the
   308         -     * database connection, such as {@link SQLiteDatabase#enableWriteAheadLogging}
   309         -     * {@link SQLiteDatabase#setForeignKeyConstraintsEnabled},
   310         -     * {@link SQLiteDatabase#setLocale}, {@link SQLiteDatabase#setMaximumSize},
   311         -     * or executing PRAGMA statements.
          347  +     * This method should only call methods that configure the parameters of the database
          348  +     * connection, such as {@link SQLiteDatabase#enableWriteAheadLogging}
          349  +     * {@link SQLiteDatabase#setForeignKeyConstraintsEnabled}, {@link SQLiteDatabase#setLocale},
          350  +     * {@link SQLiteDatabase#setMaximumSize}, or executing PRAGMA statements.
   312    351        * </p>
   313    352        *
   314    353        * @param db The database.
   315    354        */
   316    355       public void onConfigure(SQLiteDatabase db) {}
          356  +
          357  +    /**
          358  +     * Called before the database is deleted when the version returned by
          359  +     * {@link SQLiteDatabase#getVersion()} is lower than the minimum supported version passed (if at
          360  +     * all) while creating this helper. After the database is deleted, a fresh database with the
          361  +     * given version is created. This will be followed by {@link #onConfigure(SQLiteDatabase)} and
          362  +     * {@link #onCreate(SQLiteDatabase)} being called with a new SQLiteDatabase object
          363  +     *
          364  +     * @param db the database opened with this helper
          365  +     * @see #SQLiteOpenHelper(Context, String, CursorFactory, int, int, DatabaseErrorHandler)
          366  +     * @hide
          367  +     */
          368  +    public void onBeforeDelete(SQLiteDatabase db) {
          369  +    }
   317    370   
   318    371       /**
   319    372        * Called when the database is created for the first time. This is where the
   320    373        * creation of tables and the initial population of the tables should happen.
   321    374        *
   322    375        * @param db The database.
   323    376        */

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteOutOfMemoryException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   public class SQLiteOutOfMemoryException extends SQLiteException {
    24     20       public SQLiteOutOfMemoryException() {}
    25     21   
    26     22       public SQLiteOutOfMemoryException(String error) {
    27     23           super(error);
    28     24       }
    29     25   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteProgram.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import android.database.DatabaseUtils;
    24     20   import android.os.CancellationSignal;
    25     21   
    26     22   import java.util.Arrays;
    27     23   
    28     24   /**

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteQuery.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import android.database.CursorWindow;
    24     20   import android.os.CancellationSignal;
    25     21   import android.os.OperationCanceledException;
    26     22   import android.util.Log;
    27     23   
    28     24   /**

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteQueryBuilder.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import android.database.Cursor;
    24     20   import android.database.DatabaseUtils;
    25     21   import android.os.CancellationSignal;
    26     22   import android.os.OperationCanceledException;
    27     23   import android.provider.BaseColumns;
    28     24   import android.text.TextUtils;
................................................................................
   386    382               // The idea is to ensure that the selection clause is a valid SQL expression
   387    383               // by compiling it twice: once wrapped in parentheses and once as
   388    384               // originally specified. An attacker cannot create an expression that
   389    385               // would escape the SQL expression while maintaining balanced parentheses
   390    386               // in both the wrapped and original forms.
   391    387               String sqlForValidation = buildQuery(projectionIn, "(" + selection + ")", groupBy,
   392    388                       having, sortOrder, limit);
   393         -            validateQuerySql(db, sqlForValidation,
   394         -                    cancellationSignal); // will throw if query is invalid
          389  +            db.validateSql(sqlForValidation, cancellationSignal); // will throw if query is invalid
   395    390           }
   396    391   
   397    392           String sql = buildQuery(
   398    393                   projectionIn, selection, groupBy, having,
   399    394                   sortOrder, limit);
   400    395   
   401    396           if (Log.isLoggable(TAG, Log.DEBUG)) {
................................................................................
   403    398           }
   404    399           return db.rawQueryWithFactory(
   405    400                   mFactory, sql, selectionArgs,
   406    401                   SQLiteDatabase.findEditTable(mTables),
   407    402                   cancellationSignal); // will throw if query is invalid
   408    403       }
   409    404   
   410         -    /**
   411         -     * Verifies that a SQL SELECT statement is valid by compiling it.
   412         -     * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
   413         -     */
   414         -    private void validateQuerySql(SQLiteDatabase db, String sql,
   415         -            CancellationSignal cancellationSignal) {
   416         -        db.getThreadSession().prepare(sql,
   417         -                db.getThreadDefaultConnectionFlags(true /*readOnly*/), cancellationSignal, null);
   418         -    }
   419         -
   420    405       /**
   421    406        * Construct a SELECT statement suitable for use in a group of
   422    407        * SELECT statements that will be joined through UNION operators
   423    408        * in buildUnionQuery.
   424    409        *
   425    410        * @param projectionIn A list of which columns to return. Passing
   426    411        *    null will return all columns, which is discouraged to

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteReadOnlyDatabaseException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   public class SQLiteReadOnlyDatabaseException extends SQLiteException {
    24     20       public SQLiteReadOnlyDatabaseException() {}
    25     21   
    26     22       public SQLiteReadOnlyDatabaseException(String error) {
    27     23           super(error);
    28     24       }
    29     25   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteSession.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import android.database.CursorWindow;
    24     20   import android.database.DatabaseUtils;
    25     21   import android.os.CancellationSignal;
    26     22   import android.os.OperationCanceledException;
    27     23   import android.os.ParcelFileDescriptor;
    28     24   

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteStatement.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   import android.os.ParcelFileDescriptor;
    24     20   
    25     21   /**
    26     22    * Represents a statement that can be executed against a database.  The statement
    27     23    * cannot return multiple rows or columns, but single value (1 x 1) result sets
    28     24    * are supported.
................................................................................
    35     31           super(db, sql, bindArgs, null);
    36     32       }
    37     33   
    38     34       /**
    39     35        * Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example
    40     36        * CREATE / DROP table, view, trigger, index etc.
    41     37        *
    42         -     * @throws org.sqlite.database.SQLException If the SQL string is invalid for
           38  +     * @throws android.database.SQLException If the SQL string is invalid for
    43     39        *         some reason
    44     40        */
    45     41       public void execute() {
    46     42           acquireReference();
    47     43           try {
    48     44               getSession().execute(getSql(), getBindArgs(), getConnectionFlags(), null);
    49     45           } catch (SQLiteDatabaseCorruptException ex) {
................................................................................
    55     51       }
    56     52   
    57     53       /**
    58     54        * Execute this SQL statement, if the the number of rows affected by execution of this SQL
    59     55        * statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements.
    60     56        *
    61     57        * @return the number of rows affected by this SQL statement execution.
    62         -     * @throws org.sqlite.database.SQLException If the SQL string is invalid for
           58  +     * @throws android.database.SQLException If the SQL string is invalid for
    63     59        *         some reason
    64     60        */
    65     61       public int executeUpdateDelete() {
    66     62           acquireReference();
    67     63           try {
    68     64               return getSession().executeForChangedRowCount(
    69     65                       getSql(), getBindArgs(), getConnectionFlags(), null);
................................................................................
    77     73   
    78     74       /**
    79     75        * Execute this SQL statement and return the ID of the row inserted due to this call.
    80     76        * The SQL statement should be an INSERT for this to be a useful call.
    81     77        *
    82     78        * @return the row ID of the last row inserted, if this insert is successful. -1 otherwise.
    83     79        *
    84         -     * @throws org.sqlite.database.SQLException If the SQL string is invalid for
           80  +     * @throws android.database.SQLException If the SQL string is invalid for
    85     81        *         some reason
    86     82        */
    87     83       public long executeInsert() {
    88     84           acquireReference();
    89     85           try {
    90     86               return getSession().executeForLastInsertedRowId(
    91     87                       getSql(), getBindArgs(), getConnectionFlags(), null);
................................................................................
    99     95   
   100     96       /**
   101     97        * Execute a statement that returns a 1 by 1 table with a numeric value.
   102     98        * For example, SELECT COUNT(*) FROM table;
   103     99        *
   104    100        * @return The result of the query.
   105    101        *
   106         -     * @throws org.sqlite.database.sqlite.SQLiteDoneException if the query returns zero rows
          102  +     * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
   107    103        */
   108    104       public long simpleQueryForLong() {
   109    105           acquireReference();
   110    106           try {
   111    107               return getSession().executeForLong(
   112    108                       getSql(), getBindArgs(), getConnectionFlags(), null);
   113    109           } catch (SQLiteDatabaseCorruptException ex) {
................................................................................
   120    116   
   121    117       /**
   122    118        * Execute a statement that returns a 1 by 1 table with a text value.
   123    119        * For example, SELECT COUNT(*) FROM table;
   124    120        *
   125    121        * @return The result of the query.
   126    122        *
   127         -     * @throws org.sqlite.database.sqlite.SQLiteDoneException if the query returns zero rows
          123  +     * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
   128    124        */
   129    125       public String simpleQueryForString() {
   130    126           acquireReference();
   131    127           try {
   132    128               return getSession().executeForString(
   133    129                       getSql(), getBindArgs(), getConnectionFlags(), null);
   134    130           } catch (SQLiteDatabaseCorruptException ex) {
................................................................................
   141    137   
   142    138       /**
   143    139        * Executes a statement that returns a 1 by 1 table with a blob value.
   144    140        *
   145    141        * @return A read-only file descriptor for a copy of the blob value, or {@code null}
   146    142        *         if the value is null or could not be read for some reason.
   147    143        *
   148         -     * @throws org.sqlite.database.sqlite.SQLiteDoneException if the query returns zero rows
          144  +     * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
   149    145        */
   150    146       public ParcelFileDescriptor simpleQueryForBlobFileDescriptor() {
   151    147           acquireReference();
   152    148           try {
   153    149               return getSession().executeForBlobFileDescriptor(
   154    150                       getSql(), getBindArgs(), getConnectionFlags(), null);
   155    151           } catch (SQLiteDatabaseCorruptException ex) {

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteStatementInfo.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * Describes a SQLite statement.
    25     21    *
    26     22    * @hide
    27     23    */
    28     24   public final class SQLiteStatementInfo {

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteTableLockedException.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   public class SQLiteTableLockedException extends SQLiteException {
    24     20       public SQLiteTableLockedException() {}
    25     21   
    26     22       public SQLiteTableLockedException(String error) {
    27     23           super(error);
    28     24       }
    29     25   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteTransactionListener.java.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21         -package org.sqlite.database.sqlite;
           17  +package android.database.sqlite;
    22     18   
    23     19   /**
    24     20    * A listener for transaction events.
    25     21    */
    26     22   public interface SQLiteTransactionListener {
    27     23       /**
    28     24        * Called immediately after the transaction begins.

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SqliteWrapper.java.

    10     10    *
    11     11    * Unless required by applicable law or agreed to in writing, software
    12     12    * distributed under the License is distributed on an "AS IS" BASIS,
    13     13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14     14    * See the License for the specific language governing permissions and
    15     15    * limitations under the License.
    16     16    */
    17         -/*
    18         -** Modified to support SQLite extensions by the SQLite developers: 
    19         -** sqlite-dev@sqlite.org.
    20         -*/
    21     17   
    22         -package org.sqlite.database.sqlite;
           18  +package android.database.sqlite;
    23     19   
    24     20   import android.content.ContentResolver;
    25     21   import android.content.ContentValues;
    26     22   import android.content.Context;
    27     23   import android.database.Cursor;
    28         -import org.sqlite.database.sqlite.SQLiteException;
           24  +import android.database.sqlite.SQLiteException;
    29     25   import android.net.Uri;
    30     26   import android.util.Log;
    31     27   import android.widget.Toast;
    32     28   
    33     29   /**
    34     30    * @hide
    35     31    */
................................................................................
    46     42       // FIXME: need to optimize this method.
    47     43       private static boolean isLowMemory(SQLiteException e) {
    48     44           return e.getMessage().equals(SQLITE_EXCEPTION_DETAIL_MESSAGE);
    49     45       }
    50     46   
    51     47       public static void checkSQLiteException(Context context, SQLiteException e) {
    52     48           if (isLowMemory(e)) {
    53         -            Toast.makeText(context, "low memory", Toast.LENGTH_SHORT).show();
           49  +            Toast.makeText(context, com.android.internal.R.string.low_memory,
           50  +                    Toast.LENGTH_SHORT).show();
    54     51           } else {
    55     52               throw e;
    56     53           }
    57     54       }
    58     55   
    59     56       public static Cursor query(Context context, ContentResolver resolver, Uri uri,
    60     57               String[] projection, String selection, String[] selectionArgs, String sortOrder) {

Changes to sqlite3/src/main/jni/sqlite/android_database_SQLiteCommon.cpp.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21     17   #include "android_database_SQLiteCommon.h"
           18  +
           19  +#include <utils/String8.h>
    22     20   
    23     21   namespace android {
    24     22   
    25     23   /* throw a SQLiteException with a message appropriate for the error in handle */
    26     24   void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle) {
    27     25       throw_sqlite3_exception(env, handle, NULL);
    28     26   }
................................................................................
    61     59      user message
    62     60    */
    63     61   void throw_sqlite3_exception(JNIEnv* env, int errcode,
    64     62                                const char* sqlite3Message, const char* message) {
    65     63       const char* exceptionClass;
    66     64       switch (errcode & 0xff) { /* mask off extended error code */
    67     65           case SQLITE_IOERR:
    68         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteDiskIOException";
           66  +            exceptionClass = "android/database/sqlite/SQLiteDiskIOException";
    69     67               break;
    70     68           case SQLITE_CORRUPT:
    71     69           case SQLITE_NOTADB: // treat "unsupported file format" error as corruption also
    72         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteDatabaseCorruptException";
           70  +            exceptionClass = "android/database/sqlite/SQLiteDatabaseCorruptException";
    73     71               break;
    74     72           case SQLITE_CONSTRAINT:
    75         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteConstraintException";
           73  +            exceptionClass = "android/database/sqlite/SQLiteConstraintException";
    76     74               break;
    77     75           case SQLITE_ABORT:
    78         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteAbortException";
           76  +            exceptionClass = "android/database/sqlite/SQLiteAbortException";
    79     77               break;
    80     78           case SQLITE_DONE:
    81         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteDoneException";
           79  +            exceptionClass = "android/database/sqlite/SQLiteDoneException";
    82     80               sqlite3Message = NULL; // SQLite error message is irrelevant in this case
    83     81               break;
    84     82           case SQLITE_FULL:
    85         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteFullException";
           83  +            exceptionClass = "android/database/sqlite/SQLiteFullException";
    86     84               break;
    87     85           case SQLITE_MISUSE:
    88         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteMisuseException";
           86  +            exceptionClass = "android/database/sqlite/SQLiteMisuseException";
    89     87               break;
    90     88           case SQLITE_PERM:
    91         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteAccessPermException";
           89  +            exceptionClass = "android/database/sqlite/SQLiteAccessPermException";
    92     90               break;
    93     91           case SQLITE_BUSY:
    94         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteDatabaseLockedException";
           92  +            exceptionClass = "android/database/sqlite/SQLiteDatabaseLockedException";
    95     93               break;
    96     94           case SQLITE_LOCKED:
    97         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteTableLockedException";
           95  +            exceptionClass = "android/database/sqlite/SQLiteTableLockedException";
    98     96               break;
    99     97           case SQLITE_READONLY:
   100         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteReadOnlyDatabaseException";
           98  +            exceptionClass = "android/database/sqlite/SQLiteReadOnlyDatabaseException";
   101     99               break;
   102    100           case SQLITE_CANTOPEN:
   103         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteCantOpenDatabaseException";
          101  +            exceptionClass = "android/database/sqlite/SQLiteCantOpenDatabaseException";
   104    102               break;
   105    103           case SQLITE_TOOBIG:
   106         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteBlobTooBigException";
          104  +            exceptionClass = "android/database/sqlite/SQLiteBlobTooBigException";
   107    105               break;
   108    106           case SQLITE_RANGE:
   109         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException";
          107  +            exceptionClass = "android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException";
   110    108               break;
   111    109           case SQLITE_NOMEM:
   112         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteOutOfMemoryException";
          110  +            exceptionClass = "android/database/sqlite/SQLiteOutOfMemoryException";
   113    111               break;
   114    112           case SQLITE_MISMATCH:
   115         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteDatatypeMismatchException";
          113  +            exceptionClass = "android/database/sqlite/SQLiteDatatypeMismatchException";
   116    114               break;
   117    115           case SQLITE_INTERRUPT:
   118    116               exceptionClass = "android/os/OperationCanceledException";
   119    117               break;
   120    118           default:
   121         -            exceptionClass = "org/sqlite/database/sqlite/SQLiteException";
          119  +            exceptionClass = "android/database/sqlite/SQLiteException";
   122    120               break;
   123    121       }
   124    122   
   125    123       if (sqlite3Message) {
   126         -        char *zFullmsg = sqlite3_mprintf(
   127         -            "%s (code %d)%s%s", sqlite3Message, errcode, 
   128         -            (message ? ": " : ""), (message ? message : "")
   129         -        );
   130         -        jniThrowException(env, exceptionClass, zFullmsg);
   131         -        sqlite3_free(zFullmsg);
          124  +        String8 fullMessage;
          125  +        fullMessage.append(sqlite3Message);
          126  +        fullMessage.appendFormat(" (code %d)", errcode); // print extended error code
          127  +        if (message) {
          128  +            fullMessage.append(": ");
          129  +            fullMessage.append(message);
          130  +        }
          131  +        jniThrowException(env, exceptionClass, fullMessage.string());
   132    132       } else {
   133    133           jniThrowException(env, exceptionClass, message);
   134    134       }
   135    135   }
   136    136   
   137    137   
   138    138   } // namespace android

Changes to sqlite3/src/main/jni/sqlite/android_database_SQLiteCommon.h.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21     17   #ifndef _ANDROID_DATABASE_SQLITE_COMMON_H
    22     18   #define _ANDROID_DATABASE_SQLITE_COMMON_H
    23     19   
    24     20   #include <jni.h>
    25         -#include <JNIHelp.h>
           21  +#include <nativehelper/JNIHelp.h>
    26     22   
    27     23   #include <sqlite3.h>
    28     24   
    29     25   // Special log tags defined in SQLiteDebug.java.
    30     26   #define SQLITE_LOG_TAG "SQLiteLog"
    31     27   #define SQLITE_TRACE_TAG "SQLiteStatements"
    32     28   #define SQLITE_PROFILE_TAG "SQLiteTime"

Changes to sqlite3/src/main/jni/sqlite/android_database_SQLiteConnection.cpp.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21     17   #define LOG_TAG "SQLiteConnection"
    22     18   
    23     19   #include <jni.h>
    24         -#include <JNIHelp.h>
    25         -#include "ALog-priv.h"
           20  +#include <nativehelper/JNIHelp.h>
           21  +#include <android_runtime/AndroidRuntime.h>
           22  +#include <android_runtime/Log.h>
    26     23   
    27         -
           24  +#include <utils/Log.h>
           25  +#include <utils/String8.h>
           26  +#include <utils/String16.h>
           27  +#include <cutils/ashmem.h>
    28     28   #include <sys/mman.h>
           29  +
    29     30   #include <string.h>
    30     31   #include <unistd.h>
    31         -#include <assert.h>
    32     32   
    33         -#if 0
    34     33   #include <androidfw/CursorWindow.h>
    35         -#endif
    36     34   
    37     35   #include <sqlite3.h>
    38         -#if 0
    39     36   #include <sqlite3_android.h>
    40         -#endif
    41     37   
    42     38   #include "android_database_SQLiteCommon.h"
    43     39   
    44         -#include <string>
           40  +#include "core_jni_helpers.h"
    45     41   
    46     42   // Set to 1 to use UTF16 storage for localized indexes.
    47     43   #define UTF16_STORAGE 0
    48     44   
    49     45   namespace android {
    50     46   
    51     47   /* Busy timeout in milliseconds.
................................................................................
    58     54    * WAL, a timeout could occur if one connection is busy performing an auto-checkpoint
    59     55    * operation.  The busy timeout needs to be long enough to tolerate slow I/O write
    60     56    * operations but not so long as to cause the application to hang indefinitely if
    61     57    * there is a problem acquiring a database lock.
    62     58    */
    63     59   static const int BUSY_TIMEOUT_MS = 2500;
    64     60   
    65         -static JavaVM *gpJavaVM = 0;
    66         -
    67     61   static struct {
    68     62       jfieldID name;
    69     63       jfieldID numArgs;
    70     64       jmethodID dispatchCallback;
    71     65   } gSQLiteCustomFunctionClassInfo;
    72     66   
    73     67   static struct {
................................................................................
    83     77           OPEN_READ_MASK          = 0x00000001,
    84     78           NO_LOCALIZED_COLLATORS  = 0x00000010,
    85     79           CREATE_IF_NECESSARY     = 0x10000000,
    86     80       };
    87     81   
    88     82       sqlite3* const db;
    89     83       const int openFlags;
    90         -    std::string path;
    91         -    std::string label;
           84  +    const String8 path;
           85  +    const String8 label;
    92     86   
    93     87       volatile bool canceled;
    94     88   
    95         -    SQLiteConnection(sqlite3* db, int openFlags, const std::string& path, const std::string& label) :
           89  +    SQLiteConnection(sqlite3* db, int openFlags, const String8& path, const String8& label) :
    96     90           db(db), openFlags(openFlags), path(path), label(label), canceled(false) { }
    97     91   };
    98     92   
    99     93   // Called each time a statement begins execution, when tracing is enabled.
   100     94   static void sqliteTraceCallback(void *data, const char *sql) {
   101     95       SQLiteConnection* connection = static_cast<SQLiteConnection*>(data);
   102     96       ALOG(LOG_VERBOSE, SQLITE_TRACE_TAG, "%s: \"%s\"\n",
   103         -            connection->label.c_str(), sql);
           97  +            connection->label.string(), sql);
   104     98   }
   105     99   
   106    100   // Called each time a statement finishes execution, when profiling is enabled.
   107    101   static void sqliteProfileCallback(void *data, const char *sql, sqlite3_uint64 tm) {
   108    102       SQLiteConnection* connection = static_cast<SQLiteConnection*>(data);
   109    103       ALOG(LOG_VERBOSE, SQLITE_PROFILE_TAG, "%s: \"%s\" took %0.3f ms\n",
   110         -            connection->label.c_str(), sql, tm * 0.000001f);
          104  +            connection->label.string(), sql, tm * 0.000001f);
   111    105   }
   112    106   
   113    107   // Called after each SQLite VM instruction when cancelation is enabled.
   114    108   static int sqliteProgressHandlerCallback(void* data) {
   115    109       SQLiteConnection* connection = static_cast<SQLiteConnection*>(data);
   116    110       return connection->canceled;
   117    111   }
   118    112   
   119         -/*
   120         -** This function is a collation sequence callback equivalent to the built-in
   121         -** BINARY sequence. 
   122         -**
   123         -** Stock Android uses a modified version of sqlite3.c that calls out to a module
   124         -** named "sqlite3_android" to add extra built-in collations and functions to
   125         -** all database handles. Specifically, collation sequence "LOCALIZED". For now,
   126         -** this module does not include sqlite3_android (since it is difficult to build
   127         -** with the NDK only). Instead, this function is registered as "LOCALIZED" for all
   128         -** new database handles. 
   129         -*/
   130         -static int coll_localized(
   131         -  void *not_used,
   132         -  int nKey1, const void *pKey1,
   133         -  int nKey2, const void *pKey2
   134         -){
   135         -  int rc, n;
   136         -  n = nKey1<nKey2 ? nKey1 : nKey2;
   137         -  rc = memcmp(pKey1, pKey2, n);
   138         -  if( rc==0 ){
   139         -    rc = nKey1 - nKey2;
   140         -  }
   141         -  return rc;
   142         -}
   143    113   
   144    114   static jlong nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFlags,
   145    115           jstring labelStr, jboolean enableTrace, jboolean enableProfile) {
   146    116       int sqliteFlags;
   147    117       if (openFlags & SQLiteConnection::CREATE_IF_NECESSARY) {
   148    118           sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
   149    119       } else if (openFlags & SQLiteConnection::OPEN_READONLY) {
   150    120           sqliteFlags = SQLITE_OPEN_READONLY;
   151    121       } else {
   152    122           sqliteFlags = SQLITE_OPEN_READWRITE;
   153    123       }
   154    124   
   155    125       const char* pathChars = env->GetStringUTFChars(pathStr, NULL);
   156         -    std::string path(pathChars);
          126  +    String8 path(pathChars);
   157    127       env->ReleaseStringUTFChars(pathStr, pathChars);
   158    128   
   159    129       const char* labelChars = env->GetStringUTFChars(labelStr, NULL);
   160         -    std::string label(labelChars);
          130  +    String8 label(labelChars);
   161    131       env->ReleaseStringUTFChars(labelStr, labelChars);
   162    132   
   163    133       sqlite3* db;
   164         -    int err = sqlite3_open_v2(path.c_str(), &db, sqliteFlags, NULL);
          134  +    int err = sqlite3_open_v2(path.string(), &db, sqliteFlags, NULL);
   165    135       if (err != SQLITE_OK) {
   166    136           throw_sqlite3_exception_errcode(env, err, "Could not open database");
   167    137           return 0;
   168    138       }
   169         -    err = sqlite3_create_collation(db, "localized", SQLITE_UTF8, 0, coll_localized);
   170         -    if (err != SQLITE_OK) {
   171         -        throw_sqlite3_exception_errcode(env, err, "Could not register collation");
   172         -        sqlite3_close(db);
   173         -        return 0;
   174         -    }
   175    139   
   176    140       // Check that the database is really read/write when that is what we asked for.
   177    141       if ((sqliteFlags & SQLITE_OPEN_READWRITE) && sqlite3_db_readonly(db, NULL)) {
   178    142           throw_sqlite3_exception(env, db, "Could not open the database in read/write mode.");
   179    143           sqlite3_close(db);
   180    144           return 0;
   181    145       }
................................................................................
   185    149       if (err != SQLITE_OK) {
   186    150           throw_sqlite3_exception(env, db, "Could not set busy timeout");
   187    151           sqlite3_close(db);
   188    152           return 0;
   189    153       }
   190    154   
   191    155       // Register custom Android functions.
   192         -#if 0
   193    156       err = register_android_functions(db, UTF16_STORAGE);
   194    157       if (err) {
   195    158           throw_sqlite3_exception(env, db, "Could not register Android SQL functions.");
   196    159           sqlite3_close(db);
   197    160           return 0;
   198    161       }
   199         -#endif
   200    162   
   201    163       // Create wrapper object.
   202    164       SQLiteConnection* connection = new SQLiteConnection(db, openFlags, path, label);
   203    165   
   204    166       // Enable tracing and profiling if requested.
   205    167       if (enableTrace) {
   206    168           sqlite3_trace(db, &sqliteTraceCallback, connection);
   207    169       }
   208    170       if (enableProfile) {
   209    171           sqlite3_profile(db, &sqliteProfileCallback, connection);
   210    172       }
   211    173   
   212         -    ALOGV("Opened connection %p with label '%s'", db, label.c_str());
          174  +    ALOGV("Opened connection %p with label '%s'", db, label.string());
   213    175       return reinterpret_cast<jlong>(connection);
   214    176   }
   215    177   
   216    178   static void nativeClose(JNIEnv* env, jclass clazz, jlong connectionPtr) {
   217    179       SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
   218    180   
   219    181       if (connection) {
................................................................................
   229    191           delete connection;
   230    192       }
   231    193   }
   232    194   
   233    195   // Called each time a custom function is evaluated.
   234    196   static void sqliteCustomFunctionCallback(sqlite3_context *context,
   235    197           int argc, sqlite3_value **argv) {
   236         -
   237         -    JNIEnv* env = 0;
   238         -    gpJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4);
          198  +    JNIEnv* env = AndroidRuntime::getJNIEnv();
   239    199   
   240    200       // Get the callback function object.
   241    201       // Create a new local reference to it in case the callback tries to do something
   242    202       // dumb like unregister the function (thereby destroying the global ref) while it is running.
   243    203       jobject functionObjGlobal = reinterpret_cast<jobject>(sqlite3_user_data(context));
   244    204       jobject functionObj = env->NewLocalRef(functionObjGlobal);
   245    205   
................................................................................
   268    228           env->DeleteLocalRef(argsArray);
   269    229       }
   270    230   
   271    231       env->DeleteLocalRef(functionObj);
   272    232   
   273    233       if (env->ExceptionCheck()) {
   274    234           ALOGE("An exception was thrown by custom SQLite function.");
   275         -        /* LOGE_EX(env); */
          235  +        LOGE_EX(env);
   276    236           env->ExceptionClear();
   277    237       }
   278    238   }
   279    239   
   280    240   // Called when a custom function is destroyed.
   281    241   static void sqliteCustomFunctionDestructor(void* data) {
   282    242       jobject functionObjGlobal = reinterpret_cast<jobject>(data);
   283         -    JNIEnv* env = 0;
   284         -    gpJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4);
          243  +
          244  +    JNIEnv* env = AndroidRuntime::getJNIEnv();
   285    245       env->DeleteGlobalRef(functionObjGlobal);
   286    246   }
   287    247   
   288    248   static void nativeRegisterCustomFunction(JNIEnv* env, jclass clazz, jlong connectionPtr,
   289    249           jobject functionObj) {
   290    250       SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
   291    251   
................................................................................
   310    270   }
   311    271   
   312    272   static void nativeRegisterLocalizedCollators(JNIEnv* env, jclass clazz, jlong connectionPtr,
   313    273           jstring localeStr) {
   314    274       SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
   315    275   
   316    276       const char* locale = env->GetStringUTFChars(localeStr, NULL);
   317         -#if 0
   318    277       int err = register_localized_collators(connection->db, locale, UTF16_STORAGE);
   319    278       env->ReleaseStringUTFChars(localeStr, locale);
   320    279   
   321    280       if (err != SQLITE_OK) {
   322    281           throw_sqlite3_exception(env, connection->db);
   323    282       }
   324         -#endif
   325    283   }
   326    284   
   327    285   static jlong nativePrepareStatement(JNIEnv* env, jclass clazz, jlong connectionPtr,
   328    286           jstring sqlString) {
   329    287       SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
   330    288   
   331    289       jsize sqlLength = env->GetStringLength(sqlString);
................................................................................
   365    323       // is always finalized regardless.
   366    324       ALOGV("Finalized statement %p on connection %p", statement, connection->db);
   367    325       sqlite3_finalize(statement);
   368    326   }
   369    327   
   370    328   static jint nativeGetParameterCount(JNIEnv* env, jclass clazz, jlong connectionPtr,
   371    329           jlong statementPtr) {
   372         -    SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
   373    330       sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
   374    331   
   375    332       return sqlite3_bind_parameter_count(statement);
   376    333   }
   377    334   
   378    335   static jboolean nativeIsReadOnly(JNIEnv* env, jclass clazz, jlong connectionPtr,
   379    336           jlong statementPtr) {
   380         -    SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
   381    337       sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
   382    338   
   383    339       return sqlite3_stmt_readonly(statement) != 0;
   384    340   }
   385    341   
   386    342   static jint nativeGetColumnCount(JNIEnv* env, jclass clazz, jlong connectionPtr,
   387    343           jlong statementPtr) {
   388         -    SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
   389    344       sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
   390    345   
   391    346       return sqlite3_column_count(statement);
   392    347   }
   393    348   
   394    349   static jstring nativeGetColumnName(JNIEnv* env, jclass clazz, jlong connectionPtr,
   395    350           jlong statementPtr, jint index) {
   396         -    SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
   397    351       sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
   398    352   
   399    353       const jchar* name = static_cast<const jchar*>(sqlite3_column_name16(statement, index));
   400    354       if (name) {
   401    355           size_t length = 0;
   402    356           while (name[length]) {
   403    357               length += 1;
................................................................................
   554    508               return env->NewString(text, length);
   555    509           }
   556    510       }
   557    511       return NULL;
   558    512   }
   559    513   
   560    514   static int createAshmemRegionWithData(JNIEnv* env, const void* data, size_t length) {
   561         -#if 0
   562    515       int error = 0;
   563    516       int fd = ashmem_create_region(NULL, length);
   564    517       if (fd < 0) {
   565    518           error = errno;
   566    519           ALOGE("ashmem_create_region failed: %s", strerror(error));
   567    520       } else {
   568    521           if (length > 0) {
................................................................................
   584    537                   return fd;
   585    538               }
   586    539           }
   587    540   
   588    541           close(fd);
   589    542       }
   590    543   
   591         -#endif
   592         -    jniThrowIOException(env, -1);
          544  +    jniThrowIOException(env, error);
   593    545       return -1;
   594    546   }
   595    547   
   596    548   static jint nativeExecuteForBlobFileDescriptor(JNIEnv* env, jclass clazz,
   597    549           jlong connectionPtr, jlong statementPtr) {
   598    550       SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
   599    551       sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
................................................................................
   607    559                   return createAshmemRegionWithData(env, blob, length);
   608    560               }
   609    561           }
   610    562       }
   611    563       return -1;
   612    564   }
   613    565   
   614         -/*
   615         -** Note: The following symbols must be in the same order as the corresponding
   616         -** elements in the aMethod[] array in function nativeExecuteForCursorWindow().
   617         -*/
   618         -enum CWMethodNames {
   619         -  CW_CLEAR         = 0,
   620         -  CW_SETNUMCOLUMNS = 1,
   621         -  CW_ALLOCROW      = 2,
   622         -  CW_FREELASTROW   = 3,
   623         -  CW_PUTNULL       = 4,
   624         -  CW_PUTLONG       = 5,
   625         -  CW_PUTDOUBLE     = 6,
   626         -  CW_PUTSTRING     = 7,
   627         -  CW_PUTBLOB       = 8
          566  +enum CopyRowResult {
          567  +    CPR_OK,
          568  +    CPR_FULL,
          569  +    CPR_ERROR,
   628    570   };
   629    571   
   630         -/*
   631         -** An instance of this structure represents a single CursorWindow java method.
   632         -*/
   633         -struct CWMethod {
   634         -  jmethodID id;                   /* Method id */
   635         -  const char *zName;              /* Method name */
   636         -  const char *zSig;               /* Method JNI signature */
   637         -};
   638         -
   639         -/*
   640         -** Append the contents of the row that SQL statement pStmt currently points to
   641         -** to the CursorWindow object passed as the second argument. The CursorWindow
   642         -** currently contains iRow rows. Return true on success or false if an error
   643         -** occurs.
   644         -*/
   645         -static jboolean copyRowToWindow(
   646         -  JNIEnv *pEnv,
   647         -  jobject win,
   648         -  int iRow,
   649         -  sqlite3_stmt *pStmt,
   650         -  CWMethod *aMethod
   651         -){
   652         -  int nCol = sqlite3_column_count(pStmt);
   653         -  int i;
   654         -  jboolean bOk;
   655         -
   656         -  bOk = pEnv->CallBooleanMethod(win, aMethod[CW_ALLOCROW].id);
   657         -  for(i=0; bOk && i<nCol; i++){
   658         -    switch( sqlite3_column_type(pStmt, i) ){
   659         -      case SQLITE_NULL: {
   660         -        bOk = pEnv->CallBooleanMethod(win, aMethod[CW_PUTNULL].id, iRow, i);
   661         -        break;
   662         -      }
   663         -
   664         -      case SQLITE_INTEGER: {
   665         -        jlong val = sqlite3_column_int64(pStmt, i);
   666         -        bOk = pEnv->CallBooleanMethod(win, aMethod[CW_PUTLONG].id, val, iRow, i);
   667         -        break;
   668         -      }
   669         -
   670         -      case SQLITE_FLOAT: {
   671         -        jdouble val = sqlite3_column_double(pStmt, i);
   672         -        bOk = pEnv->CallBooleanMethod(win, aMethod[CW_PUTDOUBLE].id, val, iRow, i);
   673         -        break;
   674         -      }
   675         -
   676         -      case SQLITE_TEXT: {
   677         -        jchar *pStr = (jchar*)sqlite3_column_text16(pStmt, i);
   678         -        int nStr = sqlite3_column_bytes16(pStmt, i) / sizeof(jchar);
   679         -        jstring val = pEnv->NewString(pStr, nStr);
   680         -        bOk = pEnv->CallBooleanMethod(win, aMethod[CW_PUTSTRING].id, val, iRow, i);
   681         -        pEnv->DeleteLocalRef(val);
   682         -        break;
   683         -      }
   684         -
   685         -      default: {
   686         -        assert( sqlite3_column_type(pStmt, i)==SQLITE_BLOB );
   687         -        const jbyte *p = (const jbyte*)sqlite3_column_blob(pStmt, i);
   688         -        int n = sqlite3_column_bytes(pStmt, i);
   689         -        jbyteArray val = pEnv->NewByteArray(n);
   690         -        pEnv->SetByteArrayRegion(val, 0, n, p);
   691         -        bOk = pEnv->CallBooleanMethod(win, aMethod[CW_PUTBLOB].id, val, iRow, i);
   692         -        pEnv->DeleteLocalRef(val);
   693         -        break;
   694         -      }
          572  +static CopyRowResult copyRow(JNIEnv* env, CursorWindow* window,
          573  +        sqlite3_stmt* statement, int numColumns, int startPos, int addedRows) {
          574  +    // Allocate a new field directory for the row.
          575  +    status_t status = window->allocRow();
          576  +    if (status) {
          577  +        LOG_WINDOW("Failed allocating fieldDir at startPos %d row %d, error=%d",
          578  +                startPos, addedRows, status);
          579  +        return CPR_FULL;
          580  +    }
          581  +
          582  +    // Pack the row into the window.
          583  +    CopyRowResult result = CPR_OK;
          584  +    for (int i = 0; i < numColumns; i++) {
          585  +        int type = sqlite3_column_type(statement, i);
          586  +        if (type == SQLITE_TEXT) {
          587  +            // TEXT data
          588  +            const char* text = reinterpret_cast<const char*>(
          589  +                    sqlite3_column_text(statement, i));
          590  +            // SQLite does not include the NULL terminator in size, but does
          591  +            // ensure all strings are NULL terminated, so increase size by
          592  +            // one to make sure we store the terminator.
          593  +            size_t sizeIncludingNull = sqlite3_column_bytes(statement, i) + 1;
          594  +            status = window->putString(addedRows, i, text, sizeIncludingNull);
          595  +            if (status) {
          596  +                LOG_WINDOW("Failed allocating %u bytes for text at %d,%d, error=%d",
          597  +                        sizeIncludingNull, startPos + addedRows, i, status);
          598  +                result = CPR_FULL;
          599  +                break;
          600  +            }
          601  +            LOG_WINDOW("%d,%d is TEXT with %u bytes",
          602  +                    startPos + addedRows, i, sizeIncludingNull);
          603  +        } else if (type == SQLITE_INTEGER) {
          604  +            // INTEGER data
          605  +            int64_t value = sqlite3_column_int64(statement, i);
          606  +            status = window->putLong(addedRows, i, value);
          607  +            if (status) {
          608  +                LOG_WINDOW("Failed allocating space for a long in column %d, error=%d",
          609  +                        i, status);
          610  +                result = CPR_FULL;
          611  +                break;
          612  +            }
          613  +            LOG_WINDOW("%d,%d is INTEGER 0x%016llx", startPos + addedRows, i, value);
          614  +        } else if (type == SQLITE_FLOAT) {
          615  +            // FLOAT data
          616  +            double value = sqlite3_column_double(statement, i);
          617  +            status = window->putDouble(addedRows, i, value);
          618  +            if (status) {
          619  +                LOG_WINDOW("Failed allocating space for a double in column %d, error=%d",
          620  +                        i, status);
          621  +                result = CPR_FULL;
          622  +                break;
          623  +            }
          624  +            LOG_WINDOW("%d,%d is FLOAT %lf", startPos + addedRows, i, value);
          625  +        } else if (type == SQLITE_BLOB) {
          626  +            // BLOB data
          627  +            const void* blob = sqlite3_column_blob(statement, i);
          628  +            size_t size = sqlite3_column_bytes(statement, i);
          629  +            status = window->putBlob(addedRows, i, blob, size);
          630  +            if (status) {
          631  +                LOG_WINDOW("Failed allocating %u bytes for blob at %d,%d, error=%d",
          632  +                        size, startPos + addedRows, i, status);
          633  +                result = CPR_FULL;
          634  +                break;
          635  +            }
          636  +            LOG_WINDOW("%d,%d is Blob with %u bytes",
          637  +                    startPos + addedRows, i, size);
          638  +        } else if (type == SQLITE_NULL) {
          639  +            // NULL field
          640  +            status = window->putNull(addedRows, i);
          641  +            if (status) {
          642  +                LOG_WINDOW("Failed allocating space for a null in column %d, error=%d",
          643  +                        i, status);
          644  +                result = CPR_FULL;
          645  +                break;
          646  +            }
          647  +
          648  +            LOG_WINDOW("%d,%d is NULL", startPos + addedRows, i);
          649  +        } else {
          650  +            // Unknown data
          651  +            ALOGE("Unknown column type when filling database window");
          652  +            throw_sqlite3_exception(env, "Unknown column type when filling window");
          653  +            result = CPR_ERROR;
          654  +            break;
          655  +        }
          656  +    }
          657  +
          658  +    // Free the last row if if was not successfully copied.
          659  +    if (result != CPR_OK) {
          660  +        window->freeLastRow();
   695    661       }
   696         -
   697         -    if( bOk==0 ){
   698         -      pEnv->CallVoidMethod(win, aMethod[CW_FREELASTROW].id);
   699         -    }
   700         -  }
   701         -
   702         -  return bOk;
   703         -}
   704         -
   705         -static jboolean setWindowNumColumns(
   706         -  JNIEnv *pEnv,
   707         -  jobject win,
   708         -  sqlite3_stmt *pStmt,
   709         -  CWMethod *aMethod
   710         -){
   711         -  int nCol;
   712         -
   713         -  pEnv->CallVoidMethod(win, aMethod[CW_CLEAR].id);
   714         -  nCol = sqlite3_column_count(pStmt);
   715         -  return pEnv->CallBooleanMethod(win, aMethod[CW_SETNUMCOLUMNS].id, (jint)nCol);
          662  +    return result;
   716    663   }
   717    664   
   718         -/*
   719         -** This method has been rewritten for org.sqlite.database.*. The original 
   720         -** android implementation used the C++ interface to populate a CursorWindow
   721         -** object. Since the NDK does not export this interface, we invoke the Java
   722         -** interface using standard JNI methods to do the same thing.
   723         -**
   724         -** This function executes the SQLite statement object passed as the 4th 
   725         -** argument and copies one or more returned rows into the CursorWindow
   726         -** object passed as the 5th argument. The set of rows copied into the 
   727         -** CursorWindow is always contiguous.
   728         -**
   729         -** The only row that *must* be copied into the CursorWindow is row 
   730         -** iRowRequired. Ideally, all rows from iRowStart through to the end
   731         -** of the query are copied into the CursorWindow. If this is not possible
   732         -** (CursorWindow objects have a finite capacity), some compromise position
   733         -** is found (see comments embedded in the code below for details).
   734         -**
   735         -** The return value is a 64-bit integer calculated as follows:
   736         -**
   737         -**      (iStart << 32) | nRow
   738         -**
   739         -** where iStart is the index of the first row copied into the CursorWindow.
   740         -** If the countAllRows argument is true, nRow is the total number of rows
   741         -** returned by the query. Otherwise, nRow is one greater than the index of 
   742         -** the last row copied into the CursorWindow.
   743         -*/
   744         -static jlong nativeExecuteForCursorWindow(
   745         -  JNIEnv *pEnv, 
   746         -  jclass clazz,
   747         -  jlong connectionPtr,            /* Pointer to SQLiteConnection C++ object */
   748         -  jlong statementPtr,             /* Pointer to sqlite3_stmt object */
   749         -  jobject win,                    /* The CursorWindow object to populate */
   750         -  jint startPos,                  /* First row to add (advisory) */
   751         -  jint iRowRequired,              /* Required row */
   752         -  jboolean countAllRows
   753         -) {
   754         -  SQLiteConnection *pConnection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
   755         -  sqlite3_stmt *pStmt = reinterpret_cast<sqlite3_stmt*>(statementPtr);
   756         -
   757         -  CWMethod aMethod[] = {
   758         -    {0, "clear",         "()V"},
   759         -    {0, "setNumColumns", "(I)Z"},
   760         -    {0, "allocRow",      "()Z"},
   761         -    {0, "freeLastRow",   "()V"},
   762         -    {0, "putNull",       "(II)Z"},
   763         -    {0, "putLong",       "(JII)Z"},
   764         -    {0, "putDouble",     "(DII)Z"},
   765         -    {0, "putString",     "(Ljava/lang/String;II)Z"},
   766         -    {0, "putBlob",       "([BII)Z"},
   767         -  };
   768         -  jclass cls;                     /* Class android.database.CursorWindow */
   769         -  int i;                          /* Iterator variable */
   770         -  int nCol;                       /* Number of columns returned by pStmt */
   771         -  int nRow;
   772         -  jboolean bOk;
   773         -  int iStart;                     /* First row copied to CursorWindow */
   774         -
   775         -  /* Locate all required CursorWindow methods. */
   776         -  cls = pEnv->FindClass("android/database/CursorWindow");
   777         -  for(i=0; i<(sizeof(aMethod)/sizeof(struct CWMethod)); i++){
   778         -    aMethod[i].id = pEnv->GetMethodID(cls, aMethod[i].zName, aMethod[i].zSig);
   779         -    if( aMethod[i].id==NULL ){
   780         -      jniThrowExceptionFmt(pEnv, "java/lang/Exception", 
   781         -          "Failed to find method CursorWindow.%s()", aMethod[i].zName
   782         -      );
   783         -      return 0;
          665  +static jlong nativeExecuteForCursorWindow(JNIEnv* env, jclass clazz,
          666  +        jlong connectionPtr, jlong statementPtr, jlong windowPtr,
          667  +        jint startPos, jint requiredPos, jboolean countAllRows) {
          668  +    SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
          669  +    sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
          670  +    CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
          671  +
          672  +    status_t status = window->clear();
          673  +    if (status) {
          674  +        String8 msg;
          675  +        msg.appendFormat("Failed to clear the cursor window, status=%d", status);
          676  +        throw_sqlite3_exception(env, connection->db, msg.string());
          677  +        return 0;
          678  +    }
          679  +
          680  +    int numColumns = sqlite3_column_count(statement);
          681  +    status = window->setNumColumns(numColumns);
          682  +    if (status) {
          683  +        String8 msg;
          684  +        msg.appendFormat("Failed to set the cursor window column count to %d, status=%d",
          685  +                numColumns, status);
          686  +        throw_sqlite3_exception(env, connection->db, msg.string());
          687  +        return 0;
          688  +    }
          689  +
          690  +    int retryCount = 0;
          691  +    int totalRows = 0;
          692  +    int addedRows = 0;
          693  +    bool windowFull = false;
          694  +    bool gotException = false;
          695  +    while (!gotException && (!windowFull || countAllRows)) {
          696  +        int err = sqlite3_step(statement);
          697  +        if (err == SQLITE_ROW) {
          698  +            LOG_WINDOW("Stepped statement %p to row %d", statement, totalRows);
          699  +            retryCount = 0;
          700  +            totalRows += 1;
          701  +
          702  +            // Skip the row if the window is full or we haven't reached the start position yet.
          703  +            if (startPos >= totalRows || windowFull) {
          704  +                continue;
          705  +            }
          706  +
          707  +            CopyRowResult cpr = copyRow(env, window, statement, numColumns, startPos, addedRows);
          708  +            if (cpr == CPR_FULL && addedRows && startPos + addedRows <= requiredPos) {
          709  +                // We filled the window before we got to the one row that we really wanted.
          710  +                // Clear the window and start filling it again from here.
          711  +                // TODO: Would be nicer if we could progressively replace earlier rows.
          712  +                window->clear();
          713  +                window->setNumColumns(numColumns);
          714  +                startPos += addedRows;
          715  +                addedRows = 0;
          716  +                cpr = copyRow(env, window, statement, numColumns, startPos, addedRows);
          717  +            }
          718  +
          719  +            if (cpr == CPR_OK) {
          720  +                addedRows += 1;
          721  +            } else if (cpr == CPR_FULL) {
          722  +                windowFull = true;
          723  +            } else {
          724  +                gotException = true;
          725  +            }
          726  +        } else if (err == SQLITE_DONE) {
          727  +            // All rows processed, bail
          728  +            LOG_WINDOW("Processed all rows");
          729  +            break;
          730  +        } else if (err == SQLITE_LOCKED || err == SQLITE_BUSY) {
          731  +            // The table is locked, retry
          732  +            LOG_WINDOW("Database locked, retrying");
          733  +            if (retryCount > 50) {
          734  +                ALOGE("Bailing on database busy retry");
          735  +                throw_sqlite3_exception(env, connection->db, "retrycount exceeded");
          736  +                gotException = true;
          737  +            } else {
          738  +                // Sleep to give the thread holding the lock a chance to finish
          739  +                usleep(1000);
          740  +                retryCount++;
          741  +            }
          742  +        } else {
          743  +            throw_sqlite3_exception(env, connection->db);
          744  +            gotException = true;
          745  +        }
          746  +    }
          747  +
          748  +    LOG_WINDOW("Resetting statement %p after fetching %d rows and adding %d rows"
          749  +            "to the window in %d bytes",
          750  +            statement, totalRows, addedRows, window->size() - window->freeSpace());
          751  +    sqlite3_reset(statement);
          752  +
          753  +    // Report the total number of rows on request.
          754  +    if (startPos > totalRows) {
          755  +        ALOGE("startPos %d > actual rows %d", startPos, totalRows);
   784    756       }
   785         -  }
   786         -
   787         -
   788         -  /* Set the number of columns in the window */
   789         -  bOk = setWindowNumColumns(pEnv, win, pStmt, aMethod);
   790         -  if( bOk==0 ) return 0;
   791         -
   792         -  nRow = 0;
   793         -  iStart = startPos;
   794         -  while( sqlite3_step(pStmt)==SQLITE_ROW ){
   795         -    /* Only copy in rows that occur at or after row index iStart. */
   796         -    if( nRow>=iStart && bOk ){
   797         -      bOk = copyRowToWindow(pEnv, win, (nRow - iStart), pStmt, aMethod);
   798         -      if( bOk==0 ){
   799         -        /* The CursorWindow object ran out of memory. If row iRowRequired was
   800         -        ** not successfully added before this happened, clear the CursorWindow
   801         -        ** and try to add the current row again.  */
   802         -        if( nRow<=iRowRequired ){
   803         -          bOk = setWindowNumColumns(pEnv, win, pStmt, aMethod);
   804         -          if( bOk==0 ){
   805         -            sqlite3_reset(pStmt);
   806         -            return 0;
   807         -          }
   808         -          iStart = nRow;
   809         -          bOk = copyRowToWindow(pEnv, win, (nRow - iStart), pStmt, aMethod);
   810         -        }
   811         -
   812         -        /* If the CursorWindow is still full and the countAllRows flag is not
   813         -        ** set, break out of the loop here. If countAllRows is set, continue
   814         -        ** so as to set variable nRow correctly.  */
   815         -        if( bOk==0 && countAllRows==0 ) break;
   816         -      }
   817         -    }
   818         -
   819         -    nRow++;
   820         -  }
   821         -
   822         -  /* Finalize the statement. If this indicates an error occurred, throw an
   823         -  ** SQLiteException exception.  */
   824         -  int rc = sqlite3_reset(pStmt);
   825         -  if( rc!=SQLITE_OK ){
   826         -    throw_sqlite3_exception(pEnv, sqlite3_db_handle(pStmt));
   827         -    return 0;
   828         -  }
   829         -
   830         -  jlong lRet = jlong(iStart) << 32 | jlong(nRow);
   831         -  return lRet;
          757  +    jlong result = jlong(startPos) << 32 | jlong(totalRows);
          758  +    return result;
   832    759   }
   833    760   
   834    761   static jint nativeGetDbLookaside(JNIEnv* env, jobject clazz, jlong connectionPtr) {
   835    762       SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
   836    763   
   837    764       int cur = -1;
   838    765       int unused;
................................................................................
   854    781           sqlite3_progress_handler(connection->db, 4, sqliteProgressHandlerCallback,
   855    782                   connection);
   856    783       } else {
   857    784           sqlite3_progress_handler(connection->db, 0, NULL, NULL);
   858    785       }
   859    786   }
   860    787   
   861         -static jboolean nativeHasCodec(JNIEnv* env, jobject clazz){
   862         -#ifdef SQLITE_HAS_CODEC
   863         -  return true;
   864         -#else
   865         -  return false;
   866         -#endif
   867         -}
   868    788   
   869         -
   870         -static JNINativeMethod sMethods[] =
          789  +static const JNINativeMethod sMethods[] =
   871    790   {
   872    791       /* name, signature, funcPtr */
   873    792       { "nativeOpen", "(Ljava/lang/String;ILjava/lang/String;ZZ)J",
   874    793               (void*)nativeOpen },
   875    794       { "nativeClose", "(J)V",
   876    795               (void*)nativeClose },
   877         -    { "nativeRegisterCustomFunction", "(JLorg/sqlite/database/sqlite/SQLiteCustomFunction;)V",
          796  +    { "nativeRegisterCustomFunction", "(JLandroid/database/sqlite/SQLiteCustomFunction;)V",
   878    797               (void*)nativeRegisterCustomFunction },
   879    798       { "nativeRegisterLocalizedCollators", "(JLjava/lang/String;)V",
   880    799               (void*)nativeRegisterLocalizedCollators },
   881    800       { "nativePrepareStatement", "(JLjava/lang/String;)J",
   882    801               (void*)nativePrepareStatement },
   883    802       { "nativeFinalizeStatement", "(JJ)V",
   884    803               (void*)nativeFinalizeStatement },
................................................................................
   910    829               (void*)nativeExecuteForString },
   911    830       { "nativeExecuteForBlobFileDescriptor", "(JJ)I",
   912    831               (void*)nativeExecuteForBlobFileDescriptor },
   913    832       { "nativeExecuteForChangedRowCount", "(JJ)I",
   914    833               (void*)nativeExecuteForChangedRowCount },
   915    834       { "nativeExecuteForLastInsertedRowId", "(JJ)J",
   916    835               (void*)nativeExecuteForLastInsertedRowId },
   917         -    { "nativeExecuteForCursorWindow", "(JJLandroid/database/CursorWindow;IIZ)J",
          836  +    { "nativeExecuteForCursorWindow", "(JJJIIZ)J",
   918    837               (void*)nativeExecuteForCursorWindow },
   919    838       { "nativeGetDbLookaside", "(J)I",
   920    839               (void*)nativeGetDbLookaside },
   921    840       { "nativeCancel", "(J)V",
   922    841               (void*)nativeCancel },
   923    842       { "nativeResetCancel", "(JZ)V",
   924    843               (void*)nativeResetCancel },
   925         -
   926         -    { "nativeHasCodec", "()Z", (void*)nativeHasCodec },
   927    844   };
   928    845   
   929         -#define FIND_CLASS(var, className) \
   930         -        var = env->FindClass(className); \
   931         -        LOG_FATAL_IF(! var, "Unable to find class " className);
   932         -
   933         -#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
   934         -        var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
   935         -        LOG_FATAL_IF(! var, "Unable to find method" methodName);
   936         -
   937         -#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
   938         -        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
   939         -        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
   940         -
   941    846   int register_android_database_SQLiteConnection(JNIEnv *env)
   942    847   {
   943         -    jclass clazz;
   944         -    FIND_CLASS(clazz, "org/sqlite/database/sqlite/SQLiteCustomFunction");
          848  +    jclass clazz = FindClassOrDie(env, "android/database/sqlite/SQLiteCustomFunction");
          849  +
          850  +    gSQLiteCustomFunctionClassInfo.name = GetFieldIDOrDie(env, clazz, "name", "Ljava/lang/String;");
          851  +    gSQLiteCustomFunctionClassInfo.numArgs = GetFieldIDOrDie(env, clazz, "numArgs", "I");
          852  +    gSQLiteCustomFunctionClassInfo.dispatchCallback = GetMethodIDOrDie(env, clazz,
          853  +            "dispatchCallback", "([Ljava/lang/String;)V");
   945    854   
   946         -    GET_FIELD_ID(gSQLiteCustomFunctionClassInfo.name, clazz,
   947         -            "name", "Ljava/lang/String;");
   948         -    GET_FIELD_ID(gSQLiteCustomFunctionClassInfo.numArgs, clazz,
   949         -            "numArgs", "I");
   950         -    GET_METHOD_ID(gSQLiteCustomFunctionClassInfo.dispatchCallback,
   951         -            clazz, "dispatchCallback", "([Ljava/lang/String;)V");
          855  +    clazz = FindClassOrDie(env, "java/lang/String");
          856  +    gStringClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
   952    857   
   953         -    FIND_CLASS(clazz, "java/lang/String");
   954         -    gStringClassInfo.clazz = jclass(env->NewGlobalRef(clazz));
   955         -
   956         -    return jniRegisterNativeMethods(env, 
   957         -        "org/sqlite/database/sqlite/SQLiteConnection",
   958         -        sMethods, NELEM(sMethods)
   959         -    );
          858  +    return RegisterMethodsOrDie(env, "android/database/sqlite/SQLiteConnection", sMethods,
          859  +                                NELEM(sMethods));
   960    860   }
   961    861   
   962         -extern int register_android_database_SQLiteGlobal(JNIEnv *env);
   963         -extern int register_android_database_SQLiteDebug(JNIEnv *env);
   964         -
   965    862   } // namespace android
   966         -
   967         -extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
   968         -  JNIEnv *env = 0;
   969         -
   970         -  android::gpJavaVM = vm;
   971         -  vm->GetEnv((void**)&env, JNI_VERSION_1_4);
   972         -
   973         -  android::register_android_database_SQLiteConnection(env);
   974         -  android::register_android_database_SQLiteDebug(env);
   975         -  android::register_android_database_SQLiteGlobal(env);
   976         -
   977         -  return JNI_VERSION_1_4;
   978         -}
   979         -
   980         -
   981         -

Changes to sqlite3/src/main/jni/sqlite/android_database_SQLiteDebug.cpp.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21     17   #define LOG_TAG "SQLiteDebug"
    22     18   
    23     19   #include <jni.h>
    24         -#include <JNIHelp.h>
    25         -#include <ALog-priv.h>
           20  +#include <nativehelper/JNIHelp.h>
           21  +#include <android_runtime/AndroidRuntime.h>
    26     22   
    27     23   #include <stdio.h>
    28     24   #include <stdlib.h>
    29     25   #include <string.h>
    30     26   #include <unistd.h>
           27  +#include <utils/Log.h>
    31     28   
    32     29   #include <sqlite3.h>
           30  +
           31  +#include "core_jni_helpers.h"
    33     32   
    34     33   namespace android {
    35     34   
    36     35   static struct {
    37     36       jfieldID memoryUsed;
    38     37       jfieldID pageCacheOverflow;
    39     38       jfieldID largestMemAlloc;
................................................................................
    55     54       env->SetIntField(statsObj, gSQLiteDebugPagerStatsClassInfo.largestMemAlloc, largestMemAlloc);
    56     55   }
    57     56   
    58     57   /*
    59     58    * JNI registration.
    60     59    */
    61     60   
    62         -static JNINativeMethod gMethods[] =
           61  +static const JNINativeMethod gMethods[] =
    63     62   {
    64         -    { "nativeGetPagerStats", "(Lorg/sqlite/database/sqlite/SQLiteDebug$PagerStats;)V",
           63  +    { "nativeGetPagerStats", "(Landroid/database/sqlite/SQLiteDebug$PagerStats;)V",
    65     64               (void*) nativeGetPagerStats },
    66     65   };
    67     66   
    68         -#define FIND_CLASS(var, className) \
    69         -        var = env->FindClass(className); \
    70         -        LOG_FATAL_IF(! var, "Unable to find class " className);
    71         -
    72         -#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
    73         -        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
    74         -        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
    75         -
    76     67   int register_android_database_SQLiteDebug(JNIEnv *env)
    77     68   {
    78         -    jclass clazz;
    79         -    FIND_CLASS(clazz, "org/sqlite/database/sqlite/SQLiteDebug$PagerStats");
           69  +    jclass clazz = FindClassOrDie(env, "android/database/sqlite/SQLiteDebug$PagerStats");
    80     70   
    81         -    GET_FIELD_ID(gSQLiteDebugPagerStatsClassInfo.memoryUsed, clazz,
    82         -            "memoryUsed", "I");
    83         -    GET_FIELD_ID(gSQLiteDebugPagerStatsClassInfo.largestMemAlloc, clazz,
           71  +    gSQLiteDebugPagerStatsClassInfo.memoryUsed = GetFieldIDOrDie(env, clazz, "memoryUsed", "I");
           72  +    gSQLiteDebugPagerStatsClassInfo.largestMemAlloc = GetFieldIDOrDie(env, clazz,
    84     73               "largestMemAlloc", "I");
    85         -    GET_FIELD_ID(gSQLiteDebugPagerStatsClassInfo.pageCacheOverflow, clazz,
           74  +    gSQLiteDebugPagerStatsClassInfo.pageCacheOverflow = GetFieldIDOrDie(env, clazz,
    86     75               "pageCacheOverflow", "I");
    87     76   
    88         -    return jniRegisterNativeMethods(env, "org/sqlite/database/sqlite/SQLiteDebug",
           77  +    return RegisterMethodsOrDie(env, "android/database/sqlite/SQLiteDebug",
    89     78               gMethods, NELEM(gMethods));
    90     79   }
    91     80   
    92     81   } // namespace android

Changes to sqlite3/src/main/jni/sqlite/android_database_SQLiteGlobal.cpp.

     9      9    *
    10     10    * Unless required by applicable law or agreed to in writing, software
    11     11    * distributed under the License is distributed on an "AS IS" BASIS,
    12     12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16         -/*
    17         -** Modified to support SQLite extensions by the SQLite developers: 
    18         -** sqlite-dev@sqlite.org.
    19         -*/
    20     16   
    21     17   #define LOG_TAG "SQLiteGlobal"
    22     18   
    23     19   #include <jni.h>
    24         -#include <JNIHelp.h>
    25         -#include "ALog-priv.h"
    26         -
           20  +#include <nativehelper/JNIHelp.h>
           21  +#include "core_jni_helpers.h"
    27     22   
    28     23   #include <sqlite3.h>
    29         -#if 0
    30     24   #include <sqlite3_android.h>
    31         -#endif
    32         -
    33     25   
    34     26   #include "android_database_SQLiteCommon.h"
           27  +#include "android_util_Log.h"
    35     28   
    36     29   namespace android {
    37     30   
    38     31   // Limit heap to 8MB for now.  This is 4 times the maximum cursor window
    39     32   // size, as has been used by the original code in SQLiteDatabase for
    40     33   // a long time.
    41     34   static const int SOFT_HEAP_LIMIT = 8 * 1024 * 1024;
    42     35   
    43     36   
    44     37   // Called each time a message is logged.
    45         -static void sqliteLogCallback(void* data, int iErrCode, const char* zMsg) {
           38  +static void sqliteLogCallback(void* data, int err, const char* msg) {
    46     39       bool verboseLog = !!data;
    47         -    if (iErrCode == 0 || iErrCode == SQLITE_CONSTRAINT || iErrCode == SQLITE_SCHEMA) {
           40  +    int errType = err & 255;
           41  +    if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA
           42  +            || errType == SQLITE_NOTICE || err == SQLITE_WARNING_AUTOINDEX) {
    48     43           if (verboseLog) {
    49         -            ALOG(LOG_VERBOSE, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
           44  +            ALOG(LOG_VERBOSE, SQLITE_LOG_TAG, "(%d) %s\n", err, msg);
    50     45           }
           46  +    } else if (errType == SQLITE_WARNING) {
           47  +        ALOG(LOG_WARN, SQLITE_LOG_TAG, "(%d) %s\n", err, msg);
    51     48       } else {
    52         -        ALOG(LOG_ERROR, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
           49  +        ALOG(LOG_ERROR, SQLITE_LOG_TAG, "(%d) %s\n", err, msg);
    53     50       }
    54     51   }
    55     52   
    56     53   // Sets the global SQLite configuration.
    57     54   // This must be called before any other SQLite functions are called.
    58     55   static void sqliteInitialize() {
    59     56       // Enable multi-threaded mode.  In this mode, SQLite is safe to use by multiple
    60     57       // threads as long as no two threads use the same database connection at the same
    61     58       // time (which we guarantee in the SQLite database wrappers).
    62     59       sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
    63     60   
    64     61       // Redirect SQLite log messages to the Android log.
    65         -#if 0
    66     62       bool verboseLog = android_util_Log_isVerboseLogEnabled(SQLITE_LOG_TAG);
    67         -#endif
    68         -    bool verboseLog = false;
    69     63       sqlite3_config(SQLITE_CONFIG_LOG, &sqliteLogCallback, verboseLog ? (void*)1 : NULL);
    70     64   
    71     65       // The soft heap limit prevents the page cache allocations from growing
    72     66       // beyond the given limit, no matter what the max page cache sizes are
    73     67       // set to. The limit does not, as of 3.5.0, affect any other allocations.
    74     68       sqlite3_soft_heap_limit(SOFT_HEAP_LIMIT);
    75     69   
................................................................................
    77     71       sqlite3_initialize();
    78     72   }
    79     73   
    80     74   static jint nativeReleaseMemory(JNIEnv* env, jclass clazz) {
    81     75       return sqlite3_release_memory(SOFT_HEAP_LIMIT);
    82     76   }
    83     77   
    84         -static JNINativeMethod sMethods[] =
           78  +static const JNINativeMethod sMethods[] =
    85     79   {
    86     80       /* name, signature, funcPtr */
    87         -    { "nativeReleaseMemory", "()I",
    88         -            (void*)nativeReleaseMemory },
           81  +    { "nativeReleaseMemory", "()I", (void*)nativeReleaseMemory },
    89     82   };
    90     83   
    91     84   int register_android_database_SQLiteGlobal(JNIEnv *env)
    92     85   {
    93     86       sqliteInitialize();
    94     87   
    95         -    return jniRegisterNativeMethods(env, "org/sqlite/database/sqlite/SQLiteGlobal",
           88  +    return RegisterMethodsOrDie(env, "android/database/sqlite/SQLiteGlobal",
    96     89               sMethods, NELEM(sMethods));
    97     90   }
    98     91   
    99     92   } // namespace android