1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi.aware; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.hardware.wifi.V1_0.NanStatusType; 22 import android.net.wifi.RttManager; 23 import android.net.wifi.aware.Characteristics; 24 import android.net.wifi.aware.ConfigRequest; 25 import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; 26 import android.net.wifi.aware.IWifiAwareEventCallback; 27 import android.net.wifi.aware.PublishConfig; 28 import android.net.wifi.aware.SubscribeConfig; 29 import android.net.wifi.aware.WifiAwareManager; 30 import android.net.wifi.aware.WifiAwareNetworkSpecifier; 31 import android.os.Bundle; 32 import android.os.Looper; 33 import android.os.Message; 34 import android.os.RemoteException; 35 import android.os.SystemClock; 36 import android.os.UserHandle; 37 import android.util.ArrayMap; 38 import android.util.Log; 39 import android.util.Pair; 40 import android.util.SparseArray; 41 42 import com.android.internal.annotations.VisibleForTesting; 43 import com.android.internal.util.MessageUtils; 44 import com.android.internal.util.State; 45 import com.android.internal.util.StateMachine; 46 import com.android.internal.util.WakeupMessage; 47 48 import libcore.util.HexEncoding; 49 50 import java.io.FileDescriptor; 51 import java.io.PrintWriter; 52 import java.util.Arrays; 53 import java.util.Iterator; 54 import java.util.LinkedHashMap; 55 import java.util.Map; 56 57 /** 58 * Manages the state of the Wi-Fi Aware system service. 59 */ 60 public class WifiAwareStateManager { 61 private static final String TAG = "WifiAwareStateManager"; 62 private static final boolean DBG = false; 63 private static final boolean VDBG = false; // STOPSHIP if true 64 65 @VisibleForTesting 66 public static final String HAL_COMMAND_TIMEOUT_TAG = TAG + " HAL Command Timeout"; 67 68 @VisibleForTesting 69 public static final String HAL_SEND_MESSAGE_TIMEOUT_TAG = TAG + " HAL Send Message Timeout"; 70 71 @VisibleForTesting 72 public static final String HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG = 73 TAG + " HAL Data Path Confirm Timeout"; 74 75 /* 76 * State machine message types. There are sub-types for the messages (except for TIMEOUTs). 77 * Format: 78 * - Message.arg1: contains message sub-type 79 * - Message.arg2: contains transaction ID for RESPONSE & RESPONSE_TIMEOUT 80 */ 81 private static final int MESSAGE_TYPE_COMMAND = 1; 82 private static final int MESSAGE_TYPE_RESPONSE = 2; 83 private static final int MESSAGE_TYPE_NOTIFICATION = 3; 84 private static final int MESSAGE_TYPE_RESPONSE_TIMEOUT = 4; 85 private static final int MESSAGE_TYPE_SEND_MESSAGE_TIMEOUT = 5; 86 private static final int MESSAGE_TYPE_DATA_PATH_TIMEOUT = 6; 87 88 /* 89 * Message sub-types: 90 */ 91 private static final int COMMAND_TYPE_CONNECT = 100; 92 private static final int COMMAND_TYPE_DISCONNECT = 101; 93 private static final int COMMAND_TYPE_TERMINATE_SESSION = 102; 94 private static final int COMMAND_TYPE_PUBLISH = 103; 95 private static final int COMMAND_TYPE_UPDATE_PUBLISH = 104; 96 private static final int COMMAND_TYPE_SUBSCRIBE = 105; 97 private static final int COMMAND_TYPE_UPDATE_SUBSCRIBE = 106; 98 private static final int COMMAND_TYPE_ENQUEUE_SEND_MESSAGE = 107; 99 private static final int COMMAND_TYPE_ENABLE_USAGE = 108; 100 private static final int COMMAND_TYPE_DISABLE_USAGE = 109; 101 private static final int COMMAND_TYPE_START_RANGING = 110; 102 private static final int COMMAND_TYPE_GET_CAPABILITIES = 111; 103 private static final int COMMAND_TYPE_CREATE_ALL_DATA_PATH_INTERFACES = 112; 104 private static final int COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES = 113; 105 private static final int COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE = 114; 106 private static final int COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE = 115; 107 private static final int COMMAND_TYPE_INITIATE_DATA_PATH_SETUP = 116; 108 private static final int COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST = 117; 109 private static final int COMMAND_TYPE_END_DATA_PATH = 118; 110 private static final int COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE = 119; 111 112 private static final int RESPONSE_TYPE_ON_CONFIG_SUCCESS = 200; 113 private static final int RESPONSE_TYPE_ON_CONFIG_FAIL = 201; 114 private static final int RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS = 202; 115 private static final int RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL = 203; 116 private static final int RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS = 204; 117 private static final int RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL = 205; 118 private static final int RESPONSE_TYPE_ON_CAPABILITIES_UPDATED = 206; 119 private static final int RESPONSE_TYPE_ON_CREATE_INTERFACE = 207; 120 private static final int RESPONSE_TYPE_ON_DELETE_INTERFACE = 208; 121 private static final int RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS = 209; 122 private static final int RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL = 210; 123 private static final int RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST = 211; 124 private static final int RESPONSE_TYPE_ON_END_DATA_PATH = 212; 125 126 private static final int NOTIFICATION_TYPE_INTERFACE_CHANGE = 301; 127 private static final int NOTIFICATION_TYPE_CLUSTER_CHANGE = 302; 128 private static final int NOTIFICATION_TYPE_MATCH = 303; 129 private static final int NOTIFICATION_TYPE_SESSION_TERMINATED = 304; 130 private static final int NOTIFICATION_TYPE_MESSAGE_RECEIVED = 305; 131 private static final int NOTIFICATION_TYPE_AWARE_DOWN = 306; 132 private static final int NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS = 307; 133 private static final int NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL = 308; 134 private static final int NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST = 309; 135 private static final int NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM = 310; 136 private static final int NOTIFICATION_TYPE_ON_DATA_PATH_END = 311; 137 138 private static final SparseArray<String> sSmToString = MessageUtils.findMessageNames( 139 new Class[]{WifiAwareStateManager.class}, 140 new String[]{"MESSAGE_TYPE", "COMMAND_TYPE", "RESPONSE_TYPE", "NOTIFICATION_TYPE"}); 141 142 /* 143 * Keys used when passing (some) arguments to the Handler thread (too many 144 * arguments to pass in the short-cut Message members). 145 */ 146 private static final String MESSAGE_BUNDLE_KEY_SESSION_TYPE = "session_type"; 147 private static final String MESSAGE_BUNDLE_KEY_SESSION_ID = "session_id"; 148 private static final String MESSAGE_BUNDLE_KEY_CONFIG = "config"; 149 private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message"; 150 private static final String MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID = "message_peer_id"; 151 private static final String MESSAGE_BUNDLE_KEY_MESSAGE_ID = "message_id"; 152 private static final String MESSAGE_BUNDLE_KEY_SSI_DATA = "ssi_data"; 153 private static final String MESSAGE_BUNDLE_KEY_FILTER_DATA = "filter_data"; 154 private static final String MESSAGE_BUNDLE_KEY_MAC_ADDRESS = "mac_address"; 155 private static final String MESSAGE_BUNDLE_KEY_MESSAGE_DATA = "message_data"; 156 private static final String MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID = "req_instance_id"; 157 private static final String MESSAGE_BUNDLE_KEY_RANGING_ID = "ranging_id"; 158 private static final String MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME = "message_queue_time"; 159 private static final String MESSAGE_BUNDLE_KEY_RETRY_COUNT = "retry_count"; 160 private static final String MESSAGE_BUNDLE_KEY_SUCCESS_FLAG = "success_flag"; 161 private static final String MESSAGE_BUNDLE_KEY_STATUS_CODE = "status_code"; 162 private static final String MESSAGE_BUNDLE_KEY_INTERFACE_NAME = "interface_name"; 163 private static final String MESSAGE_BUNDLE_KEY_CHANNEL_REQ_TYPE = "channel_request_type"; 164 private static final String MESSAGE_BUNDLE_KEY_CHANNEL = "channel"; 165 private static final String MESSAGE_BUNDLE_KEY_PEER_ID = "peer_id"; 166 private static final String MESSAGE_BUNDLE_KEY_UID = "uid"; 167 private static final String MESSAGE_BUNDLE_KEY_PID = "pid"; 168 private static final String MESSAGE_BUNDLE_KEY_CALLING_PACKAGE = "calling_package"; 169 private static final String MESSAGE_BUNDLE_KEY_SENT_MESSAGE = "send_message"; 170 private static final String MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ = "message_arrival_seq"; 171 private static final String MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE = "notify_identity_chg"; 172 private static final String MESSAGE_BUNDLE_KEY_PMK = "pmk"; 173 private static final String MESSAGE_BUNDLE_KEY_PASSPHRASE = "passphrase"; 174 175 private WifiAwareNativeApi mWifiAwareNativeApi; 176 177 /* 178 * Asynchronous access with no lock 179 */ 180 private volatile boolean mUsageEnabled = false; 181 182 /* 183 * Synchronous access: state is only accessed through the state machine 184 * handler thread: no need to use a lock. 185 */ 186 private Context mContext; 187 private volatile Capabilities mCapabilities; 188 private volatile Characteristics mCharacteristics = null; 189 private WifiAwareStateMachine mSm; 190 private WifiAwareRttStateManager mRtt; 191 private WifiAwareDataPathStateManager mDataPathMgr; 192 193 private final SparseArray<WifiAwareClientState> mClients = new SparseArray<>(); 194 private ConfigRequest mCurrentAwareConfiguration = null; 195 private boolean mCurrentIdentityNotification = false; 196 197 private static final byte[] ALL_ZERO_MAC = new byte[] {0, 0, 0, 0, 0, 0}; 198 private byte[] mCurrentDiscoveryInterfaceMac = ALL_ZERO_MAC; 199 200 public WifiAwareStateManager() { 201 // empty 202 } 203 204 public void setNative(WifiAwareNativeApi wifiAwareNativeApi) { 205 mWifiAwareNativeApi = wifiAwareNativeApi; 206 } 207 208 /** 209 * Initialize the handler of the state manager with the specified thread 210 * looper. 211 * 212 * @param looper Thread looper on which to run the handler. 213 */ 214 public void start(Context context, Looper looper) { 215 Log.i(TAG, "start()"); 216 217 mContext = context; 218 mSm = new WifiAwareStateMachine(TAG, looper); 219 mSm.setDbg(DBG); 220 mSm.start(); 221 222 mRtt = new WifiAwareRttStateManager(); 223 mDataPathMgr = new WifiAwareDataPathStateManager(this); 224 mDataPathMgr.start(mContext, mSm.getHandler().getLooper()); 225 } 226 227 /** 228 * Initialize the late-initialization sub-services: depend on other services already existing. 229 */ 230 public void startLate() { 231 mRtt.start(mContext, mSm.getHandler().getLooper()); 232 } 233 234 /** 235 * Get the client state for the specified ID (or null if none exists). 236 */ 237 /* package */ WifiAwareClientState getClient(int clientId) { 238 return mClients.get(clientId); 239 } 240 241 /** 242 * Get the capabilities. 243 */ 244 public Capabilities getCapabilities() { 245 return mCapabilities; 246 } 247 248 /** 249 * Get the public characteristics derived from the capabilities. Use lazy initialization. 250 */ 251 public Characteristics getCharacteristics() { 252 if (mCharacteristics == null && mCapabilities != null) { 253 mCharacteristics = mCapabilities.toPublicCharacteristics(); 254 } 255 256 return mCharacteristics; 257 } 258 259 /* 260 * COMMANDS 261 */ 262 263 /** 264 * Place a request for a new client connection on the state machine queue. 265 */ 266 public void connect(int clientId, int uid, int pid, String callingPackage, 267 IWifiAwareEventCallback callback, ConfigRequest configRequest, 268 boolean notifyOnIdentityChanged) { 269 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 270 msg.arg1 = COMMAND_TYPE_CONNECT; 271 msg.arg2 = clientId; 272 msg.obj = callback; 273 msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, configRequest); 274 msg.getData().putInt(MESSAGE_BUNDLE_KEY_UID, uid); 275 msg.getData().putInt(MESSAGE_BUNDLE_KEY_PID, pid); 276 msg.getData().putString(MESSAGE_BUNDLE_KEY_CALLING_PACKAGE, callingPackage); 277 msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE, 278 notifyOnIdentityChanged); 279 mSm.sendMessage(msg); 280 } 281 282 /** 283 * Place a request to disconnect (destroy) an existing client on the state 284 * machine queue. 285 */ 286 public void disconnect(int clientId) { 287 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 288 msg.arg1 = COMMAND_TYPE_DISCONNECT; 289 msg.arg2 = clientId; 290 mSm.sendMessage(msg); 291 } 292 293 /** 294 * Place a request to stop a discovery session on the state machine queue. 295 */ 296 public void terminateSession(int clientId, int sessionId) { 297 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 298 msg.arg1 = COMMAND_TYPE_TERMINATE_SESSION; 299 msg.arg2 = clientId; 300 msg.obj = sessionId; 301 mSm.sendMessage(msg); 302 } 303 304 /** 305 * Place a request to start a new publish discovery session on the state 306 * machine queue. 307 */ 308 public void publish(int clientId, PublishConfig publishConfig, 309 IWifiAwareDiscoverySessionCallback callback) { 310 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 311 msg.arg1 = COMMAND_TYPE_PUBLISH; 312 msg.arg2 = clientId; 313 msg.obj = callback; 314 msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, publishConfig); 315 mSm.sendMessage(msg); 316 } 317 318 /** 319 * Place a request to modify an existing publish discovery session on the 320 * state machine queue. 321 */ 322 public void updatePublish(int clientId, int sessionId, PublishConfig publishConfig) { 323 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 324 msg.arg1 = COMMAND_TYPE_UPDATE_PUBLISH; 325 msg.arg2 = clientId; 326 msg.obj = publishConfig; 327 msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId); 328 mSm.sendMessage(msg); 329 } 330 331 /** 332 * Place a request to start a new subscribe discovery session on the state 333 * machine queue. 334 */ 335 public void subscribe(int clientId, SubscribeConfig subscribeConfig, 336 IWifiAwareDiscoverySessionCallback callback) { 337 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 338 msg.arg1 = COMMAND_TYPE_SUBSCRIBE; 339 msg.arg2 = clientId; 340 msg.obj = callback; 341 msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, subscribeConfig); 342 mSm.sendMessage(msg); 343 } 344 345 /** 346 * Place a request to modify an existing subscribe discovery session on the 347 * state machine queue. 348 */ 349 public void updateSubscribe(int clientId, int sessionId, SubscribeConfig subscribeConfig) { 350 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 351 msg.arg1 = COMMAND_TYPE_UPDATE_SUBSCRIBE; 352 msg.arg2 = clientId; 353 msg.obj = subscribeConfig; 354 msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId); 355 mSm.sendMessage(msg); 356 } 357 358 /** 359 * Place a request to send a message on a discovery session on the state 360 * machine queue. 361 */ 362 public void sendMessage(int clientId, int sessionId, int peerId, byte[] message, int messageId, 363 int retryCount) { 364 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 365 msg.arg1 = COMMAND_TYPE_ENQUEUE_SEND_MESSAGE; 366 msg.arg2 = clientId; 367 msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId); 368 msg.getData().putInt(MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID, peerId); 369 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, message); 370 msg.getData().putInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID, messageId); 371 msg.getData().putInt(MESSAGE_BUNDLE_KEY_RETRY_COUNT, retryCount); 372 mSm.sendMessage(msg); 373 } 374 375 /** 376 * Place a request to range a peer on the discovery session on the state machine queue. 377 */ 378 public void startRanging(int clientId, int sessionId, RttManager.RttParams[] params, 379 int rangingId) { 380 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 381 msg.arg1 = COMMAND_TYPE_START_RANGING; 382 msg.arg2 = clientId; 383 msg.obj = params; 384 msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId); 385 msg.getData().putInt(MESSAGE_BUNDLE_KEY_RANGING_ID, rangingId); 386 mSm.sendMessage(msg); 387 } 388 389 /** 390 * Enable usage of Aware. Doesn't actually turn on Aware (form clusters) - that 391 * only happens when a connection is created. 392 */ 393 public void enableUsage() { 394 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 395 msg.arg1 = COMMAND_TYPE_ENABLE_USAGE; 396 mSm.sendMessage(msg); 397 } 398 399 /** 400 * Disable usage of Aware. Terminates all existing clients with onAwareDown(). 401 */ 402 public void disableUsage() { 403 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 404 msg.arg1 = COMMAND_TYPE_DISABLE_USAGE; 405 mSm.sendMessage(msg); 406 } 407 408 /** 409 * Checks whether Aware usage is enabled (not necessarily that Aware is up right 410 * now) or disabled. 411 * 412 * @return A boolean indicating whether Aware usage is enabled (true) or 413 * disabled (false). 414 */ 415 public boolean isUsageEnabled() { 416 return mUsageEnabled; 417 } 418 419 /** 420 * Get the capabilities of the current Aware firmware. 421 */ 422 public void queryCapabilities() { 423 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 424 msg.arg1 = COMMAND_TYPE_GET_CAPABILITIES; 425 mSm.sendMessage(msg); 426 } 427 428 /** 429 * Create all Aware data path interfaces which are supported by the firmware capabilities. 430 */ 431 public void createAllDataPathInterfaces() { 432 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 433 msg.arg1 = COMMAND_TYPE_CREATE_ALL_DATA_PATH_INTERFACES; 434 mSm.sendMessage(msg); 435 } 436 437 /** 438 * delete all Aware data path interfaces. 439 */ 440 public void deleteAllDataPathInterfaces() { 441 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 442 msg.arg1 = COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES; 443 mSm.sendMessage(msg); 444 } 445 446 /** 447 * Create the specified data-path interface. Doesn't actually creates a data-path. 448 */ 449 public void createDataPathInterface(String interfaceName) { 450 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 451 msg.arg1 = COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE; 452 msg.obj = interfaceName; 453 mSm.sendMessage(msg); 454 } 455 456 /** 457 * Deletes the specified data-path interface. 458 */ 459 public void deleteDataPathInterface(String interfaceName) { 460 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 461 msg.arg1 = COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE; 462 msg.obj = interfaceName; 463 mSm.sendMessage(msg); 464 } 465 466 /** 467 * Command to initiate a data-path (executed by the initiator). 468 */ 469 public void initiateDataPathSetup(WifiAwareNetworkSpecifier networkSpecifier, int peerId, 470 int channelRequestType, int channel, byte[] peer, String interfaceName, byte[] pmk, 471 String passphrase) { 472 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 473 msg.arg1 = COMMAND_TYPE_INITIATE_DATA_PATH_SETUP; 474 msg.obj = networkSpecifier; 475 msg.getData().putInt(MESSAGE_BUNDLE_KEY_PEER_ID, peerId); 476 msg.getData().putInt(MESSAGE_BUNDLE_KEY_CHANNEL_REQ_TYPE, channelRequestType); 477 msg.getData().putInt(MESSAGE_BUNDLE_KEY_CHANNEL, channel); 478 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peer); 479 msg.getData().putString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME, interfaceName); 480 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_PMK, pmk); 481 msg.getData().putString(MESSAGE_BUNDLE_KEY_PASSPHRASE, passphrase); 482 mSm.sendMessage(msg); 483 } 484 485 /** 486 * Command to respond to the data-path request (executed by the responder). 487 */ 488 public void respondToDataPathRequest(boolean accept, int ndpId, String interfaceName, 489 byte[] pmk, String passphrase) { 490 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 491 msg.arg1 = COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST; 492 msg.arg2 = ndpId; 493 msg.obj = accept; 494 msg.getData().putString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME, interfaceName); 495 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_PMK, pmk); 496 msg.getData().putString(MESSAGE_BUNDLE_KEY_PASSPHRASE, passphrase); 497 mSm.sendMessage(msg); 498 } 499 500 /** 501 * Command to terminate the specified data-path. 502 */ 503 public void endDataPath(int ndpId) { 504 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 505 msg.arg1 = COMMAND_TYPE_END_DATA_PATH; 506 msg.arg2 = ndpId; 507 mSm.sendMessage(msg); 508 } 509 510 /** 511 * Aware follow-on messages (L2 messages) are queued by the firmware for transmission 512 * on-the-air. The firmware has limited queue depth. The host queues all messages and doles 513 * them out to the firmware when possible. This command removes the next messages for 514 * transmission from the host queue and attempts to send it through the firmware. The queues 515 * are inspected when the command is executed - not when the command is placed on the handler 516 * (i.e. not evaluated here). 517 */ 518 private void transmitNextMessage() { 519 Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); 520 msg.arg1 = COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE; 521 mSm.sendMessage(msg); 522 } 523 524 /* 525 * RESPONSES 526 */ 527 528 /** 529 * Place a callback request on the state machine queue: configuration 530 * request completed (successfully). 531 */ 532 public void onConfigSuccessResponse(short transactionId) { 533 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 534 msg.arg1 = RESPONSE_TYPE_ON_CONFIG_SUCCESS; 535 msg.arg2 = transactionId; 536 mSm.sendMessage(msg); 537 } 538 539 /** 540 * Place a callback request on the state machine queue: configuration 541 * request failed. 542 */ 543 public void onConfigFailedResponse(short transactionId, int reason) { 544 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 545 msg.arg1 = RESPONSE_TYPE_ON_CONFIG_FAIL; 546 msg.arg2 = transactionId; 547 msg.obj = reason; 548 mSm.sendMessage(msg); 549 } 550 551 /** 552 * Place a callback request on the state machine queue: session 553 * configuration (new or update) request succeeded. 554 */ 555 public void onSessionConfigSuccessResponse(short transactionId, boolean isPublish, 556 int pubSubId) { 557 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 558 msg.arg1 = RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS; 559 msg.arg2 = transactionId; 560 msg.obj = pubSubId; 561 msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE, isPublish); 562 mSm.sendMessage(msg); 563 } 564 565 /** 566 * Place a callback request on the state machine queue: session 567 * configuration (new or update) request failed. 568 */ 569 public void onSessionConfigFailResponse(short transactionId, boolean isPublish, int reason) { 570 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 571 msg.arg1 = RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL; 572 msg.arg2 = transactionId; 573 msg.obj = reason; 574 msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE, isPublish); 575 mSm.sendMessage(msg); 576 } 577 578 /** 579 * Place a callback request on the state machine queue: message has been queued successfully. 580 */ 581 public void onMessageSendQueuedSuccessResponse(short transactionId) { 582 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 583 msg.arg1 = RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS; 584 msg.arg2 = transactionId; 585 mSm.sendMessage(msg); 586 } 587 588 /** 589 * Place a callback request on the state machine queue: attempt to queue the message failed. 590 */ 591 public void onMessageSendQueuedFailResponse(short transactionId, int reason) { 592 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 593 msg.arg1 = RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL; 594 msg.arg2 = transactionId; 595 msg.obj = reason; 596 mSm.sendMessage(msg); 597 } 598 599 /** 600 * Place a callback request on the state machine queue: update vendor 601 * capabilities of the Aware stack. 602 */ 603 public void onCapabilitiesUpdateResponse(short transactionId, 604 Capabilities capabilities) { 605 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 606 msg.arg1 = RESPONSE_TYPE_ON_CAPABILITIES_UPDATED; 607 msg.arg2 = transactionId; 608 msg.obj = capabilities; 609 mSm.sendMessage(msg); 610 } 611 612 /** 613 * Places a callback request on the state machine queue: data-path interface creation command 614 * completed. 615 */ 616 public void onCreateDataPathInterfaceResponse(short transactionId, boolean success, 617 int reasonOnFailure) { 618 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 619 msg.arg1 = RESPONSE_TYPE_ON_CREATE_INTERFACE; 620 msg.arg2 = transactionId; 621 msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success); 622 msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure); 623 mSm.sendMessage(msg); 624 } 625 626 /** 627 * Places a callback request on the state machine queue: data-path interface deletion command 628 * completed. 629 */ 630 public void onDeleteDataPathInterfaceResponse(short transactionId, boolean success, 631 int reasonOnFailure) { 632 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 633 msg.arg1 = RESPONSE_TYPE_ON_DELETE_INTERFACE; 634 msg.arg2 = transactionId; 635 msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success); 636 msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure); 637 mSm.sendMessage(msg); 638 } 639 640 /** 641 * Response from firmware to initiateDataPathSetup(...). Indicates that command has started 642 * succesfully (not completed!). 643 */ 644 public void onInitiateDataPathResponseSuccess(short transactionId, int ndpId) { 645 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 646 msg.arg1 = RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS; 647 msg.arg2 = transactionId; 648 msg.obj = ndpId; 649 mSm.sendMessage(msg); 650 } 651 652 /** 653 * Response from firmware to initiateDataPathSetup(...). 654 * Indicates that command has failed. 655 */ 656 public void onInitiateDataPathResponseFail(short transactionId, int reason) { 657 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 658 msg.arg1 = RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL; 659 msg.arg2 = transactionId; 660 msg.obj = reason; 661 mSm.sendMessage(msg); 662 } 663 664 /** 665 * Response from firmware to 666 * {@link #respondToDataPathRequest(boolean, int, String, byte[], String)}. 667 */ 668 public void onRespondToDataPathSetupRequestResponse(short transactionId, boolean success, 669 int reasonOnFailure) { 670 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 671 msg.arg1 = RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST; 672 msg.arg2 = transactionId; 673 msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success); 674 msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure); 675 mSm.sendMessage(msg); 676 } 677 678 /** 679 * Response from firmware to {@link #endDataPath(int)}. 680 */ 681 public void onEndDataPathResponse(short transactionId, boolean success, int reasonOnFailure) { 682 Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE); 683 msg.arg1 = RESPONSE_TYPE_ON_END_DATA_PATH; 684 msg.arg2 = transactionId; 685 msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success); 686 msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure); 687 mSm.sendMessage(msg); 688 } 689 690 /* 691 * NOTIFICATIONS 692 */ 693 694 /** 695 * Place a callback request on the state machine queue: the discovery 696 * interface has changed. 697 */ 698 public void onInterfaceAddressChangeNotification(byte[] mac) { 699 Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); 700 msg.arg1 = NOTIFICATION_TYPE_INTERFACE_CHANGE; 701 msg.obj = mac; 702 mSm.sendMessage(msg); 703 } 704 705 /** 706 * Place a callback request on the state machine queue: the cluster 707 * membership has changed (e.g. due to starting a new cluster or joining 708 * another cluster). 709 */ 710 public void onClusterChangeNotification(int flag, byte[] clusterId) { 711 Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); 712 msg.arg1 = NOTIFICATION_TYPE_CLUSTER_CHANGE; 713 msg.arg2 = flag; 714 msg.obj = clusterId; 715 mSm.sendMessage(msg); 716 } 717 718 /** 719 * Place a callback request on the state machine queue: a discovery match 720 * has occurred - e.g. our subscription discovered someone else publishing a 721 * matching service (to the one we were looking for). 722 */ 723 public void onMatchNotification(int pubSubId, int requestorInstanceId, byte[] peerMac, 724 byte[] serviceSpecificInfo, byte[] matchFilter) { 725 Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); 726 msg.arg1 = NOTIFICATION_TYPE_MATCH; 727 msg.arg2 = pubSubId; 728 msg.getData().putInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID, requestorInstanceId); 729 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peerMac); 730 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_SSI_DATA, serviceSpecificInfo); 731 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_FILTER_DATA, matchFilter); 732 mSm.sendMessage(msg); 733 } 734 735 /** 736 * Place a callback request on the state machine queue: a session (publish 737 * or subscribe) has terminated (per plan or due to an error). 738 */ 739 public void onSessionTerminatedNotification(int pubSubId, int reason, boolean isPublish) { 740 Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); 741 msg.arg1 = NOTIFICATION_TYPE_SESSION_TERMINATED; 742 msg.arg2 = pubSubId; 743 msg.obj = reason; 744 msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE, isPublish); 745 mSm.sendMessage(msg); 746 } 747 748 /** 749 * Place a callback request on the state machine queue: a message has been 750 * received as part of a discovery session. 751 */ 752 public void onMessageReceivedNotification(int pubSubId, int requestorInstanceId, byte[] peerMac, 753 byte[] message) { 754 Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); 755 msg.arg1 = NOTIFICATION_TYPE_MESSAGE_RECEIVED; 756 msg.arg2 = pubSubId; 757 msg.obj = requestorInstanceId; 758 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peerMac); 759 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA, message); 760 mSm.sendMessage(msg); 761 } 762 763 /** 764 * Place a callback request on the state machine queue: Aware is going down. 765 */ 766 public void onAwareDownNotification(int reason) { 767 Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); 768 msg.arg1 = NOTIFICATION_TYPE_AWARE_DOWN; 769 msg.arg2 = reason; 770 mSm.sendMessage(msg); 771 } 772 773 /** 774 * Notification that a message has been sent successfully (i.e. an ACK has been received). 775 */ 776 public void onMessageSendSuccessNotification(short transactionId) { 777 Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); 778 msg.arg1 = NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS; 779 msg.arg2 = transactionId; 780 mSm.sendMessage(msg); 781 } 782 783 /** 784 * Notification that a message transmission has failed due to the indicated reason - e.g. no ACK 785 * was received. 786 */ 787 public void onMessageSendFailNotification(short transactionId, int reason) { 788 Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); 789 msg.arg1 = NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL; 790 msg.arg2 = transactionId; 791 msg.obj = reason; 792 mSm.sendMessage(msg); 793 } 794 795 /** 796 * Place a callback request on the state machine queue: data-path request (from peer) received. 797 */ 798 public void onDataPathRequestNotification(int pubSubId, byte[] mac, int ndpId) { 799 Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); 800 msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST; 801 msg.arg2 = pubSubId; 802 msg.obj = ndpId; 803 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, mac); 804 mSm.sendMessage(msg); 805 } 806 807 /** 808 * Place a callback request on the state machine queue: data-path confirmation received - i.e. 809 * data-path is now up. 810 */ 811 public void onDataPathConfirmNotification(int ndpId, byte[] mac, boolean accept, int reason, 812 byte[] message) { 813 Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); 814 msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM; 815 msg.arg2 = ndpId; 816 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, mac); 817 msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, accept); 818 msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reason); 819 msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA, message); 820 mSm.sendMessage(msg); 821 } 822 823 /** 824 * Place a callback request on the state machine queue: the specified data-path has been 825 * terminated. 826 */ 827 public void onDataPathEndNotification(int ndpId) { 828 Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION); 829 msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_END; 830 msg.arg2 = ndpId; 831 mSm.sendMessage(msg); 832 } 833 834 /** 835 * State machine. 836 */ 837 @VisibleForTesting 838 class WifiAwareStateMachine extends StateMachine { 839 private static final int TRANSACTION_ID_IGNORE = 0; 840 841 private DefaultState mDefaultState = new DefaultState(); 842 private WaitState mWaitState = new WaitState(); 843 private WaitForResponseState mWaitForResponseState = new WaitForResponseState(); 844 845 private short mNextTransactionId = 1; 846 public int mNextSessionId = 1; 847 848 private Message mCurrentCommand; 849 private short mCurrentTransactionId = TRANSACTION_ID_IGNORE; 850 851 private static final long AWARE_SEND_MESSAGE_TIMEOUT = 10_000; 852 private int mSendArrivalSequenceCounter = 0; 853 private boolean mSendQueueBlocked = false; 854 private final SparseArray<Message> mHostQueuedSendMessages = new SparseArray<>(); 855 private final Map<Short, Message> mFwQueuedSendMessages = new LinkedHashMap<>(); 856 private WakeupMessage mSendMessageTimeoutMessage = new WakeupMessage(mContext, getHandler(), 857 HAL_SEND_MESSAGE_TIMEOUT_TAG, MESSAGE_TYPE_SEND_MESSAGE_TIMEOUT); 858 859 private static final long AWARE_WAIT_FOR_DP_CONFIRM_TIMEOUT = 5_000; 860 private final Map<WifiAwareNetworkSpecifier, WakeupMessage> 861 mDataPathConfirmTimeoutMessages = new ArrayMap<>(); 862 863 WifiAwareStateMachine(String name, Looper looper) { 864 super(name, looper); 865 866 addState(mDefaultState); 867 /* --> */ addState(mWaitState, mDefaultState); 868 /* --> */ addState(mWaitForResponseState, mDefaultState); 869 870 setInitialState(mWaitState); 871 } 872 873 public void onAwareDownCleanupSendQueueState() { 874 mSendQueueBlocked = false; 875 mHostQueuedSendMessages.clear(); 876 mFwQueuedSendMessages.clear(); 877 } 878 879 private class DefaultState extends State { 880 @Override 881 public boolean processMessage(Message msg) { 882 if (VDBG) { 883 Log.v(TAG, getName() + msg.toString()); 884 } 885 886 switch (msg.what) { 887 case MESSAGE_TYPE_NOTIFICATION: 888 processNotification(msg); 889 return HANDLED; 890 case MESSAGE_TYPE_SEND_MESSAGE_TIMEOUT: 891 processSendMessageTimeout(); 892 return HANDLED; 893 case MESSAGE_TYPE_DATA_PATH_TIMEOUT: { 894 WifiAwareNetworkSpecifier networkSpecifier = 895 (WifiAwareNetworkSpecifier) msg.obj; 896 897 if (VDBG) { 898 Log.v(TAG, "MESSAGE_TYPE_DATA_PATH_TIMEOUT: networkSpecifier=" 899 + networkSpecifier); 900 } 901 902 mDataPathMgr.handleDataPathTimeout(networkSpecifier); 903 mDataPathConfirmTimeoutMessages.remove(networkSpecifier); 904 return HANDLED; 905 } 906 default: 907 /* fall-through */ 908 } 909 910 Log.wtf(TAG, 911 "DefaultState: should not get non-NOTIFICATION in this state: msg=" + msg); 912 return NOT_HANDLED; 913 } 914 } 915 916 private class WaitState extends State { 917 @Override 918 public boolean processMessage(Message msg) { 919 if (VDBG) { 920 Log.v(TAG, getName() + msg.toString()); 921 } 922 923 switch (msg.what) { 924 case MESSAGE_TYPE_COMMAND: 925 if (processCommand(msg)) { 926 transitionTo(mWaitForResponseState); 927 } 928 return HANDLED; 929 case MESSAGE_TYPE_RESPONSE: 930 /* fall-through */ 931 case MESSAGE_TYPE_RESPONSE_TIMEOUT: 932 /* 933 * remnants/delayed/out-of-sync messages - but let 934 * WaitForResponseState deal with them (identified as 935 * out-of-date by transaction ID). 936 */ 937 deferMessage(msg); 938 return HANDLED; 939 default: 940 /* fall-through */ 941 } 942 943 return NOT_HANDLED; 944 } 945 } 946 947 private class WaitForResponseState extends State { 948 private static final long AWARE_COMMAND_TIMEOUT = 5_000; 949 private WakeupMessage mTimeoutMessage; 950 951 @Override 952 public void enter() { 953 mTimeoutMessage = new WakeupMessage(mContext, getHandler(), HAL_COMMAND_TIMEOUT_TAG, 954 MESSAGE_TYPE_RESPONSE_TIMEOUT, mCurrentCommand.arg1, mCurrentTransactionId); 955 mTimeoutMessage.schedule(SystemClock.elapsedRealtime() + AWARE_COMMAND_TIMEOUT); 956 } 957 958 @Override 959 public void exit() { 960 mTimeoutMessage.cancel(); 961 } 962 963 @Override 964 public boolean processMessage(Message msg) { 965 if (VDBG) { 966 Log.v(TAG, getName() + msg.toString()); 967 } 968 969 switch (msg.what) { 970 case MESSAGE_TYPE_COMMAND: 971 /* 972 * don't want COMMANDs in this state - defer until back 973 * in WaitState 974 */ 975 deferMessage(msg); 976 return HANDLED; 977 case MESSAGE_TYPE_RESPONSE: 978 if (msg.arg2 == mCurrentTransactionId) { 979 processResponse(msg); 980 transitionTo(mWaitState); 981 } else { 982 Log.w(TAG, 983 "WaitForResponseState: processMessage: non-matching " 984 + "transaction ID on RESPONSE (a very late " 985 + "response) -- msg=" + msg); 986 /* no transition */ 987 } 988 return HANDLED; 989 case MESSAGE_TYPE_RESPONSE_TIMEOUT: 990 if (msg.arg2 == mCurrentTransactionId) { 991 processTimeout(msg); 992 transitionTo(mWaitState); 993 } else { 994 Log.w(TAG, "WaitForResponseState: processMessage: non-matching " 995 + "transaction ID on RESPONSE_TIMEOUT (either a non-cancelled " 996 + "timeout or a race condition with cancel) -- msg=" + msg); 997 /* no transition */ 998 } 999 return HANDLED; 1000 default: 1001 /* fall-through */ 1002 } 1003 1004 return NOT_HANDLED; 1005 } 1006 } 1007 1008 private void processNotification(Message msg) { 1009 if (VDBG) { 1010 Log.v(TAG, "processNotification: msg=" + msg); 1011 } 1012 1013 switch (msg.arg1) { 1014 case NOTIFICATION_TYPE_INTERFACE_CHANGE: { 1015 byte[] mac = (byte[]) msg.obj; 1016 1017 onInterfaceAddressChangeLocal(mac); 1018 break; 1019 } 1020 case NOTIFICATION_TYPE_CLUSTER_CHANGE: { 1021 int flag = msg.arg2; 1022 byte[] clusterId = (byte[]) msg.obj; 1023 1024 onClusterChangeLocal(flag, clusterId); 1025 break; 1026 } 1027 case NOTIFICATION_TYPE_MATCH: { 1028 int pubSubId = msg.arg2; 1029 int requestorInstanceId = msg.getData() 1030 .getInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID); 1031 byte[] peerMac = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS); 1032 byte[] serviceSpecificInfo = msg.getData() 1033 .getByteArray(MESSAGE_BUNDLE_KEY_SSI_DATA); 1034 byte[] matchFilter = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_FILTER_DATA); 1035 1036 onMatchLocal(pubSubId, requestorInstanceId, peerMac, serviceSpecificInfo, 1037 matchFilter); 1038 break; 1039 } 1040 case NOTIFICATION_TYPE_SESSION_TERMINATED: { 1041 int pubSubId = msg.arg2; 1042 int reason = (Integer) msg.obj; 1043 boolean isPublish = msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE); 1044 1045 onSessionTerminatedLocal(pubSubId, isPublish, reason); 1046 break; 1047 } 1048 case NOTIFICATION_TYPE_MESSAGE_RECEIVED: { 1049 int pubSubId = msg.arg2; 1050 int requestorInstanceId = (Integer) msg.obj; 1051 byte[] peerMac = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS); 1052 byte[] message = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA); 1053 1054 onMessageReceivedLocal(pubSubId, requestorInstanceId, peerMac, message); 1055 break; 1056 } 1057 case NOTIFICATION_TYPE_AWARE_DOWN: { 1058 int reason = msg.arg2; 1059 1060 /* 1061 * TODO: b/28615938. Use reason code to determine whether or not need clean-up 1062 * local state (only needed if AWARE_DOWN is due to internal firmware reason, 1063 * e.g. concurrency, rather than due to a requested shutdown). 1064 */ 1065 1066 onAwareDownLocal(); 1067 1068 break; 1069 } 1070 case NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS: { 1071 short transactionId = (short) msg.arg2; 1072 Message queuedSendCommand = mFwQueuedSendMessages.get(transactionId); 1073 if (VDBG) { 1074 Log.v(TAG, "NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS: queuedSendCommand=" 1075 + queuedSendCommand); 1076 } 1077 if (queuedSendCommand == null) { 1078 Log.w(TAG, 1079 "processNotification: NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS:" 1080 + " transactionId=" + transactionId 1081 + " - no such queued send command (timed-out?)"); 1082 } else { 1083 mFwQueuedSendMessages.remove(transactionId); 1084 updateSendMessageTimeout(); 1085 onMessageSendSuccessLocal(queuedSendCommand); 1086 } 1087 mSendQueueBlocked = false; 1088 transmitNextMessage(); 1089 1090 break; 1091 } 1092 case NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL: { 1093 short transactionId = (short) msg.arg2; 1094 int reason = (Integer) msg.obj; 1095 Message sentMessage = mFwQueuedSendMessages.get(transactionId); 1096 if (VDBG) { 1097 Log.v(TAG, "NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL: sentMessage=" 1098 + sentMessage); 1099 } 1100 if (sentMessage == null) { 1101 Log.w(TAG, 1102 "processNotification: NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL:" 1103 + " transactionId=" + transactionId 1104 + " - no such queued send command (timed-out?)"); 1105 } else { 1106 mFwQueuedSendMessages.remove(transactionId); 1107 updateSendMessageTimeout(); 1108 1109 int retryCount = sentMessage.getData() 1110 .getInt(MESSAGE_BUNDLE_KEY_RETRY_COUNT); 1111 if (retryCount > 0 && reason == NanStatusType.NO_OTA_ACK) { 1112 if (DBG) { 1113 Log.d(TAG, 1114 "NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL: transactionId=" 1115 + transactionId + ", reason=" + reason 1116 + ": retransmitting - retryCount=" + retryCount); 1117 } 1118 sentMessage.getData().putInt(MESSAGE_BUNDLE_KEY_RETRY_COUNT, 1119 retryCount - 1); 1120 1121 int arrivalSeq = sentMessage.getData().getInt( 1122 MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ); 1123 mHostQueuedSendMessages.put(arrivalSeq, sentMessage); 1124 } else { 1125 onMessageSendFailLocal(sentMessage, reason); 1126 } 1127 mSendQueueBlocked = false; 1128 transmitNextMessage(); 1129 } 1130 break; 1131 } 1132 case NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST: { 1133 WifiAwareNetworkSpecifier networkSpecifier = mDataPathMgr.onDataPathRequest( 1134 msg.arg2, msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS), 1135 (int) msg.obj); 1136 1137 if (networkSpecifier != null) { 1138 WakeupMessage timeout = new WakeupMessage(mContext, getHandler(), 1139 HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG, MESSAGE_TYPE_DATA_PATH_TIMEOUT, 1140 0, 0, networkSpecifier); 1141 mDataPathConfirmTimeoutMessages.put(networkSpecifier, timeout); 1142 timeout.schedule( 1143 SystemClock.elapsedRealtime() + AWARE_WAIT_FOR_DP_CONFIRM_TIMEOUT); 1144 } 1145 1146 break; 1147 } 1148 case NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM: { 1149 WifiAwareNetworkSpecifier networkSpecifier = mDataPathMgr.onDataPathConfirm( 1150 msg.arg2, msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS), 1151 msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), 1152 msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE), 1153 msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA)); 1154 1155 if (networkSpecifier != null) { 1156 WakeupMessage timeout = mDataPathConfirmTimeoutMessages.remove( 1157 networkSpecifier); 1158 if (timeout != null) { 1159 timeout.cancel(); 1160 } 1161 } 1162 1163 break; 1164 } 1165 case NOTIFICATION_TYPE_ON_DATA_PATH_END: 1166 mDataPathMgr.onDataPathEnd(msg.arg2); 1167 break; 1168 default: 1169 Log.wtf(TAG, "processNotification: this isn't a NOTIFICATION -- msg=" + msg); 1170 return; 1171 } 1172 } 1173 1174 /** 1175 * Execute the command specified by the input Message. Returns a true if 1176 * need to wait for a RESPONSE, otherwise a false. We may not have to 1177 * wait for a RESPONSE if there was an error in the state (so no command 1178 * is sent to HAL) OR if we choose not to wait for response - e.g. for 1179 * disconnected/terminate commands failure is not possible. 1180 */ 1181 private boolean processCommand(Message msg) { 1182 if (VDBG) { 1183 Log.v(TAG, "processCommand: msg=" + msg); 1184 } 1185 1186 if (mCurrentCommand != null) { 1187 Log.wtf(TAG, 1188 "processCommand: receiving a command (msg=" + msg 1189 + ") but current (previous) command isn't null (prev_msg=" 1190 + mCurrentCommand + ")"); 1191 mCurrentCommand = null; 1192 } 1193 1194 mCurrentTransactionId = mNextTransactionId++; 1195 1196 boolean waitForResponse = true; 1197 1198 switch (msg.arg1) { 1199 case COMMAND_TYPE_CONNECT: { 1200 int clientId = msg.arg2; 1201 IWifiAwareEventCallback callback = (IWifiAwareEventCallback) msg.obj; 1202 ConfigRequest configRequest = (ConfigRequest) msg.getData() 1203 .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG); 1204 int uid = msg.getData().getInt(MESSAGE_BUNDLE_KEY_UID); 1205 int pid = msg.getData().getInt(MESSAGE_BUNDLE_KEY_PID); 1206 String callingPackage = msg.getData().getString( 1207 MESSAGE_BUNDLE_KEY_CALLING_PACKAGE); 1208 boolean notifyIdentityChange = msg.getData().getBoolean( 1209 MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE); 1210 1211 waitForResponse = connectLocal(mCurrentTransactionId, clientId, uid, pid, 1212 callingPackage, callback, configRequest, notifyIdentityChange); 1213 break; 1214 } 1215 case COMMAND_TYPE_DISCONNECT: { 1216 int clientId = msg.arg2; 1217 1218 waitForResponse = disconnectLocal(mCurrentTransactionId, clientId); 1219 break; 1220 } 1221 case COMMAND_TYPE_TERMINATE_SESSION: { 1222 int clientId = msg.arg2; 1223 int sessionId = (Integer) msg.obj; 1224 1225 terminateSessionLocal(clientId, sessionId); 1226 waitForResponse = false; 1227 break; 1228 } 1229 case COMMAND_TYPE_PUBLISH: { 1230 int clientId = msg.arg2; 1231 IWifiAwareDiscoverySessionCallback callback = 1232 (IWifiAwareDiscoverySessionCallback) msg.obj; 1233 PublishConfig publishConfig = (PublishConfig) msg.getData() 1234 .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG); 1235 1236 waitForResponse = publishLocal(mCurrentTransactionId, clientId, publishConfig, 1237 callback); 1238 break; 1239 } 1240 case COMMAND_TYPE_UPDATE_PUBLISH: { 1241 int clientId = msg.arg2; 1242 int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); 1243 PublishConfig publishConfig = (PublishConfig) msg.obj; 1244 1245 waitForResponse = updatePublishLocal(mCurrentTransactionId, clientId, sessionId, 1246 publishConfig); 1247 break; 1248 } 1249 case COMMAND_TYPE_SUBSCRIBE: { 1250 int clientId = msg.arg2; 1251 IWifiAwareDiscoverySessionCallback callback = 1252 (IWifiAwareDiscoverySessionCallback) msg.obj; 1253 SubscribeConfig subscribeConfig = (SubscribeConfig) msg.getData() 1254 .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG); 1255 1256 waitForResponse = subscribeLocal(mCurrentTransactionId, clientId, 1257 subscribeConfig, callback); 1258 break; 1259 } 1260 case COMMAND_TYPE_UPDATE_SUBSCRIBE: { 1261 int clientId = msg.arg2; 1262 int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); 1263 SubscribeConfig subscribeConfig = (SubscribeConfig) msg.obj; 1264 1265 waitForResponse = updateSubscribeLocal(mCurrentTransactionId, clientId, 1266 sessionId, subscribeConfig); 1267 break; 1268 } 1269 case COMMAND_TYPE_ENQUEUE_SEND_MESSAGE: { 1270 if (VDBG) { 1271 Log.v(TAG, "processCommand: ENQUEUE_SEND_MESSAGE - messageId=" 1272 + msg.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID) 1273 + ", mSendArrivalSequenceCounter=" + mSendArrivalSequenceCounter); 1274 } 1275 Message sendMsg = obtainMessage(msg.what); 1276 sendMsg.copyFrom(msg); 1277 sendMsg.getData().putInt(MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ, 1278 mSendArrivalSequenceCounter); 1279 mHostQueuedSendMessages.put(mSendArrivalSequenceCounter, sendMsg); 1280 mSendArrivalSequenceCounter++; 1281 waitForResponse = false; 1282 1283 if (!mSendQueueBlocked) { 1284 transmitNextMessage(); 1285 } 1286 1287 break; 1288 } 1289 case COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE: { 1290 if (mSendQueueBlocked || mHostQueuedSendMessages.size() == 0) { 1291 if (VDBG) { 1292 Log.v(TAG, "processCommand: SEND_TOP_OF_QUEUE_MESSAGE - blocked or " 1293 + "empty host queue"); 1294 } 1295 waitForResponse = false; 1296 } else { 1297 if (VDBG) { 1298 Log.v(TAG, "processCommand: SEND_TOP_OF_QUEUE_MESSAGE - " 1299 + "sendArrivalSequenceCounter=" 1300 + mHostQueuedSendMessages.keyAt(0)); 1301 } 1302 Message sendMessage = mHostQueuedSendMessages.valueAt(0); 1303 mHostQueuedSendMessages.removeAt(0); 1304 1305 Bundle data = sendMessage.getData(); 1306 int clientId = sendMessage.arg2; 1307 int sessionId = sendMessage.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); 1308 int peerId = data.getInt(MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID); 1309 byte[] message = data.getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE); 1310 int messageId = data.getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID); 1311 1312 msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_SENT_MESSAGE, sendMessage); 1313 1314 waitForResponse = sendFollowonMessageLocal(mCurrentTransactionId, clientId, 1315 sessionId, peerId, message, messageId); 1316 } 1317 break; 1318 } 1319 case COMMAND_TYPE_ENABLE_USAGE: 1320 enableUsageLocal(); 1321 waitForResponse = false; 1322 break; 1323 case COMMAND_TYPE_DISABLE_USAGE: 1324 disableUsageLocal(); 1325 waitForResponse = false; 1326 break; 1327 case COMMAND_TYPE_START_RANGING: { 1328 Bundle data = msg.getData(); 1329 1330 int clientId = msg.arg2; 1331 RttManager.RttParams[] params = (RttManager.RttParams[]) msg.obj; 1332 int sessionId = data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); 1333 int rangingId = data.getInt(MESSAGE_BUNDLE_KEY_RANGING_ID); 1334 1335 startRangingLocal(clientId, sessionId, params, rangingId); 1336 waitForResponse = false; 1337 break; 1338 } 1339 case COMMAND_TYPE_GET_CAPABILITIES: 1340 if (mCapabilities == null) { 1341 waitForResponse = mWifiAwareNativeApi.getCapabilities( 1342 mCurrentTransactionId); 1343 } else { 1344 if (VDBG) { 1345 Log.v(TAG, "COMMAND_TYPE_GET_CAPABILITIES: already have capabilities - " 1346 + "skipping"); 1347 } 1348 waitForResponse = false; 1349 } 1350 break; 1351 case COMMAND_TYPE_CREATE_ALL_DATA_PATH_INTERFACES: 1352 mDataPathMgr.createAllInterfaces(); 1353 waitForResponse = false; 1354 break; 1355 case COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES: 1356 mDataPathMgr.deleteAllInterfaces(); 1357 waitForResponse = false; 1358 break; 1359 case COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE: 1360 waitForResponse = mWifiAwareNativeApi.createAwareNetworkInterface( 1361 mCurrentTransactionId, (String) msg.obj); 1362 break; 1363 case COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE: 1364 waitForResponse = mWifiAwareNativeApi.deleteAwareNetworkInterface( 1365 mCurrentTransactionId, (String) msg.obj); 1366 break; 1367 case COMMAND_TYPE_INITIATE_DATA_PATH_SETUP: { 1368 Bundle data = msg.getData(); 1369 1370 WifiAwareNetworkSpecifier networkSpecifier = 1371 (WifiAwareNetworkSpecifier) msg.obj; 1372 1373 int peerId = data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID); 1374 int channelRequestType = data.getInt(MESSAGE_BUNDLE_KEY_CHANNEL_REQ_TYPE); 1375 int channel = data.getInt(MESSAGE_BUNDLE_KEY_CHANNEL); 1376 byte[] peer = data.getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS); 1377 String interfaceName = data.getString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME); 1378 byte[] pmk = data.getByteArray(MESSAGE_BUNDLE_KEY_PMK); 1379 String passphrase = data.getString(MESSAGE_BUNDLE_KEY_PASSPHRASE); 1380 1381 waitForResponse = initiateDataPathSetupLocal(mCurrentTransactionId, 1382 networkSpecifier, peerId, channelRequestType, channel, peer, 1383 interfaceName, pmk, passphrase); 1384 1385 if (waitForResponse) { 1386 WakeupMessage timeout = new WakeupMessage(mContext, getHandler(), 1387 HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG, MESSAGE_TYPE_DATA_PATH_TIMEOUT, 1388 0, 0, networkSpecifier); 1389 mDataPathConfirmTimeoutMessages.put(networkSpecifier, timeout); 1390 timeout.schedule( 1391 SystemClock.elapsedRealtime() + AWARE_WAIT_FOR_DP_CONFIRM_TIMEOUT); 1392 } 1393 break; 1394 } 1395 case COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST: { 1396 Bundle data = msg.getData(); 1397 1398 int ndpId = msg.arg2; 1399 boolean accept = (boolean) msg.obj; 1400 String interfaceName = data.getString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME); 1401 byte[] pmk = data.getByteArray(MESSAGE_BUNDLE_KEY_PMK); 1402 String passphrase = data.getString(MESSAGE_BUNDLE_KEY_PASSPHRASE); 1403 1404 waitForResponse = respondToDataPathRequestLocal(mCurrentTransactionId, accept, 1405 ndpId, interfaceName, pmk, passphrase); 1406 1407 break; 1408 } 1409 case COMMAND_TYPE_END_DATA_PATH: 1410 waitForResponse = endDataPathLocal(mCurrentTransactionId, msg.arg2); 1411 break; 1412 default: 1413 waitForResponse = false; 1414 Log.wtf(TAG, "processCommand: this isn't a COMMAND -- msg=" + msg); 1415 /* fall-through */ 1416 } 1417 1418 if (!waitForResponse) { 1419 mCurrentTransactionId = TRANSACTION_ID_IGNORE; 1420 } else { 1421 mCurrentCommand = obtainMessage(msg.what); 1422 mCurrentCommand.copyFrom(msg); 1423 } 1424 1425 return waitForResponse; 1426 } 1427 1428 private void processResponse(Message msg) { 1429 if (VDBG) { 1430 Log.v(TAG, "processResponse: msg=" + msg); 1431 } 1432 1433 if (mCurrentCommand == null) { 1434 Log.wtf(TAG, "processResponse: no existing command stored!? msg=" + msg); 1435 mCurrentTransactionId = TRANSACTION_ID_IGNORE; 1436 return; 1437 } 1438 1439 switch (msg.arg1) { 1440 case RESPONSE_TYPE_ON_CONFIG_SUCCESS: 1441 onConfigCompletedLocal(mCurrentCommand); 1442 break; 1443 case RESPONSE_TYPE_ON_CONFIG_FAIL: { 1444 int reason = (Integer) msg.obj; 1445 1446 onConfigFailedLocal(mCurrentCommand, reason); 1447 break; 1448 } 1449 case RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS: { 1450 int pubSubId = (Integer) msg.obj; 1451 boolean isPublish = msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE); 1452 1453 onSessionConfigSuccessLocal(mCurrentCommand, pubSubId, isPublish); 1454 break; 1455 } 1456 case RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL: { 1457 int reason = (Integer) msg.obj; 1458 boolean isPublish = msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE); 1459 1460 onSessionConfigFailLocal(mCurrentCommand, isPublish, reason); 1461 break; 1462 } 1463 case RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS: { 1464 Message sentMessage = mCurrentCommand.getData().getParcelable( 1465 MESSAGE_BUNDLE_KEY_SENT_MESSAGE); 1466 sentMessage.getData().putLong(MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME, 1467 SystemClock.elapsedRealtime()); 1468 mFwQueuedSendMessages.put(mCurrentTransactionId, sentMessage); 1469 updateSendMessageTimeout(); 1470 if (!mSendQueueBlocked) { 1471 transmitNextMessage(); 1472 } 1473 1474 if (VDBG) { 1475 Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_SUCCESS - arrivalSeq=" 1476 + sentMessage.getData().getInt( 1477 MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ)); 1478 } 1479 break; 1480 } 1481 case RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL: { 1482 if (VDBG) { 1483 Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_FAIL - blocking!"); 1484 } 1485 int reason = (Integer) msg.obj; 1486 if (reason == NanStatusType.FOLLOWUP_TX_QUEUE_FULL) { 1487 Message sentMessage = mCurrentCommand.getData().getParcelable( 1488 MESSAGE_BUNDLE_KEY_SENT_MESSAGE); 1489 int arrivalSeq = sentMessage.getData().getInt( 1490 MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ); 1491 mHostQueuedSendMessages.put(arrivalSeq, sentMessage); 1492 mSendQueueBlocked = true; 1493 1494 if (VDBG) { 1495 Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_FAIL - arrivalSeq=" 1496 + arrivalSeq + " -- blocking"); 1497 } 1498 } else { 1499 Message sentMessage = mCurrentCommand.getData().getParcelable( 1500 MESSAGE_BUNDLE_KEY_SENT_MESSAGE); 1501 onMessageSendFailLocal(sentMessage, NanStatusType.INTERNAL_FAILURE); 1502 if (!mSendQueueBlocked) { 1503 transmitNextMessage(); 1504 } 1505 } 1506 break; 1507 } 1508 case RESPONSE_TYPE_ON_CAPABILITIES_UPDATED: { 1509 onCapabilitiesUpdatedResponseLocal((Capabilities) msg.obj); 1510 break; 1511 } 1512 case RESPONSE_TYPE_ON_CREATE_INTERFACE: 1513 onCreateDataPathInterfaceResponseLocal(mCurrentCommand, 1514 msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), 1515 msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE)); 1516 break; 1517 case RESPONSE_TYPE_ON_DELETE_INTERFACE: 1518 onDeleteDataPathInterfaceResponseLocal(mCurrentCommand, 1519 msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), 1520 msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE)); 1521 break; 1522 case RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS: 1523 onInitiateDataPathResponseSuccessLocal(mCurrentCommand, (int) msg.obj); 1524 break; 1525 case RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL: 1526 onInitiateDataPathResponseFailLocal(mCurrentCommand, (int) msg.obj); 1527 break; 1528 case RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST: 1529 onRespondToDataPathSetupRequestResponseLocal(mCurrentCommand, 1530 msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), 1531 msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE)); 1532 break; 1533 case RESPONSE_TYPE_ON_END_DATA_PATH: 1534 onEndPathEndResponseLocal(mCurrentCommand, 1535 msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), 1536 msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE)); 1537 break; 1538 default: 1539 Log.wtf(TAG, "processResponse: this isn't a RESPONSE -- msg=" + msg); 1540 mCurrentCommand = null; 1541 mCurrentTransactionId = TRANSACTION_ID_IGNORE; 1542 return; 1543 } 1544 1545 mCurrentCommand = null; 1546 mCurrentTransactionId = TRANSACTION_ID_IGNORE; 1547 } 1548 1549 private void processTimeout(Message msg) { 1550 if (VDBG) { 1551 Log.v(TAG, "processTimeout: msg=" + msg); 1552 } 1553 1554 if (mCurrentCommand == null) { 1555 Log.wtf(TAG, "processTimeout: no existing command stored!? msg=" + msg); 1556 mCurrentTransactionId = TRANSACTION_ID_IGNORE; 1557 return; 1558 } 1559 1560 /* 1561 * Only have to handle those COMMANDs which wait for a response. 1562 */ 1563 switch (msg.arg1) { 1564 case COMMAND_TYPE_CONNECT: { 1565 onConfigFailedLocal(mCurrentCommand, NanStatusType.INTERNAL_FAILURE); 1566 break; 1567 } 1568 case COMMAND_TYPE_DISCONNECT: { 1569 /* 1570 * Will only get here on DISCONNECT if was downgrading. The 1571 * callback will do a NOP - but should still call it. 1572 */ 1573 onConfigFailedLocal(mCurrentCommand, NanStatusType.INTERNAL_FAILURE); 1574 break; 1575 } 1576 case COMMAND_TYPE_TERMINATE_SESSION: { 1577 Log.wtf(TAG, "processTimeout: TERMINATE_SESSION - shouldn't be waiting!"); 1578 break; 1579 } 1580 case COMMAND_TYPE_PUBLISH: { 1581 onSessionConfigFailLocal(mCurrentCommand, true, NanStatusType.INTERNAL_FAILURE); 1582 break; 1583 } 1584 case COMMAND_TYPE_UPDATE_PUBLISH: { 1585 onSessionConfigFailLocal(mCurrentCommand, true, NanStatusType.INTERNAL_FAILURE); 1586 break; 1587 } 1588 case COMMAND_TYPE_SUBSCRIBE: { 1589 onSessionConfigFailLocal(mCurrentCommand, false, 1590 NanStatusType.INTERNAL_FAILURE); 1591 break; 1592 } 1593 case COMMAND_TYPE_UPDATE_SUBSCRIBE: { 1594 onSessionConfigFailLocal(mCurrentCommand, false, 1595 NanStatusType.INTERNAL_FAILURE); 1596 break; 1597 } 1598 case COMMAND_TYPE_ENQUEUE_SEND_MESSAGE: { 1599 Log.wtf(TAG, "processTimeout: ENQUEUE_SEND_MESSAGE - shouldn't be waiting!"); 1600 break; 1601 } 1602 case COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE: { 1603 Message sentMessage = mCurrentCommand.getData().getParcelable( 1604 MESSAGE_BUNDLE_KEY_SENT_MESSAGE); 1605 onMessageSendFailLocal(sentMessage, NanStatusType.INTERNAL_FAILURE); 1606 mSendQueueBlocked = false; 1607 transmitNextMessage(); 1608 break; 1609 } 1610 case COMMAND_TYPE_ENABLE_USAGE: 1611 Log.wtf(TAG, "processTimeout: ENABLE_USAGE - shouldn't be waiting!"); 1612 break; 1613 case COMMAND_TYPE_DISABLE_USAGE: 1614 Log.wtf(TAG, "processTimeout: DISABLE_USAGE - shouldn't be waiting!"); 1615 break; 1616 case COMMAND_TYPE_START_RANGING: 1617 Log.wtf(TAG, "processTimeout: START_RANGING - shouldn't be waiting!"); 1618 break; 1619 case COMMAND_TYPE_GET_CAPABILITIES: 1620 Log.e(TAG, 1621 "processTimeout: GET_CAPABILITIES timed-out - strange, will try again" 1622 + " when next enabled!?"); 1623 break; 1624 case COMMAND_TYPE_CREATE_ALL_DATA_PATH_INTERFACES: 1625 Log.wtf(TAG, 1626 "processTimeout: CREATE_ALL_DATA_PATH_INTERFACES - shouldn't be " 1627 + "waiting!"); 1628 break; 1629 case COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES: 1630 Log.wtf(TAG, 1631 "processTimeout: DELETE_ALL_DATA_PATH_INTERFACES - shouldn't be " 1632 + "waiting!"); 1633 break; 1634 case COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE: 1635 // TODO: fix status: timeout 1636 onCreateDataPathInterfaceResponseLocal(mCurrentCommand, false, 0); 1637 break; 1638 case COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE: 1639 // TODO: fix status: timeout 1640 onDeleteDataPathInterfaceResponseLocal(mCurrentCommand, false, 0); 1641 break; 1642 case COMMAND_TYPE_INITIATE_DATA_PATH_SETUP: 1643 // TODO: fix status: timeout 1644 onInitiateDataPathResponseFailLocal(mCurrentCommand, 0); 1645 break; 1646 case COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST: 1647 // TODO: fix status: timeout 1648 onRespondToDataPathSetupRequestResponseLocal(mCurrentCommand, false, 0); 1649 break; 1650 case COMMAND_TYPE_END_DATA_PATH: 1651 // TODO: fix status: timeout 1652 onEndPathEndResponseLocal(mCurrentCommand, false, 0); 1653 break; 1654 default: 1655 Log.wtf(TAG, "processTimeout: this isn't a COMMAND -- msg=" + msg); 1656 /* fall-through */ 1657 } 1658 1659 mCurrentCommand = null; 1660 mCurrentTransactionId = TRANSACTION_ID_IGNORE; 1661 } 1662 1663 private void updateSendMessageTimeout() { 1664 if (VDBG) { 1665 Log.v(TAG, "updateSendMessageTimeout: mHostQueuedSendMessages.size()=" 1666 + mHostQueuedSendMessages.size() + ", mFwQueuedSendMessages.size()=" 1667 + mFwQueuedSendMessages.size() + ", mSendQueueBlocked=" 1668 + mSendQueueBlocked); 1669 } 1670 Iterator<Message> it = mFwQueuedSendMessages.values().iterator(); 1671 if (it.hasNext()) { 1672 /* 1673 * Schedule timeout based on the first message in the queue (which is the earliest 1674 * submitted message). Timeout = queuing time + timeout constant. 1675 */ 1676 Message msg = it.next(); 1677 mSendMessageTimeoutMessage.schedule( 1678 msg.getData().getLong(MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME) 1679 + AWARE_SEND_MESSAGE_TIMEOUT); 1680 } else { 1681 mSendMessageTimeoutMessage.cancel(); 1682 } 1683 } 1684 1685 private void processSendMessageTimeout() { 1686 if (VDBG) { 1687 Log.v(TAG, "processSendMessageTimeout: mHostQueuedSendMessages.size()=" 1688 + mHostQueuedSendMessages.size() + ", mFwQueuedSendMessages.size()=" 1689 + mFwQueuedSendMessages.size() + ", mSendQueueBlocked=" 1690 + mSendQueueBlocked); 1691 1692 } 1693 /* 1694 * Note: using 'first' to always time-out (remove) at least 1 notification (partially) 1695 * due to test code needs: there's no way to mock elapsedRealtime(). TODO: replace with 1696 * injected getClock() once moved off of mmwd. 1697 */ 1698 boolean first = true; 1699 long currentTime = SystemClock.elapsedRealtime(); 1700 Iterator<Map.Entry<Short, Message>> it = mFwQueuedSendMessages.entrySet().iterator(); 1701 while (it.hasNext()) { 1702 Map.Entry<Short, Message> entry = it.next(); 1703 short transactionId = entry.getKey(); 1704 Message message = entry.getValue(); 1705 long messageEnqueueTime = message.getData().getLong( 1706 MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME); 1707 if (first || messageEnqueueTime + AWARE_SEND_MESSAGE_TIMEOUT <= currentTime) { 1708 if (VDBG) { 1709 Log.v(TAG, "processSendMessageTimeout: expiring - transactionId=" 1710 + transactionId + ", message=" + message 1711 + ", due to messageEnqueueTime=" + messageEnqueueTime 1712 + ", currentTime=" + currentTime); 1713 } 1714 onMessageSendFailLocal(message, NanStatusType.INTERNAL_FAILURE); 1715 it.remove(); 1716 first = false; 1717 } else { 1718 break; 1719 } 1720 } 1721 updateSendMessageTimeout(); 1722 mSendQueueBlocked = false; 1723 transmitNextMessage(); 1724 } 1725 1726 @Override 1727 protected String getLogRecString(Message msg) { 1728 StringBuilder sb = new StringBuilder(WifiAwareStateManager.messageToString(msg)); 1729 1730 if (msg.what == MESSAGE_TYPE_COMMAND 1731 && mCurrentTransactionId != TRANSACTION_ID_IGNORE) { 1732 sb.append(" (Transaction ID=").append(mCurrentTransactionId).append(")"); 1733 } 1734 1735 return sb.toString(); 1736 } 1737 1738 @Override 1739 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1740 pw.println("WifiAwareStateMachine:"); 1741 pw.println(" mNextTransactionId: " + mNextTransactionId); 1742 pw.println(" mNextSessionId: " + mNextSessionId); 1743 pw.println(" mCurrentCommand: " + mCurrentCommand); 1744 pw.println(" mCurrentTransaction: " + mCurrentTransactionId); 1745 pw.println(" mSendQueueBlocked: " + mSendQueueBlocked); 1746 pw.println(" mSendArrivalSequenceCounter: " + mSendArrivalSequenceCounter); 1747 pw.println(" mHostQueuedSendMessages: [" + mHostQueuedSendMessages + "]"); 1748 pw.println(" mFwQueuedSendMessages: [" + mFwQueuedSendMessages + "]"); 1749 super.dump(fd, pw, args); 1750 } 1751 } 1752 1753 private void sendAwareStateChangedBroadcast(boolean enabled) { 1754 if (VDBG) { 1755 Log.v(TAG, "sendAwareStateChangedBroadcast: enabled=" + enabled); 1756 } 1757 final Intent intent = new Intent(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED); 1758 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 1759 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 1760 } 1761 1762 /* 1763 * COMMANDS 1764 */ 1765 1766 private boolean connectLocal(short transactionId, int clientId, int uid, int pid, 1767 String callingPackage, IWifiAwareEventCallback callback, ConfigRequest configRequest, 1768 boolean notifyIdentityChange) { 1769 if (VDBG) { 1770 Log.v(TAG, "connectLocal(): transactionId=" + transactionId + ", clientId=" + clientId 1771 + ", uid=" + uid + ", pid=" + pid + ", callingPackage=" + callingPackage 1772 + ", callback=" + callback + ", configRequest=" + configRequest 1773 + ", notifyIdentityChange=" + notifyIdentityChange); 1774 } 1775 1776 if (!mUsageEnabled) { 1777 Log.w(TAG, "connect(): called with mUsageEnabled=false"); 1778 return false; 1779 } 1780 1781 if (mClients.get(clientId) != null) { 1782 Log.e(TAG, "connectLocal: entry already exists for clientId=" + clientId); 1783 } 1784 1785 if (VDBG) { 1786 Log.v(TAG, "mCurrentAwareConfiguration=" + mCurrentAwareConfiguration 1787 + ", mCurrentIdentityNotification=" + mCurrentIdentityNotification); 1788 } 1789 1790 ConfigRequest merged = mergeConfigRequests(configRequest); 1791 if (merged == null) { 1792 Log.e(TAG, "connectLocal: requested configRequest=" + configRequest 1793 + ", incompatible with current configurations"); 1794 try { 1795 callback.onConnectFail(NanStatusType.INTERNAL_FAILURE); 1796 } catch (RemoteException e) { 1797 Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e); 1798 } 1799 return false; 1800 } else if (VDBG) { 1801 Log.v(TAG, "connectLocal: merged=" + merged); 1802 } 1803 1804 if (mCurrentAwareConfiguration != null && mCurrentAwareConfiguration.equals(merged) 1805 && mCurrentIdentityNotification == notifyIdentityChange) { 1806 try { 1807 callback.onConnectSuccess(clientId); 1808 } catch (RemoteException e) { 1809 Log.w(TAG, "connectLocal onConnectSuccess(): RemoteException (FYI): " + e); 1810 } 1811 WifiAwareClientState client = new WifiAwareClientState(mContext, clientId, uid, pid, 1812 callingPackage, callback, configRequest, notifyIdentityChange); 1813 client.onInterfaceAddressChange(mCurrentDiscoveryInterfaceMac); 1814 mClients.append(clientId, client); 1815 return false; 1816 } 1817 boolean notificationRequired = 1818 doesAnyClientNeedIdentityChangeNotifications() || notifyIdentityChange; 1819 1820 boolean success = mWifiAwareNativeApi.enableAndConfigure(transactionId, merged, 1821 notificationRequired, mCurrentAwareConfiguration == null); 1822 if (!success) { 1823 try { 1824 callback.onConnectFail(NanStatusType.INTERNAL_FAILURE); 1825 } catch (RemoteException e) { 1826 Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e); 1827 } 1828 } 1829 1830 return success; 1831 } 1832 1833 private boolean disconnectLocal(short transactionId, int clientId) { 1834 if (VDBG) { 1835 Log.v(TAG, 1836 "disconnectLocal(): transactionId=" + transactionId + ", clientId=" + clientId); 1837 } 1838 1839 WifiAwareClientState client = mClients.get(clientId); 1840 if (client == null) { 1841 Log.e(TAG, "disconnectLocal: no entry for clientId=" + clientId); 1842 return false; 1843 } 1844 mClients.delete(clientId); 1845 client.destroy(); 1846 1847 if (mClients.size() == 0) { 1848 mCurrentAwareConfiguration = null; 1849 mWifiAwareNativeApi.disable((short) 0); 1850 return false; 1851 } 1852 1853 ConfigRequest merged = mergeConfigRequests(null); 1854 if (merged == null) { 1855 Log.wtf(TAG, "disconnectLocal: got an incompatible merge on remaining configs!?"); 1856 return false; 1857 } 1858 boolean notificationReqs = doesAnyClientNeedIdentityChangeNotifications(); 1859 if (merged.equals(mCurrentAwareConfiguration) 1860 && mCurrentIdentityNotification == notificationReqs) { 1861 return false; 1862 } 1863 1864 return mWifiAwareNativeApi.enableAndConfigure(transactionId, merged, notificationReqs, 1865 false); 1866 } 1867 1868 private void terminateSessionLocal(int clientId, int sessionId) { 1869 if (VDBG) { 1870 Log.v(TAG, 1871 "terminateSessionLocal(): clientId=" + clientId + ", sessionId=" + sessionId); 1872 } 1873 1874 WifiAwareClientState client = mClients.get(clientId); 1875 if (client == null) { 1876 Log.e(TAG, "terminateSession: no client exists for clientId=" + clientId); 1877 return; 1878 } 1879 1880 client.terminateSession(sessionId); 1881 } 1882 1883 private boolean publishLocal(short transactionId, int clientId, PublishConfig publishConfig, 1884 IWifiAwareDiscoverySessionCallback callback) { 1885 if (VDBG) { 1886 Log.v(TAG, "publishLocal(): transactionId=" + transactionId + ", clientId=" + clientId 1887 + ", publishConfig=" + publishConfig + ", callback=" + callback); 1888 } 1889 1890 WifiAwareClientState client = mClients.get(clientId); 1891 if (client == null) { 1892 Log.e(TAG, "publishLocal: no client exists for clientId=" + clientId); 1893 return false; 1894 } 1895 1896 boolean success = mWifiAwareNativeApi.publish(transactionId, 0, publishConfig); 1897 if (!success) { 1898 try { 1899 callback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); 1900 } catch (RemoteException e) { 1901 Log.w(TAG, "publishLocal onSessionConfigFail(): RemoteException (FYI): " + e); 1902 } 1903 } 1904 1905 return success; 1906 } 1907 1908 private boolean updatePublishLocal(short transactionId, int clientId, int sessionId, 1909 PublishConfig publishConfig) { 1910 if (VDBG) { 1911 Log.v(TAG, "updatePublishLocal(): transactionId=" + transactionId + ", clientId=" 1912 + clientId + ", sessionId=" + sessionId + ", publishConfig=" + publishConfig); 1913 } 1914 1915 WifiAwareClientState client = mClients.get(clientId); 1916 if (client == null) { 1917 Log.e(TAG, "updatePublishLocal: no client exists for clientId=" + clientId); 1918 return false; 1919 } 1920 1921 WifiAwareDiscoverySessionState session = client.getSession(sessionId); 1922 if (session == null) { 1923 Log.e(TAG, "updatePublishLocal: no session exists for clientId=" + clientId 1924 + ", sessionId=" + sessionId); 1925 return false; 1926 } 1927 1928 return session.updatePublish(transactionId, publishConfig); 1929 } 1930 1931 private boolean subscribeLocal(short transactionId, int clientId, 1932 SubscribeConfig subscribeConfig, IWifiAwareDiscoverySessionCallback callback) { 1933 if (VDBG) { 1934 Log.v(TAG, "subscribeLocal(): transactionId=" + transactionId + ", clientId=" + clientId 1935 + ", subscribeConfig=" + subscribeConfig + ", callback=" + callback); 1936 } 1937 1938 WifiAwareClientState client = mClients.get(clientId); 1939 if (client == null) { 1940 Log.e(TAG, "subscribeLocal: no client exists for clientId=" + clientId); 1941 return false; 1942 } 1943 1944 boolean success = mWifiAwareNativeApi.subscribe(transactionId, 0, subscribeConfig); 1945 if (!success) { 1946 try { 1947 callback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); 1948 } catch (RemoteException e) { 1949 Log.w(TAG, "subscribeLocal onSessionConfigFail(): RemoteException (FYI): " + e); 1950 } 1951 } 1952 1953 return success; 1954 } 1955 1956 private boolean updateSubscribeLocal(short transactionId, int clientId, int sessionId, 1957 SubscribeConfig subscribeConfig) { 1958 if (VDBG) { 1959 Log.v(TAG, 1960 "updateSubscribeLocal(): transactionId=" + transactionId + ", clientId=" 1961 + clientId + ", sessionId=" + sessionId + ", subscribeConfig=" 1962 + subscribeConfig); 1963 } 1964 1965 WifiAwareClientState client = mClients.get(clientId); 1966 if (client == null) { 1967 Log.e(TAG, "updateSubscribeLocal: no client exists for clientId=" + clientId); 1968 return false; 1969 } 1970 1971 WifiAwareDiscoverySessionState session = client.getSession(sessionId); 1972 if (session == null) { 1973 Log.e(TAG, "updateSubscribeLocal: no session exists for clientId=" + clientId 1974 + ", sessionId=" + sessionId); 1975 return false; 1976 } 1977 1978 return session.updateSubscribe(transactionId, subscribeConfig); 1979 } 1980 1981 private boolean sendFollowonMessageLocal(short transactionId, int clientId, int sessionId, 1982 int peerId, byte[] message, int messageId) { 1983 if (VDBG) { 1984 Log.v(TAG, 1985 "sendFollowonMessageLocal(): transactionId=" + transactionId + ", clientId=" 1986 + clientId + ", sessionId=" + sessionId + ", peerId=" + peerId 1987 + ", messageId=" + messageId); 1988 } 1989 1990 WifiAwareClientState client = mClients.get(clientId); 1991 if (client == null) { 1992 Log.e(TAG, "sendFollowonMessageLocal: no client exists for clientId=" + clientId); 1993 return false; 1994 } 1995 1996 WifiAwareDiscoverySessionState session = client.getSession(sessionId); 1997 if (session == null) { 1998 Log.e(TAG, "sendFollowonMessageLocal: no session exists for clientId=" + clientId 1999 + ", sessionId=" + sessionId); 2000 return false; 2001 } 2002 2003 return session.sendMessage(transactionId, peerId, message, messageId); 2004 } 2005 2006 private void enableUsageLocal() { 2007 if (VDBG) Log.v(TAG, "enableUsageLocal: mUsageEnabled=" + mUsageEnabled); 2008 2009 if (mUsageEnabled) { 2010 return; 2011 } 2012 2013 mUsageEnabled = true; 2014 queryCapabilities(); 2015 createAllDataPathInterfaces(); 2016 sendAwareStateChangedBroadcast(true); 2017 } 2018 2019 private void disableUsageLocal() { 2020 if (VDBG) Log.v(TAG, "disableUsageLocal: mUsageEnabled=" + mUsageEnabled); 2021 2022 if (!mUsageEnabled) { 2023 return; 2024 } 2025 2026 onAwareDownLocal(); 2027 deleteAllDataPathInterfaces(); 2028 2029 mUsageEnabled = false; 2030 mWifiAwareNativeApi.disable((short) 0); 2031 2032 sendAwareStateChangedBroadcast(false); 2033 } 2034 2035 private void startRangingLocal(int clientId, int sessionId, RttManager.RttParams[] params, 2036 int rangingId) { 2037 if (VDBG) { 2038 Log.v(TAG, "startRangingLocal: clientId=" + clientId + ", sessionId=" + sessionId 2039 + ", parms=" + Arrays.toString(params) + ", rangingId=" + rangingId); 2040 } 2041 2042 WifiAwareClientState client = mClients.get(clientId); 2043 if (client == null) { 2044 Log.e(TAG, "startRangingLocal: no client exists for clientId=" + clientId); 2045 return; 2046 } 2047 2048 WifiAwareDiscoverySessionState session = client.getSession(sessionId); 2049 if (session == null) { 2050 Log.e(TAG, "startRangingLocal: no session exists for clientId=" + clientId 2051 + ", sessionId=" + sessionId); 2052 client.onRangingFailure(rangingId, RttManager.REASON_INVALID_REQUEST, 2053 "Invalid session ID"); 2054 return; 2055 } 2056 2057 for (RttManager.RttParams param : params) { 2058 String peerIdStr = param.bssid; 2059 try { 2060 param.bssid = session.getMac(Integer.parseInt(peerIdStr), ":"); 2061 if (param.bssid == null) { 2062 Log.d(TAG, "startRangingLocal: no MAC address for peer ID=" + peerIdStr); 2063 param.bssid = ""; 2064 } 2065 } catch (NumberFormatException e) { 2066 Log.e(TAG, "startRangingLocal: invalid peer ID specification (in bssid field): '" 2067 + peerIdStr + "'"); 2068 param.bssid = ""; 2069 } 2070 } 2071 2072 mRtt.startRanging(rangingId, client, params); 2073 } 2074 2075 private boolean initiateDataPathSetupLocal(short transactionId, 2076 WifiAwareNetworkSpecifier networkSpecifier, int peerId, int channelRequestType, 2077 int channel, byte[] peer, String interfaceName, byte[] pmk, String passphrase) { 2078 if (VDBG) { 2079 Log.v(TAG, 2080 "initiateDataPathSetupLocal(): transactionId=" + transactionId 2081 + ", networkSpecifier=" + networkSpecifier + ", peerId=" + peerId 2082 + ", channelRequestType=" + channelRequestType + ", channel=" + channel 2083 + ", peer=" + String.valueOf(HexEncoding.encode(peer)) 2084 + ", interfaceName=" + interfaceName + ", pmk=" + pmk 2085 + ", passphrase=" + passphrase); 2086 } 2087 2088 boolean success = mWifiAwareNativeApi.initiateDataPath(transactionId, peerId, 2089 channelRequestType, channel, peer, interfaceName, pmk, passphrase, mCapabilities); 2090 if (!success) { 2091 mDataPathMgr.onDataPathInitiateFail(networkSpecifier, NanStatusType.INTERNAL_FAILURE); 2092 } 2093 2094 return success; 2095 } 2096 2097 private boolean respondToDataPathRequestLocal(short transactionId, boolean accept, 2098 int ndpId, String interfaceName, byte[] pmk, String passphrase) { 2099 if (VDBG) { 2100 Log.v(TAG, 2101 "respondToDataPathRequestLocal(): transactionId=" + transactionId + ", accept=" 2102 + accept + ", ndpId=" + ndpId + ", interfaceName=" + interfaceName 2103 + ", pmk=" + pmk + ", passphrase=" + passphrase); 2104 } 2105 2106 boolean success = mWifiAwareNativeApi.respondToDataPathRequest(transactionId, accept, ndpId, 2107 interfaceName, pmk, passphrase, mCapabilities); 2108 if (!success) { 2109 mDataPathMgr.onRespondToDataPathRequest(ndpId, false); 2110 } 2111 return success; 2112 } 2113 2114 private boolean endDataPathLocal(short transactionId, int ndpId) { 2115 if (VDBG) { 2116 Log.v(TAG, 2117 "endDataPathLocal: transactionId=" + transactionId + ", ndpId=" + ndpId); 2118 } 2119 2120 return mWifiAwareNativeApi.endDataPath(transactionId, ndpId); 2121 } 2122 2123 /* 2124 * RESPONSES 2125 */ 2126 2127 private void onConfigCompletedLocal(Message completedCommand) { 2128 if (VDBG) { 2129 Log.v(TAG, "onConfigCompleted: completedCommand=" + completedCommand); 2130 } 2131 2132 if (completedCommand.arg1 == COMMAND_TYPE_CONNECT) { 2133 Bundle data = completedCommand.getData(); 2134 2135 int clientId = completedCommand.arg2; 2136 IWifiAwareEventCallback callback = (IWifiAwareEventCallback) completedCommand.obj; 2137 ConfigRequest configRequest = (ConfigRequest) data 2138 .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG); 2139 int uid = data.getInt(MESSAGE_BUNDLE_KEY_UID); 2140 int pid = data.getInt(MESSAGE_BUNDLE_KEY_PID); 2141 boolean notifyIdentityChange = data.getBoolean( 2142 MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE); 2143 String callingPackage = data.getString(MESSAGE_BUNDLE_KEY_CALLING_PACKAGE); 2144 2145 WifiAwareClientState client = new WifiAwareClientState(mContext, clientId, uid, pid, 2146 callingPackage, callback, configRequest, notifyIdentityChange); 2147 mClients.put(clientId, client); 2148 try { 2149 callback.onConnectSuccess(clientId); 2150 } catch (RemoteException e) { 2151 Log.w(TAG, 2152 "onConfigCompletedLocal onConnectSuccess(): RemoteException (FYI): " + e); 2153 } 2154 client.onInterfaceAddressChange(mCurrentDiscoveryInterfaceMac); 2155 } else if (completedCommand.arg1 == COMMAND_TYPE_DISCONNECT) { 2156 /* 2157 * NOP (i.e. updated configuration after disconnecting a client) 2158 */ 2159 } else { 2160 Log.wtf(TAG, "onConfigCompletedLocal: unexpected completedCommand=" + completedCommand); 2161 return; 2162 } 2163 2164 mCurrentAwareConfiguration = mergeConfigRequests(null); 2165 if (mCurrentAwareConfiguration == null) { 2166 Log.wtf(TAG, "onConfigCompletedLocal: got a null merged configuration after config!?"); 2167 } 2168 mCurrentIdentityNotification = doesAnyClientNeedIdentityChangeNotifications(); 2169 } 2170 2171 private void onConfigFailedLocal(Message failedCommand, int reason) { 2172 if (VDBG) { 2173 Log.v(TAG, 2174 "onConfigFailedLocal: failedCommand=" + failedCommand + ", reason=" + reason); 2175 } 2176 2177 if (failedCommand.arg1 == COMMAND_TYPE_CONNECT) { 2178 IWifiAwareEventCallback callback = (IWifiAwareEventCallback) failedCommand.obj; 2179 2180 try { 2181 callback.onConnectFail(reason); 2182 } catch (RemoteException e) { 2183 Log.w(TAG, "onConfigFailedLocal onConnectFail(): RemoteException (FYI): " + e); 2184 } 2185 } else if (failedCommand.arg1 == COMMAND_TYPE_DISCONNECT) { 2186 /* 2187 * NOP (tried updating configuration after disconnecting a client - 2188 * shouldn't fail but there's nothing to do - the old configuration 2189 * is still up-and-running). 2190 */ 2191 } else { 2192 Log.wtf(TAG, "onConfigFailedLocal: unexpected failedCommand=" + failedCommand); 2193 return; 2194 } 2195 2196 } 2197 2198 private void onSessionConfigSuccessLocal(Message completedCommand, int pubSubId, 2199 boolean isPublish) { 2200 if (VDBG) { 2201 Log.v(TAG, "onSessionConfigSuccessLocal: completedCommand=" + completedCommand 2202 + ", pubSubId=" + pubSubId + ", isPublish=" + isPublish); 2203 } 2204 2205 if (completedCommand.arg1 == COMMAND_TYPE_PUBLISH 2206 || completedCommand.arg1 == COMMAND_TYPE_SUBSCRIBE) { 2207 int clientId = completedCommand.arg2; 2208 IWifiAwareDiscoverySessionCallback callback = 2209 (IWifiAwareDiscoverySessionCallback) completedCommand.obj; 2210 2211 WifiAwareClientState client = mClients.get(clientId); 2212 if (client == null) { 2213 Log.e(TAG, 2214 "onSessionConfigSuccessLocal: no client exists for clientId=" + clientId); 2215 return; 2216 } 2217 2218 int sessionId = mSm.mNextSessionId++; 2219 try { 2220 callback.onSessionStarted(sessionId); 2221 } catch (RemoteException e) { 2222 Log.e(TAG, "onSessionConfigSuccessLocal: onSessionStarted() RemoteException=" + e); 2223 return; 2224 } 2225 2226 WifiAwareDiscoverySessionState session = new WifiAwareDiscoverySessionState( 2227 mWifiAwareNativeApi, sessionId, pubSubId, callback, isPublish); 2228 client.addSession(session); 2229 } else if (completedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH 2230 || completedCommand.arg1 == COMMAND_TYPE_UPDATE_SUBSCRIBE) { 2231 int clientId = completedCommand.arg2; 2232 int sessionId = completedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); 2233 2234 WifiAwareClientState client = mClients.get(clientId); 2235 if (client == null) { 2236 Log.e(TAG, 2237 "onSessionConfigSuccessLocal: no client exists for clientId=" + clientId); 2238 return; 2239 } 2240 2241 WifiAwareDiscoverySessionState session = client.getSession(sessionId); 2242 if (session == null) { 2243 Log.e(TAG, "onSessionConfigSuccessLocal: no session exists for clientId=" + clientId 2244 + ", sessionId=" + sessionId); 2245 return; 2246 } 2247 2248 try { 2249 session.getCallback().onSessionConfigSuccess(); 2250 } catch (RemoteException e) { 2251 Log.e(TAG, "onSessionConfigSuccessLocal: onSessionConfigSuccess() RemoteException=" 2252 + e); 2253 } 2254 } else { 2255 Log.wtf(TAG, 2256 "onSessionConfigSuccessLocal: unexpected completedCommand=" + completedCommand); 2257 } 2258 } 2259 2260 private void onSessionConfigFailLocal(Message failedCommand, boolean isPublish, int reason) { 2261 if (VDBG) { 2262 Log.v(TAG, "onSessionConfigFailLocal: failedCommand=" + failedCommand + ", isPublish=" 2263 + isPublish + ", reason=" + reason); 2264 } 2265 2266 if (failedCommand.arg1 == COMMAND_TYPE_PUBLISH 2267 || failedCommand.arg1 == COMMAND_TYPE_SUBSCRIBE) { 2268 IWifiAwareDiscoverySessionCallback callback = 2269 (IWifiAwareDiscoverySessionCallback) failedCommand.obj; 2270 try { 2271 callback.onSessionConfigFail(reason); 2272 } catch (RemoteException e) { 2273 Log.w(TAG, "onSessionConfigFailLocal onSessionConfigFail(): RemoteException (FYI): " 2274 + e); 2275 } 2276 } else if (failedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH 2277 || failedCommand.arg1 == COMMAND_TYPE_UPDATE_SUBSCRIBE) { 2278 int clientId = failedCommand.arg2; 2279 int sessionId = failedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); 2280 2281 WifiAwareClientState client = mClients.get(clientId); 2282 if (client == null) { 2283 Log.e(TAG, "onSessionConfigFailLocal: no client exists for clientId=" + clientId); 2284 return; 2285 } 2286 2287 WifiAwareDiscoverySessionState session = client.getSession(sessionId); 2288 if (session == null) { 2289 Log.e(TAG, "onSessionConfigFailLocal: no session exists for clientId=" + clientId 2290 + ", sessionId=" + sessionId); 2291 return; 2292 } 2293 2294 try { 2295 session.getCallback().onSessionConfigFail(reason); 2296 } catch (RemoteException e) { 2297 Log.e(TAG, "onSessionConfigFailLocal: onSessionConfigFail() RemoteException=" + e); 2298 } 2299 } else { 2300 Log.wtf(TAG, "onSessionConfigFailLocal: unexpected failedCommand=" + failedCommand); 2301 } 2302 } 2303 2304 private void onMessageSendSuccessLocal(Message completedCommand) { 2305 if (VDBG) { 2306 Log.v(TAG, "onMessageSendSuccess: completedCommand=" + completedCommand); 2307 } 2308 2309 int clientId = completedCommand.arg2; 2310 int sessionId = completedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); 2311 int messageId = completedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID); 2312 2313 WifiAwareClientState client = mClients.get(clientId); 2314 if (client == null) { 2315 Log.e(TAG, "onMessageSendSuccessLocal: no client exists for clientId=" + clientId); 2316 return; 2317 } 2318 2319 WifiAwareDiscoverySessionState session = client.getSession(sessionId); 2320 if (session == null) { 2321 Log.e(TAG, "onMessageSendSuccessLocal: no session exists for clientId=" + clientId 2322 + ", sessionId=" + sessionId); 2323 return; 2324 } 2325 2326 try { 2327 session.getCallback().onMessageSendSuccess(messageId); 2328 } catch (RemoteException e) { 2329 Log.w(TAG, "onMessageSendSuccessLocal: RemoteException (FYI): " + e); 2330 } 2331 } 2332 2333 private void onMessageSendFailLocal(Message failedCommand, int reason) { 2334 if (VDBG) { 2335 Log.v(TAG, "onMessageSendFail: failedCommand=" + failedCommand + ", reason=" + reason); 2336 } 2337 2338 int clientId = failedCommand.arg2; 2339 int sessionId = failedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID); 2340 int messageId = failedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID); 2341 2342 WifiAwareClientState client = mClients.get(clientId); 2343 if (client == null) { 2344 Log.e(TAG, "onMessageSendFailLocal: no client exists for clientId=" + clientId); 2345 return; 2346 } 2347 2348 WifiAwareDiscoverySessionState session = client.getSession(sessionId); 2349 if (session == null) { 2350 Log.e(TAG, "onMessageSendFailLocal: no session exists for clientId=" + clientId 2351 + ", sessionId=" + sessionId); 2352 return; 2353 } 2354 2355 try { 2356 session.getCallback().onMessageSendFail(messageId, reason); 2357 } catch (RemoteException e) { 2358 Log.e(TAG, "onMessageSendFailLocal: onMessageSendFail RemoteException=" + e); 2359 } 2360 } 2361 2362 private void onCapabilitiesUpdatedResponseLocal(Capabilities capabilities) { 2363 if (VDBG) { 2364 Log.v(TAG, "onCapabilitiesUpdatedResponseLocal: capabilites=" + capabilities); 2365 } 2366 2367 mCapabilities = capabilities; 2368 mCharacteristics = null; 2369 } 2370 2371 private void onCreateDataPathInterfaceResponseLocal(Message command, boolean success, 2372 int reasonOnFailure) { 2373 if (VDBG) { 2374 Log.v(TAG, "onCreateDataPathInterfaceResponseLocal: command=" + command + ", success=" 2375 + success + ", reasonOnFailure=" + reasonOnFailure); 2376 } 2377 2378 if (success) { 2379 if (DBG) { 2380 Log.d(TAG, "onCreateDataPathInterfaceResponseLocal: successfully created interface " 2381 + command.obj); 2382 } 2383 mDataPathMgr.onInterfaceCreated((String) command.obj); 2384 } else { 2385 Log.e(TAG, 2386 "onCreateDataPathInterfaceResponseLocal: failed when trying to create " 2387 + "interface " 2388 + command.obj + ". Reason code=" + reasonOnFailure); 2389 } 2390 } 2391 2392 private void onDeleteDataPathInterfaceResponseLocal(Message command, boolean success, 2393 int reasonOnFailure) { 2394 if (VDBG) { 2395 Log.v(TAG, "onDeleteDataPathInterfaceResponseLocal: command=" + command + ", success=" 2396 + success + ", reasonOnFailure=" + reasonOnFailure); 2397 } 2398 2399 if (success) { 2400 if (DBG) { 2401 Log.d(TAG, "onDeleteDataPathInterfaceResponseLocal: successfully deleted interface " 2402 + command.obj); 2403 } 2404 mDataPathMgr.onInterfaceDeleted((String) command.obj); 2405 } else { 2406 Log.e(TAG, 2407 "onDeleteDataPathInterfaceResponseLocal: failed when trying to delete " 2408 + "interface " 2409 + command.obj + ". Reason code=" + reasonOnFailure); 2410 } 2411 } 2412 2413 private void onInitiateDataPathResponseSuccessLocal(Message command, int ndpId) { 2414 if (VDBG) { 2415 Log.v(TAG, "onInitiateDataPathResponseSuccessLocal: command=" + command + ", ndpId=" 2416 + ndpId); 2417 } 2418 2419 mDataPathMgr.onDataPathInitiateSuccess((WifiAwareNetworkSpecifier) command.obj, ndpId); 2420 } 2421 2422 private void onInitiateDataPathResponseFailLocal(Message command, int reason) { 2423 if (VDBG) { 2424 Log.v(TAG, "onInitiateDataPathResponseFailLocal: command=" + command + ", reason=" 2425 + reason); 2426 } 2427 2428 mDataPathMgr.onDataPathInitiateFail((WifiAwareNetworkSpecifier) command.obj, reason); 2429 } 2430 2431 private void onRespondToDataPathSetupRequestResponseLocal(Message command, boolean success, 2432 int reasonOnFailure) { 2433 if (VDBG) { 2434 Log.v(TAG, "onRespondToDataPathSetupRequestResponseLocal: command=" + command 2435 + ", success=" + success + ", reasonOnFailure=" + reasonOnFailure); 2436 } 2437 2438 mDataPathMgr.onRespondToDataPathRequest(command.arg2, success); 2439 } 2440 2441 private void onEndPathEndResponseLocal(Message command, boolean success, int reasonOnFailure) { 2442 if (VDBG) { 2443 Log.v(TAG, "onEndPathEndResponseLocal: command=" + command 2444 + ", success=" + success + ", reasonOnFailure=" + reasonOnFailure); 2445 } 2446 2447 // TODO: do something with this 2448 } 2449 2450 /* 2451 * NOTIFICATIONS 2452 */ 2453 2454 private void onInterfaceAddressChangeLocal(byte[] mac) { 2455 if (VDBG) { 2456 Log.v(TAG, "onInterfaceAddressChange: mac=" + String.valueOf(HexEncoding.encode(mac))); 2457 } 2458 2459 mCurrentDiscoveryInterfaceMac = mac; 2460 2461 for (int i = 0; i < mClients.size(); ++i) { 2462 WifiAwareClientState client = mClients.valueAt(i); 2463 client.onInterfaceAddressChange(mac); 2464 } 2465 } 2466 2467 private void onClusterChangeLocal(int flag, byte[] clusterId) { 2468 if (VDBG) { 2469 Log.v(TAG, "onClusterChange: flag=" + flag + ", clusterId=" 2470 + String.valueOf(HexEncoding.encode(clusterId))); 2471 } 2472 2473 for (int i = 0; i < mClients.size(); ++i) { 2474 WifiAwareClientState client = mClients.valueAt(i); 2475 client.onClusterChange(flag, clusterId, mCurrentDiscoveryInterfaceMac); 2476 } 2477 } 2478 2479 private void onMatchLocal(int pubSubId, int requestorInstanceId, byte[] peerMac, 2480 byte[] serviceSpecificInfo, byte[] matchFilter) { 2481 if (VDBG) { 2482 Log.v(TAG, 2483 "onMatch: pubSubId=" + pubSubId + ", requestorInstanceId=" + requestorInstanceId 2484 + ", peerDiscoveryMac=" + String.valueOf(HexEncoding.encode(peerMac)) 2485 + ", serviceSpecificInfo=" + Arrays.toString(serviceSpecificInfo) 2486 + ", matchFilter=" + Arrays.toString(matchFilter)); 2487 } 2488 2489 Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data = 2490 getClientSessionForPubSubId(pubSubId); 2491 if (data == null) { 2492 Log.e(TAG, "onMatch: no session found for pubSubId=" + pubSubId); 2493 return; 2494 } 2495 2496 data.second.onMatch(requestorInstanceId, peerMac, serviceSpecificInfo, matchFilter); 2497 } 2498 2499 private void onSessionTerminatedLocal(int pubSubId, boolean isPublish, int reason) { 2500 if (VDBG) { 2501 Log.v(TAG, "onSessionTerminatedLocal: pubSubId=" + pubSubId + ", isPublish=" + isPublish 2502 + ", reason=" + reason); 2503 } 2504 2505 Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data = 2506 getClientSessionForPubSubId(pubSubId); 2507 if (data == null) { 2508 Log.e(TAG, "onSessionTerminatedLocal: no session found for pubSubId=" + pubSubId); 2509 return; 2510 } 2511 2512 try { 2513 data.second.getCallback().onSessionTerminated(reason); 2514 } catch (RemoteException e) { 2515 Log.w(TAG, 2516 "onSessionTerminatedLocal onSessionTerminated(): RemoteException (FYI): " + e); 2517 } 2518 data.first.removeSession(data.second.getSessionId()); 2519 } 2520 2521 private void onMessageReceivedLocal(int pubSubId, int requestorInstanceId, byte[] peerMac, 2522 byte[] message) { 2523 if (VDBG) { 2524 Log.v(TAG, 2525 "onMessageReceivedLocal: pubSubId=" + pubSubId + ", requestorInstanceId=" 2526 + requestorInstanceId + ", peerDiscoveryMac=" 2527 + String.valueOf(HexEncoding.encode(peerMac))); 2528 } 2529 2530 Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data = 2531 getClientSessionForPubSubId(pubSubId); 2532 if (data == null) { 2533 Log.e(TAG, "onMessageReceivedLocal: no session found for pubSubId=" + pubSubId); 2534 return; 2535 } 2536 2537 data.second.onMessageReceived(requestorInstanceId, peerMac, message); 2538 } 2539 2540 private void onAwareDownLocal() { 2541 if (VDBG) { 2542 Log.v(TAG, "onAwareDown"); 2543 } 2544 2545 mClients.clear(); 2546 mCurrentAwareConfiguration = null; 2547 mSm.onAwareDownCleanupSendQueueState(); 2548 mDataPathMgr.onAwareDownCleanupDataPaths(); 2549 mCurrentDiscoveryInterfaceMac = ALL_ZERO_MAC; 2550 } 2551 2552 /* 2553 * Utilities 2554 */ 2555 2556 private Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> getClientSessionForPubSubId( 2557 int pubSubId) { 2558 for (int i = 0; i < mClients.size(); ++i) { 2559 WifiAwareClientState client = mClients.valueAt(i); 2560 WifiAwareDiscoverySessionState session = client.getAwareSessionStateForPubSubId( 2561 pubSubId); 2562 if (session != null) { 2563 return new Pair<>(client, session); 2564 } 2565 } 2566 2567 return null; 2568 } 2569 2570 /** 2571 * Merge all the existing client configurations with the (optional) input configuration request. 2572 * If the configurations are "incompatible" (rules in comment below) return a null. 2573 */ 2574 private ConfigRequest mergeConfigRequests(ConfigRequest configRequest) { 2575 if (VDBG) { 2576 Log.v(TAG, "mergeConfigRequests(): mClients=[" + mClients + "], configRequest=" 2577 + configRequest); 2578 } 2579 2580 if (mClients.size() == 0 && configRequest == null) { 2581 Log.e(TAG, "mergeConfigRequests: invalid state - called with 0 clients registered!"); 2582 return null; 2583 } 2584 2585 // TODO: continue working on merge algorithm: 2586 // - if any request 5g: enable 2587 // - maximal master preference 2588 // - cluster range: must be identical 2589 // - if any request identity change: enable 2590 // - discovery window: minimum value if specified, 0 (disable) is considered an infinity 2591 boolean support5gBand = false; 2592 int masterPreference = 0; 2593 boolean clusterIdValid = false; 2594 int clusterLow = 0; 2595 int clusterHigh = ConfigRequest.CLUSTER_ID_MAX; 2596 int[] discoveryWindowInterval = 2597 {ConfigRequest.DW_INTERVAL_NOT_INIT, ConfigRequest.DW_INTERVAL_NOT_INIT}; 2598 if (configRequest != null) { 2599 support5gBand = configRequest.mSupport5gBand; 2600 masterPreference = configRequest.mMasterPreference; 2601 clusterIdValid = true; 2602 clusterLow = configRequest.mClusterLow; 2603 clusterHigh = configRequest.mClusterHigh; 2604 discoveryWindowInterval = configRequest.mDiscoveryWindowInterval; 2605 } 2606 for (int i = 0; i < mClients.size(); ++i) { 2607 ConfigRequest cr = mClients.valueAt(i).getConfigRequest(); 2608 2609 // any request turns on 5G 2610 if (cr.mSupport5gBand) { 2611 support5gBand = true; 2612 } 2613 2614 // maximal master preference 2615 masterPreference = Math.max(masterPreference, cr.mMasterPreference); 2616 2617 // cluster range must be the same across all config requests 2618 if (!clusterIdValid) { 2619 clusterIdValid = true; 2620 clusterLow = cr.mClusterLow; 2621 clusterHigh = cr.mClusterHigh; 2622 } else { 2623 if (clusterLow != cr.mClusterLow) return null; 2624 if (clusterHigh != cr.mClusterHigh) return null; 2625 } 2626 2627 for (int band = ConfigRequest.NAN_BAND_24GHZ; band <= ConfigRequest.NAN_BAND_5GHZ; 2628 ++band) { 2629 if (discoveryWindowInterval[band] == ConfigRequest.DW_INTERVAL_NOT_INIT) { 2630 discoveryWindowInterval[band] = cr.mDiscoveryWindowInterval[band]; 2631 } else if (cr.mDiscoveryWindowInterval[band] 2632 == ConfigRequest.DW_INTERVAL_NOT_INIT) { 2633 // do nothing: keep my values 2634 } else if (discoveryWindowInterval[band] == ConfigRequest.DW_DISABLE) { 2635 discoveryWindowInterval[band] = cr.mDiscoveryWindowInterval[band]; 2636 } else if (cr.mDiscoveryWindowInterval[band] == ConfigRequest.DW_DISABLE) { 2637 // do nothing: keep my values 2638 } else { 2639 discoveryWindowInterval[band] = Math.min(discoveryWindowInterval[band], 2640 cr.mDiscoveryWindowInterval[band]); 2641 } 2642 } 2643 } 2644 ConfigRequest.Builder builder = new ConfigRequest.Builder().setSupport5gBand(support5gBand) 2645 .setMasterPreference(masterPreference).setClusterLow(clusterLow) 2646 .setClusterHigh(clusterHigh); 2647 for (int band = ConfigRequest.NAN_BAND_24GHZ; band <= ConfigRequest.NAN_BAND_5GHZ; ++band) { 2648 if (discoveryWindowInterval[band] != ConfigRequest.DW_INTERVAL_NOT_INIT) { 2649 builder.setDiscoveryWindowInterval(band, discoveryWindowInterval[band]); 2650 } 2651 } 2652 return builder.build(); 2653 } 2654 2655 private boolean doesAnyClientNeedIdentityChangeNotifications() { 2656 for (int i = 0; i < mClients.size(); ++i) { 2657 if (mClients.valueAt(i).getNotifyIdentityChange()) { 2658 return true; 2659 } 2660 } 2661 return false; 2662 } 2663 2664 private static String messageToString(Message msg) { 2665 StringBuilder sb = new StringBuilder(); 2666 2667 String s = sSmToString.get(msg.what); 2668 if (s == null) { 2669 s = "<unknown>"; 2670 } 2671 sb.append(s).append("/"); 2672 2673 if (msg.what == MESSAGE_TYPE_NOTIFICATION || msg.what == MESSAGE_TYPE_COMMAND 2674 || msg.what == MESSAGE_TYPE_RESPONSE) { 2675 s = sSmToString.get(msg.arg1); 2676 if (s == null) { 2677 s = "<unknown>"; 2678 } 2679 sb.append(s); 2680 } 2681 2682 if (msg.what == MESSAGE_TYPE_RESPONSE || msg.what == MESSAGE_TYPE_RESPONSE_TIMEOUT) { 2683 sb.append(" (Transaction ID=").append(msg.arg2).append(")"); 2684 } 2685 2686 return sb.toString(); 2687 } 2688 2689 /** 2690 * Dump the internal state of the class. 2691 */ 2692 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2693 pw.println("AwareStateManager:"); 2694 pw.println(" mClients: [" + mClients + "]"); 2695 pw.println(" mUsageEnabled: " + mUsageEnabled); 2696 pw.println(" mCapabilities: [" + mCapabilities + "]"); 2697 pw.println(" mCurrentAwareConfiguration: " + mCurrentAwareConfiguration); 2698 pw.println(" mCurrentIdentityNotification: " + mCurrentIdentityNotification); 2699 for (int i = 0; i < mClients.size(); ++i) { 2700 mClients.valueAt(i).dump(fd, pw, args); 2701 } 2702 mSm.dump(fd, pw, args); 2703 mRtt.dump(fd, pw, args); 2704 mDataPathMgr.dump(fd, pw, args); 2705 mWifiAwareNativeApi.dump(fd, pw, args); 2706 } 2707 } 2708