• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.bluetooth.BluetoothDevice;
19 import android.content.Context;
20 import android.content.Intent;
21 import android.net.Uri;
22 import android.os.Handler;
23 import android.os.Looper;
24 import android.os.Message;
25 import android.os.Messenger;
26 import android.os.SystemProperties;
27 import android.os.UserHandle;
28 import android.util.Log;
29 
30 import com.android.nfc.NfcService;
31 import com.android.nfc.R;
32 import com.android.nfc.handover.HandoverDataParser;
33 
34 /**
35  * Manager for starting and stopping Beam transfers. Prevents more than one transfer from
36  * happening at a time.
37  */
38 public class BeamManager implements Handler.Callback {
39     private static final String TAG = "BeamManager";
40     private static final boolean DBG =
41             SystemProperties.getBoolean("persist.nfc.debug_enabled", false);
42 
43     private static final String ACTION_ALLOWLIST_DEVICE =
44             "android.btopp.intent.action.WHITELIST_DEVICE";
45     public static final int MSG_BEAM_COMPLETE = 0;
46 
47     private final Object mLock;
48 
49     private boolean mBeamInProgress;
50     private final Handler mCallback;
51 
52     private NfcService mNfcService;
53 
54     private static final class Singleton {
55         public static final BeamManager INSTANCE = new BeamManager();
56     }
57 
BeamManager()58     private BeamManager() {
59         mLock = new Object();
60         mBeamInProgress = false;
61         mCallback = new Handler(Looper.getMainLooper(), this);
62         mNfcService = NfcService.getInstance();
63     }
64 
getInstance()65     public static BeamManager getInstance() {
66         return Singleton.INSTANCE;
67     }
68 
isBeamInProgress()69     public boolean isBeamInProgress() {
70         synchronized (mLock) {
71             return mBeamInProgress;
72         }
73     }
74 
startBeamReceive(Context context, HandoverDataParser.BluetoothHandoverData handoverData)75     public boolean startBeamReceive(Context context,
76                                  HandoverDataParser.BluetoothHandoverData handoverData) {
77         synchronized (mLock) {
78             if (mBeamInProgress) {
79                 return false;
80             } else {
81                 mBeamInProgress = true;
82             }
83         }
84 
85         BeamTransferRecord transferRecord =
86                 BeamTransferRecord.forBluetoothDevice(
87                         handoverData.device, handoverData.carrierActivating, null);
88 
89         Intent receiveIntent = new Intent(context.getApplicationContext(),
90                 BeamReceiveService.class);
91         receiveIntent.putExtra(BeamReceiveService.EXTRA_BEAM_TRANSFER_RECORD, transferRecord);
92         receiveIntent.putExtra(BeamReceiveService.EXTRA_BEAM_COMPLETE_CALLBACK,
93                 new Messenger(mCallback));
94         allowlistOppDevice(context, handoverData.device);
95         context.startServiceAsUser(receiveIntent, UserHandle.CURRENT);
96         return true;
97     }
98 
startBeamSend(Context context, HandoverDataParser.BluetoothHandoverData outgoingHandoverData, Uri[] uris, UserHandle userHandle)99     public boolean startBeamSend(Context context,
100                                HandoverDataParser.BluetoothHandoverData outgoingHandoverData,
101                                Uri[] uris, UserHandle userHandle) {
102         synchronized (mLock) {
103             if (mBeamInProgress) {
104                 return false;
105             } else {
106                 mBeamInProgress = true;
107             }
108         }
109 
110         BeamTransferRecord transferRecord = BeamTransferRecord.forBluetoothDevice(
111                 outgoingHandoverData.device, outgoingHandoverData.carrierActivating,
112                 uris);
113         Intent sendIntent = new Intent(context.getApplicationContext(),
114                 BeamSendService.class);
115         sendIntent.putExtra(BeamSendService.EXTRA_BEAM_TRANSFER_RECORD, transferRecord);
116         sendIntent.putExtra(BeamSendService.EXTRA_BEAM_COMPLETE_CALLBACK,
117                 new Messenger(mCallback));
118         context.startServiceAsUser(sendIntent, userHandle);
119         return true;
120     }
121 
122     @Override
handleMessage(Message msg)123     public boolean handleMessage(Message msg) {
124         if (msg.what == MSG_BEAM_COMPLETE) {
125             synchronized (mLock) {
126                 mBeamInProgress = false;
127             }
128 
129             boolean success = msg.arg1 == 1;
130             if (success) {
131                 mNfcService.playSound(NfcService.SOUND_END);
132             }
133             return true;
134         }
135         return false;
136     }
137 
allowlistOppDevice(Context context, BluetoothDevice device)138     void allowlistOppDevice(Context context, BluetoothDevice device) {
139         if (DBG) Log.d(TAG, "Allowlist " + device + " for BT OPP");
140         Intent intent = new Intent(ACTION_ALLOWLIST_DEVICE);
141         intent.setPackage(context.getString(R.string.bluetooth_package));
142         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
143         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
144         context.sendBroadcastAsUser(intent, UserHandle.CURRENT);
145     }
146 
147 }
148