• 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.annotation.Nullable;
20 import android.net.wifi.OuiKeyedData;
21 import android.net.wifi.aware.AwarePairingConfig;
22 import android.net.wifi.aware.IdentityChangedListener;
23 import android.net.wifi.aware.WifiAwareChannelInfo;
24 import android.net.wifi.rtt.RangingResult;
25 import android.util.Log;
26 import android.util.SparseArray;
27 import android.util.SparseIntArray;
28 
29 import com.android.modules.utils.BasicShellCommandHandler;
30 import com.android.server.wifi.hal.WifiNanIface;
31 import com.android.server.wifi.hal.WifiNanIface.NanClusterEventType;
32 import com.android.server.wifi.hal.WifiNanIface.NanStatusCode;
33 
34 import org.json.JSONArray;
35 import org.json.JSONException;
36 import org.json.JSONObject;
37 
38 import java.io.FileDescriptor;
39 import java.io.PrintWriter;
40 import java.util.ArrayList;
41 import java.util.List;
42 
43 /**
44  * Manages the callbacks from Wi-Fi Aware HAL.
45  */
46 public class WifiAwareNativeCallback implements WifiNanIface.Callback,
47         WifiAwareShellCommand.DelegatedShellCommand {
48     private static final String TAG = "WifiAwareNativeCallback";
49     private boolean mVerboseLoggingEnabled = false;
50 
51     private final WifiAwareStateManager mWifiAwareStateManager;
52 
WifiAwareNativeCallback(WifiAwareStateManager wifiAwareStateManager)53     public WifiAwareNativeCallback(WifiAwareStateManager wifiAwareStateManager) {
54         mWifiAwareStateManager = wifiAwareStateManager;
55     }
56 
57     /**
58      * Enable/Disable verbose logging.
59      *
60      */
enableVerboseLogging(boolean verboseEnabled)61     public void enableVerboseLogging(boolean verboseEnabled) {
62         mVerboseLoggingEnabled = verboseEnabled;
63     }
64 
65     /*
66      * Counts of callbacks from HAL. Retrievable through shell command.
67      */
68     private static final int CB_EV_CLUSTER = 0;
69     private static final int CB_EV_DISABLED = 1;
70     private static final int CB_EV_PUBLISH_TERMINATED = 2;
71     private static final int CB_EV_SUBSCRIBE_TERMINATED = 3;
72     private static final int CB_EV_MATCH = 4;
73     private static final int CB_EV_MATCH_EXPIRED = 5;
74     private static final int CB_EV_FOLLOWUP_RECEIVED = 6;
75     private static final int CB_EV_TRANSMIT_FOLLOWUP = 7;
76     private static final int CB_EV_DATA_PATH_REQUEST = 8;
77     private static final int CB_EV_DATA_PATH_CONFIRM = 9;
78     private static final int CB_EV_DATA_PATH_TERMINATED = 10;
79     private static final int CB_EV_DATA_PATH_SCHED_UPDATE = 11;
80 
81     private final SparseIntArray mCallbackCounter = new SparseIntArray();
82     private final SparseArray<List<WifiAwareChannelInfo>> mChannelInfoPerNdp = new SparseArray<>();
83 
incrementCbCount(int callbackId)84     private void incrementCbCount(int callbackId) {
85         mCallbackCounter.put(callbackId, mCallbackCounter.get(callbackId) + 1);
86     }
87 
88     /**
89      * Interpreter of adb shell command 'adb shell cmd wifiaware native_cb ...'.
90      *
91      * @return -1 if parameter not recognized or invalid value, 0 otherwise.
92      */
93     @Override
onCommand(BasicShellCommandHandler parentShell)94     public int onCommand(BasicShellCommandHandler parentShell) {
95         final PrintWriter pwe = parentShell.getErrPrintWriter();
96         final PrintWriter pwo = parentShell.getOutPrintWriter();
97 
98         String subCmd = parentShell.getNextArgRequired();
99         switch (subCmd) {
100             case "get_cb_count": {
101                 String option = parentShell.getNextOption();
102                 boolean reset = false;
103                 if (option != null) {
104                     if ("--reset".equals(option)) {
105                         reset = true;
106                     } else {
107                         pwe.println("Unknown option to 'get_cb_count'");
108                         return -1;
109                     }
110                 }
111 
112                 JSONObject j = new JSONObject();
113                 try {
114                     for (int i = 0; i < mCallbackCounter.size(); ++i) {
115                         j.put(Integer.toString(mCallbackCounter.keyAt(i)),
116                                 mCallbackCounter.valueAt(i));
117                     }
118                 } catch (JSONException e) {
119                     Log.e(TAG, "onCommand: get_cb_count e=" + e);
120                 }
121                 pwo.println(j.toString());
122                 if (reset) {
123                     mCallbackCounter.clear();
124                 }
125                 return 0;
126             }
127             case  "get_channel_info": {
128                 String option = parentShell.getNextOption();
129                 if (option != null) {
130                     pwe.println("Unknown option to 'get_channel_info'");
131                     return -1;
132                 }
133                 String channelInfoString = convertChannelInfoToJsonString();
134                 pwo.println(channelInfoString);
135                 return 0;
136             }
137             default:
138                 pwe.println("Unknown 'wifiaware native_cb <cmd>'");
139         }
140 
141         return -1;
142     }
143 
144     @Override
onReset()145     public void onReset() {
146         // NOP (onReset is intended for configuration reset - not data reset)
147     }
148 
149     @Override
onHelp(String command, BasicShellCommandHandler parentShell)150     public void onHelp(String command, BasicShellCommandHandler parentShell) {
151         final PrintWriter pw = parentShell.getOutPrintWriter();
152 
153         pw.println("  " + command);
154         pw.println("    get_cb_count [--reset]: gets the number of callbacks (and optionally reset "
155                 + "count)");
156         pw.println("    get_channel_info: prints out existing NDP channel info as a JSON String");
157     }
158 
159     @Override
notifyCapabilitiesResponse(short id, Capabilities capabilities)160     public void notifyCapabilitiesResponse(short id, Capabilities capabilities) {
161         mWifiAwareStateManager.onCapabilitiesUpdateResponse(id, capabilities);
162     }
163 
164     @Override
notifyRangingResults(ArrayList<RangingResult> rangingResults, byte sessionId)165     public void notifyRangingResults(ArrayList<RangingResult> rangingResults, byte sessionId) {
166         mWifiAwareStateManager.onRangingResults(rangingResults, sessionId);
167     }
168 
169     @Override
notifyEnableResponse(short id, int status)170     public void notifyEnableResponse(short id, int status) {
171         if (status == NanStatusCode.SUCCESS
172                 || status == NanStatusCode.ALREADY_ENABLED) {
173             mWifiAwareStateManager.onConfigSuccessResponse(id);
174         } else {
175             mWifiAwareStateManager.onConfigFailedResponse(id, status);
176         }
177     }
178 
179     @Override
notifyConfigResponse(short id, int status)180     public void notifyConfigResponse(short id, int status) {
181         if (status == NanStatusCode.SUCCESS) {
182             mWifiAwareStateManager.onConfigSuccessResponse(id);
183         } else {
184             mWifiAwareStateManager.onConfigFailedResponse(id, status);
185         }
186     }
187 
188     @Override
notifyDisableResponse(short id, int status)189     public void notifyDisableResponse(short id, int status) {
190         mWifiAwareStateManager.onDisableResponse(id, status);
191     }
192 
193     @Override
notifyStartPublishResponse(short id, int status, byte publishId)194     public void notifyStartPublishResponse(short id, int status, byte publishId) {
195         if (status == NanStatusCode.SUCCESS) {
196             mWifiAwareStateManager.onSessionConfigSuccessResponse(id, true, publishId);
197         } else {
198             mWifiAwareStateManager.onSessionConfigFailResponse(id, true, status);
199         }
200     }
201 
202     @Override
notifyStartSubscribeResponse(short id, int status, byte subscribeId)203     public void notifyStartSubscribeResponse(short id, int status, byte subscribeId) {
204         if (status == NanStatusCode.SUCCESS) {
205             mWifiAwareStateManager.onSessionConfigSuccessResponse(id, false, subscribeId);
206         } else {
207             mWifiAwareStateManager.onSessionConfigFailResponse(id, false, status);
208         }
209     }
210 
211     @Override
notifyTransmitFollowupResponse(short id, int status)212     public void notifyTransmitFollowupResponse(short id, int status) {
213         if (status == NanStatusCode.SUCCESS) {
214             mWifiAwareStateManager.onMessageSendQueuedSuccessResponse(id);
215         } else {
216             mWifiAwareStateManager.onMessageSendQueuedFailResponse(id, status);
217         }
218     }
219 
220     @Override
notifyCreateDataInterfaceResponse(short id, int status)221     public void notifyCreateDataInterfaceResponse(short id, int status) {
222         mWifiAwareStateManager.onCreateDataPathInterfaceResponse(id,
223                 status == NanStatusCode.SUCCESS, status);
224     }
225 
226     @Override
notifyDeleteDataInterfaceResponse(short id, int status)227     public void notifyDeleteDataInterfaceResponse(short id, int status) {
228         mWifiAwareStateManager.onDeleteDataPathInterfaceResponse(id,
229                 status == NanStatusCode.SUCCESS, status);
230     }
231 
232     @Override
notifyInitiateDataPathResponse(short id, int status, int ndpInstanceId)233     public void notifyInitiateDataPathResponse(short id, int status,
234             int ndpInstanceId) {
235         if (status == NanStatusCode.SUCCESS) {
236             mWifiAwareStateManager.onInitiateDataPathResponseSuccess(id, ndpInstanceId);
237         } else {
238             mWifiAwareStateManager.onInitiateDataPathResponseFail(id, status);
239         }
240     }
241 
242     @Override
notifyRespondToDataPathIndicationResponse(short id, int status)243     public void notifyRespondToDataPathIndicationResponse(short id, int status) {
244         mWifiAwareStateManager.onRespondToDataPathSetupRequestResponse(id,
245                 status == NanStatusCode.SUCCESS, status);
246     }
247 
248     @Override
notifyTerminateDataPathResponse(short id, int status)249     public void notifyTerminateDataPathResponse(short id, int status) {
250         mWifiAwareStateManager.onEndDataPathResponse(id, status == NanStatusCode.SUCCESS,
251                 status);
252     }
253 
254     @Override
notifyInitiatePairingResponse(short id, int status, int pairingInstanceId)255     public void notifyInitiatePairingResponse(short id, int status,
256             int pairingInstanceId) {
257         if (status == NanStatusCode.SUCCESS) {
258             mWifiAwareStateManager.onInitiatePairingResponseSuccess(id, pairingInstanceId);
259         } else {
260             mWifiAwareStateManager.onInitiatePairingResponseFail(id, status);
261         }
262 
263     }
264 
265     @Override
notifyRespondToPairingIndicationResponse(short id, int status)266     public void notifyRespondToPairingIndicationResponse(short id, int status) {
267         if (status == NanStatusCode.SUCCESS) {
268             mWifiAwareStateManager.onRespondToPairingIndicationResponseSuccess(id);
269         } else {
270             mWifiAwareStateManager.onRespondToPairingIndicationResponseFail(id, status);
271         }
272     }
273 
274     @Override
notifyInitiateBootstrappingResponse(short id, int status, int bootstrappingInstanceId)275     public void notifyInitiateBootstrappingResponse(short id, int status,
276             int bootstrappingInstanceId) {
277         if (status == NanStatusCode.SUCCESS) {
278             mWifiAwareStateManager.onInitiateBootStrappingResponseSuccess(id,
279                     bootstrappingInstanceId);
280         } else {
281             mWifiAwareStateManager.onInitiateBootStrappingResponseFail(id, status);
282         }
283     }
284 
285     @Override
notifyRespondToBootstrappingIndicationResponse(short id, int status)286     public void notifyRespondToBootstrappingIndicationResponse(short id, int status) {
287         if (status == NanStatusCode.SUCCESS) {
288             mWifiAwareStateManager.onRespondToBootstrappingIndicationResponseSuccess(id);
289         } else {
290             mWifiAwareStateManager.onRespondToBootstrappingIndicationResponseFail(id, status);
291         }
292     }
293 
294     @Override
notifySuspendResponse(short id, int status)295     public void notifySuspendResponse(short id, int status) {
296         mWifiAwareStateManager.onSuspendResponse(id, status);
297     }
298 
299     @Override
notifyResumeResponse(short id, int status)300     public void notifyResumeResponse(short id, int status) {
301         mWifiAwareStateManager.onResumeResponse(id, status);
302     }
303 
304     @Override
notifyTerminatePairingResponse(short id, int status)305     public void notifyTerminatePairingResponse(short id, int status) {
306         mWifiAwareStateManager.onEndPairingResponse(id, status == NanStatusCode.SUCCESS,
307                 status);
308     }
309 
310     @Override
eventClusterEvent(int eventType, byte[] addr)311     public void eventClusterEvent(int eventType, byte[] addr) {
312         incrementCbCount(CB_EV_CLUSTER);
313         if (eventType == NanClusterEventType.DISCOVERY_MAC_ADDRESS_CHANGED) {
314             mWifiAwareStateManager.onInterfaceAddressChangeNotification(addr);
315         } else if (eventType == NanClusterEventType.STARTED_CLUSTER) {
316             mWifiAwareStateManager.onClusterChangeNotification(
317                     IdentityChangedListener.CLUSTER_CHANGE_EVENT_STARTED, addr);
318         } else if (eventType == NanClusterEventType.JOINED_CLUSTER) {
319             mWifiAwareStateManager.onClusterChangeNotification(
320                     IdentityChangedListener.CLUSTER_CHANGE_EVENT_JOINED, addr);
321         } else {
322             Log.e(TAG, "eventClusterEvent: invalid eventType=" + eventType);
323         }
324     }
325 
326     @Override
eventDisabled(int status)327     public void eventDisabled(int status) {
328         incrementCbCount(CB_EV_DISABLED);
329         mWifiAwareStateManager.onAwareDownNotification(status);
330     }
331 
332     @Override
eventPublishTerminated(byte sessionId, int status)333     public void eventPublishTerminated(byte sessionId, int status) {
334         incrementCbCount(CB_EV_PUBLISH_TERMINATED);
335         mWifiAwareStateManager.onSessionTerminatedNotification(sessionId, status, true);
336     }
337 
338     @Override
eventSubscribeTerminated(byte sessionId, int status)339     public void eventSubscribeTerminated(byte sessionId, int status) {
340         incrementCbCount(CB_EV_SUBSCRIBE_TERMINATED);
341         mWifiAwareStateManager.onSessionTerminatedNotification(sessionId, status, false);
342     }
343 
344     @Override
eventMatch(byte discoverySessionId, int peerId, byte[] addr, byte[] serviceSpecificInfo, byte[] matchFilter, int rangingIndicationType, int rangingMeasurementInMm, byte[] scid, int peerCipherType, byte[] nonce, byte[] tag, AwarePairingConfig pairingConfig, @Nullable List<OuiKeyedData> vendorData)345     public void eventMatch(byte discoverySessionId, int peerId, byte[] addr,
346             byte[] serviceSpecificInfo, byte[] matchFilter, int rangingIndicationType,
347             int rangingMeasurementInMm, byte[] scid, int peerCipherType, byte[] nonce, byte[] tag,
348             AwarePairingConfig pairingConfig, @Nullable List<OuiKeyedData> vendorData) {
349         incrementCbCount(CB_EV_MATCH);
350         mWifiAwareStateManager.onMatchNotification(discoverySessionId, peerId,
351                 addr, serviceSpecificInfo, matchFilter, rangingIndicationType,
352                 rangingMeasurementInMm, scid, peerCipherType, nonce, tag, pairingConfig,
353                 vendorData);
354     }
355 
356     @Override
eventMatchExpired(byte discoverySessionId, int peerId)357     public void eventMatchExpired(byte discoverySessionId, int peerId) {
358         incrementCbCount(CB_EV_MATCH_EXPIRED);
359         mWifiAwareStateManager.onMatchExpiredNotification(discoverySessionId, peerId);
360     }
361 
362     @Override
eventFollowupReceived(byte discoverySessionId, int peerId, byte[] addr, byte[] serviceSpecificInfo)363     public void eventFollowupReceived(byte discoverySessionId, int peerId, byte[] addr,
364             byte[] serviceSpecificInfo) {
365         incrementCbCount(CB_EV_FOLLOWUP_RECEIVED);
366         mWifiAwareStateManager.onMessageReceivedNotification(discoverySessionId, peerId,
367                 addr, serviceSpecificInfo);
368     }
369 
370     @Override
eventTransmitFollowup(short id, int status)371     public void eventTransmitFollowup(short id, int status) {
372         incrementCbCount(CB_EV_TRANSMIT_FOLLOWUP);
373         if (status == NanStatusCode.SUCCESS) {
374             mWifiAwareStateManager.onMessageSendSuccessNotification(id);
375         } else {
376             mWifiAwareStateManager.onMessageSendFailNotification(id, status);
377         }
378     }
379 
380     @Override
eventDataPathRequest(byte discoverySessionId, byte[] peerDiscMacAddr, int ndpInstanceId, byte[] appInfo)381     public void eventDataPathRequest(byte discoverySessionId, byte[] peerDiscMacAddr,
382             int ndpInstanceId, byte[] appInfo) {
383         incrementCbCount(CB_EV_DATA_PATH_REQUEST);
384         mWifiAwareStateManager.onDataPathRequestNotification(discoverySessionId,
385                 peerDiscMacAddr, ndpInstanceId, appInfo);
386     }
387 
388     @Override
eventDataPathConfirm(int status, int ndpInstanceId, boolean dataPathSetupSuccess, byte[] peerNdiMacAddr, byte[] appInfo, List<WifiAwareChannelInfo> channelInfos)389     public void eventDataPathConfirm(int status, int ndpInstanceId, boolean dataPathSetupSuccess,
390             byte[] peerNdiMacAddr, byte[] appInfo,
391             List<WifiAwareChannelInfo> channelInfos) {
392         incrementCbCount(CB_EV_DATA_PATH_CONFIRM);
393         if (channelInfos != null) {
394             mChannelInfoPerNdp.put(ndpInstanceId, channelInfos);
395         }
396         mWifiAwareStateManager.onDataPathConfirmNotification(ndpInstanceId,
397                 peerNdiMacAddr, dataPathSetupSuccess, status, appInfo, channelInfos);
398     }
399 
400     @Override
eventDataPathScheduleUpdate(byte[] peerDiscoveryAddress, ArrayList<Integer> ndpInstanceIds, List<WifiAwareChannelInfo> channelInfo)401     public void eventDataPathScheduleUpdate(byte[] peerDiscoveryAddress,
402             ArrayList<Integer> ndpInstanceIds, List<WifiAwareChannelInfo> channelInfo) {
403         incrementCbCount(CB_EV_DATA_PATH_SCHED_UPDATE);
404         for (int ndpInstanceId : ndpInstanceIds) {
405             mChannelInfoPerNdp.put(ndpInstanceId, channelInfo);
406         }
407         mWifiAwareStateManager.onDataPathScheduleUpdateNotification(peerDiscoveryAddress,
408                 ndpInstanceIds, channelInfo);
409     }
410 
411     @Override
eventDataPathTerminated(int ndpInstanceId)412     public void eventDataPathTerminated(int ndpInstanceId) {
413         incrementCbCount(CB_EV_DATA_PATH_TERMINATED);
414         mChannelInfoPerNdp.remove(ndpInstanceId);
415         mWifiAwareStateManager.onDataPathEndNotification(ndpInstanceId);
416     }
417 
418     @Override
eventPairingRequest(int discoverySessionId, int peerId, byte[] peerDiscMacAddr, int ndpInstanceId, int requestType, boolean enableCache, byte[] nonce, byte[] tag)419     public void eventPairingRequest(int discoverySessionId, int peerId, byte[] peerDiscMacAddr,
420             int ndpInstanceId, int requestType, boolean enableCache, byte[] nonce, byte[] tag) {
421         mWifiAwareStateManager.onPairingRequestNotification(discoverySessionId, peerId,
422                 peerDiscMacAddr, ndpInstanceId, requestType, enableCache, nonce, tag);
423     }
424 
425     @Override
eventPairingConfirm(int pairingId, boolean accept, int reason, int requestType, boolean enableCache, PairingConfigManager.PairingSecurityAssociationInfo npksa)426     public void eventPairingConfirm(int pairingId, boolean accept, int reason, int requestType,
427             boolean enableCache,
428             PairingConfigManager.PairingSecurityAssociationInfo npksa) {
429         mWifiAwareStateManager.onPairingConfirmNotification(pairingId, accept, reason, requestType,
430                 enableCache, npksa);
431     }
432 
433     @Override
eventBootstrappingRequest(int discoverySessionId, int peerId, byte[] peerDiscMacAddr, int bootstrappingInstanceId, int method)434     public void eventBootstrappingRequest(int discoverySessionId, int peerId,
435             byte[] peerDiscMacAddr, int bootstrappingInstanceId, int method) {
436         mWifiAwareStateManager.onBootstrappingRequestNotification(discoverySessionId, peerId,
437                 peerDiscMacAddr, bootstrappingInstanceId, method);
438     }
439 
440     @Override
eventBootstrappingConfirm(int bootstrappingId, int responseCode, int reason, int comebackDelay, byte[] cookie)441     public void eventBootstrappingConfirm(int bootstrappingId, int responseCode, int reason,
442             int comebackDelay, byte[] cookie) {
443         mWifiAwareStateManager.onBootstrappingConfirmNotification(bootstrappingId, responseCode,
444                 reason, comebackDelay, cookie);
445     }
446 
447     @Override
eventSuspensionModeChanged(boolean isSuspended)448     public void eventSuspensionModeChanged(boolean isSuspended) {
449         mWifiAwareStateManager.onSuspensionModeChangedNotification(isSuspended);
450     }
451 
452     /**
453      * Reset the channel info when Aware is down.
454      */
resetChannelInfo()455     /* package */ void resetChannelInfo() {
456         mChannelInfoPerNdp.clear();
457     }
458 
459     /**
460      * Dump the internal state of the class.
461      */
dump(FileDescriptor fd, PrintWriter pw, String[] args)462     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
463         pw.println("WifiAwareNativeCallback:");
464         pw.println("  mCallbackCounter: " + mCallbackCounter);
465         pw.println("  mChannelInfoPerNdp: " + mChannelInfoPerNdp);
466     }
467 
468 
469     // utilities
470 
471     /**
472      * Transfer the channel Info dict into a Json String which can be decoded by Json reader.
473      * The Format is: "{ndpInstanceId: [{"channelFreq": channelFreq,
474      * "channelBandwidth": channelBandwidth, "numSpatialStreams": numSpatialStreams}]}"
475      * @return Json String.
476      */
convertChannelInfoToJsonString()477     private String convertChannelInfoToJsonString() {
478         JSONObject channelInfoJson = new JSONObject();
479         try {
480             for (int i = 0; i < mChannelInfoPerNdp.size(); i++) {
481                 JSONArray infoJsonArray = new JSONArray();
482                 for (WifiAwareChannelInfo info : mChannelInfoPerNdp.valueAt(i)) {
483                     JSONObject j = new JSONObject();
484                     j.put("channelFreq", info.getChannelFrequencyMhz());
485                     j.put("channelBandwidth", info.getChannelBandwidth());
486                     j.put("numSpatialStreams", info.getSpatialStreamCount());
487                     infoJsonArray.put(j);
488                 }
489                 channelInfoJson.put(Integer.toString(mChannelInfoPerNdp.keyAt(i)), infoJsonArray);
490             }
491         } catch (JSONException e) {
492             Log.e(TAG, "onCommand: get_channel_info e=" + e);
493         }
494         return channelInfoJson.toString();
495     }
496 }
497