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