BluetoothOppReceiver.java revision 2a14fd2bbefddd595a9e1cd716f62a333e0f7e06
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
33package com.android.bluetooth.opp;
34
35import com.android.bluetooth.R;
36
37import android.app.NotificationManager;
38import android.bluetooth.BluetoothAdapter;
39import android.bluetooth.BluetoothDevice;
40import android.bluetooth.BluetoothDevicePicker;
41import android.content.BroadcastReceiver;
42import android.content.ContentUris;
43import android.content.ContentValues;
44import android.content.Context;
45import android.content.Intent;
46import android.database.Cursor;
47import android.net.Uri;
48import android.util.Log;
49import 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 */
55public 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
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
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