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_ALLOWLIST_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 allowlistOppDevice(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 allowlistOppDevice(Context context, BluetoothDevice device)136 void allowlistOppDevice(Context context, BluetoothDevice device) { 137 if (DBG) Log.d(TAG, "Allowlist " + device + " for BT OPP"); 138 Intent intent = new Intent(ACTION_ALLOWLIST_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