之前測試了Sqlite 加密的 .so file & command line testing utility 後, 現在要來修改 Java 端的 API 了 , 讓我們的 APP 可以使用 !!
加密就是為了不讓其他APP可以任意使用,所以也不會和標準相容啦 !!
開始一步步來修改吧 !
A.大部份database 操作都由 SQLiteOpenHelper class 開始.
一般都由 SQLiteDatabase.getReadableDatabase() 來開始 Database file.
我們就增加一個 SQLiteDatabase.getReadableEncryDB(String key) ,
可以帶密碼的 function 開始, Java 支援多型態 ,所以修正
getDatabaseLocked(boolean writable) 為
getDatabaseLocked(boolean writable,String key) ,並且保留原來的,整個
SQLiteOpenHelper.java 的 diff 如下:
diff -Nura TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/java/android/database/sqlite/SQLiteOpenHelper.java TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/java/android/database/sqlite/SQLiteOpenHelper.java
--- TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/java/android/database/sqlite/SQLiteOpenHelper.java 2012-12-17 15:18:27.000000000 +0800
+++ TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/java/android/database/sqlite/SQLiteOpenHelper.java 2013-06-14 13:24:10.974298336 +0800
@@ -183,13 +183,29 @@
* @return a database object valid until {@link #getWritableDatabase}
* or {@link #close} is called.
*/
- public SQLiteDatabase getReadableDatabase() {
- synchronized (this) {
+ public SQLiteDatabase getReadableDatabase()
+ {
+ synchronized (this)
+ {
return getDatabaseLocked(false);
}
}
- private SQLiteDatabase getDatabaseLocked(boolean writable) {
+ public SQLiteDatabase getReadableEncryDB(String key)
+ {
+ synchronized (this)
+ {
+ return getDatabaseLocked(false,key);
+ }
+ }
+
+ private SQLiteDatabase getDatabaseLocked(boolean writable)
+ {
+ return getDatabaseLocked(writable,null);
+ }
+
+ private SQLiteDatabase getDatabaseLocked(boolean writable,String key)
+ {
if (mDatabase != null) {
if (!mDatabase.isOpen()) {
// Darn! The user closed the database by calling mDatabase.close().
@@ -205,7 +221,8 @@
}
SQLiteDatabase db = mDatabase;
- try {
+ try
+ {
mIsInitializing = true;
if (db != null) {
@@ -215,54 +232,78 @@
} else if (mName == null) {
db = SQLiteDatabase.create(null);
} else {
- try {
- if (DEBUG_STRICT_READONLY && !writable) {
+ try
+ {
+ if (DEBUG_STRICT_READONLY && !writable)
+ {
final String path = mContext.getDatabasePath(mName).getPath();
- db = SQLiteDatabase.openDatabase(path, mFactory,
+ if ( key != null )
+ db = SQLiteDatabase.openDatabase(path, mFactory,
SQLiteDatabase.OPEN_READONLY, mErrorHandler);
- } else {
- db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
- Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
- mFactory, mErrorHandler);
+ else
+ db = SQLiteDatabase.openDatabase(path, mFactory,
+ SQLiteDatabase.OPEN_READONLY, key, mErrorHandler);
+ }
+ else
+ {
+ db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
+ Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
+ mFactory,key, mErrorHandler);
}
- } catch (SQLiteException ex) {
- if (writable) {
+ }
+ catch (SQLiteException ex)
+ {
+ if (writable)
+ {
throw ex;
}
+
Log.e(TAG, "Couldn't open " + mName
+ " for writing (will try read-only):", ex);
final String path = mContext.getDatabasePath(mName).getPath();
- db = SQLiteDatabase.openDatabase(path, mFactory,
- SQLiteDatabase.OPEN_READONLY, mErrorHandler);
+ db = SQLiteDatabase.openDatabase(path, mFactory,
+ SQLiteDatabase.OPEN_READONLY,key, mErrorHandler);
}
}
onConfigure(db);
- final int version = db.getVersion();
- if (version != mNewVersion) {
- if (db.isReadOnly()) {
- throw new SQLiteException("Can't upgrade read-only database from version " +
- db.getVersion() + " to " + mNewVersion + ": " + mName);
- }
-
- db.beginTransaction();
- try {
- if (version == 0) {
- onCreate(db);
- } else {
- if (version > mNewVersion) {
- onDowngrade(db, version, mNewVersion);
- } else {
- onUpgrade(db, version, mNewVersion);
- }
- }
- db.setVersion(mNewVersion);
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
- }
+ final int version = db.getVersion();
+ if (version != mNewVersion)
+ {
+ if (db.isReadOnly())
+ {
+ throw new SQLiteException("Can't upgrade read-only database from version " +
+ db.getVersion() + " to " + mNewVersion + ": " + mName);
+ }
+
+ db.beginTransaction();
+ try
+ {
+ if (version == 0)
+ {
+ onCreate(db);
+ }
+ else
+ {
+ if (version > mNewVersion)
+ {
+ onDowngrade(db, version, mNewVersion);
+ }
+ else
+ {
+ onUpgrade(db, version, mNewVersion);
+ }
+ }
+
+ db.setVersion(mNewVersion);
+ db.setTransactionSuccessful();
+ }
+ finally
+ {
+ db.endTransaction();
+ }
+ }
onOpen(db);
@@ -272,7 +313,9 @@
mDatabase = db;
return db;
- } finally {
+ }
+ finally
+ {
mIsInitializing = false;
if (db != null && db != mDatabase) {
db.close();
@@ -283,10 +326,13 @@
/**
* Close any open database object.
*/
- public synchronized void close() {
+ public synchronized void close()
+ {
+
if (mIsInitializing) throw new IllegalStateException("Closed during initialization");
- if (mDatabase != null && mDatabase.isOpen()) {
+ if (mDatabase != null && mDatabase.isOpen())
+ {
mDatabase.close();
mDatabase = null;
}
B.接著會啟動SQLiteDatebase.java 中的 openDatabase() ,相同的,也將 password(key)
帶入, 整個 java 的 diff 如下:
diff -Nura TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/java/android/database/sqlite/SQLiteDatabase.java TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/java/android/database/sqlite/SQLiteDatabase.java
--- TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/java/android/database/sqlite/SQLiteDatabase.java 2012-12-17 15:18:27.000000000 +0800
+++ TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/java/android/database/sqlite/SQLiteDatabase.java 2013-06-14 13:22:52.593677892 +0800
@@ -251,11 +251,13 @@
*/
public static final int MAX_SQL_CACHE_SIZE = 100;
- private SQLiteDatabase(String path, int openFlags, CursorFactory cursorFactory,
- DatabaseErrorHandler errorHandler) {
+
+ private SQLiteDatabase(String path, int openFlags, CursorFactory cursorFactory, String key,
+ DatabaseErrorHandler errorHandler)
+ {
mCursorFactory = cursorFactory;
mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
- mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
+ mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags,key);
}
@Override
@@ -689,11 +691,18 @@
* @throws SQLiteException if the database cannot be opened
*/
public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags,
- DatabaseErrorHandler errorHandler) {
- SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler);
+ DatabaseErrorHandler errorHandler)
+ {
+ return openDatabase(path, factory, flags, null,errorHandler);
+ }
+
+ public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags,String key ,
+ DatabaseErrorHandler errorHandler)
+ {
+ SQLiteDatabase db = new SQLiteDatabase(path, flags, factory,key, errorHandler);
db.open();
return db;
- }
+ }
/**
* Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
@@ -783,29 +792,39 @@
}
}
- private void open() {
- try {
- try {
+ private void open()
+ {
+ try
+ {
+ try
+ {
openInner();
- } catch (SQLiteDatabaseCorruptException ex) {
+ }
+ catch (SQLiteDatabaseCorruptException ex)
+ {
onCorruption();
openInner();
}
- } catch (SQLiteException ex) {
+ }
+ catch (SQLiteException ex)
+ {
Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex);
close();
throw ex;
}
}
- private void openInner() {
- synchronized (mLock) {
+ private void openInner()
+ {
+ synchronized (mLock)
+ {
assert mConnectionPoolLocked == null;
mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
mCloseGuardLocked.open("close");
}
- synchronized (sActiveDatabases) {
+ synchronized (sActiveDatabases)
+ {
sActiveDatabases.put(this, null);
}
}
@@ -1713,7 +1732,7 @@
* Returns true if the new version code is greater than the current database version.
*
* @param newVersion The new version code.
- * @return True if the new version code is greater than the current database version.
+ * @return True if the new version code is greater than the current database version.
*/
public boolean needUpgrade(int newVersion) {
return newVersion > getVersion();
C. openDatabase 會 new SQLiteDatabaseConfigureation , 接著我們在這裡多
一個變數 key , 來存放 password.
diff 如下:
diff -Nura TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
--- TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java 2012-12-17 15:18:27.000000000 +0800
+++ TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java 2013-06-07 15:45:13.818910296 +0800
@@ -45,6 +45,8 @@
*/
public static final String MEMORY_DB_PATH = ":memory:";
+ public final String key;
+
/**
* The database path.
*/
@@ -96,11 +98,31 @@
* @param path The database path.
* @param openFlags Open flags for the database, such as {@link SQLiteDatabase#OPEN_READWRITE}.
*/
- public SQLiteDatabaseConfiguration(String path, int openFlags) {
+ public SQLiteDatabaseConfiguration(String path, int openFlags)
+ {
+ if (path == null) {
+ throw new IllegalArgumentException("path must not be null.");
+ }
+
+ this.key = null;
+
+ this.path = path;
+ label = stripPathForLogs(path);
+ this.openFlags = openFlags;
+
+ // Set default values for optional parameters.
+ maxSqlCacheSize = 25;
+ locale = Locale.getDefault();
+ }
+
+ public SQLiteDatabaseConfiguration(String path, int openFlags,String key)
+ {
if (path == null) {
throw new IllegalArgumentException("path must not be null.");
}
+ this.key = key;
+
this.path = path;
label = stripPathForLogs(path);
this.openFlags = openFlags;
@@ -120,6 +142,7 @@
throw new IllegalArgumentException("other must not be null.");
}
+ this.key = other.key;
this.path = other.path;
this.label = other.label;
updateParametersFrom(other);
D.整個 database open 過程最後回來到 SQLiteConnection.java 中 , 並且呼叫
nativeOpen() , 這個是 JNI Function.
我們在 open function 內將剛存在 Configure 內的 Password 一起帶給 nativeOpen().
在這個 class 中,我們多設定了一個 rekey() function , 這是預留,目前並不打算有rekey
的功能 , diff file 如下:
diff -Nura TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/java/android/database/sqlite/SQLiteConnection.java TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/java/android/database/sqlite/SQLiteConnection.java
--- TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/java/android/database/sqlite/SQLiteConnection.java 2012-12-17 15:18:27.000000000 +0800
+++ TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/java/android/database/sqlite/SQLiteConnection.java 2013-06-14 13:21:50.396218106 +0800
@@ -117,8 +117,9 @@
// we can ensure that we detach the signal at the right time.
private int mCancellationSignalAttachCount;
- private static native int nativeOpen(String path, int openFlags, String label,
+ private static native int nativeOpen(String path, int openFlags, String label,String key,
boolean enableTrace, boolean enableProfile);
+
private static native void nativeClose(int connectionPtr);
private static native void nativeRegisterCustomFunction(int connectionPtr,
SQLiteCustomFunction function);
@@ -157,9 +158,13 @@
private static native void nativeCancel(int connectionPtr);
private static native void nativeResetCancel(int connectionPtr, boolean cancelable);
+ private static native int nativeReKey(int connectionPtr,String key);
+
+
private SQLiteConnection(SQLiteConnectionPool pool,
SQLiteDatabaseConfiguration configuration,
- int connectionId, boolean primaryConnection) {
+ int connectionId, boolean primaryConnection)
+ {
mPool = pool;
mConfiguration = new SQLiteDatabaseConfiguration(configuration);
mConnectionId = connectionId;
@@ -186,13 +191,17 @@
// Called by SQLiteConnectionPool only.
static SQLiteConnection open(SQLiteConnectionPool pool,
SQLiteDatabaseConfiguration configuration,
- int connectionId, boolean primaryConnection) {
+ int connectionId, boolean primaryConnection)
+ {
SQLiteConnection connection = new SQLiteConnection(pool, configuration,
connectionId, primaryConnection);
- try {
+ try
+ {
connection.open();
return connection;
- } catch (SQLiteException ex) {
+ }
+ catch (SQLiteException ex)
+ {
connection.dispose(false);
throw ex;
}
@@ -205,12 +214,13 @@
dispose(false);
}
- private void open() {
+ private void open()
+ {
mConnectionPtr = nativeOpen(mConfiguration.path, mConfiguration.openFlags,
- mConfiguration.label,
+ mConfiguration.label,mConfiguration.key,
SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME);
- setPageSize();
+ setPageSize();
setForeignKeyModeFromConfiguration();
setWalModeFromConfiguration();
setJournalSizeLimit();
@@ -218,6 +228,13 @@
setLocaleFromConfiguration();
}
+ public void db_rekey(String key)
+ {
+ Log.e(TAG, "db_rekey() , Not finish ...... ");
+ }
+
+
+
private void dispose(boolean finalized) {
if (mCloseGuard != null) {
if (finalized) {
@@ -239,10 +256,12 @@
}
private void setPageSize() {
- if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
+ if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection)
+ {
final long newValue = SQLiteGlobal.getDefaultPageSize();
long value = executeForLong("PRAGMA page_size", null, null);
- if (value != newValue) {
+ if (value != newValue)
+ {
execute("PRAGMA page_size=" + newValue, null, null);
}
}
@@ -268,11 +287,14 @@
}
}
- private void setForeignKeyModeFromConfiguration() {
- if (!mIsReadOnlyConnection) {
+ private void setForeignKeyModeFromConfiguration()
+ {
+ if (!mIsReadOnlyConnection)
+ {
final long newValue = mConfiguration.foreignKeyConstraintsEnabled ? 1 : 0;
long value = executeForLong("PRAGMA foreign_keys", null, null);
- if (value != newValue) {
+ if (value != newValue)
+ {
execute("PRAGMA foreign_keys=" + newValue, null, null);
}
}
@@ -901,17 +923,23 @@
return statement;
}
- private void releasePreparedStatement(PreparedStatement statement) {
+ private void releasePreparedStatement(PreparedStatement statement)
+ {
statement.mInUse = false;
- if (statement.mInCache) {
- try {
+ if (statement.mInCache)
+ {
+ try
+ {
nativeResetStatementAndClearBindings(mConnectionPtr, statement.mStatementPtr);
- } catch (SQLiteException ex) {
+ }
+ catch (SQLiteException ex)
+ {
// The statement could not be reset due to an error. Remove it from the cache.
// When remove() is called, the cache will invoke its entryRemoved() callback,
// which will in turn call finalizePreparedStatement() to finalize and
// recycle the statement.
- if (DEBUG) {
+ if (DEBUG)
+ {
Log.d(TAG, "Could not reset prepared statement due to an exception. "
+ "Removing it from the cache. SQL: "
+ trimSqlForDisplay(statement.mSql), ex);
@@ -919,7 +947,9 @@
mPreparedStatementCache.remove(statement.mSql);
}
- } else {
+ }
+ else
+ {
finalizePreparedStatement(statement);
}
}
@@ -1240,7 +1270,8 @@
}
private final class PreparedStatementCache
- extends LruCache<String, PreparedStatement> {
+ extends LruCache<String, PreparedStatement>
+ {
public PreparedStatementCache(int size) {
super(size);
}
E.進入JNI CPP 階段 , 一樣宣告一個 rekey function 預留, 因為設定key 需要在
sqlite3_open_v2 後馬上執行sqlite3_key 不然執行任何動作都會導致 超操作失敗.
所以在 nativeOpen 中馬上檢查 key 是否 NULL , 如果不是就執行 sqlite3_key.
當然要修改 Android.mk file 增加SQLITE_HAS_CODEC , 這樣才有 sqlite3_key
Function.
Androdi.mk & SQLiteConnection.cpp 的 diff 如下:
diff -Nura TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/jni/android_database_SQLiteConnection.cpp TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/jni/android_database_SQLiteConnection.cpp
--- TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/jni/android_database_SQLiteConnection.cpp 2012-12-17 15:18:28.000000000 +0800
+++ TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/jni/android_database_SQLiteConnection.cpp 2013-06-14 13:30:11.300238584 +0800
@@ -109,13 +109,20 @@
static jint nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFlags,
- jstring labelStr, jboolean enableTrace, jboolean enableProfile) {
- int sqliteFlags;
- if (openFlags & SQLiteConnection::CREATE_IF_NECESSARY) {
+ jstring labelStr,jstring keyStr, jboolean enableTrace, jboolean enableProfile)
+{
+int sqliteFlags;
+
+ if (openFlags & SQLiteConnection::CREATE_IF_NECESSARY)
+ {
sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
- } else if (openFlags & SQLiteConnection::OPEN_READONLY) {
+ }
+ else if (openFlags & SQLiteConnection::OPEN_READONLY)
+ {
sqliteFlags = SQLITE_OPEN_READONLY;
- } else {
+ }
+ else
+ {
sqliteFlags = SQLITE_OPEN_READWRITE;
}
@@ -129,13 +136,39 @@
sqlite3* db;
int err = sqlite3_open_v2(path.string(), &db, sqliteFlags, NULL);
- if (err != SQLITE_OK) {
+ if (err != SQLITE_OK)
+ {
throw_sqlite3_exception_errcode(env, err, "Could not open database");
return 0;
}
+#ifdef SQLITE_HAS_CODEC
+
+ if ( keyStr != NULL)
+ {
+ const char* keyChars = env->GetStringUTFChars(keyStr, NULL);
+ String8 key(keyChars);
+ env->ReleaseStringUTFChars(keyStr, keyChars);
+
+ int nkey = strlen (key.string());
+
+ err = sqlite3_key(db, key.string(), nkey);
+ if (err != SQLITE_OK)
+ {
+ ALOGE("sqlite3_key failed: %d", err);
+ throw_sqlite3_exception_errcode(env, err, "Key error ! Count not Access db.");
+ return 0;
+ }
+
+
+ }
+
+#endif
+
// Check that the database is really read/write when that is what we asked for.
- if ((sqliteFlags & SQLITE_OPEN_READWRITE) && sqlite3_db_readonly(db, NULL)) {
+ if ((sqliteFlags & SQLITE_OPEN_READWRITE) && sqlite3_db_readonly(db, NULL))
+ {
throw_sqlite3_exception(env, db, "Could not open the database in read/write mode.");
sqlite3_close(db);
return 0;
@@ -143,7 +176,8 @@
// Set the default busy handler to retry automatically before returning SQLITE_BUSY.
err = sqlite3_busy_timeout(db, BUSY_TIMEOUT_MS);
- if (err != SQLITE_OK) {
+ if (err != SQLITE_OK)
+ {
throw_sqlite3_exception(env, db, "Could not set busy timeout");
sqlite3_close(db);
return 0;
@@ -151,7 +185,8 @@
// Register custom Android functions.
err = register_android_functions(db, UTF16_STORAGE);
- if (err) {
+ if (err)
+ {
throw_sqlite3_exception(env, db, "Could not register Android SQL functions.");
sqlite3_close(db);
return 0;
@@ -161,10 +196,12 @@
SQLiteConnection* connection = new SQLiteConnection(db, openFlags, path, label);
// Enable tracing and profiling if requested.
- if (enableTrace) {
+ if (enableTrace)
+ {
sqlite3_trace(db, &sqliteTraceCallback, connection);
}
- if (enableProfile) {
+ if (enableProfile)
+ {
sqlite3_profile(db, &sqliteProfileCallback, connection);
}
@@ -172,13 +209,17 @@
return reinterpret_cast<jint>(connection);
}
-static void nativeClose(JNIEnv* env, jclass clazz, jint connectionPtr) {
+static void nativeClose(JNIEnv* env, jclass clazz, jint connectionPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
- if (connection) {
+ if (connection)
+ {
+ sync();
ALOGV("Closing connection %p", connection->db);
int err = sqlite3_close(connection->db);
- if (err != SQLITE_OK) {
+ if (err != SQLITE_OK)
+ {
// This can happen if sub-objects aren't closed first. Make sure the caller knows.
ALOGE("sqlite3_close(%p) failed: %d", connection->db, err);
throw_sqlite3_exception(env, connection->db, "Count not close db.");
@@ -191,7 +232,8 @@
// Called each time a custom function is evaluated.
static void sqliteCustomFunctionCallback(sqlite3_context *context,
- int argc, sqlite3_value **argv) {
+ int argc, sqlite3_value **argv)
+{
JNIEnv* env = AndroidRuntime::getJNIEnv();
// Get the callback function object.
@@ -235,7 +277,8 @@
}
// Called when a custom function is destroyed.
-static void sqliteCustomFunctionDestructor(void* data) {
+static void sqliteCustomFunctionDestructor(void* data)
+{
jobject functionObjGlobal = reinterpret_cast<jobject>(data);
JNIEnv* env = AndroidRuntime::getJNIEnv();
@@ -243,7 +286,8 @@
}
static void nativeRegisterCustomFunction(JNIEnv* env, jclass clazz, jint connectionPtr,
- jobject functionObj) {
+ jobject functionObj)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
jstring nameStr = jstring(env->GetObjectField(
@@ -267,7 +311,8 @@
}
static void nativeRegisterLocalizedCollators(JNIEnv* env, jclass clazz, jint connectionPtr,
- jstring localeStr) {
+ jstring localeStr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
const char* locale = env->GetStringUTFChars(localeStr, NULL);
@@ -280,20 +325,25 @@
}
static jint nativePrepareStatement(JNIEnv* env, jclass clazz, jint connectionPtr,
- jstring sqlString) {
- SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
-
- jsize sqlLength = env->GetStringLength(sqlString);
- const jchar* sql = env->GetStringCritical(sqlString, NULL);
- sqlite3_stmt* statement;
- int err = sqlite3_prepare16_v2(connection->db,
- sql, sqlLength * sizeof(jchar), &statement, NULL);
- env->ReleaseStringCritical(sqlString, sql);
-
- if (err != SQLITE_OK) {
- // Error messages like 'near ")": syntax error' are not
- // always helpful enough, so construct an error string that
- // includes the query itself.
+ jstring sqlString)
+{
+SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
+int err = -1 ;
+sqlite3_stmt* statement;
+
+ jsize sqlLength = env->GetStringLength(sqlString);
+ const jchar* sql = env->GetStringCritical(sqlString, NULL);
+
+ err = sqlite3_prepare16_v2(connection->db,
+ sql, sqlLength * sizeof(jchar), &statement, NULL);
+
+ env->ReleaseStringCritical(sqlString, sql);
+
+ if (err != SQLITE_OK)
+ {
+ // Error messages like 'near ")": syntax error' are not
+ // always helpful enough, so construct an error string that
+ // includes the query itself.
const char *query = env->GetStringUTFChars(sqlString, NULL);
char *message = (char*) malloc(strlen(query) + 50);
if (message) {
@@ -311,7 +361,8 @@
}
static void nativeFinalizeStatement(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr) {
+ jint statementPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -323,7 +374,8 @@
}
static jint nativeGetParameterCount(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr) {
+ jint statementPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -331,7 +383,8 @@
}
static jboolean nativeIsReadOnly(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr) {
+ jint statementPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -339,7 +392,8 @@
}
static jint nativeGetColumnCount(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr) {
+ jint statementPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -347,7 +401,8 @@
}
static jstring nativeGetColumnName(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr, jint index) {
+ jint statementPtr, jint index)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -363,7 +418,8 @@
}
static void nativeBindNull(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr, jint index) {
+ jint statementPtr, jint index)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -374,7 +430,8 @@
}
static void nativeBindLong(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr, jint index, jlong value) {
+ jint statementPtr, jint index, jlong value)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -385,7 +442,8 @@
}
static void nativeBindDouble(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr, jint index, jdouble value) {
+ jint statementPtr, jint index, jdouble value)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -396,7 +454,8 @@
}
static void nativeBindString(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr, jint index, jstring valueString) {
+ jint statementPtr, jint index, jstring valueString)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -411,7 +470,8 @@
}
static void nativeBindBlob(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr, jint index, jbyteArray valueArray) {
+ jint statementPtr, jint index, jbyteArray valueArray)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -425,7 +485,8 @@
}
static void nativeResetStatementAndClearBindings(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr) {
+ jint statementPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -438,7 +499,8 @@
}
}
-static int executeNonQuery(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement) {
+static int executeNonQuery(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement)
+{
int err = sqlite3_step(statement);
if (err == SQLITE_ROW) {
throw_sqlite3_exception(env,
@@ -450,7 +512,8 @@
}
static void nativeExecute(JNIEnv* env, jclass clazz, jint connectionPtr,
- jint statementPtr) {
+ jint statementPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -458,7 +521,8 @@
}
static jint nativeExecuteForChangedRowCount(JNIEnv* env, jclass clazz,
- jint connectionPtr, jint statementPtr) {
+ jint connectionPtr, jint statementPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -467,7 +531,8 @@
}
static jlong nativeExecuteForLastInsertedRowId(JNIEnv* env, jclass clazz,
- jint connectionPtr, jint statementPtr) {
+ jint connectionPtr, jint statementPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -476,7 +541,8 @@
? sqlite3_last_insert_rowid(connection->db) : -1;
}
-static int executeOneRowQuery(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement) {
+static int executeOneRowQuery(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement)
+{
int err = sqlite3_step(statement);
if (err != SQLITE_ROW) {
throw_sqlite3_exception(env, connection->db);
@@ -485,7 +551,8 @@
}
static jlong nativeExecuteForLong(JNIEnv* env, jclass clazz,
- jint connectionPtr, jint statementPtr) {
+ jint connectionPtr, jint statementPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -497,7 +564,8 @@
}
static jstring nativeExecuteForString(JNIEnv* env, jclass clazz,
- jint connectionPtr, jint statementPtr) {
+ jint connectionPtr, jint statementPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -512,7 +580,8 @@
return NULL;
}
-static int createAshmemRegionWithData(JNIEnv* env, const void* data, size_t length) {
+static int createAshmemRegionWithData(JNIEnv* env, const void* data, size_t length)
+{
int error = 0;
int fd = ashmem_create_region(NULL, length);
if (fd < 0) {
@@ -547,7 +616,8 @@
}
static jint nativeExecuteForBlobFileDescriptor(JNIEnv* env, jclass clazz,
- jint connectionPtr, jint statementPtr) {
+ jint connectionPtr, jint statementPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
@@ -571,7 +641,8 @@
};
static CopyRowResult copyRow(JNIEnv* env, CursorWindow* window,
- sqlite3_stmt* statement, int numColumns, int startPos, int addedRows) {
+ sqlite3_stmt* statement, int numColumns, int startPos, int addedRows)
+{
// Allocate a new field directory for the row.
status_t status = window->allocRow();
if (status) {
@@ -665,7 +736,8 @@
static jlong nativeExecuteForCursorWindow(JNIEnv* env, jclass clazz,
jint connectionPtr, jint statementPtr, jint windowPtr,
- jint startPos, jint requiredPos, jboolean countAllRows) {
+ jint startPos, jint requiredPos, jboolean countAllRows)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
@@ -759,7 +831,8 @@
return result;
}
-static jint nativeGetDbLookaside(JNIEnv* env, jobject clazz, jint connectionPtr) {
+static jint nativeGetDbLookaside(JNIEnv* env, jobject clazz, jint connectionPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
int cur = -1;
@@ -768,13 +841,15 @@
return cur;
}
-static void nativeCancel(JNIEnv* env, jobject clazz, jint connectionPtr) {
+static void nativeCancel(JNIEnv* env, jobject clazz, jint connectionPtr)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
connection->canceled = true;
}
static void nativeResetCancel(JNIEnv* env, jobject clazz, jint connectionPtr,
- jboolean cancelable) {
+ jboolean cancelable)
+{
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
connection->canceled = false;
@@ -787,10 +862,62 @@
}
+#ifdef SQLITE_HAS_CODEC
+
+static jint nativeReKey(JNIEnv* env, jclass clazz, jint connectionPtr,jstring key)
+{
+SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
+int err;
+int nkey;
+const char* key_str;
+
+ if (connection)
+ {
+ key_str = env->GetStringUTFChars(key, NULL);
+ nkey = strlen (key_str);
+
+ err = sqlite3_rekey(connection->db, key_str, nkey);
+ env->ReleaseStringUTFChars(key, key_str);
+
+ if (err != SQLITE_OK)
+ {
+ ALOGE("sqlite3_rekey(%p) failed: %d", connection->db, err);
+ throw_sqlite3_exception(env, connection->db, "Re Key error ! Count not Access db.");
+
+ //==== Try to close db.
+ err = sqlite3_close(connection->db);
+ if (err != SQLITE_OK)
+ {
+ ALOGE("sqlite3_close(%p) failed: %d", connection->db, err);
+ throw_sqlite3_exception(env, connection->db, "Count not close db.");
+ return 0;
+ }
+
+ delete connection;
+ return 0;
+
+ }
+ else
+ return reinterpret_cast<jint>(connection);
+ }
+
+ ALOGE("Sqlite DB Connection is fail.");
+ return 0;
+}
+
+#else
+
+static jint nativeReKey(JNIEnv* env, jclass clazz, jint connectionPtr,jstring key)
+{
+ return 0;
+}
+#endif
+
+
static JNINativeMethod sMethods[] =
{
/* name, signature, funcPtr */
- { "nativeOpen", "(Ljava/lang/String;ILjava/lang/String;ZZ)I",
+ { "nativeOpen", "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;ZZ)I",
(void*)nativeOpen },
{ "nativeClose", "(I)V",
(void*)nativeClose },
@@ -842,6 +969,10 @@
(void*)nativeCancel },
{ "nativeResetCancel", "(IZ)V",
(void*)nativeResetCancel },
+#ifdef SQLITE_HAS_CODEC
+ { "nativeReKey", "(ILjava/lang/String;)I",
+ (void*)nativeReKey },
+#endif
};
#define FIND_CLASS(var, className) \
diff -Nura TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/jni/Android.mk TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/jni/Android.mk
--- TI-Android-JB-4.1.2_AM335x_4.0.1-orignal/frameworks/base/core/jni/Android.mk 2012-12-17 15:18:28.000000000 +0800
+++ TI-Android-JB-4.1.2_AM335x_4.0.1/frameworks/base/core/jni/Android.mk 2013-06-13 10:13:15.811329249 +0800
@@ -1,9 +1,14 @@
+##
+##
+##
+
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CFLAGS += -DHAVE_CONFIG_H -DKHTML_NO_EXCEPTIONS -DGKWQ_NO_JAVA
LOCAL_CFLAGS += -DNO_SUPPORT_JS_BINDING -DQT_NO_WHEELEVENT -DKHTML_NO_XBL
LOCAL_CFLAGS += -U__APPLE__
+LOCAL_CFLAGS += -DSQLITE_HAS_CODEC
ifeq ($(TARGET_ARCH), arm)
LOCAL_CFLAGS += -DPACKED="__attribute__ ((packed))"
大功告成 ,並且可以讓簡單的 APP 開啟事先已經加密好的 database.db file .
PS. 上面內容會有錯誤(基於工作內容的關係 , 有些細節沒有說明 ) , 不過可以按照這樣的
步驟修改 , 並且逐步 debug .... 即可.
沒有留言:
張貼留言