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