1 /* 2 * Copyright (C) 2017 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.NetworkCapabilities.NET_CAPABILITY_INTERNET; 20 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID; 21 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; 22 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; 23 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 24 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED; 25 import static android.net.wifi.WifiManager.ACTION_REMOVE_SUGGESTION_DISCONNECT; 26 import static android.net.wifi.WifiManager.ACTION_REMOVE_SUGGESTION_LINGER; 27 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED; 28 import static android.net.wifi.WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED; 29 import static android.net.wifi.WifiManager.VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY; 30 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; 31 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; 32 33 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP; 34 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE; 35 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_NAN; 36 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_P2P; 37 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA; 38 import static com.android.server.wifi.SelfRecovery.REASON_API_CALL; 39 40 import android.content.BroadcastReceiver; 41 import android.content.Context; 42 import android.content.Intent; 43 import android.content.IntentFilter; 44 import android.hardware.display.DisplayManager; 45 import android.location.Location; 46 import android.location.LocationManager; 47 import android.net.ConnectivityManager; 48 import android.net.MacAddress; 49 import android.net.Network; 50 import android.net.NetworkCapabilities; 51 import android.net.NetworkRequest; 52 import android.net.wifi.IActionListener; 53 import android.net.wifi.IDppCallback; 54 import android.net.wifi.ILastCallerListener; 55 import android.net.wifi.ILocalOnlyHotspotCallback; 56 import android.net.wifi.IPnoScanResultsCallback; 57 import android.net.wifi.IScoreUpdateObserver; 58 import android.net.wifi.ISoftApCallback; 59 import android.net.wifi.IWifiConnectedNetworkScorer; 60 import android.net.wifi.ScanResult; 61 import android.net.wifi.SoftApCapability; 62 import android.net.wifi.SoftApConfiguration; 63 import android.net.wifi.SoftApInfo; 64 import android.net.wifi.SoftApState; 65 import android.net.wifi.SupplicantState; 66 import android.net.wifi.WifiAvailableChannel; 67 import android.net.wifi.WifiClient; 68 import android.net.wifi.WifiConfiguration; 69 import android.net.wifi.WifiConnectedSessionInfo; 70 import android.net.wifi.WifiContext; 71 import android.net.wifi.WifiInfo; 72 import android.net.wifi.WifiManager; 73 import android.net.wifi.WifiNetworkSelectionConfig; 74 import android.net.wifi.WifiNetworkSpecifier; 75 import android.net.wifi.WifiNetworkSuggestion; 76 import android.net.wifi.WifiScanner; 77 import android.net.wifi.WifiSsid; 78 import android.net.wifi.util.ScanResultUtil; 79 import android.net.wifi.util.WifiResourceCache; 80 import android.os.Binder; 81 import android.os.Build; 82 import android.os.Bundle; 83 import android.os.PatternMatcher; 84 import android.os.Process; 85 import android.os.RemoteException; 86 import android.os.SystemClock; 87 import android.os.WorkSource; 88 import android.telephony.Annotation; 89 import android.telephony.PhysicalChannelConfig; 90 import android.telephony.SubscriptionManager; 91 import android.telephony.TelephonyManager; 92 import android.text.TextUtils; 93 import android.util.Log; 94 import android.util.Pair; 95 import android.util.SparseArray; 96 import android.util.SparseIntArray; 97 import android.view.Display; 98 99 import androidx.annotation.NonNull; 100 import androidx.annotation.Nullable; 101 import androidx.annotation.RequiresApi; 102 103 import com.android.internal.annotations.VisibleForTesting; 104 import com.android.modules.utils.BasicShellCommandHandler; 105 import com.android.modules.utils.ParceledListSlice; 106 import com.android.modules.utils.build.SdkLevel; 107 import com.android.server.wifi.ClientMode.LinkProbeCallback; 108 import com.android.server.wifi.coex.CoexManager; 109 import com.android.server.wifi.coex.CoexUtils; 110 import com.android.server.wifi.hal.WifiChip; 111 import com.android.server.wifi.hotspot2.NetworkDetail; 112 import com.android.server.wifi.util.ApConfigUtil; 113 import com.android.server.wifi.util.ArrayUtils; 114 115 import libcore.util.HexEncoding; 116 117 import java.io.PrintWriter; 118 import java.nio.charset.Charset; 119 import java.nio.charset.StandardCharsets; 120 import java.util.ArrayList; 121 import java.util.Arrays; 122 import java.util.Collection; 123 import java.util.Collections; 124 import java.util.Comparator; 125 import java.util.HashMap; 126 import java.util.List; 127 import java.util.Map; 128 import java.util.Set; 129 import java.util.concurrent.ArrayBlockingQueue; 130 import java.util.concurrent.ConcurrentHashMap; 131 import java.util.concurrent.CountDownLatch; 132 import java.util.concurrent.TimeUnit; 133 import java.util.stream.Collectors; 134 135 /** 136 * Interprets and executes 'adb shell cmd wifi [args]'. 137 * 138 * To add new commands: 139 * - onCommand: Add a case "<command>" execute. Return a 0 140 * if command executed successfully. 141 * - onHelp: add a description string. 142 * 143 * Permissions: currently root permission is required for some commands. Others will 144 * enforce the corresponding API permissions. 145 */ 146 public class WifiShellCommand extends BasicShellCommandHandler { 147 @VisibleForTesting 148 public static String SHELL_PACKAGE_NAME = "com.android.shell"; 149 150 // These don't require root access. 151 // However, these do perform permission checks in the corresponding WifiService methods. 152 private static final String[] NON_PRIVILEGED_COMMANDS = { 153 "add-suggestion", 154 "forget-network", 155 "connect-network", 156 "add-network", 157 "get-country-code", 158 "help", 159 "-h", 160 "is-verbose-logging", 161 "list-scan-results", 162 "list-networks", 163 "list-suggestions", 164 "remove-suggestion", 165 "remove-all-suggestions", 166 "reset-connected-score", 167 "set-connected-score", 168 "set-scan-always-available", 169 "set-verbose-logging", 170 "set-wifi-enabled", 171 "set-passpoint-enabled", 172 "set-multi-internet-state", 173 "start-scan", 174 "status", 175 "query-interface", 176 "interface-priority-interactive-mode", 177 "set-one-shot-screen-on-delay-ms", 178 "set-network-selection-config", 179 "set-ipreach-disconnect", 180 "get-ipreach-disconnect", 181 "take-bugreport", 182 "get-allowed-channel", 183 "set-mock-wifimodem-service", 184 "get-mock-wifimodem-service", 185 "set-mock-wifimodem-methods", 186 "force-overlay-config-value", 187 "get-softap-supported-features", 188 "get-overlay-config-values" 189 }; 190 191 private static final Map<String, Pair<NetworkRequest, ConnectivityManager.NetworkCallback>> 192 sActiveRequests = new ConcurrentHashMap<>(); 193 194 private final ActiveModeWarden mActiveModeWarden; 195 private final WifiGlobals mWifiGlobals; 196 private final WifiLockManager mWifiLockManager; 197 private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; 198 private final WifiConfigManager mWifiConfigManager; 199 private final WifiNative mWifiNative; 200 private final CoexManager mCoexManager; 201 private final WifiCountryCode mWifiCountryCode; 202 private final WifiLastResortWatchdog mWifiLastResortWatchdog; 203 private final WifiServiceImpl mWifiService; 204 private final WifiContext mContext; 205 private final ConnectivityManager mConnectivityManager; 206 private final WifiCarrierInfoManager mWifiCarrierInfoManager; 207 private final WifiNetworkFactory mWifiNetworkFactory; 208 private final SelfRecovery mSelfRecovery; 209 private final WifiThreadRunner mWifiThreadRunner; 210 private final WifiApConfigStore mWifiApConfigStore; 211 private int mSapState = WifiManager.WIFI_STATE_UNKNOWN; 212 private final ScanRequestProxy mScanRequestProxy; 213 private final @NonNull WifiDialogManager mWifiDialogManager; 214 private final HalDeviceManager mHalDeviceManager; 215 private final InterfaceConflictManager mInterfaceConflictManager; 216 private final SsidTranslator mSsidTranslator; 217 private final WifiDiagnostics mWifiDiagnostics; 218 private final DeviceConfigFacade mDeviceConfig; 219 private final AfcManager mAfcManager; 220 private final WifiInjector mWifiInjector; 221 private static final int[] OP_MODE_LIST = { 222 WifiAvailableChannel.OP_MODE_STA, 223 WifiAvailableChannel.OP_MODE_SAP, 224 WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI, 225 WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO, 226 WifiAvailableChannel.OP_MODE_WIFI_AWARE, 227 WifiAvailableChannel.OP_MODE_TDLS, 228 }; 229 230 private class SoftApCallbackProxy extends ISoftApCallback.Stub { 231 private final PrintWriter mPrintWriter; 232 private final CountDownLatch mCountDownLatch; 233 SoftApCallbackProxy(PrintWriter printWriter, CountDownLatch countDownLatch)234 SoftApCallbackProxy(PrintWriter printWriter, CountDownLatch countDownLatch) { 235 mPrintWriter = printWriter; 236 mCountDownLatch = countDownLatch; 237 } 238 239 @Override onStateChanged(SoftApState state)240 public void onStateChanged(SoftApState state) { 241 mPrintWriter.println("onStateChanged with state: " + state); 242 243 mSapState = state.getState(); 244 if (mSapState == WifiManager.WIFI_AP_STATE_ENABLED) { 245 mPrintWriter.println(" SAP is enabled successfully"); 246 // Skip countDown() and wait for onInfoChanged() which has 247 // the confirmed softAp channel information 248 } else if (mSapState == WifiManager.WIFI_AP_STATE_DISABLED) { 249 mPrintWriter.println(" SAP is disabled"); 250 } else if (mSapState == WifiManager.WIFI_AP_STATE_FAILED) { 251 mPrintWriter.println(" SAP failed to start"); 252 mCountDownLatch.countDown(); 253 } 254 } 255 256 @Override onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration)257 public void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, 258 Map<String, List<WifiClient>> clients, boolean isBridged, 259 boolean isRegistration) { 260 mPrintWriter.println("onConnectedClientsOrInfoChanged, infos: " + infos 261 + ", clients: " + clients + ", isBridged: " + isBridged); 262 if (mSapState == WifiManager.WIFI_AP_STATE_ENABLED && infos.size() != 0) { 263 mCountDownLatch.countDown(); 264 } 265 } 266 267 @Override onCapabilityChanged(SoftApCapability capability)268 public void onCapabilityChanged(SoftApCapability capability) { 269 mPrintWriter.println("onCapabilityChanged " + capability); 270 } 271 272 @Override onBlockedClientConnecting(WifiClient client, int reason)273 public void onBlockedClientConnecting(WifiClient client, int reason) { 274 } 275 } 276 277 /** 278 * Used for shell command testing of DPP feature. 279 */ 280 public static class DppCallbackProxy extends IDppCallback.Stub { 281 private final PrintWriter mPrintWriter; 282 private final CountDownLatch mCountDownLatch; 283 private static final int STATUS_SUCCESS = 0; 284 private static final int STATUS_PROGRESS = 1; 285 private static final int STATUS_FAILURE = 2; 286 DppCallbackProxy(PrintWriter printWriter, CountDownLatch countDownLatch)287 DppCallbackProxy(PrintWriter printWriter, CountDownLatch countDownLatch) { 288 mPrintWriter = printWriter; 289 mCountDownLatch = countDownLatch; 290 } 291 292 @Override onSuccessConfigReceived(int networkId)293 public void onSuccessConfigReceived(int networkId) { 294 mPrintWriter.println("onSuccessConfigReceived. netId=" + networkId); 295 mCountDownLatch.countDown(); 296 } 297 298 @Override onSuccess(int status)299 public void onSuccess(int status) { 300 mPrintWriter.println("onSuccess status=" + statusToString(STATUS_SUCCESS, status)); 301 mCountDownLatch.countDown(); 302 } 303 304 @Override onFailure(int status, String ssid, String channelList, int[] bandArray)305 public void onFailure(int status, String ssid, String channelList, int[] bandArray) { 306 mPrintWriter.println("onFailure. status=" + statusToString(STATUS_FAILURE, status) 307 + "ssid=" + ssid + "channelList=" + channelList); 308 mCountDownLatch.countDown(); 309 } 310 311 @Override onProgress(int status)312 public void onProgress(int status) { 313 mPrintWriter.println("onProgress status=" + statusToString(STATUS_PROGRESS, status)); 314 } 315 316 @Override onBootstrapUriGenerated(String uri)317 public void onBootstrapUriGenerated(String uri) { 318 mPrintWriter.println("onBootstrapUriGenerated URI = " + uri); 319 } 320 statusToString(int type, int status)321 private String statusToString(int type, int status) { 322 switch (type) { 323 case STATUS_SUCCESS: { 324 switch (status) { 325 case 0: 326 return "CONFIGURATION_SENT"; 327 case 1: 328 return "CONFIGURATION_APPLIED"; 329 default: 330 return "Unknown success code"; 331 } 332 } 333 case STATUS_PROGRESS: { 334 switch (status) { 335 case 0: 336 return "AUTHENTICATION_SUCCESS"; 337 case 1: 338 return "RESPONSE_PENDING"; 339 case 2: 340 return "CONFIGURATION_SENT_WAITING_RESPONSE"; 341 case 3: 342 return "CONFIGURATION_ACCEPTED"; 343 default: 344 return "Unknown progress code"; 345 } 346 } 347 case STATUS_FAILURE: { 348 switch (status) { 349 case -1: 350 return "INVALID_URI"; 351 case -2: 352 return "AUTHENTICATION"; 353 case -3: 354 return "NOT_COMPATIBLE"; 355 case -4: 356 return "CONFIGURATION"; 357 case -5: 358 return "BUSY"; 359 case -6: 360 return "TIMEOUT"; 361 case -7: 362 return "GENERIC"; 363 case -8: 364 return "NOT_SUPPORTED"; 365 case -9: 366 return "INVALID_NETWORK"; 367 case -10: 368 return "CANNOT_FIND_NETWORK"; 369 case -11: 370 return "ENROLLEE_AUTHENTICATION"; 371 case -12: 372 return "ENROLLEE_REJECTED_CONFIGURATION"; 373 case -13: 374 return "URI_GENERATION"; 375 case -14: 376 return "ENROLLEE_FAILED_TO_SCAN_NETWORK_CHANNEL"; 377 default: 378 return "Unknown failure code"; 379 } 380 } 381 default : 382 return "Unknown status type"; 383 } 384 } 385 } 386 387 /** 388 * Used for shell command testing of scorer. 389 */ 390 public static class WifiScorer extends IWifiConnectedNetworkScorer.Stub { 391 private final WifiServiceImpl mWifiService; 392 private final CountDownLatch mCountDownLatch; 393 private Integer mSessionId; 394 private IScoreUpdateObserver mScoreUpdateObserver; 395 WifiScorer(WifiServiceImpl wifiService, CountDownLatch countDownLatch)396 public WifiScorer(WifiServiceImpl wifiService, CountDownLatch countDownLatch) { 397 mWifiService = wifiService; 398 mCountDownLatch = countDownLatch; 399 } 400 401 @Override onStart(WifiConnectedSessionInfo sessionInfo)402 public void onStart(WifiConnectedSessionInfo sessionInfo) { 403 mSessionId = sessionInfo.getSessionId(); 404 mCountDownLatch.countDown(); 405 } 406 @Override onStop(int sessionId)407 public void onStop(int sessionId) { 408 // clear the external scorer on disconnect. 409 mWifiService.clearWifiConnectedNetworkScorer(); 410 } 411 @Override onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl)412 public void onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl) { 413 mScoreUpdateObserver = observerImpl; 414 mCountDownLatch.countDown(); 415 } 416 @Override onNetworkSwitchAccepted( int sessionId, int targetNetworkId, String targetBssid)417 public void onNetworkSwitchAccepted( 418 int sessionId, int targetNetworkId, String targetBssid) { 419 Log.i(TAG, "onNetworkSwitchAccepted:" 420 + " sessionId=" + sessionId 421 + " targetNetworkId=" + targetNetworkId 422 + " targetBssid=" + targetBssid); 423 } 424 425 @Override onNetworkSwitchRejected( int sessionId, int targetNetworkId, String targetBssid)426 public void onNetworkSwitchRejected( 427 int sessionId, int targetNetworkId, String targetBssid) { 428 Log.i(TAG, "onNetworkSwitchRejected:" 429 + " sessionId=" + sessionId 430 + " targetNetworkId=" + targetNetworkId 431 + " targetBssid=" + targetBssid); 432 } 433 getSessionId()434 public Integer getSessionId() { 435 return mSessionId; 436 } 437 getScoreUpdateObserver()438 public IScoreUpdateObserver getScoreUpdateObserver() { 439 return mScoreUpdateObserver; 440 } 441 } 442 WifiShellCommand(WifiInjector wifiInjector, WifiServiceImpl wifiService, WifiContext context, WifiGlobals wifiGlobals, WifiThreadRunner wifiThreadRunner)443 WifiShellCommand(WifiInjector wifiInjector, WifiServiceImpl wifiService, WifiContext context, 444 WifiGlobals wifiGlobals, WifiThreadRunner wifiThreadRunner) { 445 mWifiInjector = wifiInjector; 446 mWifiGlobals = wifiGlobals; 447 mWifiThreadRunner = wifiThreadRunner; 448 mActiveModeWarden = wifiInjector.getActiveModeWarden(); 449 mWifiLockManager = wifiInjector.getWifiLockManager(); 450 mWifiNetworkSuggestionsManager = wifiInjector.getWifiNetworkSuggestionsManager(); 451 mWifiConfigManager = wifiInjector.getWifiConfigManager(); 452 mWifiNative = wifiInjector.getWifiNative(); 453 mCoexManager = wifiInjector.getCoexManager(); 454 mWifiCountryCode = wifiInjector.getWifiCountryCode(); 455 mWifiLastResortWatchdog = wifiInjector.getWifiLastResortWatchdog(); 456 mWifiService = wifiService; 457 mContext = context; 458 mConnectivityManager = context.getSystemService(ConnectivityManager.class); 459 mWifiCarrierInfoManager = wifiInjector.getWifiCarrierInfoManager(); 460 mWifiNetworkFactory = wifiInjector.getWifiNetworkFactory(); 461 mSelfRecovery = wifiInjector.getSelfRecovery(); 462 mWifiApConfigStore = wifiInjector.getWifiApConfigStore(); 463 mScanRequestProxy = wifiInjector.getScanRequestProxy(); 464 mWifiDialogManager = wifiInjector.getWifiDialogManager(); 465 mHalDeviceManager = wifiInjector.getHalDeviceManager(); 466 mInterfaceConflictManager = wifiInjector.getInterfaceConflictManager(); 467 mSsidTranslator = wifiInjector.getSsidTranslator(); 468 mWifiDiagnostics = wifiInjector.getWifiDiagnostics(); 469 mDeviceConfig = wifiInjector.getDeviceConfigFacade(); 470 mAfcManager = wifiInjector.getAfcManager(); 471 } 472 getOpModeName(@ifiAvailableChannel.OpMode int mode)473 private String getOpModeName(@WifiAvailableChannel.OpMode int mode) { 474 switch (mode) { 475 case WifiAvailableChannel.OP_MODE_STA: 476 return "STA"; 477 case WifiAvailableChannel.OP_MODE_SAP: 478 return "SAP"; 479 case WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI: 480 return "WiFi-Direct GC"; 481 case WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO: 482 return "WiFi-Direct GO"; 483 case WifiAvailableChannel.OP_MODE_WIFI_AWARE: 484 return "WiFi-Aware"; 485 case WifiAvailableChannel.OP_MODE_TDLS: 486 return "TDLS"; 487 default: 488 return ""; 489 } 490 } 491 492 @Override onCommand(String cmd)493 public int onCommand(String cmd) { 494 // Treat no command as help command. 495 if (TextUtils.isEmpty(cmd)) { 496 cmd = "help"; 497 } 498 // Explicit exclusion from root permission 499 if (ArrayUtils.indexOf(NON_PRIVILEGED_COMMANDS, cmd) == -1) { 500 final int uid = Binder.getCallingUid(); 501 if (uid != Process.ROOT_UID) { 502 throw new SecurityException( 503 "Uid " + uid + " does not have access to " + cmd + " wifi command " 504 + "(or such command doesn't exist)"); 505 } 506 } 507 final PrintWriter pw = getOutPrintWriter(); 508 try { 509 switch (cmd) { 510 case "set-ipreach-disconnect": { 511 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 512 mWifiGlobals.setIpReachabilityDisconnectEnabled(enabled); 513 return 0; 514 } 515 case "get-ipreach-disconnect": 516 pw.println("IPREACH_DISCONNECT state is " 517 + mWifiGlobals.getIpReachabilityDisconnectEnabled()); 518 return 0; 519 case "set-poll-rssi-interval-msecs": 520 int newPollIntervalMsecs; 521 try { 522 newPollIntervalMsecs = Integer.parseInt(getNextArgRequired()); 523 } catch (NumberFormatException e) { 524 pw.println( 525 "Invalid argument to 'set-poll-rssi-interval-msecs' " 526 + "- must be a positive integer"); 527 return -1; 528 } 529 530 if (newPollIntervalMsecs < 1) { 531 pw.println( 532 "Invalid argument to 'set-poll-rssi-interval-msecs' " 533 + "- must be a positive integer"); 534 return -1; 535 } 536 537 mWifiGlobals.setPollRssiIntervalMillis(newPollIntervalMsecs); 538 return 0; 539 case "get-poll-rssi-interval-msecs": 540 pw.println("WifiGlobals.getPollRssiIntervalMillis() = " 541 + mWifiGlobals.getPollRssiIntervalMillis()); 542 return 0; 543 case "force-hi-perf-mode": { 544 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 545 if (!mWifiLockManager.forceHiPerfMode(enabled)) { 546 pw.println("Command execution failed"); 547 } 548 return 0; 549 } 550 case "force-low-latency-mode": { 551 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 552 if (!mWifiLockManager.forceLowLatencyMode(enabled)) { 553 pw.println("Command execution failed"); 554 } 555 return 0; 556 } 557 case "network-suggestions-set-user-approved": { 558 String packageName = getNextArgRequired(); 559 boolean approved = getNextArgRequiredTrueOrFalse("yes", "no"); 560 mWifiThreadRunner.post(() -> mWifiNetworkSuggestionsManager 561 .setHasUserApprovedForApp(approved, 562 Binder.getCallingUid(), packageName), 563 "shell#setHasUserApprovedForApp"); 564 return 0; 565 } 566 case "network-suggestions-has-user-approved": { 567 String packageName = getNextArgRequired(); 568 boolean hasUserApproved = 569 mWifiNetworkSuggestionsManager.hasUserApprovedForApp(packageName); 570 pw.println(hasUserApproved ? "yes" : "no"); 571 return 0; 572 } 573 case "imsi-protection-exemption-set-user-approved-for-carrier": { 574 String arg1 = getNextArgRequired(); 575 int carrierId = -1; 576 try { 577 carrierId = Integer.parseInt(arg1); 578 } catch (NumberFormatException e) { 579 pw.println("Invalid argument to " 580 + "'imsi-protection-exemption-set-user-approved-for-carrier' " 581 + "- carrierId must be an Integer"); 582 return -1; 583 } 584 boolean approved = getNextArgRequiredTrueOrFalse("yes", "no"); 585 mWifiCarrierInfoManager 586 .setHasUserApprovedImsiPrivacyExemptionForCarrier(approved, carrierId); 587 return 0; 588 } 589 case "imsi-protection-exemption-has-user-approved-for-carrier": { 590 String arg1 = getNextArgRequired(); 591 int carrierId = -1; 592 try { 593 carrierId = Integer.parseInt(arg1); 594 } catch (NumberFormatException e) { 595 pw.println("Invalid argument to " 596 + "'imsi-protection-exemption-has-user-approved-for-carrier' " 597 + "- 'carrierId' must be an Integer"); 598 return -1; 599 } 600 boolean hasUserApproved = mWifiCarrierInfoManager 601 .hasUserApprovedImsiPrivacyExemptionForCarrier(carrierId); 602 pw.println(hasUserApproved ? "yes" : "no"); 603 return 0; 604 } 605 case "imsi-protection-exemption-clear-user-approved-for-carrier": { 606 String arg1 = getNextArgRequired(); 607 try { 608 final int carrierId = Integer.parseInt(arg1); 609 mWifiThreadRunner.post(() -> 610 mWifiCarrierInfoManager.clearImsiPrivacyExemptionForCarrier( 611 carrierId), TAG + "#" + cmd); 612 } catch (NumberFormatException e) { 613 pw.println("Invalid argument to " 614 + "'imsi-protection-exemption-clear-user-approved-for-carrier' " 615 + "- 'carrierId' must be an Integer"); 616 return -1; 617 } 618 return 0; 619 } 620 case "network-requests-remove-user-approved-access-points": { 621 String packageName = getNextArgRequired(); 622 mWifiThreadRunner.post(() -> mWifiNetworkFactory.removeApp(packageName), 623 TAG + "#" + cmd); 624 return 0; 625 } 626 case "clear-user-disabled-networks": { 627 mWifiConfigManager.clearUserTemporarilyDisabledList(); 628 return 0; 629 } 630 case "send-link-probe": { 631 return sendLinkProbe(pw); 632 } 633 case "get-last-caller-info": { 634 int apiType = Integer.parseInt(getNextArgRequired()); 635 mWifiService.getLastCallerInfoForApi(apiType, 636 new ILastCallerListener.Stub() { 637 @Override 638 public void onResult(String packageName, boolean enabled) { 639 Log.i(TAG, "getLastCallerInfoForApi " + apiType 640 + ": packageName=" + packageName 641 + ", enabled=" + enabled); 642 } 643 }); 644 return 0; 645 } 646 case "force-softap-band": { 647 boolean forceBandEnabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 648 if (forceBandEnabled) { 649 String forcedBand = getNextArgRequired(); 650 if (forcedBand.equals("2")) { 651 mWifiApConfigStore.enableForceSoftApBandOrChannel( 652 SoftApConfiguration.BAND_2GHZ, 0, 653 SoftApInfo.CHANNEL_WIDTH_AUTO); 654 } else if (forcedBand.equals("5")) { 655 mWifiApConfigStore.enableForceSoftApBandOrChannel( 656 SoftApConfiguration.BAND_5GHZ, 0, 657 SoftApInfo.CHANNEL_WIDTH_AUTO); 658 } else if (forcedBand.equals("6")) { 659 mWifiApConfigStore.enableForceSoftApBandOrChannel( 660 SoftApConfiguration.BAND_6GHZ, 0, 661 SoftApInfo.CHANNEL_WIDTH_AUTO); 662 } else { 663 pw.println("Invalid argument to 'force-softap-band enabled' " 664 + "- must be a valid band integer (2|5|6)"); 665 return -1; 666 } 667 return 0; 668 } else { 669 mWifiApConfigStore.disableForceSoftApBandOrChannel(); 670 return 0; 671 } 672 673 } 674 case "force-softap-channel": { 675 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 676 if (enabled) { 677 int apChannelMHz; 678 int apMaxBandWidthMHz = 0; 679 try { 680 apChannelMHz = Integer.parseInt(getNextArgRequired()); 681 String option = getNextOption(); 682 if (option != null && option.equals("-w")) { 683 if (!SdkLevel.isAtLeastT()) { 684 pw.println("Maximum channel bandwidth can be set only on" 685 + " SdkLevel T or later."); 686 return -1; 687 } 688 String bandwidthStr = getNextArgRequired(); 689 try { 690 apMaxBandWidthMHz = Integer.parseInt(bandwidthStr); 691 } catch (NumberFormatException e) { 692 pw.println("Invalid maximum channel bandwidth arg: " 693 + bandwidthStr); 694 return -1; 695 } 696 } 697 } catch (NumberFormatException e) { 698 pw.println("Invalid argument to 'force-softap-channel enabled' " 699 + "- must be a positive integer"); 700 return -1; 701 } 702 int apChannel = ScanResult.convertFrequencyMhzToChannelIfSupported( 703 apChannelMHz); 704 int band = ApConfigUtil.convertFrequencyToBand(apChannelMHz); 705 int apMaxBandWidth; 706 switch (apMaxBandWidthMHz) { 707 case 0: 708 apMaxBandWidth = SoftApInfo.CHANNEL_WIDTH_AUTO; 709 break; 710 case 20: 711 apMaxBandWidth = SoftApInfo.CHANNEL_WIDTH_20MHZ; 712 break; 713 case 40: 714 apMaxBandWidth = SoftApInfo.CHANNEL_WIDTH_40MHZ; 715 break; 716 case 80: 717 apMaxBandWidth = SoftApInfo.CHANNEL_WIDTH_80MHZ; 718 break; 719 case 160: 720 apMaxBandWidth = SoftApInfo.CHANNEL_WIDTH_160MHZ; 721 break; 722 case 320: 723 apMaxBandWidth = SoftApInfo.CHANNEL_WIDTH_320MHZ; 724 break; 725 default: 726 pw.println("Invalid max channel bandwidth " + apMaxBandWidthMHz); 727 return -1; 728 } 729 pw.println("channel: " + apChannel + " band: " + band 730 + " maximum channel bandwidth: " + apMaxBandWidthMHz); 731 if (apChannel == -1 || band == -1) { 732 pw.println("Invalid argument to 'force-softap-channel enabled' " 733 + "- must be a valid WLAN channel"); 734 return -1; 735 } 736 boolean isTemporarilyEnablingWifiNeeded = mWifiService.getWifiEnabledState() 737 != WIFI_STATE_ENABLED; 738 if (isTemporarilyEnablingWifiNeeded) { 739 waitForWifiEnabled(true); 740 } 741 // Following calls will fail if wifi is not enabled 742 boolean isValidChannel = isApChannelMHzValid(pw, apChannelMHz); 743 if (isTemporarilyEnablingWifiNeeded) { 744 waitForWifiEnabled(false); 745 } 746 if (!isValidChannel 747 || (band == SoftApConfiguration.BAND_5GHZ 748 && !mWifiService.is5GHzBandSupported()) 749 || (band == SoftApConfiguration.BAND_6GHZ 750 && !mWifiService.is6GHzBandSupported()) 751 || (band == SoftApConfiguration.BAND_60GHZ 752 && !mWifiService.is60GHzBandSupported())) { 753 pw.println("Invalid argument to 'force-softap-channel enabled' " 754 + "- must be a valid WLAN channel" 755 + " in a band supported by the device"); 756 return -1; 757 } 758 mWifiApConfigStore.enableForceSoftApBandOrChannel(band, apChannel, 759 apMaxBandWidth); 760 return 0; 761 } else { 762 mWifiApConfigStore.disableForceSoftApBandOrChannel(); 763 return 0; 764 } 765 } 766 case "set-pno-request": { 767 if (!SdkLevel.isAtLeastT()) { 768 pw.println("This feature is only supported on SdkLevel T or later."); 769 return -1; 770 } 771 String ssid = getNextArgRequired(); 772 int frequency = -1; 773 WifiSsid wifiSsid = WifiSsid.fromString("\"" + ssid + "\""); 774 String option = getNextOption(); 775 if (option != null) { 776 if (option.equals("-f")) { 777 frequency = Integer.parseInt(getNextArgRequired()); 778 } else { 779 pw.println("Invalid argument to 'set-pno-request' " 780 + "- only allowed option is '-f'"); 781 return -1; 782 } 783 } 784 int[] frequencies = frequency == -1 ? new int[0] : new int[] {frequency}; 785 IPnoScanResultsCallback.Stub callback = new IPnoScanResultsCallback.Stub() { 786 @Override 787 public void onScanResultsAvailable(List<ScanResult> scanResults) { 788 Log.v(TAG, "PNO scan results available:"); 789 for (ScanResult result : scanResults) { 790 Log.v(TAG, result.getWifiSsid().toString()); 791 } 792 } 793 @Override 794 public void onRegisterSuccess() { 795 Log.v(TAG, "PNO scan request register success"); 796 } 797 798 @Override 799 public void onRegisterFailed(int reason) { 800 Log.v(TAG, "PNO scan request register failed reason=" + reason); 801 } 802 803 @Override 804 public void onRemoved(int reason) { 805 Log.v(TAG, "PNO scan request callback removed reason=" + reason); 806 } 807 }; 808 pw.println("requesting PNO scan for: " + wifiSsid); 809 mWifiService.setExternalPnoScanRequest(new Binder(), callback, 810 Arrays.asList(wifiSsid), frequencies, mContext.getOpPackageName(), 811 mContext.getAttributionTag()); 812 return 0; 813 } 814 case "clear-pno-request": { 815 if (!SdkLevel.isAtLeastT()) { 816 pw.println("This feature is only supported on SdkLevel T or later."); 817 return -1; 818 } 819 mWifiService.clearExternalPnoScanRequest(); 820 return 0; 821 } 822 case "start-lohs": { 823 CountDownLatch countDownLatch = new CountDownLatch(2); 824 SoftApConfiguration config = buildSoftApConfiguration(pw); 825 ILocalOnlyHotspotCallback.Stub lohsCallback = 826 new ILocalOnlyHotspotCallback.Stub() { 827 @Override 828 public void onHotspotStarted(SoftApConfiguration config) { 829 pw.println("Lohs onStarted, config = " + config); 830 countDownLatch.countDown(); 831 } 832 833 @Override 834 public void onHotspotStopped() { 835 pw.println("Lohs onStopped"); 836 countDownLatch.countDown(); 837 } 838 839 @Override 840 public void onHotspotFailed(int reason) { 841 pw.println("Lohs onFailed: " + reason); 842 countDownLatch.countDown(); 843 } 844 }; 845 SoftApCallbackProxy softApCallback = 846 new SoftApCallbackProxy(pw, countDownLatch); 847 Bundle extras = new Bundle(); 848 if (SdkLevel.isAtLeastS()) { 849 extras.putParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 850 mContext.getAttributionSource()); 851 } 852 mWifiService.registerLocalOnlyHotspotSoftApCallback(softApCallback, extras); 853 if (REQUEST_REGISTERED != mWifiService.startLocalOnlyHotspot( 854 lohsCallback, SHELL_PACKAGE_NAME, null /* featureId */, 855 config, extras)) { 856 pw.println("Lohs failed to start. Please check config parameters"); 857 } 858 // Wait for lohs to start and complete callback 859 countDownLatch.await(10000, TimeUnit.MILLISECONDS); 860 mWifiService.unregisterLocalOnlyHotspotSoftApCallback(softApCallback, extras); 861 return 0; 862 } 863 case "start-softap": { 864 CountDownLatch countDownLatch = new CountDownLatch(1); 865 SoftApConfiguration config = buildSoftApConfiguration(pw); 866 SoftApCallbackProxy softApCallback = 867 new SoftApCallbackProxy(pw, countDownLatch); 868 mWifiService.registerSoftApCallback(softApCallback); 869 if (!mWifiService.startTetheredHotspot(config, SHELL_PACKAGE_NAME)) { 870 pw.println("Soft AP failed to start. Please check config parameters"); 871 } 872 // Wait for softap to start and complete callback 873 countDownLatch.await(10000, TimeUnit.MILLISECONDS); 874 mWifiService.unregisterSoftApCallback(softApCallback); 875 return 0; 876 } 877 case "stop-lohs": { 878 mWifiService.stopLocalOnlyHotspot(); 879 pw.println("Lohs stopped successfully"); 880 return 0; 881 } 882 case "stop-softap": { 883 if (mWifiService.stopSoftAp()) { 884 pw.println("Soft AP stopped successfully"); 885 } else { 886 pw.println("Soft AP failed to stop"); 887 } 888 return 0; 889 } 890 case "reload-resources": { 891 mContext.resetResourceCache(); 892 return 0; 893 } 894 case "force-country-code": { 895 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 896 if (enabled) { 897 String countryCode = getNextArgRequired(); 898 if (!WifiCountryCode.isValid(countryCode)) { 899 pw.println("Invalid argument: Country code must be a 2-Character" 900 + " alphanumeric code. But got countryCode " + countryCode 901 + " instead"); 902 return -1; 903 } 904 mWifiCountryCode.setOverrideCountryCode(countryCode); 905 return 0; 906 } else { 907 mWifiCountryCode.clearOverrideCountryCode(); 908 return 0; 909 } 910 } 911 case "get-country-code": { 912 pw.println("Wifi Country Code = " 913 + mWifiCountryCode.getCountryCode()); 914 return 0; 915 } 916 case "set-wifi-watchdog": { 917 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 918 mWifiLastResortWatchdog.setWifiWatchdogFeature(enabled); 919 return 0; 920 } 921 case "get-wifi-watchdog": { 922 pw.println("wifi watchdog state is " 923 + mWifiLastResortWatchdog.getWifiWatchdogFeature()); 924 return 0; 925 } 926 case "set-wifi-enabled": { 927 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 928 mWifiService.setWifiEnabled(SHELL_PACKAGE_NAME, enabled); 929 return 0; 930 } 931 case "set-passpoint-enabled": { 932 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 933 mWifiService.setWifiPasspointEnabled(enabled); 934 return 0; 935 } 936 case "set-multi-internet-mode": { 937 int mode = Integer.parseInt(getNextArgRequired()); 938 mWifiService.setStaConcurrencyForMultiInternetMode(mode); 939 return 0; 940 } 941 case "set-scan-always-available": { 942 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 943 mWifiService.setScanAlwaysAvailable(enabled, SHELL_PACKAGE_NAME); 944 return 0; 945 } 946 case "get-softap-supported-features": 947 // This command is used for vts to check softap supported features. 948 if (ApConfigUtil.isAcsSupported(mContext)) { 949 pw.println("wifi_softap_acs_supported"); 950 } 951 if (ApConfigUtil.isWpa3SaeSupported(mContext)) { 952 pw.println("wifi_softap_wpa3_sae_supported"); 953 } 954 if ((mWifiService.getSupportedFeatures() 955 & WifiManager.WIFI_FEATURE_BRIDGED_AP) 956 == WifiManager.WIFI_FEATURE_BRIDGED_AP) { 957 pw.println("wifi_softap_bridged_ap_supported"); 958 } 959 if ((mWifiService.getSupportedFeatures() 960 & WifiManager.WIFI_FEATURE_STA_BRIDGED_AP) 961 == WifiManager.WIFI_FEATURE_STA_BRIDGED_AP) { 962 pw.println("wifi_softap_bridged_ap_with_sta_supported"); 963 } 964 return 0; 965 case "settings-reset": 966 mWifiNative.stopFakingScanDetails(); 967 mWifiNative.resetFakeScanDetails(); 968 mWifiService.factoryReset(SHELL_PACKAGE_NAME); 969 return 0; 970 case "list-scan-results": 971 List<ScanResult> scanResults = 972 mScanRequestProxy.getScanResults(); 973 if (scanResults.isEmpty()) { 974 pw.println("No scan results"); 975 } else { 976 ScanResultUtil.dumpScanResults(pw, scanResults, 977 SystemClock.elapsedRealtime()); 978 } 979 return 0; 980 case "start-scan": 981 mWifiService.startScan(SHELL_PACKAGE_NAME, null); 982 return 0; 983 case "list-networks": 984 ParceledListSlice<WifiConfiguration> networks = 985 mWifiService.getConfiguredNetworks(SHELL_PACKAGE_NAME, null, false); 986 if (networks == null || networks.getList().isEmpty()) { 987 pw.println("No networks"); 988 } else { 989 pw.println("Network Id SSID Security type"); 990 for (WifiConfiguration network : networks.getList()) { 991 String securityType = network.getSecurityParamsList().stream() 992 .map(p -> WifiConfiguration.getSecurityTypeName( 993 p.getSecurityType()) 994 + (p.isAddedByAutoUpgrade() ? "^" : "")) 995 .collect(Collectors.joining("/")); 996 pw.println(String.format("%-12d %-32s %-4s", 997 network.networkId, WifiInfo.sanitizeSsid(network.SSID), 998 securityType)); 999 } 1000 } 1001 return 0; 1002 case "connect-network": { 1003 CountDownLatch countDownLatch = new CountDownLatch(1); 1004 IActionListener.Stub actionListener = new IActionListener.Stub() { 1005 @Override 1006 public void onSuccess() throws RemoteException { 1007 pw.println("Connection initiated "); 1008 countDownLatch.countDown(); 1009 } 1010 1011 @Override 1012 public void onFailure(int i) throws RemoteException { 1013 pw.println("Connection failed"); 1014 countDownLatch.countDown(); 1015 } 1016 }; 1017 WifiConfiguration config = buildWifiConfiguration(pw); 1018 mWifiService.connect(config, -1, actionListener, SHELL_PACKAGE_NAME, 1019 new Bundle()); 1020 return 0; 1021 } 1022 case "add-network": { 1023 CountDownLatch countDownLatch = new CountDownLatch(1); 1024 IActionListener.Stub actionListener = new IActionListener.Stub() { 1025 @Override 1026 public void onSuccess() throws RemoteException { 1027 pw.println("Save successful"); 1028 countDownLatch.countDown(); 1029 } 1030 1031 @Override 1032 public void onFailure(int i) throws RemoteException { 1033 pw.println("Save failed"); 1034 countDownLatch.countDown(); 1035 } 1036 }; 1037 WifiConfiguration config = buildWifiConfiguration(pw); 1038 mWifiService.save(config, actionListener, SHELL_PACKAGE_NAME); 1039 return 0; 1040 } 1041 case "forget-network": { 1042 String networkId = getNextArgRequired(); 1043 CountDownLatch countDownLatch = new CountDownLatch(1); 1044 IActionListener.Stub actionListener = new IActionListener.Stub() { 1045 @Override 1046 public void onSuccess() throws RemoteException { 1047 pw.println("Forget successful"); 1048 countDownLatch.countDown(); 1049 } 1050 1051 @Override 1052 public void onFailure(int i) throws RemoteException { 1053 pw.println("Forget failed"); 1054 countDownLatch.countDown(); 1055 } 1056 }; 1057 mWifiService.forget(Integer.parseInt(networkId), actionListener); 1058 // wait for status. 1059 countDownLatch.await(500, TimeUnit.MILLISECONDS); 1060 return 0; 1061 } 1062 case "pmksa-flush": { 1063 String networkId = getNextArgRequired(); 1064 int netId = Integer.parseInt(networkId); 1065 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId); 1066 if (config == null) { 1067 pw.println("No Wifi config corresponding to networkId: " + netId); 1068 return -1; 1069 } 1070 mWifiNative.removeNetworkCachedData(netId); 1071 return 0; 1072 } 1073 case "status": 1074 printStatus(pw); 1075 return 0; 1076 case "set-verbose-logging": { 1077 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 1078 String levelOption = getNextOption(); 1079 int level = enabled ? 1 : 0; 1080 if (enabled && levelOption != null && levelOption.equals("-l")) { 1081 String levelStr = getNextArgRequired(); 1082 try { 1083 level = Integer.parseInt(levelStr); 1084 if (level < VERBOSE_LOGGING_LEVEL_DISABLED 1085 || level > VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY) { 1086 pw.println("Not a valid log level: " + level); 1087 return -1; 1088 } 1089 } catch (NumberFormatException e) { 1090 pw.println("Invalid verbose-logging level : " + levelStr); 1091 return -1; 1092 } 1093 } 1094 mWifiService.enableVerboseLogging(level); 1095 return 0; 1096 } 1097 case "is-verbose-logging": { 1098 int enabled = mWifiService.getVerboseLoggingLevel(); 1099 pw.println(enabled > 0 ? "enabled" : "disabled"); 1100 return 0; 1101 } 1102 case "start-restricting-auto-join-to-subscription-id": { 1103 if (!SdkLevel.isAtLeastS()) { 1104 pw.println("This feature is only supported on SdkLevel S or later."); 1105 return -1; 1106 } 1107 int subId = Integer.parseInt(getNextArgRequired()); 1108 mWifiService.startRestrictingAutoJoinToSubscriptionId(subId); 1109 return 0; 1110 } 1111 case "stop-restricting-auto-join-to-subscription-id": { 1112 if (!SdkLevel.isAtLeastS()) { 1113 pw.println("This feature is only supported on SdkLevel S or later."); 1114 return -1; 1115 } 1116 mWifiService.stopRestrictingAutoJoinToSubscriptionId(); 1117 return 0; 1118 } 1119 case "add-suggestion": { 1120 WifiNetworkSuggestion suggestion = buildSuggestion(pw); 1121 if (suggestion == null) { 1122 pw.println("Invalid network suggestion parameter"); 1123 return -1; 1124 } 1125 int errorCode = mWifiService.addNetworkSuggestions( 1126 Arrays.asList(suggestion), SHELL_PACKAGE_NAME, null); 1127 if (errorCode != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) { 1128 pw.println("Add network suggestion failed with error code: " + errorCode); 1129 return -1; 1130 } 1131 // untrusted/oem-paid networks need a corresponding NetworkRequest. 1132 if (suggestion.isUntrusted() 1133 || (SdkLevel.isAtLeastS() 1134 && (suggestion.isOemPaid() || suggestion.isOemPrivate()))) { 1135 NetworkRequest.Builder networkRequestBuilder = 1136 new NetworkRequest.Builder() 1137 .addTransportType(TRANSPORT_WIFI); 1138 if (suggestion.isUntrusted()) { 1139 networkRequestBuilder.removeCapability(NET_CAPABILITY_TRUSTED); 1140 } 1141 if (SdkLevel.isAtLeastS()) { 1142 if (suggestion.isOemPaid()) { 1143 networkRequestBuilder.addCapability(NET_CAPABILITY_OEM_PAID); 1144 } 1145 if (suggestion.isOemPrivate()) { 1146 networkRequestBuilder.addCapability(NET_CAPABILITY_OEM_PRIVATE); 1147 } 1148 } 1149 NetworkRequest networkRequest = networkRequestBuilder.build(); 1150 ConnectivityManager.NetworkCallback networkCallback = 1151 new ConnectivityManager.NetworkCallback(); 1152 pw.println("Adding request: " + networkRequest); 1153 mConnectivityManager.requestNetwork(networkRequest, networkCallback); 1154 sActiveRequests.put( 1155 suggestion.getSsid(), Pair.create(networkRequest, networkCallback)); 1156 } 1157 return 0; 1158 } 1159 case "remove-suggestion": { 1160 String ssid = getNextArgRequired(); 1161 String action = getNextArg(); 1162 int actionCode = ACTION_REMOVE_SUGGESTION_DISCONNECT; 1163 if (action != null && action.equals("lingering")) { 1164 actionCode = ACTION_REMOVE_SUGGESTION_LINGER; 1165 } 1166 List<WifiNetworkSuggestion> suggestions = 1167 mWifiService.getNetworkSuggestions(SHELL_PACKAGE_NAME); 1168 WifiNetworkSuggestion suggestion = suggestions.stream() 1169 .filter(s -> s.getSsid().equals(ssid)) 1170 .findAny() 1171 .orElse(null); 1172 if (suggestion == null) { 1173 pw.println("No matching suggestion to remove"); 1174 return -1; 1175 } 1176 mWifiService.removeNetworkSuggestions( 1177 Arrays.asList(suggestion), SHELL_PACKAGE_NAME, actionCode); 1178 // untrusted/oem-paid networks need a corresponding NetworkRequest. 1179 if (suggestion.isUntrusted() 1180 || (SdkLevel.isAtLeastS() 1181 && (suggestion.isOemPaid() || suggestion.isOemPrivate()))) { 1182 Pair<NetworkRequest, ConnectivityManager.NetworkCallback> nrAndNc = 1183 sActiveRequests.remove(suggestion.getSsid()); 1184 if (nrAndNc == null) { 1185 pw.println("No matching request to remove"); 1186 return -1; 1187 } 1188 pw.println("Removing request: " + nrAndNc.first); 1189 mConnectivityManager.unregisterNetworkCallback(nrAndNc.second); 1190 } 1191 return 0; 1192 } 1193 case "remove-all-suggestions": 1194 mWifiService.removeNetworkSuggestions( 1195 Collections.emptyList(), SHELL_PACKAGE_NAME, 1196 WifiManager.ACTION_REMOVE_SUGGESTION_DISCONNECT); 1197 return 0; 1198 case "list-suggestions": { 1199 List<WifiNetworkSuggestion> suggestions = 1200 mWifiService.getNetworkSuggestions(SHELL_PACKAGE_NAME); 1201 printWifiNetworkSuggestions(pw, suggestions); 1202 return 0; 1203 } 1204 case "list-all-suggestions": { 1205 Set<WifiNetworkSuggestion> suggestions = 1206 mWifiNetworkSuggestionsManager.getAllNetworkSuggestions(); 1207 printWifiNetworkSuggestions(pw, suggestions); 1208 return 0; 1209 } 1210 case "list-suggestions-from-app": { 1211 String packageName = getNextArgRequired(); 1212 List<WifiNetworkSuggestion> suggestions = 1213 mWifiService.getNetworkSuggestions(packageName); 1214 printWifiNetworkSuggestions(pw, suggestions); 1215 return 0; 1216 } 1217 case "allow-root-to-get-local-only-cmm": { 1218 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 1219 mActiveModeWarden.allowRootToGetLocalOnlyCmm(enabled); 1220 return 0; 1221 } 1222 case "add-request": { 1223 Pair<String, NetworkRequest> result = buildNetworkRequest(pw); 1224 String ssid = result.first; 1225 NetworkRequest networkRequest = result.second; 1226 ConnectivityManager.NetworkCallback networkCallback = 1227 new ConnectivityManager.NetworkCallback(); 1228 pw.println("Adding request: " + networkRequest); 1229 mWifiThreadRunner.post(() -> mConnectivityManager 1230 .requestNetwork(networkRequest, networkCallback), 1231 "shell#add-request"); 1232 1233 sActiveRequests.put(ssid, Pair.create(networkRequest, networkCallback)); 1234 return 0; 1235 } 1236 case "remove-request": { 1237 String ssid = getNextArgRequired(); 1238 Pair<NetworkRequest, ConnectivityManager.NetworkCallback> nrAndNc = 1239 sActiveRequests.remove(ssid); 1240 if (nrAndNc == null) { 1241 pw.println("No matching request to remove"); 1242 return -1; 1243 } 1244 pw.println("Removing request: " + nrAndNc.first); 1245 mWifiThreadRunner.post(() -> mConnectivityManager 1246 .unregisterNetworkCallback(nrAndNc.second), 1247 "shell#remove-request"); 1248 return 0; 1249 } 1250 case "remove-all-requests": 1251 if (sActiveRequests.isEmpty()) { 1252 pw.println("No active requests"); 1253 return -1; 1254 } 1255 for (Pair<NetworkRequest, ConnectivityManager.NetworkCallback> nrAndNc 1256 : sActiveRequests.values()) { 1257 pw.println("Removing request: " + nrAndNc.first); 1258 mWifiThreadRunner.post(() -> 1259 mConnectivityManager.unregisterNetworkCallback(nrAndNc.second), 1260 "shell#remove-request"); 1261 } 1262 sActiveRequests.clear(); 1263 return 0; 1264 case "list-requests": 1265 if (sActiveRequests.isEmpty()) { 1266 pw.println("No active requests"); 1267 } else { 1268 pw.println("SSID NetworkRequest"); 1269 for (Map.Entry<String, 1270 Pair<NetworkRequest, ConnectivityManager.NetworkCallback>> entry : 1271 sActiveRequests.entrySet()) { 1272 pw.println(String.format("%-32s %-4s", 1273 entry.getKey(), entry.getValue().first)); 1274 } 1275 } 1276 return 0; 1277 case "network-requests-set-user-approved": { 1278 String packageName = getNextArgRequired(); 1279 boolean approved = getNextArgRequiredTrueOrFalse("yes", "no"); 1280 mWifiNetworkFactory.setUserApprovedApp(packageName, approved); 1281 return 0; 1282 } 1283 case "network-requests-has-user-approved": { 1284 String packageName = getNextArgRequired(); 1285 boolean hasUserApproved = mWifiNetworkFactory.hasUserApprovedApp(packageName); 1286 pw.println(hasUserApproved ? "yes" : "no"); 1287 return 0; 1288 } 1289 case "set-coex-cell-channels": { 1290 if (!SdkLevel.isAtLeastS()) { 1291 return handleDefaultCommands(cmd); 1292 } 1293 mCoexManager.setMockCellChannels(buildCoexCellChannels()); 1294 return 0; 1295 } 1296 case "reset-coex-cell-channels": { 1297 if (!SdkLevel.isAtLeastS()) { 1298 return handleDefaultCommands(cmd); 1299 } 1300 mCoexManager.resetMockCellChannels(); 1301 return 0; 1302 } 1303 case "get-coex-cell-channels": { 1304 if (!SdkLevel.isAtLeastS()) { 1305 return handleDefaultCommands(cmd); 1306 } 1307 pw.println("Cell channels: " + mCoexManager.getCellChannels()); 1308 return 0; 1309 } 1310 case "set-connected-score": { 1311 int score = Integer.parseInt(getNextArgRequired()); 1312 CountDownLatch countDownLatch = new CountDownLatch(2); 1313 mWifiService.clearWifiConnectedNetworkScorer(); // clear any previous scorer 1314 WifiScorer connectedScorer = new WifiScorer(mWifiService, countDownLatch); 1315 if (mWifiService.setWifiConnectedNetworkScorer(new Binder(), connectedScorer)) { 1316 // wait for retrieving the session id & score observer. 1317 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 1318 } 1319 if (connectedScorer.getSessionId() == null 1320 || connectedScorer.getScoreUpdateObserver() == null) { 1321 pw.println("Did not receive session id and/or the score update observer. " 1322 + "Is the device connected to a wifi network?"); 1323 mWifiService.clearWifiConnectedNetworkScorer(); 1324 return -1; 1325 } 1326 pw.println("Updating score: " + score + " for session id: " 1327 + connectedScorer.getSessionId()); 1328 try { 1329 connectedScorer.getScoreUpdateObserver().notifyScoreUpdate( 1330 connectedScorer.getSessionId(), score); 1331 } catch (RemoteException e) { 1332 pw.println("Failed to send the score update"); 1333 mWifiService.clearWifiConnectedNetworkScorer(); 1334 return -1; 1335 } 1336 return 0; 1337 } 1338 case "reset-connected-score": { 1339 mWifiService.clearWifiConnectedNetworkScorer(); // clear any previous scorer 1340 return 0; 1341 } 1342 case "network-suggestions-set-as-carrier-provider": { 1343 String packageName = getNextArgRequired(); 1344 boolean enabled = getNextArgRequiredTrueOrFalse("yes", "no"); 1345 mWifiNetworkSuggestionsManager 1346 .setAppWorkingAsCrossCarrierProvider(packageName, enabled); 1347 return 0; 1348 } 1349 case "is-network-suggestions-set-as-carrier-provider": { 1350 String packageName = getNextArgRequired(); 1351 pw.println(mWifiNetworkSuggestionsManager 1352 .isAppWorkingAsCrossCarrierProvider(packageName) ? "yes" : "no"); 1353 return 0; 1354 } 1355 case "remove-shell-app-from-suggestion_database <packageName>": { 1356 String packageName = getNextArgRequired(); 1357 mWifiNetworkSuggestionsManager.removeApp(packageName); 1358 return 0; 1359 } 1360 case "set-emergency-callback-mode": { 1361 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 1362 mActiveModeWarden.emergencyCallbackModeChanged(enabled); 1363 return 0; 1364 } 1365 case "set-emergency-call-state": { 1366 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 1367 mActiveModeWarden.emergencyCallStateChanged(enabled); 1368 return 0; 1369 } 1370 case "set-emergency-scan-request": { 1371 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 1372 mWifiService.setEmergencyScanRequestInProgress(enabled); 1373 return 0; 1374 } 1375 case "trigger-recovery": { 1376 mSelfRecovery.trigger(REASON_API_CALL); 1377 return 0; 1378 } 1379 case "add-fake-scan": { 1380 String option = getNextOption(); 1381 boolean isHex = (option != null && option.equals("-x")); 1382 WifiSsid wifiSsid = WifiSsid.fromBytes(isHex 1383 ? HexEncoding.decode(getNextArgRequired()) 1384 : getNextArgRequired().getBytes(StandardCharsets.UTF_8)); 1385 String bssid = getNextArgRequired(); 1386 String capabilities = getNextArgRequired(); 1387 int frequency; 1388 int dbm; 1389 String freqStr = getNextArgRequired(); 1390 try { 1391 frequency = Integer.parseInt(freqStr); 1392 } catch (NumberFormatException e) { 1393 pw.println( 1394 "Invalid frequency argument to 'add-fake-scan' " 1395 + "- must be an integer: " + freqStr); 1396 return -1; 1397 } 1398 if (frequency <= 0) { 1399 pw.println("Invalid frequency argument to 'add-fake-scan' - must be a " 1400 + "positive integer: " + freqStr); 1401 } 1402 String dbmString = getNextArgRequired(); 1403 try { 1404 dbm = Integer.parseInt(dbmString); 1405 } catch (NumberFormatException e) { 1406 pw.println( 1407 "Invalid dbm argument to 'add-fake-scan' " 1408 + "- must be an integer: " + dbmString); 1409 return -1; 1410 } 1411 ScanResult.InformationElement ieSSid = new ScanResult.InformationElement( 1412 ScanResult.InformationElement.EID_SSID, 1413 0, 1414 wifiSsid.getBytes()); 1415 ScanResult.InformationElement[] ies = 1416 new ScanResult.InformationElement[]{ieSSid}; 1417 ScanDetail sd = new ScanDetail(new NetworkDetail(bssid, ies, null, frequency), 1418 wifiSsid, bssid, capabilities, dbm, 1419 frequency, SystemClock.elapsedRealtime() * 1000, ies, null, null); 1420 mWifiNative.addFakeScanDetail(sd); 1421 return 0; 1422 } 1423 case "reset-fake-scans": 1424 mWifiNative.resetFakeScanDetails(); 1425 return 0; 1426 case "start-faking-scans": 1427 mWifiNative.startFakingScanDetails(); 1428 mWifiService.startScan(SHELL_PACKAGE_NAME, null); // to trigger update 1429 return 0; 1430 case "stop-faking-scans": 1431 mWifiNative.stopFakingScanDetails(); 1432 return 0; 1433 case "enable-scanning": { 1434 boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 1435 boolean hiddenEnabled = false; 1436 String option = getNextOption(); 1437 if (option != null) { 1438 if (option.equals("-h")) { 1439 hiddenEnabled = true; 1440 } else { 1441 pw.println("Invalid argument to 'enable-scanning' " 1442 + "- only allowed option is '-h'"); 1443 return -1; 1444 } 1445 } 1446 mScanRequestProxy.enableScanning(enabled, hiddenEnabled); 1447 return 0; 1448 } 1449 case "launch-dialog-simple": 1450 String title = null; 1451 String message = null; 1452 String messageUrl = null; 1453 int messageUrlStart = 0; 1454 int messageUrlEnd = 0; 1455 String positiveButtonText = null; 1456 String negativeButtonText = null; 1457 String neutralButtonText = null; 1458 String dialogOption = getNextOption(); 1459 boolean simpleTimeoutSpecified = false; 1460 long simpleTimeoutMs = 0; 1461 boolean useLegacy = false; 1462 while (dialogOption != null) { 1463 switch (dialogOption) { 1464 case "-t": 1465 title = getNextArgRequired(); 1466 break; 1467 case "-m": 1468 message = getNextArgRequired(); 1469 break; 1470 case "-l": 1471 messageUrl = getNextArgRequired(); 1472 messageUrlStart = Integer.valueOf(getNextArgRequired()); 1473 messageUrlEnd = Integer.valueOf(getNextArgRequired()); 1474 break; 1475 case "-y": 1476 positiveButtonText = getNextArgRequired(); 1477 break; 1478 case "-n": 1479 negativeButtonText = getNextArgRequired(); 1480 break; 1481 case "-x": 1482 neutralButtonText = getNextArgRequired(); 1483 break; 1484 case "-c": 1485 simpleTimeoutMs = Integer.parseInt(getNextArgRequired()); 1486 simpleTimeoutSpecified = true; 1487 break; 1488 case "-s": 1489 useLegacy = true; 1490 break; 1491 default: 1492 pw.println("Ignoring unknown option " + dialogOption); 1493 break; 1494 } 1495 dialogOption = getNextOption(); 1496 } 1497 ArrayBlockingQueue<String> simpleQueue = new ArrayBlockingQueue<>(1); 1498 WifiDialogManager.SimpleDialogCallback wifiEnableRequestCallback = 1499 new WifiDialogManager.SimpleDialogCallback() { 1500 @Override 1501 public void onPositiveButtonClicked() { 1502 simpleQueue.offer("Positive button was clicked."); 1503 } 1504 1505 @Override 1506 public void onNegativeButtonClicked() { 1507 simpleQueue.offer("Negative button was clicked."); 1508 } 1509 1510 @Override 1511 public void onNeutralButtonClicked() { 1512 simpleQueue.offer("Neutral button was clicked."); 1513 } 1514 1515 @Override 1516 public void onCancelled() { 1517 simpleQueue.offer("Dialog was cancelled."); 1518 } 1519 }; 1520 WifiDialogManager.DialogHandle simpleDialogHandle; 1521 if (useLegacy) { 1522 simpleDialogHandle = mWifiDialogManager.createLegacySimpleDialogWithUrl( 1523 title, 1524 message, 1525 messageUrl, 1526 messageUrlStart, 1527 messageUrlEnd, 1528 positiveButtonText, 1529 negativeButtonText, 1530 neutralButtonText, 1531 wifiEnableRequestCallback, 1532 mWifiThreadRunner); 1533 } else { 1534 simpleDialogHandle = mWifiDialogManager.createSimpleDialogWithUrl( 1535 title, 1536 message, 1537 messageUrl, 1538 messageUrlStart, 1539 messageUrlEnd, 1540 positiveButtonText, 1541 negativeButtonText, 1542 neutralButtonText, 1543 wifiEnableRequestCallback, 1544 mWifiThreadRunner); 1545 } 1546 if (simpleTimeoutSpecified) { 1547 simpleDialogHandle.launchDialog(simpleTimeoutMs); 1548 pw.println("Launched dialog with " + simpleTimeoutMs + " millisecond" 1549 + " timeout. Waiting for user response..."); 1550 pw.flush(); 1551 String dialogResponse = simpleQueue.take(); 1552 if (dialogResponse == null) { 1553 pw.println("No response received."); 1554 } else { 1555 pw.println(dialogResponse); 1556 } 1557 } else { 1558 simpleDialogHandle.launchDialog(); 1559 pw.println("Launched dialog. Waiting up to 15 seconds for user response" 1560 + " before dismissing..."); 1561 pw.flush(); 1562 String dialogResponse = simpleQueue.poll(15, TimeUnit.SECONDS); 1563 if (dialogResponse == null) { 1564 pw.println("No response received. Dismissing dialog."); 1565 simpleDialogHandle.dismissDialog(); 1566 } else { 1567 pw.println(dialogResponse); 1568 } 1569 } 1570 return 0; 1571 case "launch-dialog-p2p-invitation-sent": { 1572 int displayId = Display.DEFAULT_DISPLAY; 1573 String deviceName = getNextArgRequired(); 1574 String displayPin = getNextArgRequired(); 1575 String cmdOption = getNextOption(); 1576 if (cmdOption != null && cmdOption.equals("-i")) { 1577 String displayIdStr = getNextArgRequired(); 1578 try { 1579 displayId = Integer.parseInt(displayIdStr); 1580 } catch (NumberFormatException e) { 1581 pw.println("Invalid <display-id> argument to " 1582 + "'launch-dialog-p2p-invitation-sent' " 1583 + "- must be an integer: " 1584 + displayIdStr); 1585 return -1; 1586 } 1587 DisplayManager dm = mContext.getSystemService(DisplayManager.class); 1588 Display[] displays = dm.getDisplays(); 1589 for (Display display : displays) { 1590 pw.println("Display: id=" + display.getDisplayId() + ", info=" 1591 + display.getDeviceProductInfo()); 1592 } 1593 } 1594 mWifiDialogManager.createP2pInvitationSentDialog(deviceName, displayPin, 1595 displayId).launchDialog(); 1596 pw.println("Launched dialog."); 1597 return 0; 1598 } 1599 case "launch-dialog-p2p-invitation-received": { 1600 String deviceName = getNextArgRequired(); 1601 boolean isPinRequested = false; 1602 String displayPin = null; 1603 String pinOption = getNextOption(); 1604 int displayId = Display.DEFAULT_DISPLAY; 1605 boolean p2pInvRecTimeoutSpecified = false; 1606 long p2pInvRecTimeout = 0; 1607 while (pinOption != null) { 1608 if (pinOption.equals("-p")) { 1609 isPinRequested = true; 1610 } else if (pinOption.equals("-d")) { 1611 displayPin = getNextArgRequired(); 1612 } else if (pinOption.equals("-i")) { 1613 String displayIdStr = getNextArgRequired(); 1614 try { 1615 displayId = Integer.parseInt(displayIdStr); 1616 } catch (NumberFormatException e) { 1617 pw.println("Invalid <display-id> argument to " 1618 + "'launch-dialog-p2p-invitation-received' " 1619 + "- must be an integer: " 1620 + displayIdStr); 1621 return -1; 1622 } 1623 DisplayManager dm = mContext.getSystemService(DisplayManager.class); 1624 Display[] displays = dm.getDisplays(); 1625 for (Display display : displays) { 1626 pw.println("Display: id=" + display.getDisplayId() + ", info=" 1627 + display.getDeviceProductInfo()); 1628 } 1629 } else if (pinOption.equals("-c")) { 1630 p2pInvRecTimeout = Integer.parseInt(getNextArgRequired()); 1631 p2pInvRecTimeoutSpecified = true; 1632 } else { 1633 pw.println("Ignoring unknown option " + pinOption); 1634 } 1635 pinOption = getNextOption(); 1636 } 1637 ArrayBlockingQueue<String> p2pInvRecQueue = new ArrayBlockingQueue<>(1); 1638 WifiDialogManager.P2pInvitationReceivedDialogCallback callback = 1639 new WifiDialogManager.P2pInvitationReceivedDialogCallback() { 1640 @Override 1641 public void onAccepted(@Nullable String optionalPin) { 1642 p2pInvRecQueue.offer("Invitation accepted with optionalPin=" 1643 + optionalPin); 1644 } 1645 1646 @Override 1647 public void onDeclined() { 1648 p2pInvRecQueue.offer("Invitation declined"); 1649 } 1650 }; 1651 WifiDialogManager.DialogHandle p2pInvitationReceivedDialogHandle = 1652 mWifiDialogManager.createP2pInvitationReceivedDialog( 1653 deviceName, 1654 isPinRequested, 1655 displayPin, 1656 displayId, 1657 callback, 1658 mWifiThreadRunner); 1659 if (p2pInvRecTimeoutSpecified) { 1660 p2pInvitationReceivedDialogHandle.launchDialog(p2pInvRecTimeout); 1661 pw.println("Launched dialog with " + p2pInvRecTimeout + " millisecond" 1662 + " timeout. Waiting for user response..."); 1663 pw.flush(); 1664 String dialogResponse = p2pInvRecQueue.take(); 1665 if (dialogResponse == null) { 1666 pw.println("No response received."); 1667 } else { 1668 pw.println(dialogResponse); 1669 } 1670 } else { 1671 p2pInvitationReceivedDialogHandle.launchDialog(); 1672 pw.println("Launched dialog. Waiting up to 15 seconds for user response" 1673 + " before dismissing..."); 1674 pw.flush(); 1675 String dialogResponse = p2pInvRecQueue.poll(15, TimeUnit.SECONDS); 1676 if (dialogResponse == null) { 1677 pw.println("No response received. Dismissing dialog."); 1678 p2pInvitationReceivedDialogHandle.dismissDialog(); 1679 } else { 1680 pw.println(dialogResponse); 1681 } 1682 } 1683 return 0; 1684 } 1685 case "query-interface": { 1686 String uidArg = getNextArgRequired(); 1687 int uid = 0; 1688 try { 1689 uid = Integer.parseInt(uidArg); 1690 } catch (NumberFormatException e) { 1691 pw.println( 1692 "Invalid UID specified, can't convert to an integer - " + uidArg); 1693 return -1; 1694 } 1695 String packageName = getNextArgRequired(); 1696 1697 String interfaceTypeArg = getNextArgRequired(); 1698 int interfaceType; 1699 switch (interfaceTypeArg) { 1700 case "STA": 1701 interfaceType = HDM_CREATE_IFACE_STA; 1702 break; 1703 case "AP": 1704 interfaceType = HDM_CREATE_IFACE_AP; 1705 break; 1706 case "AWARE": 1707 interfaceType = HDM_CREATE_IFACE_NAN; 1708 break; 1709 case "DIRECT": 1710 interfaceType = HDM_CREATE_IFACE_P2P; 1711 break; 1712 default: 1713 pw.println("Invalid interface type - expected STA|AP|AWARE|DIRECT: " 1714 + interfaceTypeArg); 1715 return -1; 1716 } 1717 boolean queryForNewInterface = false; 1718 String optArg = getNextArg(); 1719 if (optArg != null) { 1720 if (TextUtils.equals("-new", optArg)) { 1721 queryForNewInterface = true; 1722 } else { 1723 pw.println("Unknown extra arg --- " + optArg); 1724 return -1; 1725 } 1726 } 1727 List<Pair<Integer, WorkSource>> details = 1728 mHalDeviceManager.reportImpactToCreateIface(interfaceType, 1729 queryForNewInterface, new WorkSource(uid, packageName)); 1730 final SparseArray<String> ifaceMap = new SparseArray<String>() {{ 1731 put(HDM_CREATE_IFACE_STA, "STA"); 1732 put(HDM_CREATE_IFACE_AP, "AP"); 1733 put(HDM_CREATE_IFACE_AP_BRIDGE, "AP"); 1734 put(HDM_CREATE_IFACE_P2P, "DIRECT"); 1735 put(HDM_CREATE_IFACE_NAN, "AWARE"); 1736 }}; 1737 if (details == null) { 1738 pw.println("Can't create interface: " + interfaceTypeArg); 1739 } else if (details.size() == 0) { 1740 pw.println("Interface " + interfaceTypeArg 1741 + " can be created without destroying any other interfaces"); 1742 } else { 1743 pw.println("Interface " + interfaceTypeArg 1744 + " can be created. Following interfaces will be destroyed:"); 1745 for (Pair<Integer, WorkSource> detail : details) { 1746 pw.println(" Type=" + ifaceMap.get(detail.first) + ", WS=" 1747 + detail.second); 1748 } 1749 } 1750 return 0; 1751 } 1752 case "interface-priority-interactive-mode": { 1753 String flag = getNextArgRequired(); // enable|disable|default 1754 switch (flag) { 1755 case "enable": 1756 mInterfaceConflictManager.setUserApprovalNeededOverride(true, true); 1757 break; 1758 case "disable": 1759 mInterfaceConflictManager.setUserApprovalNeededOverride(true, false); 1760 break; 1761 case "default": 1762 mInterfaceConflictManager.setUserApprovalNeededOverride( 1763 false, /* don't care */ false); 1764 break; 1765 default: 1766 pw.println( 1767 "Invalid argument to `interface-priority-interactive-mode` - " 1768 + flag); 1769 return -1; 1770 } 1771 return 0; 1772 } 1773 case "set-one-shot-screen-on-delay-ms": { 1774 if (!SdkLevel.isAtLeastT()) { 1775 pw.println("This feature is only supported on SdkLevel T or later."); 1776 return -1; 1777 } 1778 int delay = Integer.parseInt(getNextArgRequired()); 1779 mWifiService.setOneShotScreenOnConnectivityScanDelayMillis(delay); 1780 return 0; 1781 } 1782 case "set-network-selection-config": { 1783 if (!SdkLevel.isAtLeastT()) { 1784 pw.println("This feature is only supported on SdkLevel T or later."); 1785 return -1; 1786 } 1787 WifiNetworkSelectionConfig.Builder builder = 1788 new WifiNetworkSelectionConfig.Builder(); 1789 builder.setSufficiencyCheckEnabledWhenScreenOff(getNextArgRequiredTrueOrFalse( 1790 "enabled", "disabled")); 1791 builder.setSufficiencyCheckEnabledWhenScreenOn(getNextArgRequiredTrueOrFalse( 1792 "enabled", "disabled")); 1793 1794 String option = getNextOption(); 1795 while (option != null) { 1796 if (option.equals("-a")) { 1797 String associatedNetworkSelectionOverride = getNextArgRequired(); 1798 int override = Integer.parseInt(associatedNetworkSelectionOverride); 1799 builder.setAssociatedNetworkSelectionOverride(override); 1800 } else { 1801 pw.println("Ignoring unknown option " + option); 1802 } 1803 option = getNextOption(); 1804 } 1805 WifiNetworkSelectionConfig nsConfig; 1806 try { 1807 nsConfig = builder.build(); 1808 } catch (Exception e) { 1809 pw.println("Failed to build wifi network selection config."); 1810 return -1; 1811 } 1812 mWifiService.setNetworkSelectionConfig(nsConfig); 1813 return 0; 1814 } 1815 case "start-dpp-enrollee-responder": { 1816 CountDownLatch countDownLatch = new CountDownLatch(1); 1817 String option = getNextOption(); 1818 String info = null; 1819 int curve = 0; 1820 while (option != null) { 1821 if (option.equals("-i")) { 1822 info = getNextArgRequired(); 1823 } else if (option.equals("-c")) { 1824 curve = Integer.parseInt(getNextArgRequired()); 1825 } else { 1826 pw.println("Ignoring unknown option " + option); 1827 } 1828 option = getNextOption(); 1829 } 1830 mWifiService.startDppAsEnrolleeResponder(new Binder(), info, curve, 1831 new DppCallbackProxy(pw, countDownLatch)); 1832 // Wait for DPP callback 1833 countDownLatch.await(10000, TimeUnit.MILLISECONDS); 1834 return 0; 1835 } 1836 case "start-dpp-configurator-initiator": { 1837 CountDownLatch countDownLatch = new CountDownLatch(1); 1838 int netId = Integer.parseInt(getNextArgRequired()); 1839 int role = Integer.parseInt(getNextArgRequired()); 1840 String enrolleeUri = getNextArgRequired(); 1841 mWifiService.startDppAsConfiguratorInitiator(new Binder(), SHELL_PACKAGE_NAME, 1842 enrolleeUri, netId, role, new DppCallbackProxy(pw, countDownLatch)); 1843 // Wait for DPP callback 1844 countDownLatch.await(10000, TimeUnit.MILLISECONDS); 1845 return 0; 1846 } 1847 case "stop-dpp": 1848 mWifiService.stopDppSession(); 1849 return 0; 1850 case "set-ssid-charset": 1851 String lang = getNextArgRequired(); 1852 Charset charset = Charset.forName(getNextArgRequired()); 1853 mSsidTranslator.setMockLocaleCharset(lang, charset); 1854 return 0; 1855 case "clear-ssid-charsets": 1856 mSsidTranslator.clearMockLocaleCharsets(); 1857 return 0; 1858 case "take-bugreport": { 1859 if (mDeviceConfig.isInterfaceFailureBugreportEnabled()) { 1860 mWifiDiagnostics.takeBugReport("Wifi bugreport test", ""); 1861 } 1862 return 0; 1863 } 1864 case "get-allowed-channel": { 1865 StringBuilder allowedChannel = new StringBuilder(); 1866 int band = WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ; 1867 1868 String option = getNextOption(); 1869 while (option != null) { 1870 if (option.equals("-b")) { 1871 band = Integer.parseInt(getNextArgRequired()); 1872 } else { 1873 pw.println("Ignoring unknown option: " + option); 1874 return -1; 1875 } 1876 option = getNextOption(); 1877 } 1878 1879 try { 1880 Bundle extras = new Bundle(); 1881 if (SdkLevel.isAtLeastS()) { 1882 extras.putParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 1883 mContext.getAttributionSource()); 1884 } else { 1885 throw new UnsupportedOperationException(); 1886 } 1887 // The option "-b 2" (getting band 5ghz active channels) is valid for old 1888 // devices, but invalid for new devices. So we first check if device 1889 // supports getUsableChannels() API. 1890 mWifiService.getUsableChannels(WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ, 1891 WifiAvailableChannel.OP_MODE_STA, 1892 WifiAvailableChannel.FILTER_REGULATORY, SHELL_PACKAGE_NAME, extras); 1893 try { 1894 for (int opMode : OP_MODE_LIST) { 1895 List<WifiAvailableChannel> usableChannels = 1896 mWifiService.getUsableChannels(band, opMode, 1897 WifiAvailableChannel.FILTER_REGULATORY, 1898 SHELL_PACKAGE_NAME, extras); 1899 allowedChannel = new StringBuilder(); 1900 for (WifiAvailableChannel channel : usableChannels) { 1901 allowedChannel.append(channel.getFrequencyMhz()).append(" "); 1902 } 1903 pw.println("Allowed ch in " + getOpModeName(opMode) + " mode:\n" 1904 + allowedChannel); 1905 } 1906 } catch (IllegalArgumentException e) { 1907 pw.println("Invalid band: " + band); 1908 return -1; 1909 } 1910 } catch (UnsupportedOperationException e) { 1911 WifiScanner wifiScanner = mContext.getSystemService(WifiScanner.class); 1912 try { 1913 List<Integer> availableChannels = wifiScanner.getAvailableChannels( 1914 band); 1915 for (Integer channel : availableChannels) { 1916 allowedChannel.append(channel).append(" "); 1917 } 1918 pw.println("Allowed ch in all modes:\n" + allowedChannel); 1919 } catch (SecurityException securityException) { 1920 pw.println("Permission is required."); 1921 return -1; 1922 } 1923 } catch (SecurityException e) { 1924 pw.println("Permission is required."); 1925 return -1; 1926 } 1927 return 0; 1928 } 1929 case "trigger-afc-location-update": 1930 Double longitude = Double.parseDouble(getNextArgRequired()); 1931 Double latitude = Double.parseDouble(getNextArgRequired()); 1932 Double height = Double.parseDouble(getNextArgRequired()); 1933 Location location = new Location(LocationManager.FUSED_PROVIDER); 1934 location.setLongitude(longitude); 1935 location.setLatitude(latitude); 1936 location.setAltitude(height); 1937 mWifiThreadRunner.post(() -> mAfcManager.onLocationChange(location, true), 1938 TAG + "#" + cmd); 1939 pw.println("The updated location with longitude of " + longitude + " degrees, " 1940 + "latitude of " + latitude + " degrees, and height of " + height 1941 + " meters was passed into the Afc Manager onLocationChange method."); 1942 return 0; 1943 case "set-afc-channel-allowance": { 1944 WifiChip.AfcChannelAllowance afcChannelAllowance = 1945 new WifiChip.AfcChannelAllowance(); 1946 boolean expiryTimeArgumentIncluded = false; 1947 boolean frequencyOrChannelArgumentIncluded = false; 1948 afcChannelAllowance.availableAfcFrequencyInfos = new ArrayList<>(); 1949 afcChannelAllowance.availableAfcChannelInfos = new ArrayList<>(); 1950 1951 String option; 1952 while ((option = getNextOption()) != null) { 1953 switch (option) { 1954 case "-e": { 1955 int secondsUntilExpiry = Integer.parseInt(getNextArgRequired()); 1956 // AfcChannelAllowance requires this field to be a UNIX timestamp 1957 // in milliseconds. 1958 afcChannelAllowance.availabilityExpireTimeMs = 1959 System.currentTimeMillis() + secondsUntilExpiry * 1000; 1960 expiryTimeArgumentIncluded = true; 1961 1962 break; 1963 } 1964 case "-f": { 1965 frequencyOrChannelArgumentIncluded = true; 1966 String frequenciesInput = getNextArgRequired(); 1967 1968 if (frequenciesInput.equals(("none"))) { 1969 break; 1970 } 1971 1972 // parse frequency list, and add it to the AfcChannelAllowance 1973 String[] unparsedFrequencies = frequenciesInput.split(":"); 1974 afcChannelAllowance.availableAfcFrequencyInfos = new ArrayList<>(); 1975 1976 for (int i = 0; i < unparsedFrequencies.length; ++i) { 1977 String[] frequencyPieces = unparsedFrequencies[i].split(","); 1978 1979 if (frequencyPieces.length != 3) { 1980 throw new IllegalArgumentException("Each frequency in the " 1981 + "available frequency list should have 3 values, " 1982 + "but found one with " + frequencyPieces.length); 1983 } 1984 1985 WifiChip.AvailableAfcFrequencyInfo frequencyInfo = new 1986 WifiChip.AvailableAfcFrequencyInfo(); 1987 1988 frequencyInfo.startFrequencyMhz = 1989 Integer.parseInt(frequencyPieces[0]); 1990 frequencyInfo.endFrequencyMhz = 1991 Integer.parseInt(frequencyPieces[1]); 1992 frequencyInfo.maxPsdDbmPerMhz = 1993 Integer.parseInt(frequencyPieces[2]); 1994 1995 afcChannelAllowance.availableAfcFrequencyInfos 1996 .add(frequencyInfo); 1997 } 1998 1999 break; 2000 } 2001 case "-c": { 2002 frequencyOrChannelArgumentIncluded = true; 2003 String channelsInput = getNextArgRequired(); 2004 2005 if (channelsInput.equals("none")) { 2006 break; 2007 } 2008 2009 // parse channel list, and add it to the AfcChannelAllowance 2010 String[] unparsedChannels = channelsInput.split(":"); 2011 afcChannelAllowance.availableAfcChannelInfos = new ArrayList<>(); 2012 2013 for (int i = 0; i < unparsedChannels.length; ++i) { 2014 String[] channelPieces = unparsedChannels[i].split(","); 2015 2016 if (channelPieces.length != 3) { 2017 throw new IllegalArgumentException("Each channel in the " 2018 + "available channel list should have 3 values, " 2019 + "but found one with " + channelPieces.length); 2020 } 2021 2022 WifiChip.AvailableAfcChannelInfo channelInfo = new 2023 WifiChip.AvailableAfcChannelInfo(); 2024 2025 channelInfo.globalOperatingClass = 2026 Integer.parseInt(channelPieces[0]); 2027 channelInfo.channelCfi = Integer.parseInt(channelPieces[1]); 2028 channelInfo.maxEirpDbm = Integer.parseInt(channelPieces[2]); 2029 2030 afcChannelAllowance.availableAfcChannelInfos.add(channelInfo); 2031 } 2032 2033 break; 2034 } 2035 default: { 2036 pw.println("Unrecognized command line argument."); 2037 return -1; 2038 } 2039 } 2040 } 2041 if (!expiryTimeArgumentIncluded) { 2042 pw.println("Please include the -e flag to set the seconds until the " 2043 + "availability expires."); 2044 return -1; 2045 } 2046 if (!frequencyOrChannelArgumentIncluded) { 2047 pw.println("Please include at least one of the -f or -c flags to set the " 2048 + "frequency or channel availability."); 2049 return -1; 2050 } 2051 2052 ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1); 2053 mWifiThreadRunner.post(() -> { 2054 if (mWifiNative.setAfcChannelAllowance(afcChannelAllowance)) { 2055 queue.offer("Successfully set the allowed AFC channels and " 2056 + "frequencies."); 2057 } else { 2058 queue.offer("Setting the allowed AFC channels and frequencies " 2059 + "failed."); 2060 } 2061 }, TAG + "#" + cmd); 2062 2063 // block until msg is received, or timed out 2064 String msg = queue.poll(3000, TimeUnit.MILLISECONDS); 2065 if (msg == null) { 2066 pw.println("Setting the allowed AFC channels and frequencies timed out."); 2067 } else { 2068 pw.println(msg); 2069 } 2070 2071 return 0; 2072 } 2073 case "get-cached-scan-data": 2074 WifiScanner.ScanData scanData = 2075 mWifiNative.getCachedScanResultsFromAllClientIfaces(); 2076 2077 if (scanData.getResults().length > 0) { 2078 pw.println("Successfully get cached scan data: "); 2079 for (ScanResult scanResult : scanData.getResults()) { 2080 pw.println(scanResult); 2081 } 2082 } else { 2083 pw.println("Cached scan data is empty"); 2084 } 2085 return 0; 2086 case "configure-afc-server": 2087 final String url = getNextArgRequired(); 2088 2089 if (!url.startsWith("http")) { 2090 pw.println("The required URL first argument is not a valid server URL for" 2091 + " a HTTP request."); 2092 return -1; 2093 } 2094 2095 String secondOption = getNextOption(); 2096 Map<String, String> requestProperties = new HashMap<>(); 2097 if (secondOption != null && secondOption.equals("-r")) { 2098 2099 String key = getNextArg(); 2100 while (key != null) { 2101 2102 String value = getNextArg(); 2103 // Check if there is a next value 2104 if (value != null) { 2105 requestProperties.put(key, value); 2106 } else { 2107 // Fail to proceed as there is no value given for the corresponding 2108 // key 2109 pw.println( 2110 "No value provided for the corresponding key " + key 2111 + ". There must be an even number of request" 2112 + " property arguments provided after the -r " 2113 + "option."); 2114 return -1; 2115 } 2116 key = getNextArg(); 2117 } 2118 2119 } else { 2120 pw.println("No -r option was provided as second argument so the HTTP " 2121 + "request will have no request properties."); 2122 } 2123 2124 mWifiThreadRunner.post(() -> { 2125 mAfcManager.setServerUrlAndRequestPropertyPairs(url, requestProperties); 2126 }, TAG + "#" + cmd); 2127 2128 pw.println("The URL is set to " + url); 2129 pw.println("The request properties are set to: "); 2130 2131 for (Map.Entry<String, String> requestProperty : requestProperties.entrySet()) { 2132 pw.println("Key: " + requestProperty.getKey() + ", Value: " 2133 + requestProperty.getValue()); 2134 } 2135 return 0; 2136 case "set-mock-wifimodem-service": 2137 String opt = null; 2138 String serviceName = null; 2139 while ((opt = getNextOption()) != null) { 2140 switch (opt) { 2141 case "-s": { 2142 serviceName = getNextArgRequired(); 2143 break; 2144 } 2145 default: 2146 pw.println("set-mock-wifimodem-service requires '-s' option"); 2147 return -1; 2148 } 2149 } 2150 mWifiService.setMockWifiService(serviceName); 2151 // The result will be checked, must print result "true" 2152 pw.print("true"); 2153 return 0; 2154 case "get-mock-wifimodem-service": 2155 pw.print(mWifiNative.getMockWifiServiceName()); 2156 return 0; 2157 case "set-mock-wifimodem-methods": 2158 String methods = getNextArgRequired(); 2159 if (mWifiService.setMockWifiMethods(methods)) { 2160 pw.print("true"); 2161 } else { 2162 pw.print("fail to set mock method: " + methods); 2163 return -1; 2164 } 2165 return 0; 2166 case "force-overlay-config-value": 2167 int uid = Binder.getCallingUid(); 2168 if (!mWifiInjector.getWifiPermissionsUtil() 2169 .checkNetworkSettingsPermission(Binder.getCallingUid())) { 2170 pw.println("current shell caller Uid " + uid 2171 + " Missing NETWORK_SETTINGS permission"); 2172 return -1; 2173 } 2174 WifiResourceCache resourceCache = mContext.getResourceCache(); 2175 String type = getNextArgRequired(); 2176 String overlayName = getNextArgRequired(); 2177 boolean isEnabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); 2178 switch (type) { 2179 case "bool" -> { 2180 boolean value = false; 2181 if (isEnabled) { 2182 value = getNextArgRequiredTrueOrFalse("true", "false"); 2183 resourceCache.overrideBooleanValue(overlayName, value); 2184 } else { 2185 resourceCache.restoreBooleanValue(overlayName); 2186 } 2187 } 2188 case "integer" -> { 2189 int value = 0; 2190 if (isEnabled) { 2191 value = Integer.parseInt(getNextArgRequired()); 2192 resourceCache.overrideIntegerValue(overlayName, value); 2193 } else { 2194 resourceCache.restoreIntegerValue(overlayName); 2195 } 2196 } 2197 default -> { 2198 pw.print("require a valid type of the overlay"); 2199 return -1; 2200 } 2201 } 2202 pw.println("true"); 2203 return 0; 2204 case "get-overlay-config-values": 2205 mContext.getResourceCache().dump(pw); 2206 return 0; 2207 default: 2208 return handleDefaultCommands(cmd); 2209 } 2210 } catch (IllegalArgumentException e) { 2211 pw.println("Invalid args for " + cmd + ": " + e); 2212 return -1; 2213 } catch (Exception e) { 2214 pw.println("Exception while executing WifiShellCommand: "); 2215 e.printStackTrace(pw); 2216 return -1; 2217 } 2218 } 2219 getNextArgRequiredTrueOrFalse(String trueString, String falseString)2220 private boolean getNextArgRequiredTrueOrFalse(String trueString, String falseString) 2221 throws IllegalArgumentException { 2222 String nextArg = getNextArgRequired(); 2223 if (trueString.equals(nextArg)) { 2224 return true; 2225 } else if (falseString.equals(nextArg)) { 2226 return false; 2227 } else { 2228 throw new IllegalArgumentException("Expected '" + trueString + "' or '" + falseString 2229 + "' as next arg but got '" + nextArg + "'"); 2230 } 2231 } 2232 buildWifiConfiguration(PrintWriter pw)2233 private WifiConfiguration buildWifiConfiguration(PrintWriter pw) { 2234 String ssid = getNextArgRequired(); 2235 String type = getNextArgRequired(); 2236 WifiConfiguration configuration = new WifiConfiguration(); 2237 // Wrap the SSID in double quotes for UTF-8. The quotes may be removed if the SSID is in 2238 // hexadecimal digits, specified by the [-x] option below. 2239 configuration.SSID = "\"" + ssid + "\""; 2240 if (TextUtils.equals(type, "wpa3")) { 2241 configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); 2242 configuration.preSharedKey = "\"" + getNextArgRequired() + "\""; 2243 } else if (TextUtils.equals(type, "wpa2")) { 2244 configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); 2245 configuration.preSharedKey = "\"" + getNextArgRequired() + "\""; 2246 } else if (TextUtils.equals(type, "owe")) { 2247 configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE); 2248 } else if (TextUtils.equals(type, "open")) { 2249 configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); 2250 } else if (TextUtils.equals(type, "dpp")) { 2251 configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_DPP); 2252 } else if (TextUtils.equals(type, "wep")) { 2253 configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WEP); 2254 String password = getNextArgRequired(); 2255 // WEP-40, WEP-104, and WEP-256 2256 if ((password.length() == 10 || password.length() == 26 || password.length() == 58) 2257 && password.matches("[0-9A-Fa-f]*")) { 2258 configuration.wepKeys[0] = password; 2259 } else { 2260 configuration.wepKeys[0] = '"' + password + '"'; 2261 } 2262 } else { 2263 throw new IllegalArgumentException("Unknown network type " + type); 2264 } 2265 String option = getNextOption(); 2266 while (option != null) { 2267 if (option.equals("-x")) { 2268 configuration.SSID = ssid; 2269 } else if (option.equals("-m")) { 2270 configuration.meteredOverride = METERED_OVERRIDE_METERED; 2271 } else if (option.equals("-d")) { 2272 configuration.allowAutojoin = false; 2273 } else if (option.equals("-b")) { 2274 configuration.BSSID = getNextArgRequired(); 2275 } else if (option.equals("-r")) { 2276 String macRandomizationScheme = getNextArgRequired(); 2277 if (macRandomizationScheme.equals("auto")) { 2278 configuration.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO; 2279 } else if (macRandomizationScheme.equals("none")) { 2280 configuration.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; 2281 } else if (macRandomizationScheme.equals("persistent")) { 2282 configuration.macRandomizationSetting = 2283 WifiConfiguration.RANDOMIZATION_PERSISTENT; 2284 } else if (macRandomizationScheme.equals("non_persistent")) { 2285 if (SdkLevel.isAtLeastS()) { 2286 configuration.macRandomizationSetting = 2287 WifiConfiguration.RANDOMIZATION_NON_PERSISTENT; 2288 } else { 2289 throw new IllegalArgumentException( 2290 "-r non_persistent MAC randomization not supported before S"); 2291 } 2292 } 2293 } else if (option.equals("-h")) { 2294 configuration.hiddenSSID = true; 2295 } else if (option.equals("-p")) { 2296 configuration.shared = false; 2297 } else { 2298 pw.println("Ignoring unknown option " + option); 2299 } 2300 option = getNextOption(); 2301 } 2302 return configuration; 2303 } 2304 buildSoftApConfiguration(PrintWriter pw)2305 private SoftApConfiguration buildSoftApConfiguration(PrintWriter pw) { 2306 String ssidStr = getNextArgRequired(); 2307 String type = getNextArgRequired(); 2308 SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); 2309 configBuilder.setSsid(ssidStr); 2310 if (TextUtils.equals(type, "wpa2")) { 2311 configBuilder.setPassphrase(getNextArgRequired(), 2312 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); 2313 } else if (TextUtils.equals(type, "wpa3")) { 2314 configBuilder.setPassphrase(getNextArgRequired(), 2315 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); 2316 } else if (TextUtils.equals(type, "wpa3_transition")) { 2317 configBuilder.setPassphrase(getNextArgRequired(), 2318 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); 2319 } else if (TextUtils.equals(type, "open")) { 2320 configBuilder.setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN); 2321 } else if (TextUtils.equals(type, "owe_transition")) { 2322 configBuilder.setPassphrase(null, 2323 SoftApConfiguration.SECURITY_TYPE_WPA3_OWE_TRANSITION); 2324 } else if (TextUtils.equals(type, "owe")) { 2325 configBuilder.setPassphrase(null, 2326 SoftApConfiguration.SECURITY_TYPE_WPA3_OWE); 2327 } else { 2328 throw new IllegalArgumentException("Unknown network type " + type); 2329 } 2330 String option = getNextOption(); 2331 while (option != null) { 2332 if (option.equals("-b")) { 2333 String preferredBand = getNextArgRequired(); 2334 if (preferredBand.equals("2")) { 2335 configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); 2336 } else if (preferredBand.equals("5")) { 2337 configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); 2338 } else if (preferredBand.equals("6")) { 2339 configBuilder.setBand(SoftApConfiguration.BAND_6GHZ); 2340 } else if (preferredBand.equals("any")) { 2341 configBuilder.setBand(SoftApConfiguration.BAND_2GHZ 2342 | SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_6GHZ); 2343 } else if (preferredBand.startsWith("bridged")) { 2344 if (!SdkLevel.isAtLeastS()) { 2345 throw new IllegalArgumentException( 2346 "-b bridged* option is not supported before S"); 2347 } 2348 switch (preferredBand) { 2349 case "bridged": 2350 // fall through 2351 case "bridged_2_5": 2352 configBuilder.setBands(new int[] { 2353 SoftApConfiguration.BAND_2GHZ, SoftApConfiguration.BAND_5GHZ}); 2354 break; 2355 case "bridged_2_6": 2356 configBuilder.setBands(new int[] { 2357 SoftApConfiguration.BAND_2GHZ, SoftApConfiguration.BAND_6GHZ}); 2358 break; 2359 case "bridged_5_6": 2360 configBuilder.setBands(new int[] { 2361 SoftApConfiguration.BAND_5GHZ, SoftApConfiguration.BAND_6GHZ}); 2362 break; 2363 default: 2364 throw new IllegalArgumentException("Invalid bridged band option " 2365 + preferredBand); 2366 } 2367 } else { 2368 throw new IllegalArgumentException("Invalid band option " + preferredBand); 2369 } 2370 } else if (SdkLevel.isAtLeastT() && option.equals("-x")) { 2371 configBuilder.setWifiSsid(WifiSsid.fromString(ssidStr)); 2372 } else if (option.equals("-f")) { 2373 SparseIntArray channels = new SparseIntArray(); 2374 while (getRemainingArgsCount() > 0) { 2375 int apChannelMHz; 2376 try { 2377 apChannelMHz = Integer.parseInt(getNextArgRequired()); 2378 } catch (NumberFormatException e) { 2379 throw new IllegalArgumentException( 2380 "-f option requires a valid channel frequency"); 2381 } 2382 channels.put(ApConfigUtil.convertFrequencyToBand(apChannelMHz), 2383 ScanResult.convertFrequencyMhzToChannelIfSupported(apChannelMHz)); 2384 } 2385 if (channels.size() == 0) { 2386 throw new IllegalArgumentException( 2387 "-f option requires a valid channel frequency atleast"); 2388 } 2389 if (SdkLevel.isAtLeastS()) { 2390 configBuilder.setChannels(channels); 2391 } else { 2392 if (channels.size() > 1) { 2393 throw new IllegalArgumentException( 2394 "dual channels are not supported before S"); 2395 } 2396 configBuilder.setChannel(channels.valueAt(0), channels.keyAt(0)); 2397 } 2398 } else if (option.equals("-w")) { 2399 String bandwidth = getNextArgRequired(); 2400 if (bandwidth.equals("20")) { 2401 configBuilder.setMaxChannelBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ); 2402 } else if (bandwidth.equals("40")) { 2403 configBuilder.setMaxChannelBandwidth(SoftApInfo.CHANNEL_WIDTH_40MHZ); 2404 } else if (bandwidth.equals("80")) { 2405 configBuilder.setMaxChannelBandwidth(SoftApInfo.CHANNEL_WIDTH_80MHZ); 2406 } else if (bandwidth.equals("160")) { 2407 configBuilder.setMaxChannelBandwidth(SoftApInfo.CHANNEL_WIDTH_160MHZ); 2408 } else if (bandwidth.equals("320")) { 2409 configBuilder.setMaxChannelBandwidth(SoftApInfo.CHANNEL_WIDTH_320MHZ); 2410 } else { 2411 throw new IllegalArgumentException("Invalid bandwidth option " + bandwidth); 2412 } 2413 } else { 2414 pw.println("Ignoring unknown option " + option); 2415 } 2416 option = getNextOption(); 2417 } 2418 return configBuilder.build(); 2419 } 2420 buildSuggestion(PrintWriter pw)2421 private WifiNetworkSuggestion buildSuggestion(PrintWriter pw) { 2422 String ssid = getNextArgRequired(); 2423 String type = getNextArgRequired(); 2424 WifiNetworkSuggestion.Builder suggestionBuilder = 2425 new WifiNetworkSuggestion.Builder(); 2426 suggestionBuilder.setSsid(ssid); 2427 if (TextUtils.equals(type, "wpa3")) { 2428 suggestionBuilder.setWpa3Passphrase(getNextArgRequired()); 2429 } else if (TextUtils.equals(type, "wpa2")) { 2430 suggestionBuilder.setWpa2Passphrase(getNextArgRequired()); 2431 } else if (TextUtils.equals(type, "owe")) { 2432 suggestionBuilder.setIsEnhancedOpen(true); 2433 } else if (TextUtils.equals(type, "open")) { 2434 // nothing to do. 2435 } else { 2436 throw new IllegalArgumentException("Unknown network type " + type); 2437 } 2438 boolean isCarrierMerged = false; 2439 String option = getNextOption(); 2440 while (option != null) { 2441 if (option.equals("-u")) { 2442 suggestionBuilder.setUntrusted(true); 2443 } else if (option.equals("-o")) { 2444 if (SdkLevel.isAtLeastS()) { 2445 suggestionBuilder.setOemPaid(true); 2446 } else { 2447 throw new IllegalArgumentException( 2448 "-o OEM paid suggestions not supported before S"); 2449 } 2450 } else if (option.equals("-p")) { 2451 if (SdkLevel.isAtLeastS()) { 2452 suggestionBuilder.setOemPrivate(true); 2453 } else { 2454 throw new IllegalArgumentException( 2455 "-p OEM private suggestions not supported before S"); 2456 } 2457 } else if (option.equals("-m")) { 2458 suggestionBuilder.setIsMetered(true); 2459 } else if (option.equals("-s")) { 2460 suggestionBuilder.setCredentialSharedWithUser(true); 2461 } else if (option.equals("-d")) { 2462 suggestionBuilder.setIsInitialAutojoinEnabled(false); 2463 } else if (option.equals("-b")) { 2464 suggestionBuilder.setBssid(MacAddress.fromString(getNextArgRequired())); 2465 } else if (option.equals("-r")) { 2466 if (SdkLevel.isAtLeastS()) { 2467 suggestionBuilder.setMacRandomizationSetting( 2468 WifiNetworkSuggestion.RANDOMIZATION_NON_PERSISTENT); 2469 } else { 2470 throw new IllegalArgumentException( 2471 "-r non_persistent MAC randomization not supported before S"); 2472 } 2473 } else if (option.equals("-a")) { 2474 if (SdkLevel.isAtLeastS()) { 2475 isCarrierMerged = true; 2476 } else { 2477 throw new IllegalArgumentException("-a option is not supported before S"); 2478 } 2479 } else if (option.equals("-i")) { 2480 if (SdkLevel.isAtLeastS()) { 2481 int subId = Integer.parseInt(getNextArgRequired()); 2482 suggestionBuilder.setSubscriptionId(subId); 2483 } else { 2484 throw new IllegalArgumentException( 2485 "-i subscription ID option is not supported before S"); 2486 } 2487 } else if (option.equals("-c")) { 2488 int carrierId = Integer.parseInt(getNextArgRequired()); 2489 suggestionBuilder.setCarrierId(carrierId); 2490 } else if (option.equals("-h")) { 2491 suggestionBuilder.setIsHiddenSsid(true); 2492 } else { 2493 pw.println("Ignoring unknown option " + option); 2494 } 2495 option = getNextOption(); 2496 } 2497 WifiNetworkSuggestion suggestion = suggestionBuilder.build(); 2498 if (isCarrierMerged) { 2499 if (suggestion.wifiConfiguration.subscriptionId 2500 == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 2501 pw.println("Carrier merged network must have valid subscription Id"); 2502 return null; 2503 } 2504 suggestion.wifiConfiguration.carrierMerged = true; 2505 } 2506 return suggestion; 2507 } 2508 buildNetworkRequest(PrintWriter pw)2509 private Pair<String, NetworkRequest> buildNetworkRequest(PrintWriter pw) { 2510 String firstOpt = getNextOption(); 2511 boolean isGlob = "-g".equals(firstOpt); 2512 boolean noSsid = "-s".equals(firstOpt); 2513 String ssid = noSsid ? "NoSsid" : getNextArgRequired(); 2514 String type = noSsid ? null : getNextArgRequired(); 2515 WifiNetworkSpecifier.Builder specifierBuilder = 2516 new WifiNetworkSpecifier.Builder(); 2517 if (isGlob) { 2518 specifierBuilder.setSsidPattern( 2519 new PatternMatcher(ssid, PatternMatcher.PATTERN_ADVANCED_GLOB)); 2520 } else { 2521 if (ssid != null && !noSsid) specifierBuilder.setSsid(ssid); 2522 } 2523 if (type != null) { 2524 if (TextUtils.equals(type, "wpa3")) { 2525 specifierBuilder.setWpa3Passphrase(getNextArgRequired()); 2526 } else if (TextUtils.equals(type, "wpa3_transition")) { 2527 specifierBuilder.setWpa3Passphrase(getNextArgRequired()); 2528 } else if (TextUtils.equals(type, "wpa2")) { 2529 specifierBuilder.setWpa2Passphrase(getNextArgRequired()); 2530 } else if (TextUtils.equals(type, "owe")) { 2531 specifierBuilder.setIsEnhancedOpen(true); 2532 } else if (TextUtils.equals(type, "open")) { 2533 // nothing to do. 2534 } else { 2535 throw new IllegalArgumentException("Unknown network type " + type); 2536 } 2537 } 2538 String bssid = null; 2539 String option = getNextOption(); 2540 String ssidKey = ssid; 2541 boolean nullBssid = false; 2542 boolean hasInternet = false; 2543 while (option != null) { 2544 if (option.equals("-b")) { 2545 bssid = getNextArgRequired(); 2546 } else if (option.equals("-n")) { 2547 nullBssid = true; 2548 } else if (option.equals("-d")) { 2549 String band = getNextArgRequired(); 2550 ssidKey = ssidKey + "_" + band + "g"; 2551 if (band.equals("2")) { 2552 specifierBuilder.setBand(ScanResult.WIFI_BAND_24_GHZ); 2553 } else if (band.equals("5")) { 2554 specifierBuilder.setBand(ScanResult.WIFI_BAND_5_GHZ); 2555 } else if (band.equals("6")) { 2556 specifierBuilder.setBand(ScanResult.WIFI_BAND_6_GHZ); 2557 } else if (band.equals("60")) { 2558 specifierBuilder.setBand(ScanResult.WIFI_BAND_60_GHZ); 2559 } else { 2560 throw new IllegalArgumentException("Unknown band " + band); 2561 } 2562 } else if (option.equals("-i")) { 2563 ssidKey = ssidKey + "_internet"; 2564 hasInternet = true; 2565 } else { 2566 pw.println("Ignoring unknown option " + option); 2567 } 2568 option = getNextOption(); 2569 } 2570 if (bssid != null && nullBssid) { 2571 throw new IllegalArgumentException("Invalid option combination: " 2572 + "Should not use both -b and -n at the same time."); 2573 } 2574 2575 // Permission approval bypass is only available to requests with both ssid & bssid set. 2576 // So, find scan result with the best rssi level to set in the request. 2577 if (bssid == null && !nullBssid && !noSsid) { 2578 ScanResult matchingScanResult = 2579 mScanRequestProxy.getScanResults() 2580 .stream() 2581 .filter(s -> s.SSID.equals(ssid)) 2582 .max(Comparator.comparingInt(s -> s.level)) 2583 .orElse(null); 2584 if (matchingScanResult != null) { 2585 bssid = matchingScanResult.BSSID; 2586 } else { 2587 pw.println("No matching bssid found, request will need UI approval"); 2588 } 2589 } 2590 if (bssid != null && !nullBssid) specifierBuilder.setBssid(MacAddress.fromString(bssid)); 2591 NetworkRequest.Builder builder = new NetworkRequest.Builder() 2592 .addTransportType(TRANSPORT_WIFI); 2593 if (hasInternet) { 2594 builder.addCapability(NET_CAPABILITY_INTERNET); 2595 } else { 2596 builder.removeCapability(NET_CAPABILITY_INTERNET); 2597 } 2598 return new Pair<String, NetworkRequest>(ssidKey, 2599 builder.setNetworkSpecifier(specifierBuilder.build()).build()); 2600 } 2601 2602 @RequiresApi(Build.VERSION_CODES.S) 2603 @NonNull buildCoexCellChannels()2604 private List<CoexUtils.CoexCellChannel> buildCoexCellChannels() { 2605 List<CoexUtils.CoexCellChannel> cellChannels = new ArrayList<>(); 2606 while (getRemainingArgsCount() > 0) { 2607 final @Annotation.NetworkType int rat; 2608 final String ratArg = getNextArgRequired(); 2609 if (TextUtils.equals(ratArg, "lte")) { 2610 rat = TelephonyManager.NETWORK_TYPE_LTE; 2611 } else if (TextUtils.equals(ratArg, "nr")) { 2612 rat = TelephonyManager.NETWORK_TYPE_NR; 2613 } else { 2614 throw new IllegalArgumentException("Unknown rat type " + ratArg); 2615 } 2616 final int band = Integer.parseInt(getNextArgRequired()); 2617 if (band < 1 || band > 261) { 2618 throw new IllegalArgumentException("Band is " + band 2619 + " but should be a value from 1 to 261"); 2620 } 2621 final int downlinkFreqKhz = Integer.parseInt(getNextArgRequired()); 2622 if (downlinkFreqKhz < 0 && downlinkFreqKhz != PhysicalChannelConfig.FREQUENCY_UNKNOWN) { 2623 throw new IllegalArgumentException("Downlink frequency is " + downlinkFreqKhz 2624 + " but should be >= 0 or UNKNOWN: " 2625 + PhysicalChannelConfig.FREQUENCY_UNKNOWN); 2626 } 2627 final int downlinkBandwidthKhz = Integer.parseInt(getNextArgRequired()); 2628 if (downlinkBandwidthKhz <= 0 2629 && downlinkBandwidthKhz != PhysicalChannelConfig.CELL_BANDWIDTH_UNKNOWN) { 2630 throw new IllegalArgumentException("Downlink bandwidth is " + downlinkBandwidthKhz 2631 + " but should be > 0 or UNKNOWN: " 2632 + PhysicalChannelConfig.CELL_BANDWIDTH_UNKNOWN); 2633 } 2634 final int uplinkFreqKhz = Integer.parseInt(getNextArgRequired()); 2635 if (uplinkFreqKhz < 0 && uplinkFreqKhz != PhysicalChannelConfig.FREQUENCY_UNKNOWN) { 2636 throw new IllegalArgumentException("Uplink frequency is " + uplinkFreqKhz 2637 + " but should be >= 0 or UNKNOWN: " 2638 + PhysicalChannelConfig.FREQUENCY_UNKNOWN); 2639 } 2640 final int uplinkBandwidthKhz = Integer.parseInt(getNextArgRequired()); 2641 if (uplinkBandwidthKhz <= 0 2642 && uplinkBandwidthKhz != PhysicalChannelConfig.CELL_BANDWIDTH_UNKNOWN) { 2643 throw new IllegalArgumentException("Uplink bandwidth is " + uplinkBandwidthKhz 2644 + " but should be > 0 or UNKNOWN: " 2645 + PhysicalChannelConfig.CELL_BANDWIDTH_UNKNOWN); 2646 } 2647 cellChannels.add(new CoexUtils.CoexCellChannel(rat, band, 2648 downlinkFreqKhz, downlinkBandwidthKhz, uplinkFreqKhz, uplinkBandwidthKhz, 2649 SubscriptionManager.INVALID_SUBSCRIPTION_ID)); 2650 } 2651 return cellChannels; 2652 } 2653 sendLinkProbe(PrintWriter pw)2654 private int sendLinkProbe(PrintWriter pw) throws InterruptedException { 2655 // Note: should match WifiNl80211Manager#SEND_MGMT_FRAME_TIMEOUT_MS 2656 final int sendMgmtFrameTimeoutMs = 1000; 2657 2658 ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1); 2659 mWifiThreadRunner.post(() -> 2660 mActiveModeWarden.getPrimaryClientModeManager().probeLink(new LinkProbeCallback() { 2661 @Override 2662 public void onAck(int elapsedTimeMs) { 2663 queue.offer("Link probe succeeded after " + elapsedTimeMs + " ms"); 2664 } 2665 2666 @Override 2667 public void onFailure(int reason) { 2668 queue.offer("Link probe failed with reason " 2669 + LinkProbeCallback.failureReasonToString(reason)); 2670 } 2671 }, -1), TAG + "#sendLinkProbe"); 2672 2673 // block until msg is received, or timed out 2674 String msg = queue.poll(sendMgmtFrameTimeoutMs + 1000, TimeUnit.MILLISECONDS); 2675 if (msg == null) { 2676 pw.println("Link probe timed out"); 2677 } else { 2678 pw.println(msg); 2679 } 2680 return 0; 2681 } 2682 isApChannelMHzValid(PrintWriter pw, int apChannelMHz)2683 private boolean isApChannelMHzValid(PrintWriter pw, int apChannelMHz) { 2684 int[] allowed2gFreq = mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ); 2685 int[] allowed5gFreq = mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ); 2686 int[] allowed5gDfsFreq = 2687 mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY); 2688 int[] allowed6gFreq = mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ); 2689 int[] allowed60gFreq = mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_60_GHZ); 2690 if (allowed2gFreq == null) { 2691 allowed2gFreq = new int[0]; 2692 } 2693 if (allowed5gFreq == null) { 2694 allowed5gFreq = new int[0]; 2695 } 2696 if (allowed5gDfsFreq == null) { 2697 allowed5gDfsFreq = new int[0]; 2698 } 2699 if (allowed6gFreq == null) { 2700 allowed6gFreq = new int[0]; 2701 } 2702 if (allowed60gFreq == null) { 2703 allowed60gFreq = new int[0]; 2704 } 2705 pw.println("2G freq: " + Arrays.toString(allowed2gFreq)); 2706 pw.println("5G freq: " + Arrays.toString(allowed5gFreq)); 2707 pw.println("5G DFS: " + Arrays.toString(allowed5gDfsFreq)); 2708 pw.println("6G freq: " + Arrays.toString(allowed6gFreq)); 2709 pw.println("60G freq: " + Arrays.toString(allowed60gFreq)); 2710 return (Arrays.binarySearch(allowed2gFreq, apChannelMHz) >= 0 2711 || Arrays.binarySearch(allowed5gFreq, apChannelMHz) >= 0 2712 || Arrays.binarySearch(allowed5gDfsFreq, apChannelMHz) >= 0) 2713 || Arrays.binarySearch(allowed6gFreq, apChannelMHz) >= 0 2714 || Arrays.binarySearch(allowed60gFreq, apChannelMHz) >= 0; 2715 } 2716 waitForWifiEnabled(boolean enabled)2717 private void waitForWifiEnabled(boolean enabled) throws InterruptedException { 2718 CountDownLatch countDownLatch = new CountDownLatch(1); 2719 BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { 2720 @Override 2721 public void onReceive(Context context, Intent intent) { 2722 String action = intent.getAction(); 2723 if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { 2724 int state = mWifiService.getWifiEnabledState(); 2725 if ((enabled && state == WIFI_STATE_ENABLED) 2726 || (!enabled && state == WIFI_STATE_DISABLED)) { 2727 countDownLatch.countDown(); 2728 } 2729 } 2730 } 2731 }; 2732 IntentFilter filter = new IntentFilter(); 2733 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 2734 mContext.registerReceiver(broadcastReceiver, filter); 2735 mWifiService.setWifiEnabled(SHELL_PACKAGE_NAME, enabled); 2736 countDownLatch.await(5000, TimeUnit.MILLISECONDS); 2737 mContext.unregisterReceiver(broadcastReceiver); 2738 } 2739 printWifiInfo(PrintWriter pw, WifiInfo info)2740 private void printWifiInfo(PrintWriter pw, WifiInfo info) { 2741 if (info.getSupplicantState() != SupplicantState.COMPLETED) { 2742 pw.println("Wifi is not connected"); 2743 return; 2744 } 2745 pw.println("Wifi is connected to " + info.getSSID()); 2746 pw.println("WifiInfo: " + info); 2747 // additional diagnostics not printed by WifiInfo.toString() 2748 pw.println("successfulTxPackets: " + info.txSuccess); 2749 pw.println("successfulTxPacketsPerSecond: " + info.getSuccessfulTxPacketsPerSecond()); 2750 pw.println("retriedTxPackets: " + info.txRetries); 2751 pw.println("retriedTxPacketsPerSecond: " + info.getRetriedTxPacketsPerSecond()); 2752 pw.println("lostTxPackets: " + info.txBad); 2753 pw.println("lostTxPacketsPerSecond: " + info.getLostTxPacketsPerSecond()); 2754 pw.println("successfulRxPackets: " + info.rxSuccess); 2755 pw.println("successfulRxPacketsPerSecond: " + info.getSuccessfulRxPacketsPerSecond()); 2756 } 2757 printStatus(PrintWriter pw)2758 private void printStatus(PrintWriter pw) { 2759 boolean wifiEnabled = mWifiService.getWifiEnabledState() == WIFI_STATE_ENABLED; 2760 pw.println("Wifi is " + (wifiEnabled ? "enabled" : "disabled")); 2761 pw.println("Wifi scanning is " 2762 + (mWifiService.isScanAlwaysAvailable() 2763 ? "always available" : "only available when wifi is enabled")); 2764 if (!wifiEnabled) { 2765 return; 2766 } 2767 if (Binder.getCallingUid() != Process.ROOT_UID) { 2768 // not privileged, just dump the primary client mode manager manager status 2769 // (public API contents). 2770 pw.println("==== Primary ClientModeManager instance ===="); 2771 printWifiInfo(pw, mWifiService.getConnectionInfo(SHELL_PACKAGE_NAME, null)); 2772 } else { 2773 // privileged, dump out all the client mode manager manager statuses 2774 for (ClientModeManager cm : mActiveModeWarden.getClientModeManagers()) { 2775 pw.println("==== ClientModeManager instance: " + cm + " ===="); 2776 WifiInfo info = cm.getConnectionInfo(); 2777 printWifiInfo(pw, info); 2778 if (info.getSupplicantState() != SupplicantState.COMPLETED) { 2779 continue; 2780 } 2781 Network network = cm.getCurrentNetwork(); 2782 NetworkCapabilities capabilities = 2783 mConnectivityManager.getNetworkCapabilities(network); 2784 pw.println("NetworkCapabilities: " + capabilities); 2785 } 2786 } 2787 } 2788 onHelpNonPrivileged(PrintWriter pw)2789 private void onHelpNonPrivileged(PrintWriter pw) { 2790 pw.println(" get-country-code"); 2791 pw.println(" Gets country code as a two-letter string"); 2792 pw.println(" set-wifi-enabled enabled|disabled"); 2793 pw.println(" Enables/disables Wifi on this device."); 2794 pw.println(" set-scan-always-available enabled|disabled"); 2795 pw.println(" Sets whether scanning should be available even when wifi is off."); 2796 pw.println(" connect-network <ssid> open|owe|wpa2|wpa3|wep [<passphrase>] [-x] [-m] " 2797 + "[-d] [-b <bssid>] [-r auto|none|persistent|non_persistent]"); 2798 pw.println(" Connect to a network with provided params and add to saved networks list"); 2799 pw.println(" <ssid> - SSID of the network"); 2800 pw.println(" open|owe|wpa2|wpa3|wep - Security type of the network."); 2801 pw.println(" - Use 'open' or 'owe' for networks with no passphrase"); 2802 pw.println(" - 'open' - Open networks (Most prevalent)"); 2803 pw.println(" - 'owe' - Enhanced open networks"); 2804 pw.println(" - Use 'wpa2' or 'wpa3' or 'wep' for networks with passphrase"); 2805 pw.println(" - 'wpa2' - WPA-2 PSK networks (Most prevalent)"); 2806 pw.println(" - 'wpa3' - WPA-3 PSK networks"); 2807 pw.println(" - 'wep' - WEP network. Passphrase should be bytes in hex or encoded" 2808 + " into String using UTF-8"); 2809 pw.println(" -x - Specifies the SSID as hex digits instead of plain text"); 2810 pw.println(" -m - Mark the network metered."); 2811 pw.println(" -d - Mark the network autojoin disabled."); 2812 pw.println(" -h - Mark the network hidden."); 2813 pw.println(" -p - Mark the network private (not shared)."); 2814 pw.println(" -b <bssid> - Set specific BSSID."); 2815 pw.println(" -r auto|none|persistent|non_persistent - MAC randomization scheme for the" 2816 + " network"); 2817 pw.println(" add-network <ssid> open|owe|wpa2|wpa3|wep [<passphrase>] [-x] [-m] [-d] " 2818 + "[-b <bssid>] [-r auto|none|persistent|non_persistent]"); 2819 pw.println(" Add/update saved network with provided params"); 2820 pw.println(" <ssid> - SSID of the network"); 2821 pw.println(" open|owe|wpa2|wpa3|wep - Security type of the network."); 2822 pw.println(" - Use 'open' or 'owe' for networks with no passphrase"); 2823 pw.println(" - 'open' - Open networks (Most prevalent)"); 2824 pw.println(" - 'owe' - Enhanced open networks"); 2825 pw.println(" - Use 'wpa2' or 'wpa3' for networks with passphrase"); 2826 pw.println(" - 'wpa2' - WPA-2 PSK networks (Most prevalent)"); 2827 pw.println(" - 'wpa3' - WPA-3 PSK networks"); 2828 pw.println(" - 'wep' - WEP network. Passphrase should be bytes in hex or encoded" 2829 + " into String using UTF-8"); 2830 pw.println(" -x - Specifies the SSID as hex digits instead of plain text"); 2831 pw.println(" -m - Mark the network metered."); 2832 pw.println(" -d - Mark the network autojoin disabled."); 2833 pw.println(" -h - Mark the network hidden."); 2834 pw.println(" -p - Mark the network private (not shared)."); 2835 pw.println(" -b <bssid> - Set specific BSSID."); 2836 pw.println(" -r auto|none|persistent|non_persistent - MAC randomization scheme for the" 2837 + " network"); 2838 pw.println(" list-scan-results"); 2839 pw.println(" Lists the latest scan results"); 2840 pw.println(" start-scan"); 2841 pw.println(" Start a new scan"); 2842 pw.println(" list-networks"); 2843 pw.println(" Lists the saved networks"); 2844 pw.println(" forget-network <networkId>"); 2845 pw.println(" Remove the network mentioned by <networkId>"); 2846 pw.println(" - Use list-networks to retrieve <networkId> for the network"); 2847 pw.println(" status"); 2848 pw.println(" Current wifi status"); 2849 pw.println(" set-verbose-logging enabled|disabled [-l <verbose log level>]"); 2850 pw.println(" Set the verbose logging enabled or disabled with log level"); 2851 pw.println(" -l - verbose logging level"); 2852 pw.println(" 0 - verbose logging disabled"); 2853 pw.println(" 1 - verbose logging enabled"); 2854 pw.println(" 2 - verbose logging Show key mode"); 2855 pw.println(" 3 - verbose logging only for Wi-Fi Aware feature"); 2856 pw.println(" is-verbose-logging"); 2857 pw.println(" Check whether verbose logging enabled or disabled"); 2858 pw.println(" start-restricting-auto-join-to-subscription-id subId"); 2859 pw.println(" temporarily disable all wifi networks except merged carrier networks with" 2860 + " the given subId"); 2861 pw.println(" stop-restricting-auto-join-to-subscription-id"); 2862 pw.println(" Undo the effects of " 2863 + "start-restricting-auto-join-to-subscription-id"); 2864 pw.println(" add-suggestion <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-u] [-o] [-p] [-m] " 2865 + " [-s] [-d] [-b <bssid>] [-e] [-i] [-a <carrierId>] [-c <subscriptionId>]"); 2866 pw.println(" Add a network suggestion with provided params"); 2867 pw.println(" Use 'network-suggestions-set-user-approved " + SHELL_PACKAGE_NAME + " yes'" 2868 + " to approve suggestions added via shell (Needs root access)"); 2869 pw.println(" <ssid> - SSID of the network"); 2870 pw.println(" open|owe|wpa2|wpa3 - Security type of the network."); 2871 pw.println(" - Use 'open' or 'owe' for networks with no passphrase"); 2872 pw.println(" - 'open' - Open networks (Most prevalent)"); 2873 pw.println(" - 'owe' - Enhanced open networks"); 2874 pw.println(" - Use 'wpa2' or 'wpa3' for networks with passphrase"); 2875 pw.println(" - 'wpa2' - WPA-2 PSK networks (Most prevalent)"); 2876 pw.println(" - 'wpa3' - WPA-3 PSK networks"); 2877 pw.println(" -u - Mark the suggestion untrusted."); 2878 pw.println(" -o - Mark the suggestion oem paid."); 2879 pw.println(" -p - Mark the suggestion oem private."); 2880 pw.println(" -m - Mark the suggestion metered."); 2881 pw.println(" -h - Mark the network hidden."); 2882 pw.println(" -s - Share the suggestion with user."); 2883 pw.println(" -d - Mark the suggestion autojoin disabled."); 2884 pw.println(" -b <bssid> - Set specific BSSID."); 2885 pw.println(" -r - Enable non_persistent randomization (disabled by default)"); 2886 pw.println(" -a - Mark the suggestion carrier merged"); 2887 pw.println(" -c <carrierId> - set carrier Id"); 2888 pw.println(" -i <subscriptionId> - set subscription Id, if -a is used, " 2889 + "this must be set"); 2890 pw.println(" remove-suggestion <ssid> [-l]"); 2891 pw.println(" Remove a network suggestion with provided SSID of the network"); 2892 pw.println(" -l - Remove suggestion with lingering, if not set will disconnect " 2893 + "immediately "); 2894 pw.println(" remove-all-suggestions"); 2895 pw.println(" Removes all suggestions added via shell"); 2896 pw.println(" list-suggestions"); 2897 pw.println(" Lists the suggested networks added via shell"); 2898 if (SdkLevel.isAtLeastS()) { 2899 pw.println(" set-coex-cell-channels [lte|nr <bandNumber 1-261> " 2900 + "<downlinkFreqKhz or UNKNOWN: " 2901 + PhysicalChannelConfig.FREQUENCY_UNKNOWN + "> " 2902 + "<downlinkBandwidthKhz or UNKNOWN: " 2903 + PhysicalChannelConfig.CELL_BANDWIDTH_UNKNOWN + "> " 2904 + "<uplinkFreqKhz or UNKNOWN: " 2905 + PhysicalChannelConfig.FREQUENCY_UNKNOWN + "> " 2906 + "<uplinkBandwidthKhz or UNKNOWN: " 2907 + PhysicalChannelConfig.CELL_BANDWIDTH_UNKNOWN + ">] ..."); 2908 pw.println(" Sets a list of zero or more cell channels to use for coex calculations." 2909 + " Actual device reported cell channels will be ignored until" 2910 + " reset-coex-cell-channels is called."); 2911 pw.println(" reset-coex-cell-channels"); 2912 pw.println(" Removes all cell channels set in set-coex-cell-channels and returns to " 2913 + "listening on actual device reported cell channels"); 2914 pw.println(" get-coex-cell-channels"); 2915 pw.println(" Prints the cell channels being used for coex."); 2916 } 2917 pw.println(" set-connected-score <score>"); 2918 pw.println(" Set connected wifi network score (to choose between LTE & Wifi for " 2919 + "default route)."); 2920 pw.println(" This turns off the active connected scorer (default or external)."); 2921 pw.println(" Only works while connected to a wifi network. This score will stay in " 2922 + "effect until you call reset-connected-score or the device disconnects from the " 2923 + "current network."); 2924 pw.println(" <score> - Integer score should be in the range of 0 - 60"); 2925 pw.println(" reset-connected-score"); 2926 pw.println(" Turns on the default connected scorer."); 2927 pw.println(" Note: Will clear any external scorer set."); 2928 pw.println(" pmksa-flush <networkId>"); 2929 pw.println(" - Flush the local PMKSA cache associated with the network id." 2930 + " Use list-networks to retrieve <networkId> for the network"); 2931 pw.println(" reload-resources"); 2932 pw.println( 2933 " Reset the WiFi resources cache which will cause them to be reloaded next " 2934 + "time they are accessed. Necessary if overlays are manually modified."); 2935 pw.println(" launch-dialog-simple [-t <title>] [-m <message>]" 2936 + " [-l <url> <url_start> <url_end>] [-y <positive_button_text>]" 2937 + " [-n <negative_button_text>] [-x <neutral_button_text>] [-c <timeout_millis>]"); 2938 pw.println(" Launches a simple dialog and waits up to 15 seconds to" 2939 + " print the response."); 2940 pw.println(" -t - Title"); 2941 pw.println(" -m - Message"); 2942 pw.println(" -l - URL of the message, with the start and end index inside the message"); 2943 pw.println(" -y - Positive Button Text"); 2944 pw.println(" -n - Negative Button Text"); 2945 pw.println(" -x - Neutral Button Text"); 2946 pw.println(" -c - Optional timeout in milliseconds"); 2947 pw.println(" -s - Use the legacy dialog implementation on the system process"); 2948 pw.println(" launch-dialog-p2p-invitation-sent <device_name> <pin> [-i <display_id>]"); 2949 pw.println(" Launches a P2P Invitation Sent dialog."); 2950 pw.println(" <device_name> - Name of the device the invitation was sent to"); 2951 pw.println(" <pin> - PIN for the invited device to input"); 2952 pw.println(" launch-dialog-p2p-invitation-received <device_name> [-p] [-d <pin>] " 2953 + "[-i <display_id>] [-c <timeout_millis>]"); 2954 pw.println(" Launches a P2P Invitation Received dialog and waits up to 15 seconds to" 2955 + " print the response."); 2956 pw.println(" <device_name> - Name of the device sending the invitation"); 2957 pw.println(" -p - Show PIN input"); 2958 pw.println(" -d - Display PIN <pin>"); 2959 pw.println(" -i - Display ID"); 2960 pw.println(" -c - Optional timeout in milliseconds"); 2961 pw.println(" query-interface <uid> <package_name> STA|AP|AWARE|DIRECT [-new]"); 2962 pw.println( 2963 " Query whether the specified could be created for the specified UID and " 2964 + "package name, and if so - what other interfaces would be destroyed"); 2965 pw.println(" -new - query for a new interfaces (otherwise an existing interface is ok"); 2966 pw.println(" interface-priority-interactive-mode enable|disable|default"); 2967 pw.println(" Enable or disable asking the user when there's an interface priority " 2968 + "conflict, |default| implies using the device default behavior."); 2969 pw.println(" set-one-shot-screen-on-delay-ms <delayMs>"); 2970 pw.println(" set the delay for the next screen-on connectivity scan in milliseconds."); 2971 pw.println(" set-network-selection-config <enabled|disabled> <enabled|disabled> " 2972 + "-a <associated_network_selection_override>"); 2973 pw.println(" set whether sufficiency check is enabled for screen off case " 2974 + "(first arg), and screen on case (second arg)"); 2975 pw.println(" -a - set as one of the int " 2976 + "WifiNetworkSelectionConfig.ASSOCIATED_NETWORK_SELECTION_OVERRIDE_ values:"); 2977 pw.println(" 0 - no override"); 2978 pw.println(" 1 - override to enabled"); 2979 pw.println(" 2 - override to disabled"); 2980 pw.println(" set-ipreach-disconnect enabled|disabled"); 2981 pw.println(" Sets whether CMD_IP_REACHABILITY_LOST events should trigger disconnects."); 2982 pw.println(" get-ipreach-disconnect"); 2983 pw.println(" Gets setting of CMD_IP_REACHABILITY_LOST events triggering disconnects."); 2984 pw.println(" take-bugreport"); 2985 pw.println( 2986 " take bugreport through betterBug. " 2987 + "If it failed, take bugreport through bugreport manager."); 2988 pw.println(" get-allowed-channel [-b 1|6|7|8|15|16|31]"); 2989 pw.println( 2990 " get allowed channels in each operation mode from wifiManager if available. " 2991 + "Otherwise, it returns from wifiScanner."); 2992 pw.println(" -b - set the band in which channels are allowed"); 2993 pw.println(" '1' - band 2.4 GHz"); 2994 pw.println(" '6' - band 5 GHz with DFS channels"); 2995 pw.println(" '7' - band 2.4 and 5 GHz with DFS channels"); 2996 pw.println(" '8' - band 6 GHz"); 2997 pw.println(" '15' - band 2.4, 5, and 6 GHz with DFS channels"); 2998 pw.println(" '16' - band 60 GHz"); 2999 pw.println(" '31' - band 2.4, 5, 6 and 60 GHz with DFS channels"); 3000 pw.println(" get-cached-scan-data"); 3001 pw.println(" Gets scan data cached by the firmware"); 3002 pw.println(" force-overlay-config-value bool|integer <overlayName> enabled|disabled" 3003 + "<configValue>"); 3004 pw.println(" Force overlay to a specified value."); 3005 pw.println(" bool|integer - specified the type of the overlay"); 3006 pw.println(" <overlayName> - name of the overlay whose value is overridden."); 3007 pw.println(" enabled|disabled: enable the override or disable it and revert to using " 3008 + "the built-in value."); 3009 pw.println(" <configValue> - override value of the overlay." 3010 + "Must match the overlay type"); 3011 pw.println(" get-overlay-config-values"); 3012 pw.println(" Get current overlay value in resource cache."); 3013 pw.println(" get-softap-supported-features"); 3014 pw.println(" Gets softap supported features. Will print 'wifi_softap_acs_supported'"); 3015 pw.println(" and/or 'wifi_softap_wpa3_sae_supported',"); 3016 pw.println(" and/or 'wifi_softap_bridged_ap_supported',"); 3017 pw.println(" and/or 'wifi_softap_bridged_ap_with_sta_supported',"); 3018 pw.println(" each on a separate line."); 3019 } 3020 onHelpPrivileged(PrintWriter pw)3021 private void onHelpPrivileged(PrintWriter pw) { 3022 pw.println(" set-poll-rssi-interval-msecs <int>"); 3023 pw.println(" Sets the interval between RSSI polls to <int> milliseconds."); 3024 pw.println(" get-poll-rssi-interval-msecs"); 3025 pw.println(" Gets current interval between RSSI polls, in milliseconds."); 3026 pw.println(" force-hi-perf-mode enabled|disabled"); 3027 pw.println(" Sets whether hi-perf mode is forced or left for normal operation."); 3028 pw.println(" force-low-latency-mode enabled|disabled"); 3029 pw.println(" Sets whether low latency mode is forced or left for normal operation."); 3030 pw.println(" network-suggestions-set-user-approved <package name> yes|no"); 3031 pw.println(" Sets whether network suggestions from the app is approved or not."); 3032 pw.println(" network-suggestions-has-user-approved <package name>"); 3033 pw.println(" Queries whether network suggestions from the app is approved or not."); 3034 pw.println(" imsi-protection-exemption-set-user-approved-for-carrier <carrier id> yes|no"); 3035 pw.println(" Sets whether Imsi protection exemption for carrier is approved or not"); 3036 pw.println(" imsi-protection-exemption-has-user-approved-for-carrier <carrier id>"); 3037 pw.println(" Queries whether Imsi protection exemption for carrier is approved or not"); 3038 pw.println(" imsi-protection-exemption-clear-user-approved-for-carrier <carrier id>"); 3039 pw.println(" Clear the user choice on Imsi protection exemption for carrier"); 3040 pw.println(" network-requests-remove-user-approved-access-points <package name>"); 3041 pw.println(" Removes all user approved network requests for the app."); 3042 pw.println(" clear-user-disabled-networks"); 3043 pw.println(" Clears the user disabled networks list."); 3044 pw.println(" send-link-probe"); 3045 pw.println(" Manually triggers a link probe."); 3046 pw.println( 3047 " start-softap <ssid> (open|wpa2|wpa3|wpa3_transition|owe|owe_transition)" 3048 + " <passphrase> [-b 2|5|6|any|bridged|bridged_2_5|bridged_2_6|bridged_5_6]" 3049 + " [-x] [-w 20|40|80|160|320] [-f <int> [<int>]]"); 3050 pw.println(" Start softap with provided params"); 3051 pw.println(" Note that the shell command doesn't activate internet tethering. In some " 3052 + "devices, internet sharing is possible when Wi-Fi STA is also enabled and is" 3053 + "associated to another AP with internet access."); 3054 pw.println(" <ssid> - SSID of the network"); 3055 pw.println(" open|wpa2|wpa3|wpa3_transition|owe|owe_transition - Security type of the " 3056 + "network."); 3057 pw.println(" - Use 'open', 'owe', 'owe_transition' for networks with no passphrase"); 3058 pw.println(" - Use 'wpa2', 'wpa3', 'wpa3_transition' for networks with passphrase"); 3059 pw.println(" -b 2|5|6|any|bridged|bridged_2_5|bridged_2_6|bridged_5_6 - select the" 3060 + " preferred bands."); 3061 pw.println(" - Use '2' to select 2.4GHz band as the preferred band"); 3062 pw.println(" - Use '5' to select 5GHz band as the preferred band"); 3063 pw.println(" - Use '6' to select 6GHz band as the preferred band"); 3064 pw.println(" - Use 'any' to indicate no band preference"); 3065 pw.println(" - Use 'bridged' to indicate bridged AP which enables APs on both " 3066 + "2.4G + 5G"); 3067 pw.println(" - Use 'bridged_2_5' to indicate bridged AP which enables APs on both " 3068 + "2.4G + 5G"); 3069 pw.println(" - Use 'bridged_2_6' to indicate bridged AP which enables APs on both " 3070 + "2.4G + 6G"); 3071 pw.println(" - Use 'bridged_5_6' to indicate bridged AP which enables APs on both " 3072 + "5G + 6G"); 3073 pw.println(" Note: If the band option is not provided, 2.4GHz is the preferred band."); 3074 pw.println(" The exact channel is auto-selected by FW unless overridden by " 3075 + "force-softap-channel command or '-f <int> <int>' option"); 3076 pw.println(" -f <int> <int> - force exact channel frequency for operation channel"); 3077 pw.println(" Note: -f <int> <int> - must be the last option"); 3078 pw.println(" For example:"); 3079 pw.println(" Use '-f 2412' to enable single Soft Ap on 2412"); 3080 pw.println(" Use '-f 2412 5745' to enable bridged dual Soft Ap on 2412 and 5745"); 3081 pw.println(" -x - Specifies the SSID as hex digits instead of plain text (T and above)"); 3082 pw.println(" -w 20|40|80|160|320 - select the maximum channel bandwidth (MHz)"); 3083 pw.println(" stop-softap"); 3084 pw.println(" Stop softap (hotspot)"); 3085 pw.println(" force-softap-band enabled <int> | disabled"); 3086 pw.println(" Forces soft AP band to 2|5|6"); 3087 pw.println(" force-softap-channel enabled <int> | disabled [-w <maxBandwidth>]"); 3088 pw.println(" Sets whether soft AP channel is forced to <int> MHz [-w <maxBandwidth>]"); 3089 pw.println(" -w 0|20|40|80|160|320 - select the maximum channel bandwidth (MHz)"); 3090 pw.println(" Note: If the bandwidth option is not provided or set to 0, framework" 3091 + " will set the maximum bandwidth to auto, allowing HAL to select the bandwidth"); 3092 pw.println(" or left for normal operation."); 3093 pw.println(" force-country-code enabled <two-letter code> | disabled "); 3094 pw.println(" Sets country code to <two-letter code> or left for normal value"); 3095 pw.println(" or '00' for forcing to world mode country code"); 3096 pw.println(" set-wifi-watchdog enabled|disabled"); 3097 pw.println(" Sets whether wifi watchdog should trigger recovery"); 3098 pw.println(" get-wifi-watchdog"); 3099 pw.println(" Gets setting of wifi watchdog trigger recovery."); 3100 pw.println(" settings-reset"); 3101 pw.println(" Initiates wifi settings reset"); 3102 pw.println(" allow-root-to-get-local-only-cmm enabled|disabled"); 3103 pw.println(" sets whether the shell running as root could use the local-only secondary " 3104 + "STA"); 3105 pw.println(" add-request [-g] [-i] [-n] [-s] <ssid> open|owe|wpa2|wpa3 [<passphrase>]" 3106 + " [-b <bssid>] [-d <band=2|5|6|60>]"); 3107 pw.println(" Add a network request with provided params"); 3108 pw.println(" Use 'network-requests-set-user-approved android yes'" 3109 + " to pre-approve requests added via rooted shell (Not persisted)"); 3110 pw.println(" -g - Marks the following SSID as a glob pattern"); 3111 pw.println(" <ssid> - SSID of the network, or glob pattern if -g is present"); 3112 pw.println(" open|owe|wpa2|wpa3 - Security type of the network."); 3113 pw.println(" - Use 'open' or 'owe' for networks with no passphrase"); 3114 pw.println(" - 'open' - Open networks (Most prevalent)"); 3115 pw.println(" - 'owe' - Enhanced open networks"); 3116 pw.println(" - Use 'wpa2' or 'wpa3' for networks with passphrase"); 3117 pw.println(" - 'wpa2' - WPA-2 PSK networks (Most prevalent)"); 3118 pw.println(" - 'wpa3' - WPA-3 PSK networks"); 3119 pw.println(" -b <bssid> - Set specific BSSID."); 3120 pw.println(" -i Set internet capability."); 3121 pw.println(" -d Specify the band of access point: 2, 5, 6, or 60"); 3122 pw.println(" -s No SSID provided, to be chosen by network selection."); 3123 pw.println(" -n - Prevent auto-selection of BSSID and force it to be null so that the " 3124 + "request matches all BSSIDs."); 3125 pw.println(" remove-request <ssid>"); 3126 pw.println(" Remove a network request with provided SSID of the network"); 3127 pw.println(" remove-all-requests"); 3128 pw.println(" Removes all active requests added via shell"); 3129 pw.println(" list-requests"); 3130 pw.println(" Lists the requested networks added via shell"); 3131 pw.println(" network-requests-set-user-approved <package name> yes|no"); 3132 pw.println(" Sets whether network requests from the app is approved or not."); 3133 pw.println(" Note: Only 1 such app can be approved from the shell at a time"); 3134 pw.println(" network-requests-has-user-approved <package name>"); 3135 pw.println(" Queries whether network requests from the app is approved or not."); 3136 pw.println(" Note: This only returns whether the app was set via the " 3137 + "'network-requests-set-user-approved' shell command"); 3138 pw.println(" list-all-suggestions"); 3139 pw.println(" Lists all suggested networks on this device"); 3140 pw.println(" list-suggestions-from-app <package name>"); 3141 pw.println(" Lists the suggested networks from the app"); 3142 pw.println(" set-emergency-callback-mode enabled|disabled"); 3143 pw.println(" Sets whether Emergency Callback Mode (ECBM) is enabled."); 3144 pw.println(" Equivalent to receiving the " 3145 + "TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED broadcast."); 3146 pw.println(" set-emergency-call-state enabled|disabled"); 3147 pw.println(" Sets whether we are in the middle of an emergency call."); 3148 pw.println("Equivalent to receiving the " 3149 + "TelephonyManager.ACTION_EMERGENCY_CALL_STATE_CHANGED broadcast."); 3150 pw.println(" set-emergency-scan-request enabled|disabled"); 3151 pw.println(" Sets whether there is a emergency scan request in progress."); 3152 pw.println(" network-suggestions-set-as-carrier-provider <packageName> yes|no"); 3153 pw.println(" Set the <packageName> work as carrier provider or not."); 3154 pw.println(" is-network-suggestions-set-as-carrier-provider <packageName>"); 3155 pw.println(" Queries whether the <packageName> is working as carrier provider or not."); 3156 pw.println(" remove-app-from-suggestion_database <packageName>"); 3157 pw.println(" Remove <packageName> from the suggestion database, all suggestions and user" 3158 + " approval will be deleted, it is the same as uninstalling this app."); 3159 pw.println(" trigger-recovery"); 3160 pw.println(" Trigger Wi-Fi subsystem restart."); 3161 pw.println(" start-faking-scans"); 3162 pw.println(" Start faking scan results into the framework (configured with " 3163 + "'add-fake-scan'), stop with 'stop-faking-scans'."); 3164 pw.println(" stop-faking-scans"); 3165 pw.println(" Stop faking scan results - started with 'start-faking-scans'."); 3166 pw.println(" add-fake-scan [-x] <ssid> <bssid> <capabilities> <frequency> <dbm>"); 3167 pw.println(" Add a fake scan result to be used when enabled via `start-faking-scans'."); 3168 pw.println(" Example WPA2: add-fake-scan fakeWpa2 80:01:02:03:04:05 " 3169 + "\"[WPA2-PSK-CCMP][RSN-PSK-CCMP][ESS]\" 2412 -55"); 3170 pw.println(" Example WPA3: add-fake-scan fakeWpa3 80:01:02:03:04:06 " 3171 + "\"[RSN-SAE+FT/SAE-CCMP][ESS]\" 2412 -55"); 3172 pw.println( 3173 " Example Open: add-fake-scan fakeOpen 80:01:02:03:04:07 \"[ESS]\" 2412 -55"); 3174 pw.println(" Example OWE: add-fake-scan fakeOwe 80:01:02:03:04:08 \"[RSN-OWE-CCMP]\" " 3175 + "2412 -55"); 3176 pw.println( 3177 " Example WPA2/WPA3 transition mode: add-fake-scan fakeWpa2t3 80:01:02:03:04:09 " 3178 + "\"[WPA2-PSK-CCMP][RSN-PSK+SAE-CCMP][ESS][MFPC]\" 2412 -55"); 3179 pw.println( 3180 " Example Open/OWE transition mode: add-fake-scan fakeOpenOwe 80:01:02:03:04:0A " 3181 + "\"[RSN-OWE_TRANSITION-CCMP][ESS]\" 2412 -55"); 3182 pw.println( 3183 " Example Passpoint: add-fake-scan fakePasspoint 80:01:02:03:04:0B " 3184 + "\"[WPA2-EAP/SHA1-CCMP][RSN-EAP/SHA1-CCMP][ESS][MFPR][MFPC]" 3185 + "[PASSPOINT]\" 2412 -55"); 3186 pw.println(" -x - Specifies the SSID as hex digits instead of plain text"); 3187 pw.println(" reset-fake-scans"); 3188 pw.println(" Resets all fake scan results added by 'add-fake-scan'."); 3189 pw.println(" enable-scanning enabled|disabled [-h]"); 3190 pw.println(" Sets whether all scanning should be enabled or disabled"); 3191 pw.println(" -h - Enable scanning for hidden networks."); 3192 pw.println(" set-passpoint-enabled enabled|disabled"); 3193 pw.println(" Sets whether Passpoint should be enabled or disabled"); 3194 pw.println( 3195 " start-lohs <ssid> (open|wpa2|wpa3|wpa3_transition|owe|owe_transition)" 3196 + " <passphrase> [-b 2|5|6|any|bridged|bridged_2_5|bridged_2_6|bridged_5_6]" 3197 + " [-x] [-w 20|40|80|160|320] [-f <int> [<int>]])"); 3198 pw.println(" Start local only softap (hotspot) with provided params"); 3199 pw.println(" <ssid> - SSID of the network"); 3200 pw.println(" open|wpa2|wpa3|wpa3_transition|owe|owe_transition - Security type of the " 3201 + "network."); 3202 pw.println(" - Use 'open', 'owe', 'owe_transition' for networks with no passphrase"); 3203 pw.println(" - Use 'wpa2', 'wpa3', 'wpa3_transition' for networks with passphrase"); 3204 pw.println(" -b 2|5|6|any|bridged|bridged_2_5|bridged_2_6|bridged_5_6 - select the " 3205 + "preferred bands."); 3206 pw.println(" - Use '2' to select 2.4GHz band as the preferred band"); 3207 pw.println(" - Use '5' to select 5GHz band as the preferred band"); 3208 pw.println(" - Use '6' to select 6GHz band as the preferred band"); 3209 pw.println(" - Use 'any' to indicate no band preference"); 3210 pw.println(" - Use 'bridged' to indicate bridged AP which enables APs on both " 3211 + "2.4G + 5G"); 3212 pw.println(" - Use 'bridged_2_5' to indicate bridged AP which enables APs on both " 3213 + "2.4G + 5G"); 3214 pw.println(" - Use 'bridged_2_6' to indicate bridged AP which enables APs on both " 3215 + "2.4G + 6G"); 3216 pw.println(" - Use 'bridged_5_6' to indicate bridged AP which enables APs on both " 3217 + "5G + 6G"); 3218 pw.println(" Note: If the band option is not provided, 2.4GHz is the preferred band."); 3219 pw.println(" The exact channel is auto-selected by FW unless overridden by " 3220 + "force-softap-channel command or '-f <int> <int>' option"); 3221 pw.println(" -f <int> <int> - force exact channel frequency for operation channel"); 3222 pw.println(" Note: -f <int> <int> - must be the last option"); 3223 pw.println(" For example:"); 3224 pw.println(" Use '-f 2412' to enable single Soft Ap on 2412"); 3225 pw.println(" Use '-f 2412 5745' to enable bridged dual lohs on 2412 and 5745"); 3226 pw.println(" -x - Specifies the SSID as hex digits instead of plain text (T and above)"); 3227 pw.println(" -w 20|40|80|160|320 - select the maximum bandwidth (MHz)"); 3228 pw.println(" stop-softap"); 3229 pw.println(" Stop softap (hotspot)"); 3230 pw.println(" Note: If the band option is not provided, 2.4GHz is the preferred band."); 3231 pw.println(" stop-lohs"); 3232 pw.println(" Stop local only softap (hotspot)"); 3233 pw.println(" set-multi-internet-mode 0|1|2"); 3234 pw.println(" Sets Multi Internet use case mode. 0-disabled 1-dbs 2-multi ap"); 3235 pw.println(" set-pno-request <ssid> [-f <frequency>]"); 3236 pw.println(" Requests to include a non-quoted UTF-8 SSID in PNO scans"); 3237 pw.println(" clear-pno-request"); 3238 pw.println(" Clear the PNO scan request."); 3239 pw.println(" start-dpp-enrollee-responder [-i <info>] [-c <curve>]"); 3240 pw.println(" Start DPP Enrollee responder mode."); 3241 pw.println(" -i - Device Info to be used in DPP Bootstrapping URI"); 3242 pw.println(" -c - Cryptography Curve integer 1:p256v1, 2:s384r1, etc"); 3243 pw.println(" start-dpp-configurator-initiator <networkId> <netRole> <enrolleeURI>"); 3244 pw.println(" Start DPP Configurator Initiator mode."); 3245 pw.println(" netRole - 0: STA, 1: AP"); 3246 pw.println(" enrolleeURI - Bootstrapping URI received from Enrollee"); 3247 pw.println(" stop-dpp"); 3248 pw.println(" Stop DPP session."); 3249 pw.println(" set-ssid-charset <locale_language> <charset_name>"); 3250 pw.println(" Sets the SSID translation charset for the given locale language."); 3251 pw.println(" Example: set-ssid-charset zh GBK"); 3252 pw.println(" clear-ssid-charsets"); 3253 pw.println(" Clears the SSID translation charsets set in set-ssid-charset."); 3254 pw.println(" get-last-caller-info api_type"); 3255 pw.println(" Get the last caller information for a WifiManager.ApiType"); 3256 pw.println(" trigger-afc-location-update <longitude> <latitude> <height>"); 3257 pw.println(" Passes in longitude, latitude, and height values as arguments of type " 3258 + "double for a fake location update to trigger framework logic to query the AFC " 3259 + "server. The longitude and latitude pair is in decimal degrees and the height" 3260 + " is the altitude in meters. The server URL needs to have been previously set " 3261 + "with the configure-afc-server shell command."); 3262 pw.println(" Example: trigger-afc-location-update 37.425056 -122.984157 3.043"); 3263 pw.println(" set-afc-channel-allowance -e <secs_until_expiry> [-f <low_freq>,<high_freq>," 3264 + "<psd>:...|none] [-c <operating_class>,<channel_cfi>,<max_eirp>:...|none]"); 3265 pw.println(" Sets the allowed AFC channels and frequencies."); 3266 pw.println(" -e - Seconds until the availability expires."); 3267 pw.println(" -f - Colon-separated list of available frequency info."); 3268 pw.println(" Note: each frequency should contain 3 comma separated values, where " 3269 + "the first is the low frequency (MHz), the second the high frequency (MHz), the " 3270 + "third the max PSD (dBm per MHz). To set an empty frequency list, enter \"none\" " 3271 + "in place of the list of allowed frequencies."); 3272 pw.println(" -c - Colon-separated list of available channel info."); 3273 pw.println(" Note: each channel should contain 3 comma separated values, where " 3274 + "the first is the global operating class, the second the channel CFI, " 3275 + "the third the max EIRP in dBm. To set an empty channel list, enter \"none\" in " 3276 + "place of the list of allowed channels."); 3277 pw.println(" Example: set-afc-channel-allowance -e 30 -c none -f " 3278 + "5925,6020,23:6020,6050,1"); 3279 pw.println(" configure-afc-server <url> [-r [<request property key> <request property " 3280 + "value>] ...]"); 3281 pw.println(" Sets the server URL and request properties for the HTTP request which the " 3282 + "AFC Client will query."); 3283 pw.println(" -r - HTTP header fields that come in pairs of key and value which are added" 3284 + " to the HTTP request. Must be an even number of arguments. If there is no -r " 3285 + "option provided or no arguments provided after the -r option, then set the " 3286 + "request properties to none in the request."); 3287 pw.println(" Example: configure-afc-server https://testURL -r key1 value1 key2 value2"); 3288 } 3289 3290 @Override onHelp()3291 public void onHelp() { 3292 final PrintWriter pw = getOutPrintWriter(); 3293 pw.println("Wi-Fi (wifi) commands:"); 3294 pw.println(" help or -h"); 3295 pw.println(" Print this help text."); 3296 onHelpNonPrivileged(pw); 3297 if (Binder.getCallingUid() == Process.ROOT_UID) { 3298 onHelpPrivileged(pw); 3299 } 3300 pw.println(); 3301 } 3302 printWifiNetworkSuggestions(PrintWriter pw, Collection<WifiNetworkSuggestion> suggestions)3303 private void printWifiNetworkSuggestions(PrintWriter pw, 3304 Collection<WifiNetworkSuggestion> suggestions) { 3305 if (suggestions == null || suggestions.isEmpty()) { 3306 pw.println("No suggestions on this device"); 3307 } else { 3308 pw.println("SSID Security type(s)"); 3309 for (WifiNetworkSuggestion suggestion : suggestions) { 3310 pw.println(String.format("%-32s %-4s", 3311 WifiInfo.sanitizeSsid(suggestion.getWifiConfiguration().SSID), 3312 suggestion.getWifiConfiguration().getSecurityParamsList().stream() 3313 .map(p -> WifiConfiguration.getSecurityTypeName( 3314 p.getSecurityType()) 3315 + (p.isAddedByAutoUpgrade() ? "^" : "")) 3316 .collect(Collectors.joining("/")))); 3317 } 3318 } 3319 } 3320 } 3321