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