1 package com.android.nfc.beam;
2 
3 import android.content.BroadcastReceiver;
4 import android.content.Context;
5 import android.content.Intent;
6 import android.content.IntentFilter;
7 import android.net.Uri;
8 import android.util.Log;
9 
10 import java.io.File;
11 
12 /**
13  * @hide
14  */
15 public class BeamStatusReceiver extends BroadcastReceiver {
16     private static final boolean DBG = true;
17     private static final String TAG = "BeamStatusReceiver";
18 
19     private static final String ACTION_HANDOVER_STARTED =
20             "android.nfc.handover.intent.action.HANDOVER_STARTED";
21 
22     private static final String ACTION_TRANSFER_PROGRESS =
23             "android.nfc.handover.intent.action.TRANSFER_PROGRESS";
24 
25     private static final String ACTION_TRANSFER_DONE =
26             "android.nfc.handover.intent.action.TRANSFER_DONE";
27 
28     private static final String EXTRA_HANDOVER_DATA_LINK_TYPE =
29             "android.nfc.handover.intent.extra.HANDOVER_DATA_LINK_TYPE";
30 
31 
32     private static final String EXTRA_TRANSFER_PROGRESS =
33             "android.nfc.handover.intent.extra.TRANSFER_PROGRESS";
34 
35     private static final String EXTRA_TRANSFER_URI =
36             "android.nfc.handover.intent.extra.TRANSFER_URI";
37 
38     private static final String EXTRA_OBJECT_COUNT =
39             "android.nfc.handover.intent.extra.OBJECT_COUNT";
40 
41     private static final String EXTRA_TRANSFER_STATUS =
42             "android.nfc.handover.intent.extra.TRANSFER_STATUS";
43 
44     private static final String EXTRA_TRANSFER_MIMETYPE =
45             "android.nfc.handover.intent.extra.TRANSFER_MIME_TYPE";
46 
47     private static final String ACTION_STOP_BLUETOOTH_TRANSFER =
48             "android.btopp.intent.action.STOP_HANDOVER_TRANSFER";
49 
50     // FIXME: Needs to stay in sync with com.android.bluetooth.opp.Constants
51     private static final int HANDOVER_TRANSFER_STATUS_SUCCESS = 0;
52     private static final int HANDOVER_TRANSFER_STATUS_FAILURE = 1;
53 
54     // permission needed to be able to receive handover status requests
55     public static final String BEAM_STATUS_PERMISSION =
56             "android.permission.NFC_HANDOVER_STATUS";
57 
58     // Needed to build cancel intent in Beam notification
59     public static final String EXTRA_INCOMING =
60             "com.android.nfc.handover.extra.INCOMING";
61 
62     public static final String EXTRA_TRANSFER_ID =
63             "android.nfc.handover.intent.extra.TRANSFER_ID";
64 
65     public static final String EXTRA_ADDRESS =
66             "android.nfc.handover.intent.extra.ADDRESS";
67 
68     public static final String ACTION_CANCEL_HANDOVER_TRANSFER =
69             "com.android.nfc.handover.action.CANCEL_HANDOVER_TRANSFER";
70 
71     public static final int DIRECTION_INCOMING = 0;
72     public static final int DIRECTION_OUTGOING = 1;
73 
74     private final Context mContext;
75     private final BeamTransferManager mTransferManager;
76 
BeamStatusReceiver(Context context, BeamTransferManager transferManager)77     BeamStatusReceiver(Context context, BeamTransferManager transferManager) {
78         mContext = context;
79         mTransferManager = transferManager;
80     }
81 
82     @Override
onReceive(Context context, Intent intent)83     public void onReceive(Context context, Intent intent) {
84         String action = intent.getAction();
85         int dataLinkType = intent.getIntExtra(EXTRA_HANDOVER_DATA_LINK_TYPE,
86                 BeamTransferManager.DATA_LINK_TYPE_BLUETOOTH);
87 
88         if (ACTION_CANCEL_HANDOVER_TRANSFER.equals(action)) {
89             if (mTransferManager != null) {
90                 mTransferManager.cancel();
91             }
92         } else if (ACTION_TRANSFER_PROGRESS.equals(action) ||
93                 ACTION_TRANSFER_DONE.equals(action) ||
94                 ACTION_HANDOVER_STARTED.equals(action)) {
95             handleTransferEvent(intent, dataLinkType);
96         }
97     }
98 
getIntentFilter()99     public IntentFilter getIntentFilter() {
100         IntentFilter filter = new IntentFilter(ACTION_TRANSFER_DONE);
101         filter.addAction(ACTION_TRANSFER_PROGRESS);
102         filter.addAction(ACTION_CANCEL_HANDOVER_TRANSFER);
103         filter.addAction(ACTION_HANDOVER_STARTED);
104         return filter;
105     }
106 
handleTransferEvent(Intent intent, int deviceType)107     private void handleTransferEvent(Intent intent, int deviceType) {
108         String action = intent.getAction();
109         int id = intent.getIntExtra(EXTRA_TRANSFER_ID, -1);
110 
111         String sourceAddress = intent.getStringExtra(EXTRA_ADDRESS);
112 
113         if (sourceAddress == null) return;
114 
115         if (mTransferManager == null) {
116             // There is no transfer running for this source address; most likely
117             // the transfer was cancelled. We need to tell BT OPP to stop transferring.
118             if (id != -1) {
119                 if (deviceType == BeamTransferManager.DATA_LINK_TYPE_BLUETOOTH) {
120                     if (DBG) Log.d(TAG, "Didn't find transfer, stopping");
121                     Intent cancelIntent = new Intent(ACTION_STOP_BLUETOOTH_TRANSFER);
122                     cancelIntent.putExtra(EXTRA_TRANSFER_ID, id);
123                     mContext.sendBroadcast(cancelIntent);
124                 }
125             }
126             return;
127         }
128 
129         mTransferManager.setBluetoothTransferId(id);
130 
131         if (action.equals(ACTION_TRANSFER_DONE)) {
132             int handoverStatus = intent.getIntExtra(EXTRA_TRANSFER_STATUS,
133                     HANDOVER_TRANSFER_STATUS_FAILURE);
134             if (handoverStatus == HANDOVER_TRANSFER_STATUS_SUCCESS) {
135                 String uriString = intent.getStringExtra(EXTRA_TRANSFER_URI);
136                 String mimeType = intent.getStringExtra(EXTRA_TRANSFER_MIMETYPE);
137                 Uri uri = Uri.parse(uriString);
138                 if (uri != null && uri.getScheme() == null) {
139                     uri = Uri.fromFile(new File(uri.getPath()));
140                 }
141                 mTransferManager.finishTransfer(true, uri, mimeType);
142             } else {
143                 mTransferManager.finishTransfer(false, null, null);
144             }
145         } else if (action.equals(ACTION_TRANSFER_PROGRESS)) {
146             float progress = intent.getFloatExtra(EXTRA_TRANSFER_PROGRESS, 0.0f);
147             mTransferManager.updateFileProgress(progress);
148         } else if (action.equals(ACTION_HANDOVER_STARTED)) {
149             int count = intent.getIntExtra(EXTRA_OBJECT_COUNT, 0);
150             if (count > 0) {
151                 mTransferManager.setObjectCount(count);
152             }
153         }
154     }
155 }
156