blob: 6c013ea390d8734d58fae8b89277eae2d69a380b [file] [log] [blame]
nxpandroid64fd68c2015-09-23 16:45:15 +05301/*
2 * Copyright (C) 2014 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
17package com.android.nfc.beam;
18
nxpandroid64fd68c2015-09-23 16:45:15 +053019import android.app.Service;
20import android.bluetooth.BluetoothAdapter;
21import android.content.BroadcastReceiver;
22import android.content.Context;
23import android.content.Intent;
24import android.content.IntentFilter;
nxpandroid64fd68c2015-09-23 16:45:15 +053025import android.os.Handler;
26import android.os.IBinder;
27import android.os.Message;
28import android.os.Messenger;
29import android.os.RemoteException;
30import android.util.Log;
31
32public class BeamSendService extends Service implements BeamTransferManager.Callback {
33 private static String TAG = "BeamSendService";
34 private static boolean DBG = true;
35
36 public static String EXTRA_BEAM_TRANSFER_RECORD
37 = "com.android.nfc.beam.EXTRA_BEAM_TRANSFER_RECORD";
38 public static final String EXTRA_BEAM_COMPLETE_CALLBACK
39 = "com.android.nfc.beam.TRANSFER_COMPLETE_CALLBACK";
40
41 private BeamTransferManager mTransferManager;
42 private BeamStatusReceiver mBeamStatusReceiver;
43 private boolean mBluetoothEnabledByNfc;
44 private Messenger mCompleteCallback;
45 private int mStartId;
nxpandroid64fd68c2015-09-23 16:45:15 +053046
47 private final BluetoothAdapter mBluetoothAdapter;
48 private final BroadcastReceiver mBluetoothStateReceiver = new BroadcastReceiver() {
49 @Override
50 public void onReceive(Context context, Intent intent) {
51 String action = intent.getAction();
52 if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
53 handleBluetoothStateChanged(intent);
54 }
55 }
56 };
57
58 public BeamSendService() {
59 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
60 }
61
62 @Override
63 public void onCreate() {
nxpandroid281eb922016-08-25 20:27:46 +053064 super.onCreate();
nxpandroid64fd68c2015-09-23 16:45:15 +053065
nxpandroid64fd68c2015-09-23 16:45:15 +053066 // register BT state receiver
67 IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
68 registerReceiver(mBluetoothStateReceiver, filter);
69 }
70
71 @Override
72 public void onDestroy() {
73 super.onDestroy();
nxpandroid64fd68c2015-09-23 16:45:15 +053074
75 if (mBeamStatusReceiver != null) {
76 unregisterReceiver(mBeamStatusReceiver);
77 }
78 unregisterReceiver(mBluetoothStateReceiver);
79 }
80
81 @Override
82 public int onStartCommand(Intent intent, int flags, int startId) {
83 mStartId = startId;
84
85 BeamTransferRecord transferRecord;
86 if (intent == null ||
nxpandroid281eb922016-08-25 20:27:46 +053087 (transferRecord = intent.getParcelableExtra(EXTRA_BEAM_TRANSFER_RECORD)) == null) {
nxpandroid64fd68c2015-09-23 16:45:15 +053088 if (DBG) Log.e(TAG, "No transfer record provided. Stopping.");
89 stopSelf(startId);
90 return START_NOT_STICKY;
91 }
92
93 mCompleteCallback = intent.getParcelableExtra(EXTRA_BEAM_COMPLETE_CALLBACK);
94
95 if (doTransfer(transferRecord)) {
96 if (DBG) Log.i(TAG, "Starting outgoing Beam transfer");
97 return START_STICKY;
98 } else {
nxpandroid1153eb32015-11-06 18:46:58 +053099 invokeCompleteCallback(false);
nxpandroid64fd68c2015-09-23 16:45:15 +0530100 stopSelf(startId);
101 return START_NOT_STICKY;
102 }
103 }
104
105 boolean doTransfer(BeamTransferRecord transferRecord) {
106 if (createBeamTransferManager(transferRecord)) {
107 // register Beam status receiver
108 mBeamStatusReceiver = new BeamStatusReceiver(this, mTransferManager);
109 registerReceiver(mBeamStatusReceiver, mBeamStatusReceiver.getIntentFilter(),
110 BeamStatusReceiver.BEAM_STATUS_PERMISSION, new Handler());
111
112 if (transferRecord.dataLinkType == BeamTransferRecord.DATA_LINK_TYPE_BLUETOOTH) {
113 if (mBluetoothAdapter.isEnabled()) {
114 // Start the transfer
115 mTransferManager.start();
116 } else {
117 if (!mBluetoothAdapter.enableNoAutoConnect()) {
118 Log.e(TAG, "Error enabling Bluetooth.");
119 mTransferManager = null;
120 return false;
121 }
122 mBluetoothEnabledByNfc = true;
123 if (DBG) Log.d(TAG, "Queueing out transfer "
124 + Integer.toString(transferRecord.id));
125 }
126 }
127 return true;
128 }
129
130 return false;
131 }
132
133 boolean createBeamTransferManager(BeamTransferRecord transferRecord) {
134 if (mTransferManager != null) {
135 return false;
136 }
137
138 if (transferRecord.dataLinkType != BeamTransferRecord.DATA_LINK_TYPE_BLUETOOTH) {
139 // only support BT
140 return false;
141 }
142
143 mTransferManager = new BeamTransferManager(this, this, transferRecord, false);
144 mTransferManager.updateNotification();
145 return true;
146 }
147
148 private void handleBluetoothStateChanged(Intent intent) {
149 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
150 BluetoothAdapter.ERROR);
151 if (state == BluetoothAdapter.STATE_ON) {
152 if (mTransferManager != null &&
153 mTransferManager.mDataLinkType == BeamTransferRecord.DATA_LINK_TYPE_BLUETOOTH) {
154 mTransferManager.start();
155 }
nxpandroid281eb922016-08-25 20:27:46 +0530156 } else if (state == BluetoothAdapter.STATE_OFF) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530157 mBluetoothEnabledByNfc = false;
158 }
159 }
160
nxpandroid1153eb32015-11-06 18:46:58 +0530161 private void invokeCompleteCallback(boolean success) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530162 if (mCompleteCallback != null) {
163 try {
nxpandroid1153eb32015-11-06 18:46:58 +0530164 Message msg = Message.obtain(null, BeamManager.MSG_BEAM_COMPLETE);
165 msg.arg1 = success ? 1 : 0;
166 mCompleteCallback.send(msg);
nxpandroid64fd68c2015-09-23 16:45:15 +0530167 } catch (RemoteException e) {
168 Log.e(TAG, "failed to invoke Beam complete callback", e);
169 }
170 }
171 }
172
173 @Override
174 public void onTransferComplete(BeamTransferManager transfer, boolean success) {
175 // Play success sound
nxpandroid1153eb32015-11-06 18:46:58 +0530176 if (!success) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530177 if (DBG) Log.d(TAG, "Transfer failed, final state: " +
178 Integer.toString(transfer.mState));
179 }
180
181 if (mBluetoothEnabledByNfc) {
182 mBluetoothEnabledByNfc = false;
183 mBluetoothAdapter.disable();
184 }
185
nxpandroid1153eb32015-11-06 18:46:58 +0530186 invokeCompleteCallback(success);
nxpandroid64fd68c2015-09-23 16:45:15 +0530187 stopSelf(mStartId);
188 }
189
190 @Override
191 public IBinder onBind(Intent intent) {
192 return null;
193 }
194}