aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com
diff options
context:
space:
mode:
authorarammelk <arammelk@gmail.com>2017-08-24 12:37:19 -0700
committerAng Li <angli@google.com>2017-08-24 12:37:19 -0700
commitccedca0a4907591d994f7412adba2555c138bd0d (patch)
tree090f953570896ebff977a75bcdecacb75fd0ce40 /src/main/java/com
parentc941a467027eaa483100d04399287918851c2fe6 (diff)
downloadmobly-bundled-snippets-ccedca0a4907591d994f7412adba2555c138bd0d.tar.gz
Add synchronous waitForSms (#76)
Diffstat (limited to 'src/main/java/com')
-rw-r--r--src/main/java/com/google/android/mobly/snippet/bundled/SmsSnippet.java58
-rw-r--r--src/main/java/com/google/android/mobly/snippet/bundled/utils/Utils.java43
2 files changed, 73 insertions, 28 deletions
diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/SmsSnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/SmsSnippet.java
index 2eb8f38..4a38798 100644
--- a/src/main/java/com/google/android/mobly/snippet/bundled/SmsSnippet.java
+++ b/src/main/java/com/google/android/mobly/snippet/bundled/SmsSnippet.java
@@ -29,16 +29,14 @@ import android.provider.Telephony.Sms.Intents;
import android.support.test.InstrumentationRegistry;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
-
import com.google.android.mobly.snippet.Snippet;
+import com.google.android.mobly.snippet.bundled.utils.Utils;
import com.google.android.mobly.snippet.event.EventCache;
import com.google.android.mobly.snippet.event.SnippetEvent;
import com.google.android.mobly.snippet.rpc.AsyncRpc;
import com.google.android.mobly.snippet.rpc.Rpc;
-
import java.util.ArrayList;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.TimeUnit;
+import org.json.JSONObject;
/** Snippet class for SMS RPCs. */
public class SmsSnippet implements Snippet {
@@ -46,12 +44,12 @@ public class SmsSnippet implements Snippet {
private static class SmsSnippetException extends Exception {
private static final long serialVersionUID = 1L;
- public SmsSnippetException(String msg) {
+ SmsSnippetException(String msg) {
super(msg);
}
}
- private static final int MAX_CHAR_COUNT_PER_SMS = 160;
+ private static final int MAX_CHAR_COUNT_PER_SMS = 160;
private static final String SMS_SENT_ACTION = ".SMS_SENT";
private static final int DEFAULT_TIMEOUT_MILLISECOND = 60 * 1000;
private static final String SMS_RECEIVED_EVENT_NAME = "ReceivedSms";
@@ -71,13 +69,12 @@ public class SmsSnippet implements Snippet {
/**
* Send SMS and return after waiting for send confirmation (with a timeout of 60 seconds).
*
- * @param phoneNumber A String representing phone number with country code.
+ * @param phoneNumber A String representing phone number with country code.
* @param message A String representing the message to send.
* @throws SmsSnippetException on SMS send error.
*/
@Rpc(description = "Send SMS to a specified phone number.")
- public void sendSms(String phoneNumber, String message)
- throws SmsSnippetException {
+ public void sendSms(String phoneNumber, String message) throws Throwable {
String callbackId = SMS_CALLBACK_ID_PREFIX + (++mCallbackCounter);
OutboundSmsReceiver receiver = new OutboundSmsReceiver(mContext, callbackId);
@@ -85,33 +82,25 @@ public class SmsSnippet implements Snippet {
ArrayList<String> parts = mSmsManager.divideMessage(message);
ArrayList<PendingIntent> sIntents = new ArrayList<>();
for (int i = 0; i < parts.size(); i++) {
- sIntents.add(PendingIntent.getBroadcast(
- mContext, 0, new Intent(SMS_SENT_ACTION), 0));
+ sIntents.add(
+ PendingIntent.getBroadcast(mContext, 0, new Intent(SMS_SENT_ACTION), 0));
}
receiver.setExpectedMessageCount(parts.size());
mContext.registerReceiver(receiver, new IntentFilter(SMS_SENT_ACTION));
mSmsManager.sendMultipartTextMessage(phoneNumber, null, parts, sIntents, null);
} else {
- PendingIntent sentIntent = PendingIntent.getBroadcast(
- mContext, 0, new Intent(SMS_SENT_ACTION), 0);
+ PendingIntent sentIntent =
+ PendingIntent.getBroadcast(mContext, 0, new Intent(SMS_SENT_ACTION), 0);
receiver.setExpectedMessageCount(1);
mContext.registerReceiver(receiver, new IntentFilter(SMS_SENT_ACTION));
mSmsManager.sendTextMessage(phoneNumber, null, message, sentIntent, null);
}
- String qId = EventCache.getQueueId(callbackId, SMS_SENT_EVENT_NAME);
- LinkedBlockingDeque<SnippetEvent> q = EventCache.getInstance().getEventDeque(qId);
- SnippetEvent result;
-
- try {
- result = q.pollFirst(DEFAULT_TIMEOUT_MILLISECOND, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- throw new SmsSnippetException("Did not receive SMS sent confirmation event.");
- }
+ SnippetEvent result =
+ Utils.waitForSnippetEvent(
+ callbackId, SMS_SENT_EVENT_NAME, DEFAULT_TIMEOUT_MILLISECOND);
- if (result == null) {
- throw new SmsSnippetException("Timed out waiting for SMS sent confirmation event.");
- } else if (result.getData().containsKey("error")) {
+ if (result.getData().containsKey("error")) {
throw new SmsSnippetException(
"Failed to send SMS, error code: " + result.getData().getInt("error"));
}
@@ -124,6 +113,17 @@ public class SmsSnippet implements Snippet {
mContext.registerReceiver(receiver, new IntentFilter(Intents.SMS_RECEIVED_ACTION));
}
+ @TargetApi(Build.VERSION_CODES.KITKAT)
+ @Rpc(description = "Wait for incoming SMS message.")
+ public JSONObject waitForSms() throws Throwable {
+ String callbackId = SMS_CALLBACK_ID_PREFIX + (++mCallbackCounter);
+ SmsReceiver receiver = new SmsReceiver(mContext, callbackId);
+ mContext.registerReceiver(receiver, new IntentFilter(Intents.SMS_RECEIVED_ACTION));
+ return Utils.waitForSnippetEvent(
+ callbackId, SMS_RECEIVED_EVENT_NAME, DEFAULT_TIMEOUT_MILLISECOND)
+ .toJson();
+ }
+
@Override
public void shutdown() {}
@@ -140,7 +140,9 @@ public class SmsSnippet implements Snippet {
mExpectedMessageCount = 0;
}
- public void setExpectedMessageCount(int count) { mExpectedMessageCount = count; }
+ public void setExpectedMessageCount(int count) {
+ mExpectedMessageCount = count;
+ }
@Override
public void onReceive(Context context, Intent intent) {
@@ -148,7 +150,7 @@ public class SmsSnippet implements Snippet {
if (SMS_SENT_ACTION.equals(action)) {
SnippetEvent event = new SnippetEvent(mCallbackId, SMS_SENT_EVENT_NAME);
- switch(getResultCode()) {
+ switch (getResultCode()) {
case Activity.RESULT_OK:
if (mExpectedMessageCount == 1) {
event.getData().putBoolean("sent", true);
@@ -156,7 +158,7 @@ public class SmsSnippet implements Snippet {
mContext.unregisterReceiver(this);
}
- if (mExpectedMessageCount > 0 ) {
+ if (mExpectedMessageCount > 0) {
mExpectedMessageCount--;
}
break;
diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/utils/Utils.java b/src/main/java/com/google/android/mobly/snippet/bundled/utils/Utils.java
index 8f4f7d6..c68ae5a 100644
--- a/src/main/java/com/google/android/mobly/snippet/bundled/utils/Utils.java
+++ b/src/main/java/com/google/android/mobly/snippet/bundled/utils/Utils.java
@@ -16,10 +16,17 @@
package com.google.android.mobly.snippet.bundled.utils;
+import com.google.android.mobly.snippet.bundled.SmsSnippet;
+import com.google.android.mobly.snippet.event.EventCache;
+import com.google.android.mobly.snippet.event.SnippetEvent;
import com.google.common.primitives.Primitives;
import com.google.common.reflect.TypeToken;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.Locale;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public final class Utils {
@@ -56,6 +63,42 @@ public final class Utils {
}
/**
+ * Wait on a specific snippet event.
+ *
+ * <p>This allows a snippet to wait on another SnippetEvent as long as they know the name and
+ * callback id. Commonly used to make async calls synchronous, see {@link
+ * SmsSnippet#waitForSms()} waitForSms} for example usage.
+ *
+ * @param callbackId String callbackId that we want to wait on.
+ * @param eventName String event name that we are waiting on.
+ * @param timeout int timeout in milliseconds for how long it will wait for the event.
+ * @return SnippetEvent if one was received.
+ * @throws Throwable if interrupted while polling for event completion. Throws TimeoutException
+ * if no snippet event is received.
+ */
+ public static SnippetEvent waitForSnippetEvent(
+ String callbackId, String eventName, Integer timeout) throws Throwable {
+ String qId = EventCache.getQueueId(callbackId, eventName);
+ LinkedBlockingDeque<SnippetEvent> q = EventCache.getInstance().getEventDeque(qId);
+ SnippetEvent result;
+ try {
+ result = q.pollFirst(timeout, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ throw e.getCause();
+ }
+
+ if (result == null) {
+ throw new TimeoutException(
+ String.format(
+ Locale.ROOT,
+ "Timed out waiting(%d millis) for SnippetEvent: %s",
+ timeout,
+ callbackId));
+ }
+ return result;
+ }
+
+ /**
* A function interface that is used by lambda functions signaling an async operation is still
* going on.
*/