The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2006 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package android.database.sqlite; |
| 18 | |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 19 | import android.database.DatabaseUtils; |
Bjorn Bringert | a006b472 | 2010-04-14 14:43:26 +0100 | [diff] [blame] | 20 | import android.os.ParcelFileDescriptor; |
Brad Fitzpatrick | 6a35387 | 2010-02-11 18:04:49 -0800 | [diff] [blame] | 21 | import android.os.SystemClock; |
Bjorn Bringert | a006b472 | 2010-04-14 14:43:26 +0100 | [diff] [blame] | 22 | import android.util.Log; |
| 23 | |
| 24 | import java.io.IOException; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 25 | |
Brad Fitzpatrick | cfda9f3 | 2010-06-03 12:52:54 -0700 | [diff] [blame] | 26 | import dalvik.system.BlockGuard; |
| 27 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 28 | /** |
| 29 | * A pre-compiled statement against a {@link SQLiteDatabase} that can be reused. |
| 30 | * The statement cannot return multiple rows, but 1x1 result sets are allowed. |
| 31 | * Don't use SQLiteStatement constructor directly, please use |
| 32 | * {@link SQLiteDatabase#compileStatement(String)} |
Vasu Nori | ccd9544 | 2010-05-28 17:04:16 -0700 | [diff] [blame] | 33 | *<p> |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 34 | * SQLiteStatement is NOT internally synchronized so code using a SQLiteStatement from multiple |
Jeff Hamilton | f3ca9a5 | 2010-05-12 15:04:33 -0700 | [diff] [blame] | 35 | * threads should perform its own synchronization when using the SQLiteStatement. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 36 | */ |
Vasu Nori | 2827d6d | 2010-07-04 00:26:18 -0700 | [diff] [blame] | 37 | @SuppressWarnings("deprecation") |
Jeff Brown | d5064be | 2011-12-14 14:25:13 -0800 | [diff] [blame] | 38 | public final class SQLiteStatement extends SQLiteProgram |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 39 | { |
Bjorn Bringert | a006b472 | 2010-04-14 14:43:26 +0100 | [diff] [blame] | 40 | private static final String TAG = "SQLiteStatement"; |
| 41 | |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 42 | private static final boolean READ = true; |
| 43 | private static final boolean WRITE = false; |
| 44 | |
Vasu Nori | e25539f | 2010-07-08 17:06:13 -0700 | [diff] [blame] | 45 | private SQLiteDatabase mOrigDb; |
Vasu Nori | 0732f79 | 2010-07-29 17:24:12 -0700 | [diff] [blame] | 46 | private int mState; |
Vasu Nori | d31211f | 2010-09-13 15:47:49 -0700 | [diff] [blame] | 47 | /** possible value for {@link #mState}. indicates that a transaction is started. */ |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 48 | private static final int TRANS_STARTED = 1; |
Vasu Nori | d31211f | 2010-09-13 15:47:49 -0700 | [diff] [blame] | 49 | /** possible value for {@link #mState}. indicates that a lock is acquired. */ |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 50 | private static final int LOCK_ACQUIRED = 2; |
Vasu Nori | e25539f | 2010-07-08 17:06:13 -0700 | [diff] [blame] | 51 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 52 | /** |
| 53 | * Don't use SQLiteStatement constructor directly, please use |
| 54 | * {@link SQLiteDatabase#compileStatement(String)} |
| 55 | * @param db |
| 56 | * @param sql |
| 57 | */ |
Vasu Nori | 0732f79 | 2010-07-29 17:24:12 -0700 | [diff] [blame] | 58 | /* package */ SQLiteStatement(SQLiteDatabase db, String sql, Object[] bindArgs) { |
| 59 | super(db, sql, bindArgs, false /* don't compile sql statement */); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | /** |
Vasu Nori | fb16cbd | 2010-07-25 16:38:48 -0700 | [diff] [blame] | 63 | * Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example |
| 64 | * CREATE / DROP table, view, trigger, index etc. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 65 | * |
| 66 | * @throws android.database.SQLException If the SQL string is invalid for |
| 67 | * some reason |
| 68 | */ |
| 69 | public void execute() { |
Vasu Nori | fb16cbd | 2010-07-25 16:38:48 -0700 | [diff] [blame] | 70 | executeUpdateDelete(); |
| 71 | } |
| 72 | |
| 73 | /** |
Vasu Nori | 4e874ed | 2010-09-15 18:40:49 -0700 | [diff] [blame] | 74 | * Execute this SQL statement, if the the number of rows affected by execution of this SQL |
Vasu Nori | fb16cbd | 2010-07-25 16:38:48 -0700 | [diff] [blame] | 75 | * statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements. |
| 76 | * |
| 77 | * @return the number of rows affected by this SQL statement execution. |
| 78 | * @throws android.database.SQLException If the SQL string is invalid for |
| 79 | * some reason |
| 80 | */ |
| 81 | public int executeUpdateDelete() { |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 82 | try { |
Vasu Nori | 16057fa | 2011-03-18 11:40:37 -0700 | [diff] [blame] | 83 | saveSqlAsLastSqlStatement(); |
| 84 | acquireAndLock(WRITE); |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 85 | int numChanges = 0; |
| 86 | if ((mStatementType & STATEMENT_DONT_PREPARE) > 0) { |
| 87 | // since the statement doesn't have to be prepared, |
| 88 | // call the following native method which will not prepare |
| 89 | // the query plan |
| 90 | native_executeSql(mSql); |
| 91 | } else { |
| 92 | numChanges = native_execute(); |
Vasu Nori | e25539f | 2010-07-08 17:06:13 -0700 | [diff] [blame] | 93 | } |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 94 | return numChanges; |
| 95 | } finally { |
| 96 | releaseAndUnlock(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 97 | } |
| 98 | } |
| 99 | |
| 100 | /** |
Vasu Nori | 5bf6724 | 2010-03-16 09:55:13 -0700 | [diff] [blame] | 101 | * Execute this SQL statement and return the ID of the row inserted due to this call. |
| 102 | * The SQL statement should be an INSERT for this to be a useful call. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 103 | * |
Vasu Nori | 5bf6724 | 2010-03-16 09:55:13 -0700 | [diff] [blame] | 104 | * @return the row ID of the last row inserted, if this insert is successful. -1 otherwise. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 105 | * |
| 106 | * @throws android.database.SQLException If the SQL string is invalid for |
| 107 | * some reason |
| 108 | */ |
| 109 | public long executeInsert() { |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 110 | try { |
Vasu Nori | 16057fa | 2011-03-18 11:40:37 -0700 | [diff] [blame] | 111 | saveSqlAsLastSqlStatement(); |
| 112 | acquireAndLock(WRITE); |
| 113 | return native_executeInsert(); |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 114 | } finally { |
| 115 | releaseAndUnlock(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 116 | } |
| 117 | } |
| 118 | |
Vasu Nori | 16057fa | 2011-03-18 11:40:37 -0700 | [diff] [blame] | 119 | private void saveSqlAsLastSqlStatement() { |
| 120 | if (((mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == |
| 121 | DatabaseUtils.STATEMENT_UPDATE) || |
| 122 | (mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == |
| 123 | DatabaseUtils.STATEMENT_BEGIN) { |
| 124 | mDatabase.setLastSqlStatement(mSql); |
| 125 | } |
| 126 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 127 | /** |
| 128 | * Execute a statement that returns a 1 by 1 table with a numeric value. |
| 129 | * For example, SELECT COUNT(*) FROM table; |
| 130 | * |
| 131 | * @return The result of the query. |
| 132 | * |
| 133 | * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows |
| 134 | */ |
| 135 | public long simpleQueryForLong() { |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 136 | try { |
| 137 | long timeStart = acquireAndLock(READ); |
| 138 | long retValue = native_1x1_long(); |
| 139 | mDatabase.logTimeStat(mSql, timeStart); |
| 140 | return retValue; |
Vasu Nori | 3045bba | 2011-01-10 14:29:04 -0800 | [diff] [blame] | 141 | } catch (SQLiteDoneException e) { |
| 142 | throw new SQLiteDoneException( |
| 143 | "expected 1 row from this query but query returned no data. check the query: " + |
| 144 | mSql); |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 145 | } finally { |
| 146 | releaseAndUnlock(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 147 | } |
| 148 | } |
| 149 | |
| 150 | /** |
| 151 | * Execute a statement that returns a 1 by 1 table with a text value. |
| 152 | * For example, SELECT COUNT(*) FROM table; |
| 153 | * |
| 154 | * @return The result of the query. |
| 155 | * |
| 156 | * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows |
| 157 | */ |
| 158 | public String simpleQueryForString() { |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 159 | try { |
| 160 | long timeStart = acquireAndLock(READ); |
| 161 | String retValue = native_1x1_string(); |
| 162 | mDatabase.logTimeStat(mSql, timeStart); |
| 163 | return retValue; |
Vasu Nori | 3045bba | 2011-01-10 14:29:04 -0800 | [diff] [blame] | 164 | } catch (SQLiteDoneException e) { |
| 165 | throw new SQLiteDoneException( |
| 166 | "expected 1 row from this query but query returned no data. check the query: " + |
| 167 | mSql); |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 168 | } finally { |
| 169 | releaseAndUnlock(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 170 | } |
| 171 | } |
| 172 | |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 173 | /** |
Bjorn Bringert | a006b472 | 2010-04-14 14:43:26 +0100 | [diff] [blame] | 174 | * Executes a statement that returns a 1 by 1 table with a blob value. |
| 175 | * |
| 176 | * @return A read-only file descriptor for a copy of the blob value, or {@code null} |
| 177 | * if the value is null or could not be read for some reason. |
| 178 | * |
| 179 | * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows |
| 180 | */ |
| 181 | public ParcelFileDescriptor simpleQueryForBlobFileDescriptor() { |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 182 | try { |
| 183 | long timeStart = acquireAndLock(READ); |
| 184 | ParcelFileDescriptor retValue = native_1x1_blob_ashmem(); |
| 185 | mDatabase.logTimeStat(mSql, timeStart); |
| 186 | return retValue; |
| 187 | } catch (IOException ex) { |
| 188 | Log.e(TAG, "simpleQueryForBlobFileDescriptor() failed", ex); |
| 189 | return null; |
Vasu Nori | 3045bba | 2011-01-10 14:29:04 -0800 | [diff] [blame] | 190 | } catch (SQLiteDoneException e) { |
| 191 | throw new SQLiteDoneException( |
| 192 | "expected 1 row from this query but query returned no data. check the query: " + |
| 193 | mSql); |
Vasu Nori | 2467561 | 2010-09-27 14:54:19 -0700 | [diff] [blame] | 194 | } finally { |
| 195 | releaseAndUnlock(); |
Bjorn Bringert | a006b472 | 2010-04-14 14:43:26 +0100 | [diff] [blame] | 196 | } |
| 197 | } |
| 198 | |
| 199 | /** |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 200 | * Called before every method in this class before executing a SQL statement, |
| 201 | * this method does the following: |
| 202 | * <ul> |
| 203 | * <li>make sure the database is open</li> |
Vasu Nori | e25539f | 2010-07-08 17:06:13 -0700 | [diff] [blame] | 204 | * <li>get a database connection from the connection pool,if possible</li> |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 205 | * <li>notifies {@link BlockGuard} of read/write</li> |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 206 | * <li>if the SQL statement is an update, start transaction if not already in one. |
| 207 | * otherwise, get lock on the database</li> |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 208 | * <li>acquire reference on this object</li> |
Vasu Nori | 16057fa | 2011-03-18 11:40:37 -0700 | [diff] [blame] | 209 | * <li>and then return the current time _after_ the database lock was acquired</li> |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 210 | * </ul> |
| 211 | * <p> |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 212 | * This method removes the duplicate code from the other public |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 213 | * methods in this class. |
| 214 | */ |
| 215 | private long acquireAndLock(boolean rwFlag) { |
Vasu Nori | 0732f79 | 2010-07-29 17:24:12 -0700 | [diff] [blame] | 216 | mState = 0; |
Vasu Nori | e25539f | 2010-07-08 17:06:13 -0700 | [diff] [blame] | 217 | // use pooled database connection handles for SELECT SQL statements |
| 218 | mDatabase.verifyDbIsOpen(); |
Vasu Nori | 4e874ed | 2010-09-15 18:40:49 -0700 | [diff] [blame] | 219 | SQLiteDatabase db = ((mStatementType & SQLiteProgram.STATEMENT_USE_POOLED_CONN) > 0) |
| 220 | ? mDatabase.getDbConnection(mSql) : mDatabase; |
Vasu Nori | e25539f | 2010-07-08 17:06:13 -0700 | [diff] [blame] | 221 | // use the database connection obtained above |
| 222 | mOrigDb = mDatabase; |
| 223 | mDatabase = db; |
Vasu Nori | 1966632 | 2010-09-10 14:09:00 -0700 | [diff] [blame] | 224 | setNativeHandle(mDatabase.mNativeHandle); |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 225 | if (rwFlag == WRITE) { |
| 226 | BlockGuard.getThreadPolicy().onWriteToDisk(); |
| 227 | } else { |
| 228 | BlockGuard.getThreadPolicy().onReadFromDisk(); |
| 229 | } |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 230 | |
| 231 | /* |
| 232 | * Special case handling of SQLiteDatabase.execSQL("BEGIN transaction"). |
| 233 | * we know it is execSQL("BEGIN transaction") from the caller IF there is no lock held. |
| 234 | * beginTransaction() methods in SQLiteDatabase call lockForced() before |
| 235 | * calling execSQL("BEGIN transaction"). |
| 236 | */ |
Vasu Nori | 4e874ed | 2010-09-15 18:40:49 -0700 | [diff] [blame] | 237 | if ((mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == DatabaseUtils.STATEMENT_BEGIN) { |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 238 | if (!mDatabase.isDbLockedByCurrentThread()) { |
| 239 | // transaction is NOT started by calling beginTransaction() methods in |
| 240 | // SQLiteDatabase |
| 241 | mDatabase.setTransactionUsingExecSqlFlag(); |
| 242 | } |
Vasu Nori | 4e874ed | 2010-09-15 18:40:49 -0700 | [diff] [blame] | 243 | } else if ((mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == |
| 244 | DatabaseUtils.STATEMENT_UPDATE) { |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 245 | // got update SQL statement. if there is NO pending transaction, start one |
| 246 | if (!mDatabase.inTransaction()) { |
| 247 | mDatabase.beginTransactionNonExclusive(); |
Vasu Nori | 0732f79 | 2010-07-29 17:24:12 -0700 | [diff] [blame] | 248 | mState = TRANS_STARTED; |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 249 | } |
| 250 | } |
| 251 | // do I have database lock? if not, grab it. |
| 252 | if (!mDatabase.isDbLockedByCurrentThread()) { |
Vasu Nori | 16057fa | 2011-03-18 11:40:37 -0700 | [diff] [blame] | 253 | mDatabase.lock(mSql); |
Vasu Nori | 0732f79 | 2010-07-29 17:24:12 -0700 | [diff] [blame] | 254 | mState = LOCK_ACQUIRED; |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 255 | } |
| 256 | |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 257 | acquireReference(); |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 258 | long startTime = SystemClock.uptimeMillis(); |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 259 | mDatabase.closePendingStatements(); |
Vasu Nori | e25539f | 2010-07-08 17:06:13 -0700 | [diff] [blame] | 260 | compileAndbindAllArgs(); |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 261 | return startTime; |
| 262 | } |
| 263 | |
| 264 | /** |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 265 | * this method releases locks and references acquired in {@link #acquireAndLock(boolean)} |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 266 | */ |
| 267 | private void releaseAndUnlock() { |
| 268 | releaseReference(); |
Vasu Nori | 0732f79 | 2010-07-29 17:24:12 -0700 | [diff] [blame] | 269 | if (mState == TRANS_STARTED) { |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 270 | try { |
| 271 | mDatabase.setTransactionSuccessful(); |
| 272 | } finally { |
| 273 | mDatabase.endTransaction(); |
| 274 | } |
Vasu Nori | 0732f79 | 2010-07-29 17:24:12 -0700 | [diff] [blame] | 275 | } else if (mState == LOCK_ACQUIRED) { |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 276 | mDatabase.unlock(); |
| 277 | } |
Vasu Nori | 4e874ed | 2010-09-15 18:40:49 -0700 | [diff] [blame] | 278 | if ((mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == |
| 279 | DatabaseUtils.STATEMENT_COMMIT || |
| 280 | (mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == |
| 281 | DatabaseUtils.STATEMENT_ABORT) { |
Vasu Nori | ce38b98 | 2010-07-22 13:57:13 -0700 | [diff] [blame] | 282 | mDatabase.resetTransactionUsingExecSqlFlag(); |
| 283 | } |
Vasu Nori | 2827d6d | 2010-07-04 00:26:18 -0700 | [diff] [blame] | 284 | clearBindings(); |
| 285 | // release the compiled sql statement so that the caller's SQLiteStatement no longer |
| 286 | // has a hard reference to a database object that may get deallocated at any point. |
Vasu Nori | cc6f549 | 2010-08-23 17:05:25 -0700 | [diff] [blame] | 287 | release(); |
Vasu Nori | e25539f | 2010-07-08 17:06:13 -0700 | [diff] [blame] | 288 | // restore the database connection handle to the original value |
| 289 | mDatabase = mOrigDb; |
Vasu Nori | 1966632 | 2010-09-10 14:09:00 -0700 | [diff] [blame] | 290 | setNativeHandle(mDatabase.mNativeHandle); |
Vasu Nori | 7501010 | 2010-07-01 16:23:06 -0700 | [diff] [blame] | 291 | } |
| 292 | |
Vasu Nori | fb16cbd | 2010-07-25 16:38:48 -0700 | [diff] [blame] | 293 | private final native int native_execute(); |
| 294 | private final native long native_executeInsert(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 295 | private final native long native_1x1_long(); |
| 296 | private final native String native_1x1_string(); |
Bjorn Bringert | a006b472 | 2010-04-14 14:43:26 +0100 | [diff] [blame] | 297 | private final native ParcelFileDescriptor native_1x1_blob_ashmem() throws IOException; |
Vasu Nori | 4e874ed | 2010-09-15 18:40:49 -0700 | [diff] [blame] | 298 | private final native void native_executeSql(String sql); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 299 | } |