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