blob: 5863e8d5620afa0d82c72c785fe689a4251aa598 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* 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.googlecode.android_scripting.facade.wifi;
import android.app.Service;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.wifi.nan.ConfigRequest;
import android.net.wifi.nan.PublishData;
import android.net.wifi.nan.PublishSettings;
import android.net.wifi.nan.SubscribeData;
import android.net.wifi.nan.SubscribeSettings;
import android.net.wifi.nan.TlvBufferUtils;
import android.net.wifi.nan.WifiNanEventListener;
import android.net.wifi.nan.WifiNanManager;
import android.net.wifi.nan.WifiNanSession;
import android.net.wifi.nan.WifiNanSessionListener;
import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.RemoteException;
import com.googlecode.android_scripting.facade.EventFacade;
import com.googlecode.android_scripting.facade.FacadeManager;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcParameter;
import org.json.JSONException;
import org.json.JSONObject;
/**
* WifiNanManager functions.
*/
public class WifiNanManagerFacade extends RpcReceiver {
private final Service mService;
private final EventFacade mEventFacade;
private WifiNanManager mMgr;
private WifiNanSession mSession;
private HandlerThread mNanFacadeThread;
private ConnectivityManager mConnMgr;
private static TlvBufferUtils.TlvConstructor getFilterData(JSONObject j) throws JSONException {
if (j == null) {
return null;
}
TlvBufferUtils.TlvConstructor constructor = new TlvBufferUtils.TlvConstructor(0, 1);
constructor.allocate(255);
if (j.has("int0")) {
constructor.putShort(0, (short) j.getInt("int0"));
}
if (j.has("int1")) {
constructor.putShort(0, (short) j.getInt("int1"));
}
if (j.has("data0")) {
constructor.putString(0, j.getString("data0"));
}
if (j.has("data1")) {
constructor.putString(0, j.getString("data1"));
}
return constructor;
}
private static ConfigRequest getConfigRequest(JSONObject j) throws JSONException {
if (j == null) {
return null;
}
ConfigRequest.Builder builder = new ConfigRequest.Builder();
if (j.has("Support5gBand")) {
builder.setSupport5gBand(j.getBoolean("Support5gBand"));
}
if (j.has("MasterPreference")) {
builder.setMasterPreference(j.getInt("MasterPreference"));
}
if (j.has("ClusterLow")) {
builder.setClusterLow(j.getInt("ClusterLow"));
}
if (j.has("ClusterHigh")) {
builder.setClusterHigh(j.getInt("ClusterHigh"));
}
return builder.build();
}
private static PublishData getPublishData(JSONObject j) throws JSONException {
if (j == null) {
return null;
}
PublishData.Builder builder = new PublishData.Builder();
if (j.has("ServiceName")) {
builder.setServiceName(j.getString("ServiceName"));
}
if (j.has("ServiceSpecificInfo")) {
String ssi = j.getString("ServiceSpecificInfo");
builder.setServiceSpecificInfo(ssi.getBytes(), ssi.length());
}
if (j.has("TxFilter")) {
TlvBufferUtils.TlvConstructor constructor = getFilterData(j.getJSONObject("TxFilter"));
builder.setTxFilter(constructor.getArray(), constructor.getActualLength());
}
if (j.has("RxFilter")) {
TlvBufferUtils.TlvConstructor constructor = getFilterData(j.getJSONObject("RxFilter"));
builder.setRxFilter(constructor.getArray(), constructor.getActualLength());
}
return builder.build();
}
private static PublishSettings getPublishSettings(JSONObject j) throws JSONException {
if (j == null) {
return null;
}
PublishSettings.Builder builder = new PublishSettings.Builder();
if (j.has("PublishType")) {
builder.setPublishType(j.getInt("PublishType"));
}
if (j.has("PublishCount")) {
builder.setPublishCount(j.getInt("PublishCount"));
}
if (j.has("TtlSec")) {
builder.setTtlSec(j.getInt("TtlSec"));
}
return builder.build();
}
private static SubscribeData getSubscribeData(JSONObject j) throws JSONException {
if (j == null) {
return null;
}
SubscribeData.Builder builder = new SubscribeData.Builder();
if (j.has("ServiceName")) {
builder.setServiceName(j.getString("ServiceName"));
}
if (j.has("ServiceSpecificInfo")) {
String ssi = j.getString("ServiceSpecificInfo");
builder.setServiceSpecificInfo(ssi);
}
if (j.has("TxFilter")) {
TlvBufferUtils.TlvConstructor constructor = getFilterData(j.getJSONObject("TxFilter"));
builder.setTxFilter(constructor.getArray(), constructor.getActualLength());
}
if (j.has("RxFilter")) {
TlvBufferUtils.TlvConstructor constructor = getFilterData(j.getJSONObject("RxFilter"));
builder.setRxFilter(constructor.getArray(), constructor.getActualLength());
}
return builder.build();
}
private static SubscribeSettings getSubscribeSettings(JSONObject j) throws JSONException {
if (j == null) {
return null;
}
SubscribeSettings.Builder builder = new SubscribeSettings.Builder();
if (j.has("SubscribeType")) {
builder.setSubscribeType(j.getInt("SubscribeType"));
}
if (j.has("SubscribeCount")) {
builder.setSubscribeCount(j.getInt("SubscribeCount"));
}
if (j.has("TtlSec")) {
builder.setTtlSec(j.getInt("TtlSec"));
}
return builder.build();
}
public WifiNanManagerFacade(FacadeManager manager) {
super(manager);
mService = manager.getService();
mNanFacadeThread = new HandlerThread("nanFacadeThread");
mNanFacadeThread.start();
mMgr = (WifiNanManager) mService.getSystemService(Context.WIFI_NAN_SERVICE);
mMgr.connect(new NanEventListenerPostsEvents(mNanFacadeThread.getLooper()),
WifiNanEventListener.LISTEN_CONFIG_COMPLETED
| WifiNanEventListener.LISTEN_CONFIG_FAILED
| WifiNanEventListener.LISTEN_NAN_DOWN
| WifiNanEventListener.LISTEN_IDENTITY_CHANGED);
mConnMgr = (ConnectivityManager) mService.getSystemService(Context.CONNECTIVITY_SERVICE);
mEventFacade = manager.getReceiver(EventFacade.class);
}
@Override
public void shutdown() {
}
@Rpc(description = "Start NAN.")
public void wifiNanEnable(@RpcParameter(name = "nanConfig") JSONObject nanConfig)
throws RemoteException, JSONException {
mMgr.requestConfig(getConfigRequest(nanConfig));
}
@Rpc(description = "Stop NAN.")
public void wifiNanDisable() throws RemoteException, JSONException {
mMgr.disconnect();
}
@Rpc(description = "Publish.")
public void wifiNanPublish(@RpcParameter(name = "publishData") JSONObject publishData,
@RpcParameter(name = "publishSettings") JSONObject publishSettings,
@RpcParameter(name = "listenerId") Integer listenerId)
throws RemoteException, JSONException {
mSession = mMgr.publish(getPublishData(publishData), getPublishSettings(publishSettings),
new NanSessionListenerPostsEvents(mNanFacadeThread.getLooper(), listenerId),
WifiNanSessionListener.LISTEN_PUBLISH_FAIL
| WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED
| WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL
| WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED
| WifiNanSessionListener.LISTEN_MATCH
| WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS
| WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL
| WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED);
}
@Rpc(description = "Subscribe.")
public void wifiNanSubscribe(@RpcParameter(name = "subscribeData") JSONObject subscribeData,
@RpcParameter(name = "subscribeSettings") JSONObject subscribeSettings,
@RpcParameter(name = "listenerId") Integer listenerId)
throws RemoteException, JSONException {
mSession = mMgr.subscribe(getSubscribeData(subscribeData),
getSubscribeSettings(subscribeSettings),
new NanSessionListenerPostsEvents(mNanFacadeThread.getLooper(), listenerId),
WifiNanSessionListener.LISTEN_PUBLISH_FAIL
| WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED
| WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL
| WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED
| WifiNanSessionListener.LISTEN_MATCH
| WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS
| WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL
| WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED);
}
@Rpc(description = "Send peer-to-peer NAN message")
public void wifiNanSendMessage(
@RpcParameter(name = "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)
throws RemoteException {
mSession.sendMessage(peerId, message.getBytes(), message.length(), messageId);
}
private class NanEventListenerPostsEvents extends WifiNanEventListener {
public NanEventListenerPostsEvents(Looper looper) {
super(looper);
}
@Override
public void onConfigCompleted(ConfigRequest configRequest) {
Bundle mResults = new Bundle();
mResults.putParcelable("configRequest", configRequest);
mEventFacade.postEvent("WifiNanOnConfigCompleted", mResults);
}
@Override
public void onConfigFailed(ConfigRequest failedConfig, int reason) {
Bundle mResults = new Bundle();
mResults.putParcelable("failedConfig", failedConfig);
mResults.putInt("reason", reason);
mEventFacade.postEvent("WifiNanOnConfigFailed", mResults);
}
@Override
public void onNanDown(int reason) {
Bundle mResults = new Bundle();
mResults.putInt("reason", reason);
mEventFacade.postEvent("WifiNanOnNanDown", mResults);
}
@Override
public void onIdentityChanged() {
Bundle mResults = new Bundle();
mEventFacade.postEvent("WifiNanOnIdentityChanged", mResults);
}
}
private class NanSessionListenerPostsEvents extends WifiNanSessionListener {
private int mListenerId;
public NanSessionListenerPostsEvents(Looper looper, int listenerId) {
super(looper);
mListenerId = listenerId;
}
@Override
public void onPublishFail(int reason) {
Bundle mResults = new Bundle();
mResults.putInt("listenerId", mListenerId);
mResults.putInt("reason", reason);
mEventFacade.postEvent("WifiNanSessionOnPublishFail", mResults);
}
@Override
public void onPublishTerminated(int reason) {
Bundle mResults = new Bundle();
mResults.putInt("listenerId", mListenerId);
mResults.putInt("reason", reason);
mEventFacade.postEvent("WifiNanSessionOnPublishTerminated", mResults);
}
@Override
public void onSubscribeFail(int reason) {
Bundle mResults = new Bundle();
mResults.putInt("listenerId", mListenerId);
mResults.putInt("reason", reason);
mEventFacade.postEvent("WifiNanSessionOnSubscribeFail", mResults);
}
@Override
public void onSubscribeTerminated(int reason) {
Bundle mResults = new Bundle();
mResults.putInt("listenerId", mListenerId);
mResults.putInt("reason", reason);
mEventFacade.postEvent("WifiNanSessionOnSubscribeTerminated", mResults);
}
@Override
public void onMatch(int peerId, byte[] serviceSpecificInfo,
int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength) {
Bundle mResults = new Bundle();
mResults.putInt("listenerId", mListenerId);
mResults.putInt("peerId", peerId);
mResults.putInt("serviceSpecificInfoLength", serviceSpecificInfoLength);
mResults.putByteArray("serviceSpecificInfo", serviceSpecificInfo); // TODO: base64
mResults.putInt("matchFilterLength", matchFilterLength);
mResults.putByteArray("matchFilter", matchFilter); // TODO: base64
mEventFacade.postEvent("WifiNanSessionOnMatch", mResults);
}
@Override
public void onMessageSendSuccess(int messageId) {
Bundle mResults = new Bundle();
mResults.putInt("listenerId", mListenerId);
mResults.putInt("messageId", messageId);
mEventFacade.postEvent("WifiNanSessionOnMessageSendSuccess", mResults);
}
@Override
public void onMessageSendFail(int messageId, int reason) {
Bundle mResults = new Bundle();
mResults.putInt("listenerId", mListenerId);
mResults.putInt("messageId", messageId);
mResults.putInt("reason", reason);
mEventFacade.postEvent("WifiNanSessionOnMessageSendFail", mResults);
}
@Override
public void onMessageReceived(int peerId, byte[] message, int messageLength) {
Bundle mResults = new Bundle();
mResults.putInt("listenerId", mListenerId);
mResults.putInt("peerId", peerId);
mResults.putInt("messageLength", messageLength);
mResults.putByteArray("message", message); // TODO: base64
mResults.putString("messageAsString", new String(message, 0, messageLength));
mEventFacade.postEvent("WifiNanSessionOnMessageReceived", mResults);
}
}
}