/* * Copyright (c) 2016 LibreTasks - https://github.com/biotinker/LibreTasks * * This file is free software: you may copy, redistribute and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * This file is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * This file incorporates work covered by the following copyright and * permission notice: /******************************************************************************* * Copyright 2009, 2010 Omnidroid - http://code.google.com/p/omnidroid * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package libretasks.app.model.db; import static libretasks.app.model.CursorHelper.getLongFromCursor; import static libretasks.app.model.CursorHelper.getStringFromCursor; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.util.Log; import libretasks.app.R; import libretasks.app.controller.Event; import libretasks.app.controller.actions.CallPhoneAction; import libretasks.app.controller.actions.OmniAction; import libretasks.app.controller.actions.SendGmailAction; import libretasks.app.controller.actions.SendSmsAction; import libretasks.app.controller.actions.PauseMediaAction; import libretasks.app.controller.actions.PlayMediaAction; import libretasks.app.controller.actions.PowerOffAction; import libretasks.app.controller.actions.SetPhoneLoudAction; import libretasks.app.controller.actions.SetPhoneSilentAction; import libretasks.app.controller.actions.SetPhoneVibrateAction; import libretasks.app.controller.actions.SetScreenBrightnessAction; import libretasks.app.controller.actions.ShowAlertAction; import libretasks.app.controller.actions.ShowNotificationAction; import libretasks.app.controller.actions.ShowWebsiteAction; import libretasks.app.controller.actions.TurnOffWifiAction; import libretasks.app.controller.actions.TurnOnWifiAction; import libretasks.app.controller.actions.TurnOffBluetoothAction; import libretasks.app.controller.actions.TurnOnBluetoothAction; import libretasks.app.controller.datatypes.OmniArea; import libretasks.app.controller.datatypes.OmniDate; import libretasks.app.controller.datatypes.OmniDayOfWeek; import libretasks.app.controller.datatypes.OmniPasswordInput; import libretasks.app.controller.datatypes.OmniPhoneNumber; import libretasks.app.controller.datatypes.OmniText; import libretasks.app.controller.datatypes.OmniTimePeriod; import libretasks.app.controller.datatypes.OmniUserAccount; import libretasks.app.controller.events.LocationChangedEvent; import libretasks.app.controller.events.InternetAvailableEvent; import libretasks.app.controller.events.MissedCallEvent; import libretasks.app.controller.events.PhoneCallEvent; import libretasks.app.controller.events.PhoneRingingEvent; import libretasks.app.controller.events.CallEndedEvent; import libretasks.app.controller.events.SMSReceivedEvent; import libretasks.app.controller.events.ServiceAvailableEvent; import libretasks.app.controller.events.SystemEvent; import libretasks.app.controller.events.TimeTickEvent; import libretasks.app.model.CursorHelper; /** * Class used for migrating a database for Omnidroid from one version to another. */ public class DbMigration { private static final String TAG = DbMigration.class.getSimpleName(); /** * This class does not need to be instantiated. */ private DbMigration() { } /** * Migrate the database to its latest version * * @param context * the context from DbHelper * * @param db * the database to migrate * @param currentDbVersionNumber * the version number of the current database before migrating */ public static void migrateToLatest(Context context, SQLiteDatabase db, int currentDbVersionNumber) { // Use standard Logger since DB may not be setup yet Log.i(TAG, "Migrating database from version " + currentDbVersionNumber); switch (currentDbVersionNumber) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: initialVersion(db); setDefaultRules(context, db); case 22: addBluetooth(db); addPowerOffAction(db); /* * Insert new versions before this line and do not forget to update {@code * DbHelper.DATABASE_VERSION}. Otherwise, the constructor call on SQLiteOpenHelper will not * trigger the {@code onUpgrade} callback method. */ break; default: Log.w(TAG, "Attempting to migrate from an unknown version!"); break; } } /** * When name restructuring was done in post r725 (Version 3 (0.1.2)) code, we reorganized the * source tree. DataTypes were moved to a new hierarchy resulting in their class names changing. * This code will update the class names stored in the database to reflect the new class names. * * @param db * the database */ private static void updateDataTypeClassNameChanges(SQLiteDatabase db) { /** * If upgrading from a r725 or earlier release, these are stored in "DataTypes" table: * * VALUES(1,'Text','edu.nyu.cs.omnidroid.app.core.datatypes.OmniText') * VALUES(2,'PhoneNumber','edu.nyu.cs.omnidroid.app.core.datatypes.OmniPhoneNumber') * VALUES(3,'DayOfWeek','edu.nyu.cs.omnidroid.app.core.datatypes.OmniDayOfWeek') * VALUES(4,'TimePeriod','edu.nyu.cs.omnidroid.app.core.datatypes.OmniTimePeriod') * VALUES(5,'Date','edu.nyu.cs.omnidroid.app.core.datatypes.OmniDate') * VALUES(6,'Area','edu.nyu.cs.omnidroid.app.core.datatypes.OmniArea') * VALUES(7,'PasswordInput','edu.nyu.cs.omnidroid.app.core.datatypes.OmniPasswordInput') * * And need to be updated to the new class names. */ DataTypeDbAdapter dataTypeDbAdapter = new DataTypeDbAdapter(db); Cursor cursor; long id; // Update OmniText cursor = dataTypeDbAdapter.fetchAll(OmniText.DB_NAME, null); cursor.moveToFirst(); id = getLongFromCursor(cursor, DataTypeDbAdapter.KEY_DATATYPEID); dataTypeDbAdapter.update(id, null, OmniText.class.getName()); cursor.close(); // Update OmniPhoneNumber cursor = dataTypeDbAdapter.fetchAll(OmniPhoneNumber.DB_NAME, null); cursor.moveToFirst(); id = getLongFromCursor(cursor, DataTypeDbAdapter.KEY_DATATYPEID); dataTypeDbAdapter.update(id, null, OmniPhoneNumber.class.getName()); cursor.close(); // Update OmniDayOfWeek cursor = dataTypeDbAdapter.fetchAll(OmniDayOfWeek.DB_NAME, null); cursor.moveToFirst(); id = getLongFromCursor(cursor, DataTypeDbAdapter.KEY_DATATYPEID); dataTypeDbAdapter.update(id, null, OmniDayOfWeek.class.getName()); cursor.close(); // Update OmniTimePeriod cursor = dataTypeDbAdapter.fetchAll(OmniTimePeriod.DB_NAME, null); cursor.moveToFirst(); id = getLongFromCursor(cursor, DataTypeDbAdapter.KEY_DATATYPEID); dataTypeDbAdapter.update(id, null, OmniTimePeriod.class.getName()); cursor.close(); // Update OmniDate cursor = dataTypeDbAdapter.fetchAll(OmniDate.DB_NAME, null); cursor.moveToFirst(); id = getLongFromCursor(cursor, DataTypeDbAdapter.KEY_DATATYPEID); dataTypeDbAdapter.update(id, null, OmniDate.class.getName()); cursor.close(); // Update OmniArea cursor = dataTypeDbAdapter.fetchAll(OmniArea.DB_NAME, null); cursor.moveToFirst(); id = getLongFromCursor(cursor, DataTypeDbAdapter.KEY_DATATYPEID); dataTypeDbAdapter.update(id, null, OmniArea.class.getName()); cursor.close(); // Update OmniPasswordInput cursor = dataTypeDbAdapter.fetchAll(OmniPasswordInput.DB_NAME, null); cursor.moveToFirst(); id = getLongFromCursor(cursor, DataTypeDbAdapter.KEY_DATATYPEID); dataTypeDbAdapter.update(id, null, OmniPasswordInput.class.getName()); cursor.close(); } /** * Set the default rules * * @param context * the context * * @param db * database * */ private static void setDefaultRules(Context context, SQLiteDatabase db) { final String TIME_NIGHT = "0001-01-01 00:00:00"; final String TIME_MORNING = "0001-01-01 09:00:00"; RuleDbAdapter ruleAdapter = new RuleDbAdapter(db); RegisteredEventDbAdapter eventsAdapter = new RegisteredEventDbAdapter(db); RegisteredActionDbAdapter actionAdapter = new RegisteredActionDbAdapter(db); RuleActionDbAdapter ruleActionAdapter = new RuleActionDbAdapter(db); RegisteredActionParameterDbAdapter actionParametersAdapter = new RegisteredActionParameterDbAdapter( db); RuleActionParameterDbAdapter ruleActionParametersAdapter = new RuleActionParameterDbAdapter(db); RegisteredEventAttributeDbAdapter eventAttributesAdapter = new RegisteredEventAttributeDbAdapter( db); DataFilterDbAdapter dataFilterAdapter = new DataFilterDbAdapter(db); RuleFilterDbAdapter ruleFilterAdapter = new RuleFilterDbAdapter(db); // Set default rule: sent back sms "Busy, in meeting. Will get back to you later" when phone // is ringing Cursor phoneRingEventCursor = eventsAdapter.fetchAll(PhoneRingingEvent.EVENT_NAME, null); if (phoneRingEventCursor.moveToNext()) { long phoneRingEventID = getLongFromCursor(phoneRingEventCursor, RegisteredEventDbAdapter.KEY_EVENTID); String phoneRingToSMSRuleName = context.getString(R.string.phoneRingToSMSRuleName); String phoneRingToSMSRuleDesc = context.getString(R.string.phoneRingToSMSRuleDesc); long phoneToSMSRuleID = ruleAdapter.insert(phoneRingEventID, phoneRingToSMSRuleName, phoneRingToSMSRuleDesc, false); Cursor smsActionCursor = actionAdapter.fetchAll(SendSmsAction.ACTION_NAME, null); if (smsActionCursor.moveToNext()) { long smsActionID = getLongFromCursor(smsActionCursor, RegisteredActionDbAdapter.KEY_ACTIONID); long phoneToSMSRuleActionID = ruleActionAdapter.insert(phoneToSMSRuleID, smsActionID); Cursor smsPhoneNOParameterCursor = actionParametersAdapter.fetchAll( SendSmsAction.PARAM_PHONE_NO, smsActionID, null); if (smsPhoneNOParameterCursor.moveToNext()) { long smsPhoneNOParameterID = getLongFromCursor(smsPhoneNOParameterCursor, RegisteredActionParameterDbAdapter.KEY_ACTIONPARAMETERID); Cursor smsMessageParameterCursor = actionParametersAdapter.fetchAll( SendSmsAction.PARAM_SMS, smsActionID, null); if (smsMessageParameterCursor.moveToNext()) { long smsMessageParameterID = getLongFromCursor(smsMessageParameterCursor, RegisteredActionParameterDbAdapter.KEY_ACTIONPARAMETERID); String phoneParameter = "<" + PhoneRingingEvent.ATTRIBUTE_PHONE_NUMBER + ">"; ruleActionParametersAdapter.insert(phoneToSMSRuleActionID, smsPhoneNOParameterID, phoneParameter); String PhoneRingToSMSRuleMessage = context .getString(R.string.phoneRingToSMSRuleMessage); ruleActionParametersAdapter.insert(phoneToSMSRuleActionID, smsMessageParameterID, PhoneRingToSMSRuleMessage); } smsMessageParameterCursor.close(); } smsPhoneNOParameterCursor.close(); } smsActionCursor.close(); } phoneRingEventCursor.close(); // Set default rule: Sleep during night, when time is after midnight set phone silent // Set default rule: Wake up during daytime, when time is after 9am set phone loud Cursor timeEventCursor = eventsAdapter.fetchAll(TimeTickEvent.EVENT_NAME, null); if (timeEventCursor.moveToNext()) { long timeEventID = getLongFromCursor(timeEventCursor, RegisteredEventDbAdapter.KEY_EVENTID); /* * Use the "deprecated" constant since addSupportForGlobalEventAttributes was accidentally * deleted causing the Event.ATTRIBUTE_TIME not to be inserted to the table. */ @SuppressWarnings("deprecation") Cursor timeAttributesCursor = eventAttributesAdapter.fetchAll( TimeTickEvent.ATTRIBUTE_CURRENT_TIME, timeEventID, null); if (timeAttributesCursor.moveToNext()) { long timeAttrbutesID = getLongFromCursor(timeAttributesCursor, RegisteredEventAttributeDbAdapter.KEY_EVENTATTRIBUTEID); String timeToSilentRuleTime = TIME_NIGHT; String timeToLoudRuleTime = TIME_MORNING; // Set rule: Sleep during night Cursor timeToSilentFilterCursor = dataFilterAdapter.fetchAll(null, OmniDate.Filter.IS_EVERYDAY.displayName, null, null); if (timeToSilentFilterCursor.moveToNext()) { long timeToSilentFilterID = getLongFromCursor(timeToSilentFilterCursor, DataFilterDbAdapter.KEY_DATAFILTERID); String timeToSilentRuleName = context.getString(R.string.timeToSilentRuleName); String timeToSilentRuleDesc = context.getString(R.string.timeToSilentRuleDesc); long timeToSilentRuleID = ruleAdapter.insert(timeEventID, timeToSilentRuleName, timeToSilentRuleDesc, false); Cursor silentActionCursor = actionAdapter .fetchAll(SetPhoneSilentAction.ACTION_NAME, null); if (silentActionCursor.moveToNext()) { long silentActionID = getLongFromCursor(silentActionCursor, RegisteredActionDbAdapter.KEY_ACTIONID); ruleActionAdapter.insert(timeToSilentRuleID, silentActionID); ruleFilterAdapter.insert(timeToSilentRuleID, timeAttrbutesID, -1l, timeToSilentFilterID, -1l, timeToSilentRuleTime); } silentActionCursor.close(); } timeToSilentFilterCursor.close(); // Set rule: Wake up during daytime Cursor timeToLoudFilterCursor = dataFilterAdapter.fetchAll(null, OmniDate.Filter.IS_EVERYDAY.displayName, null, null); if (timeToLoudFilterCursor.moveToNext()) { long timeToLoudFilterID = getLongFromCursor(timeToLoudFilterCursor, DataFilterDbAdapter.KEY_DATAFILTERID); String timeToLoudRuleName = context.getString(R.string.timeToLoudRuleName); String timeToLoudRuleDesc = context.getString(R.string.timeToLoudRuleDesc); long timeToLoudRuleID = ruleAdapter.insert(timeEventID, timeToLoudRuleName, timeToLoudRuleDesc, false); Cursor loudActionCursor = actionAdapter.fetchAll(SetPhoneLoudAction.ACTION_NAME, null); if (loudActionCursor.moveToNext()) { long loudActionID = getLongFromCursor(loudActionCursor, RegisteredActionDbAdapter.KEY_ACTIONID); ruleActionAdapter.insert(timeToLoudRuleID, loudActionID); ruleFilterAdapter.insert(timeToLoudRuleID, timeAttrbutesID, -1l, timeToLoudFilterID, -1l, timeToLoudRuleTime); } loudActionCursor.close(); } timeToLoudFilterCursor.close(); } timeAttributesCursor.close(); } timeEventCursor.close(); // Set default rule: Disable WiFi, when battery is low Cursor batteryLowEventCursor = eventsAdapter.fetchAll(SystemEvent.BatteryLowEvent.EVENT_NAME, null); if (batteryLowEventCursor.moveToNext()) { long batteryLowEventID = getLongFromCursor(batteryLowEventCursor, RegisteredEventDbAdapter.KEY_EVENTID); Cursor setWifiOffActionCursor = actionAdapter.fetchAll(TurnOffWifiAction.ACTION_NAME, null); if (setWifiOffActionCursor.moveToNext()) { long setWifiOffActionID = getLongFromCursor(setWifiOffActionCursor, RegisteredActionDbAdapter.KEY_ACTIONID); String batteryLowToSetWifiOffRuleName = context .getString(R.string.batteryLowToSetWifiOffRuleName); String batteryLowToSetWifiOffRuleDesc = context .getString(R.string.batteryLowToSetWifiOffRuleDesc); long batteryLowToSetWifiOffRuleID = ruleAdapter.insert(batteryLowEventID, batteryLowToSetWifiOffRuleName, batteryLowToSetWifiOffRuleDesc, false); ruleActionAdapter.insert(batteryLowToSetWifiOffRuleID, setWifiOffActionID); } setWifiOffActionCursor.close(); } batteryLowEventCursor.close(); } /** * Create the initial version of the Omnidroid database along with prepopulated data. * * @param db * SQLiteDatabase object to work with */ @SuppressWarnings("deprecation") private static void initialVersion(SQLiteDatabase db) { /** * Create tables */ db.execSQL(RegisteredAppDbAdapter.getSqliteCreateStatement()); db.execSQL(RegisteredEventDbAdapter.getSqliteCreateStatement()); db.execSQL(RegisteredEventAttributeDbAdapter.getSqliteCreateStatement()); db.execSQL(RegisteredActionDbAdapter.getSqliteCreateStatement()); db.execSQL(RegisteredActionParameterDbAdapter.getSqliteCreateStatement()); db.execSQL(DataFilterDbAdapter.getSqliteCreateStatement()); db.execSQL(DataTypeDbAdapter.getSqliteCreateStatement()); db.execSQL(ExternalAttributeDbAdapter.getSqliteCreateStatement()); db.execSQL(RuleDbAdapter.getSqliteCreateStatement()); db.execSQL(RuleFilterDbAdapter.getSqliteCreateStatement()); db.execSQL(RuleActionDbAdapter.getSqliteCreateStatement()); db.execSQL(RuleActionParameterDbAdapter.getSqliteCreateStatement()); /* * Populate data types and their data filters */ DataTypeDbAdapter dataTypeDbAdapter = new DataTypeDbAdapter(db); DataFilterDbAdapter dataFilterDbAdapter = new DataFilterDbAdapter(db); long dataTypeIdText = dataTypeDbAdapter.insert(OmniText.DB_NAME, OmniText.class.getName()); dataFilterDbAdapter.insert(OmniText.Filter.EQUALS.toString(), OmniText.Filter.EQUALS.displayName, dataTypeIdText, dataTypeIdText); dataFilterDbAdapter.insert(OmniText.Filter.CONTAINS.toString(), OmniText.Filter.CONTAINS.displayName, dataTypeIdText, dataTypeIdText); long dataTypeIdPhoneNumber = dataTypeDbAdapter.insert(OmniPhoneNumber.DB_NAME, OmniPhoneNumber.class.getName()); dataFilterDbAdapter.insert(OmniPhoneNumber.Filter.EQUALS.toString(), OmniPhoneNumber.Filter.EQUALS.displayName, dataTypeIdPhoneNumber, dataTypeIdPhoneNumber); long dataTypeIdDayOfWeek = dataTypeDbAdapter.insert(OmniDayOfWeek.DB_NAME, OmniDayOfWeek.class .getName()); long dataTypeIdTimePeriod = dataTypeDbAdapter.insert(OmniTimePeriod.DB_NAME, OmniTimePeriod.class.getName()); long dataTypeIdDate = dataTypeDbAdapter.insert(OmniDate.DB_NAME, OmniDate.class.getName()); dataFilterDbAdapter.insert(OmniTimePeriod.Filter.DURING_EVERYDAY.toString(), OmniTimePeriod.Filter.DURING_EVERYDAY.displayName, dataTypeIdTimePeriod, dataTypeIdDate); dataFilterDbAdapter.insert(OmniTimePeriod.Filter.EXCEPT_EVERYDAY.toString(), OmniTimePeriod.Filter.EXCEPT_EVERYDAY.displayName, dataTypeIdTimePeriod, dataTypeIdDate); dataFilterDbAdapter.insert(OmniDate.Filter.IS_EVERYDAY.toString(), OmniDate.Filter.IS_EVERYDAY.displayName, dataTypeIdDate, dataTypeIdDate); dataFilterDbAdapter.insert(OmniDate.Filter.IS_NOT_EVERYDAY.toString(), OmniDate.Filter.IS_NOT_EVERYDAY.displayName, dataTypeIdDate, dataTypeIdDate); dataFilterDbAdapter.insert(OmniDate.Filter.BEFORE_EVERYDAY.toString(), OmniDate.Filter.BEFORE_EVERYDAY.displayName, dataTypeIdDate, dataTypeIdDate); dataFilterDbAdapter.insert(OmniDate.Filter.AFTER_EVERYDAY.toString(), OmniDate.Filter.AFTER_EVERYDAY.displayName, dataTypeIdDate, dataTypeIdDate); dataFilterDbAdapter.insert(OmniDate.Filter.DURING_EVERYDAY.toString(), OmniDate.Filter.DURING_EVERYDAY.displayName, dataTypeIdDate, dataTypeIdTimePeriod); dataFilterDbAdapter.insert(OmniDate.Filter.EXCEPT_EVERYDAY.toString(), OmniDate.Filter.EXCEPT_EVERYDAY.displayName, dataTypeIdDate, dataTypeIdTimePeriod); dataFilterDbAdapter.insert(OmniDate.Filter.ISDAYOFWEEK.toString(), OmniDate.Filter.ISDAYOFWEEK.displayName, dataTypeIdDate, dataTypeIdDayOfWeek); long dataTypeIdArea = dataTypeDbAdapter.insert(OmniArea.DB_NAME, OmniArea.class.getName()); dataFilterDbAdapter.insert(OmniArea.Filter.NEAR.toString(), OmniArea.Filter.NEAR.displayName, dataTypeIdArea, dataTypeIdArea); dataFilterDbAdapter.insert(OmniArea.Filter.AWAY.toString(), OmniArea.Filter.AWAY.displayName, dataTypeIdArea, dataTypeIdArea); long dataTypeIdPasswordInput = dataTypeDbAdapter.insert(OmniPasswordInput.DB_NAME, OmniPasswordInput.class.getName()); /* * Populate registered applications */ RegisteredAppDbAdapter appDbAdapter = new RegisteredAppDbAdapter(db); long appIdSms = appDbAdapter.insert(DbHelper.AppName.SMS, "", true); long appIdPhone = appDbAdapter.insert(DbHelper.AppName.PHONE, "", true); long appIdGPS = appDbAdapter.insert(DbHelper.AppName.GPS, "", true); long appIdEmail = appDbAdapter.insert(DbHelper.AppName.EMAIL, "", true, true); long appIdOmnidroid = appDbAdapter.insert(OmniAction.APP_NAME, "", true); long appIdSettings = appDbAdapter.insert(DbHelper.AppName.SETTINGS, "", true, true); long appIdSignals = appDbAdapter.insert(DbHelper.AppName.SIGNALS, "", true, true); long appIdMedia = appDbAdapter.insert(DbHelper.AppName.MEDIA, "", true); long appIdAndroid = appDbAdapter.insert(SystemEvent.PowerConnectedEvent.APPLICATION_NAME, "", true); /* * Populate registered events and event attributes */ RegisteredEventDbAdapter eventDbAdapter = new RegisteredEventDbAdapter(db); RegisteredEventAttributeDbAdapter eventAttributeDbAdapter = new RegisteredEventAttributeDbAdapter( db); for (SystemEvent e : SystemEvent.values()) { eventDbAdapter.insert(e.EVENT_NAME, appIdAndroid); } long eventIdSmsRec = eventDbAdapter.insert(SMSReceivedEvent.EVENT_NAME, appIdSms); eventAttributeDbAdapter.insert(SMSReceivedEvent.ATTRIB_PHONE_NO, eventIdSmsRec, dataTypeIdPhoneNumber); eventAttributeDbAdapter.insert(SMSReceivedEvent.ATTRIB_MESSAGE_TEXT, eventIdSmsRec, dataTypeIdText); eventAttributeDbAdapter.insert(SMSReceivedEvent.ATTRIB_MESSAGE_TIME, eventIdSmsRec, dataTypeIdDate); long eventIdPhoneRings = eventDbAdapter.insert(PhoneRingingEvent.EVENT_NAME, appIdPhone); eventAttributeDbAdapter.insert(PhoneRingingEvent.ATTRIBUTE_PHONE_NUMBER, eventIdPhoneRings, dataTypeIdPhoneNumber); eventAttributeDbAdapter.insert(PhoneRingingEvent.ATTRIBUTE_TIMESTAMP, eventIdPhoneRings, dataTypeIdDate); long eventIdGPSLocationChanged = eventDbAdapter.insert(LocationChangedEvent.EVENT_NAME, appIdGPS); eventAttributeDbAdapter.insert(LocationChangedEvent.ATTRIBUTE_CURRENT_LOCATION, eventIdGPSLocationChanged, dataTypeIdArea); long eventIdTimeTick = eventDbAdapter.insert(TimeTickEvent.EVENT_NAME, appIdAndroid); eventAttributeDbAdapter.insert(TimeTickEvent.ATTRIBUTE_CURRENT_TIME, eventIdTimeTick, dataTypeIdDate); /* * Populate registered actions and action parameters */ RegisteredActionDbAdapter actionDbAdapter = new RegisteredActionDbAdapter(db); RegisteredActionParameterDbAdapter actionParameterDbAdapter = new RegisteredActionParameterDbAdapter(db); long actionIdDisplayMessage = actionDbAdapter.insert(ShowAlertAction.ACTION_NAME, appIdOmnidroid); actionParameterDbAdapter.insert(ShowAlertAction.PARAM_ALERT_MESSAGE, actionIdDisplayMessage, dataTypeIdText); long actionIdNotifyMessage = actionDbAdapter.insert(ShowNotificationAction.ACTION_NAME, appIdOmnidroid); actionParameterDbAdapter.insert(ShowNotificationAction.PARAM_ALERT_MESSAGE, actionIdNotifyMessage, dataTypeIdText); long actionIdShowWebsite = actionDbAdapter .insert(ShowWebsiteAction.ACTION_NAME, appIdOmnidroid); actionParameterDbAdapter.insert(ShowWebsiteAction.PARAM_WEB_URL, actionIdShowWebsite, dataTypeIdText); long actionIdSetBrightness = actionDbAdapter.insert(SetScreenBrightnessAction.ACTION_NAME, appIdSettings); actionParameterDbAdapter.insert(SetScreenBrightnessAction.PARAM_BRIGHTNESS, actionIdSetBrightness, dataTypeIdText); actionDbAdapter.insert(SetPhoneLoudAction.ACTION_NAME, appIdSettings); actionDbAdapter.insert(SetPhoneSilentAction.ACTION_NAME, appIdSettings); actionDbAdapter.insert(SetPhoneVibrateAction.ACTION_NAME, appIdSettings); actionDbAdapter.insert(PlayMediaAction.ACTION_NAME, appIdMedia); actionDbAdapter.insert(PauseMediaAction.ACTION_NAME, appIdMedia); actionDbAdapter.insert(TurnOffWifiAction.ACTION_NAME, appIdSignals); actionDbAdapter.insert(TurnOnWifiAction.ACTION_NAME, appIdSignals); long actionIdSmsSend = actionDbAdapter.insert(SendSmsAction.ACTION_NAME, appIdSms); actionParameterDbAdapter.insert(SendSmsAction.PARAM_PHONE_NO, actionIdSmsSend, dataTypeIdPhoneNumber); actionParameterDbAdapter.insert(SendSmsAction.PARAM_SMS, actionIdSmsSend, dataTypeIdText); long actionIdPhoneCall = actionDbAdapter.insert(CallPhoneAction.ACTION_NAME, appIdPhone); actionParameterDbAdapter.insert(CallPhoneAction.PARAM_PHONE_NO, actionIdPhoneCall, dataTypeIdPhoneNumber); long actionIdGmailSend = actionDbAdapter.insert(SendGmailAction.ACTION_NAME, appIdEmail); actionParameterDbAdapter.insert(SendGmailAction.PARAM_USERNAME, actionIdGmailSend, dataTypeIdText); actionParameterDbAdapter.insert(SendGmailAction.PARAM_PASSWORD, actionIdGmailSend, dataTypeIdPasswordInput); actionParameterDbAdapter.insert(SendGmailAction.PARAM_TO, actionIdGmailSend, dataTypeIdText); actionParameterDbAdapter.insert(SendGmailAction.PARAM_SUBJECT, actionIdGmailSend, dataTypeIdText); actionParameterDbAdapter.insert(SendGmailAction.PARAM_BODY, actionIdGmailSend, dataTypeIdText); //Add notifications and failed actions db.execSQL(RuleDbAdapter.ADD_NOTIFICATION_COLUMN); db.execSQL(FailedActionsDbAdapter.getSqliteCreateStatement()); db.execSQL(FailedActionParameterDbAdapter.getSqliteCreateStatement()); //Call create statements to reinitialize database addCallEndEvent(db); dropLogEvent(db); addLogEvent(db); dropLogAction(db); addLogAction(db); addLogGeneral(db); modifyGmailAndTwitterParam(db); addPhoneNumberNotEqualsFilter(db); addGeneralLogLevels(db); addInternetAndServiceAvailableEvents(db); addSupportForGlobalEventAttributes(db); alterFailedActionsTable(db); addMissedCallEvent(db); } /** * Update the database to support the call ended event. * * @param db * the database instance to work with */ @SuppressWarnings("deprecation") private static void addCallEndEvent(SQLiteDatabase db) { RegisteredEventDbAdapter eventDbAdapter = new RegisteredEventDbAdapter(db); RegisteredEventAttributeDbAdapter eventAttributeDbAdapter = new RegisteredEventAttributeDbAdapter(db); DataTypeDbAdapter dataTypeDbAdapter = new DataTypeDbAdapter(db); Cursor dataTypeDbCursor = dataTypeDbAdapter .fetchAll(OmniDate.DB_NAME, OmniDate.class.getName()); /** * Just get the first result. The identifiers used in the query should already be unique enough * that it should just return one record if it existed. */ dataTypeDbCursor.moveToFirst(); long dataTypeIdDate = CursorHelper.getLongFromCursor(dataTypeDbCursor, DataTypeDbAdapter.KEY_DATATYPEID); long eventIdPhoneCallEnded = eventDbAdapter.insert(CallEndedEvent.EVENT_NAME, DbHelper.AppName.PHONE, ""); eventAttributeDbAdapter.insert(CallEndedEvent.ATTRIBUTE_TIMESTAMP, eventIdPhoneCallEnded, dataTypeIdDate); dataTypeDbCursor.close(); } /** * Add table to provide {@code LogEvent} support. * * @param db * the database instance to work with */ private static void addLogEvent(SQLiteDatabase db) { // Create table db.execSQL(LogEventDbAdapter.DATABASE_CREATE); } /** * Drop table that provides {@code LogAction} support. * * @param db * the database instance to work with */ private static void dropLogEvent(SQLiteDatabase db) { // Drop table db.execSQL(LogEventDbAdapter.DATABASE_DROP); } /** * Add table to provide {@code LogAction} support. * * @param db * the database instance to work with */ private static void addLogAction(SQLiteDatabase db) { // Create table db.execSQL(LogActionDbAdapter.DATABASE_CREATE); } /** * Drop table that provides {@code LogAction} support. * * @param db * the database instance to work with */ private static void dropLogAction(SQLiteDatabase db) { // Drop table db.execSQL(LogActionDbAdapter.DATABASE_DROP); } /** * Add table to provide {@code LogGeneral} support. * * @param db * the database instance to work with */ private static void addLogGeneral(SQLiteDatabase db) { // Create table db.execSQL(LogGeneralDbAdapter.DATABASE_CREATE); } /** * Modify the Send Gmail and Update Twitter actions by replacing the username and password * attributes into user account (this is done for possible multi-account support and supporting * different authentication methods like OAuth). Also retrieves username and password from * existing rules and the latest entry is used if there are multiple actions that has username and * password. * * @param db * the database instance to work with */ @SuppressWarnings("deprecation") private static void modifyGmailAndTwitterParam(SQLiteDatabase db) { DataTypeDbAdapter dataTypeDbAdapter = new DataTypeDbAdapter(db); long dataTypeIdAccount = dataTypeDbAdapter.insert(OmniUserAccount.DB_NAME, OmniUserAccount.class.getName()); modifyActionToSupportUserAccount(db, DbHelper.AppName.EMAIL, SendGmailAction.ACTION_NAME, SendGmailAction.PARAM_USERNAME, SendGmailAction.PARAM_PASSWORD, SendGmailAction.PARAM_USER_ACCOUNT, dataTypeIdAccount); } /** * Modify the actions by replacing the username and password attributes into user account (this is * done for possible multi-account support and supporting different authentication methods like * OAuth). Also retrieves username and password from existing rules and the latest entry is used * if there are multiple actions that has username and password. * * @param db * the database instance to work with * @param appName * the name of the application associated with the action * @param actionName * the name of the action * @param usernameParamName * the action's parameter name for username * @param passwordParamName * the action's parameter name for password * @param userAccountParamName * the action's parameter name for user account * @param dataTypeIdAccount * primary key id for UserAccount datatype */ private static void modifyActionToSupportUserAccount(SQLiteDatabase db, String appName, String actionName, String usernameParamName, String passwordParamName, String userAccountParamName, long dataTypeIdAccount) { // Get the App ID RegisteredAppDbAdapter appDbAdapter = new RegisteredAppDbAdapter(db); Cursor cursor = appDbAdapter.fetchAll(appName, "", true); cursor.moveToFirst(); long appID = CursorHelper.getLongFromCursor(cursor, RegisteredAppDbAdapter.KEY_APPID); cursor.close(); // Get the Action ID RegisteredActionDbAdapter actionDbAdapter = new RegisteredActionDbAdapter(db); cursor = actionDbAdapter.fetchAll(actionName, appID); cursor.moveToFirst(); long actionId = CursorHelper.getLongFromCursor(cursor, RegisteredActionDbAdapter.KEY_ACTIONID); cursor.close(); RegisteredActionParameterDbAdapter actionParameterDbAdapter = new RegisteredActionParameterDbAdapter(db); /* * Modify the username parameter to user account. Update was used instead of delete then insert * to have the user account parameter appear on the top position when {@code * FactoryActions.buildUIFromAction} is called. */ cursor = actionParameterDbAdapter.fetchAll(usernameParamName, actionId, null); cursor.moveToFirst(); long paramID = CursorHelper.getLongFromCursor(cursor, RegisteredActionParameterDbAdapter.KEY_ACTIONPARAMETERID); actionParameterDbAdapter.update(paramID, userAccountParamName, null, dataTypeIdAccount); cursor.close(); /* * Get the username from existing rules and set it to the application. Use the last entry if * there are multiple actions in the database. */ RuleActionParameterDbAdapter ruleActionParamDb = new RuleActionParameterDbAdapter(db); cursor = ruleActionParamDb.fetchAll(null, paramID, null); if (cursor.moveToLast()) { String username = CursorHelper.getStringFromCursor(cursor, RuleActionParameterDbAdapter.KEY_RULEACTIONPARAMETERDATA); appDbAdapter.update(appID, null, null, null, null, username, null); } // No need to delete since paramID is now user account cursor.close(); // Remove the password parameter cursor = actionParameterDbAdapter.fetchAll(passwordParamName, actionId, null); cursor.moveToFirst(); paramID = CursorHelper.getLongFromCursor(cursor, RegisteredActionParameterDbAdapter.KEY_ACTIONPARAMETERID); actionParameterDbAdapter.delete(paramID); cursor.close(); /* * Get the password from existing rules and set it to the application. Use the last entry if * there are multiple gmail send actions in the database. And remove all rule action password * parameter entries. */ cursor = ruleActionParamDb.fetchAll(null, paramID, null); if (cursor.moveToLast()) { String password = CursorHelper.getStringFromCursor(cursor, RuleActionParameterDbAdapter.KEY_RULEACTIONPARAMETERDATA); appDbAdapter.update(appID, null, null, null, null, null, password); do { ruleActionParamDb.delete(CursorHelper.getLongFromCursor(cursor, RuleActionParameterDbAdapter.KEY_RULEACTIONPARAMETERID)); } while (cursor.moveToPrevious()); } cursor.close(); } private static void addGeneralLogLevels(SQLiteDatabase db) { db.execSQL(LogGeneralDbAdapter.ADD_LEVEL_COLUMN); } private static void addInternetAndServiceAvailableEvents(SQLiteDatabase db) { RegisteredAppDbAdapter registeredAppDbAdapter = new RegisteredAppDbAdapter(db); Cursor cursor = registeredAppDbAdapter.fetchAll(OmniAction.APP_NAME, null, null, null, null, null); cursor.moveToFirst(); long appId = CursorHelper.getLongFromCursor(cursor, RegisteredAppDbAdapter.KEY_APPID); cursor.close(); RegisteredEventDbAdapter registeredEventDbAdapter = new RegisteredEventDbAdapter(db); registeredEventDbAdapter.insert(InternetAvailableEvent.EVENT_NAME, appId); registeredEventDbAdapter.insert(ServiceAvailableEvent.EVENT_NAME, appId); } private static void addPhoneNumberNotEqualsFilter(SQLiteDatabase db) { DataFilterDbAdapter dataFilterDbAdapter = new DataFilterDbAdapter(db); DataTypeDbAdapter dataTypeDbAdapter = new DataTypeDbAdapter(db); Cursor cursor = dataTypeDbAdapter.fetchAll(OmniPhoneNumber.DB_NAME, OmniPhoneNumber.class .getName()); if ((cursor != null) && (cursor.getCount() > 0)) { cursor.moveToFirst(); } long dataTypeIdPhoneNumber = CursorHelper.getLongFromCursor(cursor, DataTypeDbAdapter.KEY_DATATYPEID); if (cursor != null) { cursor.close(); } dataFilterDbAdapter.insert(OmniPhoneNumber.Filter.NOTEQUALS.toString(), OmniPhoneNumber.Filter.NOTEQUALS.displayName, dataTypeIdPhoneNumber, dataTypeIdPhoneNumber); } /** * Convert all time and location entries in the attributes table to general attributes. * * @param db * the database instance to work with */ @SuppressWarnings("deprecation") private static void addSupportForGlobalEventAttributes(SQLiteDatabase db) { RegisteredEventAttributeDbAdapter eventAttributeDbAdapter = new RegisteredEventAttributeDbAdapter( db); DataTypeDbAdapter dataTypeDbAdapter = new DataTypeDbAdapter(db); // Query is unique enough to return one entry Cursor cursor = dataTypeDbAdapter.fetchAll(OmniDate.DB_NAME, OmniDate.class.getName()); cursor.moveToFirst(); long dataTypeIdDate = CursorHelper.getLongFromCursor(cursor, DataTypeDbAdapter.KEY_DATATYPEID); long dateAttributeID = eventAttributeDbAdapter.insertGeneralAttribute(Event.ATTRIBUTE_TIME, dataTypeIdDate); // Query is unique enough to return one entry cursor = dataTypeDbAdapter.fetchAll(OmniArea.DB_NAME, OmniArea.class.getName()); cursor.moveToFirst(); long dataTypeIdArea = CursorHelper.getLongFromCursor(cursor, DataTypeDbAdapter.KEY_DATATYPEID); long areaAttributeID = eventAttributeDbAdapter.insertGeneralAttribute(Event.ATTRIBUTE_LOCATION, dataTypeIdArea); cursor.close(); RuleFilterDbAdapter ruleFilterDbAdapter = new RuleFilterDbAdapter(db); RuleActionParameterDbAdapter ruleActionParamDbAdapter = new RuleActionParameterDbAdapter(db); generalizeAttribute(SMSReceivedEvent.ATTRIB_MESSAGE_TIME, Event.ATTRIBUTE_TIME, dateAttributeID, eventAttributeDbAdapter, ruleFilterDbAdapter, ruleActionParamDbAdapter); generalizeAttribute(PhoneCallEvent.ATTRIBUTE_TIMESTAMP, Event.ATTRIBUTE_TIME, dateAttributeID, eventAttributeDbAdapter, ruleFilterDbAdapter, ruleActionParamDbAdapter); generalizeAttribute(LocationChangedEvent.ATTRIBUTE_CURRENT_LOCATION, Event.ATTRIBUTE_LOCATION, areaAttributeID, eventAttributeDbAdapter, ruleFilterDbAdapter, ruleActionParamDbAdapter); generalizeAttribute(TimeTickEvent.ATTRIBUTE_CURRENT_TIME, Event.ATTRIBUTE_TIME, dateAttributeID, eventAttributeDbAdapter, ruleFilterDbAdapter, ruleActionParamDbAdapter); } private static void generalizeAttribute(String attributeName, String newAttributeName, long newAttributeDbID, RegisteredEventAttributeDbAdapter eventAttributeDbAdapter, RuleFilterDbAdapter ruleFilterDbAdapter, RuleActionParameterDbAdapter ruleActionParamDbAdapter) { Cursor cursor = eventAttributeDbAdapter.fetchAll(attributeName, null, null); while (cursor.moveToNext()) { // Delete the entry in the Event Attribute Table long primaryKey = CursorHelper.getLongFromCursor(cursor, RegisteredEventAttributeDbAdapter.KEY_EVENTATTRIBUTEID); eventAttributeDbAdapter.delete(primaryKey); // Update the Event Attribute ID on existing rule filters to the more general version ContentValues values = new ContentValues(); values.put(RuleFilterDbAdapter.KEY_EVENTATTRIBUTEID, newAttributeDbID); ruleFilterDbAdapter.sqlUpdate(values, RuleFilterDbAdapter.KEY_EVENTATTRIBUTEID + " = " + primaryKey); // Update all attribute tags in existing rule parameters to the general version SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); queryBuilder.appendWhere(RuleActionParameterDbAdapter.KEY_RULEACTIONPARAMETERDATA + " LIKE \"%<" + attributeName + ">%\""); Cursor paramCursor = ruleActionParamDbAdapter.sqlQuery(queryBuilder); while (paramCursor.moveToNext()) { long paramID = CursorHelper.getLongFromCursor(paramCursor, RuleActionParameterDbAdapter.KEY_RULEACTIONPARAMETERID); String newParamData = CursorHelper.getStringFromCursor(paramCursor, RuleActionParameterDbAdapter.KEY_RULEACTIONPARAMETERDATA).replaceAll( "<" + attributeName + ">", "<" + newAttributeName + ">"); ruleActionParamDbAdapter.update(paramID, null, null, newParamData); } paramCursor.close(); } cursor.close(); } private static void alterFailedActionsTable(SQLiteDatabase db) { db.execSQL(FailedActionsDbAdapter.DATABASE_DROP); db.execSQL(FailedActionsDbAdapter.DATABASE_CREATE); } private static void addMissedCallEvent(SQLiteDatabase db) { RegisteredAppDbAdapter registeredAppDbAdapter = new RegisteredAppDbAdapter(db); Cursor cursor = registeredAppDbAdapter.fetchAll(MissedCallEvent.APPLICATION_NAME, null, null); cursor.moveToFirst(); long appId = getLongFromCursor(cursor, RegisteredAppDbAdapter.KEY_APPID); RegisteredEventDbAdapter registeredEventDbAdapter = new RegisteredEventDbAdapter(db); long eventIdMissedCall = registeredEventDbAdapter.insert(MissedCallEvent.EVENT_NAME, appId); DataTypeDbAdapter dataTypeDbAdapter = new DataTypeDbAdapter(db); RegisteredEventAttributeDbAdapter eventAttributeDbAdapter = new RegisteredEventAttributeDbAdapter(db); // cursor = dataTypeDbAdapter.fetchAll(OmniPhoneNumber.DB_NAME, OmniPhoneNumber.class.getName()); cursor.moveToFirst(); long dataTypeIdPhoneNumber = CursorHelper.getLongFromCursor(cursor, DataTypeDbAdapter.KEY_DATATYPEID); eventAttributeDbAdapter.insert(MissedCallEvent.ATTRIBUTE_PHONE_NUMBER, eventIdMissedCall, dataTypeIdPhoneNumber); } private static void addBluetooth(SQLiteDatabase db) { RegisteredAppDbAdapter appDbAdapter = new RegisteredAppDbAdapter(db); long appId = appDbAdapter.getAppId(DbHelper.AppName.SIGNALS); RegisteredActionDbAdapter actionDbAdapter = new RegisteredActionDbAdapter(db); actionDbAdapter.insert(TurnOffBluetoothAction.ACTION_NAME, appId); actionDbAdapter.insert(TurnOnBluetoothAction.ACTION_NAME, appId); } private static void addPowerOffAction(SQLiteDatabase db) { RegisteredAppDbAdapter appDbAdapter = new RegisteredAppDbAdapter(db); long appId = appDbAdapter.getAppId(OmniAction.APP_NAME); RegisteredActionDbAdapter actionDbAdapter = new RegisteredActionDbAdapter(db); /* * Previous builds (since the introduction of this action) had a bug due to which this action * would get inserted in a fresh database but not when upgrading from a previous version. * This was fixed by subsequently bumping the DB version and adding this method. However, to * prevent inserting the action twice, we need to check if it's already there. */ Cursor cursor = actionDbAdapter.fetchAll(PowerOffAction.ACTION_NAME, appId); if (!cursor.moveToFirst()) { actionDbAdapter.insert(PowerOffAction.ACTION_NAME, appId); } cursor.close(); } }