Fall back to NDEF push if handover SNEP get fails.
This allows applications to be able to set both
a Uri (for handover) and an NDEF message, which
will only be sent if the handover request does
not work (as will be the case on pre-J devices).
Also, show a toast if the remote device does
not support connection handover.
Bug: 6561174
Change-Id: I9ffdcfdf0cded319fbb4ab646ae1da5382fcb74a
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1776811..50cbf63 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -25,6 +25,7 @@
<string name="beam_canceled">Beam canceled</string>
<string name="cancel">Cancel</string>
<string name="beam_touch_to_view">Touch to view</string>
+ <string name="beam_handover_not_supported">The receiver\'s device doesn\'t support large file transfer via beam.</string>
<string name="connecting_headset">Connecting</string>
<string name="connected_headset">Connected</string>
diff --git a/src/com/android/nfc/P2pEventManager.java b/src/com/android/nfc/P2pEventManager.java
index 9050288..c024afc 100644
--- a/src/com/android/nfc/P2pEventManager.java
+++ b/src/com/android/nfc/P2pEventManager.java
@@ -87,6 +87,16 @@
}
@Override
+ public void onP2pHandoverNotSupported() {
+ mNfcService.playSound(NfcService.SOUND_ERROR);
+ mVibrator.vibrate(VIBRATION_PATTERN, -1);
+ mSendUi.finishAndToast(SendUi.FINISH_SCALE_UP,
+ mContext.getString(R.string.beam_handover_not_supported));
+ mSending = false;
+ mNdefSent = false;
+ }
+
+ @Override
public void onP2pReceiveComplete(boolean playSound) {
mVibrator.vibrate(VIBRATION_PATTERN, -1);
if (playSound) mNfcService.playSound(NfcService.SOUND_END);
diff --git a/src/com/android/nfc/P2pLinkManager.java b/src/com/android/nfc/P2pLinkManager.java
index 2f70f39..2bf14a4 100755
--- a/src/com/android/nfc/P2pLinkManager.java
+++ b/src/com/android/nfc/P2pLinkManager.java
@@ -77,6 +77,11 @@
public void onP2pSendComplete();
/**
+ * Called to indicate the remote device does not support connection handover
+ */
+ public void onP2pHandoverNotSupported();
+
+ /**
* Called to indicate a receive was successful.
*/
public void onP2pReceiveComplete(boolean playSound);
@@ -127,6 +132,7 @@
static final int MSG_SEND_COMPLETE = 4;
static final int MSG_START_ECHOSERVER = 5;
static final int MSG_STOP_ECHOSERVER = 6;
+ static final int MSG_HANDOVER_NOT_SUPPORTED = 7;
// values for mLinkState
static final int LINK_STATE_DOWN = 1;
@@ -138,6 +144,10 @@
static final int SEND_STATE_NEED_CONFIRMATION = 2;
static final int SEND_STATE_SENDING = 3;
+ // return values for doSnepProtocol
+ static final int SNEP_SUCCESS = 0;
+ static final int SNEP_FAILURE = 1;
+ static final int SNEP_HANDOVER_UNSUPPORTED = 2;
static final Uri PROFILE_URI = Profile.CONTENT_VCARD_URI.buildUpon().
appendQueryParameter(Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, "true").
@@ -349,6 +359,10 @@
}
}
+ void onHandoverUnsupported() {
+ mHandler.sendEmptyMessage(MSG_HANDOVER_NOT_SUPPORTED);
+ }
+
void onSendComplete(NdefMessage msg, long elapsedRealtime) {
if (mFirstBeam) {
EventLogTags.writeNfcFirstShare();
@@ -397,7 +411,22 @@
try {
if (DBG) Log.d(TAG, "Sending ndef via SNEP");
- result = doSnepProtocol(mHandoverManager, m, uris);
+
+ int snepResult = doSnepProtocol(mHandoverManager, m, uris);
+
+ switch (snepResult) {
+ case SNEP_HANDOVER_UNSUPPORTED:
+ onHandoverUnsupported();
+ return null;
+ case SNEP_SUCCESS:
+ result = true;
+ break;
+ case SNEP_FAILURE:
+ result = false;
+ break;
+ default:
+ result = false;
+ }
} catch (IOException e) {
Log.i(TAG, "Failed to connect over SNEP, trying NPP");
@@ -422,7 +451,7 @@
}
}
- static boolean doSnepProtocol(HandoverManager handoverManager,
+ static int doSnepProtocol(HandoverManager handoverManager,
NdefMessage msg, Uri[] uris) throws IOException {
SnepClient snepClient = new SnepClient();
try {
@@ -440,17 +469,26 @@
NdefMessage response = snepResponse.getNdefMessage();
if (response != null) {
handoverManager.doHandoverUri(uris, response);
+ } else if (msg != null) {
+ // For backwards-compatibility to pre-J devices,
+ // try to push an NDEF message (if any) if the handover GET
+ // does not work.
+ snepClient.put(msg);
+ } else {
+ // We had a failed handover and no alternate message to
+ // send; indicate remote device doesn't support handover.
+ return SNEP_HANDOVER_UNSUPPORTED;
}
} else if (msg != null) {
snepClient.put(msg);
}
- return true;
+ return SNEP_SUCCESS;
} catch (IOException e) {
// SNEP available but had errors, don't fall back to NPP.
} finally {
snepClient.close();
}
- return false;
+ return SNEP_FAILURE;
}
final NdefPushServer.Callback mNppCallback = new NdefPushServer.Callback() {
@@ -552,6 +590,18 @@
NfcService.getInstance().sendMockNdefTag(m);
}
break;
+ case MSG_HANDOVER_NOT_SUPPORTED:
+ synchronized (P2pLinkManager.this) {
+ mSendTask = null;
+
+ if (mLinkState == LINK_STATE_DOWN || mSendState != SEND_STATE_SENDING) {
+ break;
+ }
+ mSendState = SEND_STATE_NOTHING_TO_SEND;
+ if (DBG) Log.d(TAG, "onP2pHandoverNotSupported()");
+ mEventListener.onP2pHandoverNotSupported();
+ }
+ break;
case MSG_SEND_COMPLETE:
synchronized (P2pLinkManager.this) {
mSendTask = null;
@@ -567,7 +617,6 @@
mCallbackNdef.onNdefPushComplete();
} catch (RemoteException e) { }
}
- mSendTask = null;
}
break;
}
diff --git a/src/com/android/nfc/SendUi.java b/src/com/android/nfc/SendUi.java
index 5c20085..23602c9 100644
--- a/src/com/android/nfc/SendUi.java
+++ b/src/com/android/nfc/SendUi.java
@@ -45,6 +45,7 @@
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.TextView;
+import android.widget.Toast;
/**
* This class is responsible for handling the UI animation
@@ -139,6 +140,7 @@
final boolean mHardwareAccelerated;
final FireflyRenderer mFireflyRenderer;
+ String mToastString;
Bitmap mScreenshotBitmap;
boolean mAttached;
@@ -305,6 +307,7 @@
// Disable statusbar pull-down
mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND);
+ mToastString = null;
mSending = false;
mAttached = true;
@@ -329,6 +332,13 @@
mSlowSendAnimator.start();
}
+ public void finishAndToast(int finishMode, String toast) {
+ if (!mAttached) return;
+ mToastString = toast;
+
+ finish(finishMode);
+ }
+
/** Return to initial state */
public void finish(int finishMode) {
if (!mAttached) return;
@@ -389,6 +399,10 @@
mWindowManager.removeView(mScreenshotLayout);
mStatusBarManager.disable(StatusBarManager.DISABLE_NONE);
releaseScreenshot();
+ if (mToastString != null) {
+ Toast.makeText(mContext, mToastString, Toast.LENGTH_LONG).show();
+ }
+ mToastString = null;
}
public void releaseScreenshot() {