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.BluetoothMethodProxy; 48 import com.android.bluetooth.R; 49 import com.android.bluetooth.Utils; 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 if (D) Log.d(TAG, " action :" + action); 64 if (action == null) return; 65 if (action.equals(BluetoothDevicePicker.ACTION_DEVICE_SELECTED)) { 66 BluetoothOppManager mOppManager = BluetoothOppManager.getInstance(context); 67 68 BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 69 70 if (remoteDevice == null) { 71 mOppManager.cleanUpSendingFileInfo(); 72 return; 73 } 74 75 if (D) { 76 Log.d(TAG, "Received BT device selected intent, bt device: " + remoteDevice.getIdentityAddress()); 77 } 78 79 // Insert transfer session record to database 80 mOppManager.startTransfer(remoteDevice); 81 82 // Display toast message 83 String deviceName = mOppManager.getDeviceName(remoteDevice); 84 String toastMsg; 85 int batchSize = mOppManager.getBatchSize(); 86 if (mOppManager.mMultipleFlag) { 87 toastMsg = context.getString(R.string.bt_toast_5, Integer.toString(batchSize), 88 deviceName); 89 } else { 90 toastMsg = context.getString(R.string.bt_toast_4, deviceName); 91 } 92 Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show(); 93 } else if (action.equals(Constants.ACTION_INCOMING_FILE_CONFIRM)) { 94 if (V) { 95 Log.v(TAG, "Receiver ACTION_INCOMING_FILE_CONFIRM"); 96 } 97 98 Uri uri = intent.getData(); 99 Intent in = new Intent(context, BluetoothOppIncomingFileConfirmActivity.class); 100 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 101 in.setDataAndNormalize(uri); 102 context.startActivity(in); 103 104 } else if (action.equals(Constants.ACTION_DECLINE)) { 105 if (V) { 106 Log.v(TAG, "Receiver ACTION_DECLINE"); 107 } 108 109 Uri uri = intent.getData(); 110 ContentValues values = new ContentValues(); 111 values.put(BluetoothShare.USER_CONFIRMATION, BluetoothShare.USER_CONFIRMATION_DENIED); 112 BluetoothMethodProxy.getInstance().contentResolverUpdate(context.getContentResolver(), 113 uri, values, null, null); 114 cancelNotification(context, BluetoothOppNotification.NOTIFICATION_ID_PROGRESS); 115 116 } else if (action.equals(Constants.ACTION_ACCEPT)) { 117 if (V) { 118 Log.v(TAG, "Receiver ACTION_ACCEPT"); 119 } 120 121 Uri uri = intent.getData(); 122 ContentValues values = new ContentValues(); 123 values.put(BluetoothShare.USER_CONFIRMATION, 124 BluetoothShare.USER_CONFIRMATION_CONFIRMED); 125 BluetoothMethodProxy.getInstance().contentResolverUpdate(context.getContentResolver(), 126 uri, values, null, null); 127 } else if (action.equals(Constants.ACTION_OPEN) || action.equals(Constants.ACTION_LIST)) { 128 if (V) { 129 if (action.equals(Constants.ACTION_OPEN)) { 130 Log.v(TAG, "Receiver open for " + intent.getData()); 131 } else { 132 Log.v(TAG, "Receiver list for " + intent.getData()); 133 } 134 } 135 136 BluetoothOppTransferInfo transInfo = new BluetoothOppTransferInfo(); 137 Uri uri = intent.getData(); 138 transInfo = BluetoothOppUtility.queryRecord(context, uri); 139 if (transInfo == null) { 140 Log.e(TAG, "Error: Can not get data from db"); 141 return; 142 } 143 144 if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND 145 && BluetoothShare.isStatusSuccess(transInfo.mStatus)) { 146 // if received file successfully, open this file 147 BluetoothOppUtility.openReceivedFile(context, transInfo.mFileName, 148 transInfo.mFileType, transInfo.mTimeStamp, uri); 149 BluetoothOppUtility.updateVisibilityToHidden(context, uri); 150 } else { 151 Intent in = new Intent(context, BluetoothOppTransferActivity.class); 152 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 153 in.setDataAndNormalize(uri); 154 context.startActivity(in); 155 } 156 157 } else if (action.equals(Constants.ACTION_OPEN_OUTBOUND_TRANSFER)) { 158 if (V) { 159 Log.v(TAG, "Received ACTION_OPEN_OUTBOUND_TRANSFER."); 160 } 161 162 Intent in = new Intent(context, BluetoothOppTransferHistory.class); 163 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 164 in.putExtra("direction", BluetoothShare.DIRECTION_OUTBOUND); 165 context.startActivity(in); 166 } else if (action.equals(Constants.ACTION_OPEN_INBOUND_TRANSFER)) { 167 if (V) { 168 Log.v(TAG, "Received ACTION_OPEN_INBOUND_TRANSFER."); 169 } 170 171 Intent in = new Intent(context, BluetoothOppTransferHistory.class); 172 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 173 in.putExtra("direction", BluetoothShare.DIRECTION_INBOUND); 174 context.startActivity(in); 175 } else if (action.equals(Constants.ACTION_OPEN_RECEIVED_FILES)) { 176 if (V) { 177 Log.v(TAG, "Received ACTION_OPEN_RECEIVED_FILES."); 178 } 179 180 Intent in = new Intent(context, BluetoothOppTransferHistory.class); 181 in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 182 in.putExtra("direction", BluetoothShare.DIRECTION_INBOUND); 183 in.putExtra(Constants.EXTRA_SHOW_ALL_FILES, true); 184 context.startActivity(in); 185 } else if (action.equals(Constants.ACTION_HIDE)) { 186 if (V) { 187 Log.v(TAG, "Receiver hide for " + intent.getData()); 188 } 189 Cursor cursor = BluetoothMethodProxy.getInstance().contentResolverQuery( 190 context.getContentResolver(), intent.getData(), null, null, null, null); 191 if (cursor != null) { 192 if (cursor.moveToFirst()) { 193 int visibilityColumn = cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY); 194 int visibility = cursor.getInt(visibilityColumn); 195 int userConfirmationColumn = 196 cursor.getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION); 197 int userConfirmation = cursor.getInt(userConfirmationColumn); 198 if (((userConfirmation == BluetoothShare.USER_CONFIRMATION_PENDING)) 199 && visibility == BluetoothShare.VISIBILITY_VISIBLE) { 200 ContentValues values = new ContentValues(); 201 values.put(BluetoothShare.VISIBILITY, BluetoothShare.VISIBILITY_HIDDEN); 202 BluetoothMethodProxy.getInstance().contentResolverUpdate( 203 context.getContentResolver(), intent.getData(), values, null, 204 null); 205 if (V) { 206 Log.v(TAG, "Action_hide received and db updated"); 207 } 208 } 209 } 210 cursor.close(); 211 } 212 } else if (action.equals(Constants.ACTION_COMPLETE_HIDE)) { 213 if (V) { 214 Log.v(TAG, "Receiver ACTION_COMPLETE_HIDE"); 215 } 216 ContentValues updateValues = new ContentValues(); 217 updateValues.put(BluetoothShare.VISIBILITY, BluetoothShare.VISIBILITY_HIDDEN); 218 BluetoothMethodProxy.getInstance().contentResolverUpdate( 219 context.getContentResolver(), BluetoothShare.CONTENT_URI, updateValues, 220 BluetoothOppNotification.WHERE_COMPLETED, null); 221 } else if (action.equals(BluetoothShare.TRANSFER_COMPLETED_ACTION)) { 222 if (V) { 223 Log.v(TAG, "Receiver Transfer Complete Intent for " + intent.getData()); 224 } 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 Utils.getTempAllowlistBroadcastOptions()); 260 return; 261 } 262 263 if (BluetoothShare.isStatusSuccess(transInfo.mStatus)) { 264 if (transInfo.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 265 toastMsg = context.getString(R.string.notification_sent, transInfo.mFileName); 266 } else if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND) { 267 toastMsg = 268 context.getString(R.string.notification_received, transInfo.mFileName); 269 } 270 271 } else if (BluetoothShare.isStatusError(transInfo.mStatus)) { 272 if (transInfo.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 273 toastMsg = 274 context.getString(R.string.notification_sent_fail, transInfo.mFileName); 275 } else if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND) { 276 toastMsg = context.getString(R.string.download_fail_line1); 277 } 278 } 279 if (V) { 280 Log.v(TAG, "Toast msg == " + toastMsg); 281 } 282 if (toastMsg != null) { 283 Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show(); 284 } 285 } 286 } 287 cancelNotification(Context context, int id)288 private void cancelNotification(Context context, int id) { 289 NotificationManager notMgr = context.getSystemService(NotificationManager.class); 290 if (notMgr == null) { 291 return; 292 } 293 notMgr.cancel(id); 294 if (V) { 295 Log.v(TAG, "notMgr.cancel called"); 296 } 297 } 298 } 299