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 V = Constants.VERBOSE;
58
59    @Override
60    public void onReceive(Context context, Intent intent) {
61        String action = intent.getAction();
62
63
64        if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
65            if (BluetoothAdapter.STATE_ON == intent.getIntExtra(
66                    BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
67                if (V) Log.v(TAG, "Received BLUETOOTH_STATE_CHANGED_ACTION, BLUETOOTH_STATE_ON");
68                context.startService(new Intent(context, BluetoothOppService.class));
69
70                // If this is within a sending process, continue the handle
71                // logic to display device picker dialog.
72                synchronized (this) {
73                    if (BluetoothOppManager.getInstance(context).mSendingFlag) {
74                        // reset the flags
75                        BluetoothOppManager.getInstance(context).mSendingFlag = false;
76
77                        Intent in1 = new Intent(BluetoothDevicePicker.ACTION_LAUNCH);
78                        in1.putExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
79                        in1.putExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE,
80                                BluetoothDevicePicker.FILTER_TYPE_TRANSFER);
81                        in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE,
82                                Constants.THIS_PACKAGE_NAME);
83                        in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS,
84                                BluetoothOppReceiver.class.getName());
85
86                        in1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
87                        context.startActivity(in1);
88                    }
89                }
90            }
91        } else if (action.equals(BluetoothDevicePicker.ACTION_DEVICE_SELECTED)) {
92            BluetoothOppManager mOppManager = BluetoothOppManager.getInstance(context);
93
94            BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
95
96            if (V) Log.v(TAG, "Received BT device selected intent, bt device: " + remoteDevice);
97
98            // Insert transfer session record to database
99            mOppManager.startTransfer(remoteDevice);
100
101            // Display toast message
102            String deviceName = mOppManager.getDeviceName(remoteDevice);
103            String toastMsg;
104            int batchSize = mOppManager.getBatchSize();
105            if (mOppManager.mMultipleFlag) {
106                toastMsg = context.getString(R.string.bt_toast_5, Integer.toString(batchSize),
107                        deviceName);
108            } else {
109                toastMsg = context.getString(R.string.bt_toast_4, deviceName);
110            }
111            Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show();
112        } else if (action.equals(Constants.ACTION_INCOMING_FILE_CONFIRM)) {
113            if (V) Log.v(TAG, "Receiver ACTION_INCOMING_FILE_CONFIRM");
114
115            Uri uri = intent.getData();
116            Intent in = new Intent(context, BluetoothOppIncomingFileConfirmActivity.class);
117            in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
118            in.setData(uri);
119            context.startActivity(in);
120
121            NotificationManager notMgr = (NotificationManager)context
122                    .getSystemService(Context.NOTIFICATION_SERVICE);
123            if (notMgr != null) {
124                notMgr.cancel((int)ContentUris.parseId(intent.getData()));
125                if (V) Log.v(TAG, "notMgr.cancel called");
126            }
127        } else if (action.equals(BluetoothShare.INCOMING_FILE_CONFIRMATION_REQUEST_ACTION)) {
128            if (V) Log.v(TAG, "Receiver INCOMING_FILE_NOTIFICATION");
129
130            Toast.makeText(context, context.getString(R.string.incoming_file_toast_msg),
131                    Toast.LENGTH_SHORT).show();
132
133        } else if (action.equals(Constants.ACTION_OPEN) || action.equals(Constants.ACTION_LIST)) {
134            if (V) {
135                if (action.equals(Constants.ACTION_OPEN)) {
136                    Log.v(TAG, "Receiver open for " + intent.getData());
137                } else {
138                    Log.v(TAG, "Receiver list for " + intent.getData());
139                }
140            }
141
142            BluetoothOppTransferInfo transInfo = new BluetoothOppTransferInfo();
143            Uri uri = intent.getData();
144            transInfo = BluetoothOppUtility.queryRecord(context, uri);
145            if (transInfo == null) {
146                Log.e(TAG, "Error: Can not get data from db");
147                return;
148            }
149
150            if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND
151                    && BluetoothShare.isStatusSuccess(transInfo.mStatus)) {
152                // if received file successfully, open this file
153                BluetoothOppUtility.openReceivedFile(context, transInfo.mFileName,
154                        transInfo.mFileType, transInfo.mTimeStamp, uri);
155                BluetoothOppUtility.updateVisibilityToHidden(context, uri);
156            } else {
157                Intent in = new Intent(context, BluetoothOppTransferActivity.class);
158                in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
159                in.setData(uri);
160                context.startActivity(in);
161            }
162
163            NotificationManager notMgr = (NotificationManager)context
164                    .getSystemService(Context.NOTIFICATION_SERVICE);
165            if (notMgr != null) {
166                notMgr.cancel((int)ContentUris.parseId(intent.getData()));
167                if (V) Log.v(TAG, "notMgr.cancel called");
168                }
169        } else if (action.equals(Constants.ACTION_OPEN_OUTBOUND_TRANSFER)) {
170            if (V) Log.v(TAG, "Received ACTION_OPEN_OUTBOUND_TRANSFER.");
171
172            Intent in = new Intent(context, BluetoothOppTransferHistory.class);
173            in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
174            in.putExtra("direction", BluetoothShare.DIRECTION_OUTBOUND);
175            context.startActivity(in);
176        } else if (action.equals(Constants.ACTION_OPEN_INBOUND_TRANSFER)) {
177            if (V) Log.v(TAG, "Received ACTION_OPEN_INBOUND_TRANSFER.");
178
179            Intent in = new Intent(context, BluetoothOppTransferHistory.class);
180            in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
181            in.putExtra("direction", BluetoothShare.DIRECTION_INBOUND);
182            context.startActivity(in);
183        } else if (action.equals(Constants.ACTION_OPEN_RECEIVED_FILES)) {
184            if (V) Log.v(TAG, "Received ACTION_OPEN_RECEIVED_FILES.");
185
186            Intent in = new Intent(context, BluetoothOppTransferHistory.class);
187            in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
188            in.putExtra("direction", BluetoothShare.DIRECTION_INBOUND);
189            in.putExtra(Constants.EXTRA_SHOW_ALL_FILES, true);
190            context.startActivity(in);
191        } else if (action.equals(Constants.ACTION_HIDE)) {
192            if (V) Log.v(TAG, "Receiver hide for " + intent.getData());
193            Cursor cursor = context.getContentResolver().query(intent.getData(), null, null, null,
194                    null);
195            if (cursor != null) {
196                if (cursor.moveToFirst()) {
197                    int statusColumn = cursor.getColumnIndexOrThrow(BluetoothShare.STATUS);
198                    int status = cursor.getInt(statusColumn);
199                    int visibilityColumn = cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY);
200                    int visibility = cursor.getInt(visibilityColumn);
201                    int userConfirmationColumn = cursor
202                            .getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION);
203                    int userConfirmation = cursor.getInt(userConfirmationColumn);
204                    if (((userConfirmation == BluetoothShare.USER_CONFIRMATION_PENDING))
205                            && visibility == BluetoothShare.VISIBILITY_VISIBLE) {
206                        ContentValues values = new ContentValues();
207                        values.put(BluetoothShare.VISIBILITY, BluetoothShare.VISIBILITY_HIDDEN);
208                        context.getContentResolver().update(intent.getData(), values, null, null);
209                        if (V) Log.v(TAG, "Action_hide received and db updated");
210                        }
211                }
212                cursor.close();
213            }
214        } else if (action.equals(Constants.ACTION_COMPLETE_HIDE)) {
215            if (V) Log.v(TAG, "Receiver ACTION_COMPLETE_HIDE");
216            ContentValues updateValues = new ContentValues();
217            updateValues.put(BluetoothShare.VISIBILITY, BluetoothShare.VISIBILITY_HIDDEN);
218            context.getContentResolver().update(BluetoothShare.CONTENT_URI, updateValues,
219                    BluetoothOppNotification.WHERE_COMPLETED, null);
220        } else if (action.equals(BluetoothShare.TRANSFER_COMPLETED_ACTION)) {
221            if (V) Log.v(TAG, "Receiver Transfer Complete Intent for " + intent.getData());
222
223            String toastMsg = null;
224            BluetoothOppTransferInfo transInfo = new BluetoothOppTransferInfo();
225            transInfo = BluetoothOppUtility.queryRecord(context, intent.getData());
226            if (transInfo == null) {
227                Log.e(TAG, "Error: Can not get data from db");
228                return;
229            }
230
231            if (BluetoothShare.isStatusSuccess(transInfo.mStatus)) {
232                if (transInfo.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
233                    toastMsg = context.getString(R.string.notification_sent, transInfo.mFileName);
234                } else if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND) {
235                    toastMsg = context.getString(R.string.notification_received,
236                            transInfo.mFileName);
237                }
238
239            } else if (BluetoothShare.isStatusError(transInfo.mStatus)) {
240                if (transInfo.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
241                    toastMsg = context.getString(R.string.notification_sent_fail,
242                            transInfo.mFileName);
243                } else if (transInfo.mDirection == BluetoothShare.DIRECTION_INBOUND) {
244                    toastMsg = context.getString(R.string.download_fail_line1);
245                }
246            }
247            if (V) Log.v(TAG, "Toast msg == " + toastMsg);
248            if (toastMsg != null) {
249                Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show();
250            }
251        }
252    }
253}
254