150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby/* 250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Copyright (C) 2011 The Android Open Source Project 350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * 450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Licensed under the Apache License, Version 2.0 (the "License"); 550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * you may not use this file except in compliance with the License. 650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * You may obtain a copy of the License at 750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * 850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * http://www.apache.org/licenses/LICENSE-2.0 950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * 1050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Unless required by applicable law or agreed to in writing, software 1150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * distributed under the License is distributed on an "AS IS" BASIS, 1250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * See the License for the specific language governing permissions and 1450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * limitations under the License. 1550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby */ 1650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 1750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambypackage com.android.cellbroadcastreceiver; 1850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 1950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.app.IntentService; 2050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.content.ContentValues; 2150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.content.Intent; 2250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.database.sqlite.SQLiteDatabase; 2350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.util.Log; 2450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 2550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby/** 2650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Service to update the SQLite database to add a new broadcast message, 2750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * or to delete one or all previously received broadcasts. 2850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby */ 2950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambypublic class CellBroadcastDatabaseService extends IntentService { 3050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby private static final String TAG = "CellBroadcastDatabaseService"; 3150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 3250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby /** Action to insert a new message (passed as CellBroadcastMessage extra). */ 3350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby static final String ACTION_INSERT_NEW_BROADCAST = "ACTION_INSERT_NEW_BROADCAST"; 3450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 3550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby /** Action to delete a single broadcast (row ID passed as extra). */ 3650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby static final String ACTION_DELETE_BROADCAST = "ACTION_DELETE_BROADCAST"; 3750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 3850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby /** Action to mark a broadcast as read by the user (by row ID or delivery time extra). */ 3950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby static final String ACTION_MARK_BROADCAST_READ = "ACTION_MARK_BROADCAST_READ"; 4050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 4150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby /** Action to delete all broadcasts from database (no extras). */ 4250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby static final String ACTION_DELETE_ALL_BROADCASTS = "ACTION_DELETE_ALL_BROADCASTS"; 4350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 4450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby /** Identifier for getExtra() for row ID to delete or mark read. */ 4550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby public static final String DATABASE_ROW_ID_EXTRA = 4650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby "com.android.cellbroadcastreceiver.DATABASE_ROW_ID"; 4750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 4850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby /** Identifier for getExtra() for delivery time of broadcast to mark read. */ 4950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby public static final String DATABASE_DELIVERY_TIME_EXTRA = 5050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby "com.android.cellbroadcastreceiver.DATABASE_DELIVERY_TIME"; 5150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 5250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby private SQLiteDatabase mBroadcastDb; 5350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 5450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby /** Callback for the active list activity when the contents change. */ 5550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby private static CellBroadcastListActivity sActiveListActivity; 5650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 5750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby public CellBroadcastDatabaseService() { 5850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby super(TAG); // use class name for worker thread name 5950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 6050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 6150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby @Override 6250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby public void onCreate() { 6350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby super.onCreate(); 6450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 6550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (mBroadcastDb == null) { 6650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby CellBroadcastDatabase.DatabaseHelper helper = 6750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby new CellBroadcastDatabase.DatabaseHelper(this); 6850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby mBroadcastDb = helper.getWritableDatabase(); 6950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 7050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 7150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 7250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby @Override 7350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby public void onDestroy() { 7450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby super.onDestroy(); 7550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 7650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (mBroadcastDb != null) { 7750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby mBroadcastDb.close(); 7850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby mBroadcastDb = null; 7950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 8050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 8150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 8250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby static void setActiveListActivity(CellBroadcastListActivity activity) { 8350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby sActiveListActivity = activity; 8450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 8550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 8650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby @Override 8750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby public void onHandleIntent(Intent intent) { 8850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby // TODO: security check to detect malicious broadcast injections 8950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby String action = intent.getAction(); 9050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby boolean notifyActiveListActivity = false; 9150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (ACTION_INSERT_NEW_BROADCAST.equals(action)) { 9250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby CellBroadcastMessage cbm = intent.getParcelableExtra( 9350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby CellBroadcastMessage.SMS_CB_MESSAGE_EXTRA); 9450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (cbm == null) { 9550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Log.e(TAG, "ACTION_INSERT_NEW_BROADCAST with no CB message extra"); 9650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby return; 9750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 9850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 9950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby ContentValues cv = cbm.getContentValues(); 10050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby long rowId = mBroadcastDb.insert(CellBroadcastDatabase.TABLE_NAME, null, cv); 10150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (rowId == -1) { 10250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Log.e(TAG, "failed to insert new broadcast into database!"); 10350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else { 10450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby notifyActiveListActivity = true; 10550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 10650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else if (ACTION_DELETE_BROADCAST.equals(action)) { 10750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby long rowId = intent.getLongExtra(DATABASE_ROW_ID_EXTRA, -1); 10850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (rowId == -1) { 10950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Log.e(TAG, "ACTION_DELETE_BROADCAST missing row ID to delete"); 11050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby return; 11150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 11250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 11350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby int rowCount = mBroadcastDb.delete(CellBroadcastDatabase.TABLE_NAME, 11450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby CellBroadcastDatabase.Columns._ID + "=?", 11550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby new String[]{Long.toString(rowId)}); 11650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (rowCount != 0) { 11750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby notifyActiveListActivity = true; 11850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 11950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else if (ACTION_DELETE_ALL_BROADCASTS.equals(action)) { 12050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby mBroadcastDb.delete(CellBroadcastDatabase.TABLE_NAME, null, null); 12150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby notifyActiveListActivity = true; 12250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else if (ACTION_MARK_BROADCAST_READ.equals(action)) { 12350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby long rowId = intent.getLongExtra(DATABASE_ROW_ID_EXTRA, -1); 12450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby long deliveryTime = intent.getLongExtra(DATABASE_DELIVERY_TIME_EXTRA, -1); 12550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (rowId == -1 && deliveryTime == -1) { 12650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Log.e(TAG, "ACTION_MARK_BROADCAST_READ missing row ID or delivery time"); 12750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby return; 12850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 12950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby ContentValues cv = new ContentValues(1); 13050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby cv.put(CellBroadcastDatabase.Columns.MESSAGE_READ, 1); 13150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby int rowCount; 13250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (rowId != -1) { 13350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby rowCount = mBroadcastDb.update(CellBroadcastDatabase.TABLE_NAME, cv, 13450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby CellBroadcastDatabase.Columns._ID + "=?", 13550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby new String[]{Long.toString(rowId)}); 13650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else { 13750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby rowCount = mBroadcastDb.update(CellBroadcastDatabase.TABLE_NAME, cv, 13850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby CellBroadcastDatabase.Columns.DELIVERY_TIME + "=?", 13950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby new String[]{Long.toString(deliveryTime)}); 14050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 14150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (rowCount != 0) { 14250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby notifyActiveListActivity = true; 14350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 14450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else { 14550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Log.e(TAG, "ignoring unexpected Intent with action " + action); 14650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 14750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (notifyActiveListActivity && sActiveListActivity != null) { 14850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby sActiveListActivity.databaseContentChanged(); 14950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 15050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 15150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby} 152