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