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