1 /* 2 * Copyright (c) 2008-2009, Motorola, Inc. 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * - Neither the name of the Motorola, Inc. nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package com.android.bluetooth.opp; 34 35 import com.android.bluetooth.R; 36 37 import android.app.NotificationManager; 38 import android.bluetooth.BluetoothAdapter; 39 import android.bluetooth.BluetoothDevice; 40 import android.bluetooth.BluetoothDevicePicker; 41 import android.content.BroadcastReceiver; 42 import android.content.ContentUris; 43 import android.content.ContentValues; 44 import android.content.Context; 45 import android.content.Intent; 46 import android.database.Cursor; 47 import android.net.Uri; 48 import android.util.Log; 49 import android.widget.Toast; 50 51 /** 52 * Receives and handles: system broadcasts; Intents from other applications; 53 * Intents from OppService; Intents from modules in Opp application layer. 54 */ 55 public class BluetoothOppReceiver extends BroadcastReceiver { 56 private static final String TAG = "BluetoothOppReceiver"; 57 private static final boolean D = Constants.DEBUG; 58 private static final boolean V = Constants.VERBOSE; 59 60 @Override onReceive(Context context, Intent intent)61 public void onReceive(Context context, Intent intent) { 62 String action = intent.getAction(); 63 64 65 if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { 66 if (BluetoothAdapter.STATE_ON == intent.getIntExtra( 67 BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) { 68 if (V) Log.v(TAG, "Received BLUETOOTH_STATE_CHANGED_ACTION, BLUETOOTH_STATE_ON"); 69 context.startService(new Intent(context, BluetoothOppService.class)); 70 71 // If this is within a sending process, continue the handle 72 // logic to display device picker dialog. 73 synchronized (this) { 74 if (BluetoothOppManager.getInstance(context).mSendingFlag) { 75 // reset the flags 76 BluetoothOppManager.getInstance(context).mSendingFlag = false; 77 78 Intent in1 = new Intent(BluetoothDevicePicker.ACTION_LAUNCH); 79 in1.putExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false); 80 in1.putExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE, 81 BluetoothDevicePicker.FILTER_TYPE_TRANSFER); 82 in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE, 83 Constants.THIS_PACKAGE_NAME); 84 in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS, 85 BluetoothOppReceiver.class.getName()); 86 87 in1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 88 context.startActivity(in1); 89 } 90 } 91 } 92 } else if (action.equals(BluetoothDevicePicker.ACTION_DEVICE_SELECTED)) { 93 BluetoothOppManager mOppManager = BluetoothOppManager.getInstance(context); 94 95 BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 96 97 if (V) Log.v(TAG, "Received BT device selected intent, bt device: " + remoteDevice); 98 99 // Insert transfer session record to database 100 mOppManager.startTransfer(remoteDevice); 101 102 // Display toast message 103 String deviceName = mOppManager.getDeviceName(remoteDevice); 104 String toastMsg; 105 int batchSize = mOppManager.getBatchSize(); 106 if (mOppManager.mMultipleFlag) { 107 toastMsg = context.getString(R.string.bt_toast_5, Integer.toString(batchSize), 108 deviceName); 109 } else { 110 toastMsg = context.getString(R.string.bt_toast_4, deviceName); 111 } 112 Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show(); 113 } else if (action.equals(Constants.ACTION_INCOMING_FILE_CONFIRM)) { 114 if (V) Log.v(TAG, "Receiver ACTION_INCOMING_FILE_CONFIRM"); 115 116 Uri uri = intent.getData(); 117 Intent in = new Intent(context, BluetoothOppIncomingFileConfirmActivity.class); 118 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 119 in.setDataAndNormalize(uri); 120 context.startActivity(in); 121 cancelNotification(context, uri); 122 123 } else if (action.equals(Constants.ACTION_DECLINE)) { 124 if (V) Log.v(TAG, "Receiver ACTION_DECLINE"); 125 126 Uri uri = intent.getData(); 127 ContentValues values = new ContentValues(); 128 values.put(BluetoothShare.USER_CONFIRMATION, BluetoothShare.USER_CONFIRMATION_DENIED); 129 context.getContentResolver().update(uri, values, null, null); 130 cancelNotification(context, uri); 131 132 } else if (action.equals(Constants.ACTION_ACCEPT)) { 133 if (V) Log.v(TAG, "Receiver ACTION_ACCEPT"); 134 135 Uri uri = intent.getData(); 136 ContentValues values = new ContentValues(); 137 values.put(BluetoothShare.USER_CONFIRMATION, BluetoothShare.USER_CONFIRMATION_CONFIRMED); 138 context.getContentResolver().update(uri, values, null, null); 139 cancelNotification(context, uri); 140 141 } else if (action.equals(Constants.ACTION_OPEN) || action.equals(Constants.ACTION_LIST)) { 142 if (V) { 143 if (action.equals(Constants.ACTION_OPEN)) { 144 Log.v(TAG, "Receiver open for " + intent.getData()); 145 } else { 146 Log.v(TAG, "Receiver list for " + intent.getData()); 147 } 148 } 149 150 BluetoothOppTransferInfo transInfo = new BluetoothOppTransferInfo(); 151 Uri uri = intent.getData(); 152 transInfo = BluetoothOppUtility.queryRecord(context, uri); 153 if (transInfo == null) { 154 Log.e(TAG, "Error: Can not get data from db"); 155 return; 156 } 157 158 if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND 159 && BluetoothShare.isStatusSuccess(transInfo.mStatus)) { 160 // if received file successfully, open this file 161 BluetoothOppUtility.openReceivedFile(context, transInfo.mFileName, 162 transInfo.mFileType, transInfo.mTimeStamp, uri); 163 BluetoothOppUtility.updateVisibilityToHidden(context, uri); 164 } else { 165 Intent in = new Intent(context, BluetoothOppTransferActivity.class); 166 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 167 in.setDataAndNormalize(uri); 168 context.startActivity(in); 169 } 170 171 cancelNotification(context, uri); 172 } else if (action.equals(Constants.ACTION_OPEN_OUTBOUND_TRANSFER)) { 173 if (V) Log.v(TAG, "Received ACTION_OPEN_OUTBOUND_TRANSFER."); 174 175 Intent in = new Intent(context, BluetoothOppTransferHistory.class); 176 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 177 in.putExtra("direction", BluetoothShare.DIRECTION_OUTBOUND); 178 context.startActivity(in); 179 } else if (action.equals(Constants.ACTION_OPEN_INBOUND_TRANSFER)) { 180 if (V) Log.v(TAG, "Received ACTION_OPEN_INBOUND_TRANSFER."); 181 182 Intent in = new Intent(context, BluetoothOppTransferHistory.class); 183 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 184 in.putExtra("direction", BluetoothShare.DIRECTION_INBOUND); 185 context.startActivity(in); 186 } else if (action.equals(Constants.ACTION_OPEN_RECEIVED_FILES)) { 187 if (V) Log.v(TAG, "Received ACTION_OPEN_RECEIVED_FILES."); 188 189 Intent in = new Intent(context, BluetoothOppTransferHistory.class); 190 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 191 in.putExtra("direction", BluetoothShare.DIRECTION_INBOUND); 192 in.putExtra(Constants.EXTRA_SHOW_ALL_FILES, true); 193 context.startActivity(in); 194 } else if (action.equals(Constants.ACTION_HIDE)) { 195 if (V) Log.v(TAG, "Receiver hide for " + intent.getData()); 196 Cursor cursor = context.getContentResolver().query(intent.getData(), null, null, null, 197 null); 198 if (cursor != null) { 199 if (cursor.moveToFirst()) { 200 int statusColumn = cursor.getColumnIndexOrThrow(BluetoothShare.STATUS); 201 int status = cursor.getInt(statusColumn); 202 int visibilityColumn = cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY); 203 int visibility = cursor.getInt(visibilityColumn); 204 int userConfirmationColumn = cursor 205 .getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION); 206 int userConfirmation = cursor.getInt(userConfirmationColumn); 207 if (((userConfirmation == BluetoothShare.USER_CONFIRMATION_PENDING)) 208 && visibility == BluetoothShare.VISIBILITY_VISIBLE) { 209 ContentValues values = new ContentValues(); 210 values.put(BluetoothShare.VISIBILITY, BluetoothShare.VISIBILITY_HIDDEN); 211 context.getContentResolver().update(intent.getData(), values, null, null); 212 if (V) Log.v(TAG, "Action_hide received and db updated"); 213 } 214 } 215 cursor.close(); 216 } 217 } else if (action.equals(Constants.ACTION_COMPLETE_HIDE)) { 218 if (V) Log.v(TAG, "Receiver ACTION_COMPLETE_HIDE"); 219 ContentValues updateValues = new ContentValues(); 220 updateValues.put(BluetoothShare.VISIBILITY, BluetoothShare.VISIBILITY_HIDDEN); 221 context.getContentResolver().update(BluetoothShare.CONTENT_URI, updateValues, 222 BluetoothOppNotification.WHERE_COMPLETED, null); 223 } else if (action.equals(BluetoothShare.TRANSFER_COMPLETED_ACTION)) { 224 if (V) Log.v(TAG, "Receiver Transfer Complete Intent for " + intent.getData()); 225 226 String toastMsg = null; 227 BluetoothOppTransferInfo transInfo = new BluetoothOppTransferInfo(); 228 transInfo = BluetoothOppUtility.queryRecord(context, intent.getData()); 229 if (transInfo == null) { 230 Log.e(TAG, "Error: Can not get data from db"); 231 return; 232 } 233 234 if (transInfo.mHandoverInitiated) { 235 // Deal with handover-initiated transfers separately 236 Intent handoverIntent = new Intent(Constants.ACTION_BT_OPP_TRANSFER_DONE); 237 if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND) { 238 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_DIRECTION, 239 Constants.DIRECTION_BLUETOOTH_INCOMING); 240 } else { 241 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_DIRECTION, 242 Constants.DIRECTION_BLUETOOTH_OUTGOING); 243 } 244 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_ID, transInfo.mID); 245 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_ADDRESS, transInfo.mDestAddr); 246 247 if (BluetoothShare.isStatusSuccess(transInfo.mStatus)) { 248 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_STATUS, 249 Constants.HANDOVER_TRANSFER_STATUS_SUCCESS); 250 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_URI, 251 transInfo.mFileName); 252 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_MIMETYPE, 253 transInfo.mFileType); 254 } else { 255 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_STATUS, 256 Constants.HANDOVER_TRANSFER_STATUS_FAILURE); 257 } 258 context.sendBroadcast(handoverIntent, Constants.HANDOVER_STATUS_PERMISSION); 259 return; 260 } 261 262 if (BluetoothShare.isStatusSuccess(transInfo.mStatus)) { 263 if (transInfo.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 264 toastMsg = context.getString(R.string.notification_sent, transInfo.mFileName); 265 } else if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND) { 266 toastMsg = context.getString(R.string.notification_received, 267 transInfo.mFileName); 268 } 269 270 } else if (BluetoothShare.isStatusError(transInfo.mStatus)) { 271 if (transInfo.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 272 toastMsg = context.getString(R.string.notification_sent_fail, 273 transInfo.mFileName); 274 } else if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND) { 275 toastMsg = context.getString(R.string.download_fail_line1); 276 } 277 } 278 if (V) Log.v(TAG, "Toast msg == " + toastMsg); 279 if (toastMsg != null) { 280 Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show(); 281 } 282 } 283 } 284 cancelNotification(Context context, Uri uri)285 private void cancelNotification(Context context, Uri uri) { 286 NotificationManager notMgr = (NotificationManager)context 287 .getSystemService(Context.NOTIFICATION_SERVICE); 288 if (notMgr == null) return; 289 290 int id = -1; 291 try { 292 id = (int) ContentUris.parseId(uri); 293 } catch (NumberFormatException ex) { 294 Log.v(TAG, "Can't parse notification ID from Uri!"); 295 return; 296 } 297 298 notMgr.cancel(id); 299 if (V) Log.v(TAG, "notMgr.cancel called"); 300 } 301 } 302