diff --git a/CHANGELOG.md b/CHANGELOG.md index 12dd7aaa..8a9fd270 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## v3.4.2 (2015-05-13) + +### Fixed +* Fixed crash on sqlite cipher when loading and sending data too early + ## v3.4.1 (2015-05-12) ### Fixed diff --git a/samples/sense-android-demo/project.properties b/samples/sense-android-demo/project.properties index 7a75c940..44b79933 100644 --- a/samples/sense-android-demo/project.properties +++ b/samples/sense-android-demo/project.properties @@ -13,4 +13,4 @@ # Project target. target=android-16 android.library.reference.1=../../sense-android-library -android.library.reference.2=../../../google-play-services_lib_brightr +android.library.reference.2=../../../google-play-services_lib diff --git a/sense-android-library/AndroidManifest.xml b/sense-android-library/AndroidManifest.xml index c6bd015e..b392fcb6 100755 --- a/sense-android-library/AndroidManifest.xml +++ b/sense-android-library/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="3.4.2"> diff --git a/sense-android-library/libs/armeabi-v7a/libsqlcipher_android.so b/sense-android-library/libs/armeabi-v7a/libsqlcipher_android.so index c19a7c4d..ab8483a2 100755 Binary files a/sense-android-library/libs/armeabi-v7a/libsqlcipher_android.so and b/sense-android-library/libs/armeabi-v7a/libsqlcipher_android.so differ diff --git a/sense-android-library/libs/armeabi/libsqlcipher_android.so b/sense-android-library/libs/armeabi/libsqlcipher_android.so index d4d095c5..24619a43 100755 Binary files a/sense-android-library/libs/armeabi/libsqlcipher_android.so and b/sense-android-library/libs/armeabi/libsqlcipher_android.so differ diff --git a/sense-android-library/libs/sqlcipher.jar b/sense-android-library/libs/sqlcipher.jar index 4d91f837..293cce15 100644 Binary files a/sense-android-library/libs/sqlcipher.jar and b/sense-android-library/libs/sqlcipher.jar differ diff --git a/sense-android-library/libs/x86/libsqlcipher_android.so b/sense-android-library/libs/x86/libsqlcipher_android.so index 51620697..7c33f953 100755 Binary files a/sense-android-library/libs/x86/libsqlcipher_android.so and b/sense-android-library/libs/x86/libsqlcipher_android.so differ diff --git a/sense-android-library/src/nl/sense_os/service/SenseService.java b/sense-android-library/src/nl/sense_os/service/SenseService.java index 80eb14c6..b0abf0a3 100755 --- a/sense-android-library/src/nl/sense_os/service/SenseService.java +++ b/sense-android-library/src/nl/sense_os/service/SenseService.java @@ -43,6 +43,7 @@ import nl.sense_os.service.provider.SNTP; import nl.sense_os.service.scheduler.ScheduleAlarmTool; import nl.sense_os.service.subscription.SubscriptionManager; +import nl.sense_os.service.storage.LocalStorage; import org.json.JSONObject; @@ -135,6 +136,8 @@ public SenseServiceStub getService() { private AppInfoSensor appInfoSensor; private FusedLocationSensor fusedLocationListener; + private LocalStorage mLocalStorage; + /** * Handler on main application thread to display toasts to the user. */ @@ -334,6 +337,8 @@ public void onCreate() { Log.v(TAG, "Sense Platform service is being created"); state = ServiceStateHelper.getInstance(this); mSubscrMgr = SubscriptionManager.getInstance(); + // Create the instance to avoid concurrency problems in the SQLCipher lib + mLocalStorage = LocalStorage.getInstance(this); } /** diff --git a/sense-android-library/src/nl/sense_os/service/phonestate/AppInfoVersion.java b/sense-android-library/src/nl/sense_os/service/phonestate/AppInfoVersion.java index 38c141f1..b51eb8f6 100644 --- a/sense-android-library/src/nl/sense_os/service/phonestate/AppInfoVersion.java +++ b/sense-android-library/src/nl/sense_os/service/phonestate/AppInfoVersion.java @@ -2,6 +2,6 @@ public abstract class AppInfoVersion { - public final static String SENSE_LIBRARY_VERSION = "v3.4.1"; + public final static String SENSE_LIBRARY_VERSION = "v3.4.2"; public final static String CORTEX_VERSION = ""; } diff --git a/sense-android-library/src/nl/sense_os/service/storage/DbHelper.java b/sense-android-library/src/nl/sense_os/service/storage/DbHelper.java index bb127c03..f78472d8 100755 --- a/sense-android-library/src/nl/sense_os/service/storage/DbHelper.java +++ b/sense-android-library/src/nl/sense_os/service/storage/DbHelper.java @@ -1,20 +1,23 @@ package nl.sense_os.service.storage; -import nl.sense_os.service.constants.SensorData.DataPoint; -import nl.sense_os.service.constants.SensePrefs; -import nl.sense_os.service.constants.SensePrefs.Main.Advanced; import android.content.Context; import android.content.SharedPreferences; -import net.sqlcipher.database.SQLiteDatabase; -import net.sqlcipher.database.SQLiteOpenHelper; -import net.sqlcipher.database.SQLiteException; import android.provider.BaseColumns; -import android.util.Log; import android.telephony.TelephonyManager; +import android.util.Log; + +import net.sqlcipher.database.SQLiteDatabase; +import net.sqlcipher.database.SQLiteException; +import net.sqlcipher.database.SQLiteOpenHelper; + import java.io.File; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import nl.sense_os.service.constants.SensePrefs; +import nl.sense_os.service.constants.SensePrefs.Main.Advanced; +import nl.sense_os.service.constants.SensorData.DataPoint; + /** * Helper class that assist in creating, opening and managing the SQLite3 database for data points. */ @@ -41,8 +44,12 @@ public class DbHelper extends SQLiteOpenHelper { private static String passphrase = ""; + private static boolean libsLoaded = false; + private static final String TAG = "DbHelper"; + private Context mContext; + /** * Constructor. The database is not actually created or opened until one of * {@link #getWritableDatabase()} or {@link #getReadableDatabase()} is called. @@ -55,45 +62,44 @@ public class DbHelper extends SQLiteOpenHelper { public DbHelper(Context context, boolean persistent) { // if the database name is null, it will be created in-memory super(context, persistent ? DATABASE_NAME : null, null, DATABASE_VERSION); + this.mContext = context; if (null == sMainPrefs) { - sMainPrefs = context.getSharedPreferences(SensePrefs.MAIN_PREFS, - Context.MODE_PRIVATE); + sMainPrefs = mContext.getSharedPreferences(SensePrefs.MAIN_PREFS, + Context.MODE_PRIVATE); } + loadLibs(context); + updateEncryption(); + // add a listener to update the encryption settings when it changes + sMainPrefs.registerOnSharedPreferenceChangeListener(encryptionChanged); + } + public void updateEncryption() + { boolean encrypt = sMainPrefs.getBoolean(Advanced.ENCRYPT_DATABASE, false); - if (encrypt) { - TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); String imei = telephonyManager.getDeviceId(); - setPassphrase(imei); } + } - SQLiteDatabase.loadLibs(context); - - // check for old plain database - if (persistent && encrypt) { - // try to open the database with the password from the user. - // The only possible error now must be a wrong password or using plain database. - try { - getWritableDatabase(passphrase); - } catch (SQLiteException e) { - Log.v(TAG, "Trying to encrypte old plain database"); - File plain = context.getDatabasePath(DATABASE_NAME); - File encrypted = context.getDatabasePath("tmp.db"); - - // try to open the database without password - SQLiteDatabase migrate_db = SQLiteDatabase.openOrCreateDatabase(plain, "", null); - migrate_db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s'", - encrypted.getAbsolutePath(), passphrase)); - migrate_db.rawExecSQL("SELECT sqlcipher_export('encrypted');"); - migrate_db.execSQL("DETACH DATABASE encrypted;"); - migrate_db.close(); - - // rename the encrypted file name back - encrypted.renameTo(new File(plain.getAbsolutePath())); - } + /** + * Monitor changes in the database encryption settings + */ + SharedPreferences.OnSharedPreferenceChangeListener encryptionChanged = new SharedPreferences.OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) + { + if(key.equals(Advanced.ENCRYPT_DATABASE) || key.equals(Advanced.ENCRYPT_DATABASE_SALT)) + updateEncryption(); + } + }; + + public static synchronized void loadLibs(Context context) { + if(!libsLoaded) { + SQLiteDatabase.loadLibs(context); + libsLoaded = true; } } @@ -127,11 +133,36 @@ public void onUpgrade(SQLiteDatabase db, int oldVers, int newVers) { } public SQLiteDatabase getWritableDatabase(){ - return getWritableDatabase(passphrase); + try { + return getWritableDatabase(passphrase); + } catch (SQLiteException e) { + migrateDatabase(); + return getWritableDatabase(passphrase); + } } public SQLiteDatabase getReadableDatabase(){ - return getReadableDatabase(passphrase); + try { + return getWritableDatabase(passphrase); + } catch (SQLiteException e) { + migrateDatabase(); + return getWritableDatabase(passphrase); + } + } + + private void migrateDatabase() { + File plain = mContext.getDatabasePath(DATABASE_NAME); + File encrypted = mContext.getDatabasePath("tmp.db"); + + // try to open the database without password + SQLiteDatabase migrate_db = SQLiteDatabase.openOrCreateDatabase(plain, "", null); + migrate_db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s'", encrypted.getAbsolutePath(), passphrase)); + migrate_db.rawExecSQL("SELECT sqlcipher_export('encrypted');"); + migrate_db.execSQL("DETACH DATABASE encrypted;"); + migrate_db.close(); + + // rename the encrypted file name back + encrypted.renameTo(new File(plain.getAbsolutePath())); } private void setPassphrase(String imei) {