• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.nfc.beam;
2 
3 import android.app.Service;
4 import android.bluetooth.BluetoothAdapter;
5 import android.content.BroadcastReceiver;
6 import android.content.Context;
7 import android.content.Intent;
8 import android.content.IntentFilter;
9 import android.os.Handler;
10 import android.os.IBinder;
11 import android.os.Message;
12 import android.os.Messenger;
13 import android.os.RemoteException;
14 import android.util.Log;
15 
16 
17 /**
18  * @hide
19  */
20 public class BeamReceiveService extends Service implements BeamTransferManager.Callback {
21     private static String TAG = "BeamReceiveService";
22     private static boolean DBG = true;
23 
24     public static final String EXTRA_BEAM_TRANSFER_RECORD
25             = "com.android.nfc.beam.EXTRA_BEAM_TRANSFER_RECORD";
26     public static final String EXTRA_BEAM_COMPLETE_CALLBACK
27             = "com.android.nfc.beam.TRANSFER_COMPLETE_CALLBACK";
28 
29     private BeamStatusReceiver mBeamStatusReceiver;
30     private boolean mBluetoothEnabledByNfc;
31     private int mStartId;
32     private BeamTransferManager mTransferManager;
33     private Messenger mCompleteCallback;
34 
35     private final BluetoothAdapter mBluetoothAdapter;
36     private final BroadcastReceiver mBluetoothStateReceiver = new BroadcastReceiver() {
37         @Override
38         public void onReceive(Context context, Intent intent) {
39             String action = intent.getAction();
40             if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
41                 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
42                         BluetoothAdapter.ERROR);
43                 if (state == BluetoothAdapter.STATE_OFF) {
44                     mBluetoothEnabledByNfc = false;
45                 }
46             }
47         }
48     };
49 
BeamReceiveService()50     public BeamReceiveService() {
51         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
52     }
53 
54     @Override
onStartCommand(Intent intent, int flags, int startId)55     public int onStartCommand(Intent intent, int flags, int startId) {
56         mStartId = startId;
57 
58         BeamTransferRecord transferRecord;
59         if (intent == null ||
60                 (transferRecord = intent.getParcelableExtra(EXTRA_BEAM_TRANSFER_RECORD)) == null) {
61             if (DBG) Log.e(TAG, "No transfer record provided. Stopping.");
62             stopSelf(startId);
63             return START_NOT_STICKY;
64         }
65 
66         mCompleteCallback = intent.getParcelableExtra(EXTRA_BEAM_COMPLETE_CALLBACK);
67 
68         if (prepareToReceive(transferRecord)) {
69             if (DBG) Log.i(TAG, "Ready for incoming Beam transfer");
70             return START_STICKY;
71         } else {
72             invokeCompleteCallback(false);
73             stopSelf(startId);
74             return START_NOT_STICKY;
75         }
76     }
77 
78     // TODO: figure out a way to not duplicate this code
79     @Override
onCreate()80     public void onCreate() {
81         super.onCreate();
82 
83         // register BT state receiver
84         IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
85         registerReceiver(mBluetoothStateReceiver, filter);
86     }
87 
88     @Override
onDestroy()89     public void onDestroy() {
90         super.onDestroy();
91         if (mBeamStatusReceiver != null) {
92             unregisterReceiver(mBeamStatusReceiver);
93         }
94         unregisterReceiver(mBluetoothStateReceiver);
95     }
96 
prepareToReceive(BeamTransferRecord transferRecord)97     boolean prepareToReceive(BeamTransferRecord transferRecord) {
98         if (mTransferManager != null) {
99             return false;
100         }
101 
102         if (transferRecord.dataLinkType != BeamTransferRecord.DATA_LINK_TYPE_BLUETOOTH) {
103             // only support BT
104             return false;
105         }
106 
107         if (!mBluetoothAdapter.isEnabled()) {
108             if (!mBluetoothAdapter.enableNoAutoConnect()) {
109                 Log.e(TAG, "Error enabling Bluetooth.");
110                 return false;
111             }
112             mBluetoothEnabledByNfc = true;
113             if (DBG) Log.d(TAG, "Queueing out transfer "
114                     + Integer.toString(transferRecord.id));
115         }
116 
117         mTransferManager = new BeamTransferManager(this, this, transferRecord, true);
118 
119         // register Beam status receiver
120         mBeamStatusReceiver = new BeamStatusReceiver(this, mTransferManager);
121         registerReceiver(mBeamStatusReceiver, mBeamStatusReceiver.getIntentFilter(),
122                 BeamStatusReceiver.BEAM_STATUS_PERMISSION, new Handler());
123 
124         mTransferManager.start();
125         mTransferManager.updateNotification();
126         return true;
127     }
128 
invokeCompleteCallback(boolean success)129     private void invokeCompleteCallback(boolean success) {
130         if (mCompleteCallback != null) {
131             try {
132                 Message msg = Message.obtain(null, BeamManager.MSG_BEAM_COMPLETE);
133                 msg.arg1 = success ? 1 : 0;
134                 mCompleteCallback.send(msg);
135             } catch (RemoteException e) {
136                 Log.e(TAG, "failed to invoke Beam complete callback", e);
137             }
138         }
139     }
140 
141     @Override
onTransferComplete(BeamTransferManager transfer, boolean success)142     public void onTransferComplete(BeamTransferManager transfer, boolean success) {
143         // Play success sound
144         if (!success) {
145             if (DBG) Log.d(TAG, "Transfer failed, final state: " +
146                     Integer.toString(transfer.mState));
147         }
148 
149         if (mBluetoothEnabledByNfc) {
150             mBluetoothEnabledByNfc = false;
151             mBluetoothAdapter.disable();
152         }
153 
154         invokeCompleteCallback(success);
155         stopSelf(mStartId);
156     }
157 
158     @Override
onBind(Intent intent)159     public IBinder onBind(Intent intent) {
160         return null;
161     }
162 }
163