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