1 /* 2 * Copyright (C) 2022 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.p2p; 18 19 import android.content.Context; 20 import android.net.MacAddress; 21 import android.net.NetworkInfo; 22 import android.net.wifi.SynchronousExecutor; 23 import android.net.wifi.p2p.WifiP2pConfig; 24 import android.net.wifi.p2p.WifiP2pDevice; 25 import android.net.wifi.p2p.WifiP2pDeviceList; 26 import android.net.wifi.p2p.WifiP2pGroup; 27 import android.net.wifi.p2p.WifiP2pGroupList; 28 import android.net.wifi.p2p.WifiP2pInfo; 29 import android.net.wifi.p2p.WifiP2pManager; 30 import android.os.Binder; 31 import android.os.Message; 32 import android.os.Process; 33 34 import com.android.internal.util.Protocol; 35 import com.android.modules.utils.BasicShellCommandHandler; 36 import com.android.modules.utils.build.SdkLevel; 37 38 import java.io.PrintWriter; 39 import java.util.concurrent.CountDownLatch; 40 import java.util.concurrent.TimeUnit; 41 42 /** 43 * Interprets and executes 'adb shell cmd wifip2p [args]'. 44 * The leading command name is defined by android.content.Context.WIFI_P2P_SERVICE. 45 */ 46 public class WifiP2pShellCommand extends BasicShellCommandHandler { 47 private static final String TAG = "WifiP2pShellCommand"; 48 49 private static WifiP2pManager.Channel sWifiP2pChannel; 50 51 private final Context mContext; 52 53 private final WifiP2pManager mWifiP2pManager; 54 WifiP2pShellCommand(Context context)55 public WifiP2pShellCommand(Context context) { 56 mContext = context; 57 mWifiP2pManager = mContext.getSystemService(WifiP2pManager.class); 58 } 59 handleCommand(String cmd, PrintWriter pw)60 private int handleCommand(String cmd, PrintWriter pw) throws Exception { 61 CountDownLatch countDownLatch = new CountDownLatch(1); 62 WifiP2pManager.ActionListener actionListener = new WifiP2pManager.ActionListener() { 63 @Override 64 public void onSuccess() { 65 countDownLatch.countDown(); 66 } 67 @Override 68 public void onFailure(int reason) { 69 pw.println("FAILED with reason " + reason); 70 countDownLatch.countDown(); 71 } 72 }; 73 74 switch (cmd) { 75 case "init": 76 if (null != sWifiP2pChannel) sWifiP2pChannel.close(); 77 sWifiP2pChannel = mWifiP2pManager.initialize( 78 mContext, mContext.getMainLooper(), null); 79 if (null == sWifiP2pChannel) { 80 pw.println("Cannot initialize p2p channel."); 81 return -1; 82 } 83 return 0; 84 case "deinit": 85 if (null != sWifiP2pChannel) sWifiP2pChannel.close(); 86 sWifiP2pChannel = null; 87 return 0; 88 case "start-peer-discovery": 89 mWifiP2pManager.discoverPeers(sWifiP2pChannel, actionListener); 90 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 91 return 0; 92 case "start-peer-discovery-on-social-channels": 93 if (!SdkLevel.isAtLeastT()) { 94 pw.println("This feature is only supported on SdkLevel T or later."); 95 return -1; 96 } 97 mWifiP2pManager.discoverPeersOnSocialChannels(sWifiP2pChannel, actionListener); 98 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 99 return 0; 100 case "start-peer-discovery-on-specific-frequency": 101 if (!SdkLevel.isAtLeastT()) { 102 pw.println("This feature is only supported on SdkLevel T or later."); 103 return -1; 104 } 105 int frequencyMhz; 106 try { 107 frequencyMhz = Integer.parseInt(getNextArgRequired()); 108 } catch (NumberFormatException e) { 109 pw.println( 110 "Invalid argument to 'start-peer-discovery-on-specific-frequency' " 111 + "- must be an integer"); 112 return -1; 113 } 114 if (frequencyMhz <= 0) { 115 pw.println("Invalid argument to 'start-peer-discovery-on-specific-frequency' " 116 + "- must be a positive integer."); 117 return -1; 118 } 119 mWifiP2pManager.discoverPeersOnSpecificFrequency( 120 sWifiP2pChannel, frequencyMhz, actionListener); 121 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 122 return 0; 123 case "stop-peer-discovery": 124 mWifiP2pManager.stopPeerDiscovery(sWifiP2pChannel, actionListener); 125 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 126 return 0; 127 case "start-service-discovery": 128 mWifiP2pManager.discoverServices(sWifiP2pChannel, actionListener); 129 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 130 return 0; 131 case "stop-service-discovery": 132 mWifiP2pManager.stopPeerDiscovery(sWifiP2pChannel, actionListener); 133 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 134 return 0; 135 case "list-peers": 136 mWifiP2pManager.requestPeers(sWifiP2pChannel, 137 new WifiP2pManager.PeerListListener() { 138 @Override 139 public void onPeersAvailable(WifiP2pDeviceList peers) { 140 pw.println(String.format("%-32s %-24s %-10s %-10s %-10s", 141 "Name", "Address", "DevCaps", "GroupCaps", "Status")); 142 for (WifiP2pDevice d: peers.getDeviceList()) { 143 pw.println(String.format("%-32s %-24s 0x%010x 0x%010x %-10s", 144 d.deviceName, d.deviceAddress, 145 d.deviceCapability, d.groupCapability, 146 wifiP2pDeviceStatusToStr(d.status))); 147 } 148 countDownLatch.countDown(); 149 } 150 }); 151 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 152 return 0; 153 case "remove-client": 154 if (!SdkLevel.isAtLeastT()) { 155 pw.println("This feature is only supported on SdkLevel T or later."); 156 return -1; 157 } 158 MacAddress peerAddress; 159 try { 160 peerAddress = MacAddress.fromString(getNextArgRequired()); 161 } catch (IllegalArgumentException e) { 162 pw.println( 163 "Invalid argument to 'remove-client' " 164 + "- must be a valid mac address"); 165 return -1; 166 } 167 mWifiP2pManager.removeClient(sWifiP2pChannel, peerAddress, actionListener); 168 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 169 return 0; 170 case "cancel-connect": 171 mWifiP2pManager.cancelConnect(sWifiP2pChannel, actionListener); 172 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 173 return 0; 174 case "create-group": 175 mWifiP2pManager.createGroup(sWifiP2pChannel, actionListener); 176 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 177 return 0; 178 case "remove-group": 179 mWifiP2pManager.removeGroup(sWifiP2pChannel, actionListener); 180 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 181 return 0; 182 case "set-device-name": 183 String deviceName = getNextArgRequired(); 184 mWifiP2pManager.setDeviceName(sWifiP2pChannel, deviceName, actionListener); 185 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 186 return 0; 187 case "get-connection-info": 188 mWifiP2pManager.requestConnectionInfo(sWifiP2pChannel, 189 new WifiP2pManager.ConnectionInfoListener() { 190 @Override 191 public void onConnectionInfoAvailable(WifiP2pInfo info) { 192 pw.println(info.toString()); 193 countDownLatch.countDown(); 194 } 195 }); 196 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 197 return 0; 198 case "get-group-info": 199 mWifiP2pManager.requestGroupInfo(sWifiP2pChannel, 200 new WifiP2pManager.GroupInfoListener() { 201 @Override 202 public void onGroupInfoAvailable(WifiP2pGroup group) { 203 pw.println(group); 204 countDownLatch.countDown(); 205 } 206 }); 207 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 208 return 0; 209 case "get-state": 210 mWifiP2pManager.requestP2pState(sWifiP2pChannel, 211 new WifiP2pManager.P2pStateListener() { 212 @Override 213 public void onP2pStateAvailable(int state) { 214 switch (state) { 215 case WifiP2pManager.WIFI_P2P_STATE_DISABLED: 216 pw.println("DISABLED"); 217 break; 218 case WifiP2pManager.WIFI_P2P_STATE_ENABLED: 219 pw.println("ENABLED"); 220 break; 221 default: 222 pw.println("UNKNOWN"); 223 break; 224 } 225 countDownLatch.countDown(); 226 } 227 }); 228 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 229 return 0; 230 case "get-discovery-state": 231 mWifiP2pManager.requestDiscoveryState(sWifiP2pChannel, 232 new WifiP2pManager.DiscoveryStateListener() { 233 @Override 234 public void onDiscoveryStateAvailable(int state) { 235 switch (state) { 236 case WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED: 237 pw.println("STARTED"); 238 break; 239 case WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED: 240 pw.println("STOPPED"); 241 break; 242 default: 243 pw.println("UNKNOWN"); 244 break; 245 } 246 countDownLatch.countDown(); 247 } 248 }); 249 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 250 return 0; 251 case "get-listen-state": { 252 mWifiP2pManager.getListenState(sWifiP2pChannel, new SynchronousExecutor(), 253 state -> { 254 switch (state) { 255 case WifiP2pManager.WIFI_P2P_LISTEN_STARTED: 256 pw.println("STARTED"); 257 break; 258 case WifiP2pManager.WIFI_P2P_LISTEN_STOPPED: 259 pw.println("STOPPED"); 260 break; 261 default: 262 pw.println("UNKNOWN"); 263 break; 264 } 265 countDownLatch.countDown(); 266 }); 267 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 268 return 0; 269 } 270 case "get-network-info": 271 mWifiP2pManager.requestNetworkInfo(sWifiP2pChannel, 272 new WifiP2pManager.NetworkInfoListener() { 273 @Override 274 public void onNetworkInfoAvailable(NetworkInfo networkInfo) { 275 pw.println(networkInfo.toString()); 276 countDownLatch.countDown(); 277 } 278 }); 279 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 280 return 0; 281 case "get-device-info": 282 mWifiP2pManager.requestDeviceInfo(sWifiP2pChannel, 283 new WifiP2pManager.DeviceInfoListener() { 284 @Override 285 public void onDeviceInfoAvailable(WifiP2pDevice dev) { 286 pw.println(dev.toString()); 287 countDownLatch.countDown(); 288 } 289 }); 290 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 291 return 0; 292 case "list-saved-groups": 293 mWifiP2pManager.requestPersistentGroupInfo(sWifiP2pChannel, 294 new WifiP2pManager.PersistentGroupInfoListener() { 295 @Override 296 public void onPersistentGroupInfoAvailable(WifiP2pGroupList groups) { 297 pw.println(groups.toString()); 298 countDownLatch.countDown(); 299 } 300 }); 301 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 302 return 0; 303 case "delete-saved-group": 304 int netId; 305 try { 306 netId = Integer.parseInt(getNextArgRequired()); 307 } catch (NumberFormatException e) { 308 pw.println( 309 "Invalid argument to 'delete-saved-group' " 310 + "- must be an integer"); 311 return -1; 312 } 313 if (netId < 0) { 314 pw.println("Invalid argument to 'delete-saved-group' " 315 + "- must be 0 or a positive integer."); 316 return -1; 317 } 318 mWifiP2pManager.deletePersistentGroup(sWifiP2pChannel, netId, actionListener); 319 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 320 return 0; 321 case "set-channels": 322 int listeningChannel, operatingChannel; 323 try { 324 listeningChannel = Integer.parseInt(getNextArgRequired()); 325 operatingChannel = Integer.parseInt(getNextArgRequired()); 326 } catch (NumberFormatException e) { 327 pw.println( 328 "Invalid argument to 'set-channels' " 329 + "- must be an integer"); 330 return -1; 331 } 332 if (listeningChannel < 0 || operatingChannel < 0) { 333 pw.println("Invalid argument to 'set-channels' " 334 + "- must be 0 or a positive integer."); 335 return -1; 336 } 337 mWifiP2pManager.setWifiP2pChannels(sWifiP2pChannel, 338 listeningChannel, operatingChannel, actionListener); 339 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 340 return 0; 341 case "start-listening": 342 mWifiP2pManager.startListening(sWifiP2pChannel, actionListener); 343 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 344 return 0; 345 case "stop-listening": 346 mWifiP2pManager.stopListening(sWifiP2pChannel, actionListener); 347 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 348 return 0; 349 case "set-miracast-mode": 350 int mode; 351 try { 352 mode = Integer.parseInt(getNextArgRequired()); 353 } catch (NumberFormatException e) { 354 pw.println("Invalid argument to 'set-miracast-mode' " 355 + "- must be an integer"); 356 return -1; 357 } 358 if (mode < 0) { 359 pw.println("Invalid argument to 'set-miracast-mode' " 360 + "- must be 0 or a positive integer."); 361 return -1; 362 } 363 mWifiP2pManager.setMiracastMode(mode); 364 return 0; 365 case "factory-reset": 366 mWifiP2pManager.factoryReset(sWifiP2pChannel, actionListener); 367 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 368 return 0; 369 case "connect": { 370 WifiP2pConfig config = buildWifiP2pConfig(pw); 371 if (null == config) { 372 pw.println("Invalid argument to 'connect'"); 373 return -1; 374 } 375 mWifiP2pManager.connect(sWifiP2pChannel, config, actionListener); 376 countDownLatch.await(3000, TimeUnit.MILLISECONDS); 377 return 0; 378 } 379 case "accept-connection": 380 mWifiP2pManager.getP2pStateMachineMessenger() 381 .send(Message.obtain(null, Protocol.BASE_WIFI_P2P_SERVICE + 2)); 382 return 0; 383 case "reject-connection": 384 mWifiP2pManager.getP2pStateMachineMessenger() 385 .send(Message.obtain(null, Protocol.BASE_WIFI_P2P_SERVICE + 3)); 386 return 0; 387 case "create-group-with-config": { 388 WifiP2pConfig config = prepareWifiP2pConfig(pw); 389 if (null == config) { 390 pw.println("Invalid argument to 'create-group-with-config'"); 391 return -1; 392 } 393 mWifiP2pManager.createGroup(sWifiP2pChannel, config, actionListener); 394 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 395 return 0; 396 } 397 case "connect-with-config": { 398 WifiP2pConfig config = prepareWifiP2pConfig(pw); 399 if (null == config) { 400 pw.println("Invalid argument to 'connect-with-config'"); 401 return -1; 402 } 403 mWifiP2pManager.connect(sWifiP2pChannel, config, actionListener); 404 countDownLatch.await(1000, TimeUnit.MILLISECONDS); 405 return 0; 406 } 407 default: 408 return handleDefaultCommands(cmd); 409 } 410 } 411 412 @Override onCommand(String cmd)413 public int onCommand(String cmd) { 414 final PrintWriter pw = getOutPrintWriter(); 415 checkRootPermission(); 416 417 // Treat no command as help command. 418 if (cmd == null || cmd.equals("")) { 419 cmd = "help"; 420 } 421 if (!commandDoesNotRequireP2pAlreadyInitialized(cmd, pw)) return -1; 422 423 try { 424 return handleCommand(cmd, pw); 425 } catch (Exception e) { 426 pw.println("Exception: " + e); 427 } 428 429 return -1; 430 } 431 commandDoesNotRequireP2pAlreadyInitialized(String cmd, PrintWriter pw)432 private boolean commandDoesNotRequireP2pAlreadyInitialized(String cmd, PrintWriter pw) { 433 if (cmd.equals("init")) return true; 434 if (cmd.equals("deinit")) return true; 435 if (cmd.equals("help")) return true; 436 437 if (null == mWifiP2pManager) { 438 pw.println("P2p service is not available."); 439 return false; 440 } 441 442 if (null == sWifiP2pChannel) { 443 pw.println("P2p client is not initialized, execute init first."); 444 return false; 445 } 446 447 return true; 448 } 449 wifiP2pDeviceStatusToStr(int status)450 private String wifiP2pDeviceStatusToStr(int status) { 451 switch (status) { 452 case WifiP2pDevice.CONNECTED: 453 return "CONNECTED"; 454 case WifiP2pDevice.INVITED: 455 return "INVITED"; 456 case WifiP2pDevice.FAILED: 457 return "FAILED"; 458 case WifiP2pDevice.AVAILABLE: 459 return "AVAILABLE"; 460 case WifiP2pDevice.UNAVAILABLE: 461 return "UNAVAILABLE"; 462 } 463 return "UNKNOWN"; 464 } 465 buildWifiP2pConfig(PrintWriter pw)466 private WifiP2pConfig buildWifiP2pConfig(PrintWriter pw) { 467 String deviceAddress = getNextArgRequired(); 468 int goIntent = WifiP2pConfig.GROUP_OWNER_INTENT_AUTO; 469 int ipProvisioningMode = WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP; 470 String option = getNextOption(); 471 while (option != null) { 472 if (option.equals("-i")) { 473 try { 474 goIntent = Integer.parseInt(getNextArgRequired()); 475 } catch (NumberFormatException e) { 476 pw.println("Invalid argument for group owner intent " 477 + "- must be an integer"); 478 return null; 479 } 480 if (goIntent < WifiP2pConfig.GROUP_OWNER_INTENT_MIN 481 || goIntent > WifiP2pConfig.GROUP_OWNER_INTENT_MAX) { 482 pw.println("Invalid argument for group owner intent " 483 + "- must be from " 484 + WifiP2pConfig.GROUP_OWNER_INTENT_MIN + " to " 485 + WifiP2pConfig.GROUP_OWNER_INTENT_MAX); 486 return null; 487 } 488 } else if (option.equals("-m")) { 489 if (!SdkLevel.isAtLeastT()) { 490 pw.println("Invalid argument for group client IP provisioning mode " 491 + "- IP provisioning mode is supported only on SdkLevel T or later"); 492 return null; 493 } 494 try { 495 ipProvisioningMode = Integer.parseInt(getNextArgRequired()); 496 } catch (NumberFormatException e) { 497 pw.println("Invalid argument for group client IP provisioning mode " 498 + "- must be an integer"); 499 return null; 500 } 501 if (ipProvisioningMode != WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP 502 && ipProvisioningMode 503 != WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL) { 504 pw.println("Invalid argument for group client IP provisioning mode " 505 + "- must be " 506 + WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP + " or " 507 + WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL); 508 return null; 509 } 510 } else { 511 pw.println("Ignoring unknown option " + option); 512 } 513 option = getNextOption(); 514 } 515 WifiP2pConfig.Builder configBuilder = new WifiP2pConfig.Builder(); 516 configBuilder.setDeviceAddress(MacAddress.fromString(deviceAddress)); 517 if (SdkLevel.isAtLeastT()) { 518 configBuilder.setGroupClientIpProvisioningMode(ipProvisioningMode); 519 } 520 WifiP2pConfig config = configBuilder.build(); 521 config.groupOwnerIntent = goIntent; 522 return config; 523 } 524 prepareWifiP2pConfig(PrintWriter pw)525 private WifiP2pConfig prepareWifiP2pConfig(PrintWriter pw) { 526 String networkName = getNextArgRequired(); 527 String passphrase = getNextArgRequired(); 528 int operatingBandOrFreq; 529 try { 530 operatingBandOrFreq = Integer.parseInt(getNextArgRequired()); 531 } catch (NumberFormatException e) { 532 pw.println("Invalid argument to for wifi p2p config opeartingBandOrFreq " 533 + "- must be an integer"); 534 return null; 535 } 536 if (operatingBandOrFreq < 0) { 537 pw.println("Invalid argument to for wifi p2p config opeartingBandOrFreq " 538 + "- must be 0 or a positive integer."); 539 return null; 540 } 541 boolean isPersistent = getNextArgRequiredTrueOrFalse("true", "false"); 542 WifiP2pConfig.Builder builder = new WifiP2pConfig.Builder() 543 .setNetworkName(networkName) 544 .setPassphrase(passphrase); 545 if (operatingBandOrFreq < 1000) { 546 builder.setGroupOperatingBand(operatingBandOrFreq); 547 } else { 548 builder.setGroupOperatingFrequency(operatingBandOrFreq); 549 } 550 builder.enablePersistentMode(isPersistent); 551 return builder.build(); 552 } 553 getNextArgRequiredTrueOrFalse(String trueString, String falseString)554 private boolean getNextArgRequiredTrueOrFalse(String trueString, String falseString) 555 throws IllegalArgumentException { 556 String nextArg = getNextArgRequired(); 557 if (trueString.equals(nextArg)) { 558 return true; 559 } else if (falseString.equals(nextArg)) { 560 return false; 561 } else { 562 throw new IllegalArgumentException("Expected '" + trueString + "' or '" + falseString 563 + "' as next arg but got '" + nextArg + "'"); 564 } 565 } 566 checkRootPermission()567 private void checkRootPermission() { 568 final int uid = Binder.getCallingUid(); 569 if (uid == Process.ROOT_UID) { 570 // Root can do anything. 571 return; 572 } 573 throw new SecurityException("Uid " + uid + " does not have access to wifip2p commands"); 574 } 575 576 @Override onHelp()577 public void onHelp() { 578 final PrintWriter pw = getOutPrintWriter(); 579 580 pw.println("Wi-Fi P2P (wifip2p) commands:"); 581 pw.println(" help"); 582 pw.println(" Print this help text."); 583 pw.println(" init"); 584 pw.println(" Init p2p client, this must be called before executing p2p commands."); 585 pw.println(" deinit"); 586 pw.println(" De-init p2p client, this must be called at the end, or wifi service will" 587 + " keep the p2p client and block SoftAp or NAN."); 588 pw.println(" start-peer-discovery"); 589 pw.println(" Start p2p peer discovery."); 590 pw.println(" start-peer-discovery-on-social-channels"); 591 pw.println(" Start p2p peer discovery on social channels."); 592 pw.println(" start-peer-discovery-on-specific-frequency <frequency>"); 593 pw.println(" Start p2p peer discovery on specific frequency."); 594 pw.println(" stop-peer-discovery"); 595 pw.println(" Stop p2p peer discovery."); 596 pw.println(" start-service-discovery"); 597 pw.println(" Start p2p service discovery."); 598 pw.println(" stop-service-discovery"); 599 pw.println(" Stop p2p service discovery."); 600 pw.println(" start-listening"); 601 pw.println(" Start p2p listening."); 602 pw.println(" stop-listening"); 603 pw.println(" Stop p2p listening."); 604 pw.println(" list-peers"); 605 pw.println(" List scanned peers."); 606 pw.println(" set-device-name <name>"); 607 pw.println(" Set the p2p device name."); 608 pw.println(" get-connection-info"); 609 pw.println(" Get current connection information."); 610 pw.println(" get-group-info"); 611 pw.println(" Get current group information."); 612 pw.println(" get-network-info"); 613 pw.println(" Get current P2P network information."); 614 pw.println(" get-device-info"); 615 pw.println(" Get the device information"); 616 pw.println(" get-state"); 617 pw.println(" Get P2P state."); 618 pw.println(" get-discovery-state"); 619 pw.println(" Indicate whether p2p discovery is running or not."); 620 pw.println(" get-listen-state"); 621 pw.println(" Indicate whether p2p listen is running or not."); 622 pw.println(" list-saved-groups"); 623 pw.println(" List saved groups."); 624 pw.println(" delete-saved-group <networkId>"); 625 pw.println(" Delete a saved group."); 626 pw.println(" set-channels <listening channel> <operating channel>"); 627 pw.println(" Set listening channel and operating channel."); 628 pw.println(" set-miracast-mode (0|1|2)"); 629 pw.println(" Set Miracast mode. 0 is DISABLED, 1 is SOURCE, and 2 is SINK."); 630 pw.println(" factory-reset"); 631 pw.println(" Do P2P factory reset."); 632 pw.println(" accept-connection"); 633 pw.println(" Accept an incoming connection request."); 634 pw.println(" reject-connection"); 635 pw.println(" Reject an incoming connection request."); 636 pw.println(" connect <device address> [-i <groupOwnerIntent>] " 637 + "[-m <groupClientIpProvisioningMode>]"); 638 pw.println(" <device address> - the peer's MAC address."); 639 pw.println(" <groupOwnerIntent> - Set group owner intent value. The value range is " 640 + WifiP2pConfig.GROUP_OWNER_INTENT_MIN + " to " 641 + WifiP2pConfig.GROUP_OWNER_INTENT_MAX); 642 pw.println(" <groupClientIpProvisioningMode> - Set group client IP provisioning " 643 + "mode (supported on SdkLevel T or later)"); 644 pw.println(" - Use '" + WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP 645 + "' to select IPv4 DHCP which is system default behavior"); 646 pw.println(" - Use '" 647 + WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL 648 + "' to select IPv6 link-local."); 649 pw.println(" Connect to a device with provided params."); 650 pw.println(" connect-with-config <network name> <passphrase>" 651 + " <bandOrFreq> <persistent>"); 652 pw.println(" <bandOrFreq> - select the preferred band or frequency."); 653 pw.println(" - Use '2' to select 2.4GHz band as the preferred band"); 654 pw.println(" - Use '5' to select 5GHz band as the preferred band"); 655 pw.println(" - Use a frequency in MHz to indicate the preferred frequency."); 656 pw.println(" <persistent> true for a persistent group; otherwise false."); 657 pw.println(" Connect to a device with a configuration."); 658 pw.println(" remove-client <peerAddress>"); 659 pw.println(" <peerAddress> the MAC address of the p2p client."); 660 pw.println(" Remove the p2p client."); 661 pw.println(" cancel-connect"); 662 pw.println(" Cancel an onging connection request."); 663 pw.println(" create-group"); 664 pw.println(" Create a persistent autonomous group."); 665 pw.println(" create-group-with-config <network name> <passphrase>" 666 + " <bandOrFreq> <persistent>"); 667 pw.println(" <bandOrFreq> - select the preferred band or frequency."); 668 pw.println(" - Use '2' to select 2.4GHz band as the preferred band"); 669 pw.println(" - Use '5' to select 5GHz band as the preferred band"); 670 pw.println(" - Use a frequency in MHz to indicate the preferred frequency."); 671 pw.println(" <persistent> true for a persistent group; otherwise false."); 672 pw.println(" Create an autonomous group with a configuration."); 673 pw.println(" remove-group"); 674 pw.println(" Remove current formed group."); 675 pw.println(); 676 } 677 } 678