aboutsummaryrefslogtreecommitdiff
path: root/third_party/sl4a/src
diff options
context:
space:
mode:
authorAng Li <angli@google.com>2017-02-22 13:07:00 -0800
committerGitHub <noreply@github.com>2017-02-22 13:07:00 -0800
commitb1f23a3dd1fce48791758fc57b0a35f8da6fe961 (patch)
tree65086d01ea136cfeed2de6e0d448f6d30142221a /third_party/sl4a/src
parent0f9ab75ee996dbf8f3f1e9f400c71068df5bfe62 (diff)
downloadmobly-snippet-lib-b1f23a3dd1fce48791758fc57b0a35f8da6fe961.tar.gz
Add support for asynchronous Rpc (#38)
* Add @AsyncRpc annotation to mark Rpc methods that trigger async events. * Add `EventCache`, which is the repo of events. * Add `EventSnippet`, which has Rpc methods for client to poll events. * Add `SnippetEvent` type to represent an event. * Add `callbackId` field to Rpc protocol's server resp msg.
Diffstat (limited to 'third_party/sl4a/src')
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/EventCache.java96
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/EventSnippet.java88
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/SnippetEvent.java94
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/ReflectionSnippetManagerFactory.java5
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/SnippetManager.java1
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/AsyncRpc.java49
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcResult.java15
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcServer.java15
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java21
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/SimpleServer.java4
10 files changed, 371 insertions, 17 deletions
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/EventCache.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/EventCache.java
new file mode 100644
index 0000000..3d8775f
--- /dev/null
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/EventCache.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.android.mobly.snippet.event;
+
+import com.google.android.mobly.snippet.util.Log;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * Manage the event queue.
+ *
+ * <p>EventCache APIs interact with the SnippetEvent cache - a data structure that holds {@link
+ * SnippetEvent} objects posted from snippet classes. The SnippetEvent cache provides a useful means
+ * of recording background events (such as sensor data) when the phone is busy with foreground
+ * activities.
+ */
+public class EventCache {
+ private static final String EVENT_DEQUE_ID_TEMPLATE = "%s|%s";
+ private static final int EVENT_DEQUE_MAX_SIZE = 1024;
+
+ // A Map with each value being the queue for a particular type of event, and the key being the
+ // unique ID of the queue. The ID is composed of a callback ID and an event's name.
+ private final Map<String, LinkedBlockingDeque<SnippetEvent>> mEventDeques = new HashMap<>();
+
+ private static volatile EventCache mEventCache;
+
+ private EventCache() {}
+
+ public static synchronized EventCache getInstance() {
+ if (mEventCache == null) {
+ mEventCache = new EventCache();
+ }
+ return mEventCache;
+ }
+
+ public static String getQueueId(String callbackId, String name) {
+ return String.format(EVENT_DEQUE_ID_TEMPLATE, callbackId, name);
+ }
+
+ public LinkedBlockingDeque<SnippetEvent> getEventDeque(String qId) {
+ synchronized (mEventDeques) {
+ LinkedBlockingDeque<SnippetEvent> eventDeque = mEventDeques.get(qId);
+ if (eventDeque == null) {
+ eventDeque = new LinkedBlockingDeque<>(EVENT_DEQUE_MAX_SIZE);
+ mEventDeques.put(qId, eventDeque);
+ }
+ return eventDeque;
+ }
+ }
+
+ /**
+ * Post an {@link SnippetEvent} object to the Event cache.
+ *
+ * <p>Snippet classes should use this method to post events. If EVENT_DEQUE_MAX_SIZE is reached,
+ * the oldest elements will be retired until the new event could be posted.
+ *
+ * @param snippetEvent The snippetEvent to post to {@link EventCache}.
+ */
+ public void postEvent(SnippetEvent snippetEvent) {
+ String qId = getQueueId(snippetEvent.getCallbackId(), snippetEvent.getName());
+ Deque<SnippetEvent> q = getEventDeque(qId);
+ synchronized (q) {
+ while (!q.offer(snippetEvent)) {
+ SnippetEvent retiredEvent = q.removeFirst();
+ Log.v(
+ String.format(
+ "Retired event %s due to deque reaching the size limit (%s).",
+ retiredEvent, EVENT_DEQUE_MAX_SIZE));
+ }
+ }
+ Log.v(String.format("Posted event(%s)", qId));
+ }
+
+ /** Clears all cached events. */
+ public void clearAll() {
+ synchronized (mEventDeques) {
+ mEventDeques.clear();
+ }
+ }
+}
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/EventSnippet.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/EventSnippet.java
new file mode 100644
index 0000000..1a29b39
--- /dev/null
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/EventSnippet.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.android.mobly.snippet.event;
+
+import android.support.annotation.Nullable;
+import com.google.android.mobly.snippet.Snippet;
+import com.google.android.mobly.snippet.rpc.Rpc;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.TimeUnit;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class EventSnippet implements Snippet {
+
+ private static class EventSnippetException extends Exception {
+ public EventSnippetException(String msg) {
+ super(msg);
+ }
+ }
+
+ private static final int DEFAULT_TIMEOUT_MILLISECOND = 60 * 1000;
+ private final EventCache mEventCache = EventCache.getInstance();
+
+ @Rpc(
+ description =
+ "Blocks until an event of a specified type has been received. The returned event is removed from the cache. Default timeout is 60s."
+ )
+ public JSONObject eventWaitAndGet(
+ String callbackId, String eventName, @Nullable Integer timeout)
+ throws InterruptedException, JSONException, EventSnippetException {
+ // The server side should never wait forever, so we'll use a default timeout is one is not
+ // provided.
+ if (timeout == null) {
+ timeout = DEFAULT_TIMEOUT_MILLISECOND;
+ }
+ String qId = EventCache.getQueueId(callbackId, eventName);
+ LinkedBlockingDeque<SnippetEvent> q = mEventCache.getEventDeque(qId);
+ SnippetEvent result = q.pollFirst(timeout, TimeUnit.MILLISECONDS);
+ if (result == null) {
+ throw new EventSnippetException("timeout.");
+ }
+ return result.toJson();
+ }
+
+ @Rpc(
+ description =
+ "Gets and removes all the events of a certain name that have been received so far. "
+ + "Non-blocking. Potentially racey since it does not guarantee no event of "
+ + "the same name will occur after the call."
+ )
+ public List<JSONObject> eventGetAll(String callbackId, String eventName)
+ throws InterruptedException, JSONException {
+ String qId = EventCache.getQueueId(callbackId, eventName);
+ LinkedBlockingDeque<SnippetEvent> q = mEventCache.getEventDeque(qId);
+ ArrayList<JSONObject> results = new ArrayList<>(q.size());
+ ArrayList<SnippetEvent> buffer = new ArrayList<>(q.size());
+ q.drainTo(buffer);
+ for (SnippetEvent snippetEvent : buffer) {
+ results.add(snippetEvent.toJson());
+ }
+ if (results.size() == 0) {
+ return Collections.emptyList();
+ }
+ return results;
+ }
+
+ @Override
+ public void shutdown() {
+ mEventCache.clearAll();
+ }
+}
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/SnippetEvent.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/SnippetEvent.java
new file mode 100644
index 0000000..3db2906
--- /dev/null
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/event/SnippetEvent.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.android.mobly.snippet.event;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/** Class used to store information from a callback event. */
+public class SnippetEvent {
+
+ // The ID used to associate an event to a callback object on the client side.
+ private final String mCallbackId;
+ // The name of this event, e.g. startXxxServiceOnSuccess.
+ private final String mName;
+ // The content of this event.
+ private final JSONObject mData = new JSONObject();
+
+ private final long mCreationTime;
+
+ /**
+ * Constructs an {@link SnippetEvent} object.
+ *
+ * <p>The object is used to store information from a callback method associated with a call to
+ * an {@link com.google.android.mobly.snippet.rpc.AsyncRpc} method.
+ *
+ * @param callbackId The callbackId passed to the {@link
+ * com.google.android.mobly.snippet.rpc.AsyncRpc} method.
+ * @param name The name of the event.
+ */
+ public SnippetEvent(String callbackId, String name) {
+ if (callbackId == null) {
+ throw new IllegalArgumentException("SnippetEvent's callback ID shall not be null.");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("SnippetEvent's name shall not be null.");
+ }
+ mCallbackId = callbackId;
+ mName = name;
+ mCreationTime = System.currentTimeMillis();
+ }
+
+ public String getCallbackId() {
+ return mCallbackId;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Add serializable data to the Event.
+ *
+ * <p>This is usually for information passed by the original callback API. The data has to be
+ * JSON serializable so it can be transferred to the client side.
+ *
+ * @param name Name of the data set.
+ * @param data Content of the data.
+ * @throws JSONException
+ */
+ public void addData(String name, Object data) throws JSONException {
+ mData.put(name, data);
+ }
+
+ private JSONObject getData() {
+ return mData;
+ }
+
+ public long getCreationTime() {
+ return mCreationTime;
+ }
+
+ public JSONObject toJson() throws JSONException {
+ JSONObject result = new JSONObject();
+ result.put("callbackId", getCallbackId());
+ result.put("name", getName());
+ result.put("time", getCreationTime());
+ result.put("data", getData());
+ return result;
+ }
+}
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/ReflectionSnippetManagerFactory.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/ReflectionSnippetManagerFactory.java
index db90f32..5e4259d 100644
--- a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/ReflectionSnippetManagerFactory.java
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/ReflectionSnippetManagerFactory.java
@@ -19,9 +19,9 @@ package com.google.android.mobly.snippet.manager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.os.Build;
import android.os.Bundle;
import com.google.android.mobly.snippet.Snippet;
+import com.google.android.mobly.snippet.event.EventSnippet;
import com.google.android.mobly.snippet.util.Log;
import java.util.Collections;
import java.util.HashMap;
@@ -44,7 +44,6 @@ public class ReflectionSnippetManagerFactory implements SnippetManagerFactory {
@Override
public SnippetManager create(Integer UID) {
- int sdkLevel = Build.VERSION.SDK_INT;
SnippetManager manager = new SnippetManager(mClasses);
mSnippetManagers.put(UID, manager);
return manager;
@@ -78,6 +77,8 @@ public class ReflectionSnippetManagerFactory implements SnippetManagerFactory {
}
String[] snippetClassNames = snippets.split("\\s*,\\s*");
Set<Class<? extends Snippet>> receiverSet = new HashSet<>();
+ /** Add the event snippet class which is provided within the Snippet Lib. */
+ receiverSet.add(EventSnippet.class);
for (String snippetClassName : snippetClassNames) {
try {
Log.i("Trying to load Snippet class: " + snippetClassName);
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/SnippetManager.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/SnippetManager.java
index da5a56d..8944a84 100644
--- a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/SnippetManager.java
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/SnippetManager.java
@@ -98,7 +98,6 @@ public class SnippetManager {
if (object != null) {
return object;
}
-
Constructor<? extends Snippet> constructor;
constructor = clazz.getConstructor();
object = constructor.newInstance();
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/AsyncRpc.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/AsyncRpc.java
new file mode 100644
index 0000000..6bdd8ca
--- /dev/null
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/AsyncRpc.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.android.mobly.snippet.rpc;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link AsyncRpc} annotation is used to annotate server-side implementations of RPCs that
+ * trigger asynchronous events. This behaves generally the same as {@link Rpc}, but methods that are
+ * annotated with {@link AsyncRpc} are expected to take the extra parameter which is the ID to use
+ * when posting async events.
+ *
+ * <p>Sample Usage:
+ *
+ * <pre>{@code
+ * {@literal @}AsyncRpc(description = "An example showing the usage of AsyncRpc")
+ * public void doSomethingAsync(String callbackId, ...) {
+ * // start some async operation and post a Snippet Event object with the given callbackId.
+ * }
+ * }</pre>
+ *
+ * AsyncRpc methods can still return serializable values, which will be transported in the regular
+ * return value field of the Rpc protocol.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+@Documented
+public @interface AsyncRpc {
+ /** Returns brief description of the function. Should be limited to one or two sentences. */
+ String description();
+}
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcResult.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcResult.java
index 739eadf..de8537c 100644
--- a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcResult.java
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcResult.java
@@ -24,7 +24,7 @@ import org.json.JSONObject;
/**
* Represents a JSON RPC result.
*
- * @see http://json-rpc.org/wiki/specification
+ * @see <a href="http://json-rpc.org/wiki/specification">http://json-rpc.org/wiki/specification</a>
*/
public class JsonRpcResult {
@@ -36,6 +36,7 @@ public class JsonRpcResult {
JSONObject json = new JSONObject();
json.put("id", id);
json.put("result", JSONObject.NULL);
+ json.put("callback", JSONObject.NULL);
json.put("error", JSONObject.NULL);
return json;
}
@@ -44,6 +45,16 @@ public class JsonRpcResult {
JSONObject json = new JSONObject();
json.put("id", id);
json.put("result", JsonBuilder.build(data));
+ json.put("callback", JSONObject.NULL);
+ json.put("error", JSONObject.NULL);
+ return json;
+ }
+
+ public static JSONObject callback(int id, Object data, String callbackId) throws JSONException {
+ JSONObject json = new JSONObject();
+ json.put("id", id);
+ json.put("result", JsonBuilder.build(data));
+ json.put("callback", callbackId);
json.put("error", JSONObject.NULL);
return json;
}
@@ -54,10 +65,10 @@ public class JsonRpcResult {
t.printStackTrace(new PrintWriter(stackTraceWriter));
stackTraceWriter.write("----------------------------------------------");
String stackTrace = stackTraceWriter.toString();
-
JSONObject json = new JSONObject();
json.put("id", id);
json.put("result", JSONObject.NULL);
+ json.put("callback", JSONObject.NULL);
json.put("error", stackTrace);
return json;
}
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcServer.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcServer.java
index 6542aad..e031dcb 100644
--- a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcServer.java
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcServer.java
@@ -100,7 +100,20 @@ public class JsonRpcServer extends SimpleServer {
continue;
}
try {
- send(writer, JsonRpcResult.result(id, rpc.invoke(receiverManager, params)), UID);
+ /** If calling an {@link AsyncRpc}, put the message ID as the first param. */
+ if (rpc.isAsync()) {
+ String callbackId = String.format("%d-%d", UID, id);
+ JSONArray newParams = new JSONArray();
+ newParams.put(callbackId);
+ for (int i = 0; i < params.length(); i++) {
+ newParams.put(params.get(i));
+ }
+ Object returnValue = rpc.invoke(receiverManager, newParams);
+ send(writer, JsonRpcResult.callback(id, returnValue, callbackId), UID);
+ } else {
+ Object returnValue = rpc.invoke(receiverManager, params);
+ send(writer, JsonRpcResult.result(id, returnValue), UID);
+ }
} catch (Throwable t) {
Log.e("Invocation error.", t);
send(writer, JsonRpcResult.error(id, t), UID);
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java
index c64fdd4..6c268a0 100644
--- a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java
@@ -49,7 +49,8 @@ public final class MethodDescriptor {
public static Collection<MethodDescriptor> collectFrom(Class<? extends Snippet> clazz) {
List<MethodDescriptor> descriptors = new ArrayList<MethodDescriptor>();
for (Method method : clazz.getMethods()) {
- if (method.isAnnotationPresent(Rpc.class)) {
+ if (method.isAnnotationPresent(Rpc.class)
+ || method.isAnnotationPresent(AsyncRpc.class)) {
descriptors.add(new MethodDescriptor(clazz, method));
}
}
@@ -100,28 +101,28 @@ public final class MethodDescriptor {
// also need to convert implicitly from numbers to bools.
if (parameters.isNull(index)) {
return null;
- } else if (type == Boolean.class) {
+ } else if (type == Boolean.class || type == boolean.class) {
try {
return parameters.getBoolean(index);
} catch (JSONException e) {
return new Boolean(parameters.getInt(index) != 0);
}
- } else if (type == Long.class) {
+ } else if (type == Long.class || type == long.class) {
return parameters.getLong(index);
- } else if (type == Double.class) {
+ } else if (type == Double.class || type == double.class) {
return parameters.getDouble(index);
- } else if (type == Integer.class) {
+ } else if (type == Integer.class || type == int.class) {
return parameters.getInt(index);
} else if (type == Intent.class) {
return buildIntent(parameters.getJSONObject(index));
- } else if (type == Integer[].class) {
+ } else if (type == Integer[].class || type == int[].class) {
JSONArray list = parameters.getJSONArray(index);
Integer[] result = new Integer[list.length()];
for (int i = 0; i < list.length(); i++) {
result[i] = list.getInt(i);
}
return result;
- } else if (type == byte[].class) {
+ } else if (type == Byte.class || type == byte[].class) {
JSONArray list = parameters.getJSONArray(index);
byte[] result = new byte[list.length()];
for (int i = 0; i < list.length(); i++) {
@@ -147,7 +148,8 @@ public final class MethodDescriptor {
+ (index + 1)
+ " should be of type "
+ ((Class<?>) type).getSimpleName()
- + ".");
+ + ", but is of type "
+ + parameters.get(index).getClass().getSimpleName());
}
}
@@ -192,6 +194,9 @@ public final class MethodDescriptor {
return mMethod.getGenericParameterTypes();
}
+ public boolean isAsync() {
+ return mMethod.isAnnotationPresent(AsyncRpc.class);
+ }
/**
* Returns a human-readable help text for this RPC, based on annotations in the source code.
*
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/SimpleServer.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/SimpleServer.java
index 5b59129..61880be 100644
--- a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/SimpleServer.java
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/SimpleServer.java
@@ -191,9 +191,7 @@ public abstract class SimpleServer {
* @throws IOException
*/
public void startLocal(int port) throws IOException {
- InetAddress address;
- // address = InetAddress.getLocalHost();
- address = getPrivateInetAddress();
+ InetAddress address = getPrivateInetAddress();
mServer = new ServerSocket(port, 5, address);
start();
}