11a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott/*
28188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski * Copyright (C) 2013 The Android Open Source Project
31a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott *
41a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott * Licensed under the Apache License, Version 2.0 (the "License");
51a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott * you may not use this file except in compliance with the License.
61a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott * You may obtain a copy of the License at
71a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott *
81a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott *      http://www.apache.org/licenses/LICENSE-2.0
91a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott *
101a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott * Unless required by applicable law or agreed to in writing, software
111a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott * distributed under the License is distributed on an "AS IS" BASIS,
121a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott * See the License for the specific language governing permissions and
141a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott * limitations under the License.
151a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott */
161a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott
17b839a7d1f42a1f3d58887f5a3c7978791d508cdbPaul Sliwowskipackage com.android.deskclock.provider;
181a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott
191a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scottimport android.content.ContentValues;
201a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scottimport android.content.Context;
210a117b5dee4c7666ab9c15787d4e0a802545278aChiao Chengimport android.database.Cursor;
221a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scottimport android.database.SQLException;
231a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scottimport android.database.sqlite.SQLiteDatabase;
241a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scottimport android.database.sqlite.SQLiteOpenHelper;
25ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowskiimport android.net.Uri;
26fd8ddaaa59e8b5e150ac450baad16dfaee1b1881Paul Sliwowskiimport android.text.TextUtils;
271a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott
28cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassenimport com.android.deskclock.LogUtils;
29ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski
30ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowskiimport java.util.Calendar;
31b839a7d1f42a1f3d58887f5a3c7978791d508cdbPaul Sliwowski
321a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott/**
331a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott * Helper class for opening the database from multiple providers.  Also provides
341a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott * some common functionality.
351a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott */
36b839a7d1f42a1f3d58887f5a3c7978791d508cdbPaul Sliwowskiclass ClockDatabaseHelper extends SQLiteOpenHelper {
37ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski    /**
38ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski     * Original Clock Database.
39ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski     **/
40ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski    private static final int VERSION_5 = 5;
41ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski
42ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski    /**
43ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski     * Introduce:
44ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski     * Added alarm_instances table
45ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski     * Added selected_cities table
46ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski     * Added DELETE_AFTER_USE column to alarms table
47ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski     */
48ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski    private static final int VERSION_6 = 6;
49ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski
50ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski    /**
51ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski     * Added alarm settings to instance table.
52ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski     */
53ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski    private static final int VERSION_7 = 7;
541a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott
558188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    // This creates a default alarm at 8:30 for every Mon,Tue,Wed,Thu,Fri
56ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski    private static final String DEFAULT_ALARM_1 = "(8, 30, 31, 0, 0, '', NULL, 0);";
578188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski
588188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    // This creates a default alarm at 9:30 for every Sat,Sun
59ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski    private static final String DEFAULT_ALARM_2 = "(9, 00, 96, 0, 0, '', NULL, 0);";
608188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski
618188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    // Database and table names
628188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    static final String DATABASE_NAME = "alarms.db";
63ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski    static final String OLD_ALARMS_TABLE_NAME = "alarms";
64ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski    static final String ALARMS_TABLE_NAME = "alarm_templates";
658188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    static final String INSTANCES_TABLE_NAME = "alarm_instances";
668188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    static final String CITIES_TABLE_NAME = "selected_cities";
678188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski
688188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    private static void createAlarmsTable(SQLiteDatabase db) {
698188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski        db.execSQL("CREATE TABLE " + ALARMS_TABLE_NAME + " (" +
708188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                ClockContract.AlarmsColumns._ID + " INTEGER PRIMARY KEY," +
71ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.AlarmsColumns.HOUR + " INTEGER NOT NULL, " +
72ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.AlarmsColumns.MINUTES + " INTEGER NOT NULL, " +
73ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.AlarmsColumns.DAYS_OF_WEEK + " INTEGER NOT NULL, " +
74ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.AlarmsColumns.ENABLED + " INTEGER NOT NULL, " +
75ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.AlarmsColumns.VIBRATE + " INTEGER NOT NULL, " +
76ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.AlarmsColumns.LABEL + " TEXT NOT NULL, " +
77ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.AlarmsColumns.RINGTONE + " TEXT, " +
78ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.AlarmsColumns.DELETE_AFTER_USE + " INTEGER NOT NULL DEFAULT 0);");
79cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen        LogUtils.i("Alarms Table created");
808188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    }
818188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski
828188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    private static void createInstanceTable(SQLiteDatabase db) {
838188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski        db.execSQL("CREATE TABLE " + INSTANCES_TABLE_NAME + " (" +
848188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                ClockContract.InstancesColumns._ID + " INTEGER PRIMARY KEY," +
85ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.InstancesColumns.YEAR + " INTEGER NOT NULL, " +
86ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.InstancesColumns.MONTH + " INTEGER NOT NULL, " +
87ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.InstancesColumns.DAY + " INTEGER NOT NULL, " +
88ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.InstancesColumns.HOUR + " INTEGER NOT NULL, " +
89ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.InstancesColumns.MINUTES + " INTEGER NOT NULL, " +
90ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.InstancesColumns.VIBRATE + " INTEGER NOT NULL, " +
91ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.InstancesColumns.LABEL + " TEXT NOT NULL, " +
92ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.InstancesColumns.RINGTONE + " TEXT, " +
93ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.InstancesColumns.ALARM_STATE + " INTEGER NOT NULL, " +
948188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                ClockContract.InstancesColumns.ALARM_ID + " INTEGER REFERENCES " +
958188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                    ALARMS_TABLE_NAME + "(" + ClockContract.AlarmsColumns._ID + ") " +
968188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                    "ON UPDATE CASCADE ON DELETE CASCADE" +
978188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                ");");
98cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen        LogUtils.i("Instance table created");
998188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    }
1008188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski
1018188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    private static void createCitiesTable(SQLiteDatabase db) {
1028188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski        db.execSQL("CREATE TABLE " + CITIES_TABLE_NAME + " (" +
1038188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                ClockContract.CitiesColumns.CITY_ID + " TEXT PRIMARY KEY," +
104ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.CitiesColumns.CITY_NAME + " TEXT NOT NULL, " +
105ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.CitiesColumns.TIMEZONE_NAME + " TEXT NOT NULL, " +
106ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.CitiesColumns.TIMEZONE_OFFSET + " INTEGER NOT NULL);");
107cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen        LogUtils.i("Cities table created");
1088188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    }
1091a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott
110ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski    private Context mContext;
111ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski
112b839a7d1f42a1f3d58887f5a3c7978791d508cdbPaul Sliwowski    public ClockDatabaseHelper(Context context) {
113ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski        super(context, DATABASE_NAME, null, VERSION_7);
114ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski        mContext = context;
1151a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott    }
1161a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott
1171a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott    @Override
1181a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott    public void onCreate(SQLiteDatabase db) {
1198188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski        createAlarmsTable(db);
1208188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski        createInstanceTable(db);
1218188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski        createCitiesTable(db);
1221a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott
1231a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott        // insert default alarms
124cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen        LogUtils.i("Inserting default alarms");
125982295f9412d9ce7474c902aa0d8de8fce9890d4Isaac Katzenelson        String cs = ", "; //comma and space
1268188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski        String insertMe = "INSERT INTO " + ALARMS_TABLE_NAME + " (" +
1278188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                ClockContract.AlarmsColumns.HOUR + cs +
1288188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                ClockContract.AlarmsColumns.MINUTES + cs +
1298188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                ClockContract.AlarmsColumns.DAYS_OF_WEEK + cs +
1308188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                ClockContract.AlarmsColumns.ENABLED + cs +
1318188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                ClockContract.AlarmsColumns.VIBRATE + cs +
132ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.AlarmsColumns.LABEL + cs +
133ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                ClockContract.AlarmsColumns.RINGTONE + cs +
1347ef0150a7ba2aa09c7138563cd7ef6984ed7fc56Paul Sliwowski                ClockContract.AlarmsColumns.DELETE_AFTER_USE + ") VALUES ";
1358188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski        db.execSQL(insertMe + DEFAULT_ALARM_1);
1368188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski        db.execSQL(insertMe + DEFAULT_ALARM_2);
1371a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott    }
1381a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott
1391a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott    @Override
1408188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
141cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen        LogUtils.v("Upgrading alarms database from version "
142cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen                + oldVersion + " to " + currentVersion);
1438188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski
144ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski        if (oldVersion <= VERSION_6) {
145ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski            // These were not used in DB_VERSION_6, so we can just drop them.
146285aa982a20eb686512c4c72ca54524c4b55aefdPaul Sliwowski            db.execSQL("DROP TABLE IF EXISTS " + INSTANCES_TABLE_NAME + ";");
147285aa982a20eb686512c4c72ca54524c4b55aefdPaul Sliwowski            db.execSQL("DROP TABLE IF EXISTS " + CITIES_TABLE_NAME + ";");
148ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski
149ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski            // Create new alarms table and copy over the data
150ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski            createAlarmsTable(db);
151a5a4521002afe0e2c9fd354cf9cf978145354f91Paul Sliwowski            createInstanceTable(db);
152a5a4521002afe0e2c9fd354cf9cf978145354f91Paul Sliwowski            createCitiesTable(db);
153a5a4521002afe0e2c9fd354cf9cf978145354f91Paul Sliwowski
154cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen            LogUtils.i("Copying old alarms to new table");
155ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski            String[] OLD_TABLE_COLUMNS = {
156ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    "_id",
157ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    "hour",
158ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    "minutes",
159ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    "daysofweek",
160ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    "enabled",
161ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    "vibrate",
162ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    "message",
163ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    "alert",
164ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski            };
165ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski            Cursor cursor = db.query(OLD_ALARMS_TABLE_NAME, OLD_TABLE_COLUMNS,
166ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    null, null, null, null, null);
167ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski            Calendar currentTime = Calendar.getInstance();
168ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski            while (cursor.moveToNext()) {
169ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                Alarm alarm = new Alarm();
170ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                alarm.id = cursor.getLong(0);
171ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                alarm.hour = cursor.getInt(1);
172ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                alarm.minutes = cursor.getInt(2);
173ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                alarm.daysOfWeek = new DaysOfWeek(cursor.getInt(3));
174ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                alarm.enabled = cursor.getInt(4) == 1;
175ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                alarm.vibrate = cursor.getInt(5) == 1;
176ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                alarm.label = cursor.getString(6);
177ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski
178ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                String alertString = cursor.getString(7);
179ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                if ("silent".equals(alertString)) {
180ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    alarm.alert = Alarm.NO_RINGTONE_URI;
181ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                } else {
182fd8ddaaa59e8b5e150ac450baad16dfaee1b1881Paul Sliwowski                    alarm.alert = TextUtils.isEmpty(alertString) ? null : Uri.parse(alertString);
183ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                }
184ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski
185ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                // Save new version of alarm and create alarminstance for it
186ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                db.insert(ALARMS_TABLE_NAME, null, Alarm.createContentValues(alarm));
187ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                if (alarm.enabled) {
188ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    AlarmInstance newInstance = alarm.createInstanceAfter(currentTime);
189ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                    db.insert(INSTANCES_TABLE_NAME, null,
190ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                            AlarmInstance.createContentValues(newInstance));
191ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski                }
192ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski            }
193ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski            cursor.close();
194ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski
195cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen            LogUtils.i("Dropping old alarm table");
196285aa982a20eb686512c4c72ca54524c4b55aefdPaul Sliwowski            db.execSQL("DROP TABLE IF EXISTS " + OLD_ALARMS_TABLE_NAME + ";");
1978188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski        }
1981a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott    }
1991a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott
2008188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski    long fixAlarmInsert(ContentValues values) {
201ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski        // Why are we doing this? Is this not a programming bug if we try to
202ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski        // insert an already used id?
2031a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott        SQLiteDatabase db = getWritableDatabase();
2040a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng        db.beginTransaction();
2050a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng        long rowId = -1;
2060a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng        try {
2070a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng            // Check if we are trying to re-use an existing id.
2088188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski            Object value = values.get(ClockContract.AlarmsColumns._ID);
2090a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng            if (value != null) {
210b9dff52be236a4c3a2088ecbbdf9811b0533d21fSam Blitzstein                long id = (Long) value;
2110a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng                if (id > -1) {
2128188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                    final Cursor cursor = db.query(ALARMS_TABLE_NAME,
2138188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                            new String[]{ClockContract.AlarmsColumns._ID},
2148188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                            ClockContract.AlarmsColumns._ID + " = ?",
215982295f9412d9ce7474c902aa0d8de8fce9890d4Isaac Katzenelson                            new String[]{id + ""}, null, null, null);
2160a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng                    if (cursor.moveToFirst()) {
2170a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng                        // Record exists. Remove the id so sqlite can generate a new one.
2188188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski                        values.putNull(ClockContract.AlarmsColumns._ID);
2190a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng                    }
2200a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng                }
2210a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng            }
2220a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng
223ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowski            rowId = db.insert(ALARMS_TABLE_NAME, ClockContract.AlarmsColumns.RINGTONE, values);
2240a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng            db.setTransactionSuccessful();
2250a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng        } finally {
2260a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng            db.endTransaction();
2270a117b5dee4c7666ab9c15787d4e0a802545278aChiao Cheng        }
2281a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott        if (rowId < 0) {
2291a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott            throw new SQLException("Failed to insert row");
2301a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott        }
231cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen        LogUtils.v("Added alarm rowId = " + rowId);
2321a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott
2338188813bc869d3df4885f9c2972f9cc85745b59bPaul Sliwowski        return rowId;
2341a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott    }
2351a7925761a5db1b424d976ba03fb335e821b7db3Patrick Scott}
236