• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.googlecode.android_scripting.facade.wifi;
18 
19 import android.app.Service;
20 import android.content.Context;
21 import android.net.ConnectivityManager;
22 import android.net.wifi.nan.ConfigRequest;
23 import android.net.wifi.nan.PublishData;
24 import android.net.wifi.nan.PublishSettings;
25 import android.net.wifi.nan.SubscribeData;
26 import android.net.wifi.nan.SubscribeSettings;
27 import android.net.wifi.nan.TlvBufferUtils;
28 import android.net.wifi.nan.WifiNanEventListener;
29 import android.net.wifi.nan.WifiNanManager;
30 import android.net.wifi.nan.WifiNanSession;
31 import android.net.wifi.nan.WifiNanSessionListener;
32 import android.os.Bundle;
33 import android.os.HandlerThread;
34 import android.os.Looper;
35 import android.os.RemoteException;
36 
37 import com.googlecode.android_scripting.facade.EventFacade;
38 import com.googlecode.android_scripting.facade.FacadeManager;
39 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
40 import com.googlecode.android_scripting.rpc.Rpc;
41 import com.googlecode.android_scripting.rpc.RpcParameter;
42 
43 import org.json.JSONException;
44 import org.json.JSONObject;
45 
46 /**
47  * WifiNanManager functions.
48  */
49 public class WifiNanManagerFacade extends RpcReceiver {
50     private final Service mService;
51     private final EventFacade mEventFacade;
52 
53     private WifiNanManager mMgr;
54     private WifiNanSession mSession;
55     private HandlerThread mNanFacadeThread;
56     private ConnectivityManager mConnMgr;
57 
getFilterData(JSONObject j)58     private static TlvBufferUtils.TlvConstructor getFilterData(JSONObject j) throws JSONException {
59         if (j == null) {
60             return null;
61         }
62 
63         TlvBufferUtils.TlvConstructor constructor = new TlvBufferUtils.TlvConstructor(0, 1);
64         constructor.allocate(255);
65 
66         if (j.has("int0")) {
67             constructor.putShort(0, (short) j.getInt("int0"));
68         }
69 
70         if (j.has("int1")) {
71             constructor.putShort(0, (short) j.getInt("int1"));
72         }
73 
74         if (j.has("data0")) {
75             constructor.putString(0, j.getString("data0"));
76         }
77 
78         if (j.has("data1")) {
79             constructor.putString(0, j.getString("data1"));
80         }
81 
82         return constructor;
83     }
84 
getConfigRequest(JSONObject j)85     private static ConfigRequest getConfigRequest(JSONObject j) throws JSONException {
86         if (j == null) {
87             return null;
88         }
89 
90         ConfigRequest.Builder builder = new ConfigRequest.Builder();
91 
92         if (j.has("Support5gBand")) {
93             builder.setSupport5gBand(j.getBoolean("Support5gBand"));
94         }
95         if (j.has("MasterPreference")) {
96             builder.setMasterPreference(j.getInt("MasterPreference"));
97         }
98         if (j.has("ClusterLow")) {
99             builder.setClusterLow(j.getInt("ClusterLow"));
100         }
101         if (j.has("ClusterHigh")) {
102             builder.setClusterHigh(j.getInt("ClusterHigh"));
103         }
104 
105         return builder.build();
106     }
107 
getPublishData(JSONObject j)108     private static PublishData getPublishData(JSONObject j) throws JSONException {
109         if (j == null) {
110             return null;
111         }
112 
113         PublishData.Builder builder = new PublishData.Builder();
114 
115         if (j.has("ServiceName")) {
116             builder.setServiceName(j.getString("ServiceName"));
117         }
118 
119         if (j.has("ServiceSpecificInfo")) {
120             String ssi = j.getString("ServiceSpecificInfo");
121             builder.setServiceSpecificInfo(ssi.getBytes(), ssi.length());
122         }
123 
124         if (j.has("TxFilter")) {
125             TlvBufferUtils.TlvConstructor constructor = getFilterData(j.getJSONObject("TxFilter"));
126             builder.setTxFilter(constructor.getArray(), constructor.getActualLength());
127         }
128 
129         if (j.has("RxFilter")) {
130             TlvBufferUtils.TlvConstructor constructor = getFilterData(j.getJSONObject("RxFilter"));
131             builder.setRxFilter(constructor.getArray(), constructor.getActualLength());
132         }
133 
134         return builder.build();
135     }
136 
getPublishSettings(JSONObject j)137     private static PublishSettings getPublishSettings(JSONObject j) throws JSONException {
138         if (j == null) {
139             return null;
140         }
141 
142         PublishSettings.Builder builder = new PublishSettings.Builder();
143 
144         if (j.has("PublishType")) {
145             builder.setPublishType(j.getInt("PublishType"));
146         }
147         if (j.has("PublishCount")) {
148             builder.setPublishCount(j.getInt("PublishCount"));
149         }
150         if (j.has("TtlSec")) {
151             builder.setTtlSec(j.getInt("TtlSec"));
152         }
153 
154         return builder.build();
155     }
156 
getSubscribeData(JSONObject j)157     private static SubscribeData getSubscribeData(JSONObject j) throws JSONException {
158         if (j == null) {
159             return null;
160         }
161 
162         SubscribeData.Builder builder = new SubscribeData.Builder();
163 
164         if (j.has("ServiceName")) {
165             builder.setServiceName(j.getString("ServiceName"));
166         }
167 
168         if (j.has("ServiceSpecificInfo")) {
169             String ssi = j.getString("ServiceSpecificInfo");
170             builder.setServiceSpecificInfo(ssi);
171         }
172 
173         if (j.has("TxFilter")) {
174             TlvBufferUtils.TlvConstructor constructor = getFilterData(j.getJSONObject("TxFilter"));
175             builder.setTxFilter(constructor.getArray(), constructor.getActualLength());
176         }
177 
178         if (j.has("RxFilter")) {
179             TlvBufferUtils.TlvConstructor constructor = getFilterData(j.getJSONObject("RxFilter"));
180             builder.setRxFilter(constructor.getArray(), constructor.getActualLength());
181         }
182 
183         return builder.build();
184     }
185 
getSubscribeSettings(JSONObject j)186     private static SubscribeSettings getSubscribeSettings(JSONObject j) throws JSONException {
187         if (j == null) {
188             return null;
189         }
190 
191         SubscribeSettings.Builder builder = new SubscribeSettings.Builder();
192 
193         if (j.has("SubscribeType")) {
194             builder.setSubscribeType(j.getInt("SubscribeType"));
195         }
196         if (j.has("SubscribeCount")) {
197             builder.setSubscribeCount(j.getInt("SubscribeCount"));
198         }
199         if (j.has("TtlSec")) {
200             builder.setTtlSec(j.getInt("TtlSec"));
201         }
202 
203         return builder.build();
204     }
205 
WifiNanManagerFacade(FacadeManager manager)206     public WifiNanManagerFacade(FacadeManager manager) {
207         super(manager);
208         mService = manager.getService();
209 
210         mNanFacadeThread = new HandlerThread("nanFacadeThread");
211         mNanFacadeThread.start();
212 
213         mMgr = (WifiNanManager) mService.getSystemService(Context.WIFI_NAN_SERVICE);
214         mMgr.connect(new NanEventListenerPostsEvents(mNanFacadeThread.getLooper()),
215                 WifiNanEventListener.LISTEN_CONFIG_COMPLETED
216                         | WifiNanEventListener.LISTEN_CONFIG_FAILED
217                         | WifiNanEventListener.LISTEN_NAN_DOWN
218                         | WifiNanEventListener.LISTEN_IDENTITY_CHANGED);
219 
220         mConnMgr = (ConnectivityManager) mService.getSystemService(Context.CONNECTIVITY_SERVICE);
221 
222         mEventFacade = manager.getReceiver(EventFacade.class);
223     }
224 
225     @Override
shutdown()226     public void shutdown() {
227     }
228 
229     @Rpc(description = "Start NAN.")
wifiNanEnable(@pcParametername = "nanConfig") JSONObject nanConfig)230     public void wifiNanEnable(@RpcParameter(name = "nanConfig") JSONObject nanConfig)
231             throws RemoteException, JSONException {
232         mMgr.requestConfig(getConfigRequest(nanConfig));
233     }
234 
235     @Rpc(description = "Stop NAN.")
wifiNanDisable()236     public void wifiNanDisable() throws RemoteException, JSONException {
237         mMgr.disconnect();
238     }
239 
240     @Rpc(description = "Publish.")
wifiNanPublish(@pcParametername = "publishData") JSONObject publishData, @RpcParameter(name = "publishSettings") JSONObject publishSettings, @RpcParameter(name = "listenerId") Integer listenerId)241     public void wifiNanPublish(@RpcParameter(name = "publishData") JSONObject publishData,
242             @RpcParameter(name = "publishSettings") JSONObject publishSettings,
243             @RpcParameter(name = "listenerId") Integer listenerId)
244                     throws RemoteException, JSONException {
245         mSession = mMgr.publish(getPublishData(publishData), getPublishSettings(publishSettings),
246                 new NanSessionListenerPostsEvents(mNanFacadeThread.getLooper(), listenerId),
247                 WifiNanSessionListener.LISTEN_PUBLISH_FAIL
248                         | WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED
249                         | WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL
250                         | WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED
251                         | WifiNanSessionListener.LISTEN_MATCH
252                         | WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS
253                         | WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL
254                         | WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED);
255     }
256 
257     @Rpc(description = "Subscribe.")
wifiNanSubscribe(@pcParametername = "subscribeData") JSONObject subscribeData, @RpcParameter(name = "subscribeSettings") JSONObject subscribeSettings, @RpcParameter(name = "listenerId") Integer listenerId)258     public void wifiNanSubscribe(@RpcParameter(name = "subscribeData") JSONObject subscribeData,
259             @RpcParameter(name = "subscribeSettings") JSONObject subscribeSettings,
260             @RpcParameter(name = "listenerId") Integer listenerId)
261                     throws RemoteException, JSONException {
262 
263         mSession = mMgr.subscribe(getSubscribeData(subscribeData),
264                 getSubscribeSettings(subscribeSettings),
265                 new NanSessionListenerPostsEvents(mNanFacadeThread.getLooper(), listenerId),
266                 WifiNanSessionListener.LISTEN_PUBLISH_FAIL
267                         | WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED
268                         | WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL
269                         | WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED
270                         | WifiNanSessionListener.LISTEN_MATCH
271                         | WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS
272                         | WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL
273                         | WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED);
274     }
275 
276     @Rpc(description = "Send peer-to-peer NAN message")
wifiNanSendMessage( @pcParametername = "peerId", description = "The ID of the peer being communicated " + "with. Obtained from a previous message or match session.") Integer peerId, @RpcParameter(name = "message") String message, @RpcParameter(name = "messageId", description = "Arbitrary handle used for " + "identification of the message in the message status callbacks") Integer messageId)277     public void wifiNanSendMessage(
278             @RpcParameter(name = "peerId", description = "The ID of the peer being communicated "
279                     + "with. Obtained from a previous message or match session.") Integer peerId,
280             @RpcParameter(name = "message") String message,
281             @RpcParameter(name = "messageId", description = "Arbitrary handle used for "
282                     + "identification of the message in the message status callbacks")
283             Integer messageId)
284                     throws RemoteException {
285         mSession.sendMessage(peerId, message.getBytes(), message.length(), messageId);
286     }
287 
288     private class NanEventListenerPostsEvents extends WifiNanEventListener {
NanEventListenerPostsEvents(Looper looper)289         public NanEventListenerPostsEvents(Looper looper) {
290             super(looper);
291         }
292 
293         @Override
onConfigCompleted(ConfigRequest configRequest)294         public void onConfigCompleted(ConfigRequest configRequest) {
295             Bundle mResults = new Bundle();
296             mResults.putParcelable("configRequest", configRequest);
297             mEventFacade.postEvent("WifiNanOnConfigCompleted", mResults);
298         }
299 
300         @Override
onConfigFailed(ConfigRequest failedConfig, int reason)301         public void onConfigFailed(ConfigRequest failedConfig, int reason) {
302             Bundle mResults = new Bundle();
303             mResults.putParcelable("failedConfig", failedConfig);
304             mResults.putInt("reason", reason);
305             mEventFacade.postEvent("WifiNanOnConfigFailed", mResults);
306         }
307 
308         @Override
onNanDown(int reason)309         public void onNanDown(int reason) {
310             Bundle mResults = new Bundle();
311             mResults.putInt("reason", reason);
312             mEventFacade.postEvent("WifiNanOnNanDown", mResults);
313         }
314 
315         @Override
onIdentityChanged()316         public void onIdentityChanged() {
317             Bundle mResults = new Bundle();
318             mEventFacade.postEvent("WifiNanOnIdentityChanged", mResults);
319         }
320     }
321 
322     private class NanSessionListenerPostsEvents extends WifiNanSessionListener {
323         private int mListenerId;
324 
NanSessionListenerPostsEvents(Looper looper, int listenerId)325         public NanSessionListenerPostsEvents(Looper looper, int listenerId) {
326             super(looper);
327             mListenerId = listenerId;
328         }
329 
330         @Override
onPublishFail(int reason)331         public void onPublishFail(int reason) {
332             Bundle mResults = new Bundle();
333             mResults.putInt("listenerId", mListenerId);
334             mResults.putInt("reason", reason);
335             mEventFacade.postEvent("WifiNanSessionOnPublishFail", mResults);
336         }
337 
338         @Override
onPublishTerminated(int reason)339         public void onPublishTerminated(int reason) {
340             Bundle mResults = new Bundle();
341             mResults.putInt("listenerId", mListenerId);
342             mResults.putInt("reason", reason);
343             mEventFacade.postEvent("WifiNanSessionOnPublishTerminated", mResults);
344         }
345 
346         @Override
onSubscribeFail(int reason)347         public void onSubscribeFail(int reason) {
348             Bundle mResults = new Bundle();
349             mResults.putInt("listenerId", mListenerId);
350             mResults.putInt("reason", reason);
351             mEventFacade.postEvent("WifiNanSessionOnSubscribeFail", mResults);
352         }
353 
354         @Override
onSubscribeTerminated(int reason)355         public void onSubscribeTerminated(int reason) {
356             Bundle mResults = new Bundle();
357             mResults.putInt("listenerId", mListenerId);
358             mResults.putInt("reason", reason);
359             mEventFacade.postEvent("WifiNanSessionOnSubscribeTerminated", mResults);
360         }
361 
362         @Override
onMatch(int peerId, byte[] serviceSpecificInfo, int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength)363         public void onMatch(int peerId, byte[] serviceSpecificInfo,
364                 int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength) {
365             Bundle mResults = new Bundle();
366             mResults.putInt("listenerId", mListenerId);
367             mResults.putInt("peerId", peerId);
368             mResults.putInt("serviceSpecificInfoLength", serviceSpecificInfoLength);
369             mResults.putByteArray("serviceSpecificInfo", serviceSpecificInfo); // TODO: base64
370             mResults.putInt("matchFilterLength", matchFilterLength);
371             mResults.putByteArray("matchFilter", matchFilter); // TODO: base64
372             mEventFacade.postEvent("WifiNanSessionOnMatch", mResults);
373         }
374 
375         @Override
onMessageSendSuccess(int messageId)376         public void onMessageSendSuccess(int messageId) {
377             Bundle mResults = new Bundle();
378             mResults.putInt("listenerId", mListenerId);
379             mResults.putInt("messageId", messageId);
380             mEventFacade.postEvent("WifiNanSessionOnMessageSendSuccess", mResults);
381         }
382 
383         @Override
onMessageSendFail(int messageId, int reason)384         public void onMessageSendFail(int messageId, int reason) {
385             Bundle mResults = new Bundle();
386             mResults.putInt("listenerId", mListenerId);
387             mResults.putInt("messageId", messageId);
388             mResults.putInt("reason", reason);
389             mEventFacade.postEvent("WifiNanSessionOnMessageSendFail", mResults);
390         }
391 
392         @Override
onMessageReceived(int peerId, byte[] message, int messageLength)393         public void onMessageReceived(int peerId, byte[] message, int messageLength) {
394             Bundle mResults = new Bundle();
395             mResults.putInt("listenerId", mListenerId);
396             mResults.putInt("peerId", peerId);
397             mResults.putInt("messageLength", messageLength);
398             mResults.putByteArray("message", message); // TODO: base64
399             mResults.putString("messageAsString", new String(message, 0, messageLength));
400             mEventFacade.postEvent("WifiNanSessionOnMessageReceived", mResults);
401         }
402     }
403 }
404