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