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 android.app.NotificationManager; 36 import android.bluetooth.BluetoothDevice; 37 import android.bluetooth.BluetoothDevicePicker; 38 import android.content.BroadcastReceiver; 39 import android.content.ContentValues; 40 import android.content.Context; 41 import android.content.Intent; 42 import android.database.Cursor; 43 import android.net.Uri; 44 import android.util.Log; 45 import android.widget.Toast; 46 47 import com.android.bluetooth.R; 48 import com.android.bluetooth.Utils; 49 50 /** 51 * Receives and handles: system broadcasts; Intents from other applications; 52 * Intents from OppService; Intents from modules in Opp application layer. 53 */ 54 public class BluetoothOppReceiver extends BroadcastReceiver { 55 private static final String TAG = "BluetoothOppReceiver"; 56 private static final boolean D = Constants.DEBUG; 57 private static final boolean V = Constants.VERBOSE; 58 59 @Override onReceive(Context context, Intent intent)60 public void onReceive(Context context, Intent intent) { 61 String action = intent.getAction(); 62 if (D) Log.d(TAG, " action :" + action); 63 if (action == null) return; 64 if (action.equals(BluetoothDevicePicker.ACTION_DEVICE_SELECTED)) { 65 BluetoothOppManager mOppManager = BluetoothOppManager.getInstance(context); 66 67 BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 68 69 if (D) { 70 Log.d(TAG, "Received BT device selected intent, bt device: " + remoteDevice); 71 } 72 73 if (remoteDevice == null) { 74 mOppManager.cleanUpSendingFileInfo(); 75 return; 76 } 77 // Insert transfer session record to database 78 mOppManager.startTransfer(remoteDevice); 79 80 // Display toast message 81 String deviceName = mOppManager.getDeviceName(remoteDevice); 82 String toastMsg; 83 int batchSize = mOppManager.getBatchSize(); 84 if (mOppManager.mMultipleFlag) { 85 toastMsg = context.getString(R.string.bt_toast_5, Integer.toString(batchSize), 86 deviceName); 87 } else { 88 toastMsg = context.getString(R.string.bt_toast_4, deviceName); 89 } 90 Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show(); 91 } else if (action.equals(Constants.ACTION_INCOMING_FILE_CONFIRM)) { 92 if (V) { 93 Log.v(TAG, "Receiver ACTION_INCOMING_FILE_CONFIRM"); 94 } 95 96 Uri uri = intent.getData(); 97 Intent in = new Intent(context, BluetoothOppIncomingFileConfirmActivity.class); 98 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 99 in.setDataAndNormalize(uri); 100 context.startActivity(in); 101 102 } else if (action.equals(Constants.ACTION_DECLINE)) { 103 if (V) { 104 Log.v(TAG, "Receiver ACTION_DECLINE"); 105 } 106 107 Uri uri = intent.getData(); 108 ContentValues values = new ContentValues(); 109 values.put(BluetoothShare.USER_CONFIRMATION, BluetoothShare.USER_CONFIRMATION_DENIED); 110 context.getContentResolver().update(uri, values, null, null); 111 cancelNotification(context, BluetoothOppNotification.NOTIFICATION_ID_PROGRESS); 112 113 } else if (action.equals(Constants.ACTION_ACCEPT)) { 114 if (V) { 115 Log.v(TAG, "Receiver ACTION_ACCEPT"); 116 } 117 118 Uri uri = intent.getData(); 119 ContentValues values = new ContentValues(); 120 values.put(BluetoothShare.USER_CONFIRMATION, 121 BluetoothShare.USER_CONFIRMATION_CONFIRMED); 122 context.getContentResolver().update(uri, values, null, null); 123 } else if (action.equals(Constants.ACTION_OPEN) || action.equals(Constants.ACTION_LIST)) { 124 if (V) { 125 if (action.equals(Constants.ACTION_OPEN)) { 126 Log.v(TAG, "Receiver open for " + intent.getData()); 127 } else { 128 Log.v(TAG, "Receiver list for " + intent.getData()); 129 } 130 } 131 132 BluetoothOppTransferInfo transInfo = new BluetoothOppTransferInfo(); 133 Uri uri = intent.getData(); 134 transInfo = BluetoothOppUtility.queryRecord(context, uri); 135 if (transInfo == null) { 136 Log.e(TAG, "Error: Can not get data from db"); 137 return; 138 } 139 140 if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND 141 && BluetoothShare.isStatusSuccess(transInfo.mStatus)) { 142 // if received file successfully, open this file 143 BluetoothOppUtility.openReceivedFile(context, transInfo.mFileName, 144 transInfo.mFileType, transInfo.mTimeStamp, uri); 145 BluetoothOppUtility.updateVisibilityToHidden(context, uri); 146 } else { 147 Intent in = new Intent(context, BluetoothOppTransferActivity.class); 148 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 149 in.setDataAndNormalize(uri); 150 context.startActivity(in); 151 } 152 153 } else if (action.equals(Constants.ACTION_OPEN_OUTBOUND_TRANSFER)) { 154 if (V) { 155 Log.v(TAG, "Received ACTION_OPEN_OUTBOUND_TRANSFER."); 156 } 157 158 Intent in = new Intent(context, BluetoothOppTransferHistory.class); 159 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 160 in.putExtra("direction", BluetoothShare.DIRECTION_OUTBOUND); 161 context.startActivity(in); 162 } else if (action.equals(Constants.ACTION_OPEN_INBOUND_TRANSFER)) { 163 if (V) { 164 Log.v(TAG, "Received ACTION_OPEN_INBOUND_TRANSFER."); 165 } 166 167 Intent in = new Intent(context, BluetoothOppTransferHistory.class); 168 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 169 in.putExtra("direction", BluetoothShare.DIRECTION_INBOUND); 170 context.startActivity(in); 171 } else if (action.equals(Constants.ACTION_OPEN_RECEIVED_FILES)) { 172 if (V) { 173 Log.v(TAG, "Received ACTION_OPEN_RECEIVED_FILES."); 174 } 175 176 Intent in = new Intent(context, BluetoothOppTransferHistory.class); 177 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 178 in.putExtra("direction", BluetoothShare.DIRECTION_INBOUND); 179 in.putExtra(Constants.EXTRA_SHOW_ALL_FILES, true); 180 context.startActivity(in); 181 } else if (action.equals(Constants.ACTION_HIDE)) { 182 if (V) { 183 Log.v(TAG, "Receiver hide for " + intent.getData()); 184 } 185 Cursor cursor = 186 context.getContentResolver().query(intent.getData(), null, null, null, null); 187 if (cursor != null) { 188 if (cursor.moveToFirst()) { 189 int visibilityColumn = cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY); 190 int visibility = cursor.getInt(visibilityColumn); 191 int userConfirmationColumn = 192 cursor.getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION); 193 int userConfirmation = cursor.getInt(userConfirmationColumn); 194 if (((userConfirmation == BluetoothShare.USER_CONFIRMATION_PENDING)) 195 && visibility == BluetoothShare.VISIBILITY_VISIBLE) { 196 ContentValues values = new ContentValues(); 197 values.put(BluetoothShare.VISIBILITY, BluetoothShare.VISIBILITY_HIDDEN); 198 context.getContentResolver().update(intent.getData(), values, null, null); 199 if (V) { 200 Log.v(TAG, "Action_hide received and db updated"); 201 } 202 } 203 } 204 cursor.close(); 205 } 206 } else if (action.equals(Constants.ACTION_COMPLETE_HIDE)) { 207 if (V) { 208 Log.v(TAG, "Receiver ACTION_COMPLETE_HIDE"); 209 } 210 ContentValues updateValues = new ContentValues(); 211 updateValues.put(BluetoothShare.VISIBILITY, BluetoothShare.VISIBILITY_HIDDEN); 212 context.getContentResolver() 213 .update(BluetoothShare.CONTENT_URI, updateValues, 214 BluetoothOppNotification.WHERE_COMPLETED, null); 215 } else if (action.equals(BluetoothShare.TRANSFER_COMPLETED_ACTION)) { 216 if (V) { 217 Log.v(TAG, "Receiver Transfer Complete Intent for " + intent.getData()); 218 } 219 220 String toastMsg = null; 221 BluetoothOppTransferInfo transInfo = new BluetoothOppTransferInfo(); 222 transInfo = BluetoothOppUtility.queryRecord(context, intent.getData()); 223 if (transInfo == null) { 224 Log.e(TAG, "Error: Can not get data from db"); 225 return; 226 } 227 228 if (transInfo.mHandoverInitiated) { 229 // Deal with handover-initiated transfers separately 230 Intent handoverIntent = new Intent(Constants.ACTION_BT_OPP_TRANSFER_DONE); 231 if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND) { 232 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_DIRECTION, 233 Constants.DIRECTION_BLUETOOTH_INCOMING); 234 } else { 235 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_DIRECTION, 236 Constants.DIRECTION_BLUETOOTH_OUTGOING); 237 } 238 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_ID, transInfo.mID); 239 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_ADDRESS, transInfo.mDestAddr); 240 241 if (BluetoothShare.isStatusSuccess(transInfo.mStatus)) { 242 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_STATUS, 243 Constants.HANDOVER_TRANSFER_STATUS_SUCCESS); 244 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_URI, 245 transInfo.mFileName); 246 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_MIMETYPE, 247 transInfo.mFileType); 248 } else { 249 handoverIntent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_STATUS, 250 Constants.HANDOVER_TRANSFER_STATUS_FAILURE); 251 } 252 context.sendBroadcast(handoverIntent, Constants.HANDOVER_STATUS_PERMISSION, 253 Utils.getTempAllowlistBroadcastOptions()); 254 return; 255 } 256 257 if (BluetoothShare.isStatusSuccess(transInfo.mStatus)) { 258 if (transInfo.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 259 toastMsg = context.getString(R.string.notification_sent, transInfo.mFileName); 260 } else if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND) { 261 toastMsg = 262 context.getString(R.string.notification_received, transInfo.mFileName); 263 } 264 265 } else if (BluetoothShare.isStatusError(transInfo.mStatus)) { 266 if (transInfo.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 267 toastMsg = 268 context.getString(R.string.notification_sent_fail, transInfo.mFileName); 269 } else if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND) { 270 toastMsg = context.getString(R.string.download_fail_line1); 271 } 272 } 273 if (V) { 274 Log.v(TAG, "Toast msg == " + toastMsg); 275 } 276 if (toastMsg != null) { 277 Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show(); 278 } 279 } 280 } 281 cancelNotification(Context context, int id)282 private void cancelNotification(Context context, int id) { 283 NotificationManager notMgr = 284 (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 285 if (notMgr == null) { 286 return; 287 } 288 notMgr.cancel(id); 289 if (V) { 290 Log.v(TAG, "notMgr.cancel called"); 291 } 292 } 293 } 294