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