1 /* 2 * Copyright (C) 2011 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 static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_DEVICE_NAME; 20 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_PENDING_FACTORY_RESET; 21 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; 22 23 import android.annotation.Nullable; 24 import android.app.AlertDialog; 25 import android.content.BroadcastReceiver; 26 import android.content.Context; 27 import android.content.DialogInterface; 28 import android.content.DialogInterface.OnClickListener; 29 import android.content.Intent; 30 import android.content.IntentFilter; 31 import android.content.pm.PackageInfo; 32 import android.content.pm.PackageManager; 33 import android.content.res.Configuration; 34 import android.content.res.Resources; 35 import android.location.LocationManager; 36 import android.net.ConnectivityManager; 37 import android.net.DhcpResultsParcelable; 38 import android.net.InetAddresses; 39 import android.net.LinkProperties; 40 import android.net.NetworkInfo; 41 import android.net.NetworkStack; 42 import android.net.TetheringManager; 43 import android.net.ip.IIpClient; 44 import android.net.ip.IpClientCallbacks; 45 import android.net.ip.IpClientUtil; 46 import android.net.shared.ProvisioningConfiguration; 47 import android.net.wifi.CoexUnsafeChannel; 48 import android.net.wifi.ScanResult; 49 import android.net.wifi.WifiConfiguration; 50 import android.net.wifi.WifiInfo; 51 import android.net.wifi.WifiManager; 52 import android.net.wifi.WpsInfo; 53 import android.net.wifi.p2p.IWifiP2pManager; 54 import android.net.wifi.p2p.WifiP2pConfig; 55 import android.net.wifi.p2p.WifiP2pDevice; 56 import android.net.wifi.p2p.WifiP2pDeviceList; 57 import android.net.wifi.p2p.WifiP2pGroup; 58 import android.net.wifi.p2p.WifiP2pGroupList; 59 import android.net.wifi.p2p.WifiP2pGroupList.GroupDeleteListener; 60 import android.net.wifi.p2p.WifiP2pInfo; 61 import android.net.wifi.p2p.WifiP2pManager; 62 import android.net.wifi.p2p.WifiP2pProvDiscEvent; 63 import android.net.wifi.p2p.WifiP2pWfdInfo; 64 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; 65 import android.net.wifi.p2p.nsd.WifiP2pServiceRequest; 66 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; 67 import android.os.Binder; 68 import android.os.Bundle; 69 import android.os.Handler; 70 import android.os.HandlerThread; 71 import android.os.IBinder; 72 import android.os.Looper; 73 import android.os.Message; 74 import android.os.Messenger; 75 import android.os.Process; 76 import android.os.RemoteException; 77 import android.os.SystemClock; 78 import android.os.UserHandle; 79 import android.os.UserManager; 80 import android.os.WorkSource; 81 import android.provider.Settings; 82 import android.text.TextUtils; 83 import android.util.Log; 84 import android.util.SparseArray; 85 import android.view.KeyEvent; 86 import android.view.LayoutInflater; 87 import android.view.View; 88 import android.view.ViewGroup; 89 import android.view.WindowManager; 90 import android.widget.EditText; 91 import android.widget.TextView; 92 93 import com.android.internal.annotations.VisibleForTesting; 94 import com.android.internal.util.AsyncChannel; 95 import com.android.internal.util.Protocol; 96 import com.android.internal.util.State; 97 import com.android.internal.util.StateMachine; 98 import com.android.internal.util.WakeupMessage; 99 import com.android.modules.utils.build.SdkLevel; 100 import com.android.server.wifi.FrameworkFacade; 101 import com.android.server.wifi.WifiGlobals; 102 import com.android.server.wifi.WifiInjector; 103 import com.android.server.wifi.WifiLog; 104 import com.android.server.wifi.WifiSettingsConfigStore; 105 import com.android.server.wifi.coex.CoexManager; 106 import com.android.server.wifi.proto.nano.WifiMetricsProto.P2pConnectionEvent; 107 import com.android.server.wifi.util.NetdWrapper; 108 import com.android.server.wifi.util.StringUtil; 109 import com.android.server.wifi.util.WifiAsyncChannel; 110 import com.android.server.wifi.util.WifiHandler; 111 import com.android.server.wifi.util.WifiPermissionsUtil; 112 import com.android.server.wifi.util.WifiPermissionsWrapper; 113 import com.android.wifi.resources.R; 114 115 import java.io.FileDescriptor; 116 import java.io.PrintWriter; 117 import java.net.Inet4Address; 118 import java.net.InetAddress; 119 import java.net.NetworkInterface; 120 import java.net.SocketException; 121 import java.nio.charset.StandardCharsets; 122 import java.util.ArrayList; 123 import java.util.Collection; 124 import java.util.Enumeration; 125 import java.util.HashMap; 126 import java.util.List; 127 import java.util.Map; 128 import java.util.Objects; 129 import java.util.concurrent.ConcurrentHashMap; 130 import java.util.stream.Collectors; 131 132 /** 133 * WifiP2pService includes a state machine to perform Wi-Fi p2p operations. Applications 134 * communicate with this service to issue device discovery and connectivity requests 135 * through the WifiP2pManager interface. The state machine communicates with the wifi 136 * driver through wpa_supplicant and handles the event responses through WifiMonitor. 137 * 138 * Note that the term Wifi when used without a p2p suffix refers to the client mode 139 * of Wifi operation 140 * @hide 141 */ 142 public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { 143 private static final String TAG = "WifiP2pService"; 144 @VisibleForTesting 145 public static final String P2P_IDLE_SHUTDOWN_MESSAGE_TIMEOUT_TAG = TAG 146 + " Idle Shutdown Message Timeout"; 147 private boolean mVerboseLoggingEnabled = false; 148 private static final String NETWORKTYPE = "WIFI_P2P"; 149 @VisibleForTesting 150 static final String DEFAULT_DEVICE_NAME_PREFIX = "Android_"; 151 // The maxinum length of the device name is 32 bytes, see 152 // Section 4.1.15 in Wi-Fi Direct Specification v1 and 153 // Section 12 in Wi-Fi Protected Setup Specification v2. 154 @VisibleForTesting 155 static final int DEVICE_NAME_LENGTH_MAX = 32; 156 @VisibleForTesting 157 static final int DEVICE_NAME_POSTFIX_LENGTH_MIN = 4; 158 @VisibleForTesting 159 static final int DEVICE_NAME_PREFIX_LENGTH_MAX = 160 DEVICE_NAME_LENGTH_MAX - DEVICE_NAME_POSTFIX_LENGTH_MIN; 161 @VisibleForTesting 162 static final int DEFAULT_GROUP_OWNER_INTENT = 6; 163 164 @VisibleForTesting 165 // It requires to over "DISCOVER_TIMEOUT_S(120)" or "GROUP_CREATING_WAIT_TIME_MS(120)". 166 // Otherwise it will cause interface down before function timeout. 167 static final long P2P_INTERFACE_IDLE_SHUTDOWN_TIMEOUT_MS = 150_000; 168 169 private Context mContext; 170 171 NetdWrapper mNetdWrapper; 172 private IIpClient mIpClient; 173 private int mIpClientStartIndex = 0; 174 private DhcpResultsParcelable mDhcpResultsParcelable; 175 176 private P2pStateMachine mP2pStateMachine; 177 private AsyncChannel mReplyChannel = new WifiAsyncChannel(TAG); 178 private AsyncChannel mWifiChannel; 179 private LocationManager mLocationManager; 180 private WifiInjector mWifiInjector; 181 private WifiPermissionsUtil mWifiPermissionsUtil; 182 private FrameworkFacade mFrameworkFacade; 183 private WifiSettingsConfigStore mSettingsConfigStore; 184 private WifiP2pMetrics mWifiP2pMetrics; 185 // This will only be null if SdkLevel is not at least S 186 @Nullable private CoexManager mCoexManager; 187 private WifiGlobals mWifiGlobals; 188 189 private static final Boolean JOIN_GROUP = true; 190 private static final Boolean FORM_GROUP = false; 191 192 private static final Boolean RELOAD = true; 193 private static final Boolean NO_RELOAD = false; 194 195 private static final String[] RECEIVER_PERMISSIONS_FOR_BROADCAST = { 196 android.Manifest.permission.ACCESS_FINE_LOCATION, 197 android.Manifest.permission.ACCESS_WIFI_STATE 198 }; 199 200 private static final String[] RECEIVER_PERMISSIONS_FOR_BROADCAST_LOCATION_OFF = { 201 android.Manifest.permission.NETWORK_SETTINGS, 202 android.Manifest.permission.ACCESS_FINE_LOCATION, 203 android.Manifest.permission.ACCESS_WIFI_STATE 204 }; 205 206 // Maximum number of bytes allowed for a network name, i.e. SSID. 207 private static final int MAX_NETWORK_NAME_BYTES = 32; 208 // Minimum number of bytes for a network name, i.e. DIRECT-xy. 209 private static final int MIN_NETWORK_NAME_BYTES = 9; 210 211 // Two minutes comes from the wpa_supplicant setting 212 private static final int GROUP_CREATING_WAIT_TIME_MS = 120 * 1000; 213 private static int sGroupCreatingTimeoutIndex = 0; 214 215 private static final int DISABLE_P2P_WAIT_TIME_MS = 5 * 1000; 216 private static int sDisableP2pTimeoutIndex = 0; 217 218 // Set a two minute discover timeout to avoid STA scans from being blocked 219 private static final int DISCOVER_TIMEOUT_S = 120; 220 221 // Idle time after a peer is gone when the group is torn down 222 private static final int GROUP_IDLE_TIME_S = 10; 223 224 private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE; 225 226 // Delayed message to timeout group creation 227 public static final int GROUP_CREATING_TIMED_OUT = BASE + 1; 228 229 // User accepted a peer request 230 private static final int PEER_CONNECTION_USER_ACCEPT = BASE + 2; 231 // User rejected a peer request 232 private static final int PEER_CONNECTION_USER_REJECT = BASE + 3; 233 // User wants to disconnect wifi in favour of p2p 234 private static final int DROP_WIFI_USER_ACCEPT = BASE + 4; 235 // User wants to keep his wifi connection and drop p2p 236 private static final int DROP_WIFI_USER_REJECT = BASE + 5; 237 // Delayed message to timeout p2p disable 238 public static final int DISABLE_P2P_TIMED_OUT = BASE + 6; 239 // User confirm a peer request 240 public static final int PEER_CONNECTION_USER_CONFIRM = BASE + 7; 241 242 // Commands to the ClientModeImpl 243 public static final int P2P_CONNECTION_CHANGED = BASE + 11; 244 245 // These commands are used to temporarily disconnect wifi when we detect 246 // a frequency conflict which would make it impossible to have with p2p 247 // and wifi active at the same time. 248 // If the user chooses to disable wifi temporarily, we keep wifi disconnected 249 // until the p2p connection is done and terminated at which point we will 250 // bring back wifi up 251 // DISCONNECT_WIFI_REQUEST 252 // msg.arg1 = 1 enables temporary disconnect and 0 disables it. 253 public static final int DISCONNECT_WIFI_REQUEST = BASE + 12; 254 public static final int DISCONNECT_WIFI_RESPONSE = BASE + 13; 255 256 public static final int SET_MIRACAST_MODE = BASE + 14; 257 258 // During dhcp (and perhaps other times) we can't afford to drop packets 259 // but Discovery will switch our channel enough we will. 260 // msg.arg1 = ENABLED for blocking, DISABLED for resumed. 261 // msg.arg2 = msg to send when blocked 262 // msg.obj = StateMachine to send to when blocked 263 public static final int BLOCK_DISCOVERY = BASE + 15; 264 public static final int ENABLE_P2P = BASE + 16; 265 public static final int DISABLE_P2P = BASE + 17; 266 public static final int REMOVE_CLIENT_INFO = BASE + 18; 267 // idle shutdown message 268 public static final int CMD_P2P_IDLE_SHUTDOWN = BASE + 19; 269 270 // Messages for interaction with IpClient. 271 private static final int IPC_PRE_DHCP_ACTION = BASE + 30; 272 private static final int IPC_POST_DHCP_ACTION = BASE + 31; 273 private static final int IPC_DHCP_RESULTS = BASE + 32; 274 private static final int IPC_PROVISIONING_SUCCESS = BASE + 33; 275 private static final int IPC_PROVISIONING_FAILURE = BASE + 34; 276 277 private static final int GROUP_OWNER_TETHER_READY = BASE + 35; 278 279 private static final int UPDATE_P2P_DISALLOWED_CHANNELS = BASE + 36; 280 281 public static final int ENABLED = 1; 282 public static final int DISABLED = 0; 283 284 private static final int P2P_CONNECT_TRIGGER_GROUP_NEG_REQ = 1; 285 private static final int P2P_CONNECT_TRIGGER_INVITATION_REQ = 2; 286 private static final int P2P_CONNECT_TRIGGER_OTHER = 3; 287 288 289 private final boolean mP2pSupported; 290 291 private final WifiP2pDevice mThisDevice = new WifiP2pDevice(); 292 293 // When a group has been explicitly created by an app, we persist the group 294 // even after all clients have been disconnected until an explicit remove 295 // is invoked 296 private boolean mAutonomousGroup; 297 298 // Invitation to join an existing p2p group 299 private boolean mJoinExistingGroup; 300 301 // Track whether we are in p2p discovery. This is used to avoid sending duplicate 302 // broadcasts 303 private boolean mDiscoveryStarted; 304 305 // Track whether servcice/peer discovery is blocked in favor of other wifi actions 306 // (notably dhcp) 307 private boolean mDiscoveryBlocked; 308 309 // remember if we were in a scan when it had to be stopped 310 private boolean mDiscoveryPostponed = false; 311 312 private NetworkInfo.DetailedState mDetailedState; 313 314 private boolean mTemporarilyDisconnectedWifi = false; 315 316 // The transaction Id of service discovery request 317 private int mServiceTransactionId = 0; 318 319 // Service discovery request ID of wpa_supplicant. 320 // null means it's not set yet. 321 private String mServiceDiscReqId; 322 323 // clients(application) information list 324 private HashMap<Messenger, ClientInfo> mClientInfoList = new HashMap<Messenger, ClientInfo>(); 325 326 // clients(application) channel list 327 private Map<IBinder, Messenger> mClientChannelList = new HashMap<IBinder, Messenger>(); 328 329 // The empty device address set by wpa_supplicant. 330 private static final String EMPTY_DEVICE_ADDRESS = "00:00:00:00:00:00"; 331 332 // An anonymized device address. This is used instead of the own device MAC to prevent the 333 // latter from leaking to apps 334 private static final String ANONYMIZED_DEVICE_ADDRESS = "02:00:00:00:00:00"; 335 336 // Idle shut down 337 @VisibleForTesting 338 public WakeupMessage mP2pIdleShutdownMessage; 339 340 /** 341 * Error code definition. 342 * see the Table.8 in the WiFi Direct specification for the detail. 343 */ 344 public enum P2pStatus { 345 // Success 346 SUCCESS, 347 348 // The target device is currently unavailable 349 INFORMATION_IS_CURRENTLY_UNAVAILABLE, 350 351 // Protocol error 352 INCOMPATIBLE_PARAMETERS, 353 354 // The target device reached the limit of the number of the connectable device. 355 // For example, device limit or group limit is set 356 LIMIT_REACHED, 357 358 // Protocol error 359 INVALID_PARAMETER, 360 361 // Unable to accommodate request 362 UNABLE_TO_ACCOMMODATE_REQUEST, 363 364 // Previous protocol error, or disruptive behavior 365 PREVIOUS_PROTOCOL_ERROR, 366 367 // There is no common channels the both devices can use 368 NO_COMMON_CHANNEL, 369 370 // Unknown p2p group. For example, Device A tries to invoke the previous persistent group, 371 // but device B has removed the specified credential already 372 UNKNOWN_P2P_GROUP, 373 374 // Both p2p devices indicated an intent of 15 in group owner negotiation 375 BOTH_GO_INTENT_15, 376 377 // Incompatible provisioning method 378 INCOMPATIBLE_PROVISIONING_METHOD, 379 380 // Rejected by user 381 REJECTED_BY_USER, 382 383 // Unknown error 384 UNKNOWN; 385 386 /** 387 * Returns P2p status corresponding to a given error value 388 * @param error integer error value 389 * @return P2pStatus enum for value 390 */ valueOf(int error)391 public static P2pStatus valueOf(int error) { 392 switch(error) { 393 case 0 : 394 return SUCCESS; 395 case 1: 396 return INFORMATION_IS_CURRENTLY_UNAVAILABLE; 397 case 2: 398 return INCOMPATIBLE_PARAMETERS; 399 case 3: 400 return LIMIT_REACHED; 401 case 4: 402 return INVALID_PARAMETER; 403 case 5: 404 return UNABLE_TO_ACCOMMODATE_REQUEST; 405 case 6: 406 return PREVIOUS_PROTOCOL_ERROR; 407 case 7: 408 return NO_COMMON_CHANNEL; 409 case 8: 410 return UNKNOWN_P2P_GROUP; 411 case 9: 412 return BOTH_GO_INTENT_15; 413 case 10: 414 return INCOMPATIBLE_PROVISIONING_METHOD; 415 case 11: 416 return REJECTED_BY_USER; 417 default: 418 return UNKNOWN; 419 } 420 } 421 } 422 423 /** 424 * Handles client connections 425 */ 426 private class ClientHandler extends WifiHandler { 427 ClientHandler(String tag, android.os.Looper looper)428 ClientHandler(String tag, android.os.Looper looper) { 429 super(tag, looper); 430 } 431 432 @Override handleMessage(Message msg)433 public void handleMessage(Message msg) { 434 super.handleMessage(msg); 435 switch (msg.what) { 436 case WifiP2pManager.SET_DEVICE_NAME: 437 case WifiP2pManager.SET_WFD_INFO: 438 case WifiP2pManager.DISCOVER_PEERS: 439 case WifiP2pManager.STOP_DISCOVERY: 440 case WifiP2pManager.CONNECT: 441 case WifiP2pManager.CANCEL_CONNECT: 442 case WifiP2pManager.CREATE_GROUP: 443 case WifiP2pManager.REMOVE_GROUP: 444 case WifiP2pManager.START_LISTEN: 445 case WifiP2pManager.STOP_LISTEN: 446 case WifiP2pManager.SET_CHANNEL: 447 case WifiP2pManager.START_WPS: 448 case WifiP2pManager.ADD_LOCAL_SERVICE: 449 case WifiP2pManager.REMOVE_LOCAL_SERVICE: 450 case WifiP2pManager.CLEAR_LOCAL_SERVICES: 451 case WifiP2pManager.DISCOVER_SERVICES: 452 case WifiP2pManager.ADD_SERVICE_REQUEST: 453 case WifiP2pManager.REMOVE_SERVICE_REQUEST: 454 case WifiP2pManager.CLEAR_SERVICE_REQUESTS: 455 case WifiP2pManager.REQUEST_PEERS: 456 case WifiP2pManager.REQUEST_CONNECTION_INFO: 457 case WifiP2pManager.REQUEST_GROUP_INFO: 458 case WifiP2pManager.DELETE_PERSISTENT_GROUP: 459 case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO: 460 case WifiP2pManager.FACTORY_RESET: 461 case WifiP2pManager.SET_ONGOING_PEER_CONFIG: 462 case WifiP2pManager.REQUEST_ONGOING_PEER_CONFIG: 463 case WifiP2pManager.REQUEST_P2P_STATE: 464 case WifiP2pManager.REQUEST_DISCOVERY_STATE: 465 case WifiP2pManager.REQUEST_NETWORK_INFO: 466 case WifiP2pManager.UPDATE_CHANNEL_INFO: 467 case WifiP2pManager.REQUEST_DEVICE_INFO: 468 mP2pStateMachine.sendMessage(Message.obtain(msg)); 469 break; 470 default: 471 Log.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg); 472 break; 473 } 474 } 475 } 476 private ClientHandler mClientHandler; 477 makeNetworkInfo()478 private NetworkInfo makeNetworkInfo() { 479 final NetworkInfo info = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 480 0, NETWORKTYPE, ""); 481 if (mDetailedState != NetworkInfo.DetailedState.IDLE) { 482 info.setDetailedState(mDetailedState, null, null); 483 } 484 return info; 485 } 486 487 /** 488 * Provide a way for unit tests to set valid log object in the WifiHandler 489 * @param log WifiLog object to assign to the clientHandler 490 */ 491 @VisibleForTesting setWifiHandlerLogForTest(WifiLog log)492 void setWifiHandlerLogForTest(WifiLog log) { 493 mClientHandler.setWifiLog(log); 494 495 } 496 497 /** 498 * Provide a way for unit tests to set valid log object in the WifiAsyncChannel 499 * @param log WifiLog object to assign to the mReplyChannel 500 */ 501 @VisibleForTesting setWifiLogForReplyChannel(WifiLog log)502 void setWifiLogForReplyChannel(WifiLog log) { 503 ((WifiAsyncChannel) mReplyChannel).setWifiLog(log); 504 } 505 506 private class DeathHandlerData { DeathHandlerData(DeathRecipient dr, Messenger m, WorkSource ws)507 DeathHandlerData(DeathRecipient dr, Messenger m, WorkSource ws) { 508 mDeathRecipient = dr; 509 mMessenger = m; 510 mWorkSource = ws; 511 } 512 513 @Override toString()514 public String toString() { 515 return "deathRecipient=" + mDeathRecipient + ", messenger=" + mMessenger 516 + ", worksource=" + mWorkSource; 517 } 518 519 final DeathRecipient mDeathRecipient; 520 final Messenger mMessenger; 521 final WorkSource mWorkSource; 522 } 523 private Object mLock = new Object(); 524 private final Map<IBinder, DeathHandlerData> mDeathDataByBinder = new ConcurrentHashMap<>(); 525 WifiP2pServiceImpl(Context context, WifiInjector wifiInjector)526 public WifiP2pServiceImpl(Context context, WifiInjector wifiInjector) { 527 mContext = context; 528 mWifiInjector = wifiInjector; 529 mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil(); 530 mFrameworkFacade = mWifiInjector.getFrameworkFacade(); 531 mSettingsConfigStore = mWifiInjector.getSettingsConfigStore(); 532 mWifiP2pMetrics = mWifiInjector.getWifiP2pMetrics(); 533 mCoexManager = mWifiInjector.getCoexManager(); 534 mWifiGlobals = mWifiInjector.getWifiGlobals(); 535 536 mDetailedState = NetworkInfo.DetailedState.IDLE; 537 538 mP2pSupported = mContext.getPackageManager().hasSystemFeature( 539 PackageManager.FEATURE_WIFI_DIRECT); 540 541 HandlerThread wifiP2pThread = mWifiInjector.getWifiP2pServiceHandlerThread(); 542 mClientHandler = new ClientHandler(TAG, wifiP2pThread.getLooper()); 543 mP2pStateMachine = new P2pStateMachine(TAG, wifiP2pThread.getLooper(), mP2pSupported); 544 mP2pStateMachine.start(); 545 } 546 547 /** 548 * Obtains the service interface for Managements services 549 */ connectivityServiceReady()550 public void connectivityServiceReady() { 551 mNetdWrapper = mWifiInjector.makeNetdWrapper(); 552 } 553 enforceAccessPermission()554 private void enforceAccessPermission() { 555 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, 556 "WifiP2pService"); 557 } 558 enforceChangePermission()559 private void enforceChangePermission() { 560 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, 561 "WifiP2pService"); 562 } 563 checkAnyPermissionOf(String... permissions)564 private boolean checkAnyPermissionOf(String... permissions) { 565 for (String permission : permissions) { 566 if (mContext.checkCallingOrSelfPermission(permission) 567 == PackageManager.PERMISSION_GRANTED) { 568 return true; 569 } 570 } 571 return false; 572 } 573 enforceAnyPermissionOf(String... permissions)574 private void enforceAnyPermissionOf(String... permissions) { 575 if (!checkAnyPermissionOf(permissions)) { 576 throw new SecurityException("Requires one of the following permissions: " 577 + String.join(", ", permissions) + "."); 578 } 579 } 580 enforceNetworkStackOrLocationHardwarePermission()581 private void enforceNetworkStackOrLocationHardwarePermission() { 582 enforceAnyPermissionOf( 583 android.Manifest.permission.LOCATION_HARDWARE, 584 android.Manifest.permission.NETWORK_STACK, 585 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); 586 } 587 stopIpClient()588 private void stopIpClient() { 589 // Invalidate all previous start requests 590 mIpClientStartIndex++; 591 if (mIpClient != null) { 592 try { 593 mIpClient.shutdown(); 594 } catch (RemoteException e) { 595 e.rethrowFromSystemServer(); 596 } 597 mIpClient = null; 598 } 599 mDhcpResultsParcelable = null; 600 } 601 startIpClient(String ifname, Handler smHandler)602 private void startIpClient(String ifname, Handler smHandler) { 603 stopIpClient(); 604 mIpClientStartIndex++; 605 IpClientUtil.makeIpClient(mContext, ifname, new IpClientCallbacksImpl( 606 mIpClientStartIndex, smHandler)); 607 } 608 609 private class IpClientCallbacksImpl extends IpClientCallbacks { 610 private final int mStartIndex; 611 private final Handler mHandler; 612 IpClientCallbacksImpl(int startIndex, Handler handler)613 private IpClientCallbacksImpl(int startIndex, Handler handler) { 614 mStartIndex = startIndex; 615 mHandler = handler; 616 } 617 618 @Override onIpClientCreated(IIpClient ipClient)619 public void onIpClientCreated(IIpClient ipClient) { 620 mHandler.post(() -> { 621 if (mIpClientStartIndex != mStartIndex) { 622 // This start request is obsolete 623 return; 624 } 625 mIpClient = ipClient; 626 627 final ProvisioningConfiguration config = 628 new ProvisioningConfiguration.Builder() 629 .withoutIpReachabilityMonitor() 630 .withPreDhcpAction(30 * 1000) 631 .withProvisioningTimeoutMs(36 * 1000) 632 .build(); 633 try { 634 mIpClient.startProvisioning(config.toStableParcelable()); 635 } catch (RemoteException e) { 636 e.rethrowFromSystemServer(); 637 } 638 }); 639 } 640 641 @Override onPreDhcpAction()642 public void onPreDhcpAction() { 643 mP2pStateMachine.sendMessage(IPC_PRE_DHCP_ACTION); 644 } 645 @Override onPostDhcpAction()646 public void onPostDhcpAction() { 647 mP2pStateMachine.sendMessage(IPC_POST_DHCP_ACTION); 648 } 649 @Override onNewDhcpResults(DhcpResultsParcelable dhcpResults)650 public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) { 651 mP2pStateMachine.sendMessage(IPC_DHCP_RESULTS, dhcpResults); 652 } 653 @Override onProvisioningSuccess(LinkProperties newLp)654 public void onProvisioningSuccess(LinkProperties newLp) { 655 mP2pStateMachine.sendMessage(IPC_PROVISIONING_SUCCESS); 656 } 657 @Override onProvisioningFailure(LinkProperties newLp)658 public void onProvisioningFailure(LinkProperties newLp) { 659 mP2pStateMachine.sendMessage(IPC_PROVISIONING_FAILURE); 660 } 661 } 662 663 /** 664 * Get a reference to handler. This is used by a client to establish 665 * an AsyncChannel communication with WifiP2pService 666 */ 667 @Override getMessenger(final IBinder binder, final String packageName)668 public Messenger getMessenger(final IBinder binder, final String packageName) { 669 enforceAccessPermission(); 670 enforceChangePermission(); 671 672 synchronized (mLock) { 673 final Messenger messenger = new Messenger(mClientHandler); 674 if (mVerboseLoggingEnabled) { 675 Log.d(TAG, "getMessenger: uid=" + getCallingUid() + ", binder=" + binder 676 + ", messenger=" + messenger); 677 } 678 679 IBinder.DeathRecipient dr = () -> { 680 if (mVerboseLoggingEnabled) Log.d(TAG, "binderDied: binder=" + binder); 681 close(binder); 682 }; 683 684 WorkSource ws = packageName != null 685 ? new WorkSource(Binder.getCallingUid(), packageName) 686 : new WorkSource(Binder.getCallingUid()); 687 try { 688 binder.linkToDeath(dr, 0); 689 mDeathDataByBinder.put(binder, new DeathHandlerData(dr, messenger, ws)); 690 } catch (RemoteException e) { 691 Log.e(TAG, "Error on linkToDeath: e=" + e); 692 // fall-through here - won't clean up 693 } 694 // If p2p is already on, send ENABLE_P2P to merge the new worksource. 695 // If p2p is off, the first one activates P2P will merge all worksources. 696 if (!mP2pStateMachine.isP2pDisabled()) { 697 mP2pStateMachine.sendMessage(ENABLE_P2P); 698 } 699 return messenger; 700 } 701 } 702 703 /** 704 * Get a reference to handler. This is used by a ClientModeImpl to establish 705 * an AsyncChannel communication with P2pStateMachine 706 * @hide 707 */ 708 @Override getP2pStateMachineMessenger()709 public Messenger getP2pStateMachineMessenger() { 710 enforceNetworkStackOrLocationHardwarePermission(); 711 enforceAccessPermission(); 712 enforceChangePermission(); 713 return new Messenger(mP2pStateMachine.getHandler()); 714 } 715 716 /** 717 * Clean-up the state and configuration requested by the closing app. Takes same action as 718 * when the app dies (binder death). 719 */ 720 @Override close(IBinder binder)721 public void close(IBinder binder) { 722 enforceAccessPermission(); 723 enforceChangePermission(); 724 725 DeathHandlerData dhd; 726 synchronized (mLock) { 727 dhd = mDeathDataByBinder.get(binder); 728 if (dhd == null) { 729 Log.w(TAG, "close(): no death recipient for binder"); 730 return; 731 } 732 733 mP2pStateMachine.sendMessage(REMOVE_CLIENT_INFO, 0, 0, binder); 734 binder.unlinkToDeath(dhd.mDeathRecipient, 0); 735 mDeathDataByBinder.remove(binder); 736 737 // clean-up if there are no more clients registered 738 // TODO: what does the ClientModeImpl client do? It isn't tracked through here! 739 if (dhd.mMessenger != null && mDeathDataByBinder.isEmpty()) { 740 try { 741 dhd.mMessenger.send( 742 mClientHandler.obtainMessage(WifiP2pManager.STOP_DISCOVERY)); 743 dhd.mMessenger.send(mClientHandler.obtainMessage(WifiP2pManager.REMOVE_GROUP)); 744 } catch (RemoteException e) { 745 Log.e(TAG, "close: Failed sending clean-up commands: e=" + e); 746 } 747 mP2pStateMachine.sendMessage(DISABLE_P2P); 748 } 749 } 750 } 751 752 /** This is used to provide information to drivers to optimize performance depending 753 * on the current mode of operation. 754 * 0 - disabled 755 * 1 - source operation 756 * 2 - sink operation 757 * 758 * As an example, the driver could reduce the channel dwell time during scanning 759 * when acting as a source or sink to minimize impact on miracast. 760 * @param int mode of operation 761 */ 762 @Override setMiracastMode(int mode)763 public void setMiracastMode(int mode) { 764 checkConfigureWifiDisplayPermission(); 765 mP2pStateMachine.sendMessage(SET_MIRACAST_MODE, mode); 766 } 767 768 @Override checkConfigureWifiDisplayPermission()769 public void checkConfigureWifiDisplayPermission() { 770 if (!getWfdPermission(Binder.getCallingUid())) { 771 throw new SecurityException("Wifi Display Permission denied for uid = " 772 + Binder.getCallingUid()); 773 } 774 } 775 getWfdPermission(int uid)776 private boolean getWfdPermission(int uid) { 777 WifiPermissionsWrapper wifiPermissionsWrapper = mWifiInjector.getWifiPermissionsWrapper(); 778 return wifiPermissionsWrapper.getUidPermission( 779 android.Manifest.permission.CONFIGURE_WIFI_DISPLAY, uid) 780 != PackageManager.PERMISSION_DENIED; 781 } 782 783 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)784 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 785 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 786 != PackageManager.PERMISSION_GRANTED) { 787 pw.println("Permission Denial: can't dump WifiP2pService from from pid=" 788 + Binder.getCallingPid() 789 + ", uid=" + Binder.getCallingUid()); 790 return; 791 } 792 mP2pStateMachine.dump(fd, pw, args); 793 pw.println("mAutonomousGroup " + mAutonomousGroup); 794 pw.println("mJoinExistingGroup " + mJoinExistingGroup); 795 pw.println("mDiscoveryStarted " + mDiscoveryStarted); 796 pw.println("mDetailedState " + mDetailedState); 797 pw.println("mTemporarilyDisconnectedWifi " + mTemporarilyDisconnectedWifi); 798 pw.println("mServiceDiscReqId " + mServiceDiscReqId); 799 pw.println("mDeathDataByBinder " + mDeathDataByBinder); 800 pw.println("mClientInfoList " + mClientInfoList.size()); 801 pw.println(); 802 803 final IIpClient ipClient = mIpClient; 804 if (ipClient != null) { 805 pw.println("mIpClient:"); 806 IpClientUtil.dumpIpClient(ipClient, fd, pw, args); 807 } 808 } 809 810 /** 811 * Handles interaction with ClientModeImpl 812 */ 813 private class P2pStateMachine extends StateMachine { 814 815 private DefaultState mDefaultState = new DefaultState(); 816 private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState(); 817 private P2pDisablingState mP2pDisablingState = new P2pDisablingState(); 818 private P2pDisabledState mP2pDisabledState = new P2pDisabledState(); 819 private P2pEnabledState mP2pEnabledState = new P2pEnabledState(); 820 // Inactive is when p2p is enabled with no connectivity 821 private InactiveState mInactiveState = new InactiveState(); 822 private GroupCreatingState mGroupCreatingState = new GroupCreatingState(); 823 private UserAuthorizingInviteRequestState mUserAuthorizingInviteRequestState = 824 new UserAuthorizingInviteRequestState(); 825 private UserAuthorizingNegotiationRequestState mUserAuthorizingNegotiationRequestState = 826 new UserAuthorizingNegotiationRequestState(); 827 private ProvisionDiscoveryState mProvisionDiscoveryState = new ProvisionDiscoveryState(); 828 private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState(); 829 private FrequencyConflictState mFrequencyConflictState = new FrequencyConflictState(); 830 831 private GroupCreatedState mGroupCreatedState = new GroupCreatedState(); 832 private UserAuthorizingJoinState mUserAuthorizingJoinState = new UserAuthorizingJoinState(); 833 private OngoingGroupRemovalState mOngoingGroupRemovalState = new OngoingGroupRemovalState(); 834 835 private WifiP2pNative mWifiNative = mWifiInjector.getWifiP2pNative(); 836 private WifiP2pMonitor mWifiMonitor = mWifiInjector.getWifiP2pMonitor(); 837 private final WifiP2pDeviceList mPeers = new WifiP2pDeviceList(); 838 private String mInterfaceName; 839 840 private List<CoexUnsafeChannel> mCoexUnsafeChannels = new ArrayList<>(); 841 private int mUserListenChannel = 0; 842 private int mUserOperatingChannel = 0; 843 844 // During a connection, supplicant can tell us that a device was lost. From a supplicant's 845 // perspective, the discovery stops during connection and it purges device since it does 846 // not get latest updates about the device without being in discovery state. 847 // From the framework perspective, the device is still there since we are connecting or 848 // connected to it. so we keep these devices in a separate list, so that they are removed 849 // when connection is cancelled or lost 850 private final WifiP2pDeviceList mPeersLostDuringConnection = new WifiP2pDeviceList(); 851 private final WifiP2pGroupList mGroups = new WifiP2pGroupList(null, 852 new GroupDeleteListener() { 853 @Override 854 public void onDeleteGroup(int netId) { 855 if (mVerboseLoggingEnabled) logd("called onDeleteGroup() netId=" + netId); 856 mWifiNative.removeP2pNetwork(netId); 857 mWifiNative.saveConfig(); 858 sendP2pPersistentGroupsChangedBroadcast(); 859 } 860 }); 861 private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo(); 862 private WifiP2pGroup mGroup; 863 // Is wifi on or off. 864 private boolean mIsWifiEnabled = false; 865 866 // Saved WifiP2pConfig for an ongoing peer connection. This will never be null. 867 // The deviceAddress will be an empty string when the device is inactive 868 // or if it is connected without any ongoing join request 869 private WifiP2pConfig mSavedPeerConfig = new WifiP2pConfig(); 870 P2pStateMachine(String name, Looper looper, boolean p2pSupported)871 P2pStateMachine(String name, Looper looper, boolean p2pSupported) { 872 super(name, looper); 873 874 // CHECKSTYLE:OFF IndentationCheck 875 addState(mDefaultState); 876 addState(mP2pNotSupportedState, mDefaultState); 877 addState(mP2pDisablingState, mDefaultState); 878 addState(mP2pDisabledState, mDefaultState); 879 addState(mP2pEnabledState, mDefaultState); 880 addState(mInactiveState, mP2pEnabledState); 881 addState(mGroupCreatingState, mP2pEnabledState); 882 addState(mUserAuthorizingInviteRequestState, mGroupCreatingState); 883 addState(mUserAuthorizingNegotiationRequestState, mGroupCreatingState); 884 addState(mProvisionDiscoveryState, mGroupCreatingState); 885 addState(mGroupNegotiationState, mGroupCreatingState); 886 addState(mFrequencyConflictState, mGroupCreatingState); 887 addState(mGroupCreatedState, mP2pEnabledState); 888 addState(mUserAuthorizingJoinState, mGroupCreatedState); 889 addState(mOngoingGroupRemovalState, mGroupCreatedState); 890 // CHECKSTYLE:ON IndentationCheck 891 892 if (p2pSupported) { 893 setInitialState(mP2pDisabledState); 894 } else { 895 setInitialState(mP2pNotSupportedState); 896 } 897 setLogRecSize(50); 898 setLogOnlyTransitions(true); 899 900 if (p2pSupported) { 901 // Init p2p idle shutdown message 902 mP2pIdleShutdownMessage = new WakeupMessage(mContext, 903 this.getHandler(), 904 P2P_IDLE_SHUTDOWN_MESSAGE_TIMEOUT_TAG, 905 CMD_P2P_IDLE_SHUTDOWN); 906 907 // Register for wifi on/off broadcasts 908 mContext.registerReceiver(new BroadcastReceiver() { 909 @Override 910 public void onReceive(Context context, Intent intent) { 911 int wifistate = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 912 WifiManager.WIFI_STATE_UNKNOWN); 913 if (wifistate == WifiManager.WIFI_STATE_ENABLED) { 914 mIsWifiEnabled = true; 915 } else { 916 mIsWifiEnabled = false; 917 // Teardown P2P if it's up already. 918 sendMessage(DISABLE_P2P); 919 } 920 checkAndSendP2pStateChangedBroadcast(); 921 } 922 }, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)); 923 // Register for location mode on/off broadcasts 924 mContext.registerReceiver(new BroadcastReceiver() { 925 @Override 926 public void onReceive(Context context, Intent intent) { 927 /* if location mode is off, ongoing discovery should be stopped. 928 * possible ongoing discovery: 929 * - peer discovery 930 * - service discovery 931 * - group joining scan in native service 932 */ 933 if (!mWifiPermissionsUtil.isLocationModeEnabled()) { 934 sendMessage(WifiP2pManager.STOP_DISCOVERY); 935 } 936 } 937 }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION)); 938 // Register for tethering state 939 mContext.registerReceiver(new BroadcastReceiver() { 940 @Override 941 public void onReceive(Context context, Intent intent) { 942 if (mGroup == null) return; 943 if (!mGroup.isGroupOwner()) return; 944 if (TextUtils.isEmpty(mGroup.getInterface())) return; 945 946 final ArrayList<String> interfaces = intent.getStringArrayListExtra( 947 TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY); 948 949 if (interfaces.contains(mGroup.getInterface())) { 950 sendMessage(GROUP_OWNER_TETHER_READY); 951 } 952 } 953 }, new IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)); 954 mSettingsConfigStore.registerChangeListener( 955 WIFI_VERBOSE_LOGGING_ENABLED, 956 (key, newValue) -> enableVerboseLogging(newValue), 957 getHandler()); 958 if (SdkLevel.isAtLeastS()) { 959 mCoexManager.registerCoexListener(new CoexManager.CoexListener() { 960 @Override 961 public void onCoexUnsafeChannelsChanged() { 962 checkCoexUnsafeChannels(); 963 } 964 }); 965 } 966 } 967 } 968 isP2pDisabled()969 boolean isP2pDisabled() { 970 return getCurrentState() == mP2pDisabledState; 971 } 972 scheduleIdleShutdown()973 void scheduleIdleShutdown() { 974 if (mP2pIdleShutdownMessage != null) { 975 mP2pIdleShutdownMessage.cancel(); 976 mP2pIdleShutdownMessage.schedule(SystemClock.elapsedRealtime() 977 + P2P_INTERFACE_IDLE_SHUTDOWN_TIMEOUT_MS); 978 if (mVerboseLoggingEnabled) { 979 Log.d(TAG, "IdleShutDown message (re)scheduled in " 980 + (P2P_INTERFACE_IDLE_SHUTDOWN_TIMEOUT_MS / 1000) + "s"); 981 } 982 } 983 mP2pStateMachine.getHandler().removeMessages(CMD_P2P_IDLE_SHUTDOWN); 984 } 985 cancelIdleShutdown()986 void cancelIdleShutdown() { 987 if (mP2pIdleShutdownMessage != null) { 988 mP2pIdleShutdownMessage.cancel(); 989 if (mVerboseLoggingEnabled) { 990 Log.d(TAG, "IdleShutDown message canceled"); 991 } 992 } 993 mP2pStateMachine.getHandler().removeMessages(CMD_P2P_IDLE_SHUTDOWN); 994 } 995 checkCoexUnsafeChannels()996 void checkCoexUnsafeChannels() { 997 List<CoexUnsafeChannel> unsafeChannels = null; 998 999 // If WIFI DIRECT bit is not set, pass null to clear unsafe channels. 1000 if (SdkLevel.isAtLeastS() 1001 && (mCoexManager.getCoexRestrictions() 1002 & WifiManager.COEX_RESTRICTION_WIFI_DIRECT) != 0) { 1003 unsafeChannels = mCoexManager.getCoexUnsafeChannels(); 1004 Log.d(TAG, "UnsafeChannels: " 1005 + unsafeChannels.stream() 1006 .map(Object::toString) 1007 .collect(Collectors.joining(","))); 1008 } 1009 1010 sendMessage(UPDATE_P2P_DISALLOWED_CHANNELS, unsafeChannels); 1011 } 1012 1013 /** 1014 * Enable verbose logging for all sub modules. 1015 */ enableVerboseLogging(boolean verbose)1016 private void enableVerboseLogging(boolean verbose) { 1017 mVerboseLoggingEnabled = verbose; 1018 mWifiNative.enableVerboseLogging(verbose ? 1 : 0); 1019 mWifiMonitor.enableVerboseLogging(verbose ? 1 : 0); 1020 } 1021 registerForWifiMonitorEvents()1022 public void registerForWifiMonitorEvents() { 1023 mWifiMonitor.registerHandler(mInterfaceName, 1024 WifiP2pMonitor.AP_STA_CONNECTED_EVENT, getHandler()); 1025 mWifiMonitor.registerHandler(mInterfaceName, 1026 WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT, getHandler()); 1027 mWifiMonitor.registerHandler(mInterfaceName, 1028 WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT, getHandler()); 1029 mWifiMonitor.registerHandler(mInterfaceName, 1030 WifiP2pMonitor.P2P_DEVICE_LOST_EVENT, getHandler()); 1031 mWifiMonitor.registerHandler(mInterfaceName, 1032 WifiP2pMonitor.P2P_FIND_STOPPED_EVENT, getHandler()); 1033 mWifiMonitor.registerHandler(mInterfaceName, 1034 WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT, getHandler()); 1035 mWifiMonitor.registerHandler(mInterfaceName, 1036 WifiP2pMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT, getHandler()); 1037 mWifiMonitor.registerHandler(mInterfaceName, 1038 WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT, getHandler()); 1039 mWifiMonitor.registerHandler(mInterfaceName, 1040 WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT, getHandler()); 1041 mWifiMonitor.registerHandler(mInterfaceName, 1042 WifiP2pMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT, getHandler()); 1043 mWifiMonitor.registerHandler(mInterfaceName, 1044 WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT, getHandler()); 1045 mWifiMonitor.registerHandler(mInterfaceName, 1046 WifiP2pMonitor.P2P_GROUP_STARTED_EVENT, getHandler()); 1047 mWifiMonitor.registerHandler(mInterfaceName, 1048 WifiP2pMonitor.P2P_INVITATION_RECEIVED_EVENT, getHandler()); 1049 mWifiMonitor.registerHandler(mInterfaceName, 1050 WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT, getHandler()); 1051 mWifiMonitor.registerHandler(mInterfaceName, 1052 WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT, getHandler()); 1053 mWifiMonitor.registerHandler(mInterfaceName, 1054 WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT, getHandler()); 1055 mWifiMonitor.registerHandler(mInterfaceName, 1056 WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT, getHandler()); 1057 mWifiMonitor.registerHandler(mInterfaceName, 1058 WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT, getHandler()); 1059 mWifiMonitor.registerHandler(mInterfaceName, 1060 WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT, getHandler()); 1061 mWifiMonitor.registerHandler(mInterfaceName, 1062 WifiP2pMonitor.P2P_SERV_DISC_RESP_EVENT, getHandler()); 1063 mWifiMonitor.registerHandler(mInterfaceName, 1064 WifiP2pMonitor.SUP_CONNECTION_EVENT, getHandler()); 1065 mWifiMonitor.registerHandler(mInterfaceName, 1066 WifiP2pMonitor.SUP_DISCONNECTION_EVENT, getHandler()); 1067 1068 mWifiMonitor.startMonitoring(mInterfaceName); 1069 } 1070 createMergedRequestorWs()1071 private WorkSource createMergedRequestorWs() { 1072 WorkSource requestorWs = new WorkSource(); 1073 for (DeathHandlerData deathHandlerData : mDeathDataByBinder.values()) { 1074 requestorWs.add(deathHandlerData.mWorkSource); 1075 } 1076 return requestorWs; 1077 } 1078 1079 class DefaultState extends State { 1080 @Override processMessage(Message message)1081 public boolean processMessage(Message message) { 1082 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 1083 switch (message.what) { 1084 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 1085 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 1086 if (mVerboseLoggingEnabled) { 1087 logd("Full connection with ClientModeImpl established"); 1088 } 1089 mWifiChannel = (AsyncChannel) message.obj; 1090 } else { 1091 loge("Full connection failure, error = " + message.arg1); 1092 mWifiChannel = null; 1093 transitionTo(mP2pDisabledState); 1094 } 1095 break; 1096 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 1097 if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { 1098 loge("Send failed, client connection lost"); 1099 } else { 1100 loge("Client connection lost with reason: " + message.arg1); 1101 } 1102 mWifiChannel = null; 1103 transitionTo(mP2pDisabledState); 1104 break; 1105 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: 1106 AsyncChannel ac = new WifiAsyncChannel(TAG); 1107 ac.connect(mContext, getHandler(), message.replyTo); 1108 break; 1109 case BLOCK_DISCOVERY: 1110 mDiscoveryBlocked = (message.arg1 == ENABLED ? true : false); 1111 // always reset this - we went to a state that doesn't support discovery so 1112 // it would have stopped regardless 1113 mDiscoveryPostponed = false; 1114 if (mDiscoveryBlocked && mWifiChannel != null) { 1115 mWifiChannel.replyToMessage(message, message.arg2); 1116 } 1117 break; 1118 case WifiP2pManager.DISCOVER_PEERS: 1119 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 1120 WifiP2pManager.BUSY); 1121 break; 1122 case WifiP2pManager.STOP_DISCOVERY: 1123 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, 1124 WifiP2pManager.BUSY); 1125 break; 1126 case WifiP2pManager.DISCOVER_SERVICES: 1127 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 1128 WifiP2pManager.BUSY); 1129 break; 1130 case WifiP2pManager.CONNECT: 1131 replyToMessage(message, WifiP2pManager.CONNECT_FAILED, 1132 WifiP2pManager.BUSY); 1133 break; 1134 case WifiP2pManager.CANCEL_CONNECT: 1135 replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED, 1136 WifiP2pManager.BUSY); 1137 break; 1138 case WifiP2pManager.CREATE_GROUP: 1139 replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, 1140 WifiP2pManager.BUSY); 1141 break; 1142 case WifiP2pManager.REMOVE_GROUP: 1143 replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, 1144 WifiP2pManager.BUSY); 1145 break; 1146 case WifiP2pManager.ADD_LOCAL_SERVICE: 1147 replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED, 1148 WifiP2pManager.BUSY); 1149 break; 1150 case WifiP2pManager.REMOVE_LOCAL_SERVICE: 1151 replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED, 1152 WifiP2pManager.BUSY); 1153 break; 1154 case WifiP2pManager.CLEAR_LOCAL_SERVICES: 1155 replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED, 1156 WifiP2pManager.BUSY); 1157 break; 1158 case WifiP2pManager.ADD_SERVICE_REQUEST: 1159 replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED, 1160 WifiP2pManager.BUSY); 1161 break; 1162 case WifiP2pManager.REMOVE_SERVICE_REQUEST: 1163 replyToMessage(message, 1164 WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED, 1165 WifiP2pManager.BUSY); 1166 break; 1167 case WifiP2pManager.CLEAR_SERVICE_REQUESTS: 1168 replyToMessage(message, 1169 WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED, 1170 WifiP2pManager.BUSY); 1171 break; 1172 case WifiP2pManager.SET_DEVICE_NAME: 1173 replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, 1174 WifiP2pManager.BUSY); 1175 break; 1176 case WifiP2pManager.DELETE_PERSISTENT_GROUP: 1177 replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, 1178 WifiP2pManager.BUSY); 1179 break; 1180 case WifiP2pManager.SET_WFD_INFO: 1181 if (!getWfdPermission(message.sendingUid)) { 1182 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 1183 WifiP2pManager.ERROR); 1184 } else { 1185 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 1186 WifiP2pManager.BUSY); 1187 } 1188 break; 1189 case WifiP2pManager.REQUEST_PEERS: 1190 replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, 1191 getPeers(getCallingPkgName(message.sendingUid, message.replyTo), 1192 getCallingFeatureId(message.sendingUid, message.replyTo), 1193 message.sendingUid)); 1194 break; 1195 case WifiP2pManager.REQUEST_CONNECTION_INFO: 1196 replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, 1197 new WifiP2pInfo(mWifiP2pInfo)); 1198 break; 1199 case WifiP2pManager.REQUEST_GROUP_INFO: 1200 if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( 1201 getCallingPkgName(message.sendingUid, message.replyTo), 1202 getCallingFeatureId(message.sendingUid, message.replyTo), 1203 message.sendingUid, false)) { 1204 replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, null); 1205 // remain at this state. 1206 break; 1207 } 1208 replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, 1209 maybeEraseOwnDeviceAddress(mGroup, message.sendingUid)); 1210 break; 1211 case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO: 1212 if (!checkNetworkSettingsOrNetworkStackOrReadWifiCredentialPermission( 1213 message.sendingUid)) { 1214 loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," 1215 + " or READ_WIFI_CREDENTIAL permission, uid = " 1216 + message.sendingUid); 1217 replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO, 1218 new WifiP2pGroupList()); 1219 break; 1220 } 1221 replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO, 1222 new WifiP2pGroupList( 1223 maybeEraseOwnDeviceAddress(mGroups, message.sendingUid), 1224 null)); 1225 break; 1226 case WifiP2pManager.REQUEST_P2P_STATE: 1227 replyToMessage(message, WifiP2pManager.RESPONSE_P2P_STATE, 1228 mIsWifiEnabled 1229 ? WifiP2pManager.WIFI_P2P_STATE_ENABLED 1230 : WifiP2pManager.WIFI_P2P_STATE_DISABLED); 1231 break; 1232 case WifiP2pManager.REQUEST_DISCOVERY_STATE: 1233 replyToMessage(message, WifiP2pManager.RESPONSE_DISCOVERY_STATE, 1234 mDiscoveryStarted 1235 ? WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED 1236 : WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED); 1237 break; 1238 case WifiP2pManager.REQUEST_NETWORK_INFO: 1239 replyToMessage(message, WifiP2pManager.RESPONSE_NETWORK_INFO, 1240 makeNetworkInfo()); 1241 break; 1242 case WifiP2pManager.START_WPS: 1243 replyToMessage(message, WifiP2pManager.START_WPS_FAILED, 1244 WifiP2pManager.BUSY); 1245 break; 1246 case WifiP2pManager.GET_HANDOVER_REQUEST: 1247 case WifiP2pManager.GET_HANDOVER_SELECT: 1248 replyToMessage(message, WifiP2pManager.RESPONSE_GET_HANDOVER_MESSAGE, null); 1249 break; 1250 case WifiP2pManager.INITIATOR_REPORT_NFC_HANDOVER: 1251 case WifiP2pManager.RESPONDER_REPORT_NFC_HANDOVER: 1252 replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED, 1253 WifiP2pManager.BUSY); 1254 break; 1255 case WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT: 1256 case WifiP2pMonitor.SUP_CONNECTION_EVENT: 1257 case WifiP2pMonitor.SUP_DISCONNECTION_EVENT: 1258 case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: 1259 case WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT: 1260 case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: 1261 case WifiP2pMonitor.P2P_FIND_STOPPED_EVENT: 1262 case WifiP2pMonitor.P2P_SERV_DISC_RESP_EVENT: 1263 case PEER_CONNECTION_USER_ACCEPT: 1264 case PEER_CONNECTION_USER_REJECT: 1265 case DISCONNECT_WIFI_RESPONSE: 1266 case DROP_WIFI_USER_ACCEPT: 1267 case DROP_WIFI_USER_REJECT: 1268 case GROUP_CREATING_TIMED_OUT: 1269 case DISABLE_P2P_TIMED_OUT: 1270 case IPC_PRE_DHCP_ACTION: 1271 case IPC_POST_DHCP_ACTION: 1272 case IPC_DHCP_RESULTS: 1273 case IPC_PROVISIONING_SUCCESS: 1274 case IPC_PROVISIONING_FAILURE: 1275 case GROUP_OWNER_TETHER_READY: 1276 case UPDATE_P2P_DISALLOWED_CHANNELS: 1277 case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: 1278 case SET_MIRACAST_MODE: 1279 case WifiP2pManager.START_LISTEN: 1280 case WifiP2pManager.STOP_LISTEN: 1281 case WifiP2pManager.SET_CHANNEL: 1282 case ENABLE_P2P: 1283 // Enable is lazy and has no response 1284 break; 1285 case DISABLE_P2P: 1286 // If we end up handling in default, p2p is not enabled 1287 break; 1288 case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: 1289 // unexpected group created, remove 1290 if (message.obj == null) { 1291 Log.e(TAG, "Illegal arguments"); 1292 break; 1293 } 1294 mGroup = (WifiP2pGroup) message.obj; 1295 loge("Unexpected group creation, remove " + mGroup); 1296 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 1297 break; 1298 case WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: 1299 // A group formation failure is always followed by 1300 // a group removed event. Flushing things at group formation 1301 // failure causes supplicant issues. Ignore right now. 1302 break; 1303 case WifiP2pManager.FACTORY_RESET: 1304 if (factoryReset(message.sendingUid)) { 1305 replyToMessage(message, WifiP2pManager.FACTORY_RESET_SUCCEEDED); 1306 } else { 1307 replyToMessage(message, WifiP2pManager.FACTORY_RESET_FAILED, 1308 WifiP2pManager.ERROR); 1309 } 1310 break; 1311 case WifiP2pManager.SET_ONGOING_PEER_CONFIG: 1312 if (mWifiPermissionsUtil.checkNetworkStackPermission(message.sendingUid)) { 1313 WifiP2pConfig peerConfig = (WifiP2pConfig) message.obj; 1314 if (isConfigInvalid(peerConfig)) { 1315 loge("Dropping set mSavedPeerConfig requeset" + peerConfig); 1316 replyToMessage(message, 1317 WifiP2pManager.SET_ONGOING_PEER_CONFIG_FAILED); 1318 } else { 1319 logd("setSavedPeerConfig to " + peerConfig); 1320 mSavedPeerConfig = peerConfig; 1321 replyToMessage(message, 1322 WifiP2pManager.SET_ONGOING_PEER_CONFIG_SUCCEEDED); 1323 } 1324 } else { 1325 loge("Permission violation - no NETWORK_STACK permission," 1326 + " uid = " + message.sendingUid); 1327 replyToMessage(message, 1328 WifiP2pManager.SET_ONGOING_PEER_CONFIG_FAILED); 1329 } 1330 break; 1331 case WifiP2pManager.REQUEST_ONGOING_PEER_CONFIG: 1332 if (mWifiPermissionsUtil.checkNetworkStackPermission(message.sendingUid)) { 1333 replyToMessage(message, 1334 WifiP2pManager.RESPONSE_ONGOING_PEER_CONFIG, mSavedPeerConfig); 1335 } else { 1336 loge("Permission violation - no NETWORK_STACK permission," 1337 + " uid = " + message.sendingUid); 1338 replyToMessage(message, 1339 WifiP2pManager.RESPONSE_ONGOING_PEER_CONFIG, null); 1340 } 1341 break; 1342 case WifiP2pManager.UPDATE_CHANNEL_INFO: 1343 if (!(message.obj instanceof Bundle)) { 1344 break; 1345 } 1346 Bundle bundle = (Bundle) message.obj; 1347 String pkgName = bundle.getString(WifiP2pManager.CALLING_PACKAGE); 1348 String featureId = bundle.getString(WifiP2pManager.CALLING_FEATURE_ID); 1349 IBinder binder = bundle.getBinder(WifiP2pManager.CALLING_BINDER); 1350 try { 1351 mWifiPermissionsUtil.checkPackage(message.sendingUid, pkgName); 1352 } catch (SecurityException se) { 1353 loge("Unable to update calling package, " + se); 1354 break; 1355 } 1356 if (binder != null && message.replyTo != null) { 1357 mClientChannelList.put(binder, message.replyTo); 1358 ClientInfo clientInfo = getClientInfo(message.replyTo, true); 1359 clientInfo.mPackageName = pkgName; 1360 clientInfo.mFeatureId = featureId; 1361 } 1362 break; 1363 case WifiP2pManager.REQUEST_DEVICE_INFO: 1364 if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( 1365 getCallingPkgName(message.sendingUid, message.replyTo), 1366 getCallingFeatureId(message.sendingUid, message.replyTo), 1367 message.sendingUid, false)) { 1368 replyToMessage(message, WifiP2pManager.RESPONSE_DEVICE_INFO, null); 1369 break; 1370 } 1371 replyToMessage(message, WifiP2pManager.RESPONSE_DEVICE_INFO, 1372 maybeEraseOwnDeviceAddress(mThisDevice, message.sendingUid)); 1373 break; 1374 default: 1375 loge("Unhandled message " + message); 1376 return NOT_HANDLED; 1377 } 1378 return HANDLED; 1379 } 1380 } 1381 1382 class P2pNotSupportedState extends State { 1383 @Override processMessage(Message message)1384 public boolean processMessage(Message message) { 1385 switch (message.what) { 1386 case WifiP2pManager.DISCOVER_PEERS: 1387 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 1388 WifiP2pManager.P2P_UNSUPPORTED); 1389 break; 1390 case WifiP2pManager.STOP_DISCOVERY: 1391 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, 1392 WifiP2pManager.P2P_UNSUPPORTED); 1393 break; 1394 case WifiP2pManager.DISCOVER_SERVICES: 1395 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 1396 WifiP2pManager.P2P_UNSUPPORTED); 1397 break; 1398 case WifiP2pManager.CONNECT: 1399 replyToMessage(message, WifiP2pManager.CONNECT_FAILED, 1400 WifiP2pManager.P2P_UNSUPPORTED); 1401 break; 1402 case WifiP2pManager.CANCEL_CONNECT: 1403 replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED, 1404 WifiP2pManager.P2P_UNSUPPORTED); 1405 break; 1406 case WifiP2pManager.CREATE_GROUP: 1407 replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, 1408 WifiP2pManager.P2P_UNSUPPORTED); 1409 break; 1410 case WifiP2pManager.REMOVE_GROUP: 1411 replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, 1412 WifiP2pManager.P2P_UNSUPPORTED); 1413 break; 1414 case WifiP2pManager.ADD_LOCAL_SERVICE: 1415 replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED, 1416 WifiP2pManager.P2P_UNSUPPORTED); 1417 break; 1418 case WifiP2pManager.REMOVE_LOCAL_SERVICE: 1419 replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED, 1420 WifiP2pManager.P2P_UNSUPPORTED); 1421 break; 1422 case WifiP2pManager.CLEAR_LOCAL_SERVICES: 1423 replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED, 1424 WifiP2pManager.P2P_UNSUPPORTED); 1425 break; 1426 case WifiP2pManager.ADD_SERVICE_REQUEST: 1427 replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED, 1428 WifiP2pManager.P2P_UNSUPPORTED); 1429 break; 1430 case WifiP2pManager.REMOVE_SERVICE_REQUEST: 1431 replyToMessage(message, 1432 WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED, 1433 WifiP2pManager.P2P_UNSUPPORTED); 1434 break; 1435 case WifiP2pManager.CLEAR_SERVICE_REQUESTS: 1436 replyToMessage(message, 1437 WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED, 1438 WifiP2pManager.P2P_UNSUPPORTED); 1439 break; 1440 case WifiP2pManager.SET_DEVICE_NAME: 1441 replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, 1442 WifiP2pManager.P2P_UNSUPPORTED); 1443 break; 1444 case WifiP2pManager.DELETE_PERSISTENT_GROUP: 1445 replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, 1446 WifiP2pManager.P2P_UNSUPPORTED); 1447 break; 1448 case WifiP2pManager.SET_WFD_INFO: 1449 if (!getWfdPermission(message.sendingUid)) { 1450 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 1451 WifiP2pManager.ERROR); 1452 } else { 1453 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 1454 WifiP2pManager.P2P_UNSUPPORTED); 1455 } 1456 break; 1457 case WifiP2pManager.START_WPS: 1458 replyToMessage(message, WifiP2pManager.START_WPS_FAILED, 1459 WifiP2pManager.P2P_UNSUPPORTED); 1460 break; 1461 case WifiP2pManager.START_LISTEN: 1462 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED, 1463 WifiP2pManager.P2P_UNSUPPORTED); 1464 break; 1465 case WifiP2pManager.STOP_LISTEN: 1466 replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED, 1467 WifiP2pManager.P2P_UNSUPPORTED); 1468 break; 1469 case WifiP2pManager.FACTORY_RESET: 1470 replyToMessage(message, WifiP2pManager.FACTORY_RESET_FAILED, 1471 WifiP2pManager.P2P_UNSUPPORTED); 1472 break; 1473 1474 default: 1475 return NOT_HANDLED; 1476 } 1477 return HANDLED; 1478 } 1479 } 1480 1481 class P2pDisablingState extends State { 1482 @Override enter()1483 public void enter() { 1484 if (mVerboseLoggingEnabled) logd(getName()); 1485 sendMessageDelayed(obtainMessage(DISABLE_P2P_TIMED_OUT, 1486 ++sDisableP2pTimeoutIndex, 0), DISABLE_P2P_WAIT_TIME_MS); 1487 } 1488 1489 @Override processMessage(Message message)1490 public boolean processMessage(Message message) { 1491 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 1492 switch (message.what) { 1493 case WifiP2pMonitor.SUP_DISCONNECTION_EVENT: 1494 if (mVerboseLoggingEnabled) logd("p2p socket connection lost"); 1495 transitionTo(mP2pDisabledState); 1496 break; 1497 case ENABLE_P2P: 1498 case DISABLE_P2P: 1499 case REMOVE_CLIENT_INFO: 1500 deferMessage(message); 1501 break; 1502 case DISABLE_P2P_TIMED_OUT: 1503 if (sDisableP2pTimeoutIndex == message.arg1) { 1504 loge("P2p disable timed out"); 1505 transitionTo(mP2pDisabledState); 1506 } 1507 break; 1508 default: 1509 return NOT_HANDLED; 1510 } 1511 return HANDLED; 1512 } 1513 } 1514 1515 class P2pDisabledState extends State { 1516 @Override enter()1517 public void enter() { 1518 if (mVerboseLoggingEnabled) logd(getName()); 1519 mInterfaceName = null; // reset iface name on disable. 1520 } 1521 setupInterfaceFeatures(String interfaceName)1522 private void setupInterfaceFeatures(String interfaceName) { 1523 if (mContext.getResources().getBoolean( 1524 R.bool.config_wifi_p2p_mac_randomization_supported)) { 1525 Log.i(TAG, "Supported feature: P2P MAC randomization"); 1526 mWifiNative.setMacRandomization(true); 1527 } else { 1528 mWifiNative.setMacRandomization(false); 1529 } 1530 } 1531 setupInterface()1532 private boolean setupInterface() { 1533 if (!mIsWifiEnabled) { 1534 Log.e(TAG, "Ignore P2P enable since wifi is " + mIsWifiEnabled); 1535 return false; 1536 } 1537 WorkSource requestorWs = createMergedRequestorWs(); 1538 mInterfaceName = mWifiNative.setupInterface((String ifaceName) -> { 1539 sendMessage(DISABLE_P2P); 1540 checkAndSendP2pStateChangedBroadcast(); 1541 }, getHandler(), requestorWs); 1542 if (mInterfaceName == null) { 1543 Log.e(TAG, "Failed to setup interface for P2P"); 1544 return false; 1545 } 1546 setupInterfaceFeatures(mInterfaceName); 1547 try { 1548 mNetdWrapper.setInterfaceUp(mInterfaceName); 1549 } catch (IllegalStateException ie) { 1550 loge("Unable to change interface settings: " + ie); 1551 } 1552 registerForWifiMonitorEvents(); 1553 return true; 1554 } 1555 1556 @Override processMessage(Message message)1557 public boolean processMessage(Message message) { 1558 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 1559 switch (message.what) { 1560 case ENABLE_P2P: 1561 if (setupInterface()) { 1562 transitionTo(mInactiveState); 1563 } 1564 break; 1565 case REMOVE_CLIENT_INFO: 1566 if (!(message.obj instanceof IBinder)) { 1567 loge("Invalid obj when REMOVE_CLIENT_INFO"); 1568 break; 1569 } 1570 IBinder b = (IBinder) message.obj; 1571 // client service info is clear before enter disable p2p, 1572 // just need to remove it from list 1573 Messenger m = mClientChannelList.remove(b); 1574 ClientInfo clientInfo = mClientInfoList.remove(m); 1575 if (clientInfo != null) { 1576 logd("Remove client - " + clientInfo.mPackageName); 1577 } 1578 break; 1579 default: 1580 // only handle commands from clients and only commands 1581 // which require P2P to be active. 1582 if (message.what < Protocol.BASE_WIFI_P2P_MANAGER 1583 || Protocol.BASE_WIFI_P2P_SERVICE <= message.what 1584 || message.what == WifiP2pManager.UPDATE_CHANNEL_INFO) { 1585 return NOT_HANDLED; 1586 } 1587 // If P2P is not ready, it might be disabled due 1588 // to another interface, ex. turn on softap from 1589 // the quicksettings. 1590 // As the new priority scheme, the foreground app 1591 // might be able to use P2P, so just try to enable 1592 // it. 1593 // Check & re-enable P2P if needed. 1594 // P2P interface will be created if all of the below are true: 1595 // a) Wifi is enabled. 1596 // b) There is at least 1 client app which invoked initialize(). 1597 if (mVerboseLoggingEnabled) { 1598 Log.d(TAG, "Wifi enabled=" + mIsWifiEnabled + ", Number of clients=" 1599 + mDeathDataByBinder.size()); 1600 } 1601 if (!mIsWifiEnabled) return NOT_HANDLED; 1602 if (mDeathDataByBinder.isEmpty()) return NOT_HANDLED; 1603 if (!setupInterface()) return NOT_HANDLED; 1604 deferMessage(message); 1605 transitionTo(mInactiveState); 1606 break; 1607 } 1608 return HANDLED; 1609 } 1610 } 1611 1612 class P2pEnabledState extends State { 1613 @Override enter()1614 public void enter() { 1615 if (mVerboseLoggingEnabled) logd(getName()); 1616 1617 if (isPendingFactoryReset()) { 1618 factoryReset(Process.SYSTEM_UID); 1619 } 1620 1621 checkCoexUnsafeChannels(); 1622 1623 sendP2pConnectionChangedBroadcast(); 1624 initializeP2pSettings(); 1625 } 1626 1627 @Override processMessage(Message message)1628 public boolean processMessage(Message message) { 1629 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 1630 switch (message.what) { 1631 case WifiP2pMonitor.SUP_DISCONNECTION_EVENT: 1632 loge("Unexpected loss of p2p socket connection"); 1633 transitionTo(mP2pDisabledState); 1634 break; 1635 case ENABLE_P2P: 1636 if (!mWifiNative.replaceRequestorWs(createMergedRequestorWs())) { 1637 Log.e(TAG, "Failed to replace requestorWs"); 1638 } 1639 break; 1640 case DISABLE_P2P: 1641 if (mPeers.clear()) { 1642 sendPeersChangedBroadcast(); 1643 } 1644 if (mGroups.clear()) sendP2pPersistentGroupsChangedBroadcast(); 1645 // clear services list for all clients since interface will teardown soon. 1646 clearServicesForAllClients(); 1647 mWifiMonitor.stopMonitoring(mInterfaceName); 1648 mWifiNative.teardownInterface(); 1649 transitionTo(mP2pDisablingState); 1650 break; 1651 case REMOVE_CLIENT_INFO: 1652 if (!(message.obj instanceof IBinder)) { 1653 break; 1654 } 1655 IBinder b = (IBinder) message.obj; 1656 // clear client info and remove it from list 1657 clearClientInfo(mClientChannelList.get(b)); 1658 mClientChannelList.remove(b); 1659 if (!mWifiNative.replaceRequestorWs(createMergedRequestorWs())) { 1660 Log.e(TAG, "Failed to replace requestorWs"); 1661 } 1662 break; 1663 case WifiP2pManager.SET_DEVICE_NAME: 1664 { 1665 if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( 1666 message.sendingUid)) { 1667 loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," 1668 + " or OVERRIDE_WIFI_CONFIG permission, uid = " 1669 + message.sendingUid); 1670 replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, 1671 WifiP2pManager.ERROR); 1672 break; 1673 } 1674 WifiP2pDevice d = (WifiP2pDevice) message.obj; 1675 if (d != null && setAndPersistDeviceName(d.deviceName)) { 1676 if (mVerboseLoggingEnabled) logd("set device name " + d.deviceName); 1677 replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_SUCCEEDED); 1678 } else { 1679 replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, 1680 WifiP2pManager.ERROR); 1681 } 1682 break; 1683 } 1684 case WifiP2pManager.SET_WFD_INFO: 1685 { 1686 WifiP2pWfdInfo d = (WifiP2pWfdInfo) message.obj; 1687 if (!getWfdPermission(message.sendingUid)) { 1688 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 1689 WifiP2pManager.ERROR); 1690 } else if (d != null && setWfdInfo(d)) { 1691 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_SUCCEEDED); 1692 } else { 1693 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 1694 WifiP2pManager.ERROR); 1695 } 1696 break; 1697 } 1698 case BLOCK_DISCOVERY: 1699 boolean blocked = (message.arg1 == ENABLED ? true : false); 1700 if (mDiscoveryBlocked == blocked) break; 1701 mDiscoveryBlocked = blocked; 1702 if (blocked && mDiscoveryStarted) { 1703 mWifiNative.p2pStopFind(); 1704 mDiscoveryPostponed = true; 1705 } 1706 if (!blocked && mDiscoveryPostponed) { 1707 mDiscoveryPostponed = false; 1708 if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) { 1709 sendP2pDiscoveryChangedBroadcast(true); 1710 } 1711 } 1712 if (blocked && mWifiChannel != null) { 1713 mWifiChannel.replyToMessage(message, message.arg2); 1714 } 1715 break; 1716 case WifiP2pManager.DISCOVER_PEERS: 1717 if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( 1718 getCallingPkgName(message.sendingUid, message.replyTo), 1719 getCallingFeatureId(message.sendingUid, message.replyTo), 1720 message.sendingUid, true)) { 1721 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 1722 WifiP2pManager.ERROR); 1723 // remain at this state. 1724 break; 1725 } 1726 if (mDiscoveryBlocked) { 1727 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 1728 WifiP2pManager.BUSY); 1729 break; 1730 } 1731 // do not send service discovery request while normal find operation. 1732 clearSupplicantServiceRequest(); 1733 if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) { 1734 mWifiP2pMetrics.incrementPeerScans(); 1735 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED); 1736 sendP2pDiscoveryChangedBroadcast(true); 1737 } else { 1738 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 1739 WifiP2pManager.ERROR); 1740 } 1741 break; 1742 case WifiP2pMonitor.P2P_FIND_STOPPED_EVENT: 1743 sendP2pDiscoveryChangedBroadcast(false); 1744 break; 1745 case WifiP2pManager.STOP_DISCOVERY: 1746 if (mWifiNative.p2pStopFind()) { 1747 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED); 1748 } else { 1749 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, 1750 WifiP2pManager.ERROR); 1751 } 1752 break; 1753 case WifiP2pManager.DISCOVER_SERVICES: 1754 if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( 1755 getCallingPkgName(message.sendingUid, message.replyTo), 1756 getCallingFeatureId(message.sendingUid, message.replyTo), 1757 message.sendingUid, true)) { 1758 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 1759 WifiP2pManager.ERROR); 1760 // remain at this state. 1761 break; 1762 } 1763 if (mDiscoveryBlocked) { 1764 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 1765 WifiP2pManager.BUSY); 1766 break; 1767 } 1768 if (mVerboseLoggingEnabled) logd(getName() + " discover services"); 1769 if (!updateSupplicantServiceRequest()) { 1770 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 1771 WifiP2pManager.NO_SERVICE_REQUESTS); 1772 break; 1773 } 1774 if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) { 1775 sendP2pDiscoveryChangedBroadcast(true); 1776 mWifiP2pMetrics.incrementServiceScans(); 1777 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_SUCCEEDED); 1778 } else { 1779 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 1780 WifiP2pManager.ERROR); 1781 } 1782 break; 1783 case WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT: 1784 if (message.obj == null) { 1785 Log.e(TAG, "Illegal argument(s)"); 1786 break; 1787 } 1788 WifiP2pDevice device = (WifiP2pDevice) message.obj; 1789 if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break; 1790 mPeers.updateSupplicantDetails(device); 1791 sendPeersChangedBroadcast(); 1792 break; 1793 case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: 1794 if (message.obj == null) { 1795 Log.e(TAG, "Illegal argument(s)"); 1796 break; 1797 } 1798 device = (WifiP2pDevice) message.obj; 1799 // Gets current details for the one removed 1800 device = mPeers.remove(device.deviceAddress); 1801 if (device != null) { 1802 sendPeersChangedBroadcast(); 1803 } 1804 break; 1805 case WifiP2pManager.ADD_LOCAL_SERVICE: 1806 if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( 1807 getCallingPkgName(message.sendingUid, message.replyTo), 1808 getCallingFeatureId(message.sendingUid, message.replyTo), 1809 message.sendingUid, false)) { 1810 replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED); 1811 // remain at this state. 1812 break; 1813 } 1814 if (mVerboseLoggingEnabled) logd(getName() + " add service"); 1815 WifiP2pServiceInfo servInfo = (WifiP2pServiceInfo) message.obj; 1816 if (addLocalService(message.replyTo, servInfo)) { 1817 replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_SUCCEEDED); 1818 } else { 1819 replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED); 1820 } 1821 break; 1822 case WifiP2pManager.REMOVE_LOCAL_SERVICE: 1823 if (mVerboseLoggingEnabled) logd(getName() + " remove service"); 1824 servInfo = (WifiP2pServiceInfo) message.obj; 1825 removeLocalService(message.replyTo, servInfo); 1826 replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_SUCCEEDED); 1827 break; 1828 case WifiP2pManager.CLEAR_LOCAL_SERVICES: 1829 if (mVerboseLoggingEnabled) logd(getName() + " clear service"); 1830 clearLocalServices(message.replyTo); 1831 replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_SUCCEEDED); 1832 break; 1833 case WifiP2pManager.ADD_SERVICE_REQUEST: 1834 if (mVerboseLoggingEnabled) logd(getName() + " add service request"); 1835 if (!addServiceRequest(message.replyTo, 1836 (WifiP2pServiceRequest) message.obj)) { 1837 replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED); 1838 break; 1839 } 1840 replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_SUCCEEDED); 1841 break; 1842 case WifiP2pManager.REMOVE_SERVICE_REQUEST: 1843 if (mVerboseLoggingEnabled) logd(getName() + " remove service request"); 1844 removeServiceRequest(message.replyTo, (WifiP2pServiceRequest) message.obj); 1845 replyToMessage(message, WifiP2pManager.REMOVE_SERVICE_REQUEST_SUCCEEDED); 1846 break; 1847 case WifiP2pManager.CLEAR_SERVICE_REQUESTS: 1848 if (mVerboseLoggingEnabled) logd(getName() + " clear service request"); 1849 clearServiceRequests(message.replyTo); 1850 replyToMessage(message, WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED); 1851 break; 1852 case WifiP2pMonitor.P2P_SERV_DISC_RESP_EVENT: 1853 if (mVerboseLoggingEnabled) logd(getName() + " receive service response"); 1854 if (message.obj == null) { 1855 Log.e(TAG, "Illegal argument(s)"); 1856 break; 1857 } 1858 List<WifiP2pServiceResponse> sdRespList = 1859 (List<WifiP2pServiceResponse>) message.obj; 1860 for (WifiP2pServiceResponse resp : sdRespList) { 1861 WifiP2pDevice dev = 1862 mPeers.get(resp.getSrcDevice().deviceAddress); 1863 resp.setSrcDevice(dev); 1864 sendServiceResponse(resp); 1865 } 1866 break; 1867 case WifiP2pManager.DELETE_PERSISTENT_GROUP: 1868 if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( 1869 message.sendingUid)) { 1870 loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," 1871 + " or OVERRIDE_WIFI_CONFIG permission, uid = " 1872 + message.sendingUid); 1873 replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, 1874 WifiP2pManager.ERROR); 1875 break; 1876 } 1877 if (mVerboseLoggingEnabled) logd(getName() + " delete persistent group"); 1878 mGroups.remove(message.arg1); 1879 mWifiP2pMetrics.updatePersistentGroup(mGroups); 1880 replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_SUCCEEDED); 1881 break; 1882 case SET_MIRACAST_MODE: 1883 mWifiNative.setMiracastMode(message.arg1); 1884 break; 1885 case WifiP2pManager.START_LISTEN: 1886 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission( 1887 message.sendingUid)) { 1888 loge("Permission violation - no NETWORK_SETTING permission," 1889 + " uid = " + message.sendingUid); 1890 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); 1891 break; 1892 } 1893 if (mVerboseLoggingEnabled) logd(getName() + " start listen mode"); 1894 mWifiNative.p2pFlush(); 1895 if (mWifiNative.p2pExtListen(true, 500, 500)) { 1896 replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED); 1897 } else { 1898 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); 1899 } 1900 break; 1901 case WifiP2pManager.STOP_LISTEN: 1902 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission( 1903 message.sendingUid)) { 1904 loge("Permission violation - no NETWORK_SETTING permission," 1905 + " uid = " + message.sendingUid); 1906 replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); 1907 break; 1908 } 1909 if (mVerboseLoggingEnabled) logd(getName() + " stop listen mode"); 1910 if (mWifiNative.p2pExtListen(false, 0, 0)) { 1911 replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); 1912 } else { 1913 replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); 1914 } 1915 mWifiNative.p2pFlush(); 1916 break; 1917 case WifiP2pManager.SET_CHANNEL: 1918 if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( 1919 message.sendingUid)) { 1920 loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," 1921 + " or OVERRIDE_WIFI_CONFIG permission, uid = " 1922 + message.sendingUid); 1923 replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED, 1924 WifiP2pManager.ERROR); 1925 break; 1926 } 1927 if (message.obj == null) { 1928 Log.e(TAG, "Illegal arguments(s)"); 1929 break; 1930 } 1931 Bundle p2pChannels = (Bundle) message.obj; 1932 mUserListenChannel = p2pChannels.getInt("lc", 0); 1933 mUserOperatingChannel = p2pChannels.getInt("oc", 0); 1934 if (updateP2pChannels()) { 1935 replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED); 1936 } else { 1937 replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED); 1938 } 1939 break; 1940 case WifiP2pManager.GET_HANDOVER_REQUEST: 1941 Bundle requestBundle = new Bundle(); 1942 requestBundle.putString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE, 1943 mWifiNative.getNfcHandoverRequest()); 1944 replyToMessage(message, WifiP2pManager.RESPONSE_GET_HANDOVER_MESSAGE, 1945 requestBundle); 1946 break; 1947 case WifiP2pManager.GET_HANDOVER_SELECT: 1948 Bundle selectBundle = new Bundle(); 1949 selectBundle.putString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE, 1950 mWifiNative.getNfcHandoverSelect()); 1951 replyToMessage(message, WifiP2pManager.RESPONSE_GET_HANDOVER_MESSAGE, 1952 selectBundle); 1953 break; 1954 case UPDATE_P2P_DISALLOWED_CHANNELS: 1955 mCoexUnsafeChannels.clear(); 1956 if (null != message.obj) { 1957 mCoexUnsafeChannels.addAll((List<CoexUnsafeChannel>) message.obj); 1958 } 1959 updateP2pChannels(); 1960 break; 1961 default: 1962 return NOT_HANDLED; 1963 } 1964 return HANDLED; 1965 } 1966 1967 @Override exit()1968 public void exit() { 1969 sendP2pDiscoveryChangedBroadcast(false); 1970 mUserListenChannel = 0; 1971 mUserOperatingChannel = 0; 1972 mCoexUnsafeChannels.clear(); 1973 } 1974 } 1975 1976 class InactiveState extends State { 1977 @Override enter()1978 public void enter() { 1979 if (mVerboseLoggingEnabled) logd(getName()); 1980 mSavedPeerConfig.invalidate(); 1981 mDetailedState = NetworkInfo.DetailedState.IDLE; 1982 scheduleIdleShutdown(); 1983 } 1984 1985 @Override exit()1986 public void exit() { 1987 cancelIdleShutdown(); 1988 } 1989 1990 @Override processMessage(Message message)1991 public boolean processMessage(Message message) { 1992 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 1993 // Re-schedule the shutdown timer since we got the new operation. 1994 // only handle commands from clients. 1995 if (message.what > Protocol.BASE_WIFI_P2P_MANAGER 1996 && message.what < Protocol.BASE_WIFI_P2P_SERVICE) { 1997 scheduleIdleShutdown(); 1998 } 1999 switch (message.what) { 2000 case WifiP2pManager.CONNECT: 2001 if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( 2002 getCallingPkgName(message.sendingUid, message.replyTo), 2003 getCallingFeatureId(message.sendingUid, message.replyTo), 2004 message.sendingUid, false)) { 2005 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 2006 // remain at this state. 2007 break; 2008 } 2009 if (mVerboseLoggingEnabled) logd(getName() + " sending connect"); 2010 WifiP2pConfig config = (WifiP2pConfig) message.obj; 2011 2012 boolean isConnectFailed = false; 2013 if (isConfigValidAsGroup(config)) { 2014 mAutonomousGroup = false; 2015 mWifiNative.p2pStopFind(); 2016 if (mWifiNative.p2pGroupAdd(config, true)) { 2017 mWifiP2pMetrics.startConnectionEvent( 2018 P2pConnectionEvent.CONNECTION_FAST, 2019 config); 2020 transitionTo(mGroupNegotiationState); 2021 } else { 2022 loge("Cannot join a group with config."); 2023 isConnectFailed = true; 2024 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 2025 } 2026 } else { 2027 if (isConfigInvalid(config)) { 2028 loge("Dropping connect request " + config); 2029 isConnectFailed = true; 2030 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 2031 } else { 2032 mAutonomousGroup = false; 2033 mWifiNative.p2pStopFind(); 2034 if (reinvokePersistentGroup(config, false)) { 2035 mWifiP2pMetrics.startConnectionEvent( 2036 P2pConnectionEvent.CONNECTION_REINVOKE, 2037 config); 2038 transitionTo(mGroupNegotiationState); 2039 } else { 2040 mWifiP2pMetrics.startConnectionEvent( 2041 P2pConnectionEvent.CONNECTION_FRESH, 2042 config); 2043 transitionTo(mProvisionDiscoveryState); 2044 } 2045 } 2046 } 2047 2048 if (!isConnectFailed) { 2049 mSavedPeerConfig = config; 2050 mPeers.updateStatus(mSavedPeerConfig.deviceAddress, 2051 WifiP2pDevice.INVITED); 2052 sendPeersChangedBroadcast(); 2053 replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); 2054 } 2055 break; 2056 case WifiP2pManager.STOP_DISCOVERY: 2057 if (mWifiNative.p2pStopFind()) { 2058 // When discovery stops in inactive state, flush to clear 2059 // state peer data 2060 mWifiNative.p2pFlush(); 2061 mServiceDiscReqId = null; 2062 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED); 2063 } else { 2064 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, 2065 WifiP2pManager.ERROR); 2066 } 2067 break; 2068 case CMD_P2P_IDLE_SHUTDOWN: 2069 Log.d(TAG, "IdleShutDown message received"); 2070 sendMessage(DISABLE_P2P); 2071 break; 2072 case WifiP2pMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT: 2073 config = (WifiP2pConfig) message.obj; 2074 if (isConfigInvalid(config)) { 2075 loge("Dropping GO neg request " + config); 2076 break; 2077 } 2078 mSavedPeerConfig = config; 2079 mAutonomousGroup = false; 2080 mJoinExistingGroup = false; 2081 mWifiP2pMetrics.startConnectionEvent( 2082 P2pConnectionEvent.CONNECTION_FRESH, 2083 config); 2084 transitionTo(mUserAuthorizingNegotiationRequestState); 2085 break; 2086 case WifiP2pMonitor.P2P_INVITATION_RECEIVED_EVENT: 2087 if (message.obj == null) { 2088 Log.e(TAG, "Invalid argument(s)"); 2089 break; 2090 } 2091 WifiP2pGroup group = (WifiP2pGroup) message.obj; 2092 WifiP2pDevice owner = group.getOwner(); 2093 if (owner == null) { 2094 int id = group.getNetworkId(); 2095 if (id < 0) { 2096 loge("Ignored invitation from null owner"); 2097 break; 2098 } 2099 2100 String addr = mGroups.getOwnerAddr(id); 2101 if (addr != null) { 2102 group.setOwner(new WifiP2pDevice(addr)); 2103 owner = group.getOwner(); 2104 } else { 2105 loge("Ignored invitation from null owner"); 2106 break; 2107 } 2108 } 2109 config = new WifiP2pConfig(); 2110 config.deviceAddress = group.getOwner().deviceAddress; 2111 if (isConfigInvalid(config)) { 2112 loge("Dropping invitation request " + config); 2113 break; 2114 } 2115 mSavedPeerConfig = config; 2116 2117 // Check if we have the owner in peer list and use appropriate 2118 // wps method. Default is to use PBC. 2119 if (owner != null && ((owner = mPeers.get(owner.deviceAddress)) != null)) { 2120 if (owner.wpsPbcSupported()) { 2121 mSavedPeerConfig.wps.setup = WpsInfo.PBC; 2122 } else if (owner.wpsKeypadSupported()) { 2123 mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; 2124 } else if (owner.wpsDisplaySupported()) { 2125 mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; 2126 } 2127 } 2128 2129 mAutonomousGroup = false; 2130 mJoinExistingGroup = true; 2131 mWifiP2pMetrics.startConnectionEvent( 2132 P2pConnectionEvent.CONNECTION_FRESH, 2133 config); 2134 transitionTo(mUserAuthorizingInviteRequestState); 2135 break; 2136 case WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: 2137 case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: 2138 // We let the supplicant handle the provision discovery response 2139 // and wait instead for the GO_NEGOTIATION_REQUEST_EVENT. 2140 // Handling provision discovery and issuing a p2p_connect before 2141 // group negotiation comes through causes issues 2142 break; 2143 case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: 2144 if (message.obj == null) { 2145 Log.e(TAG, "Illegal argument(s)"); 2146 break; 2147 } 2148 WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj; 2149 WifiP2pDevice device = provDisc.device; 2150 if (device == null) { 2151 loge("Device entry is null"); 2152 break; 2153 } 2154 mSavedPeerConfig = new WifiP2pConfig(); 2155 mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; 2156 mSavedPeerConfig.deviceAddress = device.deviceAddress; 2157 mSavedPeerConfig.wps.pin = provDisc.pin; 2158 2159 notifyP2pProvDiscShowPinRequest(provDisc.pin, device.deviceAddress); 2160 mPeers.updateStatus(device.deviceAddress, WifiP2pDevice.INVITED); 2161 sendPeersChangedBroadcast(); 2162 transitionTo(mUserAuthorizingNegotiationRequestState); 2163 break; 2164 case WifiP2pManager.CREATE_GROUP: 2165 if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( 2166 getCallingPkgName(message.sendingUid, message.replyTo), 2167 getCallingFeatureId(message.sendingUid, message.replyTo), 2168 message.sendingUid, false)) { 2169 replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, 2170 WifiP2pManager.ERROR); 2171 // remain at this state. 2172 break; 2173 } 2174 mAutonomousGroup = true; 2175 int netId = message.arg1; 2176 config = (WifiP2pConfig) message.obj; 2177 boolean ret = false; 2178 if (config != null) { 2179 if (isConfigValidAsGroup(config)) { 2180 mWifiP2pMetrics.startConnectionEvent( 2181 P2pConnectionEvent.CONNECTION_FAST, 2182 config); 2183 ret = mWifiNative.p2pGroupAdd(config, false); 2184 } else { 2185 ret = false; 2186 } 2187 } else if (netId == WifiP2pGroup.NETWORK_ID_PERSISTENT) { 2188 // check if the go persistent group is present. 2189 netId = mGroups.getNetworkId(mThisDevice.deviceAddress); 2190 if (netId != -1) { 2191 mWifiP2pMetrics.startConnectionEvent( 2192 P2pConnectionEvent.CONNECTION_REINVOKE, 2193 null); 2194 ret = mWifiNative.p2pGroupAdd(netId); 2195 } else { 2196 mWifiP2pMetrics.startConnectionEvent( 2197 P2pConnectionEvent.CONNECTION_LOCAL, 2198 null); 2199 ret = mWifiNative.p2pGroupAdd(true); 2200 } 2201 } else { 2202 mWifiP2pMetrics.startConnectionEvent( 2203 P2pConnectionEvent.CONNECTION_LOCAL, 2204 null); 2205 ret = mWifiNative.p2pGroupAdd(false); 2206 } 2207 2208 if (ret) { 2209 replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED); 2210 transitionTo(mGroupNegotiationState); 2211 } else { 2212 replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, 2213 WifiP2pManager.ERROR); 2214 // remain at this state. 2215 } 2216 break; 2217 case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: 2218 if (message.obj == null) { 2219 Log.e(TAG, "Invalid argument(s)"); 2220 break; 2221 } 2222 mGroup = (WifiP2pGroup) message.obj; 2223 if (mVerboseLoggingEnabled) logd(getName() + " group started"); 2224 if (mGroup.isGroupOwner() 2225 && EMPTY_DEVICE_ADDRESS.equals(mGroup.getOwner().deviceAddress)) { 2226 // wpa_supplicant doesn't set own device address to go_dev_addr. 2227 mGroup.getOwner().deviceAddress = mThisDevice.deviceAddress; 2228 } 2229 // We hit this scenario when a persistent group is reinvoked 2230 if (mGroup.getNetworkId() == WifiP2pGroup.NETWORK_ID_PERSISTENT) { 2231 mAutonomousGroup = false; 2232 deferMessage(message); 2233 transitionTo(mGroupNegotiationState); 2234 } else { 2235 loge("Unexpected group creation, remove " + mGroup); 2236 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 2237 } 2238 break; 2239 case WifiP2pManager.START_LISTEN: 2240 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission( 2241 message.sendingUid)) { 2242 loge("Permission violation - no NETWORK_SETTING permission," 2243 + " uid = " + message.sendingUid); 2244 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); 2245 break; 2246 } 2247 if (mVerboseLoggingEnabled) logd(getName() + " start listen mode"); 2248 mWifiNative.p2pFlush(); 2249 if (mWifiNative.p2pExtListen(true, 500, 500)) { 2250 replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED); 2251 } else { 2252 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); 2253 } 2254 break; 2255 case WifiP2pManager.STOP_LISTEN: 2256 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission( 2257 message.sendingUid)) { 2258 loge("Permission violation - no NETWORK_SETTING permission," 2259 + " uid = " + message.sendingUid); 2260 replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); 2261 break; 2262 } 2263 if (mVerboseLoggingEnabled) logd(getName() + " stop listen mode"); 2264 if (mWifiNative.p2pExtListen(false, 0, 0)) { 2265 replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); 2266 } else { 2267 replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); 2268 } 2269 mWifiNative.p2pFlush(); 2270 break; 2271 case WifiP2pManager.SET_CHANNEL: 2272 if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( 2273 message.sendingUid)) { 2274 loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," 2275 + " or OVERRIDE_WIFI_CONFIG permission, uid = " 2276 + message.sendingUid); 2277 replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED, 2278 WifiP2pManager.ERROR); 2279 break; 2280 } 2281 if (message.obj == null) { 2282 Log.e(TAG, "Illegal arguments(s)"); 2283 break; 2284 } 2285 Bundle p2pChannels = (Bundle) message.obj; 2286 mUserListenChannel = p2pChannels.getInt("lc", 0); 2287 mUserOperatingChannel = p2pChannels.getInt("oc", 0); 2288 if (updateP2pChannels()) { 2289 replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED); 2290 } else { 2291 replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED); 2292 } 2293 break; 2294 case WifiP2pManager.INITIATOR_REPORT_NFC_HANDOVER: 2295 String handoverSelect = null; 2296 2297 if (message.obj != null) { 2298 handoverSelect = ((Bundle) message.obj) 2299 .getString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE); 2300 } 2301 2302 if (handoverSelect != null 2303 && mWifiNative.initiatorReportNfcHandover(handoverSelect)) { 2304 replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_SUCCEEDED); 2305 transitionTo(mGroupCreatingState); 2306 } else { 2307 replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED); 2308 } 2309 break; 2310 case WifiP2pManager.RESPONDER_REPORT_NFC_HANDOVER: 2311 String handoverRequest = null; 2312 2313 if (message.obj != null) { 2314 handoverRequest = ((Bundle) message.obj) 2315 .getString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE); 2316 } 2317 2318 if (handoverRequest != null 2319 && mWifiNative.responderReportNfcHandover(handoverRequest)) { 2320 replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_SUCCEEDED); 2321 transitionTo(mGroupCreatingState); 2322 } else { 2323 replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED); 2324 } 2325 break; 2326 default: 2327 return NOT_HANDLED; 2328 } 2329 return HANDLED; 2330 } 2331 } 2332 2333 class GroupCreatingState extends State { 2334 @Override enter()2335 public void enter() { 2336 if (mVerboseLoggingEnabled) logd(getName()); 2337 sendMessageDelayed(obtainMessage(GROUP_CREATING_TIMED_OUT, 2338 ++sGroupCreatingTimeoutIndex, 0), GROUP_CREATING_WAIT_TIME_MS); 2339 } 2340 2341 @Override processMessage(Message message)2342 public boolean processMessage(Message message) { 2343 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 2344 boolean ret = HANDLED; 2345 switch (message.what) { 2346 case GROUP_CREATING_TIMED_OUT: 2347 if (sGroupCreatingTimeoutIndex == message.arg1) { 2348 if (mVerboseLoggingEnabled) logd("Group negotiation timed out"); 2349 mWifiP2pMetrics.endConnectionEvent( 2350 P2pConnectionEvent.CLF_TIMEOUT); 2351 handleGroupCreationFailure(); 2352 transitionTo(mInactiveState); 2353 } 2354 break; 2355 case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: 2356 if (message.obj == null) { 2357 Log.e(TAG, "Illegal argument(s)"); 2358 break; 2359 } 2360 WifiP2pDevice device = (WifiP2pDevice) message.obj; 2361 if (!mSavedPeerConfig.deviceAddress.equals(device.deviceAddress)) { 2362 if (mVerboseLoggingEnabled) { 2363 logd("mSavedPeerConfig " + mSavedPeerConfig.deviceAddress 2364 + "device " + device.deviceAddress); 2365 } 2366 // Do the regular device lost handling 2367 ret = NOT_HANDLED; 2368 break; 2369 } 2370 // Do nothing 2371 if (mVerboseLoggingEnabled) logd("Add device to lost list " + device); 2372 mPeersLostDuringConnection.updateSupplicantDetails(device); 2373 break; 2374 case WifiP2pManager.DISCOVER_PEERS: 2375 // Discovery will break negotiation 2376 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 2377 WifiP2pManager.BUSY); 2378 break; 2379 case WifiP2pManager.CANCEL_CONNECT: 2380 // Do a supplicant p2p_cancel which only cancels an ongoing 2381 // group negotiation. This will fail for a pending provision 2382 // discovery or for a pending user action, but at the framework 2383 // level, we always treat cancel as succeeded and enter 2384 // an inactive state 2385 mWifiNative.p2pCancelConnect(); 2386 mWifiP2pMetrics.endConnectionEvent( 2387 P2pConnectionEvent.CLF_CANCEL); 2388 handleGroupCreationFailure(); 2389 transitionTo(mInactiveState); 2390 replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED); 2391 break; 2392 case WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT: 2393 // We hit this scenario when NFC handover is invoked. 2394 mAutonomousGroup = false; 2395 transitionTo(mGroupNegotiationState); 2396 break; 2397 default: 2398 ret = NOT_HANDLED; 2399 } 2400 return ret; 2401 } 2402 } 2403 2404 class UserAuthorizingNegotiationRequestState extends State { 2405 @Override enter()2406 public void enter() { 2407 if (mVerboseLoggingEnabled) logd(getName()); 2408 if (mSavedPeerConfig.wps.setup == WpsInfo.PBC 2409 || TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) { 2410 notifyInvitationReceived(); 2411 } 2412 } 2413 2414 @Override processMessage(Message message)2415 public boolean processMessage(Message message) { 2416 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 2417 boolean ret = HANDLED; 2418 switch (message.what) { 2419 case PEER_CONNECTION_USER_ACCEPT: 2420 mWifiNative.p2pStopFind(); 2421 p2pConnectWithPinDisplay(mSavedPeerConfig, 2422 P2P_CONNECT_TRIGGER_GROUP_NEG_REQ); 2423 mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED); 2424 sendPeersChangedBroadcast(); 2425 transitionTo(mGroupNegotiationState); 2426 break; 2427 case PEER_CONNECTION_USER_REJECT: 2428 if (mVerboseLoggingEnabled) { 2429 logd("User rejected negotiation " + mSavedPeerConfig); 2430 } 2431 transitionTo(mInactiveState); 2432 break; 2433 case PEER_CONNECTION_USER_CONFIRM: 2434 mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; 2435 mSavedPeerConfig.groupOwnerIntent = 2436 selectGroupOwnerIntentIfNecessary(mSavedPeerConfig); 2437 mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP); 2438 transitionTo(mGroupNegotiationState); 2439 break; 2440 default: 2441 return NOT_HANDLED; 2442 } 2443 return ret; 2444 } 2445 2446 @Override exit()2447 public void exit() { 2448 // TODO: dismiss dialog if not already done 2449 } 2450 } 2451 2452 class UserAuthorizingInviteRequestState extends State { 2453 @Override enter()2454 public void enter() { 2455 if (mVerboseLoggingEnabled) logd(getName()); 2456 notifyInvitationReceived(); 2457 } 2458 2459 @Override processMessage(Message message)2460 public boolean processMessage(Message message) { 2461 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 2462 boolean ret = HANDLED; 2463 switch (message.what) { 2464 case PEER_CONNECTION_USER_ACCEPT: 2465 mWifiNative.p2pStopFind(); 2466 if (!reinvokePersistentGroup(mSavedPeerConfig, true)) { 2467 // Do negotiation when persistence fails 2468 p2pConnectWithPinDisplay(mSavedPeerConfig, 2469 P2P_CONNECT_TRIGGER_INVITATION_REQ); 2470 } 2471 mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED); 2472 sendPeersChangedBroadcast(); 2473 transitionTo(mGroupNegotiationState); 2474 break; 2475 case PEER_CONNECTION_USER_REJECT: 2476 if (mVerboseLoggingEnabled) { 2477 logd("User rejected invitation " + mSavedPeerConfig); 2478 } 2479 transitionTo(mInactiveState); 2480 break; 2481 default: 2482 return NOT_HANDLED; 2483 } 2484 return ret; 2485 } 2486 2487 @Override exit()2488 public void exit() { 2489 // TODO: dismiss dialog if not already done 2490 } 2491 } 2492 2493 class ProvisionDiscoveryState extends State { 2494 @Override enter()2495 public void enter() { 2496 if (mVerboseLoggingEnabled) logd(getName()); 2497 mWifiNative.p2pProvisionDiscovery(mSavedPeerConfig); 2498 } 2499 2500 @Override processMessage(Message message)2501 public boolean processMessage(Message message) { 2502 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 2503 WifiP2pProvDiscEvent provDisc = null; 2504 WifiP2pDevice device = null; 2505 switch (message.what) { 2506 case WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT: 2507 if (message.obj == null) { 2508 Log.e(TAG, "Invalid argument(s)"); 2509 break; 2510 } 2511 provDisc = (WifiP2pProvDiscEvent) message.obj; 2512 device = provDisc.device; 2513 if (device != null 2514 && !device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) { 2515 break; 2516 } 2517 if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) { 2518 if (mVerboseLoggingEnabled) logd("Found a match " + mSavedPeerConfig); 2519 p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_OTHER); 2520 transitionTo(mGroupNegotiationState); 2521 } 2522 break; 2523 case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: 2524 if (message.obj == null) { 2525 Log.e(TAG, "Illegal argument(s)"); 2526 break; 2527 } 2528 provDisc = (WifiP2pProvDiscEvent) message.obj; 2529 device = provDisc.device; 2530 if (device != null 2531 && !device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) { 2532 break; 2533 } 2534 if (mSavedPeerConfig.wps.setup == WpsInfo.KEYPAD) { 2535 if (mVerboseLoggingEnabled) logd("Found a match " + mSavedPeerConfig); 2536 // we already have the pin 2537 if (!TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) { 2538 p2pConnectWithPinDisplay(mSavedPeerConfig, 2539 P2P_CONNECT_TRIGGER_OTHER); 2540 transitionTo(mGroupNegotiationState); 2541 } else { 2542 mJoinExistingGroup = false; 2543 transitionTo(mUserAuthorizingNegotiationRequestState); 2544 } 2545 } 2546 break; 2547 case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: 2548 if (message.obj == null) { 2549 Log.e(TAG, "Illegal argument(s)"); 2550 break; 2551 } 2552 provDisc = (WifiP2pProvDiscEvent) message.obj; 2553 device = provDisc.device; 2554 if (device == null) { 2555 Log.e(TAG, "Invalid device"); 2556 break; 2557 } 2558 if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) { 2559 break; 2560 } 2561 if (mSavedPeerConfig.wps.setup == WpsInfo.DISPLAY) { 2562 if (mVerboseLoggingEnabled) logd("Found a match " + mSavedPeerConfig); 2563 mSavedPeerConfig.wps.pin = provDisc.pin; 2564 p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_OTHER); 2565 notifyInvitationSent(provDisc.pin, device.deviceAddress); 2566 transitionTo(mGroupNegotiationState); 2567 } 2568 break; 2569 case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: 2570 loge("provision discovery failed"); 2571 mWifiP2pMetrics.endConnectionEvent( 2572 P2pConnectionEvent.CLF_PROV_DISC_FAIL); 2573 handleGroupCreationFailure(); 2574 transitionTo(mInactiveState); 2575 break; 2576 default: 2577 return NOT_HANDLED; 2578 } 2579 return HANDLED; 2580 } 2581 } 2582 2583 class GroupNegotiationState extends State { 2584 @Override enter()2585 public void enter() { 2586 if (mVerboseLoggingEnabled) logd(getName()); 2587 } 2588 2589 @Override processMessage(Message message)2590 public boolean processMessage(Message message) { 2591 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 2592 switch (message.what) { 2593 // We ignore these right now, since we get a GROUP_STARTED notification 2594 // afterwards 2595 case WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT: 2596 case WifiP2pMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT: 2597 if (mVerboseLoggingEnabled) logd(getName() + " go success"); 2598 break; 2599 case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: 2600 if (message.obj == null) { 2601 Log.e(TAG, "Illegal argument(s)"); 2602 break; 2603 } 2604 mGroup = (WifiP2pGroup) message.obj; 2605 if (mVerboseLoggingEnabled) logd(getName() + " group started"); 2606 if (mGroup.isGroupOwner() 2607 && EMPTY_DEVICE_ADDRESS.equals(mGroup.getOwner().deviceAddress)) { 2608 // wpa_supplicant doesn't set own device address to go_dev_addr. 2609 mGroup.getOwner().deviceAddress = mThisDevice.deviceAddress; 2610 } 2611 if (mGroup.getNetworkId() == WifiP2pGroup.NETWORK_ID_PERSISTENT) { 2612 // update cache information and set network id to mGroup. 2613 updatePersistentNetworks(RELOAD); 2614 String devAddr = mGroup.getOwner().deviceAddress; 2615 mGroup.setNetworkId(mGroups.getNetworkId(devAddr, 2616 mGroup.getNetworkName())); 2617 } 2618 2619 if (mGroup.isGroupOwner()) { 2620 // Setting an idle time out on GO causes issues with certain scenarios 2621 // on clients where it can be off-channel for longer and with the power 2622 // save modes used. 2623 // TODO: Verify multi-channel scenarios and supplicant behavior are 2624 // better before adding a time out in future 2625 // Set group idle timeout of 10 sec, to avoid GO beaconing incase of any 2626 // failure during 4-way Handshake. 2627 if (!mAutonomousGroup) { 2628 mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 2629 GROUP_IDLE_TIME_S); 2630 } 2631 // {@link com.android.server.connectivity.Tethering} listens to 2632 // {@link WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION} 2633 // events and takes over the DHCP server management automatically. 2634 // Because tethering service introduces random IP range, P2P could not 2635 // hard-coded group owner IP and needs to wait for tethering completion. 2636 // As a result, P2P sends a unicast intent to tether service to trigger 2637 // the whole flow before entering GroupCreatedState. 2638 setWifiP2pInfoOnGroupFormation(null); 2639 if (!sendP2pTetherRequestBroadcast()) { 2640 loge("Cannot start tethering, remove " + mGroup); 2641 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 2642 } 2643 break; 2644 } 2645 2646 mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S); 2647 startIpClient(mGroup.getInterface(), getHandler()); 2648 WifiP2pDevice groupOwner = mGroup.getOwner(); 2649 WifiP2pDevice peer = mPeers.get(groupOwner.deviceAddress); 2650 if (peer != null) { 2651 // update group owner details with peer details found at discovery 2652 groupOwner.updateSupplicantDetails(peer); 2653 mPeers.updateStatus(groupOwner.deviceAddress, 2654 WifiP2pDevice.CONNECTED); 2655 sendPeersChangedBroadcast(); 2656 } else { 2657 // A supplicant bug can lead to reporting an invalid 2658 // group owner address (all zeroes) at times. Avoid a 2659 // crash, but continue group creation since it is not 2660 // essential. 2661 logw("Unknown group owner " + groupOwner); 2662 } 2663 transitionTo(mGroupCreatedState); 2664 break; 2665 case GROUP_OWNER_TETHER_READY: 2666 if (mGroup != null && mGroup.isGroupOwner()) { 2667 Log.d(TAG, "tether " + mGroup.getInterface() + " ready"); 2668 transitionTo(mGroupCreatedState); 2669 } 2670 break; 2671 case WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: 2672 P2pStatus status = (P2pStatus) message.obj; 2673 if (status == P2pStatus.NO_COMMON_CHANNEL) { 2674 transitionTo(mFrequencyConflictState); 2675 break; 2676 } 2677 // continue with group removal handling 2678 case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: 2679 if (mVerboseLoggingEnabled) logd(getName() + " go failure"); 2680 mWifiP2pMetrics.endConnectionEvent( 2681 P2pConnectionEvent.CLF_UNKNOWN); 2682 handleGroupCreationFailure(); 2683 transitionTo(mInactiveState); 2684 break; 2685 case WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: 2686 // A group formation failure is always followed by 2687 // a group removed event. Flushing things at group formation 2688 // failure causes supplicant issues. Ignore right now. 2689 status = (P2pStatus) message.obj; 2690 if (status == P2pStatus.NO_COMMON_CHANNEL) { 2691 transitionTo(mFrequencyConflictState); 2692 break; 2693 } 2694 break; 2695 case WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT: 2696 status = (P2pStatus) message.obj; 2697 if (status == P2pStatus.SUCCESS) { 2698 // invocation was succeeded. 2699 // wait P2P_GROUP_STARTED_EVENT. 2700 break; 2701 } 2702 loge("Invitation result " + status); 2703 if (status == P2pStatus.UNKNOWN_P2P_GROUP) { 2704 // target device has already removed the credential. 2705 // So, remove this credential accordingly. 2706 int netId = mSavedPeerConfig.netId; 2707 if (netId >= 0) { 2708 if (mVerboseLoggingEnabled) { 2709 logd("Remove unknown client from the list"); 2710 } 2711 removeClientFromList(netId, mSavedPeerConfig.deviceAddress, true); 2712 } 2713 2714 // Reinvocation has failed, try group negotiation 2715 mSavedPeerConfig.netId = WifiP2pGroup.NETWORK_ID_PERSISTENT; 2716 p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_OTHER); 2717 } else if (status == P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE) { 2718 2719 // Devices setting persistent_reconnect to 0 in wpa_supplicant 2720 // always defer the invocation request and return 2721 // "information is currently unavailable" error. 2722 // So, try another way to connect for interoperability. 2723 mSavedPeerConfig.netId = WifiP2pGroup.NETWORK_ID_PERSISTENT; 2724 p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_OTHER); 2725 } else if (status == P2pStatus.NO_COMMON_CHANNEL) { 2726 transitionTo(mFrequencyConflictState); 2727 } else { 2728 mWifiP2pMetrics.endConnectionEvent( 2729 P2pConnectionEvent.CLF_INVITATION_FAIL); 2730 handleGroupCreationFailure(); 2731 transitionTo(mInactiveState); 2732 } 2733 break; 2734 case WifiP2pMonitor.AP_STA_CONNECTED_EVENT: 2735 case WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT: 2736 // Group owner needs to wait for tethering completion before 2737 // moving to GroupCreatedState. If native layer reports STA event 2738 // earlier, defer it. 2739 if (mGroup != null && mGroup.isGroupOwner()) { 2740 deferMessage(message); 2741 break; 2742 } 2743 default: 2744 return NOT_HANDLED; 2745 } 2746 return HANDLED; 2747 } 2748 } 2749 2750 class FrequencyConflictState extends State { 2751 private AlertDialog mFrequencyConflictDialog; 2752 @Override enter()2753 public void enter() { 2754 if (mVerboseLoggingEnabled) logd(getName()); 2755 notifyFrequencyConflict(); 2756 } 2757 notifyFrequencyConflict()2758 private void notifyFrequencyConflict() { 2759 logd("Notify frequency conflict"); 2760 Resources r = mContext.getResources(); 2761 2762 AlertDialog dialog = mFrameworkFacade.makeAlertDialogBuilder(mContext) 2763 .setMessage(r.getString(R.string.wifi_p2p_frequency_conflict_message, 2764 getDeviceName(mSavedPeerConfig.deviceAddress))) 2765 .setPositiveButton(r.getString(R.string.dlg_ok), new OnClickListener() { 2766 @Override 2767 public void onClick(DialogInterface dialog, int which) { 2768 sendMessage(DROP_WIFI_USER_ACCEPT); 2769 } 2770 }) 2771 .setNegativeButton(r.getString(R.string.decline), new OnClickListener() { 2772 @Override 2773 public void onClick(DialogInterface dialog, int which) { 2774 sendMessage(DROP_WIFI_USER_REJECT); 2775 } 2776 }) 2777 .setOnCancelListener(new DialogInterface.OnCancelListener() { 2778 @Override 2779 public void onCancel(DialogInterface arg0) { 2780 sendMessage(DROP_WIFI_USER_REJECT); 2781 } 2782 }) 2783 .create(); 2784 dialog.setCanceledOnTouchOutside(false); 2785 2786 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 2787 dialog.getWindow().addSystemFlags( 2788 WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); 2789 dialog.show(); 2790 mFrequencyConflictDialog = dialog; 2791 } 2792 2793 @Override processMessage(Message message)2794 public boolean processMessage(Message message) { 2795 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 2796 switch (message.what) { 2797 case WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT: 2798 case WifiP2pMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT: 2799 loge(getName() + "group sucess during freq conflict!"); 2800 break; 2801 case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: 2802 loge(getName() + "group started after freq conflict, handle anyway"); 2803 deferMessage(message); 2804 transitionTo(mGroupNegotiationState); 2805 break; 2806 case WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: 2807 case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: 2808 case WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: 2809 // Ignore failures since we retry again 2810 break; 2811 case DROP_WIFI_USER_REJECT: 2812 // User rejected dropping wifi in favour of p2p 2813 mWifiP2pMetrics.endConnectionEvent( 2814 P2pConnectionEvent.CLF_USER_REJECT); 2815 handleGroupCreationFailure(); 2816 transitionTo(mInactiveState); 2817 break; 2818 case DROP_WIFI_USER_ACCEPT: 2819 // User accepted dropping wifi in favour of p2p 2820 if (mWifiChannel != null) { 2821 mWifiChannel.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST, 1); 2822 } else { 2823 loge("DROP_WIFI_USER_ACCEPT message received when WifiChannel is null"); 2824 } 2825 mTemporarilyDisconnectedWifi = true; 2826 break; 2827 case DISCONNECT_WIFI_RESPONSE: 2828 // Got a response from ClientModeImpl, retry p2p 2829 if (mVerboseLoggingEnabled) { 2830 logd(getName() + "Wifi disconnected, retry p2p"); 2831 } 2832 transitionTo(mInactiveState); 2833 sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig); 2834 break; 2835 default: 2836 return NOT_HANDLED; 2837 } 2838 return HANDLED; 2839 } 2840 exit()2841 public void exit() { 2842 if (mFrequencyConflictDialog != null) mFrequencyConflictDialog.dismiss(); 2843 } 2844 } 2845 2846 class GroupCreatedState extends State { 2847 @Override enter()2848 public void enter() { 2849 if (mVerboseLoggingEnabled) logd(getName()); 2850 // Once connected, peer config details are invalid 2851 mSavedPeerConfig.invalidate(); 2852 mDetailedState = NetworkInfo.DetailedState.CONNECTED; 2853 2854 updateThisDevice(WifiP2pDevice.CONNECTED); 2855 2856 // DHCP server has already been started if I am a group owner 2857 if (mGroup.isGroupOwner()) { 2858 Inet4Address addr = getInterfaceAddress(mGroup.getInterface()); 2859 if (addr != null) { 2860 setWifiP2pInfoOnGroupFormation(addr.getHostAddress()); 2861 Log.d(TAG, "Group owner address: " + addr.getHostAddress() 2862 + " at " + mGroup.getInterface()); 2863 } else { 2864 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 2865 } 2866 } 2867 2868 // In case of a negotiation group, connection changed is sent 2869 // after a client joins. For autonomous, send now 2870 if (mAutonomousGroup) { 2871 sendP2pConnectionChangedBroadcast(); 2872 } 2873 2874 mWifiP2pMetrics.endConnectionEvent( 2875 P2pConnectionEvent.CLF_NONE); 2876 mWifiP2pMetrics.startGroupEvent(mGroup); 2877 } 2878 2879 @Override processMessage(Message message)2880 public boolean processMessage(Message message) { 2881 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 2882 WifiP2pDevice device = null; 2883 String deviceAddress = null; 2884 switch (message.what) { 2885 case WifiP2pMonitor.AP_STA_CONNECTED_EVENT: 2886 if (message.obj == null) { 2887 Log.e(TAG, "Illegal argument(s)"); 2888 break; 2889 } 2890 device = (WifiP2pDevice) message.obj; 2891 deviceAddress = device.deviceAddress; 2892 // Clear timeout that was set when group was started. 2893 mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0); 2894 if (deviceAddress != null) { 2895 if (mPeers.get(deviceAddress) != null) { 2896 mGroup.addClient(mPeers.get(deviceAddress)); 2897 } else { 2898 mGroup.addClient(deviceAddress); 2899 } 2900 mPeers.updateStatus(deviceAddress, WifiP2pDevice.CONNECTED); 2901 if (mVerboseLoggingEnabled) logd(getName() + " ap sta connected"); 2902 sendPeersChangedBroadcast(); 2903 mWifiP2pMetrics.updateGroupEvent(mGroup); 2904 } else { 2905 loge("Connect on null device address, ignore"); 2906 } 2907 sendP2pConnectionChangedBroadcast(); 2908 break; 2909 case WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT: 2910 if (message.obj == null) { 2911 Log.e(TAG, "Illegal argument(s)"); 2912 break; 2913 } 2914 device = (WifiP2pDevice) message.obj; 2915 deviceAddress = device.deviceAddress; 2916 if (deviceAddress != null) { 2917 mPeers.updateStatus(deviceAddress, WifiP2pDevice.AVAILABLE); 2918 if (mGroup.removeClient(deviceAddress)) { 2919 if (mVerboseLoggingEnabled) logd("Removed client " + deviceAddress); 2920 if (!mAutonomousGroup && mGroup.isClientListEmpty()) { 2921 logd("Client list empty, remove non-persistent p2p group"); 2922 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 2923 // We end up sending connection changed broadcast 2924 // when this happens at exit() 2925 } else { 2926 // Notify when a client disconnects from group 2927 sendP2pConnectionChangedBroadcast(); 2928 } 2929 mWifiP2pMetrics.updateGroupEvent(mGroup); 2930 } else { 2931 if (mVerboseLoggingEnabled) { 2932 logd("Failed to remove client " + deviceAddress); 2933 } 2934 for (WifiP2pDevice c : mGroup.getClientList()) { 2935 if (mVerboseLoggingEnabled) logd("client " + c.deviceAddress); 2936 } 2937 } 2938 sendPeersChangedBroadcast(); 2939 if (mVerboseLoggingEnabled) logd(getName() + " ap sta disconnected"); 2940 } else { 2941 loge("Disconnect on unknown device: " + device); 2942 } 2943 break; 2944 case IPC_PRE_DHCP_ACTION: 2945 mWifiNative.setP2pPowerSave(mGroup.getInterface(), false); 2946 try { 2947 mIpClient.completedPreDhcpAction(); 2948 } catch (RemoteException e) { 2949 e.rethrowFromSystemServer(); 2950 } 2951 break; 2952 case IPC_POST_DHCP_ACTION: 2953 mWifiNative.setP2pPowerSave(mGroup.getInterface(), true); 2954 break; 2955 case IPC_DHCP_RESULTS: 2956 mDhcpResultsParcelable = (DhcpResultsParcelable) message.obj; 2957 if (mDhcpResultsParcelable == null) { 2958 break; 2959 } 2960 2961 if (mVerboseLoggingEnabled) { 2962 logd("mDhcpResultsParcelable: " + mDhcpResultsParcelable); 2963 } 2964 setWifiP2pInfoOnGroupFormation(mDhcpResultsParcelable.serverAddress); 2965 try { 2966 final String ifname = mGroup.getInterface(); 2967 if (mDhcpResultsParcelable != null) { 2968 mNetdWrapper.addInterfaceToLocalNetwork( 2969 ifname, 2970 mDhcpResultsParcelable.baseConfiguration.getRoutes(ifname)); 2971 } 2972 } catch (Exception e) { 2973 loge("Failed to add iface to local network " + e); 2974 } 2975 sendP2pConnectionChangedBroadcast(); 2976 break; 2977 case IPC_PROVISIONING_SUCCESS: 2978 break; 2979 case IPC_PROVISIONING_FAILURE: 2980 loge("IP provisioning failed"); 2981 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 2982 break; 2983 case WifiP2pManager.REMOVE_GROUP: 2984 if (mVerboseLoggingEnabled) logd(getName() + " remove group"); 2985 if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) { 2986 transitionTo(mOngoingGroupRemovalState); 2987 replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED); 2988 } else { 2989 handleGroupRemoved(); 2990 transitionTo(mInactiveState); 2991 replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, 2992 WifiP2pManager.ERROR); 2993 } 2994 break; 2995 case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: 2996 // We do not listen to NETWORK_DISCONNECTION_EVENT for group removal 2997 // handling since supplicant actually tries to reconnect after a temporary 2998 // disconnect until group idle time out. Eventually, a group removal event 2999 // will come when group has been removed. 3000 // 3001 // When there are connectivity issues during temporary disconnect, 3002 // the application will also just remove the group. 3003 // 3004 // Treating network disconnection as group removal causes race conditions 3005 // since supplicant would still maintain the group at that stage. 3006 if (mVerboseLoggingEnabled) logd(getName() + " group removed"); 3007 handleGroupRemoved(); 3008 transitionTo(mInactiveState); 3009 break; 3010 case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: 3011 if (message.obj == null) { 3012 Log.e(TAG, "Illegal argument(s)"); 3013 return NOT_HANDLED; 3014 } 3015 device = (WifiP2pDevice) message.obj; 3016 if (!mGroup.contains(device)) { 3017 // do the regular device lost handling 3018 return NOT_HANDLED; 3019 } 3020 // Device loss for a connected device indicates 3021 // it is not in discovery any more 3022 if (mVerboseLoggingEnabled) logd("Add device to lost list " + device); 3023 mPeersLostDuringConnection.updateSupplicantDetails(device); 3024 return HANDLED; 3025 case DISABLE_P2P: 3026 sendMessage(WifiP2pManager.REMOVE_GROUP); 3027 deferMessage(message); 3028 break; 3029 // This allows any client to join the GO during the 3030 // WPS window 3031 case WifiP2pManager.START_WPS: 3032 WpsInfo wps = (WpsInfo) message.obj; 3033 if (wps == null) { 3034 replyToMessage(message, WifiP2pManager.START_WPS_FAILED); 3035 break; 3036 } 3037 boolean ret = true; 3038 if (wps.setup == WpsInfo.PBC) { 3039 ret = mWifiNative.startWpsPbc(mGroup.getInterface(), null); 3040 } else { 3041 if (wps.pin == null) { 3042 String pin = mWifiNative.startWpsPinDisplay( 3043 mGroup.getInterface(), null); 3044 try { 3045 Integer.parseInt(pin); 3046 notifyInvitationSent(pin, "any"); 3047 } catch (NumberFormatException ignore) { 3048 ret = false; 3049 } 3050 } else { 3051 ret = mWifiNative.startWpsPinKeypad(mGroup.getInterface(), 3052 wps.pin); 3053 } 3054 } 3055 replyToMessage(message, ret ? WifiP2pManager.START_WPS_SUCCEEDED : 3056 WifiP2pManager.START_WPS_FAILED); 3057 break; 3058 case WifiP2pManager.CONNECT: 3059 if (!mWifiPermissionsUtil.checkCanAccessWifiDirect( 3060 getCallingPkgName(message.sendingUid, message.replyTo), 3061 getCallingFeatureId(message.sendingUid, message.replyTo), 3062 message.sendingUid, false)) { 3063 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 3064 // remain at this state. 3065 break; 3066 } 3067 WifiP2pConfig config = (WifiP2pConfig) message.obj; 3068 if (isConfigInvalid(config)) { 3069 loge("Dropping connect request " + config); 3070 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 3071 break; 3072 } 3073 logd("Inviting device : " + config.deviceAddress); 3074 mSavedPeerConfig = config; 3075 if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) { 3076 mPeers.updateStatus(config.deviceAddress, WifiP2pDevice.INVITED); 3077 sendPeersChangedBroadcast(); 3078 replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); 3079 } else { 3080 replyToMessage(message, WifiP2pManager.CONNECT_FAILED, 3081 WifiP2pManager.ERROR); 3082 } 3083 // TODO: figure out updating the status to declined 3084 // when invitation is rejected 3085 break; 3086 case WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT: 3087 P2pStatus status = (P2pStatus) message.obj; 3088 if (status == P2pStatus.SUCCESS) { 3089 // invocation was succeeded. 3090 break; 3091 } 3092 loge("Invitation result " + status); 3093 if (status == P2pStatus.UNKNOWN_P2P_GROUP) { 3094 // target device has already removed the credential. 3095 // So, remove this credential accordingly. 3096 int netId = mGroup.getNetworkId(); 3097 if (netId >= 0) { 3098 if (mVerboseLoggingEnabled) { 3099 logd("Remove unknown client from the list"); 3100 } 3101 removeClientFromList(netId, mSavedPeerConfig.deviceAddress, false); 3102 // try invitation. 3103 sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig); 3104 } 3105 } 3106 break; 3107 case WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: 3108 case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: 3109 case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: 3110 WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj; 3111 mSavedPeerConfig = new WifiP2pConfig(); 3112 if (provDisc != null && provDisc.device != null) { 3113 mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress; 3114 } 3115 if (message.what == WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) { 3116 mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; 3117 } else if (message.what == WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) { 3118 mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; 3119 mSavedPeerConfig.wps.pin = provDisc.pin; 3120 } else { 3121 mSavedPeerConfig.wps.setup = WpsInfo.PBC; 3122 } 3123 3124 // According to section 3.2.3 in SPEC, only GO can handle group join. 3125 // Multiple groups is not supported, ignore this discovery for GC. 3126 if (mGroup.isGroupOwner()) { 3127 transitionTo(mUserAuthorizingJoinState); 3128 } else { 3129 if (mVerboseLoggingEnabled) logd("Ignore provision discovery for GC"); 3130 } 3131 break; 3132 case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: 3133 loge("Duplicate group creation event notice, ignore"); 3134 break; 3135 case WifiP2pManager.CANCEL_CONNECT: 3136 mWifiNative.p2pCancelConnect(); 3137 mWifiP2pMetrics.endConnectionEvent( 3138 P2pConnectionEvent.CLF_CANCEL); 3139 3140 ArrayList<WifiP2pDevice> invitingPeers = new ArrayList<>(); 3141 mPeers.getDeviceList().forEach(dev -> { 3142 if (dev.status == WifiP2pDevice.INVITED) { 3143 invitingPeers.add(dev); 3144 } 3145 }); 3146 if (mPeers.remove(new WifiP2pDeviceList(invitingPeers))) { 3147 sendPeersChangedBroadcast(); 3148 } 3149 3150 replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED); 3151 break; 3152 default: 3153 return NOT_HANDLED; 3154 } 3155 return HANDLED; 3156 } 3157 exit()3158 public void exit() { 3159 // The group is still there and handling incoming request, 3160 // no need to update P2P connection information. 3161 if (mGroup != null) return; 3162 3163 mWifiP2pMetrics.endGroupEvent(); 3164 updateThisDevice(WifiP2pDevice.AVAILABLE); 3165 resetWifiP2pInfo(); 3166 mDetailedState = NetworkInfo.DetailedState.DISCONNECTED; 3167 sendP2pConnectionChangedBroadcast(); 3168 // When location mode is off, tethering service cannot receive regular 3169 // p2p connection changed event to stop tethering, send a 3170 // dedicated update to stop it. 3171 if (!mWifiPermissionsUtil.isLocationModeEnabled()) { 3172 sendP2pTetherRequestBroadcast(); 3173 } 3174 } 3175 } 3176 3177 class UserAuthorizingJoinState extends State { 3178 @Override enter()3179 public void enter() { 3180 if (mVerboseLoggingEnabled) logd(getName()); 3181 notifyInvitationReceived(); 3182 } 3183 3184 @Override processMessage(Message message)3185 public boolean processMessage(Message message) { 3186 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 3187 switch (message.what) { 3188 case WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: 3189 case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: 3190 case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: 3191 // Ignore more client requests 3192 break; 3193 case PEER_CONNECTION_USER_ACCEPT: 3194 // Stop discovery to avoid failure due to channel switch 3195 mWifiNative.p2pStopFind(); 3196 if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) { 3197 mWifiNative.startWpsPbc(mGroup.getInterface(), null); 3198 } else { 3199 mWifiNative.startWpsPinKeypad(mGroup.getInterface(), 3200 mSavedPeerConfig.wps.pin); 3201 } 3202 transitionTo(mGroupCreatedState); 3203 break; 3204 case PEER_CONNECTION_USER_REJECT: 3205 if (mVerboseLoggingEnabled) logd("User rejected incoming request"); 3206 transitionTo(mGroupCreatedState); 3207 break; 3208 default: 3209 return NOT_HANDLED; 3210 } 3211 return HANDLED; 3212 } 3213 3214 @Override exit()3215 public void exit() { 3216 // TODO: dismiss dialog if not already done 3217 } 3218 } 3219 3220 class OngoingGroupRemovalState extends State { 3221 @Override enter()3222 public void enter() { 3223 if (mVerboseLoggingEnabled) logd(getName()); 3224 } 3225 3226 @Override processMessage(Message message)3227 public boolean processMessage(Message message) { 3228 if (mVerboseLoggingEnabled) logd(getName() + message.toString()); 3229 switch (message.what) { 3230 // Group removal ongoing. Multiple calls 3231 // end up removing persisted network. Do nothing. 3232 case WifiP2pManager.REMOVE_GROUP: 3233 replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED); 3234 break; 3235 // Parent state will transition out of this state 3236 // when removal is complete 3237 default: 3238 return NOT_HANDLED; 3239 } 3240 return HANDLED; 3241 } 3242 } 3243 3244 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)3245 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 3246 super.dump(fd, pw, args); 3247 pw.println("mWifiP2pInfo " + mWifiP2pInfo); 3248 pw.println("mGroup " + mGroup); 3249 pw.println("mSavedPeerConfig " + mSavedPeerConfig); 3250 pw.println("mGroups" + mGroups); 3251 pw.println(); 3252 } 3253 checkAndSendP2pStateChangedBroadcast()3254 private void checkAndSendP2pStateChangedBroadcast() { 3255 Log.d(TAG, "Wifi enabled=" + mIsWifiEnabled); 3256 sendP2pStateChangedBroadcast(mIsWifiEnabled); 3257 } 3258 sendP2pStateChangedBroadcast(boolean enabled)3259 private void sendP2pStateChangedBroadcast(boolean enabled) { 3260 final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); 3261 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3262 if (enabled) { 3263 intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE, 3264 WifiP2pManager.WIFI_P2P_STATE_ENABLED); 3265 } else { 3266 intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE, 3267 WifiP2pManager.WIFI_P2P_STATE_DISABLED); 3268 } 3269 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3270 } 3271 sendP2pDiscoveryChangedBroadcast(boolean started)3272 private void sendP2pDiscoveryChangedBroadcast(boolean started) { 3273 if (mDiscoveryStarted == started) return; 3274 mDiscoveryStarted = started; 3275 3276 if (mVerboseLoggingEnabled) logd("discovery change broadcast " + started); 3277 3278 final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION); 3279 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3280 intent.putExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, started 3281 ? WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED : 3282 WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED); 3283 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3284 } 3285 sendBroadcastMultiplePermissions(Intent intent)3286 private void sendBroadcastMultiplePermissions(Intent intent) { 3287 Context context = mContext.createContextAsUser(UserHandle.ALL, 0); 3288 String[] permissions = RECEIVER_PERMISSIONS_FOR_BROADCAST; 3289 if (!mWifiPermissionsUtil.isLocationModeEnabled()) { 3290 permissions = RECEIVER_PERMISSIONS_FOR_BROADCAST_LOCATION_OFF; 3291 } 3292 context.sendBroadcastWithMultiplePermissions( 3293 intent, permissions); 3294 } 3295 sendThisDeviceChangedBroadcast()3296 private void sendThisDeviceChangedBroadcast() { 3297 final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); 3298 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3299 intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE, 3300 eraseOwnDeviceAddress(mThisDevice)); 3301 sendBroadcastMultiplePermissions(intent); 3302 } 3303 sendPeersChangedBroadcast()3304 private void sendPeersChangedBroadcast() { 3305 final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); 3306 intent.putExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST, new WifiP2pDeviceList(mPeers)); 3307 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3308 sendBroadcastMultiplePermissions(intent); 3309 } 3310 sendP2pConnectionChangedBroadcast()3311 private void sendP2pConnectionChangedBroadcast() { 3312 if (mVerboseLoggingEnabled) logd("sending p2p connection changed broadcast"); 3313 Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 3314 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 3315 | Intent.FLAG_RECEIVER_REPLACE_PENDING); 3316 intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo)); 3317 intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, makeNetworkInfo()); 3318 intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, eraseOwnDeviceAddress(mGroup)); 3319 sendBroadcastMultiplePermissions(intent); 3320 if (mWifiChannel != null) { 3321 mWifiChannel.sendMessage(WifiP2pServiceImpl.P2P_CONNECTION_CHANGED, 3322 makeNetworkInfo()); 3323 } else { 3324 loge("sendP2pConnectionChangedBroadcast(): WifiChannel is null"); 3325 } 3326 } 3327 isPackageExisted(String pkgName)3328 private boolean isPackageExisted(String pkgName) { 3329 PackageManager pm = mContext.getPackageManager(); 3330 try { 3331 PackageInfo info = pm.getPackageInfo(pkgName, PackageManager.GET_META_DATA); 3332 } catch (PackageManager.NameNotFoundException e) { 3333 return false; 3334 } 3335 return true; 3336 } 3337 findTetheringServicePackage()3338 private String findTetheringServicePackage() { 3339 ArrayList<String> possiblePackageNames = new ArrayList<>(); 3340 // AOSP 3341 possiblePackageNames.add("com.android.networkstack.tethering"); 3342 // mainline release 3343 possiblePackageNames.add("com.google.android.networkstack.tethering"); 3344 // Android Go 3345 possiblePackageNames.add("com.android.networkstack.tethering.inprocess"); 3346 3347 for (String pkgName: possiblePackageNames) { 3348 if (isPackageExisted(pkgName)) { 3349 Log.d(TAG, "Tethering service package: " + pkgName); 3350 return pkgName; 3351 } 3352 } 3353 Log.w(TAG, "Cannot find tethering service package!"); 3354 return null; 3355 } 3356 sendP2pTetherRequestBroadcast()3357 private boolean sendP2pTetherRequestBroadcast() { 3358 String tetheringServicePackage = findTetheringServicePackage(); 3359 if (TextUtils.isEmpty(tetheringServicePackage)) return false; 3360 Log.i(TAG, "sending p2p tether request broadcast to " 3361 + tetheringServicePackage); 3362 3363 Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 3364 intent.setPackage(tetheringServicePackage); 3365 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 3366 | Intent.FLAG_RECEIVER_REPLACE_PENDING); 3367 intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo)); 3368 intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, makeNetworkInfo()); 3369 intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, eraseOwnDeviceAddress(mGroup)); 3370 3371 Context context = mContext.createContextAsUser(UserHandle.ALL, 0); 3372 context.sendBroadcastWithMultiplePermissions( 3373 intent, RECEIVER_PERMISSIONS_FOR_BROADCAST); 3374 return true; 3375 } 3376 sendP2pPersistentGroupsChangedBroadcast()3377 private void sendP2pPersistentGroupsChangedBroadcast() { 3378 if (mVerboseLoggingEnabled) logd("sending p2p persistent groups changed broadcast"); 3379 Intent intent = new Intent(WifiP2pManager.ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED); 3380 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3381 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3382 } 3383 addRowToDialog(ViewGroup group, int stringId, String value)3384 private void addRowToDialog(ViewGroup group, int stringId, String value) { 3385 Resources r = mContext.getResources(); 3386 View row = LayoutInflater.from(mContext).cloneInContext(mContext) 3387 .inflate(R.layout.wifi_p2p_dialog_row, group, false); 3388 ((TextView) row.findViewById(R.id.name)).setText(r.getString(stringId)); 3389 ((TextView) row.findViewById(R.id.value)).setText(value); 3390 group.addView(row); 3391 } 3392 notifyInvitationSent(String pin, String peerAddress)3393 private void notifyInvitationSent(String pin, String peerAddress) { 3394 Resources r = mContext.getResources(); 3395 3396 final View textEntryView = LayoutInflater.from(mContext).cloneInContext(mContext) 3397 .inflate(R.layout.wifi_p2p_dialog, null); 3398 3399 ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info); 3400 addRowToDialog(group, R.string.wifi_p2p_to_message, getDeviceName(peerAddress)); 3401 addRowToDialog(group, R.string.wifi_p2p_show_pin_message, pin); 3402 3403 AlertDialog dialog = mFrameworkFacade.makeAlertDialogBuilder(mContext) 3404 .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title)) 3405 .setView(textEntryView) 3406 .setPositiveButton(r.getString(R.string.ok), null) 3407 .create(); 3408 dialog.setCanceledOnTouchOutside(false); 3409 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 3410 dialog.getWindow().addSystemFlags( 3411 WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); 3412 dialog.show(); 3413 } 3414 notifyP2pProvDiscShowPinRequest(String pin, String peerAddress)3415 private void notifyP2pProvDiscShowPinRequest(String pin, String peerAddress) { 3416 Resources r = mContext.getResources(); 3417 final View textEntryView = LayoutInflater.from(mContext).cloneInContext(mContext) 3418 .inflate(R.layout.wifi_p2p_dialog, null); 3419 3420 ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info); 3421 addRowToDialog(group, R.string.wifi_p2p_to_message, getDeviceName(peerAddress)); 3422 addRowToDialog(group, R.string.wifi_p2p_show_pin_message, pin); 3423 3424 AlertDialog dialog = mFrameworkFacade.makeAlertDialogBuilder(mContext) 3425 .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title)) 3426 .setView(textEntryView) 3427 .setPositiveButton(r.getString(R.string.accept), new OnClickListener() { 3428 public void onClick(DialogInterface dialog, int which) { 3429 sendMessage(PEER_CONNECTION_USER_CONFIRM); 3430 } 3431 }) 3432 .create(); 3433 dialog.setCanceledOnTouchOutside(false); 3434 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 3435 dialog.getWindow().addSystemFlags( 3436 WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); 3437 dialog.show(); 3438 } 3439 notifyInvitationReceived()3440 private void notifyInvitationReceived() { 3441 Resources r = mContext.getResources(); 3442 final WpsInfo wps = mSavedPeerConfig.wps; 3443 final View textEntryView = LayoutInflater.from(mContext).cloneInContext(mContext) 3444 .inflate(R.layout.wifi_p2p_dialog, null); 3445 3446 ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info); 3447 addRowToDialog(group, R.string.wifi_p2p_from_message, getDeviceName( 3448 mSavedPeerConfig.deviceAddress)); 3449 3450 final EditText pin = (EditText) textEntryView.findViewById(R.id.wifi_p2p_wps_pin); 3451 3452 AlertDialog dialog = mFrameworkFacade.makeAlertDialogBuilder(mContext) 3453 .setTitle(r.getString(R.string.wifi_p2p_invitation_to_connect_title)) 3454 .setView(textEntryView) 3455 .setPositiveButton(r.getString(R.string.accept), new OnClickListener() { 3456 public void onClick(DialogInterface dialog, int which) { 3457 if (wps.setup == WpsInfo.KEYPAD) { 3458 mSavedPeerConfig.wps.pin = pin.getText().toString(); 3459 } 3460 if (mVerboseLoggingEnabled) { 3461 logd(getName() + " accept invitation " + mSavedPeerConfig); 3462 } 3463 sendMessage(PEER_CONNECTION_USER_ACCEPT); 3464 } 3465 }) 3466 .setNegativeButton(r.getString(R.string.decline), new OnClickListener() { 3467 @Override 3468 public void onClick(DialogInterface dialog, int which) { 3469 if (mVerboseLoggingEnabled) logd(getName() + " ignore connect"); 3470 sendMessage(PEER_CONNECTION_USER_REJECT); 3471 } 3472 }) 3473 .setOnCancelListener(new DialogInterface.OnCancelListener() { 3474 @Override 3475 public void onCancel(DialogInterface arg0) { 3476 if (mVerboseLoggingEnabled) logd(getName() + " ignore connect"); 3477 sendMessage(PEER_CONNECTION_USER_REJECT); 3478 } 3479 }) 3480 .create(); 3481 dialog.setCanceledOnTouchOutside(false); 3482 3483 // make the enter pin area or the display pin area visible 3484 switch (wps.setup) { 3485 case WpsInfo.KEYPAD: 3486 if (mVerboseLoggingEnabled) logd("Enter pin section visible"); 3487 textEntryView.findViewById(R.id.enter_pin_section).setVisibility(View.VISIBLE); 3488 break; 3489 case WpsInfo.DISPLAY: 3490 if (mVerboseLoggingEnabled) logd("Shown pin section visible"); 3491 addRowToDialog(group, R.string.wifi_p2p_show_pin_message, wps.pin); 3492 break; 3493 default: 3494 break; 3495 } 3496 3497 if ((r.getConfiguration().uiMode & Configuration.UI_MODE_TYPE_APPLIANCE) 3498 == Configuration.UI_MODE_TYPE_APPLIANCE) { 3499 // For appliance devices, add a key listener which accepts. 3500 dialog.setOnKeyListener(new DialogInterface.OnKeyListener() { 3501 3502 @Override 3503 public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { 3504 // TODO: make the actual key come from a config value. 3505 if (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) { 3506 sendMessage(PEER_CONNECTION_USER_ACCEPT); 3507 dialog.dismiss(); 3508 return true; 3509 } 3510 return false; 3511 } 3512 }); 3513 // TODO: add timeout for this dialog. 3514 // TODO: update UI in appliance mode to tell user what to do. 3515 } 3516 3517 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 3518 dialog.getWindow().addSystemFlags( 3519 WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); 3520 dialog.show(); 3521 } 3522 3523 /** 3524 * This method unifies the persisent group list, cleans up unused 3525 * networks and if required, updates corresponding broadcast receivers 3526 * @param reload if true, reload the group list from scratch 3527 * and send broadcast message with fresh list 3528 */ updatePersistentNetworks(boolean reload)3529 private void updatePersistentNetworks(boolean reload) { 3530 if (reload) mGroups.clear(); 3531 3532 // Save in all cases, including when reload was requested, but 3533 // no network has been found. 3534 if (mWifiNative.p2pListNetworks(mGroups) || reload) { 3535 for (WifiP2pGroup group : mGroups.getGroupList()) { 3536 if (group.getOwner() == null) { 3537 Log.d(TAG, "group.getOwner() null"); 3538 continue; 3539 } 3540 if (Objects.equals(mThisDevice.deviceAddress, group.getOwner().deviceAddress)) { 3541 group.setOwner(mThisDevice); 3542 } 3543 } 3544 mWifiNative.saveConfig(); 3545 mWifiP2pMetrics.updatePersistentGroup(mGroups); 3546 sendP2pPersistentGroupsChangedBroadcast(); 3547 } 3548 } 3549 3550 /** 3551 * A config is valid if it has a peer address that has already been 3552 * discovered 3553 * @param WifiP2pConfig config to be validated 3554 * @return true if it is invalid, false otherwise 3555 */ isConfigInvalid(WifiP2pConfig config)3556 private boolean isConfigInvalid(WifiP2pConfig config) { 3557 if (config == null) return true; 3558 if (TextUtils.isEmpty(config.deviceAddress)) return true; 3559 if (mPeers.get(config.deviceAddress) == null) return true; 3560 return false; 3561 } 3562 3563 /** 3564 * Check the network name complies standard SSID naming rules. 3565 * 3566 * The network name of a group is also the broadcasting SSID, 3567 * as a result, the network name must complies standard SSID naming 3568 * rules. 3569 */ isValidNetworkName(String networkName)3570 private boolean isValidNetworkName(String networkName) { 3571 if (TextUtils.isEmpty(networkName)) return false; 3572 3573 byte[] ssidBytes = networkName.getBytes(StandardCharsets.UTF_8); 3574 if (ssidBytes.length < MIN_NETWORK_NAME_BYTES) return false; 3575 if (ssidBytes.length > MAX_NETWORK_NAME_BYTES) return false; 3576 3577 return true; 3578 } 3579 3580 /** 3581 * A config is valid as a group if it has network name and passphrase. 3582 * Supplicant can construct a group on the fly for creating a group with specified config 3583 * or join a group without negotiation and WPS. 3584 * @param WifiP2pConfig config to be validated 3585 * @return true if it is valid, false otherwise 3586 */ isConfigValidAsGroup(WifiP2pConfig config)3587 private boolean isConfigValidAsGroup(WifiP2pConfig config) { 3588 if (config == null) return false; 3589 if (TextUtils.isEmpty(config.deviceAddress)) return false; 3590 if (isValidNetworkName(config.networkName) 3591 && !TextUtils.isEmpty(config.passphrase)) { 3592 return true; 3593 } 3594 3595 return false; 3596 } 3597 fetchCurrentDeviceDetails(WifiP2pConfig config)3598 private WifiP2pDevice fetchCurrentDeviceDetails(WifiP2pConfig config) { 3599 if (config == null) return null; 3600 // Fetch & update group capability from supplicant on the device 3601 int gc = mWifiNative.getGroupCapability(config.deviceAddress); 3602 // TODO: The supplicant does not provide group capability changes as an event. 3603 // Having it pushed as an event would avoid polling for this information right 3604 // before a connection 3605 mPeers.updateGroupCapability(config.deviceAddress, gc); 3606 return mPeers.get(config.deviceAddress); 3607 } 3608 3609 /** 3610 * Erase the MAC address of our interface if it is present in a given device, to prevent 3611 * apps from having access to persistent identifiers. 3612 * 3613 * @param device a device possibly having the same physical address as the wlan interface. 3614 * @return a copy of the input, possibly with the device address erased. 3615 */ eraseOwnDeviceAddress(WifiP2pDevice device)3616 private WifiP2pDevice eraseOwnDeviceAddress(WifiP2pDevice device) { 3617 if (device == null) { 3618 return null; 3619 } 3620 WifiP2pDevice result = new WifiP2pDevice(device); 3621 if (device.deviceAddress != null 3622 && mThisDevice.deviceAddress != null 3623 && device.deviceAddress.length() > 0 3624 && mThisDevice.deviceAddress.equals(device.deviceAddress)) { 3625 result.deviceAddress = ANONYMIZED_DEVICE_ADDRESS; 3626 } 3627 return result; 3628 } 3629 3630 /** 3631 * Erase the MAC address of our interface if it is set as the device address for any of the 3632 * devices in a group. 3633 * 3634 * @param group a p2p group containing p2p devices. 3635 * @return a copy of the input, with any devices corresponding to our wlan interface having 3636 * their device address erased. 3637 */ eraseOwnDeviceAddress(WifiP2pGroup group)3638 private WifiP2pGroup eraseOwnDeviceAddress(WifiP2pGroup group) { 3639 if (group == null) { 3640 return null; 3641 } 3642 3643 WifiP2pGroup result = new WifiP2pGroup(group); 3644 3645 // Create copies of the clients so they're not shared with the original object. 3646 for (WifiP2pDevice originalDevice : group.getClientList()) { 3647 result.removeClient(originalDevice); 3648 result.addClient(eraseOwnDeviceAddress(originalDevice)); 3649 } 3650 3651 WifiP2pDevice groupOwner = group.getOwner(); 3652 result.setOwner(eraseOwnDeviceAddress(groupOwner)); 3653 3654 return result; 3655 } 3656 3657 /** 3658 * Erase the MAC address of our interface if it is present in a given device, to prevent 3659 * apps from having access to persistent identifiers. If the requesting party holds the 3660 * {@link Manifest.permission.LOCAL_MAC_ADDRESS} permission, the address is not erased. 3661 * 3662 * @param device a device possibly having the same physical address as the wlan interface. 3663 * @param uid the user id of the app that requested the information. 3664 * @return a copy of the input, possibly with the device address erased. 3665 */ maybeEraseOwnDeviceAddress(WifiP2pDevice device, int uid)3666 private WifiP2pDevice maybeEraseOwnDeviceAddress(WifiP2pDevice device, int uid) { 3667 if (device == null) { 3668 return null; 3669 } 3670 if (mWifiPermissionsUtil.checkLocalMacAddressPermission(uid)) { 3671 // Calling app holds the LOCAL_MAC_ADDRESS permission, and is allowed to see this 3672 // device's MAC. 3673 return new WifiP2pDevice(device); 3674 } else { 3675 return eraseOwnDeviceAddress(device); 3676 } 3677 } 3678 3679 /** 3680 * Erase the MAC address of our interface if it is set as the device address for any of the 3681 * devices in a group. If the requesting party holds the 3682 * {@link Manifest.permission.LOCAL_MAC_ADDRESS} permission, the address is not erased. 3683 * 3684 * @param group a p2p group containing p2p devices. 3685 * @param uid the user id of the app that requested the information. 3686 * @return a copy of the input, with any devices corresponding to our wlan interface having 3687 * their device address erased. If the requesting app holds the LOCAL_MAC_ADDRESS 3688 * permission, this method returns a copy of the input. 3689 */ maybeEraseOwnDeviceAddress(WifiP2pGroup group, int uid)3690 private WifiP2pGroup maybeEraseOwnDeviceAddress(WifiP2pGroup group, int uid) { 3691 if (group == null) { 3692 return null; 3693 } 3694 if (mWifiPermissionsUtil.checkLocalMacAddressPermission(uid)) { 3695 // Calling app holds the LOCAL_MAC_ADDRESS permission, and is allowed to see this 3696 // device's MAC. 3697 return new WifiP2pGroup(group); 3698 } else { 3699 return eraseOwnDeviceAddress(group); 3700 } 3701 } 3702 3703 /** 3704 * Erase the MAC address of our interface if it is set as the device address for any of the 3705 * devices in a list of groups. If the requesting party holds the 3706 * {@link Manifest.permission.LOCAL_MAC_ADDRESS} permission, the address is not erased. 3707 * 3708 * @param groupList a list of p2p groups containing p2p devices. 3709 * @param uid the user id of the app that requested the information. 3710 * @return a copy of the input, with any devices corresponding to our wlan interface having 3711 * their device address erased. If the requesting app holds the LOCAL_MAC_ADDRESS 3712 * permission, this method returns a copy of the input. 3713 */ maybeEraseOwnDeviceAddress(WifiP2pGroupList groupList, int uid)3714 private WifiP2pGroupList maybeEraseOwnDeviceAddress(WifiP2pGroupList groupList, int uid) { 3715 if (groupList == null) { 3716 return null; 3717 } 3718 WifiP2pGroupList result = new WifiP2pGroupList(); 3719 for (WifiP2pGroup group : groupList.getGroupList()) { 3720 result.add(maybeEraseOwnDeviceAddress(group, uid)); 3721 } 3722 return result; 3723 } 3724 3725 /** 3726 * Start a p2p group negotiation and display pin if necessary 3727 * @param config for the peer 3728 */ p2pConnectWithPinDisplay(WifiP2pConfig config, int triggerType)3729 private void p2pConnectWithPinDisplay(WifiP2pConfig config, int triggerType) { 3730 if (config == null) { 3731 Log.e(TAG, "Illegal argument(s)"); 3732 return; 3733 } 3734 WifiP2pDevice dev = fetchCurrentDeviceDetails(config); 3735 if (dev == null) { 3736 Log.e(TAG, "Invalid device"); 3737 return; 3738 } 3739 config.groupOwnerIntent = selectGroupOwnerIntentIfNecessary(config); 3740 boolean action; 3741 if (triggerType == P2P_CONNECT_TRIGGER_GROUP_NEG_REQ) { 3742 // If this is called from the GO negotiation path, the sender initiated 3743 // a group negotiation. 3744 action = FORM_GROUP; 3745 } else if (triggerType == P2P_CONNECT_TRIGGER_INVITATION_REQ) { 3746 // The group owner won't report it is a Group Owner always. 3747 // If this is called from the invitation path, the sender should be in 3748 // a group, and the target should be a group owner. 3749 action = JOIN_GROUP; 3750 } else { 3751 action = dev.isGroupOwner() ? JOIN_GROUP : FORM_GROUP; 3752 } 3753 3754 String pin = mWifiNative.p2pConnect(config, action); 3755 try { 3756 Integer.parseInt(pin); 3757 notifyInvitationSent(pin, config.deviceAddress); 3758 } catch (NumberFormatException ignore) { 3759 // do nothing if p2pConnect did not return a pin 3760 } 3761 } 3762 3763 /** 3764 * Reinvoke a persistent group. 3765 * 3766 * @param config for the peer 3767 * @return true on success, false on failure 3768 */ reinvokePersistentGroup(WifiP2pConfig config, boolean isInvited)3769 private boolean reinvokePersistentGroup(WifiP2pConfig config, boolean isInvited) { 3770 if (config == null) { 3771 Log.e(TAG, "Illegal argument(s)"); 3772 return false; 3773 } 3774 WifiP2pDevice dev = fetchCurrentDeviceDetails(config); 3775 if (dev == null) { 3776 Log.e(TAG, "Invalid device"); 3777 return false; 3778 } 3779 // The group owner won't report it is a Group Owner always. 3780 // If this is called from the invitation path, the sender should be in 3781 // a group, and the target should be a group owner. 3782 boolean join = dev.isGroupOwner() || isInvited; 3783 String ssid = mWifiNative.p2pGetSsid(dev.deviceAddress); 3784 if (mVerboseLoggingEnabled) logd("target ssid is " + ssid + " join:" + join); 3785 3786 if (join && dev.isGroupLimit()) { 3787 if (mVerboseLoggingEnabled) logd("target device reaches group limit."); 3788 3789 // if the target group has reached the limit, 3790 // try group formation. 3791 join = false; 3792 } else if (join) { 3793 int netId = mGroups.getNetworkId(dev.deviceAddress, ssid); 3794 if (isInvited && netId < 0) { 3795 netId = mGroups.getNetworkId(dev.deviceAddress); 3796 } 3797 if (netId >= 0) { 3798 // Skip WPS and start 4way handshake immediately. 3799 if (!mWifiNative.p2pGroupAdd(netId)) { 3800 return false; 3801 } 3802 return true; 3803 } 3804 } 3805 3806 if (!join && dev.isDeviceLimit()) { 3807 loge("target device reaches the device limit."); 3808 return false; 3809 } 3810 3811 if (!join && dev.isInvitationCapable()) { 3812 int netId = WifiP2pGroup.NETWORK_ID_PERSISTENT; 3813 if (config.netId >= 0) { 3814 if (config.deviceAddress.equals(mGroups.getOwnerAddr(config.netId))) { 3815 netId = config.netId; 3816 } 3817 } else { 3818 netId = mGroups.getNetworkId(dev.deviceAddress); 3819 } 3820 if (netId < 0) { 3821 netId = getNetworkIdFromClientList(dev.deviceAddress); 3822 } 3823 if (mVerboseLoggingEnabled) { 3824 logd("netId related with " + dev.deviceAddress + " = " + netId); 3825 } 3826 if (netId >= 0) { 3827 // Invoke the persistent group. 3828 if (mWifiNative.p2pReinvoke(netId, dev.deviceAddress)) { 3829 // Save network id. It'll be used when an invitation 3830 // result event is received. 3831 config.netId = netId; 3832 return true; 3833 } else { 3834 loge("p2pReinvoke() failed, update networks"); 3835 updatePersistentNetworks(RELOAD); 3836 return false; 3837 } 3838 } 3839 } 3840 return false; 3841 } 3842 3843 /** 3844 * Return the network id of the group owner profile which has the p2p client with 3845 * the specified device address in it's client list. 3846 * If more than one persistent group of the same address is present in its client 3847 * lists, return the first one. 3848 * 3849 * @param deviceAddress p2p device address. 3850 * @return the network id. if not found, return -1. 3851 */ getNetworkIdFromClientList(String deviceAddress)3852 private int getNetworkIdFromClientList(String deviceAddress) { 3853 if (deviceAddress == null) return -1; 3854 3855 Collection<WifiP2pGroup> groups = mGroups.getGroupList(); 3856 for (WifiP2pGroup group : groups) { 3857 int netId = group.getNetworkId(); 3858 String[] p2pClientList = getClientList(netId); 3859 if (p2pClientList == null) continue; 3860 for (String client : p2pClientList) { 3861 if (deviceAddress.equalsIgnoreCase(client)) { 3862 return netId; 3863 } 3864 } 3865 } 3866 return -1; 3867 } 3868 3869 /** 3870 * Return p2p client list associated with the specified network id. 3871 * @param netId network id. 3872 * @return p2p client list. if not found, return null. 3873 */ getClientList(int netId)3874 private String[] getClientList(int netId) { 3875 String p2pClients = mWifiNative.getP2pClientList(netId); 3876 if (p2pClients == null) { 3877 return null; 3878 } 3879 return p2pClients.split(" "); 3880 } 3881 3882 /** 3883 * Remove the specified p2p client from the specified profile. 3884 * @param netId network id of the profile. 3885 * @param addr p2p client address to be removed. 3886 * @param isRemovable if true, remove the specified profile if its client 3887 * list becomes empty. 3888 * @return whether removing the specified p2p client is successful or not. 3889 */ removeClientFromList(int netId, String addr, boolean isRemovable)3890 private boolean removeClientFromList(int netId, String addr, boolean isRemovable) { 3891 StringBuilder modifiedClientList = new StringBuilder(); 3892 String[] currentClientList = getClientList(netId); 3893 boolean isClientRemoved = false; 3894 if (currentClientList != null) { 3895 for (String client : currentClientList) { 3896 if (!client.equalsIgnoreCase(addr)) { 3897 modifiedClientList.append(" "); 3898 modifiedClientList.append(client); 3899 } else { 3900 isClientRemoved = true; 3901 } 3902 } 3903 } 3904 if (modifiedClientList.length() == 0 && isRemovable) { 3905 // the client list is empty. so remove it. 3906 if (mVerboseLoggingEnabled) logd("Remove unknown network"); 3907 mGroups.remove(netId); 3908 mWifiP2pMetrics.updatePersistentGroup(mGroups); 3909 return true; 3910 } 3911 3912 if (!isClientRemoved) { 3913 // specified p2p client is not found. already removed. 3914 return false; 3915 } 3916 3917 if (mVerboseLoggingEnabled) logd("Modified client list: " + modifiedClientList); 3918 if (modifiedClientList.length() == 0) { 3919 modifiedClientList.append("\"\""); 3920 } 3921 mWifiNative.setP2pClientList(netId, modifiedClientList.toString()); 3922 mWifiNative.saveConfig(); 3923 return true; 3924 } 3925 getInterfaceAddress(String interfaceName)3926 private Inet4Address getInterfaceAddress(String interfaceName) { 3927 NetworkInterface iface; 3928 try { 3929 iface = NetworkInterface.getByName(interfaceName); 3930 } catch (SocketException ex) { 3931 Log.w(TAG, "Could not obtain address of network interface " 3932 + interfaceName, ex); 3933 return null; 3934 } 3935 Enumeration<InetAddress> addrs = iface.getInetAddresses(); 3936 while (addrs.hasMoreElements()) { 3937 InetAddress addr = addrs.nextElement(); 3938 if (addr instanceof Inet4Address) { 3939 return (Inet4Address) addr; 3940 } 3941 } 3942 Log.w(TAG, "Could not obtain address of network interface " 3943 + interfaceName + " because it had no IPv4 addresses."); 3944 return null; 3945 } 3946 setWifiP2pInfoOnGroupFormation(String serverAddress)3947 private void setWifiP2pInfoOnGroupFormation(String serverAddress) { 3948 InetAddress serverInetAddress = serverAddress == null 3949 ? null 3950 : InetAddresses.parseNumericAddress(serverAddress); 3951 mWifiP2pInfo.groupFormed = true; 3952 mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner(); 3953 mWifiP2pInfo.groupOwnerAddress = serverInetAddress; 3954 } 3955 resetWifiP2pInfo()3956 private void resetWifiP2pInfo() { 3957 mWifiP2pInfo.groupFormed = false; 3958 mWifiP2pInfo.isGroupOwner = false; 3959 mWifiP2pInfo.groupOwnerAddress = null; 3960 } 3961 getDeviceName(String deviceAddress)3962 private String getDeviceName(String deviceAddress) { 3963 WifiP2pDevice d = mPeers.get(deviceAddress); 3964 if (d != null) { 3965 return d.deviceName; 3966 } 3967 //Treat the address as name if there is no match 3968 return deviceAddress; 3969 } 3970 getPersistedDeviceName()3971 private String getPersistedDeviceName() { 3972 String deviceName = mSettingsConfigStore.get(WIFI_P2P_DEVICE_NAME); 3973 if (null != deviceName) return deviceName; 3974 3975 String prefix = mWifiGlobals.getWifiP2pDeviceNamePrefix(); 3976 if (DEVICE_NAME_PREFIX_LENGTH_MAX < prefix.getBytes(StandardCharsets.UTF_8).length 3977 || 0 == prefix.getBytes(StandardCharsets.UTF_8).length) { 3978 logw("The length of default device name prefix is invalid" 3979 + ", fallback to default name."); 3980 prefix = DEFAULT_DEVICE_NAME_PREFIX; 3981 } 3982 // The length of remaining bytes is at least {@link #DEVICE_NAME_POSTFIX_LENGTH_MIN}. 3983 int remainingBytes = 3984 DEVICE_NAME_LENGTH_MAX - prefix.getBytes(StandardCharsets.UTF_8).length; 3985 3986 int numDigits = mWifiGlobals.getWifiP2pDeviceNamePostfixNumDigits(); 3987 if (numDigits > remainingBytes) { 3988 logw("The postfix length exceeds the remaining byte number" 3989 + ", use the smaller one."); 3990 numDigits = remainingBytes; 3991 } 3992 3993 String postfix; 3994 if (numDigits >= DEVICE_NAME_POSTFIX_LENGTH_MIN) { 3995 postfix = StringUtil.generateRandomNumberString(numDigits); 3996 } else { 3997 // We use the 4 digits of the ANDROID_ID to have a friendly 3998 // default that has low likelihood of collision with a peer 3999 String id = mFrameworkFacade.getSecureStringSetting(mContext, 4000 Settings.Secure.ANDROID_ID); 4001 postfix = id.substring(0, 4); 4002 } 4003 logd("the default device name: " + prefix + postfix); 4004 return prefix + postfix; 4005 } 4006 setAndPersistDeviceName(String devName)4007 private boolean setAndPersistDeviceName(String devName) { 4008 if (devName == null) return false; 4009 4010 if (!mWifiNative.setDeviceName(devName)) { 4011 loge("Failed to set device name " + devName); 4012 return false; 4013 } 4014 4015 mThisDevice.deviceName = devName; 4016 mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName); 4017 4018 mSettingsConfigStore.put(WIFI_P2P_DEVICE_NAME, devName); 4019 sendThisDeviceChangedBroadcast(); 4020 return true; 4021 } 4022 setWfdInfo(WifiP2pWfdInfo wfdInfo)4023 private boolean setWfdInfo(WifiP2pWfdInfo wfdInfo) { 4024 final boolean enabled = wfdInfo.isEnabled(); 4025 boolean success; 4026 if (!mWifiNative.setWfdEnable(enabled)) { 4027 loge("Failed to set wfd enable: " + enabled); 4028 return false; 4029 } 4030 4031 if (enabled) { 4032 if (!mWifiNative.setWfdDeviceInfo(wfdInfo.getDeviceInfoHex())) { 4033 loge("Failed to set wfd properties"); 4034 return false; 4035 } 4036 if (!setWfdR2InfoIfNecessary(wfdInfo)) { 4037 loge("Failed to set wfd r2 properties"); 4038 return false; 4039 } 4040 } 4041 mThisDevice.wfdInfo = wfdInfo; 4042 sendThisDeviceChangedBroadcast(); 4043 return true; 4044 } 4045 setWfdR2InfoIfNecessary(WifiP2pWfdInfo wfdInfo)4046 private boolean setWfdR2InfoIfNecessary(WifiP2pWfdInfo wfdInfo) { 4047 if (!SdkLevel.isAtLeastS()) return true; 4048 if (!wfdInfo.isR2Supported()) return true; 4049 return mWifiNative.setWfdR2DeviceInfo(wfdInfo.getR2DeviceInfoHex()); 4050 } 4051 initializeP2pSettings()4052 private void initializeP2pSettings() { 4053 mThisDevice.deviceName = getPersistedDeviceName(); 4054 mThisDevice.primaryDeviceType = mContext.getResources().getString( 4055 R.string.config_wifi_p2p_device_type); 4056 4057 mWifiNative.setP2pDeviceName(mThisDevice.deviceName); 4058 // DIRECT-XY-DEVICENAME (XY is randomly generated) 4059 mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName); 4060 mWifiNative.setP2pDeviceType(mThisDevice.primaryDeviceType); 4061 // Supplicant defaults to using virtual display with display 4062 // which refers to a remote display. Use physical_display 4063 mWifiNative.setConfigMethods("virtual_push_button physical_display keypad"); 4064 4065 mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress(); 4066 updateThisDevice(WifiP2pDevice.AVAILABLE); 4067 if (mVerboseLoggingEnabled) logd("DeviceAddress: " + mThisDevice.deviceAddress); 4068 mWifiNative.p2pFlush(); 4069 mWifiNative.p2pServiceFlush(); 4070 mServiceTransactionId = 0; 4071 mServiceDiscReqId = null; 4072 4073 updatePersistentNetworks(RELOAD); 4074 enableVerboseLogging(mSettingsConfigStore.get(WIFI_VERBOSE_LOGGING_ENABLED)); 4075 } 4076 updateThisDevice(int status)4077 private void updateThisDevice(int status) { 4078 mThisDevice.status = status; 4079 sendThisDeviceChangedBroadcast(); 4080 } 4081 handleGroupCreationFailure()4082 private void handleGroupCreationFailure() { 4083 // A group is formed, but the tethering request is not proceed. 4084 if (null != mGroup) { 4085 // Clear any timeout that was set. This is essential for devices 4086 // that reuse the main p2p interface for a created group. 4087 mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0); 4088 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 4089 mGroup = null; 4090 } 4091 resetWifiP2pInfo(); 4092 mDetailedState = NetworkInfo.DetailedState.FAILED; 4093 sendP2pConnectionChangedBroadcast(); 4094 4095 // Remove only the peer we failed to connect to so that other devices discovered 4096 // that have not timed out still remain in list for connection 4097 boolean peersChanged = mPeers.remove(mPeersLostDuringConnection); 4098 if (!TextUtils.isEmpty(mSavedPeerConfig.deviceAddress) 4099 && mPeers.remove(mSavedPeerConfig.deviceAddress) != null) { 4100 peersChanged = true; 4101 } 4102 if (peersChanged) { 4103 sendPeersChangedBroadcast(); 4104 } 4105 4106 mPeersLostDuringConnection.clear(); 4107 mServiceDiscReqId = null; 4108 sendMessage(WifiP2pManager.DISCOVER_PEERS); 4109 } 4110 handleGroupRemoved()4111 private void handleGroupRemoved() { 4112 if (mGroup.isGroupOwner()) { 4113 // {@link com.android.server.connectivity.Tethering} listens to 4114 // {@link WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION} 4115 // events and takes over the DHCP server management automatically. 4116 } else { 4117 if (mVerboseLoggingEnabled) logd("stop IpClient"); 4118 stopIpClient(); 4119 try { 4120 mNetdWrapper.removeInterfaceFromLocalNetwork(mGroup.getInterface()); 4121 } catch (IllegalStateException e) { 4122 loge("Failed to remove iface from local network " + e); 4123 } 4124 } 4125 4126 try { 4127 mNetdWrapper.clearInterfaceAddresses(mGroup.getInterface()); 4128 } catch (Exception e) { 4129 loge("Failed to clear addresses " + e); 4130 } 4131 4132 // Clear any timeout that was set. This is essential for devices 4133 // that reuse the main p2p interface for a created group. 4134 mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0); 4135 4136 boolean peersChanged = false; 4137 // Remove only peers part of the group, so that other devices discovered 4138 // that have not timed out still remain in list for connection 4139 for (WifiP2pDevice d : mGroup.getClientList()) { 4140 if (mPeers.remove(d)) peersChanged = true; 4141 } 4142 if (mPeers.remove(mGroup.getOwner())) peersChanged = true; 4143 if (mPeers.remove(mPeersLostDuringConnection)) peersChanged = true; 4144 if (peersChanged) { 4145 sendPeersChangedBroadcast(); 4146 } 4147 4148 mGroup = null; 4149 mPeersLostDuringConnection.clear(); 4150 mServiceDiscReqId = null; 4151 4152 if (mTemporarilyDisconnectedWifi) { 4153 if (mWifiChannel != null) { 4154 mWifiChannel.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST, 0); 4155 } else { 4156 loge("handleGroupRemoved(): WifiChannel is null"); 4157 } 4158 mTemporarilyDisconnectedWifi = false; 4159 } 4160 } 4161 replyToMessage(Message msg, int what)4162 private void replyToMessage(Message msg, int what) { 4163 // State machine initiated requests can have replyTo set to null 4164 // indicating there are no recipients, we ignore those reply actions 4165 if (msg.replyTo == null) return; 4166 Message dstMsg = obtainMessage(msg); 4167 dstMsg.what = what; 4168 mReplyChannel.replyToMessage(msg, dstMsg); 4169 } 4170 replyToMessage(Message msg, int what, int arg1)4171 private void replyToMessage(Message msg, int what, int arg1) { 4172 if (msg.replyTo == null) return; 4173 Message dstMsg = obtainMessage(msg); 4174 dstMsg.what = what; 4175 dstMsg.arg1 = arg1; 4176 mReplyChannel.replyToMessage(msg, dstMsg); 4177 } 4178 replyToMessage(Message msg, int what, Object obj)4179 private void replyToMessage(Message msg, int what, Object obj) { 4180 if (msg.replyTo == null) return; 4181 Message dstMsg = obtainMessage(msg); 4182 dstMsg.what = what; 4183 dstMsg.obj = obj; 4184 mReplyChannel.replyToMessage(msg, dstMsg); 4185 } 4186 obtainMessage(Message srcMsg)4187 private Message obtainMessage(Message srcMsg) { 4188 // arg2 on the source message has a hash code that needs to 4189 // be retained in replies see WifiP2pManager for details 4190 Message msg = Message.obtain(); 4191 msg.arg2 = srcMsg.arg2; 4192 return msg; 4193 } 4194 4195 @Override logd(String s)4196 protected void logd(String s) { 4197 Log.d(TAG, s); 4198 } 4199 4200 @Override loge(String s)4201 protected void loge(String s) { 4202 Log.e(TAG, s); 4203 } 4204 4205 /** 4206 * Update service discovery request to wpa_supplicant. 4207 */ updateSupplicantServiceRequest()4208 private boolean updateSupplicantServiceRequest() { 4209 clearSupplicantServiceRequest(); 4210 4211 StringBuffer sb = new StringBuffer(); 4212 for (ClientInfo c: mClientInfoList.values()) { 4213 int key; 4214 WifiP2pServiceRequest req; 4215 for (int i = 0; i < c.mReqList.size(); i++) { 4216 req = c.mReqList.valueAt(i); 4217 if (req != null) { 4218 sb.append(req.getSupplicantQuery()); 4219 } 4220 } 4221 } 4222 4223 if (sb.length() == 0) { 4224 return false; 4225 } 4226 4227 mServiceDiscReqId = mWifiNative.p2pServDiscReq("00:00:00:00:00:00", sb.toString()); 4228 if (mServiceDiscReqId == null) { 4229 return false; 4230 } 4231 return true; 4232 } 4233 4234 /** 4235 * Clear service discovery request in wpa_supplicant 4236 */ clearSupplicantServiceRequest()4237 private void clearSupplicantServiceRequest() { 4238 if (mServiceDiscReqId == null) return; 4239 4240 mWifiNative.p2pServDiscCancelReq(mServiceDiscReqId); 4241 mServiceDiscReqId = null; 4242 } 4243 addServiceRequest(Messenger m, WifiP2pServiceRequest req)4244 private boolean addServiceRequest(Messenger m, WifiP2pServiceRequest req) { 4245 if (m == null || req == null) { 4246 Log.e(TAG, "Illegal argument(s)"); 4247 return false; 4248 } 4249 // TODO: We could track individual service adds separately and avoid 4250 // having to do update all service requests on every new request 4251 clearClientDeadChannels(); 4252 4253 ClientInfo clientInfo = getClientInfo(m, false); 4254 if (clientInfo == null) { 4255 return false; 4256 } 4257 4258 ++mServiceTransactionId; 4259 // The Wi-Fi p2p spec says transaction id should be 1 byte and non-zero. 4260 if (mServiceTransactionId == 256) mServiceTransactionId = 1; 4261 req.setTransactionId((mServiceTransactionId)); 4262 clientInfo.mReqList.put(mServiceTransactionId, req); 4263 4264 if (mServiceDiscReqId == null) { 4265 return true; 4266 } 4267 4268 return updateSupplicantServiceRequest(); 4269 } 4270 removeServiceRequest(Messenger m, WifiP2pServiceRequest req)4271 private void removeServiceRequest(Messenger m, WifiP2pServiceRequest req) { 4272 if (m == null || req == null) { 4273 Log.e(TAG, "Illegal argument(s)"); 4274 } 4275 4276 ClientInfo clientInfo = getClientInfo(m, false); 4277 if (clientInfo == null) { 4278 return; 4279 } 4280 4281 // Application does not have transaction id information 4282 // go through stored requests to remove 4283 boolean removed = false; 4284 for (int i = 0; i < clientInfo.mReqList.size(); i++) { 4285 if (req.equals(clientInfo.mReqList.valueAt(i))) { 4286 removed = true; 4287 clientInfo.mReqList.removeAt(i); 4288 break; 4289 } 4290 } 4291 4292 if (!removed) return; 4293 4294 if (mServiceDiscReqId == null) { 4295 return; 4296 } 4297 4298 updateSupplicantServiceRequest(); 4299 } 4300 clearServiceRequests(Messenger m)4301 private void clearServiceRequests(Messenger m) { 4302 if (m == null) { 4303 Log.e(TAG, "Illegal argument(s)"); 4304 return; 4305 } 4306 4307 ClientInfo clientInfo = getClientInfo(m, false); 4308 if (clientInfo == null) { 4309 return; 4310 } 4311 4312 if (clientInfo.mReqList.size() == 0) { 4313 return; 4314 } 4315 4316 clientInfo.mReqList.clear(); 4317 4318 if (mServiceDiscReqId == null) { 4319 return; 4320 } 4321 4322 updateSupplicantServiceRequest(); 4323 } 4324 addLocalService(Messenger m, WifiP2pServiceInfo servInfo)4325 private boolean addLocalService(Messenger m, WifiP2pServiceInfo servInfo) { 4326 if (m == null || servInfo == null) { 4327 Log.e(TAG, "Illegal arguments"); 4328 return false; 4329 } 4330 4331 clearClientDeadChannels(); 4332 4333 ClientInfo clientInfo = getClientInfo(m, false); 4334 4335 if (clientInfo == null) { 4336 return false; 4337 } 4338 4339 if (!clientInfo.mServList.add(servInfo)) { 4340 return false; 4341 } 4342 4343 if (!mWifiNative.p2pServiceAdd(servInfo)) { 4344 clientInfo.mServList.remove(servInfo); 4345 return false; 4346 } 4347 4348 return true; 4349 } 4350 removeLocalService(Messenger m, WifiP2pServiceInfo servInfo)4351 private void removeLocalService(Messenger m, WifiP2pServiceInfo servInfo) { 4352 if (m == null || servInfo == null) { 4353 Log.e(TAG, "Illegal arguments"); 4354 return; 4355 } 4356 4357 ClientInfo clientInfo = getClientInfo(m, false); 4358 if (clientInfo == null) { 4359 return; 4360 } 4361 4362 mWifiNative.p2pServiceDel(servInfo); 4363 clientInfo.mServList.remove(servInfo); 4364 } 4365 clearLocalServices(Messenger m)4366 private void clearLocalServices(Messenger m) { 4367 if (m == null) { 4368 Log.e(TAG, "Illegal argument(s)"); 4369 return; 4370 } 4371 4372 ClientInfo clientInfo = getClientInfo(m, false); 4373 if (clientInfo == null) { 4374 return; 4375 } 4376 4377 for (WifiP2pServiceInfo servInfo: clientInfo.mServList) { 4378 mWifiNative.p2pServiceDel(servInfo); 4379 } 4380 4381 clientInfo.mServList.clear(); 4382 } 4383 clearClientInfo(Messenger m)4384 private void clearClientInfo(Messenger m) { 4385 // update wpa_supplicant service info 4386 clearLocalServices(m); 4387 clearServiceRequests(m); 4388 // remove client from client list 4389 ClientInfo clientInfo = mClientInfoList.remove(m); 4390 if (clientInfo != null) { 4391 logd("Client:" + clientInfo.mPackageName + " is removed"); 4392 } 4393 } 4394 4395 /** 4396 * Send the service response to the WifiP2pManager.Channel. 4397 * @param WifiP2pServiceResponse response to service discovery 4398 */ sendServiceResponse(WifiP2pServiceResponse resp)4399 private void sendServiceResponse(WifiP2pServiceResponse resp) { 4400 if (resp == null) { 4401 Log.e(TAG, "sendServiceResponse with null response"); 4402 return; 4403 } 4404 for (ClientInfo c : mClientInfoList.values()) { 4405 WifiP2pServiceRequest req = c.mReqList.get(resp.getTransactionId()); 4406 if (req != null) { 4407 Message msg = Message.obtain(); 4408 msg.what = WifiP2pManager.RESPONSE_SERVICE; 4409 msg.arg1 = 0; 4410 msg.arg2 = 0; 4411 msg.obj = resp; 4412 if (c.mMessenger == null) { 4413 continue; 4414 } 4415 try { 4416 c.mMessenger.send(msg); 4417 } catch (RemoteException e) { 4418 if (mVerboseLoggingEnabled) logd("detect dead channel"); 4419 clearClientInfo(c.mMessenger); 4420 return; 4421 } 4422 } 4423 } 4424 } 4425 4426 /** 4427 * We don't get notifications of clients that have gone away. 4428 * We detect this actively when services are added and throw 4429 * them away. 4430 * 4431 * TODO: This can be done better with full async channels. 4432 */ clearClientDeadChannels()4433 private void clearClientDeadChannels() { 4434 ArrayList<Messenger> deadClients = new ArrayList<Messenger>(); 4435 4436 for (ClientInfo c : mClientInfoList.values()) { 4437 Message msg = Message.obtain(); 4438 msg.what = WifiP2pManager.PING; 4439 msg.arg1 = 0; 4440 msg.arg2 = 0; 4441 msg.obj = null; 4442 if (c.mMessenger == null) { 4443 continue; 4444 } 4445 try { 4446 c.mMessenger.send(msg); 4447 } catch (RemoteException e) { 4448 if (mVerboseLoggingEnabled) logd("detect dead channel"); 4449 deadClients.add(c.mMessenger); 4450 } 4451 } 4452 4453 for (Messenger m : deadClients) { 4454 clearClientInfo(m); 4455 } 4456 } 4457 4458 /** 4459 * Return the specified ClientInfo. 4460 * @param m Messenger 4461 * @param createIfNotExist if true and the specified channel info does not exist, 4462 * create new client info. 4463 * @return the specified ClientInfo. 4464 */ getClientInfo(Messenger m, boolean createIfNotExist)4465 private ClientInfo getClientInfo(Messenger m, boolean createIfNotExist) { 4466 ClientInfo clientInfo = mClientInfoList.get(m); 4467 4468 if (clientInfo == null && createIfNotExist) { 4469 if (mVerboseLoggingEnabled) logd("add a new client"); 4470 clientInfo = new ClientInfo(m); 4471 mClientInfoList.put(m, clientInfo); 4472 } 4473 4474 return clientInfo; 4475 } 4476 4477 /** 4478 * Enforces permissions on the caller who is requesting for P2p Peers 4479 * @param pkgName Package name of the caller 4480 * @param featureId Feature in the package of the caller 4481 * @param uid of the caller 4482 * @return WifiP2pDeviceList the peer list 4483 */ getPeers(String pkgName, @Nullable String featureId, int uid)4484 private WifiP2pDeviceList getPeers(String pkgName, @Nullable String featureId, int uid) { 4485 // getPeers() is guaranteed to be invoked after Wifi Service is up 4486 // This ensures getInstance() will return a non-null object now 4487 if (mWifiPermissionsUtil.checkCanAccessWifiDirect(pkgName, featureId, uid, true)) { 4488 return new WifiP2pDeviceList(mPeers); 4489 } else { 4490 return new WifiP2pDeviceList(); 4491 } 4492 } 4493 setPendingFactoryReset(boolean pending)4494 private void setPendingFactoryReset(boolean pending) { 4495 mSettingsConfigStore.put(WIFI_P2P_PENDING_FACTORY_RESET, pending); 4496 } 4497 isPendingFactoryReset()4498 private boolean isPendingFactoryReset() { 4499 return mSettingsConfigStore.get(WIFI_P2P_PENDING_FACTORY_RESET); 4500 } 4501 4502 /** 4503 * Enforces permissions on the caller who is requesting factory reset. 4504 * @param pkg Bundle containing the calling package string. 4505 * @param uid The caller uid. 4506 */ factoryReset(int uid)4507 private boolean factoryReset(int uid) { 4508 String pkgName = mContext.getPackageManager().getNameForUid(uid); 4509 UserManager userManager = mWifiInjector.getUserManager(); 4510 4511 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) return false; 4512 4513 if (userManager.hasUserRestrictionForUser( 4514 UserManager.DISALLOW_NETWORK_RESET, UserHandle.getUserHandleForUid(uid)) 4515 || userManager.hasUserRestrictionForUser( 4516 UserManager.DISALLOW_CONFIG_WIFI, UserHandle.getUserHandleForUid(uid))) { 4517 return false; 4518 } 4519 4520 Log.i(TAG, "factoryReset uid=" + uid + " pkg=" + pkgName); 4521 4522 if (mInterfaceName != null) { 4523 if (mWifiNative.p2pListNetworks(mGroups)) { 4524 for (WifiP2pGroup group : mGroups.getGroupList()) { 4525 mWifiNative.removeP2pNetwork(group.getNetworkId()); 4526 } 4527 } 4528 // reload will save native config and broadcast changed event. 4529 updatePersistentNetworks(true); 4530 setPendingFactoryReset(false); 4531 } else { 4532 setPendingFactoryReset(true); 4533 } 4534 return true; 4535 } 4536 4537 /** 4538 * Get calling package string from Client HashMap 4539 * 4540 * @param uid The uid of the caller package 4541 * @param replyMessenger AsyncChannel handler in caller 4542 */ getCallingPkgName(int uid, Messenger replyMessenger)4543 private String getCallingPkgName(int uid, Messenger replyMessenger) { 4544 ClientInfo clientInfo = mClientInfoList.get(replyMessenger); 4545 if (clientInfo != null) { 4546 return clientInfo.mPackageName; 4547 } 4548 if (uid == Process.SYSTEM_UID) return mContext.getOpPackageName(); 4549 return null; 4550 } 4551 4552 /** 4553 * Get calling feature id from Client HashMap 4554 * 4555 * @param uid The uid of the caller 4556 * @param replyMessenger AsyncChannel handler in caller 4557 */ getCallingFeatureId(int uid, Messenger replyMessenger)4558 private String getCallingFeatureId(int uid, Messenger replyMessenger) { 4559 ClientInfo clientInfo = mClientInfoList.get(replyMessenger); 4560 if (clientInfo != null) { 4561 return clientInfo.mFeatureId; 4562 } 4563 if (uid == Process.SYSTEM_UID) return mContext.getAttributionTag(); 4564 return null; 4565 } 4566 4567 /** 4568 * Clear all of p2p local service request/response for all p2p clients 4569 */ clearServicesForAllClients()4570 private void clearServicesForAllClients() { 4571 for (ClientInfo c : mClientInfoList.values()) { 4572 clearLocalServices(c.mMessenger); 4573 clearServiceRequests(c.mMessenger); 4574 } 4575 } 4576 selectGroupOwnerIntentIfNecessary(WifiP2pConfig config)4577 private int selectGroupOwnerIntentIfNecessary(WifiP2pConfig config) { 4578 int intent = config.groupOwnerIntent; 4579 // return the legacy default value for invalid values. 4580 if (intent != WifiP2pConfig.GROUP_OWNER_INTENT_AUTO) { 4581 if (intent < WifiP2pConfig.GROUP_OWNER_INTENT_MIN 4582 || intent > WifiP2pConfig.GROUP_OWNER_INTENT_MAX) { 4583 intent = DEFAULT_GROUP_OWNER_INTENT; 4584 } 4585 return intent; 4586 } 4587 4588 WifiManager wifiManager = mContext.getSystemService(WifiManager.class); 4589 4590 WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 4591 Log.d(TAG, "WifiInfo: " + wifiInfo); 4592 int freq = wifiInfo.getFrequency(); 4593 if (wifiInfo.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID) { 4594 intent = DEFAULT_GROUP_OWNER_INTENT + 1; 4595 } else if (ScanResult.is24GHz(freq)) { 4596 intent = WifiP2pConfig.GROUP_OWNER_INTENT_MIN; 4597 } else if (ScanResult.is5GHz(freq)) { 4598 // If both sides use the maximum, the negotiation would fail. 4599 intent = WifiP2pConfig.GROUP_OWNER_INTENT_MAX - 1; 4600 } else { 4601 intent = DEFAULT_GROUP_OWNER_INTENT; 4602 } 4603 Log.i(TAG, "change GO intent value from " 4604 + config.groupOwnerIntent + " to " + intent); 4605 return intent; 4606 } 4607 updateP2pChannels()4608 private boolean updateP2pChannels() { 4609 Log.d(TAG, "Set P2P listen channel to " + mUserListenChannel); 4610 if (!mWifiNative.p2pSetListenChannel(mUserListenChannel)) { 4611 Log.e(TAG, "Cannot set listen channel."); 4612 return false; 4613 } 4614 4615 Log.d(TAG, "Set P2P operating channel to " + mUserOperatingChannel 4616 + ", unsafe channels: " 4617 + mCoexUnsafeChannels.stream() 4618 .map(Object::toString).collect(Collectors.joining(","))); 4619 if (!mWifiNative.p2pSetOperatingChannel(mUserOperatingChannel, mCoexUnsafeChannels)) { 4620 Log.e(TAG, "Cannot set operate channel."); 4621 return false; 4622 } 4623 return true; 4624 } 4625 } 4626 4627 /** 4628 * Information about a particular client and we track the service discovery requests 4629 * and the local services registered by the client. 4630 */ 4631 private class ClientInfo { 4632 4633 // A reference to WifiP2pManager.Channel handler. 4634 // The response of this request is notified to WifiP2pManager.Channel handler 4635 private Messenger mMessenger; 4636 private String mPackageName; 4637 private @Nullable String mFeatureId; 4638 4639 4640 // A service discovery request list. 4641 private SparseArray<WifiP2pServiceRequest> mReqList; 4642 4643 // A local service information list. 4644 private List<WifiP2pServiceInfo> mServList; 4645 ClientInfo(Messenger m)4646 private ClientInfo(Messenger m) { 4647 mMessenger = m; 4648 mPackageName = null; 4649 mFeatureId = null; 4650 mReqList = new SparseArray(); 4651 mServList = new ArrayList<WifiP2pServiceInfo>(); 4652 } 4653 } 4654 4655 /** 4656 * Check that the UID has one of the following permissions: 4657 * {@link android.Manifest.permission.NETWORK_SETTINGS} 4658 * {@link android.Manifest.permission.NETWORK_STACK} 4659 * {@link android.Manifest.permission.OVERRIDE_WIFI_CONFIG} 4660 * 4661 * @param uid the UID to check 4662 * @return whether the UID has any of the above permissions 4663 */ checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission(int uid)4664 private boolean checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission(int uid) { 4665 return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 4666 || mWifiPermissionsUtil.checkNetworkStackPermission(uid) 4667 || mWifiPermissionsUtil.checkConfigOverridePermission(uid); 4668 } 4669 4670 /** 4671 * Check that the UID has one of the following permissions: 4672 * {@link android.Manifest.permission.NETWORK_SETTINGS} 4673 * {@link android.Manifest.permission.NETWORK_STACK} 4674 * {@link android.Manifest.permission.READ_WIFI_CREDENTIAL} 4675 * 4676 * @param uid the UID to check 4677 * @return whether the UID has any of the above permissions 4678 */ checkNetworkSettingsOrNetworkStackOrReadWifiCredentialPermission(int uid)4679 private boolean checkNetworkSettingsOrNetworkStackOrReadWifiCredentialPermission(int uid) { 4680 return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 4681 || mWifiPermissionsUtil.checkNetworkStackPermission(uid) 4682 || mWifiPermissionsUtil.checkReadWifiCredentialPermission(uid); 4683 } 4684 } 4685