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