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