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