diff options
author | Martijn Coenen <maco@google.com> | 2012-05-17 15:32:43 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2012-05-17 15:32:43 -0700 |
commit | 0b61093016daae3df331e1a6780757254c06859a (patch) | |
tree | f44b79be6ecd3813cf3ba6006b58570aedc4b0c1 | |
parent | c9f617a9c99f579e753a09387629f3ddac8e9ca7 (diff) | |
parent | 2aa9b461d148f49ab9c63858f1c8f87c0b40b824 (diff) | |
download | packages_apps_nfc-0b61093016daae3df331e1a6780757254c06859a.zip packages_apps_nfc-0b61093016daae3df331e1a6780757254c06859a.tar.gz packages_apps_nfc-0b61093016daae3df331e1a6780757254c06859a.tar.bz2 |
am 2aa9b461: Merge "Allow cancelling of Bluetooth Beam transfers." into jb-dev
* commit '2aa9b461d148f49ab9c63858f1c8f87c0b40b824':
Allow cancelling of Bluetooth Beam transfers.
-rw-r--r-- | res/drawable-hdpi/ic_menu_cancel_holo_dark.png | bin | 0 -> 583 bytes | |||
-rw-r--r-- | res/drawable-mdpi/ic_menu_cancel_holo_dark.png | bin | 0 -> 520 bytes | |||
-rwxr-xr-x | res/values/strings.xml | 2 | ||||
-rw-r--r-- | src/com/android/nfc/handover/BluetoothOppHandover.java | 10 | ||||
-rw-r--r-- | src/com/android/nfc/handover/HandoverManager.java | 129 |
5 files changed, 111 insertions, 30 deletions
diff --git a/res/drawable-hdpi/ic_menu_cancel_holo_dark.png b/res/drawable-hdpi/ic_menu_cancel_holo_dark.png Binary files differnew file mode 100644 index 0000000..2956109 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_cancel_holo_dark.png diff --git a/res/drawable-mdpi/ic_menu_cancel_holo_dark.png b/res/drawable-mdpi/ic_menu_cancel_holo_dark.png Binary files differnew file mode 100644 index 0000000..6ed1327 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_cancel_holo_dark.png diff --git a/res/values/strings.xml b/res/values/strings.xml index 06cc01c..005f770 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -22,6 +22,8 @@ <string name="beam_progress">Incoming beam...</string> <string name="beam_complete">Beam complete</string> <string name="beam_failed">Beam failed</string> + <string name="beam_canceled">Beam canceled</string> + <string name="cancel">Cancel</string> <string name="beam_touch_to_view">Touch to view</string> <string name="connecting_headset">Connecting</string> diff --git a/src/com/android/nfc/handover/BluetoothOppHandover.java b/src/com/android/nfc/handover/BluetoothOppHandover.java index 1835aa8..3180e83 100644 --- a/src/com/android/nfc/handover/BluetoothOppHandover.java +++ b/src/com/android/nfc/handover/BluetoothOppHandover.java @@ -2,6 +2,7 @@ package com.android.nfc.handover; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -116,11 +117,9 @@ public class BluetoothOppHandover implements Handler.Callback { void sendIntent() { //TODO: either open up BluetoothOppLauncherActivity to all MIME types // or gracefully handle mime types that can't be sent - Log.d(TAG, "Sending handover intent for " + mDevice.getAddress()); Intent intent = new Intent(); intent.setPackage("com.android.bluetooth"); String mimeType = getMimeTypeForUri(mContext, mUris[0]); - Log.d(TAG, "Determined mime type as " + mimeType); intent.setType(mimeType); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); if (mUris.length == 1) { @@ -133,8 +132,11 @@ public class BluetoothOppHandover implements Handler.Callback { } intent.putExtra(EXTRA_CONNECTION_HANDOVER, true); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mContext.startActivity(intent); - + try { + mContext.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "Failed to handover file to bluetooth, mimeType not allowed."); + } complete(); } diff --git a/src/com/android/nfc/handover/HandoverManager.java b/src/com/android/nfc/handover/HandoverManager.java index 79bcef1..9458472 100644 --- a/src/com/android/nfc/handover/HandoverManager.java +++ b/src/com/android/nfc/handover/HandoverManager.java @@ -117,6 +117,11 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, static final String ACTION_WHITELIST_DEVICE = "android.btopp.intent.action.WHITELIST_DEVICE"; + static final String ACTION_CANCEL_HANDOVER_TRANSFER = + "com.android.nfc.handover.action.CANCEL_HANDOVER_TRANSFER"; + static final String EXTRA_SOURCE_ADDRESS = + "com.android.nfc.handover.extra.SOURCE_ADDRESS"; + static final int SOURCE_BLUETOOTH_INCOMING = 0; static final int SOURCE_BLUETOOTH_OUTGOING = 1; @@ -131,7 +136,9 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, final NotificationManager mNotificationManager; final HandoverPowerManager mHandoverPowerManager; - // synchronized on HandoverManager.this + // Variables below synchronized on HandoverManager.this + final HashMap<Pair<String, Boolean>, HandoverTransfer> mTransfers; + BluetoothHeadset mBluetoothHeadset; BluetoothA2dp mBluetoothA2dp; BluetoothHeadsetHandover mBluetoothHeadsetHandover; @@ -139,7 +146,6 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, String mLocalBluetoothAddress; int mNotificationId; - HashMap<Pair<String, Boolean>, HandoverTransfer> mTransfers; static class BluetoothHandoverData { public boolean valid = false; @@ -232,20 +238,24 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, */ class HandoverTransfer implements Handler.Callback, MediaScannerConnection.OnScanCompletedListener { + // In the states below we still accept new file transfer static final int STATE_NEW = 0; static final int STATE_IN_PROGRESS = 1; static final int STATE_W4_NEXT_TRANSFER = 2; + + // In the states below no new files are accepted. static final int STATE_W4_MEDIA_SCANNER = 3; static final int STATE_FAILED = 4; static final int STATE_SUCCESS = 5; static final int STATE_CANCELLED = 6; static final int MSG_NEXT_TRANSFER_TIMER = 0; + static final int MSG_TRANSFER_TIMEOUT = 1; // We need to receive an update within this time period // to still consider this transfer to be "alive" (ie // a reason to keep the handover transport enabled). - static final int ALIVE_CHECK_MS = 20000; + static final int ALIVE_CHECK_MS = 10000; // The amount of time to wait for a new transfer // once the current one completes. @@ -258,6 +268,7 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, final boolean incoming; // whether this is an incoming transfer final int notificationId; // Unique ID of this transfer used for notifications final Handler handler; + final PendingIntent cancelIntent; int state; Long lastUpdate; // Last time an event occurred for this transfer @@ -285,8 +296,11 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, this.sourceAddress = sourceAddress; this.incoming = incoming; this.handler = new Handler(mContext.getMainLooper(), this); + this.cancelIntent = buildCancelIntent(); this.urisScanned = 0; this.device = mBluetoothAdapter.getRemoteDevice(sourceAddress); + + handler.sendEmptyMessageDelayed(MSG_TRANSFER_TIMEOUT, ALIVE_CHECK_MS); } public synchronized void updateFileProgress(float progress) { @@ -330,17 +344,23 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, public synchronized boolean isRunning() { if (state != STATE_NEW && state != STATE_IN_PROGRESS && state != STATE_W4_NEXT_TRANSFER) { return false; - } - - // Check that we've made progress - Long currentTime = SystemClock.elapsedRealtime(); - if (currentTime - lastUpdate > ALIVE_CHECK_MS) { - return false; } else { return true; } } + synchronized void cancel() { + if (!isRunning()) return; + + // Delete all files received so far + for (Uri uri : btUris) { + File file = new File(uri.getPath()); + if (file.exists()) file.delete(); + } + + updateStateAndNotification(STATE_CANCELLED); + } + synchronized void updateNotification() { if (!incoming) return; // No notifications for outgoing transfers @@ -352,6 +372,10 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, notBuilder.setSmallIcon(android.R.drawable.stat_sys_download); notBuilder.setTicker(mContext.getString(R.string.beam_progress)); notBuilder.setContentTitle(mContext.getString(R.string.beam_progress)); + notBuilder.addAction(R.drawable.ic_menu_cancel_holo_dark, + mContext.getString(R.string.cancel), cancelIntent); + notBuilder.setDeleteIntent(cancelIntent); + notBuilder.setWhen(0); // We do have progress indication on a per-file basis, but in a multi-file // transfer we don't know the total progress. So for now, just show an // indeterminate progress bar. @@ -362,6 +386,7 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, notBuilder.setTicker(mContext.getString(R.string.beam_complete)); notBuilder.setContentTitle(mContext.getString(R.string.beam_complete)); notBuilder.setContentText(mContext.getString(R.string.beam_touch_to_view)); + notBuilder.setWhen(0); Intent viewIntent = buildViewIntent(); PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, viewIntent, 0); @@ -371,10 +396,17 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, // Play Beam success sound NfcService.getInstance().playSound(NfcService.SOUND_END); } else if (state == STATE_FAILED) { - notBuilder.setAutoCancel(true); + notBuilder.setAutoCancel(false); notBuilder.setSmallIcon(android.R.drawable.stat_sys_download_done); notBuilder.setTicker(mContext.getString(R.string.beam_failed)); notBuilder.setContentTitle(mContext.getString(R.string.beam_failed)); + notBuilder.setWhen(0); + } else if (state == STATE_CANCELLED) { + notBuilder.setAutoCancel(false); + notBuilder.setSmallIcon(android.R.drawable.stat_sys_download_done); + notBuilder.setTicker(mContext.getString(R.string.beam_canceled)); + notBuilder.setContentTitle(mContext.getString(R.string.beam_canceled)); + notBuilder.setWhen(0); } else { return; } @@ -385,6 +417,12 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, synchronized void updateStateAndNotification(int newState) { this.state = newState; this.lastUpdate = SystemClock.elapsedRealtime(); + + if (handler.hasMessages(MSG_TRANSFER_TIMEOUT)) { + // Update timeout timer + handler.removeMessages(MSG_TRANSFER_TIMEOUT); + handler.sendEmptyMessageDelayed(MSG_TRANSFER_TIMEOUT, ALIVE_CHECK_MS); + } updateNotification(); } @@ -447,8 +485,18 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, public boolean handleMessage(Message msg) { if (msg.what == MSG_NEXT_TRANSFER_TIMER) { // We didn't receive a new transfer in time, finalize this one - processFiles(); + if (incoming) { + processFiles(); + } else { + updateStateAndNotification(STATE_SUCCESS); + } return true; + } else if (msg.what == MSG_TRANSFER_TIMEOUT) { + // No update on this transfer for a while, check + // to see if it's still running, and fail it if it is. + if (isRunning()) { + updateStateAndNotification(STATE_FAILED); + } } return false; } @@ -492,6 +540,14 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, return viewIntent; } + PendingIntent buildCancelIntent() { + Intent intent = new Intent(ACTION_CANCEL_HANDOVER_TRANSFER); + intent.putExtra(EXTRA_SOURCE_ADDRESS, sourceAddress); + PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0); + + return pi; + } + synchronized File generateMultiplePath(String beamRoot) { // Generate a unique directory with the date String format = "yyyy-MM-dd"; @@ -508,24 +564,27 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, return newFile; } - - } - synchronized HandoverTransfer getHandoverTransfer(String sourceAddress, boolean incoming) { + synchronized HandoverTransfer getOrCreateHandoverTransfer(String sourceAddress, boolean incoming, + boolean create) { Pair<String, Boolean> key = new Pair<String, Boolean>(sourceAddress, incoming); if (mTransfers.containsKey(key)) { HandoverTransfer transfer = mTransfers.get(key); if (transfer.isRunning()) { return transfer; } else { - // Remove old transfer; new one will be created below - mTransfers.remove(key); + if (create) mTransfers.remove(key); // new one created below } } - HandoverTransfer transfer = new HandoverTransfer(sourceAddress, incoming); - mTransfers.put(key, transfer); - return transfer; + if (create) { + HandoverTransfer transfer = new HandoverTransfer(sourceAddress, incoming); + mTransfers.put(key, transfer); + + return transfer; + } else { + return null; + } } public HandoverManager(Context context) { @@ -543,6 +602,7 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, IntentFilter filter = new IntentFilter(ACTION_BT_OPP_TRANSFER_DONE); filter.addAction(ACTION_BT_OPP_TRANSFER_PROGRESS); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); + filter.addAction(ACTION_CANCEL_HANDOVER_TRANSFER); mContext.registerReceiver(mReceiver, filter, HANDOVER_STATUS_PERMISSION, null); } @@ -666,8 +726,8 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, } // Create the initial transfer object - HandoverTransfer transfer = getHandoverTransfer(bluetoothData.device.getAddress(), - true); + HandoverTransfer transfer = getOrCreateHandoverTransfer( + bluetoothData.device.getAddress(), true, true); transfer.updateNotification(); } @@ -715,6 +775,8 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, public void doHandoverUri(Uri[] uris, NdefMessage m) { BluetoothHandoverData data = parse(m); if (data != null && data.valid) { + // Register a new handover transfer object + getOrCreateHandoverTransfer(data.device.getAddress(), false, true); BluetoothOppHandover handover = new BluetoothOppHandover(mContext, data.device, uris, mHandoverPowerManager, data.carrierActivating); handover.start(); @@ -928,9 +990,16 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, } return; + } else if (action.equals(ACTION_CANCEL_HANDOVER_TRANSFER)) { + String sourceAddress = intent.getStringExtra(EXTRA_SOURCE_ADDRESS); + HandoverTransfer transfer = getOrCreateHandoverTransfer(sourceAddress, true, + false); + if (transfer != null) { + transfer.cancel(); + } } else if (action.equals(ACTION_BT_OPP_TRANSFER_PROGRESS) || action.equals(ACTION_BT_OPP_TRANSFER_DONE)) { - // Clean up old transfers in progress + // Clean up old transfers no longer in progress cleanupTransfers(); int direction = intent.getIntExtra(EXTRA_BT_OPP_TRANSFER_DIRECTION, -1); @@ -939,8 +1008,18 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, if (direction == -1 || id == -1 || sourceAddress == null) return; boolean incoming = (direction == DIRECTION_BLUETOOTH_INCOMING); - HandoverTransfer transfer = getHandoverTransfer(sourceAddress, incoming); - if (transfer == null) return; + + HandoverTransfer transfer = getOrCreateHandoverTransfer(sourceAddress, incoming, + false); + if (transfer == null) { + // There is no transfer running for this source address; most likely + // the transfer was cancelled. We need to tell BT OPP to stop transferring + // in case this was an incoming transfer + Intent cancelIntent = new Intent("android.btopp.intent.action.STOP_HANDOVER_TRANSFER"); + cancelIntent.putExtra(EXTRA_BT_OPP_TRANSFER_ID, id); + mContext.sendBroadcast(cancelIntent); + return; + } if (action.equals(ACTION_BT_OPP_TRANSFER_DONE)) { int handoverStatus = intent.getIntExtra(EXTRA_BT_OPP_TRANSFER_STATUS, @@ -963,8 +1042,6 @@ public class HandoverManager implements BluetoothProfile.ServiceListener, } } } - }; - } |