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.android.server.wifi.nan; 18 19 import android.net.wifi.nan.IWifiNanSessionListener; 20 import android.net.wifi.nan.PublishData; 21 import android.net.wifi.nan.PublishSettings; 22 import android.net.wifi.nan.SubscribeData; 23 import android.net.wifi.nan.SubscribeSettings; 24 import android.net.wifi.nan.WifiNanSessionListener; 25 import android.os.RemoteException; 26 import android.util.Log; 27 import android.util.SparseArray; 28 29 import libcore.util.HexEncoding; 30 31 import java.io.FileDescriptor; 32 import java.io.PrintWriter; 33 34 public class WifiNanSessionState { 35 private static final String TAG = "WifiNanSessionState"; 36 private static final boolean DBG = false; 37 private static final boolean VDBG = false; // STOPSHIP if true 38 39 private final SparseArray<String> mMacByRequestorInstanceId = new SparseArray<>(); 40 41 private int mSessionId; 42 private IWifiNanSessionListener mListener; 43 private int mEvents; 44 45 private boolean mPubSubIdValid = false; 46 private int mPubSubId; 47 48 private static final int SESSION_TYPE_NOT_INIT = 0; 49 private static final int SESSION_TYPE_PUBLISH = 1; 50 private static final int SESSION_TYPE_SUBSCRIBE = 2; 51 private int mSessionType = SESSION_TYPE_NOT_INIT; 52 WifiNanSessionState(int sessionId, IWifiNanSessionListener listener, int events)53 public WifiNanSessionState(int sessionId, IWifiNanSessionListener listener, int events) { 54 mSessionId = sessionId; 55 mListener = listener; 56 mEvents = events; 57 } 58 destroy()59 public void destroy() { 60 stop(WifiNanStateManager.getInstance().createNextTransactionId()); 61 if (mPubSubIdValid) { 62 mMacByRequestorInstanceId.clear(); 63 mListener = null; 64 mPubSubIdValid = false; 65 } 66 } 67 getSessionId()68 public int getSessionId() { 69 return mSessionId; 70 } 71 isPubSubIdSession(int pubSubId)72 public boolean isPubSubIdSession(int pubSubId) { 73 return mPubSubIdValid && mPubSubId == pubSubId; 74 } 75 publish(short transactionId, PublishData data, PublishSettings settings)76 public void publish(short transactionId, PublishData data, PublishSettings settings) { 77 if (mSessionType == SESSION_TYPE_SUBSCRIBE) { 78 throw new IllegalStateException("A SUBSCRIBE session is being used for publish"); 79 } 80 mSessionType = SESSION_TYPE_PUBLISH; 81 82 WifiNanNative.getInstance().publish(transactionId, mPubSubIdValid ? mPubSubId : 0, data, 83 settings); 84 } 85 subscribe(short transactionId, SubscribeData data, SubscribeSettings settings)86 public void subscribe(short transactionId, SubscribeData data, SubscribeSettings settings) { 87 if (mSessionType == SESSION_TYPE_PUBLISH) { 88 throw new IllegalStateException("A PUBLISH session is being used for publish"); 89 } 90 mSessionType = SESSION_TYPE_SUBSCRIBE; 91 92 WifiNanNative.getInstance().subscribe(transactionId, mPubSubIdValid ? mPubSubId : 0, data, 93 settings); 94 } 95 sendMessage(short transactionId, int peerId, byte[] message, int messageLength, int messageId)96 public void sendMessage(short transactionId, int peerId, byte[] message, int messageLength, 97 int messageId) { 98 if (!mPubSubIdValid) { 99 Log.e(TAG, "sendMessage: attempting to send a message on a non-live session " 100 + "(no successful publish or subscribe"); 101 onMessageSendFail(messageId, WifiNanSessionListener.FAIL_REASON_NO_MATCH_SESSION); 102 return; 103 } 104 105 String peerMacStr = mMacByRequestorInstanceId.get(peerId); 106 if (peerMacStr == null) { 107 Log.e(TAG, "sendMessage: attempting to send a message to an address which didn't " 108 + "match/contact us"); 109 onMessageSendFail(messageId, WifiNanSessionListener.FAIL_REASON_NO_MATCH_SESSION); 110 return; 111 } 112 byte[] peerMac = HexEncoding.decode(peerMacStr.toCharArray(), false); 113 114 WifiNanNative.getInstance().sendMessage(transactionId, mPubSubId, peerId, peerMac, message, 115 messageLength); 116 } 117 stop(short transactionId)118 public void stop(short transactionId) { 119 if (!mPubSubIdValid || mSessionType == SESSION_TYPE_NOT_INIT) { 120 Log.e(TAG, "sendMessage: attempting to stop pub/sub on a non-live session (no " 121 + "successful publish or subscribe"); 122 return; 123 } 124 125 if (mSessionType == SESSION_TYPE_PUBLISH) { 126 WifiNanNative.getInstance().stopPublish(transactionId, mPubSubId); 127 } else if (mSessionType == SESSION_TYPE_SUBSCRIBE) { 128 WifiNanNative.getInstance().stopSubscribe(transactionId, mPubSubId); 129 } 130 } 131 onPublishSuccess(int publishId)132 public void onPublishSuccess(int publishId) { 133 mPubSubId = publishId; 134 mPubSubIdValid = true; 135 } 136 onPublishFail(int status)137 public void onPublishFail(int status) { 138 mPubSubIdValid = false; 139 try { 140 if (mListener != null && (mEvents & WifiNanSessionListener.LISTEN_PUBLISH_FAIL) != 0) { 141 mListener.onPublishFail(status); 142 } 143 } catch (RemoteException e) { 144 Log.w(TAG, "onPublishFail: RemoteException (FYI): " + e); 145 } 146 } 147 onPublishTerminated(int status)148 public void onPublishTerminated(int status) { 149 mPubSubIdValid = false; 150 try { 151 if (mListener != null 152 && (mEvents & WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED) != 0) { 153 mListener.onPublishTerminated(status); 154 } 155 } catch (RemoteException e) { 156 Log.w(TAG, "onPublishTerminated: RemoteException (FYI): " + e); 157 } 158 } 159 onSubscribeSuccess(int subscribeId)160 public void onSubscribeSuccess(int subscribeId) { 161 mPubSubId = subscribeId; 162 mPubSubIdValid = true; 163 } 164 onSubscribeFail(int status)165 public void onSubscribeFail(int status) { 166 mPubSubIdValid = false; 167 try { 168 if (mListener != null 169 && (mEvents & WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL) != 0) { 170 mListener.onSubscribeFail(status); 171 } 172 } catch (RemoteException e) { 173 Log.w(TAG, "onSubscribeFail: RemoteException (FYI): " + e); 174 } 175 } 176 onSubscribeTerminated(int status)177 public void onSubscribeTerminated(int status) { 178 mPubSubIdValid = false; 179 try { 180 if (mListener != null 181 && (mEvents & WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED) != 0) { 182 mListener.onSubscribeTerminated(status); 183 } 184 } catch (RemoteException e) { 185 Log.w(TAG, "onSubscribeTerminated: RemoteException (FYI): " + e); 186 } 187 } 188 onMessageSendSuccess(int messageId)189 public void onMessageSendSuccess(int messageId) { 190 try { 191 if (mListener != null 192 && (mEvents & WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS) != 0) { 193 mListener.onMessageSendSuccess(messageId); 194 } 195 } catch (RemoteException e) { 196 Log.w(TAG, "onMessageSendSuccess: RemoteException (FYI): " + e); 197 } 198 } 199 onMessageSendFail(int messageId, int status)200 public void onMessageSendFail(int messageId, int status) { 201 try { 202 if (mListener != null 203 && (mEvents & WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL) != 0) { 204 mListener.onMessageSendFail(messageId, status); 205 } 206 } catch (RemoteException e) { 207 Log.w(TAG, "onMessageSendFail: RemoteException (FYI): " + e); 208 } 209 } 210 onMatch(int requestorInstanceId, byte[] peerMac, byte[] serviceSpecificInfo, int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength)211 public void onMatch(int requestorInstanceId, byte[] peerMac, byte[] serviceSpecificInfo, 212 int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength) { 213 String prevMac = mMacByRequestorInstanceId.get(requestorInstanceId); 214 mMacByRequestorInstanceId.put(requestorInstanceId, new String(HexEncoding.encode(peerMac))); 215 216 if (DBG) Log.d(TAG, "onMatch: previous peer MAC replaced - " + prevMac); 217 218 try { 219 if (mListener != null && (mEvents & WifiNanSessionListener.LISTEN_MATCH) != 0) { 220 mListener.onMatch(requestorInstanceId, serviceSpecificInfo, 221 serviceSpecificInfoLength, matchFilter, matchFilterLength); 222 } 223 } catch (RemoteException e) { 224 Log.w(TAG, "onMatch: RemoteException (FYI): " + e); 225 } 226 } 227 onMessageReceived(int requestorInstanceId, byte[] peerMac, byte[] message, int messageLength)228 public void onMessageReceived(int requestorInstanceId, byte[] peerMac, byte[] message, 229 int messageLength) { 230 String prevMac = mMacByRequestorInstanceId.get(requestorInstanceId); 231 mMacByRequestorInstanceId.put(requestorInstanceId, new String(HexEncoding.encode(peerMac))); 232 233 if (DBG) { 234 Log.d(TAG, "onMessageReceived: previous peer MAC replaced - " + prevMac); 235 } 236 237 try { 238 if (mListener != null 239 && (mEvents & WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED) != 0) { 240 mListener.onMessageReceived(requestorInstanceId, message, messageLength); 241 } 242 } catch (RemoteException e) { 243 Log.w(TAG, "onMessageReceived: RemoteException (FYI): " + e); 244 } 245 } 246 dump(FileDescriptor fd, PrintWriter pw, String[] args)247 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 248 pw.println("NanSessionState:"); 249 pw.println(" mSessionId: " + mSessionId); 250 pw.println(" mSessionType: " + mSessionType); 251 pw.println(" mEvents: " + mEvents); 252 pw.println(" mPubSubId: " + (mPubSubIdValid ? Integer.toString(mPubSubId) : "not valid")); 253 pw.println(" mMacByRequestorInstanceId: [" + mMacByRequestorInstanceId + "]"); 254 } 255 } 256