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