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