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