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