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