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