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