1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.android.nfc.beam;
17 
18 import com.android.nfc.NfcService;
19 import com.android.nfc.R;
20 import com.android.nfc.handover.HandoverDataParser;
21 
22 import android.bluetooth.BluetoothDevice;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.net.Uri;
26 import android.os.Handler;
27 import android.os.Looper;
28 import android.os.Message;
29 import android.os.Messenger;
30 import android.os.UserHandle;
31 import android.util.Log;
32 
33 /**
34  * Manager for starting and stopping Beam transfers. Prevents more than one transfer from
35  * happening at a time.
36  */
37 public class BeamManager implements Handler.Callback {
38     private static final String TAG = "BeamManager";
39     private static final boolean DBG = false;
40 
41     private static final String ACTION_WHITELIST_DEVICE =
42             "android.btopp.intent.action.WHITELIST_DEVICE";
43     public static final int MSG_BEAM_COMPLETE = 0;
44 
45     private final Object mLock;
46 
47     private boolean mBeamInProgress;
48     private final Handler mCallback;
49 
50     private NfcService mNfcService;
51 
52     private static final class Singleton {
53         public static final BeamManager INSTANCE = new BeamManager();
54     }
55 
BeamManager()56     private BeamManager() {
57         mLock = new Object();
58         mBeamInProgress = false;
59         mCallback = new Handler(Looper.getMainLooper(), this);
60         mNfcService = NfcService.getInstance();
61     }
62 
getInstance()63     public static BeamManager getInstance() {
64         return Singleton.INSTANCE;
65     }
66 
isBeamInProgress()67     public boolean isBeamInProgress() {
68         synchronized (mLock) {
69             return mBeamInProgress;
70         }
71     }
72 
startBeamReceive(Context context, HandoverDataParser.BluetoothHandoverData handoverData)73     public boolean startBeamReceive(Context context,
74                                  HandoverDataParser.BluetoothHandoverData handoverData) {
75         synchronized (mLock) {
76             if (mBeamInProgress) {
77                 return false;
78             } else {
79                 mBeamInProgress = true;
80             }
81         }
82 
83         BeamTransferRecord transferRecord =
84                 BeamTransferRecord.forBluetoothDevice(
85                         handoverData.device, handoverData.carrierActivating, null);
86 
87         Intent receiveIntent = new Intent(context.getApplicationContext(),
88                 BeamReceiveService.class);
89         receiveIntent.putExtra(BeamReceiveService.EXTRA_BEAM_TRANSFER_RECORD, transferRecord);
90         receiveIntent.putExtra(BeamReceiveService.EXTRA_BEAM_COMPLETE_CALLBACK,
91                 new Messenger(mCallback));
92         whitelistOppDevice(context, handoverData.device);
93         context.startServiceAsUser(receiveIntent, UserHandle.CURRENT);
94         return true;
95     }
96 
startBeamSend(Context context, HandoverDataParser.BluetoothHandoverData outgoingHandoverData, Uri[] uris, UserHandle userHandle)97     public boolean startBeamSend(Context context,
98                                HandoverDataParser.BluetoothHandoverData outgoingHandoverData,
99                                Uri[] uris, UserHandle userHandle) {
100         synchronized (mLock) {
101             if (mBeamInProgress) {
102                 return false;
103             } else {
104                 mBeamInProgress = true;
105             }
106         }
107 
108         BeamTransferRecord transferRecord = BeamTransferRecord.forBluetoothDevice(
109                 outgoingHandoverData.device, outgoingHandoverData.carrierActivating,
110                 uris);
111         Intent sendIntent = new Intent(context.getApplicationContext(),
112                 BeamSendService.class);
113         sendIntent.putExtra(BeamSendService.EXTRA_BEAM_TRANSFER_RECORD, transferRecord);
114         sendIntent.putExtra(BeamSendService.EXTRA_BEAM_COMPLETE_CALLBACK,
115                 new Messenger(mCallback));
116         context.startServiceAsUser(sendIntent, userHandle);
117         return true;
118     }
119 
120     @Override
handleMessage(Message msg)121     public boolean handleMessage(Message msg) {
122         if (msg.what == MSG_BEAM_COMPLETE) {
123             synchronized (mLock) {
124                 mBeamInProgress = false;
125             }
126 
127             boolean success = msg.arg1 == 1;
128             if (success) {
129                 mNfcService.playSound(NfcService.SOUND_END);
130             }
131             return true;
132         }
133         return false;
134     }
135 
whitelistOppDevice(Context context, BluetoothDevice device)136     void whitelistOppDevice(Context context, BluetoothDevice device) {
137         if (DBG) Log.d(TAG, "Whitelisting " + device + " for BT OPP");
138         Intent intent = new Intent(ACTION_WHITELIST_DEVICE);
139         intent.setPackage(context.getString(R.string.bluetooth_package));
140         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
141         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
142         context.sendBroadcastAsUser(intent, UserHandle.CURRENT);
143     }
144 
145 }
146