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; 18 19 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; 20 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING; 21 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; 22 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING; 23 import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.net.ConnectivityManager; 30 import android.net.ConnectivityManager.NetworkCallback; 31 import android.net.DhcpResultsParcelable; 32 import android.net.Network; 33 import android.net.NetworkCapabilities; 34 import android.net.NetworkRequest; 35 import android.net.wifi.IWifiConnectedNetworkScorer; 36 import android.net.wifi.WifiAnnotations; 37 import android.net.wifi.WifiConfiguration; 38 import android.net.wifi.WifiInfo; 39 import android.net.wifi.WifiManager; 40 import android.net.wifi.hotspot2.IProvisioningCallback; 41 import android.net.wifi.hotspot2.OsuProvider; 42 import android.net.wifi.nl80211.DeviceWiphyCapabilities; 43 import android.os.Handler; 44 import android.os.HandlerExecutor; 45 import android.os.IBinder; 46 import android.os.Looper; 47 import android.os.Message; 48 import android.os.PersistableBundle; 49 import android.os.UserHandle; 50 import android.os.WorkSource; 51 import android.telephony.AccessNetworkConstants; 52 import android.telephony.CarrierConfigManager; 53 import android.telephony.SubscriptionInfo; 54 import android.telephony.SubscriptionManager; 55 import android.telephony.ims.ImsException; 56 import android.telephony.ims.ImsMmTelManager; 57 import android.telephony.ims.ImsReasonInfo; 58 import android.telephony.ims.RegistrationManager; 59 import android.telephony.ims.feature.MmTelFeature; 60 import android.telephony.ims.stub.ImsRegistrationImplBase; 61 import android.text.TextUtils; 62 import android.util.Log; 63 64 import com.android.internal.util.IState; 65 import com.android.internal.util.State; 66 import com.android.internal.util.StateMachine; 67 import com.android.server.wifi.WifiNative.InterfaceCallback; 68 import com.android.server.wifi.WifiNative.RxFateReport; 69 import com.android.server.wifi.WifiNative.TxFateReport; 70 import com.android.server.wifi.util.ActionListenerWrapper; 71 import com.android.server.wifi.util.StateMachineObituary; 72 import com.android.server.wifi.util.WifiHandler; 73 import com.android.wifi.resources.R; 74 75 import java.io.FileDescriptor; 76 import java.io.PrintWriter; 77 import java.util.ArrayDeque; 78 import java.util.List; 79 import java.util.Set; 80 import java.util.concurrent.atomic.AtomicInteger; 81 82 /** 83 * Manage WiFi in Client Mode where we connect to configured networks and in Scan Only Mode where 84 * we do not connect to configured networks but do perform scanning. 85 * 86 * An instance of this class is active to manage each client interface. This is in contrast to 87 * {@link DefaultClientModeManager} which handles calls when no client interfaces are active. 88 * 89 * This class will dynamically instantiate {@link ClientModeImpl} when it enters client mode, and 90 * tear it down when it exits client mode. No instance of ClientModeImpl will be active in 91 * scan-only mode, instead {@link ScanOnlyModeImpl} will be used to respond to calls. 92 * 93 * <pre> 94 * ActiveModeWarden 95 * / \ 96 * / \ 97 * ConcreteClientModeManager DefaultClientModeManager 98 * (Client Mode + Scan Only Mode) (Wifi off) 99 * / \ 100 * / \ 101 * ClientModeImpl ScanOnlyModeImpl 102 * </pre> 103 */ 104 public class ConcreteClientModeManager implements ClientModeManager { 105 private static final String TAG = "WifiClientModeManager"; 106 107 private final ClientModeStateMachine mStateMachine; 108 109 private final Context mContext; 110 private final Clock mClock; 111 private final WifiNative mWifiNative; 112 private final WifiMetrics mWifiMetrics; 113 private final WakeupController mWakeupController; 114 private final WifiInjector mWifiInjector; 115 private final SelfRecovery mSelfRecovery; 116 private final WifiGlobals mWifiGlobals; 117 private final DefaultClientModeManager mDefaultClientModeManager; 118 private final ClientModeManagerBroadcastQueue mBroadcastQueue; 119 private final long mId; 120 private final Graveyard mGraveyard = new Graveyard(); 121 122 private String mClientInterfaceName; 123 private boolean mIfaceIsUp = false; 124 private boolean mShouldReduceNetworkScore = false; 125 private final DeferStopHandler mDeferStopHandler; 126 @Nullable 127 private ClientRole mRole = null; 128 @Nullable 129 private ClientRole mPreviousRole = null; 130 private long mLastRoleChangeSinceBootMs = 0; 131 @Nullable 132 private WorkSource mRequestorWs = null; 133 @NonNull 134 private Listener<ConcreteClientModeManager> mModeListener; 135 /** Caches the latest role change request. This is needed for the IMS dereg delay */ 136 @Nullable 137 private RoleChangeInfo mTargetRoleChangeInfo; 138 private boolean mVerboseLoggingEnabled = false; 139 private int mActiveSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 140 private boolean mWifiStateChangeBroadcastEnabled = true; 141 /** 142 * mClientModeImpl is only non-null when in {@link ClientModeStateMachine.ConnectModeState} - 143 * it will be null in all other states 144 */ 145 @Nullable 146 private ClientModeImpl mClientModeImpl = null; 147 148 @Nullable 149 private ScanOnlyModeImpl mScanOnlyModeImpl = null; 150 151 /** 152 * One of {@link WifiManager#WIFI_STATE_DISABLED}, 153 * {@link WifiManager#WIFI_STATE_DISABLING}, 154 * {@link WifiManager#WIFI_STATE_ENABLED}, 155 * {@link WifiManager#WIFI_STATE_ENABLING}, 156 * {@link WifiManager#WIFI_STATE_UNKNOWN} 157 */ 158 private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED); 159 160 private boolean mIsStopped = true; 161 ConcreteClientModeManager( Context context, @NonNull Looper looper, Clock clock, WifiNative wifiNative, @NonNull Listener<ConcreteClientModeManager> listener, WifiMetrics wifiMetrics, WakeupController wakeupController, WifiInjector wifiInjector, SelfRecovery selfRecovery, WifiGlobals wifiGlobals, DefaultClientModeManager defaultClientModeManager, long id, @NonNull WorkSource requestorWs, @NonNull ClientRole role, @NonNull ClientModeManagerBroadcastQueue broadcastQueue, boolean verboseLoggingEnabled)162 ConcreteClientModeManager( 163 Context context, @NonNull Looper looper, Clock clock, 164 WifiNative wifiNative, @NonNull Listener<ConcreteClientModeManager> listener, 165 WifiMetrics wifiMetrics, 166 WakeupController wakeupController, WifiInjector wifiInjector, 167 SelfRecovery selfRecovery, WifiGlobals wifiGlobals, 168 DefaultClientModeManager defaultClientModeManager, long id, 169 @NonNull WorkSource requestorWs, @NonNull ClientRole role, 170 @NonNull ClientModeManagerBroadcastQueue broadcastQueue, 171 boolean verboseLoggingEnabled) { 172 mContext = context; 173 mClock = clock; 174 mWifiNative = wifiNative; 175 mModeListener = listener; 176 mWifiMetrics = wifiMetrics; 177 mWakeupController = wakeupController; 178 mWifiInjector = wifiInjector; 179 mStateMachine = new ClientModeStateMachine(looper); 180 mDeferStopHandler = new DeferStopHandler(looper); 181 mSelfRecovery = selfRecovery; 182 mWifiGlobals = wifiGlobals; 183 mDefaultClientModeManager = defaultClientModeManager; 184 mId = id; 185 mTargetRoleChangeInfo = new RoleChangeInfo(role, requestorWs, listener); 186 mBroadcastQueue = broadcastQueue; 187 enableVerboseLogging(verboseLoggingEnabled); 188 mStateMachine.sendMessage(ClientModeStateMachine.CMD_START, mTargetRoleChangeInfo); 189 } 190 getTag()191 private String getTag() { 192 return TAG + "[" + (mClientInterfaceName == null ? "unknown" : mClientInterfaceName) + "]"; 193 } 194 195 /** 196 * Sets whether to send WIFI_STATE_CHANGED broadcast for this ClientModeManager. 197 * @param enabled 198 */ setWifiStateChangeBroadcastEnabled(boolean enabled)199 public void setWifiStateChangeBroadcastEnabled(boolean enabled) { 200 mWifiStateChangeBroadcastEnabled = enabled; 201 } 202 203 /** 204 * Disconnect from any currently connected networks and stop client mode. 205 */ 206 @Override stop()207 public void stop() { 208 Log.d(getTag(), " currentstate: " + getCurrentStateName()); 209 mTargetRoleChangeInfo = null; 210 if (mIfaceIsUp) { 211 updateConnectModeState(mRole, WifiManager.WIFI_STATE_DISABLING, 212 WifiManager.WIFI_STATE_ENABLED); 213 } else { 214 updateConnectModeState(mRole, WifiManager.WIFI_STATE_DISABLING, 215 WifiManager.WIFI_STATE_ENABLING); 216 } 217 mDeferStopHandler.start(getWifiOffDeferringTimeMs()); 218 } 219 220 private class DeferStopHandler extends WifiHandler { 221 private boolean mIsDeferring = false; 222 private ImsMmTelManager mImsMmTelManager = null; 223 private Looper mLooper = null; 224 private final Runnable mRunnable = () -> continueToStopWifi(); 225 private int mMaximumDeferringTimeMillis = 0; 226 private long mDeferringStartTimeMillis = 0; 227 private ConnectivityManager mConnectivityManager = null; 228 private boolean mIsImsNetworkLost = false; 229 private boolean mIsImsNetworkUnregistered = false; 230 231 private final RegistrationManager.RegistrationCallback mImsRegistrationCallback = 232 new RegistrationManager.RegistrationCallback() { 233 @Override 234 public void onRegistered(int imsRadioTech) { 235 Log.d(getTag(), "on IMS registered on type " + imsRadioTech); 236 if (!mIsDeferring) return; 237 238 if (imsRadioTech != AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { 239 continueToStopWifi(); 240 } 241 } 242 243 @Override 244 public void onUnregistered(ImsReasonInfo imsReasonInfo) { 245 Log.d(getTag(), "on IMS unregistered"); 246 mIsImsNetworkUnregistered = true; 247 checkAndContinueToStopWifi(); 248 } 249 }; 250 251 private final class ImsNetworkCallback extends NetworkCallback { 252 private int mRegisteredImsNetworkCount = 0; 253 254 @Override onAvailable(Network network)255 public void onAvailable(Network network) { 256 synchronized (this) { 257 Log.d(getTag(), "IMS network available: " + network); 258 mRegisteredImsNetworkCount++; 259 } 260 } 261 262 @Override onLost(Network network)263 public void onLost(Network network) { 264 synchronized (this) { 265 Log.d(getTag(), "IMS network lost: " + network 266 + " ,isDeferring: " + mIsDeferring 267 + " ,registered IMS network count: " + mRegisteredImsNetworkCount); 268 mRegisteredImsNetworkCount--; 269 if (mIsDeferring && mRegisteredImsNetworkCount <= 0) { 270 mRegisteredImsNetworkCount = 0; 271 mIsImsNetworkLost = true; 272 checkAndContinueToStopWifi(); 273 } 274 } 275 } 276 } 277 278 private NetworkCallback mImsNetworkCallback = null; 279 DeferStopHandler(Looper looper)280 DeferStopHandler(Looper looper) { 281 super(TAG, looper); 282 mLooper = looper; 283 } 284 start(int delayMs)285 public void start(int delayMs) { 286 if (mIsDeferring) return; 287 288 mMaximumDeferringTimeMillis = delayMs; 289 mDeferringStartTimeMillis = mClock.getElapsedSinceBootMillis(); 290 // Most cases don't need delay, check it first to avoid unnecessary work. 291 if (delayMs == 0) { 292 continueToStopWifi(); 293 return; 294 } 295 296 mImsMmTelManager = ImsMmTelManager.createForSubscriptionId(mActiveSubId); 297 if (mImsMmTelManager == null || !postDelayed(mRunnable, delayMs)) { 298 // if no delay or failed to add runnable, stop Wifi immediately. 299 continueToStopWifi(); 300 return; 301 } 302 303 mIsDeferring = true; 304 Log.d(getTag(), "Start DeferWifiOff handler with deferring time " 305 + delayMs + " ms for subId: " + mActiveSubId); 306 try { 307 mImsMmTelManager.registerImsRegistrationCallback( 308 new HandlerExecutor(new Handler(mLooper)), 309 mImsRegistrationCallback); 310 } catch (RuntimeException | ImsException e) { 311 Log.e(getTag(), "registerImsRegistrationCallback failed", e); 312 continueToStopWifi(); 313 return; 314 } 315 316 NetworkRequest imsRequest = new NetworkRequest.Builder() 317 .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS) 318 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) 319 .build(); 320 321 mConnectivityManager = 322 (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 323 324 mImsNetworkCallback = new ImsNetworkCallback(); 325 mConnectivityManager.registerNetworkCallback(imsRequest, mImsNetworkCallback, 326 new Handler(mLooper)); 327 } 328 checkAndContinueToStopWifi()329 private void checkAndContinueToStopWifi() { 330 if (mIsImsNetworkLost && mIsImsNetworkUnregistered) { 331 // Add delay for targets where IMS PDN down at modem takes additional delay. 332 int delay = mContext.getResources() 333 .getInteger(R.integer.config_wifiDelayDisconnectOnImsLostMs); 334 if (delay == 0 || !postDelayed(mRunnable, delay)) { 335 continueToStopWifi(); 336 } 337 } 338 } 339 continueToStopWifi()340 private void continueToStopWifi() { 341 Log.d(getTag(), "The target role change info " + mTargetRoleChangeInfo); 342 343 int deferringDurationMillis = 344 (int) (mClock.getElapsedSinceBootMillis() - mDeferringStartTimeMillis); 345 boolean isTimedOut = mMaximumDeferringTimeMillis > 0 346 && deferringDurationMillis >= mMaximumDeferringTimeMillis; 347 if (mTargetRoleChangeInfo == null) { 348 Log.d(getTag(), "Continue to stop wifi"); 349 mStateMachine.captureObituaryAndQuitNow(); 350 mWifiMetrics.noteWifiOff(mIsDeferring, isTimedOut, deferringDurationMillis); 351 } else if (mTargetRoleChangeInfo.role == ROLE_CLIENT_SCAN_ONLY) { 352 if (!mWifiNative.switchClientInterfaceToScanMode( 353 mClientInterfaceName, mTargetRoleChangeInfo.requestorWs)) { 354 mModeListener.onStartFailure(ConcreteClientModeManager.this); 355 } else { 356 mStateMachine.sendMessage( 357 ClientModeStateMachine.CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE, 358 mTargetRoleChangeInfo); 359 mWifiMetrics.noteWifiOff(mIsDeferring, isTimedOut, deferringDurationMillis); 360 } 361 } else { 362 updateConnectModeState(mRole, WifiManager.WIFI_STATE_ENABLED, 363 WifiManager.WIFI_STATE_DISABLING); 364 } 365 366 if (!mIsDeferring) return; 367 368 Log.d(getTag(), "Stop DeferWifiOff handler."); 369 removeCallbacks(mRunnable); 370 if (mImsMmTelManager != null) { 371 try { 372 mImsMmTelManager.unregisterImsRegistrationCallback(mImsRegistrationCallback); 373 } catch (RuntimeException e) { 374 Log.e(getTag(), "unregisterImsRegistrationCallback failed", e); 375 } 376 } 377 378 if (mConnectivityManager != null && mImsNetworkCallback != null) { 379 mConnectivityManager.unregisterNetworkCallback(mImsNetworkCallback); 380 mImsNetworkCallback = null; 381 } 382 383 mIsDeferring = false; 384 mIsImsNetworkLost = false; 385 mIsImsNetworkUnregistered = false; 386 } 387 } 388 389 /** 390 * Get deferring time before turning off WiFi. 391 */ getWifiOffDeferringTimeMs()392 private int getWifiOffDeferringTimeMs() { 393 SubscriptionManager subscriptionManager = (SubscriptionManager) mContext.getSystemService( 394 Context.TELEPHONY_SUBSCRIPTION_SERVICE); 395 if (subscriptionManager == null) { 396 Log.d(getTag(), "SubscriptionManager not found"); 397 return 0; 398 } 399 400 List<SubscriptionInfo> subInfoList = subscriptionManager.getActiveSubscriptionInfoList(); 401 if (subInfoList == null) { 402 Log.d(getTag(), "Active SubscriptionInfo list not found"); 403 return 0; 404 } 405 406 // Get the maximum delay for the active subscription latched on IWLAN. 407 int maxDelay = 0; 408 for (SubscriptionInfo subInfo : subInfoList) { 409 int curDelay = getWifiOffDeferringTimeMs(subInfo.getSubscriptionId()); 410 if (curDelay > maxDelay) { 411 maxDelay = curDelay; 412 mActiveSubId = subInfo.getSubscriptionId(); 413 } 414 } 415 return maxDelay; 416 } 417 getWifiOffDeferringTimeMs(int subId)418 private int getWifiOffDeferringTimeMs(int subId) { 419 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 420 Log.d(getTag(), "Invalid Subscription ID: " + subId); 421 return 0; 422 } 423 424 ImsMmTelManager imsMmTelManager = ImsMmTelManager.createForSubscriptionId(subId); 425 // If no wifi calling, no delay 426 try { 427 if (!imsMmTelManager.isAvailable( 428 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 429 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN)) { 430 Log.d(getTag(), "IMS not registered over IWLAN for subId: " + subId); 431 return 0; 432 } 433 } catch (RuntimeException ex) { 434 Log.e(TAG, "IMS Manager is not available.", ex); 435 return 0; 436 } 437 438 CarrierConfigManager configManager = 439 (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 440 PersistableBundle config = configManager.getConfigForSubId(subId); 441 return (config != null) 442 ? config.getInt(CarrierConfigManager.Ims.KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT) 443 : 0; 444 } 445 446 @Override getRole()447 @Nullable public ClientRole getRole() { 448 return mRole; 449 } 450 451 @Override getPreviousRole()452 @Nullable public ClientRole getPreviousRole() { 453 return mPreviousRole; 454 } 455 456 @Override getLastRoleChangeSinceBootMs()457 public long getLastRoleChangeSinceBootMs() { 458 return mLastRoleChangeSinceBootMs; 459 } 460 461 /** 462 * Class to hold info needed for role change. 463 */ 464 private static class RoleChangeInfo { 465 @Nullable public final ClientRole role; 466 @Nullable public final WorkSource requestorWs; 467 @Nullable public final Listener<ConcreteClientModeManager> modeListener; 468 RoleChangeInfo(@ullable ClientRole role)469 RoleChangeInfo(@Nullable ClientRole role) { 470 this(role, null, null); 471 } 472 RoleChangeInfo(@ullable ClientRole role, @Nullable WorkSource requestorWs, @Nullable Listener<ConcreteClientModeManager> modeListener)473 RoleChangeInfo(@Nullable ClientRole role, @Nullable WorkSource requestorWs, 474 @Nullable Listener<ConcreteClientModeManager> modeListener) { 475 this.role = role; 476 this.requestorWs = requestorWs; 477 this.modeListener = modeListener; 478 } 479 480 @Override toString()481 public String toString() { 482 return "Role: " + role + ", RequestorWs: " + requestorWs 483 + ", ModeListener: " + modeListener; 484 } 485 } 486 487 /** Set the role of this ClientModeManager */ setRole(@onNull ClientRole role, @NonNull WorkSource requestorWs)488 public void setRole(@NonNull ClientRole role, @NonNull WorkSource requestorWs) { 489 setRole(role, requestorWs, null); 490 } 491 492 /** Set the role of this ClientModeManager */ setRole(@onNull ClientRole role, @NonNull WorkSource requestorWs, @Nullable Listener<ConcreteClientModeManager> modeListener)493 public void setRole(@NonNull ClientRole role, @NonNull WorkSource requestorWs, 494 @Nullable Listener<ConcreteClientModeManager> modeListener) { 495 mTargetRoleChangeInfo = new RoleChangeInfo(role, requestorWs, modeListener); 496 if (role == ROLE_CLIENT_SCAN_ONLY) { 497 // Switch client mode manager to scan only mode. 498 mStateMachine.sendMessage( 499 ClientModeStateMachine.CMD_SWITCH_TO_SCAN_ONLY_MODE); 500 } else { 501 // Switch client mode manager to connect mode. 502 mStateMachine.sendMessage( 503 ClientModeStateMachine.CMD_SWITCH_TO_CONNECT_MODE, 504 mTargetRoleChangeInfo); 505 } 506 } 507 508 @Override getInterfaceName()509 public String getInterfaceName() { 510 return mClientInterfaceName; 511 } 512 513 @Override getRequestorWs()514 public WorkSource getRequestorWs() { 515 return mRequestorWs; 516 } 517 518 /** 519 * Keep stopped {@link ClientModeImpl} instances so that they can be dumped to aid debugging. 520 * 521 * TODO(b/160283853): Find a smarter way to evict old ClientModeImpls 522 */ 523 private static class Graveyard { 524 private static final int INSTANCES_TO_KEEP = 3; 525 526 private final ArrayDeque<ClientModeImpl> mClientModeImpls = new ArrayDeque<>(); 527 528 /** 529 * Add this stopped {@link ClientModeImpl} to the graveyard, and evict the oldest 530 * ClientModeImpl if the graveyard is full. 531 */ inter(ClientModeImpl clientModeImpl)532 void inter(ClientModeImpl clientModeImpl) { 533 if (mClientModeImpls.size() == INSTANCES_TO_KEEP) { 534 mClientModeImpls.removeFirst(); 535 } 536 mClientModeImpls.addLast(clientModeImpl); 537 } 538 539 /** Dump the contents of the graveyard. */ dump(FileDescriptor fd, PrintWriter pw, String[] args)540 void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 541 pw.println("Dump of ConcreteClientModeManager.Graveyard"); 542 pw.println("Stopped ClientModeImpls: " + mClientModeImpls.size() + " total"); 543 for (ClientModeImpl clientModeImpl : mClientModeImpls) { 544 clientModeImpl.dump(fd, pw, args); 545 } 546 pw.println(); 547 } 548 hasAllClientModeImplsQuit()549 boolean hasAllClientModeImplsQuit() { 550 for (ClientModeImpl cmi : mClientModeImpls) { 551 if (!cmi.hasQuit()) return false; 552 } 553 return true; 554 } 555 } 556 557 /** 558 * Dump info about this ClientMode manager. 559 */ 560 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)561 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 562 pw.println("Dump of ClientModeManager id=" + mId); 563 pw.println("current StateMachine mode: " + getCurrentStateName()); 564 pw.println("mRole: " + mRole); 565 pw.println("mTargetRoleChangeInfo: " + mTargetRoleChangeInfo); 566 pw.println("mClientInterfaceName: " + mClientInterfaceName); 567 pw.println("mIfaceIsUp: " + mIfaceIsUp); 568 mStateMachine.dump(fd, pw, args); 569 pw.println(); 570 pw.println("Wi-Fi is " + syncGetWifiStateByName()); 571 if (mClientModeImpl == null) { 572 pw.println("No active ClientModeImpl instance"); 573 } else { 574 mClientModeImpl.dump(fd, pw, args); 575 } 576 mGraveyard.dump(fd, pw, args); 577 pw.println(); 578 } 579 getCurrentStateName()580 private String getCurrentStateName() { 581 IState currentState = mStateMachine.getCurrentState(); 582 583 if (currentState != null) { 584 return currentState.getName(); 585 } 586 587 return "StateMachine not active"; 588 } 589 590 /** 591 * Update Wifi state and send the broadcast. 592 * 593 * @param role Target/Set role for this client mode manager instance. 594 * @param newState new Wifi state 595 * @param currentState current wifi state 596 */ updateConnectModeState(ClientRole role, int newState, int currentState)597 private void updateConnectModeState(ClientRole role, int newState, int currentState) { 598 setWifiStateForApiCalls(newState); 599 600 if (newState == WifiManager.WIFI_STATE_UNKNOWN) { 601 // do not need to broadcast failure to system 602 return; 603 } 604 if (role != ROLE_CLIENT_PRIMARY || !mWifiStateChangeBroadcastEnabled) { 605 // do not raise public broadcast unless this is the primary client mode manager 606 return; 607 } 608 609 // TODO(b/175839153): this broadcast should only be sent out when wifi is toggled on/off, 610 // not per CMM 611 final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); 612 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 613 intent.putExtra(WifiManager.EXTRA_WIFI_STATE, newState); 614 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, currentState); 615 String summary = "broadcast=WIFI_STATE_CHANGED_ACTION" 616 + " EXTRA_WIFI_STATE=" + newState 617 + " EXTRA_PREVIOUS_WIFI_STATE=" + currentState; 618 if (mVerboseLoggingEnabled) Log.d(getTag(), "Queuing " + summary); 619 ClientModeManagerBroadcastQueue.QueuedBroadcast broadcast = 620 () -> { 621 if (mVerboseLoggingEnabled) Log.d(getTag(), "Sending " + summary); 622 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 623 }; 624 if (mRole == null && role == ROLE_CLIENT_PRIMARY) { 625 // This CMM is intended to be the primary, but has not completed the mode transition 626 // yet. Need to force broadcast to be sent. 627 broadcast.send(); 628 } else { 629 mBroadcastQueue.queueOrSendBroadcast(this, broadcast); 630 } 631 } 632 setWifiStateForApiCalls(int newState)633 private void setWifiStateForApiCalls(int newState) { 634 switch (newState) { 635 case WIFI_STATE_DISABLING: 636 case WIFI_STATE_DISABLED: 637 case WIFI_STATE_ENABLING: 638 case WIFI_STATE_ENABLED: 639 case WIFI_STATE_UNKNOWN: 640 if (mVerboseLoggingEnabled) { 641 Log.d(getTag(), "setting wifi state to: " + newState); 642 } 643 mWifiState.set(newState); 644 break; 645 default: 646 Log.d(getTag(), "attempted to set an invalid state: " + newState); 647 break; 648 } 649 } 650 syncGetWifiStateByName()651 private String syncGetWifiStateByName() { 652 switch (mWifiState.get()) { 653 case WIFI_STATE_DISABLING: 654 return "disabling"; 655 case WIFI_STATE_DISABLED: 656 return "disabled"; 657 case WIFI_STATE_ENABLING: 658 return "enabling"; 659 case WIFI_STATE_ENABLED: 660 return "enabled"; 661 case WIFI_STATE_UNKNOWN: 662 return "unknown state"; 663 default: 664 return "[invalid state]"; 665 } 666 } 667 668 private class ClientModeStateMachine extends StateMachine { 669 // Commands for the state machine. 670 public static final int CMD_START = 0; 671 public static final int CMD_SWITCH_TO_SCAN_ONLY_MODE = 1; 672 public static final int CMD_SWITCH_TO_CONNECT_MODE = 2; 673 public static final int CMD_INTERFACE_STATUS_CHANGED = 3; 674 public static final int CMD_INTERFACE_DESTROYED = 4; 675 public static final int CMD_INTERFACE_DOWN = 5; 676 public static final int CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE = 6; 677 private final State mIdleState = new IdleState(); 678 private final State mStartedState = new StartedState(); 679 private final State mScanOnlyModeState = new ScanOnlyModeState(); 680 private final State mConnectModeState = new ConnectModeState(); 681 // Workaround since we cannot use transitionTo(mScanOnlyModeState, RoleChangeInfo) 682 private RoleChangeInfo mScanRoleChangeInfoToSetOnTransition = null; 683 // Workaround since we cannot use transitionTo(mConnectModeState, RoleChangeInfo) 684 private RoleChangeInfo mConnectRoleChangeInfoToSetOnTransition = null; 685 686 @Nullable 687 private StateMachineObituary mObituary = null; 688 689 private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() { 690 @Override 691 public void onDestroyed(String ifaceName) { 692 if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) { 693 Log.d(getTag(), "STA iface " + ifaceName + " was destroyed, " 694 + "stopping client mode"); 695 696 // we must immediately clean up state in ClientModeImpl to unregister 697 // all client mode related objects 698 // Note: onDestroyed is only called from the main Wifi thread 699 if (mClientModeImpl == null) { 700 Log.w(getTag(), "Received mWifiNativeInterfaceCallback.onDestroyed " 701 + "callback when no ClientModeImpl instance is active."); 702 } else { 703 mClientModeImpl.handleIfaceDestroyed(); 704 } 705 706 sendMessage(CMD_INTERFACE_DESTROYED); 707 } 708 } 709 710 @Override 711 public void onUp(String ifaceName) { 712 if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) { 713 sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1); 714 } 715 } 716 717 @Override 718 public void onDown(String ifaceName) { 719 if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) { 720 sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0); 721 } 722 } 723 }; 724 ClientModeStateMachine(Looper looper)725 ClientModeStateMachine(Looper looper) { 726 super(TAG, looper); 727 728 // CHECKSTYLE:OFF IndentationCheck 729 addState(mIdleState); 730 addState(mStartedState, mIdleState); 731 addState(mScanOnlyModeState, mStartedState); 732 addState(mConnectModeState, mStartedState); 733 // CHECKSTYLE:ON IndentationCheck 734 735 setInitialState(mIdleState); 736 start(); 737 } 738 captureObituaryAndQuitNow()739 void captureObituaryAndQuitNow() { 740 // capture StateMachine LogRecs since we will lose them after we call quitNow() 741 // This is used for debugging. 742 mObituary = new StateMachineObituary(this); 743 744 quitNow(); 745 } 746 747 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)748 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 749 if (mObituary == null) { 750 // StateMachine hasn't quit yet, dump `this` via StateMachineObituary's dump() 751 // method for consistency with `else` branch. 752 new StateMachineObituary(this).dump(fd, pw, args); 753 } else { 754 // StateMachine has quit and cleared all LogRecs. 755 // Get them from the obituary instead. 756 mObituary.dump(fd, pw, args); 757 } 758 } 759 760 /** 761 * Reset this ConcreteClientModeManager when its role changes, so that it can be reused for 762 * another purpose. 763 */ reset()764 private void reset() { 765 // Therefore, the caller must ensure that the role change has been completed and these 766 // settings have already reset before setting them, otherwise the new setting would be 767 // lost. 768 setShouldReduceNetworkScore(false); 769 } 770 setRoleInternal(@onNull RoleChangeInfo roleChangeInfo)771 private void setRoleInternal(@NonNull RoleChangeInfo roleChangeInfo) { 772 mPreviousRole = mRole; 773 mLastRoleChangeSinceBootMs = mClock.getElapsedSinceBootMillis(); 774 mRole = roleChangeInfo.role; 775 if (roleChangeInfo.requestorWs != null) { 776 mRequestorWs = roleChangeInfo.requestorWs; 777 } 778 if (roleChangeInfo.modeListener != null) { 779 mModeListener = roleChangeInfo.modeListener; 780 } 781 } 782 setRoleInternalAndInvokeCallback(@onNull RoleChangeInfo roleChangeInfo)783 private void setRoleInternalAndInvokeCallback(@NonNull RoleChangeInfo roleChangeInfo) { 784 if (roleChangeInfo.role == mRole) return; 785 if (mRole == null) { 786 Log.v(getTag(), "ClientModeManager started in role: " + roleChangeInfo); 787 setRoleInternal(roleChangeInfo); 788 mModeListener.onStarted(ConcreteClientModeManager.this); 789 } else { 790 Log.v(getTag(), "ClientModeManager role changed: " + roleChangeInfo); 791 setRoleInternal(roleChangeInfo); 792 reset(); 793 mModeListener.onRoleChanged(ConcreteClientModeManager.this); 794 } 795 if (mClientModeImpl != null) { 796 mClientModeImpl.onRoleChanged(); 797 } 798 } 799 800 private class IdleState extends State { 801 @Override enter()802 public void enter() { 803 Log.d(getTag(), "entering IdleState"); 804 mClientInterfaceName = null; 805 mIfaceIsUp = false; 806 } 807 808 @Override exit()809 public void exit() { 810 // Sometimes the wifi handler thread may become blocked that the statemachine 811 // will exit in the IdleState without first entering StartedState. Trigger a 812 // cleanup here in case the above sequence happens. This the statemachine was 813 // started normally this will will not send a duplicate broadcast since mIsStopped 814 // will get set to false the first time the exit happens. 815 cleanupOnQuitIfApplicable(); 816 } 817 818 @Override processMessage(Message message)819 public boolean processMessage(Message message) { 820 switch (message.what) { 821 case CMD_START: 822 // Always start in scan mode first. 823 RoleChangeInfo roleChangeInfo = (RoleChangeInfo) message.obj; 824 mClientInterfaceName = mWifiNative.setupInterfaceForClientInScanMode( 825 mWifiNativeInterfaceCallback, roleChangeInfo.requestorWs); 826 if (TextUtils.isEmpty(mClientInterfaceName)) { 827 Log.e(getTag(), "Failed to create ClientInterface. Sit in Idle"); 828 mModeListener.onStartFailure(ConcreteClientModeManager.this); 829 break; 830 } 831 if (roleChangeInfo.role instanceof ClientConnectivityRole) { 832 sendMessage(CMD_SWITCH_TO_CONNECT_MODE, roleChangeInfo); 833 transitionTo(mStartedState); 834 } else { 835 mScanRoleChangeInfoToSetOnTransition = roleChangeInfo; 836 transitionTo(mScanOnlyModeState); 837 } 838 break; 839 default: 840 Log.d(getTag(), "received an invalid message: " + message); 841 return NOT_HANDLED; 842 } 843 return HANDLED; 844 } 845 } 846 847 private class StartedState extends State { 848 onUpChanged(boolean isUp)849 private void onUpChanged(boolean isUp) { 850 if (isUp == mIfaceIsUp) { 851 return; // no change 852 } 853 mIfaceIsUp = isUp; 854 if (!isUp) { 855 // if the interface goes down we should exit and go back to idle state. 856 Log.d(getTag(), "interface down!"); 857 mStateMachine.sendMessage(CMD_INTERFACE_DOWN); 858 } 859 } 860 861 @Override enter()862 public void enter() { 863 Log.d(getTag(), "entering StartedState"); 864 mIfaceIsUp = false; 865 mIsStopped = false; 866 onUpChanged(mWifiNative.isInterfaceUp(mClientInterfaceName)); 867 } 868 869 @Override processMessage(Message message)870 public boolean processMessage(Message message) { 871 switch (message.what) { 872 case CMD_START: 873 // Already started, ignore this command. 874 break; 875 case CMD_SWITCH_TO_CONNECT_MODE: { 876 RoleChangeInfo roleChangeInfo = (RoleChangeInfo) message.obj; 877 updateConnectModeState(roleChangeInfo.role, 878 WifiManager.WIFI_STATE_ENABLING, 879 WifiManager.WIFI_STATE_DISABLED); 880 if (!mWifiNative.switchClientInterfaceToConnectivityMode( 881 mClientInterfaceName, roleChangeInfo.requestorWs)) { 882 updateConnectModeState(roleChangeInfo.role, 883 WifiManager.WIFI_STATE_UNKNOWN, 884 WifiManager.WIFI_STATE_ENABLING); 885 updateConnectModeState(roleChangeInfo.role, 886 WifiManager.WIFI_STATE_DISABLED, 887 WifiManager.WIFI_STATE_UNKNOWN); 888 mModeListener.onStartFailure(ConcreteClientModeManager.this); 889 break; 890 } 891 // Role set in the enter of ConnectModeState. 892 mConnectRoleChangeInfoToSetOnTransition = roleChangeInfo; 893 transitionTo(mConnectModeState); 894 break; 895 } 896 case CMD_SWITCH_TO_SCAN_ONLY_MODE: 897 updateConnectModeState(mRole, WifiManager.WIFI_STATE_DISABLING, 898 WifiManager.WIFI_STATE_ENABLED); 899 mDeferStopHandler.start(getWifiOffDeferringTimeMs()); 900 break; 901 case CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE: { 902 RoleChangeInfo roleChangeInfo = (RoleChangeInfo) message.obj; 903 mScanRoleChangeInfoToSetOnTransition = roleChangeInfo; 904 transitionTo(mScanOnlyModeState); 905 break; 906 } 907 case CMD_INTERFACE_DOWN: 908 Log.e(getTag(), "Detected an interface down, reporting failure to " 909 + "SelfRecovery"); 910 mSelfRecovery.trigger(SelfRecovery.REASON_STA_IFACE_DOWN); 911 // once interface down, nothing else to do... stop the state machine 912 captureObituaryAndQuitNow(); 913 break; 914 case CMD_INTERFACE_STATUS_CHANGED: 915 boolean isUp = message.arg1 == 1; 916 onUpChanged(isUp); 917 break; 918 case CMD_INTERFACE_DESTROYED: 919 Log.e(getTag(), "interface destroyed - client mode stopping"); 920 mClientInterfaceName = null; 921 // once interface destroyed, nothing else to do... stop the state machine 922 captureObituaryAndQuitNow(); 923 break; 924 default: 925 return NOT_HANDLED; 926 } 927 return HANDLED; 928 } 929 930 /** 931 * Clean up state, unregister listeners and update wifi state. 932 */ 933 @Override exit()934 public void exit() { 935 if (mClientInterfaceName != null) { 936 mWifiNative.teardownInterface(mClientInterfaceName); 937 mClientInterfaceName = null; 938 mIfaceIsUp = false; 939 } 940 941 Log.i(getTag(), "StartedState#exit(), setting mRole = null"); 942 mIsStopped = true; 943 cleanupOnQuitIfApplicable(); 944 } 945 } 946 947 private class ScanOnlyModeState extends State { 948 @Override enter()949 public void enter() { 950 Log.d(getTag(), "entering ScanOnlyModeState"); 951 952 if (mClientInterfaceName != null) { 953 mScanOnlyModeImpl = mWifiInjector.makeScanOnlyModeImpl( 954 mClientInterfaceName); 955 } else { 956 Log.e(getTag(), "Entered ScanOnlyModeState with a null interface name!"); 957 } 958 959 if (mScanRoleChangeInfoToSetOnTransition == null 960 || (mScanRoleChangeInfoToSetOnTransition.role != ROLE_CLIENT_SCAN_ONLY)) { 961 Log.wtf(TAG, "Unexpected mScanRoleChangeInfoToSetOnTransition: " 962 + mScanRoleChangeInfoToSetOnTransition); 963 // Should never happen, but fallback to scan only to avoid a crash. 964 mScanRoleChangeInfoToSetOnTransition = 965 new RoleChangeInfo(ROLE_CLIENT_SCAN_ONLY); 966 } 967 968 setRoleInternalAndInvokeCallback(mScanRoleChangeInfoToSetOnTransition); 969 // If we're in ScanOnlyModeState, there is only 1 CMM. So it's ok to call 970 // WakeupController directly, there won't be multiple CMMs trampling over each other 971 mWakeupController.start(); 972 mWifiNative.setScanMode(mClientInterfaceName, true); 973 } 974 975 @Override processMessage(Message message)976 public boolean processMessage(Message message) { 977 switch (message.what) { 978 case CMD_SWITCH_TO_SCAN_ONLY_MODE: 979 // Already in scan only mode, ignore this command. 980 break; 981 default: 982 return NOT_HANDLED; 983 } 984 return HANDLED; 985 } 986 987 @Override exit()988 public void exit() { 989 mScanOnlyModeImpl = null; 990 mScanRoleChangeInfoToSetOnTransition = null; 991 992 // If we're in ScanOnlyModeState, there is only 1 CMM. So it's ok to call 993 // WakeupController directly, there won't be multiple CMMs trampling over each other 994 mWakeupController.stop(); 995 mWifiNative.setScanMode(mClientInterfaceName, false); 996 } 997 } 998 999 private class ConnectModeState extends State { 1000 @Override enter()1001 public void enter() { 1002 Log.d(getTag(), "entering ConnectModeState, starting ClientModeImpl"); 1003 if (mClientInterfaceName == null) { 1004 Log.e(getTag(), "Supposed to start ClientModeImpl, but iface is null!"); 1005 } else { 1006 if (mClientModeImpl != null) { 1007 Log.e(getTag(), "ConnectModeState.enter(): mClientModeImpl is already " 1008 + "instantiated?!"); 1009 } 1010 mClientModeImpl = mWifiInjector.makeClientModeImpl( 1011 mClientInterfaceName, ConcreteClientModeManager.this, 1012 mVerboseLoggingEnabled); 1013 mClientModeImpl.setShouldReduceNetworkScore(mShouldReduceNetworkScore); 1014 } 1015 if (mConnectRoleChangeInfoToSetOnTransition == null 1016 || !(mConnectRoleChangeInfoToSetOnTransition.role 1017 instanceof ClientConnectivityRole)) { 1018 Log.wtf(TAG, "Unexpected mConnectRoleChangeInfoToSetOnTransition: " 1019 + mConnectRoleChangeInfoToSetOnTransition); 1020 // Should never happen, but fallback to primary to avoid a crash. 1021 mConnectRoleChangeInfoToSetOnTransition = 1022 new RoleChangeInfo(ROLE_CLIENT_PRIMARY); 1023 } 1024 1025 // Could be any one of possible connect mode roles. 1026 setRoleInternalAndInvokeCallback(mConnectRoleChangeInfoToSetOnTransition); 1027 updateConnectModeState(mConnectRoleChangeInfoToSetOnTransition.role, 1028 WIFI_STATE_ENABLED, WIFI_STATE_ENABLING); 1029 } 1030 1031 @Override processMessage(Message message)1032 public boolean processMessage(Message message) { 1033 switch (message.what) { 1034 case CMD_SWITCH_TO_CONNECT_MODE: 1035 RoleChangeInfo roleChangeInfo = (RoleChangeInfo) message.obj; 1036 // switching to connect mode when already in connect mode, just update the 1037 // requestor WorkSource. 1038 boolean success = mWifiNative.replaceStaIfaceRequestorWs( 1039 mClientInterfaceName, roleChangeInfo.requestorWs); 1040 if (success) { 1041 setRoleInternalAndInvokeCallback(roleChangeInfo); 1042 } else { 1043 // If this call failed, the iface would be torn down. 1044 // Thus, simply abort and let the iface down handling take care of the 1045 // rest. 1046 Log.e(getTag(), "Failed to switch ClientModeManager=" 1047 + ConcreteClientModeManager.this + "'s requestorWs"); 1048 } 1049 break; 1050 case CMD_SWITCH_TO_SCAN_ONLY_MODE: 1051 case CMD_INTERFACE_DESTROYED: 1052 updateConnectModeState(mRole, WifiManager.WIFI_STATE_DISABLING, 1053 WifiManager.WIFI_STATE_ENABLED); 1054 return NOT_HANDLED; // Handled in StartedState. 1055 case CMD_INTERFACE_DOWN: 1056 updateConnectModeState(mRole, WifiManager.WIFI_STATE_DISABLING, 1057 WifiManager.WIFI_STATE_UNKNOWN); 1058 return NOT_HANDLED; // Handled in StartedState. 1059 case CMD_INTERFACE_STATUS_CHANGED: 1060 boolean isUp = message.arg1 == 1; 1061 if (isUp == mIfaceIsUp) { 1062 break; // no change 1063 } 1064 if (!isUp) { 1065 if (mWifiGlobals.isConnectedMacRandomizationEnabled() 1066 && getClientMode().isConnecting()) { 1067 return HANDLED; // For MAC randomization, ignore... 1068 } else { 1069 // Handle the error case where our underlying interface went down if 1070 // we do not have mac randomization enabled (b/72459123). 1071 // if the interface goes down we should exit and go back to idle 1072 // state. 1073 updateConnectModeState(mRole, WifiManager.WIFI_STATE_UNKNOWN, 1074 WifiManager.WIFI_STATE_ENABLED); 1075 } 1076 } 1077 return NOT_HANDLED; // Handled in StartedState. 1078 default: 1079 return NOT_HANDLED; 1080 } 1081 return HANDLED; 1082 } 1083 1084 @Override exit()1085 public void exit() { 1086 updateConnectModeState(mRole, WifiManager.WIFI_STATE_DISABLED, 1087 WifiManager.WIFI_STATE_DISABLING); 1088 1089 if (mClientModeImpl == null) { 1090 Log.w(getTag(), "ConnectModeState.exit(): mClientModeImpl is already null?!"); 1091 } else { 1092 Log.d(getTag(), "Stopping ClientModeImpl"); 1093 mClientModeImpl.stop(); 1094 mGraveyard.inter(mClientModeImpl); 1095 mClientModeImpl = null; 1096 } 1097 1098 mConnectRoleChangeInfoToSetOnTransition = null; 1099 } 1100 } 1101 } 1102 1103 /** Called by a ClientModeImpl owned by this CMM informing it has fully stopped. */ onClientModeImplQuit()1104 public void onClientModeImplQuit() { 1105 cleanupOnQuitIfApplicable(); 1106 } 1107 1108 /** 1109 * Only clean up this CMM once the CMM and all associated ClientModeImpls have been stopped. 1110 * This is necessary because ClientModeImpl sends broadcasts during stop, and the role must 1111 * remain primary for {@link ClientModeManagerBroadcastQueue} to send them out. 1112 */ cleanupOnQuitIfApplicable()1113 private void cleanupOnQuitIfApplicable() { 1114 if (mIsStopped && mGraveyard.hasAllClientModeImplsQuit()) { 1115 mPreviousRole = mRole; 1116 mLastRoleChangeSinceBootMs = mClock.getElapsedSinceBootMillis(); 1117 mRole = null; 1118 // only call onStopped() after role has been reset to null since ActiveModeWarden 1119 // expects the CMM to be fully stopped before onStopped(). 1120 mModeListener.onStopped(ConcreteClientModeManager.this); 1121 1122 // reset to false so that onStopped() won't be triggered again. 1123 mIsStopped = false; 1124 } 1125 } 1126 1127 @Override syncGetWifiState()1128 public int syncGetWifiState() { 1129 return mWifiState.get(); 1130 } 1131 1132 @NonNull getClientMode()1133 private ClientMode getClientMode() { 1134 if (mClientModeImpl != null) { 1135 return mClientModeImpl; 1136 } 1137 if (mScanOnlyModeImpl != null) { 1138 return mScanOnlyModeImpl; 1139 } 1140 return mDefaultClientModeManager; 1141 } 1142 1143 /* 1144 * Note: These are simple wrappers over methods to {@link ClientModeImpl}. 1145 */ 1146 1147 @Override connectNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper, int callingUid)1148 public void connectNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper, 1149 int callingUid) { 1150 getClientMode().connectNetwork(result, wrapper, callingUid); 1151 } 1152 1153 @Override saveNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper, int callingUid)1154 public void saveNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper, 1155 int callingUid) { 1156 getClientMode().saveNetwork(result, wrapper, callingUid); 1157 } 1158 1159 @Override disconnect()1160 public void disconnect() { 1161 getClientMode().disconnect(); 1162 } 1163 1164 @Override reconnect(WorkSource ws)1165 public void reconnect(WorkSource ws) { 1166 getClientMode().reconnect(ws); 1167 } 1168 1169 @Override reassociate()1170 public void reassociate() { 1171 getClientMode().reassociate(); 1172 } 1173 1174 @Override startConnectToNetwork(int networkId, int uid, String bssid)1175 public void startConnectToNetwork(int networkId, int uid, String bssid) { 1176 getClientMode().startConnectToNetwork(networkId, uid, bssid); 1177 } 1178 1179 @Override startRoamToNetwork(int networkId, String bssid)1180 public void startRoamToNetwork(int networkId, String bssid) { 1181 getClientMode().startRoamToNetwork(networkId, bssid); 1182 } 1183 1184 @Override setWifiConnectedNetworkScorer( IBinder binder, IWifiConnectedNetworkScorer scorer)1185 public boolean setWifiConnectedNetworkScorer( 1186 IBinder binder, IWifiConnectedNetworkScorer scorer) { 1187 return getClientMode().setWifiConnectedNetworkScorer(binder, scorer); 1188 } 1189 1190 @Override clearWifiConnectedNetworkScorer()1191 public void clearWifiConnectedNetworkScorer() { 1192 getClientMode().clearWifiConnectedNetworkScorer(); 1193 } 1194 1195 @Override resetSimAuthNetworks(@lientModeImpl.ResetSimReason int resetReason)1196 public void resetSimAuthNetworks(@ClientModeImpl.ResetSimReason int resetReason) { 1197 getClientMode().resetSimAuthNetworks(resetReason); 1198 } 1199 1200 @Override onBluetoothConnectionStateChanged()1201 public void onBluetoothConnectionStateChanged() { 1202 getClientMode().onBluetoothConnectionStateChanged(); 1203 } 1204 1205 @Override syncRequestConnectionInfo()1206 public WifiInfo syncRequestConnectionInfo() { 1207 return getClientMode().syncRequestConnectionInfo(); 1208 } 1209 1210 @Override syncQueryPasspointIcon(long bssid, String fileName)1211 public boolean syncQueryPasspointIcon(long bssid, String fileName) { 1212 return getClientMode().syncQueryPasspointIcon(bssid, fileName); 1213 } 1214 1215 @Override syncGetCurrentNetwork()1216 public Network syncGetCurrentNetwork() { 1217 return getClientMode().syncGetCurrentNetwork(); 1218 } 1219 1220 @Override syncGetDhcpResultsParcelable()1221 public DhcpResultsParcelable syncGetDhcpResultsParcelable() { 1222 return getClientMode().syncGetDhcpResultsParcelable(); 1223 } 1224 1225 @Override getSupportedFeatures()1226 public long getSupportedFeatures() { 1227 return getClientMode().getSupportedFeatures(); 1228 } 1229 1230 @Override syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider, IProvisioningCallback callback)1231 public boolean syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider, 1232 IProvisioningCallback callback) { 1233 return getClientMode().syncStartSubscriptionProvisioning( 1234 callingUid, provider, callback); 1235 } 1236 1237 @Override isWifiStandardSupported(@ifiAnnotations.WifiStandard int standard)1238 public boolean isWifiStandardSupported(@WifiAnnotations.WifiStandard int standard) { 1239 return getClientMode().isWifiStandardSupported(standard); 1240 } 1241 1242 @Override enableTdls(String remoteMacAddress, boolean enable)1243 public void enableTdls(String remoteMacAddress, boolean enable) { 1244 getClientMode().enableTdls(remoteMacAddress, enable); 1245 } 1246 1247 @Override dumpIpClient(FileDescriptor fd, PrintWriter pw, String[] args)1248 public void dumpIpClient(FileDescriptor fd, PrintWriter pw, String[] args) { 1249 getClientMode().dumpIpClient(fd, pw, args); 1250 } 1251 1252 @Override dumpWifiScoreReport(FileDescriptor fd, PrintWriter pw, String[] args)1253 public void dumpWifiScoreReport(FileDescriptor fd, PrintWriter pw, String[] args) { 1254 getClientMode().dumpWifiScoreReport(fd, pw, args); 1255 } 1256 1257 @Override enableVerboseLogging(boolean verbose)1258 public void enableVerboseLogging(boolean verbose) { 1259 mVerboseLoggingEnabled = verbose; 1260 getClientMode().enableVerboseLogging(verbose); 1261 } 1262 1263 @Override getFactoryMacAddress()1264 public String getFactoryMacAddress() { 1265 return getClientMode().getFactoryMacAddress(); 1266 } 1267 1268 @Override getConnectedWifiConfiguration()1269 public WifiConfiguration getConnectedWifiConfiguration() { 1270 return getClientMode().getConnectedWifiConfiguration(); 1271 } 1272 1273 @Override getConnectingWifiConfiguration()1274 public WifiConfiguration getConnectingWifiConfiguration() { 1275 return getClientMode().getConnectingWifiConfiguration(); 1276 } 1277 1278 @Override getConnectedBssid()1279 public String getConnectedBssid() { 1280 return getClientMode().getConnectedBssid(); 1281 } 1282 1283 @Override getConnectingBssid()1284 public String getConnectingBssid() { 1285 return getClientMode().getConnectingBssid(); 1286 } 1287 1288 @Override getWifiLinkLayerStats()1289 public WifiLinkLayerStats getWifiLinkLayerStats() { 1290 return getClientMode().getWifiLinkLayerStats(); 1291 } 1292 1293 @Override setPowerSave(boolean ps)1294 public boolean setPowerSave(boolean ps) { 1295 return getClientMode().setPowerSave(ps); 1296 } 1297 1298 @Override setLowLatencyMode(boolean enabled)1299 public boolean setLowLatencyMode(boolean enabled) { 1300 return getClientMode().setLowLatencyMode(enabled); 1301 } 1302 1303 @Override getMcastLockManagerFilterController()1304 public WifiMulticastLockManager.FilterController getMcastLockManagerFilterController() { 1305 return getClientMode().getMcastLockManagerFilterController(); 1306 } 1307 1308 @Override isConnected()1309 public boolean isConnected() { 1310 return getClientMode().isConnected(); 1311 } 1312 1313 @Override isConnecting()1314 public boolean isConnecting() { 1315 return getClientMode().isConnecting(); 1316 } 1317 1318 @Override isRoaming()1319 public boolean isRoaming() { 1320 return getClientMode().isRoaming(); 1321 } 1322 1323 @Override isDisconnected()1324 public boolean isDisconnected() { 1325 return getClientMode().isDisconnected(); 1326 } 1327 1328 @Override isSupplicantTransientState()1329 public boolean isSupplicantTransientState() { 1330 return getClientMode().isSupplicantTransientState(); 1331 } 1332 1333 @Override onCellularConnectivityChanged(@ifiDataStall.CellularDataStatusCode int status)1334 public void onCellularConnectivityChanged(@WifiDataStall.CellularDataStatusCode int status) { 1335 getClientMode().onCellularConnectivityChanged(status); 1336 } 1337 1338 @Override probeLink(LinkProbeCallback callback, int mcs)1339 public void probeLink(LinkProbeCallback callback, int mcs) { 1340 getClientMode().probeLink(callback, mcs); 1341 } 1342 1343 @Override sendMessageToClientModeImpl(Message msg)1344 public void sendMessageToClientModeImpl(Message msg) { 1345 getClientMode().sendMessageToClientModeImpl(msg); 1346 } 1347 1348 @Override getId()1349 public long getId() { 1350 return mId; 1351 } 1352 1353 @Override setMboCellularDataStatus(boolean available)1354 public void setMboCellularDataStatus(boolean available) { 1355 getClientMode().setMboCellularDataStatus(available); 1356 } 1357 1358 @Override getRoamingCapabilities()1359 public WifiNative.RoamingCapabilities getRoamingCapabilities() { 1360 return getClientMode().getRoamingCapabilities(); 1361 } 1362 1363 @Override configureRoaming(WifiNative.RoamingConfig config)1364 public boolean configureRoaming(WifiNative.RoamingConfig config) { 1365 return getClientMode().configureRoaming(config); 1366 } 1367 1368 @Override enableRoaming(boolean enabled)1369 public boolean enableRoaming(boolean enabled) { 1370 return getClientMode().enableRoaming(enabled); 1371 } 1372 1373 @Override setCountryCode(String countryCode)1374 public boolean setCountryCode(String countryCode) { 1375 return getClientMode().setCountryCode(countryCode); 1376 } 1377 1378 @Override getTxPktFates()1379 public List<TxFateReport> getTxPktFates() { 1380 return getClientMode().getTxPktFates(); 1381 } 1382 1383 @Override getRxPktFates()1384 public List<RxFateReport> getRxPktFates() { 1385 return getClientMode().getRxPktFates(); 1386 } 1387 1388 @Override getDeviceWiphyCapabilities()1389 public DeviceWiphyCapabilities getDeviceWiphyCapabilities() { 1390 return getClientMode().getDeviceWiphyCapabilities(); 1391 } 1392 1393 @Override requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes)1394 public boolean requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes) { 1395 return getClientMode().requestAnqp(bssid, anqpIds, hs20Subtypes); 1396 } 1397 1398 @Override requestVenueUrlAnqp(String bssid)1399 public boolean requestVenueUrlAnqp(String bssid) { 1400 return getClientMode().requestVenueUrlAnqp(bssid); 1401 } 1402 1403 @Override requestIcon(String bssid, String fileName)1404 public boolean requestIcon(String bssid, String fileName) { 1405 return getClientMode().requestIcon(bssid, fileName); 1406 } 1407 1408 @Override setShouldReduceNetworkScore(boolean shouldReduceNetworkScore)1409 public void setShouldReduceNetworkScore(boolean shouldReduceNetworkScore) { 1410 mShouldReduceNetworkScore = shouldReduceNetworkScore; 1411 getClientMode().setShouldReduceNetworkScore(shouldReduceNetworkScore); 1412 } 1413 1414 @Override toString()1415 public String toString() { 1416 return "ConcreteClientModeManager{id=" + getId() 1417 + " iface=" + getInterfaceName() 1418 + " role=" + getRole() 1419 + "}"; 1420 } 1421 } 1422