Home | History | Annotate | Download | only in beam
      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 
     50     public BeamReceiveService() {
     51         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
     52     }
     53 
     54     @Override
     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
     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
     89     public void onDestroy() {
     90         super.onDestroy();
     91         if (mBeamStatusReceiver != null) {
     92             unregisterReceiver(mBeamStatusReceiver);
     93         }
     94         unregisterReceiver(mBluetoothStateReceiver);
     95     }
     96 
     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 
    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
    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
    159     public IBinder onBind(Intent intent) {
    160         return null;
    161     }
    162 }
    163