• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.aware;
18 
19 import android.hardware.wifi.V1_0.NanClusterEventInd;
20 import android.hardware.wifi.V1_0.NanClusterEventType;
21 import android.hardware.wifi.V1_0.NanDataPathConfirmInd;
22 import android.hardware.wifi.V1_0.NanDataPathRequestInd;
23 import android.hardware.wifi.V1_0.NanFollowupReceivedInd;
24 import android.hardware.wifi.V1_0.NanMatchInd;
25 import android.hardware.wifi.V1_0.NanStatusType;
26 import android.hardware.wifi.V1_0.WifiNanStatus;
27 import android.hardware.wifi.V1_2.NanDataPathChannelInfo;
28 import android.hardware.wifi.V1_2.NanDataPathScheduleUpdateInd;
29 import android.hardware.wifi.V1_5.IWifiNanIfaceEventCallback;
30 import android.net.MacAddress;
31 import android.net.wifi.util.HexEncoding;
32 import android.os.RemoteException;
33 import android.util.Log;
34 import android.util.SparseArray;
35 import android.util.SparseIntArray;
36 
37 import com.android.modules.utils.BasicShellCommandHandler;
38 
39 import org.json.JSONArray;
40 import org.json.JSONException;
41 import org.json.JSONObject;
42 
43 import java.io.FileDescriptor;
44 import java.io.PrintWriter;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 
48 /**
49  * Manages the callbacks from Wi-Fi Aware HIDL (HAL).
50  */
51 public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub implements
52         WifiAwareShellCommand.DelegatedShellCommand {
53     private static final String TAG = "WifiAwareNativeCallback";
54     private boolean mDbg = false;
55 
56     /* package */ boolean mIsHal12OrLater = false;
57     /* package */ boolean mIsHal15OrLater = false;
58 
59     private final WifiAwareStateManager mWifiAwareStateManager;
60 
WifiAwareNativeCallback(WifiAwareStateManager wifiAwareStateManager)61     public WifiAwareNativeCallback(WifiAwareStateManager wifiAwareStateManager) {
62         mWifiAwareStateManager = wifiAwareStateManager;
63     }
64 
65     /**
66      * Enable verbose logging.
67      */
enableVerboseLogging(boolean verbose)68     public void enableVerboseLogging(boolean verbose) {
69         mDbg = verbose;
70     }
71 
72 
73     /*
74      * Counts of callbacks from HAL. Retrievable through shell command.
75      */
76     private static final int CB_EV_CLUSTER = 0;
77     private static final int CB_EV_DISABLED = 1;
78     private static final int CB_EV_PUBLISH_TERMINATED = 2;
79     private static final int CB_EV_SUBSCRIBE_TERMINATED = 3;
80     private static final int CB_EV_MATCH = 4;
81     private static final int CB_EV_MATCH_EXPIRED = 5;
82     private static final int CB_EV_FOLLOWUP_RECEIVED = 6;
83     private static final int CB_EV_TRANSMIT_FOLLOWUP = 7;
84     private static final int CB_EV_DATA_PATH_REQUEST = 8;
85     private static final int CB_EV_DATA_PATH_CONFIRM = 9;
86     private static final int CB_EV_DATA_PATH_TERMINATED = 10;
87     private static final int CB_EV_DATA_PATH_SCHED_UPDATE = 11;
88 
89     private SparseIntArray mCallbackCounter = new SparseIntArray();
90     private SparseArray<ArrayList<NanDataPathChannelInfo>> mChannelInfoPerNdp = new SparseArray<>();
91 
incrementCbCount(int callbackId)92     private void incrementCbCount(int callbackId) {
93         mCallbackCounter.put(callbackId, mCallbackCounter.get(callbackId) + 1);
94     }
95 
96     /**
97      * Interpreter of adb shell command 'adb shell cmd wifiaware native_cb ...'.
98      *
99      * @return -1 if parameter not recognized or invalid value, 0 otherwise.
100      */
101     @Override
onCommand(BasicShellCommandHandler parentShell)102     public int onCommand(BasicShellCommandHandler parentShell) {
103         final PrintWriter pwe = parentShell.getErrPrintWriter();
104         final PrintWriter pwo = parentShell.getOutPrintWriter();
105 
106         String subCmd = parentShell.getNextArgRequired();
107         switch (subCmd) {
108             case "get_cb_count": {
109                 String option = parentShell.getNextOption();
110                 boolean reset = false;
111                 if (option != null) {
112                     if ("--reset".equals(option)) {
113                         reset = true;
114                     } else {
115                         pwe.println("Unknown option to 'get_cb_count'");
116                         return -1;
117                     }
118                 }
119 
120                 JSONObject j = new JSONObject();
121                 try {
122                     for (int i = 0; i < mCallbackCounter.size(); ++i) {
123                         j.put(Integer.toString(mCallbackCounter.keyAt(i)),
124                                 mCallbackCounter.valueAt(i));
125                     }
126                 } catch (JSONException e) {
127                     Log.e(TAG, "onCommand: get_cb_count e=" + e);
128                 }
129                 pwo.println(j.toString());
130                 if (reset) {
131                     mCallbackCounter.clear();
132                 }
133                 return 0;
134             }
135             case  "get_channel_info": {
136                 String option = parentShell.getNextOption();
137                 if (option != null) {
138                     pwe.println("Unknown option to 'get_channel_info'");
139                     return -1;
140                 }
141                 String channelInfoString = convertChannelInfoToJsonString();
142                 pwo.println(channelInfoString);
143                 return 0;
144             }
145             default:
146                 pwe.println("Unknown 'wifiaware native_cb <cmd>'");
147         }
148 
149         return -1;
150     }
151 
152     @Override
onReset()153     public void onReset() {
154         // NOP (onReset is intended for configuration reset - not data reset)
155     }
156 
157     @Override
onHelp(String command, BasicShellCommandHandler parentShell)158     public void onHelp(String command, BasicShellCommandHandler parentShell) {
159         final PrintWriter pw = parentShell.getOutPrintWriter();
160 
161         pw.println("  " + command);
162         pw.println("    get_cb_count [--reset]: gets the number of callbacks (and optionally reset "
163                 + "count)");
164         pw.println("    get_channel_info: prints out existing NDP channel info as a JSON String");
165     }
166 
167     @Override
notifyCapabilitiesResponse(short id, WifiNanStatus status, android.hardware.wifi.V1_0.NanCapabilities capabilities)168     public void notifyCapabilitiesResponse(short id, WifiNanStatus status,
169             android.hardware.wifi.V1_0.NanCapabilities capabilities) {
170         if (mDbg) {
171             Log.v(TAG, "notifyCapabilitiesResponse: id=" + id + ", status=" + statusString(status)
172                     + ", capabilities=" + capabilities);
173         }
174 
175         if (mIsHal15OrLater) {
176             Log.wtf(TAG, "notifyCapabilitiesResponse should not be called by a >=1.5 HAL!");
177         }
178 
179         if (status.status == NanStatusType.SUCCESS) {
180             Capabilities frameworkCapabilities = toFrameworkCapability10(capabilities);
181 
182             mWifiAwareStateManager.onCapabilitiesUpdateResponse(id, frameworkCapabilities);
183         } else {
184             Log.e(TAG, "notifyCapabilitiesResponse: error code=" + status.status + " ("
185                     + status.description + ")");
186         }
187     }
188 
189     @Override
notifyCapabilitiesResponse_1_5(short id, WifiNanStatus status, android.hardware.wifi.V1_5.NanCapabilities capabilities)190     public void notifyCapabilitiesResponse_1_5(short id, WifiNanStatus status,
191             android.hardware.wifi.V1_5.NanCapabilities capabilities) throws RemoteException {
192         if (mDbg) {
193             Log.v(TAG, "notifyCapabilitiesResponse_1_5: id=" + id + ", status="
194                     + statusString(status) + ", capabilities=" + capabilities);
195         }
196 
197         if (!mIsHal15OrLater) {
198             Log.wtf(TAG, "notifyCapabilitiesResponse_1_5 should not be called by a <1.5 HAL!");
199             return;
200         }
201 
202         if (status.status == NanStatusType.SUCCESS) {
203             Capabilities frameworkCapabilities = toFrameworkCapability10(capabilities.V1_0);
204             frameworkCapabilities.isInstantCommunicationModeSupported =
205                     capabilities.instantCommunicationModeSupportFlag;
206 
207             mWifiAwareStateManager.onCapabilitiesUpdateResponse(id, frameworkCapabilities);
208         } else {
209             Log.e(TAG, "notifyCapabilitiesResponse_1_5: error code=" + status.status + " ("
210                     + status.description + ")");
211         }
212 
213     }
214 
toFrameworkCapability10( android.hardware.wifi.V1_0.NanCapabilities capabilities)215     private Capabilities toFrameworkCapability10(
216             android.hardware.wifi.V1_0.NanCapabilities capabilities) {
217         Capabilities frameworkCapabilities = new Capabilities();
218         frameworkCapabilities.maxConcurrentAwareClusters = capabilities.maxConcurrentClusters;
219         frameworkCapabilities.maxPublishes = capabilities.maxPublishes;
220         frameworkCapabilities.maxSubscribes = capabilities.maxSubscribes;
221         frameworkCapabilities.maxServiceNameLen = capabilities.maxServiceNameLen;
222         frameworkCapabilities.maxMatchFilterLen = capabilities.maxMatchFilterLen;
223         frameworkCapabilities.maxTotalMatchFilterLen = capabilities.maxTotalMatchFilterLen;
224         frameworkCapabilities.maxServiceSpecificInfoLen =
225                 capabilities.maxServiceSpecificInfoLen;
226         frameworkCapabilities.maxExtendedServiceSpecificInfoLen =
227                 capabilities.maxExtendedServiceSpecificInfoLen;
228         frameworkCapabilities.maxNdiInterfaces = capabilities.maxNdiInterfaces;
229         frameworkCapabilities.maxNdpSessions = capabilities.maxNdpSessions;
230         frameworkCapabilities.maxAppInfoLen = capabilities.maxAppInfoLen;
231         frameworkCapabilities.maxQueuedTransmitMessages =
232                 capabilities.maxQueuedTransmitFollowupMsgs;
233         frameworkCapabilities.maxSubscribeInterfaceAddresses =
234                 capabilities.maxSubscribeInterfaceAddresses;
235         frameworkCapabilities.supportedCipherSuites = capabilities.supportedCipherSuites;
236         frameworkCapabilities.isInstantCommunicationModeSupported = false;
237         return frameworkCapabilities;
238     }
239 
240     @Override
notifyEnableResponse(short id, WifiNanStatus status)241     public void notifyEnableResponse(short id, WifiNanStatus status) {
242         if (mDbg) Log.v(TAG, "notifyEnableResponse: id=" + id + ", status=" + statusString(status));
243 
244         if (status.status == NanStatusType.ALREADY_ENABLED) {
245             Log.wtf(TAG, "notifyEnableResponse: id=" + id + ", already enabled!?");
246         }
247 
248         if (status.status == NanStatusType.SUCCESS
249                 || status.status == NanStatusType.ALREADY_ENABLED) {
250             mWifiAwareStateManager.onConfigSuccessResponse(id);
251         } else {
252             mWifiAwareStateManager.onConfigFailedResponse(id, status.status);
253         }
254     }
255 
256     @Override
notifyConfigResponse(short id, WifiNanStatus status)257     public void notifyConfigResponse(short id, WifiNanStatus status) {
258         if (mDbg) Log.v(TAG, "notifyConfigResponse: id=" + id + ", status=" + statusString(status));
259 
260         if (status.status == NanStatusType.SUCCESS) {
261             mWifiAwareStateManager.onConfigSuccessResponse(id);
262         } else {
263             mWifiAwareStateManager.onConfigFailedResponse(id, status.status);
264         }
265     }
266 
267     @Override
notifyDisableResponse(short id, WifiNanStatus status)268     public void notifyDisableResponse(short id, WifiNanStatus status) {
269         if (mDbg) {
270             Log.v(TAG, "notifyDisableResponse: id=" + id + ", status=" + statusString(status));
271         }
272 
273         if (status.status != NanStatusType.SUCCESS) {
274             Log.e(TAG, "notifyDisableResponse: failure - code=" + status.status + " ("
275                     + status.description + ")");
276         }
277         mWifiAwareStateManager.onDisableResponse(id, status.status);
278     }
279 
280     @Override
notifyStartPublishResponse(short id, WifiNanStatus status, byte publishId)281     public void notifyStartPublishResponse(short id, WifiNanStatus status, byte publishId) {
282         if (mDbg) {
283             Log.v(TAG, "notifyStartPublishResponse: id=" + id + ", status=" + statusString(status)
284                     + ", publishId=" + publishId);
285         }
286 
287         if (status.status == NanStatusType.SUCCESS) {
288             mWifiAwareStateManager.onSessionConfigSuccessResponse(id, true, publishId);
289         } else {
290             mWifiAwareStateManager.onSessionConfigFailResponse(id, true, status.status);
291         }
292     }
293 
294     @Override
notifyStopPublishResponse(short id, WifiNanStatus status)295     public void notifyStopPublishResponse(short id, WifiNanStatus status) {
296         if (mDbg) {
297             Log.v(TAG, "notifyStopPublishResponse: id=" + id + ", status=" + statusString(status));
298         }
299 
300         if (status.status == NanStatusType.SUCCESS) {
301             // NOP
302         } else {
303             Log.e(TAG, "notifyStopPublishResponse: failure - code=" + status.status + " ("
304                     + status.description + ")");
305         }
306     }
307 
308     @Override
notifyStartSubscribeResponse(short id, WifiNanStatus status, byte subscribeId)309     public void notifyStartSubscribeResponse(short id, WifiNanStatus status, byte subscribeId) {
310         if (mDbg) {
311             Log.v(TAG, "notifyStartSubscribeResponse: id=" + id + ", status=" + statusString(status)
312                     + ", subscribeId=" + subscribeId);
313         }
314 
315         if (status.status == NanStatusType.SUCCESS) {
316             mWifiAwareStateManager.onSessionConfigSuccessResponse(id, false, subscribeId);
317         } else {
318             mWifiAwareStateManager.onSessionConfigFailResponse(id, false, status.status);
319         }
320     }
321 
322     @Override
notifyStopSubscribeResponse(short id, WifiNanStatus status)323     public void notifyStopSubscribeResponse(short id, WifiNanStatus status) {
324         if (mDbg) {
325             Log.v(TAG, "notifyStopSubscribeResponse: id=" + id + ", status="
326                     + statusString(status));
327         }
328 
329         if (status.status == NanStatusType.SUCCESS) {
330             // NOP
331         } else {
332             Log.e(TAG, "notifyStopSubscribeResponse: failure - code=" + status.status + " ("
333                     + status.description + ")");
334         }
335     }
336 
337     @Override
notifyTransmitFollowupResponse(short id, WifiNanStatus status)338     public void notifyTransmitFollowupResponse(short id, WifiNanStatus status) {
339         if (mDbg) {
340             Log.v(TAG, "notifyTransmitFollowupResponse: id=" + id + ", status="
341                     + statusString(status));
342         }
343 
344         if (status.status == NanStatusType.SUCCESS) {
345             mWifiAwareStateManager.onMessageSendQueuedSuccessResponse(id);
346         } else {
347             mWifiAwareStateManager.onMessageSendQueuedFailResponse(id, status.status);
348         }
349     }
350 
351     @Override
notifyCreateDataInterfaceResponse(short id, WifiNanStatus status)352     public void notifyCreateDataInterfaceResponse(short id, WifiNanStatus status) {
353         if (mDbg) {
354             Log.v(TAG, "notifyCreateDataInterfaceResponse: id=" + id + ", status="
355                     + statusString(status));
356         }
357 
358         mWifiAwareStateManager.onCreateDataPathInterfaceResponse(id,
359                 status.status == NanStatusType.SUCCESS, status.status);
360     }
361 
362     @Override
notifyDeleteDataInterfaceResponse(short id, WifiNanStatus status)363     public void notifyDeleteDataInterfaceResponse(short id, WifiNanStatus status) {
364         if (mDbg) {
365             Log.v(TAG, "notifyDeleteDataInterfaceResponse: id=" + id + ", status="
366                     + statusString(status));
367         }
368 
369         mWifiAwareStateManager.onDeleteDataPathInterfaceResponse(id,
370                 status.status == NanStatusType.SUCCESS, status.status);
371     }
372 
373     @Override
notifyInitiateDataPathResponse(short id, WifiNanStatus status, int ndpInstanceId)374     public void notifyInitiateDataPathResponse(short id, WifiNanStatus status,
375             int ndpInstanceId) {
376         if (mDbg) {
377             Log.v(TAG, "notifyInitiateDataPathResponse: id=" + id + ", status="
378                     + statusString(status) + ", ndpInstanceId=" + ndpInstanceId);
379         }
380 
381         if (status.status == NanStatusType.SUCCESS) {
382             mWifiAwareStateManager.onInitiateDataPathResponseSuccess(id, ndpInstanceId);
383         } else {
384             mWifiAwareStateManager.onInitiateDataPathResponseFail(id, status.status);
385         }
386     }
387 
388     @Override
notifyRespondToDataPathIndicationResponse(short id, WifiNanStatus status)389     public void notifyRespondToDataPathIndicationResponse(short id, WifiNanStatus status) {
390         if (mDbg) {
391             Log.v(TAG, "notifyRespondToDataPathIndicationResponse: id=" + id
392                     + ", status=" + statusString(status));
393         }
394 
395         mWifiAwareStateManager.onRespondToDataPathSetupRequestResponse(id,
396                 status.status == NanStatusType.SUCCESS, status.status);
397     }
398 
399     @Override
notifyTerminateDataPathResponse(short id, WifiNanStatus status)400     public void notifyTerminateDataPathResponse(short id, WifiNanStatus status) {
401         if (mDbg) {
402             Log.v(TAG, "notifyTerminateDataPathResponse: id=" + id + ", status="
403                     + statusString(status));
404         }
405 
406         mWifiAwareStateManager.onEndDataPathResponse(id, status.status == NanStatusType.SUCCESS,
407                 status.status);
408     }
409 
410     @Override
eventClusterEvent(NanClusterEventInd event)411     public void eventClusterEvent(NanClusterEventInd event) {
412         if (mDbg) {
413             Log.v(TAG, "eventClusterEvent: eventType=" + event.eventType + ", addr="
414                     + String.valueOf(HexEncoding.encode(event.addr)));
415         }
416         incrementCbCount(CB_EV_CLUSTER);
417 
418         if (event.eventType == NanClusterEventType.DISCOVERY_MAC_ADDRESS_CHANGED) {
419             mWifiAwareStateManager.onInterfaceAddressChangeNotification(event.addr);
420         } else if (event.eventType == NanClusterEventType.STARTED_CLUSTER) {
421             mWifiAwareStateManager.onClusterChangeNotification(
422                     WifiAwareClientState.CLUSTER_CHANGE_EVENT_STARTED, event.addr);
423         } else if (event.eventType == NanClusterEventType.JOINED_CLUSTER) {
424             mWifiAwareStateManager.onClusterChangeNotification(
425                     WifiAwareClientState.CLUSTER_CHANGE_EVENT_JOINED, event.addr);
426         } else {
427             Log.e(TAG, "eventClusterEvent: invalid eventType=" + event.eventType);
428         }
429     }
430 
431     @Override
eventDisabled(WifiNanStatus status)432     public void eventDisabled(WifiNanStatus status) {
433         if (mDbg) Log.v(TAG, "eventDisabled: status=" + statusString(status));
434         incrementCbCount(CB_EV_DISABLED);
435 
436         mWifiAwareStateManager.onAwareDownNotification(status.status);
437     }
438 
439     @Override
eventPublishTerminated(byte sessionId, WifiNanStatus status)440     public void eventPublishTerminated(byte sessionId, WifiNanStatus status) {
441         if (mDbg) {
442             Log.v(TAG, "eventPublishTerminated: sessionId=" + sessionId + ", status="
443                     + statusString(status));
444         }
445         incrementCbCount(CB_EV_PUBLISH_TERMINATED);
446 
447         mWifiAwareStateManager.onSessionTerminatedNotification(sessionId, status.status, true);
448     }
449 
450     @Override
eventSubscribeTerminated(byte sessionId, WifiNanStatus status)451     public void eventSubscribeTerminated(byte sessionId, WifiNanStatus status) {
452         if (mDbg) {
453             Log.v(TAG, "eventSubscribeTerminated: sessionId=" + sessionId + ", status="
454                     + statusString(status));
455         }
456         incrementCbCount(CB_EV_SUBSCRIBE_TERMINATED);
457 
458         mWifiAwareStateManager.onSessionTerminatedNotification(sessionId, status.status, false);
459     }
460 
461     @Override
eventMatch(NanMatchInd event)462     public void eventMatch(NanMatchInd event) {
463         if (mDbg) {
464             Log.v(TAG, "eventMatch: discoverySessionId=" + event.discoverySessionId + ", peerId="
465                     + event.peerId + ", addr=" + String.valueOf(HexEncoding.encode(event.addr))
466                     + ", serviceSpecificInfo=" + Arrays.toString(
467                     convertArrayListToNativeByteArray(event.serviceSpecificInfo)) + ", ssi.size()="
468                     + (event.serviceSpecificInfo == null ? 0 : event.serviceSpecificInfo.size())
469                     + ", matchFilter=" + Arrays.toString(
470                     convertArrayListToNativeByteArray(event.matchFilter)) + ", mf.size()=" + (
471                     event.matchFilter == null ? 0 : event.matchFilter.size())
472                     + ", rangingIndicationType=" + event.rangingIndicationType
473                     + ", rangingMeasurementInCm=" + event.rangingMeasurementInCm);
474         }
475         incrementCbCount(CB_EV_MATCH);
476 
477         // TODO: b/69428593 get rid of conversion once HAL moves from CM to MM
478         mWifiAwareStateManager.onMatchNotification(event.discoverySessionId, event.peerId,
479                 event.addr, convertArrayListToNativeByteArray(event.serviceSpecificInfo),
480                 convertArrayListToNativeByteArray(event.matchFilter), event.rangingIndicationType,
481                 event.rangingMeasurementInCm * 10);
482     }
483 
484     @Override
eventMatchExpired(byte discoverySessionId, int peerId)485     public void eventMatchExpired(byte discoverySessionId, int peerId) {
486         if (mDbg) {
487             Log.v(TAG, "eventMatchExpired: discoverySessionId=" + discoverySessionId
488                     + ", peerId=" + peerId);
489         }
490         incrementCbCount(CB_EV_MATCH_EXPIRED);
491         mWifiAwareStateManager.onMatchExpiredNotification(discoverySessionId, peerId);
492     }
493 
494     @Override
eventFollowupReceived(NanFollowupReceivedInd event)495     public void eventFollowupReceived(NanFollowupReceivedInd event) {
496         if (mDbg) {
497             Log.v(TAG, "eventFollowupReceived: discoverySessionId=" + event.discoverySessionId
498                     + ", peerId=" + event.peerId + ", addr=" + String.valueOf(
499                     HexEncoding.encode(event.addr)) + ", serviceSpecificInfo=" + Arrays.toString(
500                     convertArrayListToNativeByteArray(event.serviceSpecificInfo)) + ", ssi.size()="
501                     + (event.serviceSpecificInfo == null ? 0 : event.serviceSpecificInfo.size()));
502         }
503         incrementCbCount(CB_EV_FOLLOWUP_RECEIVED);
504 
505         mWifiAwareStateManager.onMessageReceivedNotification(event.discoverySessionId, event.peerId,
506                 event.addr, convertArrayListToNativeByteArray(event.serviceSpecificInfo));
507     }
508 
509     @Override
eventTransmitFollowup(short id, WifiNanStatus status)510     public void eventTransmitFollowup(short id, WifiNanStatus status) {
511         if (mDbg) {
512             Log.v(TAG, "eventTransmitFollowup: id=" + id + ", status=" + statusString(status));
513         }
514         incrementCbCount(CB_EV_TRANSMIT_FOLLOWUP);
515 
516         if (status.status == NanStatusType.SUCCESS) {
517             mWifiAwareStateManager.onMessageSendSuccessNotification(id);
518         } else {
519             mWifiAwareStateManager.onMessageSendFailNotification(id, status.status);
520         }
521     }
522 
523     @Override
eventDataPathRequest(NanDataPathRequestInd event)524     public void eventDataPathRequest(NanDataPathRequestInd event) {
525         if (mDbg) {
526             Log.v(TAG, "eventDataPathRequest: discoverySessionId=" + event.discoverySessionId
527                     + ", peerDiscMacAddr=" + String.valueOf(
528                     HexEncoding.encode(event.peerDiscMacAddr)) + ", ndpInstanceId="
529                     + event.ndpInstanceId + ", appInfo.size()=" + event.appInfo.size());
530         }
531         incrementCbCount(CB_EV_DATA_PATH_REQUEST);
532 
533         mWifiAwareStateManager.onDataPathRequestNotification(event.discoverySessionId,
534                 event.peerDiscMacAddr, event.ndpInstanceId,
535                 convertArrayListToNativeByteArray(event.appInfo));
536     }
537 
538     @Override
eventDataPathConfirm(NanDataPathConfirmInd event)539     public void eventDataPathConfirm(NanDataPathConfirmInd event) {
540         if (mDbg) {
541             Log.v(TAG, "onDataPathConfirm: ndpInstanceId=" + event.ndpInstanceId
542                     + ", peerNdiMacAddr=" + String.valueOf(HexEncoding.encode(event.peerNdiMacAddr))
543                     + ", dataPathSetupSuccess=" + event.dataPathSetupSuccess + ", reason="
544                     + event.status.status + ", appInfo.size()=" + event.appInfo.size());
545         }
546         if (mIsHal12OrLater) {
547             Log.wtf(TAG, "eventDataPathConfirm should not be called by a >=1.2 HAL!");
548         }
549         incrementCbCount(CB_EV_DATA_PATH_CONFIRM);
550 
551         mWifiAwareStateManager.onDataPathConfirmNotification(event.ndpInstanceId,
552                 event.peerNdiMacAddr, event.dataPathSetupSuccess, event.status.status,
553                 convertArrayListToNativeByteArray(event.appInfo), null);
554     }
555 
556     @Override
eventDataPathConfirm_1_2(android.hardware.wifi.V1_2.NanDataPathConfirmInd event)557     public void eventDataPathConfirm_1_2(android.hardware.wifi.V1_2.NanDataPathConfirmInd event) {
558         if (mDbg) {
559             Log.v(TAG, "eventDataPathConfirm_1_2: ndpInstanceId=" + event.V1_0.ndpInstanceId
560                     + ", peerNdiMacAddr=" + String.valueOf(
561                     HexEncoding.encode(event.V1_0.peerNdiMacAddr)) + ", dataPathSetupSuccess="
562                     + event.V1_0.dataPathSetupSuccess + ", reason=" + event.V1_0.status.status
563                     + ", appInfo.size()=" + event.V1_0.appInfo.size()
564                     + ", channelInfo" + event.channelInfo);
565         }
566         if (!mIsHal12OrLater) {
567             Log.wtf(TAG, "eventDataPathConfirm_1_2 should not be called by a <1.2 HAL!");
568             return;
569         }
570         incrementCbCount(CB_EV_DATA_PATH_CONFIRM);
571         mChannelInfoPerNdp.put(event.V1_0.ndpInstanceId, event.channelInfo);
572 
573         mWifiAwareStateManager.onDataPathConfirmNotification(event.V1_0.ndpInstanceId,
574                 event.V1_0.peerNdiMacAddr, event.V1_0.dataPathSetupSuccess,
575                 event.V1_0.status.status, convertArrayListToNativeByteArray(event.V1_0.appInfo),
576                 event.channelInfo);
577     }
578 
579     @Override
eventDataPathScheduleUpdate(NanDataPathScheduleUpdateInd event)580     public void eventDataPathScheduleUpdate(NanDataPathScheduleUpdateInd event) {
581         if (mDbg) {
582             Log.v(TAG, "eventDataPathScheduleUpdate: peerMac="
583                     + MacAddress.fromBytes(event.peerDiscoveryAddress).toString()
584                     + ", ndpIds=" + event.ndpInstanceIds + ", channelInfo=" + event.channelInfo);
585         }
586         if (!mIsHal12OrLater) {
587             Log.wtf(TAG, "eventDataPathScheduleUpdate should not be called by a <1.2 HAL!");
588             return;
589         }
590         incrementCbCount(CB_EV_DATA_PATH_SCHED_UPDATE);
591         for (int ndpInstanceId : event.ndpInstanceIds) {
592             mChannelInfoPerNdp.put(ndpInstanceId, event.channelInfo);
593         }
594 
595         mWifiAwareStateManager.onDataPathScheduleUpdateNotification(event.peerDiscoveryAddress,
596                 event.ndpInstanceIds, event.channelInfo);
597     }
598 
599     @Override
eventDataPathTerminated(int ndpInstanceId)600     public void eventDataPathTerminated(int ndpInstanceId) {
601         if (mDbg) Log.v(TAG, "eventDataPathTerminated: ndpInstanceId=" + ndpInstanceId);
602         incrementCbCount(CB_EV_DATA_PATH_TERMINATED);
603         mChannelInfoPerNdp.remove(ndpInstanceId);
604 
605         mWifiAwareStateManager.onDataPathEndNotification(ndpInstanceId);
606     }
607 
608     /**
609      * Reset the channel info when Aware is down.
610      */
resetChannelInfo()611     /* package */ void resetChannelInfo() {
612         mChannelInfoPerNdp.clear();
613     }
614 
615     /**
616      * Dump the internal state of the class.
617      */
dump(FileDescriptor fd, PrintWriter pw, String[] args)618     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
619         pw.println("WifiAwareNativeCallback:");
620         pw.println("  mCallbackCounter: " + mCallbackCounter);
621         pw.println("  mChannelInfoPerNdp: " + mChannelInfoPerNdp);
622     }
623 
624 
625     // utilities
626 
627     /**
628      * Converts an ArrayList<Byte> to a byte[].
629      *
630      * @param from The input ArrayList<Byte></Byte> to convert from.
631      *
632      * @return A newly allocated byte[].
633      */
convertArrayListToNativeByteArray(ArrayList<Byte> from)634     private byte[] convertArrayListToNativeByteArray(ArrayList<Byte> from) {
635         if (from == null) {
636             return null;
637         }
638 
639         byte[] to = new byte[from.size()];
640         for (int i = 0; i < from.size(); ++i) {
641             to[i] = from.get(i);
642         }
643         return to;
644     }
645 
statusString(WifiNanStatus status)646     private static String statusString(WifiNanStatus status) {
647         if (status == null) {
648             return "status=null";
649         }
650         StringBuilder sb = new StringBuilder();
651         sb.append(status.status).append(" (").append(status.description).append(")");
652         return sb.toString();
653     }
654 
655     /**
656      * Transfer the channel Info dict into a Json String which can be decoded by Json reader.
657      * The Format is: "{ndpInstanceId: [{"channelFreq": channelFreq,
658      * "channelBandwidth": channelBandwidth, "numSpatialStreams": numSpatialStreams}]}"
659      * @return Json String.
660      */
convertChannelInfoToJsonString()661     private String convertChannelInfoToJsonString() {
662         JSONObject channelInfoJson = new JSONObject();
663         try {
664             for (int i = 0; i < mChannelInfoPerNdp.size(); i++) {
665                 JSONArray infoJsonArray = new JSONArray();
666                 for (NanDataPathChannelInfo info : mChannelInfoPerNdp.valueAt(i)) {
667                     JSONObject j = new JSONObject();
668                     j.put("channelFreq", info.channelFreq);
669                     j.put("channelBandwidth", info.channelBandwidth);
670                     j.put("numSpatialStreams", info.numSpatialStreams);
671                     infoJsonArray.put(j);
672                 }
673                 channelInfoJson.put(Integer.toString(mChannelInfoPerNdp.keyAt(i)), infoJsonArray);
674             }
675         } catch (JSONException e) {
676             Log.e(TAG, "onCommand: get_channel_info e=" + e);
677         }
678         return channelInfoJson.toString();
679     }
680 }
681