Merge "Facade changes for uid de-race automation" am: 973d71b61a am: 2eecda2365 am: cd8bd4fb64
am: 6eb507dd8d

Change-Id: I40a378a40bee8e1d04ceac00e70c219bece79253
diff --git a/Common/src/com/googlecode/android_scripting/facade/wifi/WifiAwareManagerFacade.java b/Common/src/com/googlecode/android_scripting/facade/wifi/WifiAwareManagerFacade.java
index ff60bd5..2b6249e 100644
--- a/Common/src/com/googlecode/android_scripting/facade/wifi/WifiAwareManagerFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/wifi/WifiAwareManagerFacade.java
@@ -47,6 +47,8 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
 import libcore.util.HexEncoding;
 
 import com.googlecode.android_scripting.facade.EventFacade;
@@ -194,6 +196,13 @@
         return constructor;
     }
 
+    private static String getStringOrNull(JSONObject j, String name) throws JSONException {
+        if (j.isNull(name)) {
+            return null;
+        }
+        return j.getString(name);
+    }
+
     private static ConfigRequest getConfigRequest(JSONObject j) throws JSONException {
         if (j == null) {
             return null;
@@ -232,6 +241,14 @@
         return builder.build();
     }
 
+    private static List<byte[]> getMatchFilter(JSONArray ja) throws JSONException {
+        List<byte[]> la = new ArrayList<>();
+        for (int i = 0; i < ja.length(); ++i) {
+            la.add(Base64.decode(ja.getString(i).getBytes(StandardCharsets.UTF_8), Base64.DEFAULT));
+        }
+        return la;
+    }
+
     private static PublishConfig getPublishConfig(JSONObject j) throws JSONException {
         if (j == null) {
             return null;
@@ -240,13 +257,14 @@
         PublishConfig.Builder builder = new PublishConfig.Builder();
 
         if (j.has("ServiceName")) {
-            builder.setServiceName(j.getString("ServiceName"));
+            builder.setServiceName(getStringOrNull(j, "ServiceName"));
         }
 
         if (j.has("ServiceSpecificInfo")) {
-            String ssi = j.getString("ServiceSpecificInfo");
-            byte[] bytes = ssi.getBytes();
-            builder.setServiceSpecificInfo(bytes);
+            String ssi = getStringOrNull(j, "ServiceSpecificInfo");
+            if (ssi != null) {
+                builder.setServiceSpecificInfo(ssi.getBytes());
+            }
         }
 
         if (j.has("MatchFilter")) {
@@ -256,13 +274,17 @@
                     new TlvBufferUtils.TlvIterable(0, 1, constructor.getArray()).toList());
         }
 
-        if (j.has("PublishType")) {
-            builder.setPublishType(j.getInt("PublishType"));
+        if (!j.isNull("MatchFilterList")) {
+            builder.setMatchFilter(getMatchFilter(j.getJSONArray("MatchFilterList")));
+        }
+
+        if (j.has("DiscoveryType")) {
+            builder.setPublishType(j.getInt("DiscoveryType"));
         }
         if (j.has("TtlSec")) {
             builder.setTtlSec(j.getInt("TtlSec"));
         }
-        if (j.has("EnableTerminateNotification")) {
+        if (j.has("TerminateNotificationEnabled")) {
             builder.setTerminateNotificationEnabled(j.getBoolean("TerminateNotificationEnabled"));
         }
 
@@ -281,8 +303,10 @@
         }
 
         if (j.has("ServiceSpecificInfo")) {
-            String ssi = j.getString("ServiceSpecificInfo");
-            builder.setServiceSpecificInfo(ssi.getBytes());
+            String ssi = getStringOrNull(j, "ServiceSpecificInfo");
+            if (ssi != null) {
+                builder.setServiceSpecificInfo(ssi.getBytes());
+            }
         }
 
         if (j.has("MatchFilter")) {
@@ -292,13 +316,17 @@
                     new TlvBufferUtils.TlvIterable(0, 1, constructor.getArray()).toList());
         }
 
-        if (j.has("SubscribeType")) {
-            builder.setSubscribeType(j.getInt("SubscribeType"));
+        if (!j.isNull("MatchFilterList")) {
+            builder.setMatchFilter(getMatchFilter(j.getJSONArray("MatchFilterList")));
+        }
+
+        if (j.has("DiscoveryType")) {
+            builder.setSubscribeType(j.getInt("DiscoveryType"));
         }
         if (j.has("TtlSec")) {
             builder.setTtlSec(j.getInt("TtlSec"));
         }
-        if (j.has("EnableTerminateNotification")) {
+        if (j.has("TerminateNotificationEnabled")) {
             builder.setTerminateNotificationEnabled(j.getBoolean("TerminateNotificationEnabled"));
         }
 
@@ -349,13 +377,26 @@
 
     @Rpc(description = "Attach to Aware.")
     public Integer wifiAwareAttach(
-            @RpcParameter(name = "awareConfig") @RpcOptional JSONObject awareConfig)
+            @RpcParameter(name = "identityCb",
+                description = "Controls whether an identity callback is provided")
+                @RpcOptional Boolean identityCb,
+            @RpcParameter(name = "awareConfig",
+                description = "The session configuration, or null for default config")
+                @RpcOptional JSONObject awareConfig,
+            @RpcParameter(name = "useIdInCallbackEvent",
+                description =
+                    "Specifies whether the callback events should be decorated with session Id")
+                @RpcOptional Boolean useIdInCallbackEvent)
             throws RemoteException, JSONException {
         synchronized (mLock) {
             int sessionId = getNextSessionId();
+            boolean useIdInCallbackEventName =
+                (useIdInCallbackEvent != null) ? useIdInCallbackEvent : false;
             mMgr.attach(null, getConfigRequest(awareConfig),
-                    new AwareAttachCallbackPostsEvents(sessionId),
-                    new AwareIdentityChangeListenerPostsEvents(sessionId));
+                    new AwareAttachCallbackPostsEvents(sessionId, useIdInCallbackEventName),
+                    (identityCb != null && identityCb.booleanValue())
+                        ? new AwareIdentityChangeListenerPostsEvents(sessionId,
+                        useIdInCallbackEventName) : null);
             return sessionId;
         }
     }
@@ -379,7 +420,11 @@
     @Rpc(description = "Publish.")
     public Integer wifiAwarePublish(
             @RpcParameter(name = "clientId", description = "The client ID returned when a connection was created") Integer clientId,
-            @RpcParameter(name = "publishConfig") JSONObject publishConfig)
+            @RpcParameter(name = "publishConfig") JSONObject publishConfig,
+            @RpcParameter(name = "useIdInCallbackEvent",
+            description =
+                "Specifies whether the callback events should be decorated with session Id")
+                @RpcOptional Boolean useIdInCallbackEvent)
             throws RemoteException, JSONException {
         synchronized (mLock) {
             WifiAwareSession session = mSessions.get(clientId);
@@ -388,18 +433,47 @@
                         "Calling WifiAwarePublish before session (client ID " + clientId
                                 + ") is ready/or already disconnected");
             }
+            boolean useIdInCallbackEventName =
+                (useIdInCallbackEvent != null) ? useIdInCallbackEvent : false;
 
             int discoverySessionId = getNextDiscoverySessionId();
             session.publish(getPublishConfig(publishConfig),
-                    new AwareDiscoverySessionCallbackPostsEvents(discoverySessionId), null);
+                new AwareDiscoverySessionCallbackPostsEvents(discoverySessionId,
+                    useIdInCallbackEventName), null);
             return discoverySessionId;
         }
     }
 
+    @Rpc(description = "Update Publish.")
+    public void wifiAwareUpdatePublish(
+        @RpcParameter(name = "sessionId", description = "The discovery session ID")
+            Integer sessionId,
+        @RpcParameter(name = "publishConfig", description = "Publish configuration")
+            JSONObject publishConfig)
+        throws RemoteException, JSONException {
+        synchronized (mLock) {
+            DiscoverySession session = mDiscoverySessions.get(sessionId);
+            if (session == null) {
+                throw new IllegalStateException(
+                    "Calling wifiAwareUpdatePublish before session (session ID "
+                        + sessionId + ") is ready");
+            }
+            if (!(session instanceof PublishDiscoverySession)) {
+                throw new IllegalArgumentException(
+                    "Calling wifiAwareUpdatePublish with a subscribe session ID");
+            }
+            ((PublishDiscoverySession) session).updatePublish(getPublishConfig(publishConfig));
+        }
+    }
+
     @Rpc(description = "Subscribe.")
     public Integer wifiAwareSubscribe(
             @RpcParameter(name = "clientId", description = "The client ID returned when a connection was created") Integer clientId,
-            @RpcParameter(name = "subscribeConfig") JSONObject subscribeConfig)
+            @RpcParameter(name = "subscribeConfig") JSONObject subscribeConfig,
+            @RpcParameter(name = "useIdInCallbackEvent",
+                description =
+                "Specifies whether the callback events should be decorated with session Id")
+                @RpcOptional Boolean useIdInCallbackEvent)
             throws RemoteException, JSONException {
         synchronized (mLock) {
             WifiAwareSession session = mSessions.get(clientId);
@@ -408,14 +482,40 @@
                         "Calling WifiAwareSubscribe before session (client ID " + clientId
                                 + ") is ready/or already disconnected");
             }
+            boolean useIdInCallbackEventName =
+                (useIdInCallbackEvent != null) ? useIdInCallbackEvent : false;
 
             int discoverySessionId = getNextDiscoverySessionId();
             session.subscribe(getSubscribeConfig(subscribeConfig),
-                    new AwareDiscoverySessionCallbackPostsEvents(discoverySessionId), null);
+                new AwareDiscoverySessionCallbackPostsEvents(discoverySessionId,
+                    useIdInCallbackEventName), null);
             return discoverySessionId;
         }
     }
 
+    @Rpc(description = "Update Subscribe.")
+    public void wifiAwareUpdateSubscribe(
+        @RpcParameter(name = "sessionId", description = "The discovery session ID")
+            Integer sessionId,
+        @RpcParameter(name = "subscribeConfig", description = "Subscribe configuration")
+            JSONObject subscribeConfig)
+        throws RemoteException, JSONException {
+        synchronized (mLock) {
+            DiscoverySession session = mDiscoverySessions.get(sessionId);
+            if (session == null) {
+                throw new IllegalStateException(
+                    "Calling wifiAwareUpdateSubscribe before session (session ID "
+                        + sessionId + ") is ready");
+            }
+            if (!(session instanceof SubscribeDiscoverySession)) {
+                throw new IllegalArgumentException(
+                    "Calling wifiAwareUpdateSubscribe with a publish session ID");
+            }
+            ((SubscribeDiscoverySession) session)
+                .updateSubscribe(getSubscribeConfig(subscribeConfig));
+        }
+    }
+
     @Rpc(description = "Destroy a discovery Session.")
     public void wifiAwareDestroyDiscoverySession(
             @RpcParameter(name = "sessionId", description = "The discovery session ID returned when session was created using publish or subscribe") Integer sessionId)
@@ -516,10 +616,12 @@
     private class AwareAttachCallbackPostsEvents extends AttachCallback {
         private int mSessionId;
         private long mCreateTimestampMs;
+        private boolean mUseIdInCallbackEventName;
 
-        public AwareAttachCallbackPostsEvents(int sessionId) {
+        public AwareAttachCallbackPostsEvents(int sessionId, boolean useIdInCallbackEventName) {
             mSessionId = sessionId;
             mCreateTimestampMs = System.currentTimeMillis();
+            mUseIdInCallbackEventName = useIdInCallbackEventName;
         }
 
         @Override
@@ -532,7 +634,11 @@
             mResults.putInt("sessionId", mSessionId);
             mResults.putLong("latencyMs", System.currentTimeMillis() - mCreateTimestampMs);
             mResults.putLong("timestampMs", System.currentTimeMillis());
-            mEventFacade.postEvent("WifiAwareOnAttached", mResults);
+            if (mUseIdInCallbackEventName) {
+                mEventFacade.postEvent("WifiAwareOnAttached_" + mSessionId, mResults);
+            } else {
+                mEventFacade.postEvent("WifiAwareOnAttached", mResults);
+            }
         }
 
         @Override
@@ -540,15 +646,22 @@
             Bundle mResults = new Bundle();
             mResults.putInt("sessionId", mSessionId);
             mResults.putLong("latencyMs", System.currentTimeMillis() - mCreateTimestampMs);
-            mEventFacade.postEvent("WifiAwareOnAttachFailed", mResults);
+            if (mUseIdInCallbackEventName) {
+                mEventFacade.postEvent("WifiAwareOnAttachFailed_" + mSessionId, mResults);
+            } else {
+                mEventFacade.postEvent("WifiAwareOnAttachFailed", mResults);
+            }
         }
     }
 
     private class AwareIdentityChangeListenerPostsEvents extends IdentityChangedListener {
         private int mSessionId;
+        private boolean mUseIdInCallbackEventName;
 
-        public AwareIdentityChangeListenerPostsEvents(int sessionId) {
+        public AwareIdentityChangeListenerPostsEvents(int sessionId,
+            boolean useIdInCallbackEventName) {
             mSessionId = sessionId;
+            mUseIdInCallbackEventName = useIdInCallbackEventName;
         }
 
         @Override
@@ -557,20 +670,36 @@
             mResults.putInt("sessionId", mSessionId);
             mResults.putString("mac", String.valueOf(HexEncoding.encode(mac)));
             mResults.putLong("timestampMs", System.currentTimeMillis());
-            mEventFacade.postEvent("WifiAwareOnIdentityChanged", mResults);
+            if (mUseIdInCallbackEventName) {
+                mEventFacade.postEvent("WifiAwareOnIdentityChanged_" + mSessionId, mResults);
+            } else {
+                mEventFacade.postEvent("WifiAwareOnIdentityChanged", mResults);
+            }
         }
     }
 
     private class AwareDiscoverySessionCallbackPostsEvents extends
             DiscoverySessionCallback {
         private int mDiscoverySessionId;
+        private boolean mUseIdInCallbackEventName;
         private long mCreateTimestampMs;
 
-        public AwareDiscoverySessionCallbackPostsEvents(int discoverySessionId) {
+        public AwareDiscoverySessionCallbackPostsEvents(int discoverySessionId,
+                boolean useIdInCallbackEventName) {
             mDiscoverySessionId = discoverySessionId;
+            mUseIdInCallbackEventName = useIdInCallbackEventName;
             mCreateTimestampMs = System.currentTimeMillis();
         }
 
+        private void postEvent(String eventName, Bundle results) {
+            String finalEventName = eventName;
+            if (mUseIdInCallbackEventName) {
+                finalEventName += "_" + mDiscoverySessionId;
+            }
+
+            mEventFacade.postEvent(finalEventName, results);
+        }
+
         @Override
         public void onPublishStarted(PublishDiscoverySession discoverySession) {
             synchronized (mLock) {
@@ -581,7 +710,7 @@
             mResults.putInt("discoverySessionId", mDiscoverySessionId);
             mResults.putLong("latencyMs", System.currentTimeMillis() - mCreateTimestampMs);
             mResults.putLong("timestampMs", System.currentTimeMillis());
-            mEventFacade.postEvent("WifiAwareSessionOnPublishStarted", mResults);
+            postEvent("WifiAwareSessionOnPublishStarted", mResults);
         }
 
         @Override
@@ -594,28 +723,28 @@
             mResults.putInt("discoverySessionId", mDiscoverySessionId);
             mResults.putLong("latencyMs", System.currentTimeMillis() - mCreateTimestampMs);
             mResults.putLong("timestampMs", System.currentTimeMillis());
-            mEventFacade.postEvent("WifiAwareSessionOnSubscribeStarted", mResults);
+            postEvent("WifiAwareSessionOnSubscribeStarted", mResults);
         }
 
         @Override
         public void onSessionConfigUpdated() {
             Bundle mResults = new Bundle();
             mResults.putInt("discoverySessionId", mDiscoverySessionId);
-            mEventFacade.postEvent("WifiAwareSessionOnSessionConfigUpdated", mResults);
+            postEvent("WifiAwareSessionOnSessionConfigUpdated", mResults);
         }
 
         @Override
         public void onSessionConfigFailed() {
             Bundle mResults = new Bundle();
             mResults.putInt("discoverySessionId", mDiscoverySessionId);
-            mEventFacade.postEvent("WifiAwareSessionOnSessionConfigFailed", mResults);
+            postEvent("WifiAwareSessionOnSessionConfigFailed", mResults);
         }
 
         @Override
         public void onSessionTerminated() {
             Bundle mResults = new Bundle();
             mResults.putInt("discoverySessionId", mDiscoverySessionId);
-            mEventFacade.postEvent("WifiAwareSessionOnSessionTerminated", mResults);
+            postEvent("WifiAwareSessionOnSessionTerminated", mResults);
         }
 
         @Override
@@ -624,11 +753,16 @@
             Bundle mResults = new Bundle();
             mResults.putInt("discoverySessionId", mDiscoverySessionId);
             mResults.putInt("peerId", peerHandle.peerId);
-            mResults.putByteArray("serviceSpecificInfo", serviceSpecificInfo); // TODO: base64
+            mResults.putByteArray("serviceSpecificInfo", serviceSpecificInfo);
             mResults.putByteArray("matchFilter", new TlvBufferUtils.TlvConstructor(0,
-                    1).allocateAndPut(matchFilter).getArray()); // TODO: base64
+                    1).allocateAndPut(matchFilter).getArray());
+            ArrayList<String> matchFilterStrings = new ArrayList<>(matchFilter.size());
+            for (byte[] be: matchFilter) {
+                matchFilterStrings.add(Base64.encodeToString(be, Base64.DEFAULT));
+            }
+            mResults.putStringArrayList("matchFilterList", matchFilterStrings);
             mResults.putLong("timestampMs", System.currentTimeMillis());
-            mEventFacade.postEvent("WifiAwareSessionOnServiceDiscovered", mResults);
+            postEvent("WifiAwareSessionOnServiceDiscovered", mResults);
         }
 
         @Override
@@ -644,7 +778,7 @@
                     mMessageStartTime.remove(messageId);
                 }
             }
-            mEventFacade.postEvent("WifiAwareSessionOnMessageSent", mResults);
+            postEvent("WifiAwareSessionOnMessageSent", mResults);
         }
 
         @Override
@@ -660,7 +794,7 @@
                     mMessageStartTime.remove(messageId);
                 }
             }
-            mEventFacade.postEvent("WifiAwareSessionOnMessageSendFailed", mResults);
+            postEvent("WifiAwareSessionOnMessageSendFailed", mResults);
         }
 
         @Override
@@ -670,7 +804,7 @@
             mResults.putInt("peerId", peerHandle.peerId);
             mResults.putByteArray("message", message); // TODO: base64
             mResults.putString("messageAsString", new String(message));
-            mEventFacade.postEvent("WifiAwareSessionOnMessageReceived", mResults);
+            postEvent("WifiAwareSessionOnMessageReceived", mResults);
         }
     }