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