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 android.net.wifi.p2p.WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP; 20 import static android.net.wifi.p2p.WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL; 21 22 import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTL; 23 import static com.android.net.module.util.Inet4AddressUtils.netmaskToPrefixLength; 24 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_DEVICE_ADDRESS; 25 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_DEVICE_NAME; 26 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_PENDING_FACTORY_RESET; 27 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; 28 29 import android.annotation.NonNull; 30 import android.annotation.Nullable; 31 import android.annotation.SuppressLint; 32 import android.app.AlertDialog; 33 import android.app.BroadcastOptions; 34 import android.content.AttributionSource; 35 import android.content.BroadcastReceiver; 36 import android.content.Context; 37 import android.content.Intent; 38 import android.content.IntentFilter; 39 import android.content.pm.PackageInfo; 40 import android.content.pm.PackageManager; 41 import android.content.res.Configuration; 42 import android.content.res.Resources; 43 import android.location.LocationManager; 44 import android.net.ConnectivityManager; 45 import android.net.DhcpResultsParcelable; 46 import android.net.InetAddresses; 47 import android.net.LinkAddress; 48 import android.net.LinkProperties; 49 import android.net.MacAddress; 50 import android.net.NetworkInfo; 51 import android.net.NetworkStack; 52 import android.net.StaticIpConfiguration; 53 import android.net.TetheringInterface; 54 import android.net.TetheringManager; 55 import android.net.TetheringManager.TetheringEventCallback; 56 import android.net.ip.IIpClient; 57 import android.net.ip.IpClientCallbacks; 58 import android.net.ip.IpClientUtil; 59 import android.net.shared.ProvisioningConfiguration; 60 import android.net.wifi.CoexUnsafeChannel; 61 import android.net.wifi.ScanResult; 62 import android.net.wifi.WifiConfiguration; 63 import android.net.wifi.WifiInfo; 64 import android.net.wifi.WifiManager; 65 import android.net.wifi.WpsInfo; 66 import android.net.wifi.p2p.IWifiP2pManager; 67 import android.net.wifi.p2p.WifiP2pConfig; 68 import android.net.wifi.p2p.WifiP2pDevice; 69 import android.net.wifi.p2p.WifiP2pDeviceList; 70 import android.net.wifi.p2p.WifiP2pGroup; 71 import android.net.wifi.p2p.WifiP2pGroupList; 72 import android.net.wifi.p2p.WifiP2pGroupList.GroupDeleteListener; 73 import android.net.wifi.p2p.WifiP2pInfo; 74 import android.net.wifi.p2p.WifiP2pManager; 75 import android.net.wifi.p2p.WifiP2pManager.ExternalApproverRequestListener; 76 import android.net.wifi.p2p.WifiP2pProvDiscEvent; 77 import android.net.wifi.p2p.WifiP2pWfdInfo; 78 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; 79 import android.net.wifi.p2p.nsd.WifiP2pServiceRequest; 80 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; 81 import android.os.Binder; 82 import android.os.Build; 83 import android.os.Bundle; 84 import android.os.Handler; 85 import android.os.HandlerThread; 86 import android.os.IBinder; 87 import android.os.Looper; 88 import android.os.Message; 89 import android.os.Messenger; 90 import android.os.ParcelFileDescriptor; 91 import android.os.Process; 92 import android.os.RemoteException; 93 import android.os.SystemClock; 94 import android.os.UserHandle; 95 import android.os.UserManager; 96 import android.os.WorkSource; 97 import android.provider.Settings; 98 import android.text.TextUtils; 99 import android.util.Log; 100 import android.util.SparseArray; 101 import android.view.Display; 102 import android.view.KeyEvent; 103 import android.view.LayoutInflater; 104 import android.view.View; 105 import android.view.ViewGroup; 106 import android.view.WindowManager; 107 import android.widget.EditText; 108 import android.widget.TextView; 109 110 import androidx.annotation.RequiresApi; 111 112 import com.android.internal.annotations.VisibleForTesting; 113 import com.android.internal.util.AsyncChannel; 114 import com.android.internal.util.Protocol; 115 import com.android.internal.util.State; 116 import com.android.internal.util.StateMachine; 117 import com.android.internal.util.WakeupMessage; 118 import com.android.modules.utils.build.SdkLevel; 119 import com.android.server.wifi.BuildProperties; 120 import com.android.server.wifi.Clock; 121 import com.android.server.wifi.FrameworkFacade; 122 import com.android.server.wifi.HalDeviceManager; 123 import com.android.server.wifi.InterfaceConflictManager; 124 import com.android.server.wifi.WifiDialogManager; 125 import com.android.server.wifi.WifiGlobals; 126 import com.android.server.wifi.WifiInjector; 127 import com.android.server.wifi.WifiSettingsConfigStore; 128 import com.android.server.wifi.WifiThreadRunner; 129 import com.android.server.wifi.coex.CoexManager; 130 import com.android.server.wifi.p2p.ExternalApproverManager.ApproverEntry; 131 import com.android.server.wifi.proto.nano.WifiMetricsProto; 132 import com.android.server.wifi.proto.nano.WifiMetricsProto.GroupEvent; 133 import com.android.server.wifi.proto.nano.WifiMetricsProto.P2pConnectionEvent; 134 import com.android.server.wifi.util.LastCallerInfoManager; 135 import com.android.server.wifi.util.NetdWrapper; 136 import com.android.server.wifi.util.StringUtil; 137 import com.android.server.wifi.util.WaitingState; 138 import com.android.server.wifi.util.WifiPermissionsUtil; 139 import com.android.server.wifi.util.WifiPermissionsWrapper; 140 import com.android.wifi.resources.R; 141 142 import java.io.FileDescriptor; 143 import java.io.PrintWriter; 144 import java.net.Inet4Address; 145 import java.net.Inet6Address; 146 import java.net.InetAddress; 147 import java.net.NetworkInterface; 148 import java.net.SocketException; 149 import java.net.UnknownHostException; 150 import java.nio.ByteBuffer; 151 import java.nio.CharBuffer; 152 import java.nio.charset.Charset; 153 import java.nio.charset.CharsetDecoder; 154 import java.nio.charset.CodingErrorAction; 155 import java.nio.charset.StandardCharsets; 156 import java.util.ArrayList; 157 import java.util.Collection; 158 import java.util.Enumeration; 159 import java.util.HashMap; 160 import java.util.HashSet; 161 import java.util.List; 162 import java.util.Map; 163 import java.util.Objects; 164 import java.util.Set; 165 import java.util.concurrent.ConcurrentHashMap; 166 import java.util.stream.Collectors; 167 168 /** 169 * WifiP2pService includes a state machine to perform Wi-Fi p2p operations. Applications 170 * communicate with this service to issue device discovery and connectivity requests 171 * through the WifiP2pManager interface. The state machine communicates with the wifi 172 * driver through wpa_supplicant and handles the event responses through WifiMonitor. 173 * 174 * Note that the term Wifi when used without a p2p suffix refers to the client mode 175 * of Wifi operation 176 * @hide 177 */ 178 public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { 179 private static final String TAG = "WifiP2pService"; 180 @VisibleForTesting 181 public static final String P2P_IDLE_SHUTDOWN_MESSAGE_TIMEOUT_TAG = TAG 182 + " Idle Shutdown Message Timeout"; 183 private boolean mVerboseLoggingEnabled = false; 184 private boolean mVerboseHalLoggingEnabled = false; 185 private static final String NETWORK_TYPE = "WIFI_P2P"; 186 @VisibleForTesting 187 static final String DEFAULT_DEVICE_NAME_PREFIX = "Android_"; 188 // The maxinum length of the device name is 32 bytes, see 189 // Section 4.1.15 in Wi-Fi Direct Specification v1 and 190 // Section 12 in Wi-Fi Protected Setup Specification v2. 191 @VisibleForTesting 192 static final int DEVICE_NAME_LENGTH_MAX = 32; 193 @VisibleForTesting 194 static final int DEVICE_NAME_POSTFIX_LENGTH_MIN = 4; 195 @VisibleForTesting 196 static final int DEVICE_NAME_PREFIX_LENGTH_MAX = 197 DEVICE_NAME_LENGTH_MAX - DEVICE_NAME_POSTFIX_LENGTH_MIN; 198 @VisibleForTesting 199 static final int DEFAULT_GROUP_OWNER_INTENT = 6; 200 // The maximum length of a group name is the same as SSID, i.e. 32 bytes. 201 // Wi-Fi Direct group name starts with "DIRECT-xy-" where xy is two ASCII characters 202 // randomly selected, so there are 10 bytes occupied. 203 @VisibleForTesting 204 static final int GROUP_NAME_POSTFIX_LENGTH_MAX = 22; 205 206 @VisibleForTesting 207 // It requires to over "DISCOVER_TIMEOUT_S(120)" or "GROUP_CREATING_WAIT_TIME_MS(120)". 208 // Otherwise it will cause interface down before function timeout. 209 static final long P2P_INTERFACE_IDLE_SHUTDOWN_TIMEOUT_MS = 150_000; 210 211 private final Context mContext; 212 213 NetdWrapper mNetdWrapper; 214 private IIpClient mIpClient; 215 private int mIpClientStartIndex = 0; 216 private DhcpResultsParcelable mDhcpResultsParcelable; 217 218 private final P2pStateMachine mP2pStateMachine; 219 private final AsyncChannel mReplyChannel = new AsyncChannel(); 220 private AsyncChannel mWifiChannel; 221 private final WifiInjector mWifiInjector; 222 private final WifiPermissionsUtil mWifiPermissionsUtil; 223 private final FrameworkFacade mFrameworkFacade; 224 private final WifiSettingsConfigStore mSettingsConfigStore; 225 private final WifiP2pMetrics mWifiP2pMetrics; 226 private final BuildProperties mBuildProperties; 227 // This will only be null if SdkLevel is not at least S 228 @Nullable private final CoexManager mCoexManager; 229 private final WifiGlobals mWifiGlobals; 230 private final UserManager mUserManager; 231 private final InterfaceConflictManager mInterfaceConflictManager; 232 private TetheringManager mTetheringManager = null; 233 private final WifiP2pNative mWifiNative; 234 private final LastCallerInfoManager mLastCallerInfoManager; 235 private HalDeviceManager mHalDeviceManager; 236 237 private static final Boolean JOIN_GROUP = true; 238 private static final Boolean FORM_GROUP = false; 239 240 private static final Boolean RELOAD = true; 241 private static final Boolean NO_RELOAD = false; 242 243 private static final String[] RECEIVER_PERMISSIONS_FOR_BROADCAST = { 244 android.Manifest.permission.ACCESS_FINE_LOCATION, 245 android.Manifest.permission.ACCESS_WIFI_STATE 246 }; 247 248 private static final String[] RECEIVER_PERMISSIONS_FOR_BROADCAST_LOCATION_OFF = { 249 android.Manifest.permission.NETWORK_SETTINGS, 250 android.Manifest.permission.ACCESS_FINE_LOCATION, 251 android.Manifest.permission.ACCESS_WIFI_STATE 252 }; 253 254 // Maximum number of bytes allowed for a network name, i.e. SSID. 255 private static final int MAX_NETWORK_NAME_BYTES = 32; 256 // Minimum number of bytes for a network name, i.e. DIRECT-xy. 257 private static final int MIN_NETWORK_NAME_BYTES = 9; 258 259 // Two minutes comes from the wpa_supplicant setting 260 private static final int GROUP_CREATING_WAIT_TIME_MS = 120 * 1000; 261 private static int sGroupCreatingTimeoutIndex = 0; 262 263 private static final int DISABLE_P2P_WAIT_TIME_MS = 5 * 1000; 264 private static int sDisableP2pTimeoutIndex = 0; 265 266 // Set a two minute discover timeout to avoid STA scans from being blocked 267 private static final int DISCOVER_TIMEOUT_S = 120; 268 269 // Idle time after a peer is gone when the group is torn down 270 private static final int GROUP_IDLE_TIME_S = 10; 271 272 private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE; 273 274 // Delayed message to timeout group creation 275 public static final int GROUP_CREATING_TIMED_OUT = BASE + 1; 276 277 // User accepted a peer request 278 private static final int PEER_CONNECTION_USER_ACCEPT = BASE + 2; 279 // User rejected a peer request 280 @VisibleForTesting 281 static final int PEER_CONNECTION_USER_REJECT = BASE + 3; 282 // User wants to disconnect wifi in favour of p2p 283 private static final int DROP_WIFI_USER_ACCEPT = BASE + 4; 284 // User wants to keep his wifi connection and drop p2p 285 @VisibleForTesting 286 static final int DROP_WIFI_USER_REJECT = BASE + 5; 287 // Delayed message to timeout p2p disable 288 public static final int DISABLE_P2P_TIMED_OUT = BASE + 6; 289 // User confirm a peer request 290 public static final int PEER_CONNECTION_USER_CONFIRM = BASE + 7; 291 292 // Commands to the ClientModeImpl 293 public static final int P2P_CONNECTION_CHANGED = BASE + 11; 294 295 // These commands are used to temporarily disconnect wifi when we detect 296 // a frequency conflict which would make it impossible to have with p2p 297 // and wifi active at the same time. 298 // If the user chooses to disable wifi temporarily, we keep wifi disconnected 299 // until the p2p connection is done and terminated at which point we will 300 // bring back wifi up 301 // DISCONNECT_WIFI_REQUEST 302 // msg.arg1 = 1 enables temporary disconnect and 0 disables it. 303 public static final int DISCONNECT_WIFI_REQUEST = BASE + 12; 304 public static final int DISCONNECT_WIFI_RESPONSE = BASE + 13; 305 306 public static final int SET_MIRACAST_MODE = BASE + 14; 307 308 // During dhcp (and perhaps other times) we can't afford to drop packets 309 // but Discovery will switch our channel enough we will. 310 // msg.arg1 = ENABLED for blocking, DISABLED for resumed. 311 // msg.arg2 = msg to send when blocked 312 // msg.obj = StateMachine to send to when blocked 313 public static final int BLOCK_DISCOVERY = BASE + 15; 314 public static final int ENABLE_P2P = BASE + 16; 315 public static final int DISABLE_P2P = BASE + 17; 316 public static final int REMOVE_CLIENT_INFO = BASE + 18; 317 // idle shutdown message 318 public static final int CMD_P2P_IDLE_SHUTDOWN = BASE + 19; 319 320 // Messages for interaction with IpClient. 321 private static final int IPC_PRE_DHCP_ACTION = BASE + 30; 322 private static final int IPC_POST_DHCP_ACTION = BASE + 31; 323 private static final int IPC_DHCP_RESULTS = BASE + 32; 324 private static final int IPC_PROVISIONING_SUCCESS = BASE + 33; 325 private static final int IPC_PROVISIONING_FAILURE = BASE + 34; 326 @VisibleForTesting 327 static final int TETHER_INTERFACE_STATE_CHANGED = BASE + 35; 328 329 private static final int UPDATE_P2P_DISALLOWED_CHANNELS = BASE + 36; 330 331 public static final int ENABLED = 1; 332 public static final int DISABLED = 0; 333 334 private static final int P2P_CONNECT_TRIGGER_GROUP_NEG_REQ = 1; 335 private static final int P2P_CONNECT_TRIGGER_INVITATION_REQ = 2; 336 private static final int P2P_CONNECT_TRIGGER_OTHER = 3; 337 338 private final boolean mP2pSupported; 339 340 private final WifiP2pDevice mThisDevice = new WifiP2pDevice(); 341 342 // To avoid changing the default name on every initialization, preserve it 343 // in a period if this device is not rebooted. 344 private String mDefaultDeviceName = null; 345 private long mLastDefaultDeviceNameGeneratingTimeMillis = 0L; 346 // Keep the default name in 24 hours. 347 @VisibleForTesting 348 static final long DEFAULT_DEVICE_NAME_LIFE_TIME_MILLIS = 24 * 60 * 60 * 1000; 349 350 // When a group has been explicitly created by an app, we persist the group 351 // even after all clients have been disconnected until an explicit remove 352 // is invoked 353 private boolean mAutonomousGroup; 354 355 // Invitation to join an existing p2p group 356 private boolean mJoinExistingGroup; 357 358 // Track whether we are in p2p discovery. This is used to avoid sending duplicate 359 // broadcasts 360 private boolean mDiscoveryStarted; 361 362 // Track whether servcice/peer discovery is blocked in favor of other wifi actions 363 // (notably dhcp) 364 private boolean mDiscoveryBlocked; 365 366 // remember if we were in a scan when it had to be stopped 367 private boolean mDiscoveryPostponed = false; 368 369 // Track whether we are in p2p listen. This is used to avoid sending duplicate broadcasts 370 private boolean mListenStarted; 371 372 // Track whether DISALLOW_WIFI_DIRECT user restriction has been set 373 private boolean mIsP2pDisallowedByAdmin = false; 374 375 // Track the last p2p availability state that was broadcasted 376 private boolean mLastP2pState = false; 377 378 private NetworkInfo.DetailedState mDetailedState; 379 380 private boolean mTemporarilyDisconnectedWifi = false; 381 382 // The transaction Id of service discovery request 383 private int mServiceTransactionId = 0; 384 385 // Service discovery request ID of wpa_supplicant. 386 // null means it's not set yet. 387 private String mServiceDiscReqId; 388 389 // clients(application) information list 390 private final HashMap<Messenger, ClientInfo> mClientInfoList = new HashMap<>(); 391 392 // clients(application) channel list 393 private final Map<IBinder, Messenger> mClientChannelList = new HashMap<>(); 394 395 // clients(application) approver manager 396 private final ExternalApproverManager mExternalApproverManager = new ExternalApproverManager(); 397 398 // client(application) attribution source list 399 private Map<IBinder, AttributionSource> mClientAttributionSource = new HashMap<>(); 400 401 // client(application) vendor-specific information element list 402 private final Map<String, HashSet<ScanResult.InformationElement>> mVendorElements = 403 new HashMap<>(); 404 405 // peer authorizing timestamp which is indexed by the peer MAC address. 406 private final Map<String, Long> mPeerAuthorizingTimestamp = new HashMap<>(); 407 408 // The empty device address set by wpa_supplicant. 409 private static final String EMPTY_DEVICE_ADDRESS = "00:00:00:00:00:00"; 410 411 // An anonymized device address. This is used instead of the own device MAC to prevent the 412 // latter from leaking to apps 413 private static final String ANONYMIZED_DEVICE_ADDRESS = "02:00:00:00:00:00"; 414 415 // Idle shut down 416 @VisibleForTesting 417 public WakeupMessage mP2pIdleShutdownMessage; 418 419 private WifiP2pConfig mSavedRejectedPeerConfig = null; 420 421 private boolean mIsBootComplete; 422 423 // Constants for configuring P2P GO IP Address Allocation in EAPOL-Key Frames (4-Way Handshake) 424 // when device overlay config_wifiP2pGoIpAddressAllocationInEapolFrames is set to True 425 @VisibleForTesting 426 static final String GO_EAPOL_IP_ADDRESS = "192.168.49.1"; 427 @VisibleForTesting 428 static final String GO_EAPOL_IP_SUBNET_MASK = "255.255.255.0"; 429 // The default P2P GO IP address range reserved for IP assignment in EAPOL frame 430 // when device overlay config_wifiP2pGoEapolIpAddressRangeStart and 431 // config_wifiP2pGoEapolIpAddressRangeEnd is not configured in device overlay. 432 @VisibleForTesting 433 static final String GO_EAPOL_IP_RANGE_DEFAULT_START_ADDRESS = "192.168.49.128"; 434 @VisibleForTesting 435 static final String GO_EAPOL_IP_RANGE_DEFAULT_END_ADDRESS = "192.168.49.254"; 436 437 /** 438 * Error code definition. 439 * see the Table.8 in the WiFi Direct specification for the detail. 440 */ 441 public enum P2pStatus { 442 // Success 443 SUCCESS, 444 445 // The target device is currently unavailable 446 INFORMATION_IS_CURRENTLY_UNAVAILABLE, 447 448 // Protocol error 449 INCOMPATIBLE_PARAMETERS, 450 451 // The target device reached the limit of the number of the connectable device. 452 // For example, device limit or group limit is set 453 LIMIT_REACHED, 454 455 // Protocol error 456 INVALID_PARAMETER, 457 458 // Unable to accommodate request 459 UNABLE_TO_ACCOMMODATE_REQUEST, 460 461 // Previous protocol error, or disruptive behavior 462 PREVIOUS_PROTOCOL_ERROR, 463 464 // There is no common channels the both devices can use 465 NO_COMMON_CHANNEL, 466 467 // Unknown p2p group. For example, Device A tries to invoke the previous persistent group, 468 // but device B has removed the specified credential already 469 UNKNOWN_P2P_GROUP, 470 471 // Both p2p devices indicated an intent of 15 in group owner negotiation 472 BOTH_GO_INTENT_15, 473 474 // Incompatible provisioning method 475 INCOMPATIBLE_PROVISIONING_METHOD, 476 477 // Rejected by user 478 REJECTED_BY_USER, 479 480 // Unknown error 481 UNKNOWN; 482 483 /** 484 * Returns P2p status corresponding to a given error value 485 * @param error integer error value 486 * @return P2pStatus enum for value 487 */ valueOf(int error)488 public static P2pStatus valueOf(int error) { 489 switch(error) { 490 case 0 : 491 return SUCCESS; 492 case 1: 493 return INFORMATION_IS_CURRENTLY_UNAVAILABLE; 494 case 2: 495 return INCOMPATIBLE_PARAMETERS; 496 case 3: 497 return LIMIT_REACHED; 498 case 4: 499 return INVALID_PARAMETER; 500 case 5: 501 return UNABLE_TO_ACCOMMODATE_REQUEST; 502 case 6: 503 return PREVIOUS_PROTOCOL_ERROR; 504 case 7: 505 return NO_COMMON_CHANNEL; 506 case 8: 507 return UNKNOWN_P2P_GROUP; 508 case 9: 509 return BOTH_GO_INTENT_15; 510 case 10: 511 return INCOMPATIBLE_PROVISIONING_METHOD; 512 case 11: 513 return REJECTED_BY_USER; 514 default: 515 return UNKNOWN; 516 } 517 } 518 } 519 520 /** 521 * Proxy for the final native call of the parent class. Enables mocking of 522 * the function. 523 */ getMockableCallingUid()524 public int getMockableCallingUid() { 525 return Binder.getCallingUid(); 526 } 527 updateWorkSourceByUid(int uid, boolean active)528 private void updateWorkSourceByUid(int uid, boolean active) { 529 if (uid == -1) return; 530 if (active == mActiveClients.containsKey(uid)) return; 531 Log.d(TAG, "Update WorkSource UID=" + uid + " active=" + active); 532 533 if (!active) mActiveClients.remove(uid); 534 // The worksource is based on UID, just find the first one. 535 DeathHandlerData dhd = mDeathDataByBinder.values().stream() 536 .filter(d -> d.mUid == uid) 537 .findAny() 538 .orElse(null); 539 if (active && null == dhd) { 540 Log.w(TAG, "No WorkSource for UID " + uid); 541 return; 542 } 543 544 if (null != dhd) { 545 mActiveClients.put(uid, dhd.mWorkSource); 546 } 547 // If p2p is off, the first one activates P2P will merge all worksources. 548 // If p2p is already on, send ENABLE_P2P to merge the new worksource. 549 if (mP2pStateMachine.isP2pDisabled()) return; 550 mP2pStateMachine.sendMessage(ENABLE_P2P); 551 } 552 553 /** 554 * Handles client connections 555 */ 556 private class ClientHandler extends Handler { 557 ClientHandler(String tag, Looper looper)558 ClientHandler(String tag, Looper looper) { 559 super(looper); 560 } 561 562 @Override handleMessage(Message msg)563 public void handleMessage(Message msg) { 564 super.handleMessage(msg); 565 switch (msg.what) { 566 case WifiP2pManager.SET_DEVICE_NAME: 567 case WifiP2pManager.SET_WFD_INFO: 568 case WifiP2pManager.DISCOVER_PEERS: 569 case WifiP2pManager.STOP_DISCOVERY: 570 case WifiP2pManager.CONNECT: 571 case WifiP2pManager.CANCEL_CONNECT: 572 case WifiP2pManager.CREATE_GROUP: 573 case WifiP2pManager.REMOVE_GROUP: 574 case WifiP2pManager.START_LISTEN: 575 case WifiP2pManager.STOP_LISTEN: 576 case WifiP2pManager.SET_CHANNEL: 577 case WifiP2pManager.START_WPS: 578 case WifiP2pManager.ADD_LOCAL_SERVICE: 579 case WifiP2pManager.REMOVE_LOCAL_SERVICE: 580 case WifiP2pManager.CLEAR_LOCAL_SERVICES: 581 case WifiP2pManager.DISCOVER_SERVICES: 582 case WifiP2pManager.ADD_SERVICE_REQUEST: 583 case WifiP2pManager.REMOVE_SERVICE_REQUEST: 584 case WifiP2pManager.CLEAR_SERVICE_REQUESTS: 585 case WifiP2pManager.REQUEST_PEERS: 586 case WifiP2pManager.REQUEST_CONNECTION_INFO: 587 case WifiP2pManager.REQUEST_GROUP_INFO: 588 case WifiP2pManager.DELETE_PERSISTENT_GROUP: 589 case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO: 590 case WifiP2pManager.FACTORY_RESET: 591 case WifiP2pManager.SET_ONGOING_PEER_CONFIG: 592 case WifiP2pManager.REQUEST_ONGOING_PEER_CONFIG: 593 case WifiP2pManager.REQUEST_P2P_STATE: 594 case WifiP2pManager.REQUEST_DISCOVERY_STATE: 595 case WifiP2pManager.GET_LISTEN_STATE: 596 case WifiP2pManager.REQUEST_NETWORK_INFO: 597 case WifiP2pManager.UPDATE_CHANNEL_INFO: 598 case WifiP2pManager.REQUEST_DEVICE_INFO: 599 case WifiP2pManager.REMOVE_CLIENT: 600 case WifiP2pManager.ADD_EXTERNAL_APPROVER: 601 case WifiP2pManager.REMOVE_EXTERNAL_APPROVER: 602 case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: 603 case WifiP2pManager.SET_VENDOR_ELEMENTS: 604 mP2pStateMachine.sendMessage(Message.obtain(msg)); 605 break; 606 default: 607 Log.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg); 608 break; 609 } 610 } 611 } 612 private final ClientHandler mClientHandler; 613 makeNetworkInfo()614 private NetworkInfo makeNetworkInfo() { 615 final NetworkInfo info = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 616 0, NETWORK_TYPE, ""); 617 if (mDetailedState != NetworkInfo.DetailedState.IDLE) { 618 info.setDetailedState(mDetailedState, null, null); 619 } 620 return info; 621 } 622 623 private static class DeathHandlerData { DeathHandlerData(int uid, DeathRecipient dr, Messenger m, WorkSource ws, int displayId)624 DeathHandlerData(int uid, DeathRecipient dr, Messenger m, WorkSource ws, int displayId) { 625 mUid = uid; 626 mDeathRecipient = dr; 627 mMessenger = m; 628 mWorkSource = ws; 629 mDisplayId = displayId; 630 } 631 632 @Override toString()633 public String toString() { 634 return "mUid=" + mUid + ", deathRecipient=" + mDeathRecipient + ", messenger=" 635 + mMessenger + ", worksource=" + mWorkSource + ", displayId=" + mDisplayId; 636 } 637 638 final int mUid; 639 final DeathRecipient mDeathRecipient; 640 final Messenger mMessenger; 641 final WorkSource mWorkSource; 642 final int mDisplayId; 643 } 644 private final Object mLock = new Object(); 645 private final Map<IBinder, DeathHandlerData> mDeathDataByBinder = new ConcurrentHashMap<>(); 646 private final Map<Integer, WorkSource> mActiveClients = new ConcurrentHashMap<>(); 647 648 private final Clock mClock; 649 WifiP2pServiceImpl(Context context, WifiInjector wifiInjector)650 public WifiP2pServiceImpl(Context context, WifiInjector wifiInjector) { 651 mContext = context; 652 mWifiInjector = wifiInjector; 653 mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil(); 654 mFrameworkFacade = mWifiInjector.getFrameworkFacade(); 655 mSettingsConfigStore = mWifiInjector.getSettingsConfigStore(); 656 mWifiP2pMetrics = mWifiInjector.getWifiP2pMetrics(); 657 mCoexManager = mWifiInjector.getCoexManager(); 658 mWifiGlobals = mWifiInjector.getWifiGlobals(); 659 mBuildProperties = mWifiInjector.getBuildProperties(); 660 mUserManager = mWifiInjector.getUserManager(); 661 mInterfaceConflictManager = mWifiInjector.getInterfaceConflictManager(); 662 mClock = mWifiInjector.getClock(); 663 664 mDetailedState = NetworkInfo.DetailedState.IDLE; 665 666 mP2pSupported = mContext.getPackageManager().hasSystemFeature( 667 PackageManager.FEATURE_WIFI_DIRECT); 668 669 HandlerThread wifiP2pThread = mWifiInjector.getWifiP2pServiceHandlerThread(); 670 mClientHandler = new ClientHandler(TAG, wifiP2pThread.getLooper()); 671 mWifiNative = mWifiInjector.getWifiP2pNative(); 672 mLastCallerInfoManager = mWifiInjector.getLastCallerInfoManager(); 673 mHalDeviceManager = mWifiInjector.getHalDeviceManager(); 674 mP2pStateMachine = new P2pStateMachine(TAG, wifiP2pThread.getLooper(), mP2pSupported); 675 mP2pStateMachine.setDbg(false); // can enable for very verbose logs 676 mP2pStateMachine.start(); 677 } 678 679 /** 680 * Obtains the service interface for Managements services 681 */ connectivityServiceReady()682 public void connectivityServiceReady() { 683 mNetdWrapper = mWifiInjector.makeNetdWrapper(); 684 } 685 686 /** Indicate that boot is completed. */ handleBootCompleted()687 public void handleBootCompleted() { 688 updateVerboseLoggingEnabled(); 689 mIsBootComplete = true; 690 mTetheringManager = mContext.getSystemService(TetheringManager.class); 691 if (mTetheringManager == null) { 692 Log.wtf(TAG, "Tethering manager is null when WifiP2pServiceImp handles boot completed"); 693 } 694 String deviceAddress = mSettingsConfigStore.get(WIFI_P2P_DEVICE_ADDRESS); 695 if (!mWifiGlobals.isP2pMacRandomizationSupported() && !TextUtils.isEmpty(deviceAddress)) { 696 mThisDevice.deviceAddress = deviceAddress; 697 } 698 String deviceName = mSettingsConfigStore.get(WIFI_P2P_DEVICE_NAME); 699 if (!TextUtils.isEmpty(deviceName)) { 700 mThisDevice.deviceName = deviceName; 701 } 702 } 703 updateVerboseLoggingEnabled()704 private void updateVerboseLoggingEnabled() { 705 final int verboseAlwaysOnLevel = mContext.getResources().getInteger( 706 R.integer.config_wifiVerboseLoggingAlwaysOnLevel); 707 mVerboseLoggingEnabled = mFrameworkFacade.isVerboseLoggingAlwaysOn(verboseAlwaysOnLevel, 708 mBuildProperties) || mVerboseHalLoggingEnabled; 709 } 710 enforceAccessPermission()711 private void enforceAccessPermission() { 712 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, 713 "WifiP2pService"); 714 } 715 enforceChangePermission()716 private void enforceChangePermission() { 717 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, 718 "WifiP2pService"); 719 } 720 checkAnyPermissionOf(String... permissions)721 private boolean checkAnyPermissionOf(String... permissions) { 722 for (String permission : permissions) { 723 if (mContext.checkCallingOrSelfPermission(permission) 724 == PackageManager.PERMISSION_GRANTED) { 725 return true; 726 } 727 } 728 return false; 729 } 730 enforceAnyPermissionOf(String... permissions)731 private void enforceAnyPermissionOf(String... permissions) { 732 if (!checkAnyPermissionOf(permissions)) { 733 throw new SecurityException("Requires one of the following permissions: " 734 + String.join(", ", permissions) + "."); 735 } 736 } 737 enforceNetworkStackOrLocationHardwarePermission()738 private void enforceNetworkStackOrLocationHardwarePermission() { 739 enforceAnyPermissionOf( 740 android.Manifest.permission.LOCATION_HARDWARE, 741 android.Manifest.permission.NETWORK_STACK, 742 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); 743 } 744 stopIpClient()745 private void stopIpClient() { 746 // Invalidate all previous start requests 747 mIpClientStartIndex++; 748 if (mIpClient != null) { 749 try { 750 mIpClient.shutdown(); 751 } catch (RemoteException e) { 752 e.rethrowFromSystemServer(); 753 } 754 mIpClient = null; 755 } 756 mDhcpResultsParcelable = null; 757 } 758 startIpClient(String ifname, Handler smHandler, int groupClientIpProvisioningMode, WifiP2pGroup.P2pGroupClientEapolIpAddressData p2pClientEapolIpInfo)759 private void startIpClient(String ifname, Handler smHandler, 760 int groupClientIpProvisioningMode, 761 WifiP2pGroup.P2pGroupClientEapolIpAddressData p2pClientEapolIpInfo) { 762 stopIpClient(); 763 mIpClientStartIndex++; 764 IpClientUtil.makeIpClient(mContext, ifname, new IpClientCallbacksImpl( 765 mIpClientStartIndex, smHandler, groupClientIpProvisioningMode, 766 p2pClientEapolIpInfo)); 767 } 768 makeStaticIpConfigurationFromEapolIpAddressInfo( WifiP2pGroup.P2pGroupClientEapolIpAddressData p2pClientEapolIpInfo)769 private StaticIpConfiguration makeStaticIpConfigurationFromEapolIpAddressInfo( 770 WifiP2pGroup.P2pGroupClientEapolIpAddressData p2pClientEapolIpInfo) { 771 try { 772 final Inet4Address addressGo = p2pClientEapolIpInfo.mIpAddressGo; 773 final Inet4Address addressClient = p2pClientEapolIpInfo.mIpAddressClient; 774 final Inet4Address addressMask = p2pClientEapolIpInfo.mIpAddressMask; 775 final LinkAddress linkAddressClient = new LinkAddress(addressClient, 776 netmaskToPrefixLength(addressMask)); 777 778 final StaticIpConfiguration staticIpConfig = new StaticIpConfiguration.Builder() 779 .setIpAddress(linkAddressClient) 780 .setGateway(addressGo).build(); 781 if (mVerboseLoggingEnabled) { 782 Log.i(TAG, "IP Addresses obtained via EAPOL H/S - CLIENT: " 783 + addressClient.getHostAddress() 784 + ", GO: " + addressGo.getHostAddress() + " MASK: " 785 + addressMask.getHostAddress()); 786 } 787 return staticIpConfig; 788 } catch (Exception e) { 789 Log.e(TAG, "Failed to build EAPOL static IP configuration: " + e); 790 return null; 791 } 792 } 793 794 private class IpClientCallbacksImpl extends IpClientCallbacks { 795 private final int mStartIndex; 796 private final Handler mHandler; 797 private final int mGroupClientIpProvisioningMode; 798 private WifiP2pGroup.P2pGroupClientEapolIpAddressData mP2pClientEapolIpInfo; 799 IpClientCallbacksImpl(int startIndex, Handler handler, int groupClientIpProvisioningMode, WifiP2pGroup.P2pGroupClientEapolIpAddressData p2pClientEapolIpInfo)800 private IpClientCallbacksImpl(int startIndex, Handler handler, 801 int groupClientIpProvisioningMode, 802 WifiP2pGroup.P2pGroupClientEapolIpAddressData p2pClientEapolIpInfo) { 803 mStartIndex = startIndex; 804 mHandler = handler; 805 mGroupClientIpProvisioningMode = groupClientIpProvisioningMode; 806 mP2pClientEapolIpInfo = p2pClientEapolIpInfo; 807 } 808 809 @Override onIpClientCreated(IIpClient ipClient)810 public void onIpClientCreated(IIpClient ipClient) { 811 mHandler.post(() -> { 812 if (mIpClientStartIndex != mStartIndex) { 813 // This start request is obsolete 814 return; 815 } 816 mIpClient = ipClient; 817 818 ProvisioningConfiguration config = null; 819 switch (mGroupClientIpProvisioningMode) { 820 case GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL: 821 config = new ProvisioningConfiguration.Builder() 822 .withoutIPv4() 823 .withIpv6LinkLocalOnly() 824 .withRandomMacAddress() 825 .withUniqueEui64AddressesOnly() 826 .build(); 827 break; 828 case GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP: 829 default: 830 // DHCP IPV4 by default. 831 if (mP2pClientEapolIpInfo != null) { 832 // Start provisioning with IP address received via EAPOL-Key exchange 833 final StaticIpConfiguration staticIpConfig = 834 makeStaticIpConfigurationFromEapolIpAddressInfo( 835 mP2pClientEapolIpInfo); 836 if (staticIpConfig != null) { 837 config = new ProvisioningConfiguration.Builder() 838 .withoutIpReachabilityMonitor() 839 .withStaticConfiguration(staticIpConfig).build(); 840 } 841 } 842 if (config == null) { 843 // start DHCP provisioning 844 config = new ProvisioningConfiguration.Builder() 845 .withoutIpReachabilityMonitor() 846 .withPreDhcpAction(30 * 1000) 847 .withProvisioningTimeoutMs(36 * 1000) 848 .build(); 849 } 850 } 851 852 try { 853 mIpClient.startProvisioning(config.toStableParcelable()); 854 } catch (RemoteException e) { 855 e.rethrowFromSystemServer(); 856 } 857 }); 858 } 859 860 @Override onPreDhcpAction()861 public void onPreDhcpAction() { 862 mP2pStateMachine.sendMessage(IPC_PRE_DHCP_ACTION); 863 } 864 @Override onPostDhcpAction()865 public void onPostDhcpAction() { 866 mP2pStateMachine.sendMessage(IPC_POST_DHCP_ACTION); 867 } 868 @Override onNewDhcpResults(DhcpResultsParcelable dhcpResults)869 public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) { 870 mP2pStateMachine.sendMessage(IPC_DHCP_RESULTS, dhcpResults); 871 } 872 @Override onProvisioningSuccess(LinkProperties newLp)873 public void onProvisioningSuccess(LinkProperties newLp) { 874 mP2pStateMachine.sendMessage(IPC_PROVISIONING_SUCCESS, newLp); 875 } 876 @Override onProvisioningFailure(LinkProperties newLp)877 public void onProvisioningFailure(LinkProperties newLp) { 878 mP2pStateMachine.sendMessage(IPC_PROVISIONING_FAILURE); 879 } 880 } 881 882 /** 883 * Get a reference to handler. This is used by a client to establish 884 * an AsyncChannel communication with WifiP2pService 885 */ 886 @Override getMessenger(final IBinder binder, final String packageName, Bundle extras)887 public Messenger getMessenger(final IBinder binder, final String packageName, Bundle extras) { 888 enforceAccessPermission(); 889 enforceChangePermission(); 890 891 int callerUid = getMockableCallingUid(); 892 int uidToUse = callerUid; 893 String packageNameToUse = packageName; 894 895 // if we're being called from the SYSTEM_UID then allow usage of the AttributionSource to 896 // locate the original caller. 897 if (SdkLevel.isAtLeastS() && UserHandle.getAppId(callerUid) == Process.SYSTEM_UID) { 898 if (extras == null) { 899 throw new SecurityException("extras bundle is null"); 900 } 901 AttributionSource as = extras.getParcelable( 902 WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE); 903 if (as == null) { 904 throw new SecurityException( 905 "WifiP2pManager getMessenger attributionSource is null"); 906 } 907 908 if (!as.checkCallingUid()) { 909 throw new SecurityException("WifiP2pManager getMessenger invalid (checkCallingUid " 910 + "fails) attribution source=" + as); 911 } 912 913 // an attribution chain is either of size 1: unregistered (valid by definition) or 914 // size >1: in which case all are validated. 915 if (as.getNext() != null) { 916 AttributionSource asIt = as; 917 AttributionSource asLast = as; 918 do { 919 if (!asIt.isTrusted(mContext)) { 920 throw new SecurityException("WifiP2pManager getMessenger invalid " 921 + "(isTrusted fails) attribution source=" + asIt); 922 } 923 asIt = asIt.getNext(); 924 if (asIt != null) asLast = asIt; 925 } while (asIt != null); 926 927 // use the last AttributionSource in the chain - i.e. the original caller 928 uidToUse = asLast.getUid(); 929 packageNameToUse = asLast.getPackageName(); 930 } 931 } 932 933 // get the DisplayId of the caller (if available) 934 int displayId = Display.DEFAULT_DISPLAY; 935 if (mWifiPermissionsUtil.isSystem(packageName, callerUid)) { 936 displayId = extras.getInt(WifiP2pManager.EXTRA_PARAM_KEY_DISPLAY_ID, 937 Display.DEFAULT_DISPLAY); 938 } 939 940 synchronized (mLock) { 941 final Messenger messenger = new Messenger(mClientHandler); 942 if (mVerboseLoggingEnabled) { 943 Log.d(TAG, "getMessenger: uid=" + getCallingUid() + ", binder=" + binder 944 + ", messenger=" + messenger); 945 } 946 947 IBinder.DeathRecipient dr = () -> { 948 if (mVerboseLoggingEnabled) Log.d(TAG, "binderDied: binder=" + binder); 949 close(binder); 950 }; 951 952 WorkSource ws = packageNameToUse != null 953 ? new WorkSource(uidToUse, packageNameToUse) 954 : new WorkSource(uidToUse); 955 try { 956 binder.linkToDeath(dr, 0); 957 mDeathDataByBinder.put(binder, 958 new DeathHandlerData(callerUid, dr, messenger, ws, displayId)); 959 } catch (RemoteException e) { 960 Log.e(TAG, "Error on linkToDeath: e=" + e); 961 // fall-through here - won't clean up 962 } 963 return messenger; 964 } 965 } 966 967 /** 968 * Get a reference to handler. This is used by a ClientModeImpl to establish 969 * an AsyncChannel communication with P2pStateMachine 970 * @hide 971 */ 972 @Override getP2pStateMachineMessenger()973 public Messenger getP2pStateMachineMessenger() { 974 enforceNetworkStackOrLocationHardwarePermission(); 975 enforceAccessPermission(); 976 enforceChangePermission(); 977 return new Messenger(mP2pStateMachine.getHandler()); 978 } 979 980 /** 981 * Clean-up the state and configuration requested by the closing app. Takes same action as 982 * when the app dies (binder death). 983 */ 984 @Override close(IBinder binder)985 public void close(IBinder binder) { 986 enforceAccessPermission(); 987 enforceChangePermission(); 988 989 DeathHandlerData dhd; 990 synchronized (mLock) { 991 dhd = mDeathDataByBinder.get(binder); 992 if (dhd == null) { 993 Log.w(TAG, "close(): no death recipient for binder"); 994 return; 995 } 996 997 binder.unlinkToDeath(dhd.mDeathRecipient, 0); 998 mDeathDataByBinder.remove(binder); 999 updateWorkSourceByUid(Binder.getCallingUid(), false); 1000 mP2pStateMachine.sendMessage(REMOVE_CLIENT_INFO, 0, 0, binder); 1001 1002 if (SdkLevel.isAtLeastS()) { 1003 AttributionSource source = mClientAttributionSource.remove(binder); 1004 if (null != source) { 1005 mVendorElements.remove(source.getPackageName()); 1006 } 1007 } 1008 1009 // clean-up if there are no more clients registered 1010 // TODO: what does the ClientModeImpl client do? It isn't tracked through here! 1011 if (dhd.mMessenger != null && mDeathDataByBinder.isEmpty()) { 1012 try { 1013 dhd.mMessenger.send( 1014 mClientHandler.obtainMessage(WifiP2pManager.STOP_DISCOVERY)); 1015 dhd.mMessenger.send(mClientHandler.obtainMessage(WifiP2pManager.REMOVE_GROUP)); 1016 } catch (RemoteException e) { 1017 Log.e(TAG, "close: Failed sending clean-up commands: e=" + e); 1018 } 1019 mP2pStateMachine.sendMessage(DISABLE_P2P); 1020 } 1021 } 1022 } 1023 1024 /** This is used to provide information to drivers to optimize performance depending 1025 * on the current mode of operation. 1026 * 0 - disabled 1027 * 1 - source operation 1028 * 2 - sink operation 1029 * 1030 * As an example, the driver could reduce the channel dwell time during scanning 1031 * when acting as a source or sink to minimize impact on miracast. 1032 * @param int mode of operation 1033 */ 1034 @Override setMiracastMode(int mode)1035 public void setMiracastMode(int mode) { 1036 checkConfigureWifiDisplayPermission(); 1037 mP2pStateMachine.sendMessage(SET_MIRACAST_MODE, mode); 1038 } 1039 1040 @Override checkConfigureWifiDisplayPermission()1041 public void checkConfigureWifiDisplayPermission() { 1042 if (!getWfdPermission(Binder.getCallingUid())) { 1043 throw new SecurityException("Wifi Display Permission denied for uid = " 1044 + Binder.getCallingUid()); 1045 } 1046 } 1047 1048 /** 1049 * see {@link android.net.wifi.p2p.WifiP2pManager#getSupportedFeatures()} 1050 */ 1051 @Override getSupportedFeatures()1052 public long getSupportedFeatures() { 1053 return mWifiNative.getSupportedFeatures(); 1054 } 1055 getWfdPermission(int uid)1056 private boolean getWfdPermission(int uid) { 1057 WifiPermissionsWrapper wifiPermissionsWrapper = mWifiInjector.getWifiPermissionsWrapper(); 1058 return wifiPermissionsWrapper.getUidPermission( 1059 android.Manifest.permission.CONFIGURE_WIFI_DISPLAY, uid) 1060 != PackageManager.PERMISSION_DENIED; 1061 } 1062 1063 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1064 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1065 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1066 != PackageManager.PERMISSION_GRANTED) { 1067 pw.println("Permission Denial: can't dump WifiP2pService from from pid=" 1068 + Binder.getCallingPid() 1069 + ", uid=" + Binder.getCallingUid()); 1070 return; 1071 } 1072 mP2pStateMachine.dump(fd, pw, args); 1073 mWifiP2pMetrics.dump(pw); 1074 pw.println("mAutonomousGroup " + mAutonomousGroup); 1075 pw.println("mJoinExistingGroup " + mJoinExistingGroup); 1076 pw.println("mDiscoveryStarted " + mDiscoveryStarted); 1077 pw.println("mListenStarted " + mListenStarted); 1078 pw.println("mDetailedState " + mDetailedState); 1079 pw.println("mTemporarilyDisconnectedWifi " + mTemporarilyDisconnectedWifi); 1080 pw.println("mServiceDiscReqId " + mServiceDiscReqId); 1081 pw.println("mDeathDataByBinder " + mDeathDataByBinder); 1082 pw.println("mClientInfoList " + mClientInfoList.size()); 1083 pw.println("mActiveClients " + mActiveClients); 1084 pw.println("mPeerAuthorizingTimestamp" + mPeerAuthorizingTimestamp); 1085 pw.println(); 1086 1087 final IIpClient ipClient = mIpClient; 1088 if (ipClient != null) { 1089 pw.println("mIpClient:"); 1090 IpClientUtil.dumpIpClient(ipClient, fd, pw, args); 1091 } 1092 } 1093 1094 @Override handleShellCommand(@onNull ParcelFileDescriptor in, @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, @NonNull String[] args)1095 public int handleShellCommand(@NonNull ParcelFileDescriptor in, 1096 @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, 1097 @NonNull String[] args) { 1098 if (!mIsBootComplete) { 1099 Log.w(TAG, "Received shell command when boot is not complete!"); 1100 return -1; 1101 } 1102 1103 WifiP2pShellCommand shellCommand = new WifiP2pShellCommand(mContext); 1104 return shellCommand.exec( 1105 this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), 1106 args); 1107 } 1108 1109 /** 1110 * Handles interaction with ClientModeImpl 1111 */ 1112 private class P2pStateMachine extends StateMachine { 1113 1114 private final DefaultState mDefaultState = new DefaultState(); 1115 private final P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState(); 1116 private final P2pDisablingState mP2pDisablingState = new P2pDisablingState(); 1117 private final P2pDisabledContainerState mP2pDisabledContainerState = 1118 new P2pDisabledContainerState(); 1119 private final P2pDisabledState mP2pDisabledState = new P2pDisabledState(); 1120 private final WaitingState mWaitingState = new WaitingState(this); 1121 private final P2pEnabledState mP2pEnabledState = new P2pEnabledState(); 1122 // Inactive is when p2p is enabled with no connectivity 1123 private final InactiveState mInactiveState = new InactiveState(); 1124 private final GroupCreatingState mGroupCreatingState = new GroupCreatingState(); 1125 private final UserAuthorizingInviteRequestState mUserAuthorizingInviteRequestState = 1126 new UserAuthorizingInviteRequestState(); 1127 private final UserAuthorizingNegotiationRequestState 1128 mUserAuthorizingNegotiationRequestState = 1129 new UserAuthorizingNegotiationRequestState(); 1130 private final ProvisionDiscoveryState mProvisionDiscoveryState = 1131 new ProvisionDiscoveryState(); 1132 private final GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState(); 1133 private final FrequencyConflictState mFrequencyConflictState = new FrequencyConflictState(); 1134 1135 private final GroupCreatedState mGroupCreatedState = new GroupCreatedState(); 1136 private final UserAuthorizingJoinState mUserAuthorizingJoinState = 1137 new UserAuthorizingJoinState(); 1138 private final OngoingGroupRemovalState mOngoingGroupRemovalState = 1139 new OngoingGroupRemovalState(); 1140 1141 private final WifiP2pMonitor mWifiMonitor = mWifiInjector.getWifiP2pMonitor(); 1142 private final WifiP2pDeviceList mPeers = new WifiP2pDeviceList(); 1143 private String mInterfaceName; 1144 private TetheringEventCallback mTetheringEventCallback = 1145 new TetheringManager.TetheringEventCallback() { 1146 @Override 1147 public void onLocalOnlyInterfacesChanged(Set<TetheringInterface> interfaces) { 1148 ArrayList<String> ifaceList = interfaces.stream().map( 1149 p -> p.getInterface()).collect( 1150 Collectors.toCollection(ArrayList::new)); 1151 logd(getName() + " Tethering localOnlyInterfacesChanged" 1152 + " callback for ifaceList: " + ifaceList); 1153 sendMessage(TETHER_INTERFACE_STATE_CHANGED, ifaceList); 1154 } 1155 }; 1156 1157 private final List<CoexUnsafeChannel> mCoexUnsafeChannels = new ArrayList<>(); 1158 private int mUserListenChannel = 0; 1159 private int mUserOperatingChannel = 0; 1160 1161 // During a connection, supplicant can tell us that a device was lost. From a supplicant's 1162 // perspective, the discovery stops during connection and it purges device since it does 1163 // not get latest updates about the device without being in discovery state. 1164 // From the framework perspective, the device is still there since we are connecting or 1165 // connected to it. so we keep these devices in a separate list, so that they are removed 1166 // when connection is cancelled or lost 1167 private final WifiP2pDeviceList mPeersLostDuringConnection = new WifiP2pDeviceList(); 1168 private final WifiP2pGroupList mGroups = new WifiP2pGroupList(null, 1169 new GroupDeleteListener() { 1170 @Override 1171 public void onDeleteGroup(int netId) { 1172 if (mVerboseLoggingEnabled) { 1173 logd("called onDeleteGroup() netId=" + netId); 1174 } 1175 mWifiNative.removeP2pNetwork(netId); 1176 mWifiNative.saveConfig(); 1177 sendP2pPersistentGroupsChangedBroadcast(); 1178 } 1179 }); 1180 private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo(); 1181 private WifiP2pGroup mGroup; 1182 // Is wifi on or off. 1183 private boolean mIsWifiEnabled = false; 1184 1185 // Saved WifiP2pConfig for an ongoing peer connection. This will never be null. 1186 // The deviceAddress will be an empty string when the device is inactive 1187 // or if it is connected without any ongoing join request 1188 private WifiP2pConfig mSavedPeerConfig = new WifiP2pConfig(); 1189 private AlertDialog mLegacyInvitationDialog = null; 1190 private WifiDialogManager.DialogHandle mInvitationDialogHandle = null; 1191 P2pStateMachine(String name, Looper looper, boolean p2pSupported)1192 P2pStateMachine(String name, Looper looper, boolean p2pSupported) { 1193 super(name, looper); 1194 1195 // CHECKSTYLE:OFF IndentationCheck 1196 addState(mDefaultState); 1197 addState(mP2pNotSupportedState, mDefaultState); 1198 addState(mP2pDisablingState, mDefaultState); 1199 addState(mP2pDisabledContainerState, mDefaultState); 1200 addState(mP2pDisabledState, mP2pDisabledContainerState); 1201 addState(mWaitingState, mP2pDisabledContainerState); 1202 addState(mP2pEnabledState, mDefaultState); 1203 addState(mInactiveState, mP2pEnabledState); 1204 addState(mGroupCreatingState, mP2pEnabledState); 1205 addState(mUserAuthorizingInviteRequestState, mGroupCreatingState); 1206 addState(mUserAuthorizingNegotiationRequestState, mGroupCreatingState); 1207 addState(mProvisionDiscoveryState, mGroupCreatingState); 1208 addState(mGroupNegotiationState, mGroupCreatingState); 1209 addState(mFrequencyConflictState, mGroupCreatingState); 1210 addState(mGroupCreatedState, mP2pEnabledState); 1211 addState(mUserAuthorizingJoinState, mGroupCreatedState); 1212 addState(mOngoingGroupRemovalState, mGroupCreatedState); 1213 // CHECKSTYLE:ON IndentationCheck 1214 1215 if (p2pSupported) { 1216 setInitialState(mP2pDisabledState); 1217 } else { 1218 setInitialState(mP2pNotSupportedState); 1219 } 1220 setLogRecSize(100); 1221 1222 if (p2pSupported) { 1223 // Init p2p idle shutdown message 1224 mP2pIdleShutdownMessage = new WakeupMessage(mContext, 1225 this.getHandler(), 1226 P2P_IDLE_SHUTDOWN_MESSAGE_TIMEOUT_TAG, 1227 CMD_P2P_IDLE_SHUTDOWN); 1228 1229 // Register for wifi on/off broadcasts 1230 mContext.registerReceiver(new BroadcastReceiver() { 1231 @Override 1232 public void onReceive(Context context, Intent intent) { 1233 int wifistate = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 1234 WifiManager.WIFI_STATE_UNKNOWN); 1235 if (wifistate == WifiManager.WIFI_STATE_ENABLED) { 1236 mIsWifiEnabled = true; 1237 } else { 1238 mIsWifiEnabled = false; 1239 // Teardown P2P if it's up already. 1240 sendMessage(DISABLE_P2P); 1241 } 1242 if (wifistate == WifiManager.WIFI_STATE_ENABLED 1243 || wifistate == WifiManager.WIFI_STATE_DISABLING) { 1244 checkAndSendP2pStateChangedBroadcast(); 1245 } 1246 } 1247 }, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)); 1248 // Register for location mode on/off broadcasts 1249 mContext.registerReceiver(new BroadcastReceiver() { 1250 @Override 1251 public void onReceive(Context context, Intent intent) { 1252 /* if location mode is off, ongoing discovery should be stopped. 1253 * possible ongoing discovery: 1254 * - peer discovery 1255 * - service discovery 1256 * - group joining scan in native service 1257 */ 1258 if (!mWifiPermissionsUtil.isLocationModeEnabled() 1259 && !SdkLevel.isAtLeastT()) { 1260 sendMessage(WifiP2pManager.STOP_DISCOVERY); 1261 } 1262 } 1263 }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION)); 1264 // Register for tethering state 1265 if (!SdkLevel.isAtLeastS()) { 1266 mContext.registerReceiver(new BroadcastReceiver() { 1267 @Override 1268 public void onReceive(Context context, Intent intent) { 1269 final ArrayList<String> interfaces = intent.getStringArrayListExtra( 1270 TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY); 1271 1272 sendMessage(TETHER_INTERFACE_STATE_CHANGED, interfaces); 1273 } 1274 }, new IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)); 1275 } 1276 mSettingsConfigStore.registerChangeListener( 1277 WIFI_VERBOSE_LOGGING_ENABLED, 1278 (key, newValue) -> enableVerboseLogging(newValue), 1279 getHandler()); 1280 if (SdkLevel.isAtLeastS()) { 1281 mCoexManager.registerCoexListener(this::checkCoexUnsafeChannels); 1282 } 1283 if (SdkLevel.isAtLeastT()) { 1284 mContext.registerReceiver( 1285 new BroadcastReceiver() { 1286 @Override 1287 public void onReceive(Context context, Intent intent) { 1288 Log.d(TAG, "user restrictions changed"); 1289 onUserRestrictionsChanged(); 1290 } 1291 }, 1292 new IntentFilter(UserManager.ACTION_USER_RESTRICTIONS_CHANGED)); 1293 mIsP2pDisallowedByAdmin = mUserManager.getUserRestrictions() 1294 .getBoolean(UserManager.DISALLOW_WIFI_DIRECT); 1295 } 1296 } 1297 } 1298 1299 /** 1300 * Find which user restrictions have changed and take corresponding actions 1301 */ 1302 @RequiresApi(Build.VERSION_CODES.TIRAMISU) onUserRestrictionsChanged()1303 private void onUserRestrictionsChanged() { 1304 final Bundle restrictions = mUserManager.getUserRestrictions(); 1305 final boolean newIsP2pDisallowedByAdmin = 1306 restrictions.getBoolean(UserManager.DISALLOW_WIFI_DIRECT); 1307 1308 if (newIsP2pDisallowedByAdmin != mIsP2pDisallowedByAdmin) { 1309 if (newIsP2pDisallowedByAdmin) { 1310 Log.i(TAG, "Disable P2P: DISALLOW_WIFI_DIRECT set"); 1311 sendMessage(DISABLE_P2P); 1312 } 1313 mIsP2pDisallowedByAdmin = newIsP2pDisallowedByAdmin; 1314 checkAndSendP2pStateChangedBroadcast(); 1315 } 1316 } 1317 1318 @Override getLogRecString(Message msg)1319 protected String getLogRecString(Message msg) { 1320 StringBuilder sb = new StringBuilder(); 1321 sb.append("sender=").append(getCallingPkgName(msg.sendingUid, msg.replyTo)) 1322 .append("(").append(msg.sendingUid).append(")"); 1323 return sb.toString(); 1324 } 1325 1326 @Override recordLogRec(Message msg)1327 protected boolean recordLogRec(Message msg) { 1328 // Filter unnecessary records to avoid overwhelming the buffer. 1329 switch (msg.what) { 1330 case WifiP2pManager.REQUEST_PEERS: 1331 case WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT: 1332 case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: 1333 return false; 1334 default: 1335 return true; 1336 } 1337 } 1338 1339 @Override getWhatToString(int what)1340 protected String getWhatToString(int what) { 1341 switch (what) { 1342 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 1343 return "AsyncChannel.CMD_CHANNEL_DISCONNECTED"; 1344 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: 1345 return "AsyncChannel.CMD_CHANNEL_FULL_CONNECTION"; 1346 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 1347 return "AsyncChannel.CMD_CHANNEL_HALF_CONNECTED"; 1348 case BLOCK_DISCOVERY: 1349 return "BLOCK_DISCOVERY"; 1350 case CMD_P2P_IDLE_SHUTDOWN: 1351 return "CMD_P2P_IDLE_SHUTDOWN"; 1352 case DISABLE_P2P: 1353 return "DISABLE_P2P"; 1354 case DISABLE_P2P_TIMED_OUT: 1355 return "DISABLE_P2P_TIMED_OUT"; 1356 case DISCONNECT_WIFI_RESPONSE: 1357 return "DISCONNECT_WIFI_RESPONSE"; 1358 case DROP_WIFI_USER_ACCEPT: 1359 return "DROP_WIFI_USER_ACCEPT"; 1360 case DROP_WIFI_USER_REJECT: 1361 return "DROP_WIFI_USER_REJECT"; 1362 case ENABLE_P2P: 1363 return "ENABLE_P2P"; 1364 case GROUP_CREATING_TIMED_OUT: 1365 return "GROUP_CREATING_TIMED_OUT"; 1366 case IPC_DHCP_RESULTS: 1367 return "IPC_DHCP_RESULTS"; 1368 case IPC_POST_DHCP_ACTION: 1369 return "IPC_POST_DHCP_ACTION"; 1370 case IPC_PRE_DHCP_ACTION: 1371 return "IPC_PRE_DHCP_ACTION"; 1372 case IPC_PROVISIONING_FAILURE: 1373 return "IPC_PROVISIONING_FAILURE"; 1374 case IPC_PROVISIONING_SUCCESS: 1375 return "IPC_PROVISIONING_SUCCESS"; 1376 case PEER_CONNECTION_USER_ACCEPT: 1377 return "PEER_CONNECTION_USER_ACCEPT"; 1378 case PEER_CONNECTION_USER_CONFIRM: 1379 return "PEER_CONNECTION_USER_CONFIRM"; 1380 case PEER_CONNECTION_USER_REJECT: 1381 return "PEER_CONNECTION_USER_REJECT"; 1382 case REMOVE_CLIENT_INFO: 1383 return "REMOVE_CLIENT_INFO"; 1384 case SET_MIRACAST_MODE: 1385 return "SET_MIRACAST_MODE"; 1386 case TETHER_INTERFACE_STATE_CHANGED: 1387 return "TETHER_INTERFACE_STATE_CHANGED"; 1388 case UPDATE_P2P_DISALLOWED_CHANNELS: 1389 return "UPDATE_P2P_DISALLOWED_CHANNELS"; 1390 case WifiP2pManager.ADD_EXTERNAL_APPROVER: 1391 return "WifiP2pManager.ADD_EXTERNAL_APPROVER"; 1392 case WifiP2pManager.ADD_LOCAL_SERVICE: 1393 return "WifiP2pManager.ADD_LOCAL_SERVICE"; 1394 case WifiP2pManager.ADD_SERVICE_REQUEST: 1395 return "WifiP2pManager.ADD_SERVICE_REQUEST"; 1396 case WifiP2pManager.CANCEL_CONNECT: 1397 return "WifiP2pManager.CANCEL_CONNECT"; 1398 case WifiP2pManager.CLEAR_LOCAL_SERVICES: 1399 return "WifiP2pManager.CLEAR_LOCAL_SERVICES"; 1400 case WifiP2pManager.CLEAR_SERVICE_REQUESTS: 1401 return "WifiP2pManager.CLEAR_SERVICE_REQUESTS"; 1402 case WifiP2pManager.CONNECT: 1403 return "WifiP2pManager.CONNECT"; 1404 case WifiP2pManager.CREATE_GROUP: 1405 return "WifiP2pManager.CREATE_GROUP"; 1406 case WifiP2pManager.DELETE_PERSISTENT_GROUP: 1407 return "WifiP2pManager.DELETE_PERSISTENT_GROUP"; 1408 case WifiP2pManager.DISCOVER_PEERS: 1409 return "WifiP2pManager.DISCOVER_PEERS"; 1410 case WifiP2pManager.DISCOVER_SERVICES: 1411 return "WifiP2pManager.DISCOVER_SERVICES"; 1412 case WifiP2pManager.EXTERNAL_APPROVER_ATTACH: 1413 return "WifiP2pManager.EXTERNAL_APPROVER_ATTACH"; 1414 case WifiP2pManager.FACTORY_RESET: 1415 return "WifiP2pManager.FACTORY_RESET"; 1416 case WifiP2pManager.GET_HANDOVER_REQUEST: 1417 return "WifiP2pManager.GET_HANDOVER_REQUEST"; 1418 case WifiP2pManager.GET_HANDOVER_SELECT: 1419 return "WifiP2pManager.GET_HANDOVER_SELECT"; 1420 case WifiP2pManager.INITIATOR_REPORT_NFC_HANDOVER: 1421 return "WifiP2pManager.INITIATOR_REPORT_NFC_HANDOVER"; 1422 case WifiP2pManager.REMOVE_EXTERNAL_APPROVER: 1423 return "WifiP2pManager.REMOVE_EXTERNAL_APPROVER"; 1424 case WifiP2pManager.REMOVE_GROUP: 1425 return "WifiP2pManager.REMOVE_GROUP"; 1426 case WifiP2pManager.REMOVE_LOCAL_SERVICE: 1427 return "WifiP2pManager.REMOVE_LOCAL_SERVICE"; 1428 case WifiP2pManager.REMOVE_SERVICE_REQUEST: 1429 return "WifiP2pManager.REMOVE_SERVICE_REQUEST"; 1430 case WifiP2pManager.REQUEST_CONNECTION_INFO: 1431 return "WifiP2pManager.REQUEST_CONNECTION_INFO"; 1432 case WifiP2pManager.REQUEST_DEVICE_INFO: 1433 return "WifiP2pManager.REQUEST_DEVICE_INFO"; 1434 case WifiP2pManager.REQUEST_DISCOVERY_STATE: 1435 return "WifiP2pManager.REQUEST_DISCOVERY_STATE"; 1436 case WifiP2pManager.GET_LISTEN_STATE: 1437 return "WifiP2pManager.GET_LISTEN_STATE"; 1438 case WifiP2pManager.REQUEST_GROUP_INFO: 1439 return "WifiP2pManager.REQUEST_GROUP_INFO"; 1440 case WifiP2pManager.REQUEST_NETWORK_INFO: 1441 return "WifiP2pManager.REQUEST_NETWORK_INFO"; 1442 case WifiP2pManager.REQUEST_ONGOING_PEER_CONFIG: 1443 return "WifiP2pManager.REQUEST_ONGOING_PEER_CONFIG"; 1444 case WifiP2pManager.REQUEST_P2P_STATE: 1445 return "WifiP2pManager.REQUEST_P2P_STATE"; 1446 case WifiP2pManager.REQUEST_PEERS: 1447 return "WifiP2pManager.REQUEST_PEERS"; 1448 case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO: 1449 return "WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO"; 1450 case WifiP2pManager.RESPONDER_REPORT_NFC_HANDOVER: 1451 return "WifiP2pManager.RESPONDER_REPORT_NFC_HANDOVER"; 1452 case WifiP2pManager.SET_CHANNEL: 1453 return "WifiP2pManager.SET_CHANNEL"; 1454 case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: 1455 return "WifiP2pManager.SET_CONNECTION_REQUEST_RESULT"; 1456 case WifiP2pManager.SET_DEVICE_NAME: 1457 return "WifiP2pManager.SET_DEVICE_NAME"; 1458 case WifiP2pManager.SET_ONGOING_PEER_CONFIG: 1459 return "WifiP2pManager.SET_ONGOING_PEER_CONFIG"; 1460 case WifiP2pManager.SET_WFD_INFO: 1461 return "WifiP2pManager.SET_WFD_INFO"; 1462 case WifiP2pManager.START_LISTEN: 1463 return "WifiP2pManager.START_LISTEN"; 1464 case WifiP2pManager.START_WPS: 1465 return "WifiP2pManager.START_WPS"; 1466 case WifiP2pManager.STOP_DISCOVERY: 1467 return "WifiP2pManager.STOP_DISCOVERY"; 1468 case WifiP2pManager.STOP_LISTEN: 1469 return "WifiP2pManager.STOP_LISTEN"; 1470 case WifiP2pManager.UPDATE_CHANNEL_INFO: 1471 return "WifiP2pManager.UPDATE_CHANNEL_INFO"; 1472 case WifiP2pManager.REMOVE_CLIENT: 1473 return "WifiP2pManager.REMOVE_CLIENT"; 1474 case WifiP2pMonitor.AP_STA_CONNECTED_EVENT: 1475 return "WifiP2pMonitor.AP_STA_CONNECTED_EVENT"; 1476 case WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT: 1477 return "WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT"; 1478 case WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT: 1479 return "WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT"; 1480 case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: 1481 return "WifiP2pMonitor.P2P_DEVICE_LOST_EVENT"; 1482 case WifiP2pMonitor.P2P_FIND_STOPPED_EVENT: 1483 return "WifiP2pMonitor.P2P_FIND_STOPPED_EVENT"; 1484 case WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: 1485 return "WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT"; 1486 case WifiP2pMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT: 1487 return "WifiP2pMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT"; 1488 case WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT: 1489 return "WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT"; 1490 case WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: 1491 return "WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT"; 1492 case WifiP2pMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT: 1493 return "WifiP2pMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT"; 1494 case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: 1495 return "WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT"; 1496 case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: 1497 return "WifiP2pMonitor.P2P_GROUP_STARTED_EVENT"; 1498 case WifiP2pMonitor.P2P_INVITATION_RECEIVED_EVENT: 1499 return "WifiP2pMonitor.P2P_INVITATION_RECEIVED_EVENT"; 1500 case WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT: 1501 return "WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT"; 1502 case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: 1503 return "WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT"; 1504 case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: 1505 return "WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT"; 1506 case WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: 1507 return "WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT"; 1508 case WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT: 1509 return "WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT"; 1510 case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: 1511 return "WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT"; 1512 case WifiP2pMonitor.P2P_SERV_DISC_RESP_EVENT: 1513 return "WifiP2pMonitor.P2P_SERV_DISC_RESP_EVENT"; 1514 case WifiP2pMonitor.SUP_CONNECTION_EVENT: 1515 return "WifiP2pMonitor.SUP_CONNECTION_EVENT"; 1516 case WifiP2pMonitor.SUP_DISCONNECTION_EVENT: 1517 return "WifiP2pMonitor.SUP_DISCONNECTION_EVENT"; 1518 case WifiP2pMonitor.P2P_FREQUENCY_CHANGED_EVENT: 1519 return "WifiP2pMonitor.P2P_FREQUENCY_CHANGED_EVENT"; 1520 case WpsInfo.DISPLAY: 1521 return "WpsInfo.DISPLAY"; 1522 case WpsInfo.KEYPAD: 1523 return "WpsInfo.KEYPAD"; 1524 case WifiP2pManager.SET_VENDOR_ELEMENTS: 1525 return "WifiP2pManager.SET_VENDOR_ELEMENTS"; 1526 default: 1527 return "what:" + what; 1528 } 1529 } 1530 reportConnectionEventTakeBugReportIfOverlapped(int connectionType, WifiP2pConfig config, int groupRole, int uid)1531 private void reportConnectionEventTakeBugReportIfOverlapped(int connectionType, 1532 WifiP2pConfig config, int groupRole, int uid) { 1533 if (mWifiP2pMetrics.hasOngoingConnection()) { 1534 takeBugReportP2pFailureIfNeeded("Wi-Fi BugReport (P2P " 1535 + mWifiP2pMetrics.getP2pGroupRoleString() 1536 + " overlapping connection attempt)", 1537 "new and old connection attempts overlap"); 1538 } 1539 mWifiP2pMetrics.startConnectionEvent(connectionType, config, groupRole, uid); 1540 } 1541 takeBugReportP2pFailureIfNeeded(String bugTitle, String bugDetail)1542 private void takeBugReportP2pFailureIfNeeded(String bugTitle, String bugDetail) { 1543 if (mWifiInjector.getDeviceConfigFacade().isP2pFailureBugreportEnabled()) { 1544 mWifiInjector.getWifiDiagnostics().takeBugReport(bugTitle, bugDetail); 1545 } 1546 } 1547 logSmMessage(String stateName, Message message)1548 private void logSmMessage(String stateName, Message message) { 1549 if (mVerboseLoggingEnabled) { 1550 logd(stateName + " cmd = " + getWhatToString(message.what) + " " 1551 + message.toString()); 1552 } 1553 } 1554 logSmStateName(String currStateName, String targetStateName)1555 private void logSmStateName(String currStateName, String targetStateName) { 1556 if (mVerboseLoggingEnabled) { 1557 StringBuilder sb = new StringBuilder("State: ").append(currStateName); 1558 if (!currStateName.equals(targetStateName)) { 1559 sb.append(" (target: ").append(targetStateName).append(")"); 1560 } 1561 logd(sb.toString()); 1562 } 1563 } 1564 smTransition(State currState, State targetState)1565 private void smTransition(State currState, State targetState) { 1566 if (mVerboseLoggingEnabled) { 1567 StringBuilder sb = new StringBuilder(); 1568 sb.append("State: ").append(currState.getName()).append(" -> ").append( 1569 targetState.getName()); 1570 logd(sb.toString()); 1571 } 1572 transitionTo(targetState); 1573 } 1574 getGroupOwnerBandToString(int groupOwnerBand)1575 private String getGroupOwnerBandToString(int groupOwnerBand) { 1576 switch(groupOwnerBand) { 1577 case WifiP2pConfig.GROUP_OWNER_BAND_AUTO: 1578 return "band_auto"; 1579 case WifiP2pConfig.GROUP_OWNER_BAND_2GHZ: 1580 return "band_2g"; 1581 case WifiP2pConfig.GROUP_OWNER_BAND_5GHZ: 1582 return "band_5g"; 1583 default: 1584 return String.valueOf(groupOwnerBand); 1585 } 1586 } 1587 1588 // Clear internal data when P2P is shut down due to wifi off or no client. 1589 // For idle shutdown case, there are clients and data should be restored when 1590 // P2P goes back P2pEnabledState. 1591 // For a real shutdown case which caused by wifi off or no client, those internal 1592 // data should be cleared because the caller might not clear them, ex. WFD app 1593 // enables WFD, but does not disable it after leaving the app. clearP2pInternalDataIfNecessary()1594 private void clearP2pInternalDataIfNecessary() { 1595 if (isWifiP2pAvailable() && !mDeathDataByBinder.isEmpty()) return; 1596 1597 mThisDevice.wfdInfo = null; 1598 } 1599 isP2pDisabled()1600 boolean isP2pDisabled() { 1601 return getCurrentState() == mP2pDisabledState; 1602 } 1603 scheduleIdleShutdown()1604 void scheduleIdleShutdown() { 1605 if (mP2pIdleShutdownMessage != null) { 1606 mP2pIdleShutdownMessage.cancel(); 1607 mP2pIdleShutdownMessage.schedule(SystemClock.elapsedRealtime() 1608 + P2P_INTERFACE_IDLE_SHUTDOWN_TIMEOUT_MS); 1609 if (mVerboseLoggingEnabled) { 1610 Log.d(TAG, "IdleShutDown message (re)scheduled in " 1611 + (P2P_INTERFACE_IDLE_SHUTDOWN_TIMEOUT_MS / 1000) + "s"); 1612 } 1613 } 1614 mP2pStateMachine.getHandler().removeMessages(CMD_P2P_IDLE_SHUTDOWN); 1615 } 1616 cancelIdleShutdown()1617 void cancelIdleShutdown() { 1618 if (mP2pIdleShutdownMessage != null) { 1619 mP2pIdleShutdownMessage.cancel(); 1620 if (mVerboseLoggingEnabled) { 1621 Log.d(TAG, "IdleShutDown message canceled"); 1622 } 1623 } 1624 mP2pStateMachine.getHandler().removeMessages(CMD_P2P_IDLE_SHUTDOWN); 1625 } 1626 checkCoexUnsafeChannels()1627 void checkCoexUnsafeChannels() { 1628 List<CoexUnsafeChannel> unsafeChannels = null; 1629 1630 // If WIFI DIRECT bit is not set, pass null to clear unsafe channels. 1631 if (SdkLevel.isAtLeastS() 1632 && (mCoexManager.getCoexRestrictions() 1633 & WifiManager.COEX_RESTRICTION_WIFI_DIRECT) != 0) { 1634 unsafeChannels = mCoexManager.getCoexUnsafeChannels(); 1635 Log.d(TAG, "UnsafeChannels: " 1636 + unsafeChannels.stream() 1637 .map(Object::toString) 1638 .collect(Collectors.joining(","))); 1639 } 1640 1641 sendMessage(UPDATE_P2P_DISALLOWED_CHANNELS, unsafeChannels); 1642 } 1643 1644 /** 1645 * Enable verbose logging for all sub modules. 1646 */ enableVerboseLogging(boolean verboseEnabled)1647 private void enableVerboseLogging(boolean verboseEnabled) { 1648 mVerboseHalLoggingEnabled = verboseEnabled; 1649 updateVerboseLoggingEnabled(); 1650 mWifiNative.enableVerboseLogging(mVerboseLoggingEnabled, mVerboseHalLoggingEnabled); 1651 mWifiMonitor.enableVerboseLogging(mVerboseLoggingEnabled); 1652 mExternalApproverManager.enableVerboseLogging(mVerboseLoggingEnabled); 1653 } 1654 registerForWifiMonitorEvents()1655 public void registerForWifiMonitorEvents() { 1656 mWifiMonitor.registerHandler(mInterfaceName, 1657 WifiP2pMonitor.AP_STA_CONNECTED_EVENT, getHandler()); 1658 mWifiMonitor.registerHandler(mInterfaceName, 1659 WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT, getHandler()); 1660 mWifiMonitor.registerHandler(mInterfaceName, 1661 WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT, getHandler()); 1662 mWifiMonitor.registerHandler(mInterfaceName, 1663 WifiP2pMonitor.P2P_DEVICE_LOST_EVENT, getHandler()); 1664 mWifiMonitor.registerHandler(mInterfaceName, 1665 WifiP2pMonitor.P2P_FIND_STOPPED_EVENT, getHandler()); 1666 mWifiMonitor.registerHandler(mInterfaceName, 1667 WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT, getHandler()); 1668 mWifiMonitor.registerHandler(mInterfaceName, 1669 WifiP2pMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT, getHandler()); 1670 mWifiMonitor.registerHandler(mInterfaceName, 1671 WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT, getHandler()); 1672 mWifiMonitor.registerHandler(mInterfaceName, 1673 WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT, getHandler()); 1674 mWifiMonitor.registerHandler(mInterfaceName, 1675 WifiP2pMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT, getHandler()); 1676 mWifiMonitor.registerHandler(mInterfaceName, 1677 WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT, getHandler()); 1678 mWifiMonitor.registerHandler(mInterfaceName, 1679 WifiP2pMonitor.P2P_GROUP_STARTED_EVENT, getHandler()); 1680 mWifiMonitor.registerHandler(mInterfaceName, 1681 WifiP2pMonitor.P2P_INVITATION_RECEIVED_EVENT, getHandler()); 1682 mWifiMonitor.registerHandler(mInterfaceName, 1683 WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT, getHandler()); 1684 mWifiMonitor.registerHandler(mInterfaceName, 1685 WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT, getHandler()); 1686 mWifiMonitor.registerHandler(mInterfaceName, 1687 WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT, getHandler()); 1688 mWifiMonitor.registerHandler(mInterfaceName, 1689 WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT, getHandler()); 1690 mWifiMonitor.registerHandler(mInterfaceName, 1691 WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT, getHandler()); 1692 mWifiMonitor.registerHandler(mInterfaceName, 1693 WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT, getHandler()); 1694 mWifiMonitor.registerHandler(mInterfaceName, 1695 WifiP2pMonitor.P2P_SERV_DISC_RESP_EVENT, getHandler()); 1696 mWifiMonitor.registerHandler(mInterfaceName, 1697 WifiP2pMonitor.SUP_CONNECTION_EVENT, getHandler()); 1698 mWifiMonitor.registerHandler(mInterfaceName, 1699 WifiP2pMonitor.SUP_DISCONNECTION_EVENT, getHandler()); 1700 mWifiMonitor.registerHandler(mInterfaceName, 1701 WifiP2pMonitor.P2P_FREQUENCY_CHANGED_EVENT, getHandler()); 1702 1703 mWifiMonitor.startMonitoring(mInterfaceName); 1704 } 1705 createRequestorWs(int uid, String packageName)1706 private WorkSource createRequestorWs(int uid, String packageName) { 1707 WorkSource requestorWs = new WorkSource(uid, packageName); 1708 logd("Requestor WorkSource: " + requestorWs); 1709 return requestorWs; 1710 } 1711 createMergedRequestorWs()1712 private WorkSource createMergedRequestorWs() { 1713 WorkSource requestorWs = new WorkSource(); 1714 for (WorkSource ws: mActiveClients.values()) { 1715 requestorWs.add(ws); 1716 } 1717 logd("Requestor WorkSource: " + requestorWs); 1718 return requestorWs; 1719 } 1720 needsActiveP2p(int cmd)1721 private boolean needsActiveP2p(int cmd) { 1722 if (cmd < Protocol.BASE_WIFI_P2P_MANAGER) return false; 1723 if (cmd >= Protocol.BASE_WIFI_P2P_SERVICE) return false; 1724 switch (cmd) { 1725 case WifiP2pManager.UPDATE_CHANNEL_INFO: 1726 case WifiP2pManager.SET_WFD_INFO: 1727 // If P2P is not active, these commands do not take effect actually. 1728 case WifiP2pManager.STOP_DISCOVERY: 1729 case WifiP2pManager.STOP_LISTEN: 1730 case WifiP2pManager.CANCEL_CONNECT: 1731 case WifiP2pManager.REMOVE_GROUP: 1732 case WifiP2pManager.REMOVE_LOCAL_SERVICE: 1733 case WifiP2pManager.CLEAR_LOCAL_SERVICES: 1734 case WifiP2pManager.REMOVE_SERVICE_REQUEST: 1735 case WifiP2pManager.CLEAR_SERVICE_REQUESTS: 1736 case WifiP2pManager.REMOVE_CLIENT: 1737 // These commands return wifi service p2p information which 1738 // does not need active P2P. 1739 case WifiP2pManager.REQUEST_P2P_STATE: 1740 case WifiP2pManager.REQUEST_DISCOVERY_STATE: 1741 case WifiP2pManager.GET_LISTEN_STATE: 1742 case WifiP2pManager.REQUEST_NETWORK_INFO: 1743 case WifiP2pManager.REQUEST_CONNECTION_INFO: 1744 case WifiP2pManager.REQUEST_GROUP_INFO: 1745 case WifiP2pManager.REQUEST_PEERS: 1746 // These commands configure the framework behavior. 1747 case WifiP2pManager.ADD_EXTERNAL_APPROVER: 1748 case WifiP2pManager.REMOVE_EXTERNAL_APPROVER: 1749 case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: 1750 // These commands could be cached and executed on activating P2P. 1751 case WifiP2pManager.SET_DEVICE_NAME: 1752 case WifiP2pManager.SET_VENDOR_ELEMENTS: 1753 return false; 1754 case WifiP2pManager.REQUEST_DEVICE_INFO: 1755 if (!mWifiGlobals.isP2pMacRandomizationSupported() 1756 && !TextUtils.isEmpty(mThisDevice.deviceAddress)) { 1757 return false; 1758 } 1759 break; 1760 } 1761 return true; 1762 } 1763 1764 @Override onPreHandleMessage(Message msg)1765 protected void onPreHandleMessage(Message msg) { 1766 if (needsActiveP2p(msg.what)) { 1767 updateWorkSourceByUid(msg.sendingUid, true); 1768 } 1769 } 1770 1771 class DefaultState extends State { 1772 @Override processMessage(Message message)1773 public boolean processMessage(Message message) { 1774 logSmMessage(getName(), message); 1775 switch (message.what) { 1776 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 1777 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 1778 if (mVerboseLoggingEnabled) { 1779 logd("Full connection with ClientModeImpl established"); 1780 } 1781 mWifiChannel = (AsyncChannel) message.obj; 1782 } else { 1783 loge("Full connection failure, error = " + message.arg1); 1784 mWifiChannel = null; 1785 smTransition(this, mP2pDisabledState); 1786 } 1787 break; 1788 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 1789 if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { 1790 loge("Send failed, client connection lost"); 1791 } else { 1792 loge("Client connection lost with reason: " + message.arg1); 1793 } 1794 mWifiChannel = null; 1795 smTransition(this, mP2pDisabledState); 1796 break; 1797 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: 1798 AsyncChannel ac = new AsyncChannel(); 1799 ac.connect(mContext, getHandler(), message.replyTo); 1800 break; 1801 case BLOCK_DISCOVERY: 1802 mDiscoveryBlocked = (message.arg1 == ENABLED); 1803 // always reset this - we went to a state that doesn't support discovery so 1804 // it would have stopped regardless 1805 mDiscoveryPostponed = false; 1806 if (mDiscoveryBlocked && mWifiChannel != null) { 1807 mWifiChannel.replyToMessage(message, message.arg2); 1808 } 1809 break; 1810 case WifiP2pManager.DISCOVER_PEERS: 1811 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 1812 WifiP2pManager.BUSY); 1813 break; 1814 case WifiP2pManager.STOP_DISCOVERY: 1815 if (isWifiP2pAvailable()) { 1816 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED); 1817 } else { 1818 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, 1819 WifiP2pManager.BUSY); 1820 } 1821 break; 1822 case WifiP2pManager.DISCOVER_SERVICES: 1823 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 1824 WifiP2pManager.BUSY); 1825 break; 1826 case WifiP2pManager.CONNECT: 1827 replyToMessage(message, WifiP2pManager.CONNECT_FAILED, 1828 WifiP2pManager.BUSY); 1829 break; 1830 case WifiP2pManager.CANCEL_CONNECT: 1831 replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED, 1832 WifiP2pManager.BUSY); 1833 break; 1834 case WifiP2pManager.CREATE_GROUP: 1835 replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, 1836 WifiP2pManager.BUSY); 1837 break; 1838 case WifiP2pManager.REMOVE_GROUP: 1839 replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, 1840 WifiP2pManager.BUSY); 1841 break; 1842 case WifiP2pManager.STOP_LISTEN: 1843 if (isWifiP2pAvailable()) { 1844 replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); 1845 } 1846 break; 1847 case WifiP2pManager.ADD_LOCAL_SERVICE: 1848 replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED, 1849 WifiP2pManager.BUSY); 1850 break; 1851 case WifiP2pManager.REMOVE_LOCAL_SERVICE: 1852 replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED, 1853 WifiP2pManager.BUSY); 1854 break; 1855 case WifiP2pManager.CLEAR_LOCAL_SERVICES: 1856 replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED, 1857 WifiP2pManager.BUSY); 1858 break; 1859 case WifiP2pManager.ADD_SERVICE_REQUEST: 1860 replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED, 1861 WifiP2pManager.BUSY); 1862 break; 1863 case WifiP2pManager.REMOVE_SERVICE_REQUEST: 1864 replyToMessage(message, 1865 WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED, 1866 WifiP2pManager.BUSY); 1867 break; 1868 case WifiP2pManager.CLEAR_SERVICE_REQUESTS: 1869 replyToMessage(message, 1870 WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED, 1871 WifiP2pManager.BUSY); 1872 break; 1873 case WifiP2pManager.SET_DEVICE_NAME: 1874 { 1875 if (!isWifiP2pAvailable()) { 1876 replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, 1877 WifiP2pManager.BUSY); 1878 break; 1879 } 1880 if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( 1881 message.sendingUid)) { 1882 loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," 1883 + " or OVERRIDE_WIFI_CONFIG permission, uid = " 1884 + message.sendingUid); 1885 replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, 1886 WifiP2pManager.ERROR); 1887 break; 1888 } 1889 WifiP2pDevice d = (WifiP2pDevice) message.obj; 1890 if (d != null && setAndPersistDeviceName(d.deviceName)) { 1891 if (mVerboseLoggingEnabled) logd("set device name " + d.deviceName); 1892 replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_SUCCEEDED); 1893 } else { 1894 replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, 1895 WifiP2pManager.ERROR); 1896 } 1897 break; 1898 } 1899 case WifiP2pManager.DELETE_PERSISTENT_GROUP: 1900 replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, 1901 WifiP2pManager.BUSY); 1902 break; 1903 case WifiP2pManager.SET_WFD_INFO: 1904 WifiP2pWfdInfo d = (WifiP2pWfdInfo) message.obj; 1905 if (!getWfdPermission(message.sendingUid)) { 1906 loge("No WFD permission, uid = " + message.sendingUid); 1907 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 1908 WifiP2pManager.ERROR); 1909 } else if (d != null) { 1910 mThisDevice.wfdInfo = d; 1911 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_SUCCEEDED); 1912 } else { 1913 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 1914 WifiP2pManager.ERROR); 1915 } 1916 break; 1917 case WifiP2pManager.REQUEST_PEERS: 1918 replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, 1919 getPeers(getCallingPkgName(message.sendingUid, message.replyTo), 1920 getCallingFeatureId(message.sendingUid, message.replyTo), 1921 message.sendingUid, message.getData().getBundle( 1922 WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE), 1923 message.obj)); 1924 break; 1925 case WifiP2pManager.REQUEST_CONNECTION_INFO: 1926 replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, 1927 new WifiP2pInfo(mWifiP2pInfo)); 1928 break; 1929 case WifiP2pManager.REQUEST_GROUP_INFO: { 1930 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 1931 if (packageName == null) { 1932 replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, null); 1933 break; 1934 } 1935 int uid = message.sendingUid; 1936 Bundle extras = message.getData() 1937 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 1938 boolean hasPermission = false; 1939 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 1940 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 1941 packageName, 1942 getCallingFeatureId(message.sendingUid, message.replyTo), 1943 uid, false); 1944 } else { 1945 hasPermission = checkNearbyDevicesPermission(uid, packageName, 1946 extras, "REQUEST_GROUP_INFO", message.obj); 1947 } 1948 if (!hasPermission) { 1949 replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, null); 1950 // remain at this state. 1951 break; 1952 } 1953 replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, 1954 maybeEraseOwnDeviceAddress(mGroup, message.sendingUid)); 1955 break; 1956 } 1957 case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO: { 1958 if (!checkNetworkSettingsOrNetworkStackOrReadWifiCredentialPermission( 1959 message.sendingUid)) { 1960 loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," 1961 + " or READ_WIFI_CREDENTIAL permission, uid = " 1962 + message.sendingUid); 1963 replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO, 1964 new WifiP2pGroupList()); 1965 break; 1966 } 1967 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 1968 if (packageName == null) { 1969 replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO, 1970 new WifiP2pGroupList()); 1971 break; 1972 } 1973 Bundle extras = message.getData() 1974 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 1975 if (!isPlatformOrTargetSdkLessThanT(packageName, message.sendingUid) 1976 && !checkNearbyDevicesPermission(message.sendingUid, packageName, 1977 extras, "REQUEST_PERSISTENT_GROUP_INFO", message.obj)) { 1978 loge("Permission violation - no NEARBY_WIFI_DEVICES permission, uid = " 1979 + message.sendingUid); 1980 replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO, 1981 new WifiP2pGroupList()); 1982 break; 1983 } 1984 replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO, 1985 new WifiP2pGroupList( 1986 maybeEraseOwnDeviceAddress(mGroups, message.sendingUid), 1987 null)); 1988 break; 1989 } 1990 case WifiP2pManager.REQUEST_P2P_STATE: 1991 replyToMessage(message, WifiP2pManager.RESPONSE_P2P_STATE, 1992 isWifiP2pAvailable() 1993 ? WifiP2pManager.WIFI_P2P_STATE_ENABLED 1994 : WifiP2pManager.WIFI_P2P_STATE_DISABLED); 1995 break; 1996 case WifiP2pManager.REQUEST_DISCOVERY_STATE: 1997 replyToMessage(message, WifiP2pManager.RESPONSE_DISCOVERY_STATE, 1998 mDiscoveryStarted 1999 ? WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED 2000 : WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED); 2001 break; 2002 case WifiP2pManager.GET_LISTEN_STATE: { 2003 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 2004 if (packageName == null) { 2005 replyToMessage(message, WifiP2pManager.GET_LISTEN_STATE_FAILED); 2006 break; 2007 } 2008 int uid = message.sendingUid; 2009 Bundle extras = message.getData() 2010 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 2011 boolean hasPermission; 2012 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 2013 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 2014 packageName, 2015 getCallingFeatureId(message.sendingUid, message.replyTo), 2016 uid, true); 2017 } else { 2018 hasPermission = checkNearbyDevicesPermission(uid, packageName, 2019 extras, "GET_LISTEN_STATE", message.obj); 2020 } 2021 if (!hasPermission) { 2022 replyToMessage(message, WifiP2pManager.GET_LISTEN_STATE_FAILED); 2023 break; 2024 } 2025 replyToMessage(message, WifiP2pManager.RESPONSE_GET_LISTEN_STATE, 2026 mListenStarted 2027 ? WifiP2pManager.WIFI_P2P_LISTEN_STARTED 2028 : WifiP2pManager.WIFI_P2P_LISTEN_STOPPED); 2029 break; 2030 } 2031 case WifiP2pManager.REQUEST_NETWORK_INFO: 2032 replyToMessage(message, WifiP2pManager.RESPONSE_NETWORK_INFO, 2033 makeNetworkInfo()); 2034 break; 2035 case WifiP2pManager.START_WPS: 2036 replyToMessage(message, WifiP2pManager.START_WPS_FAILED, 2037 WifiP2pManager.BUSY); 2038 break; 2039 case WifiP2pManager.GET_HANDOVER_REQUEST: 2040 case WifiP2pManager.GET_HANDOVER_SELECT: 2041 replyToMessage(message, WifiP2pManager.RESPONSE_GET_HANDOVER_MESSAGE, null); 2042 break; 2043 case WifiP2pManager.INITIATOR_REPORT_NFC_HANDOVER: 2044 case WifiP2pManager.RESPONDER_REPORT_NFC_HANDOVER: 2045 replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED, 2046 WifiP2pManager.BUSY); 2047 break; 2048 case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: 2049 replyToMessage(message, WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_FAILED, 2050 WifiP2pManager.BUSY); 2051 break; 2052 case WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT: 2053 case WifiP2pMonitor.SUP_CONNECTION_EVENT: 2054 case WifiP2pMonitor.SUP_DISCONNECTION_EVENT: 2055 case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: 2056 case WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT: 2057 case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: 2058 case WifiP2pMonitor.P2P_FIND_STOPPED_EVENT: 2059 case WifiP2pMonitor.P2P_SERV_DISC_RESP_EVENT: 2060 case PEER_CONNECTION_USER_ACCEPT: 2061 case PEER_CONNECTION_USER_REJECT: 2062 case DISCONNECT_WIFI_RESPONSE: 2063 case DROP_WIFI_USER_ACCEPT: 2064 case DROP_WIFI_USER_REJECT: 2065 case GROUP_CREATING_TIMED_OUT: 2066 case DISABLE_P2P_TIMED_OUT: 2067 case IPC_PRE_DHCP_ACTION: 2068 case IPC_POST_DHCP_ACTION: 2069 case IPC_DHCP_RESULTS: 2070 case IPC_PROVISIONING_SUCCESS: 2071 case IPC_PROVISIONING_FAILURE: 2072 case TETHER_INTERFACE_STATE_CHANGED: 2073 case UPDATE_P2P_DISALLOWED_CHANNELS: 2074 case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: 2075 case SET_MIRACAST_MODE: 2076 break; 2077 case WifiP2pManager.START_LISTEN: 2078 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED, 2079 WifiP2pManager.BUSY); 2080 break; 2081 case WifiP2pManager.SET_CHANNEL: 2082 replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED, 2083 WifiP2pManager.BUSY); 2084 break; 2085 case ENABLE_P2P: 2086 // Enable is lazy and has no response 2087 break; 2088 case DISABLE_P2P: 2089 // If we end up handling in default, p2p is not enabled 2090 break; 2091 case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: 2092 // unexpected group created, remove 2093 if (message.obj == null) { 2094 Log.e(TAG, "Illegal arguments"); 2095 break; 2096 } 2097 mGroup = (WifiP2pGroup) message.obj; 2098 loge("Unexpected group creation, remove " + mGroup); 2099 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 2100 break; 2101 case WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: 2102 // A group formation failure is always followed by 2103 // a group removed event. Flushing things at group formation 2104 // failure causes supplicant issues. Ignore right now. 2105 break; 2106 case WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: 2107 if (null != mSavedRejectedPeerConfig) { 2108 sendP2pRequestChangedBroadcast(false); 2109 mSavedRejectedPeerConfig = null; 2110 } 2111 break; 2112 case WifiP2pManager.FACTORY_RESET: 2113 if (factoryReset(message.sendingUid)) { 2114 replyToMessage(message, WifiP2pManager.FACTORY_RESET_SUCCEEDED); 2115 } else { 2116 replyToMessage(message, WifiP2pManager.FACTORY_RESET_FAILED, 2117 WifiP2pManager.ERROR); 2118 } 2119 break; 2120 case WifiP2pManager.SET_ONGOING_PEER_CONFIG: 2121 if (mWifiPermissionsUtil.checkNetworkStackPermission(message.sendingUid)) { 2122 WifiP2pConfig peerConfig = (WifiP2pConfig) message.obj; 2123 if (isConfigInvalid(peerConfig)) { 2124 loge("Dropping set mSavedPeerConfig requeset" + peerConfig); 2125 replyToMessage(message, 2126 WifiP2pManager.SET_ONGOING_PEER_CONFIG_FAILED); 2127 } else { 2128 logd("setSavedPeerConfig to " + peerConfig); 2129 mSavedPeerConfig = peerConfig; 2130 replyToMessage(message, 2131 WifiP2pManager.SET_ONGOING_PEER_CONFIG_SUCCEEDED); 2132 } 2133 } else { 2134 loge("Permission violation - no NETWORK_STACK permission," 2135 + " uid = " + message.sendingUid); 2136 replyToMessage(message, 2137 WifiP2pManager.SET_ONGOING_PEER_CONFIG_FAILED); 2138 } 2139 break; 2140 case WifiP2pManager.REQUEST_ONGOING_PEER_CONFIG: 2141 if (mWifiPermissionsUtil.checkNetworkStackPermission(message.sendingUid)) { 2142 replyToMessage(message, 2143 WifiP2pManager.RESPONSE_ONGOING_PEER_CONFIG, mSavedPeerConfig); 2144 } else { 2145 loge("Permission violation - no NETWORK_STACK permission," 2146 + " uid = " + message.sendingUid); 2147 replyToMessage(message, 2148 WifiP2pManager.RESPONSE_ONGOING_PEER_CONFIG, null); 2149 } 2150 break; 2151 case WifiP2pManager.UPDATE_CHANNEL_INFO: { 2152 Bundle bundle = message.getData() 2153 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 2154 if (!(bundle instanceof Bundle)) { 2155 break; 2156 } 2157 String pkgName = bundle.getString(WifiP2pManager.CALLING_PACKAGE); 2158 String featureId = bundle.getString(WifiP2pManager.CALLING_FEATURE_ID); 2159 IBinder binder = bundle.getBinder(WifiP2pManager.CALLING_BINDER); 2160 try { 2161 mWifiPermissionsUtil.checkPackage(message.sendingUid, pkgName); 2162 } catch (SecurityException se) { 2163 loge("Unable to update calling package, " + se); 2164 break; 2165 } 2166 if (binder != null && message.replyTo != null) { 2167 mClientChannelList.put(binder, message.replyTo); 2168 ClientInfo clientInfo = getClientInfo(message.replyTo, true); 2169 clientInfo.mPackageName = pkgName; 2170 clientInfo.mFeatureId = featureId; 2171 if (SdkLevel.isAtLeastS()) { 2172 AttributionSource source = (AttributionSource) message.obj; 2173 if (null != source) { 2174 mClientAttributionSource.put(binder, source); 2175 } 2176 } 2177 } 2178 break; 2179 } 2180 case WifiP2pManager.REQUEST_DEVICE_INFO: 2181 { 2182 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 2183 if (packageName == null) { 2184 replyToMessage(message, WifiP2pManager.RESPONSE_DEVICE_INFO, null); 2185 break; 2186 } 2187 int uid = message.sendingUid; 2188 Bundle extras = message.getData() 2189 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 2190 boolean hasPermission = false; 2191 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 2192 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 2193 packageName, 2194 getCallingFeatureId(message.sendingUid, message.replyTo), 2195 uid, false); 2196 } else { 2197 hasPermission = checkNearbyDevicesPermission(uid, packageName, 2198 extras, "REQUEST_DEVICE_INFO", message.obj); 2199 } 2200 if (!hasPermission) { 2201 replyToMessage(message, WifiP2pManager.RESPONSE_DEVICE_INFO, null); 2202 break; 2203 } 2204 replyToMessage(message, WifiP2pManager.RESPONSE_DEVICE_INFO, 2205 maybeEraseOwnDeviceAddress(mThisDevice, message.sendingUid)); 2206 break; 2207 } 2208 case WifiP2pManager.REMOVE_CLIENT: 2209 if (!isFeatureSupported(WifiP2pManager.FEATURE_GROUP_CLIENT_REMOVAL)) { 2210 replyToMessage(message, WifiP2pManager.REMOVE_CLIENT_FAILED, 2211 WifiP2pManager.ERROR); 2212 break; 2213 } 2214 replyToMessage(message, WifiP2pManager.REMOVE_CLIENT_SUCCEEDED); 2215 break; 2216 case WifiP2pManager.ADD_EXTERNAL_APPROVER: { 2217 Bundle extras = message.getData().getBundle( 2218 WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 2219 MacAddress devAddr = extras.getParcelable( 2220 WifiP2pManager.EXTRA_PARAM_KEY_PEER_ADDRESS); 2221 IBinder binder = extras.getBinder(WifiP2pManager.CALLING_BINDER); 2222 if (!checkExternalApproverCaller(message, binder, devAddr, 2223 "ADD_EXTERNAL_APPROVER")) { 2224 replyToMessage(message, WifiP2pManager.EXTERNAL_APPROVER_DETACH, 2225 ExternalApproverRequestListener.APPROVER_DETACH_REASON_FAILURE, 2226 devAddr); 2227 break; 2228 } 2229 ApproverEntry entry = mExternalApproverManager.put( 2230 binder, devAddr, message); 2231 // A non-null entry indicates that the device address was added before. 2232 // So inform the approver about detach. 2233 if (null != entry) { 2234 logd("Replace an existing approver " + entry); 2235 replyToMessage(entry.getMessage(), 2236 WifiP2pManager.EXTERNAL_APPROVER_DETACH, 2237 ExternalApproverRequestListener.APPROVER_DETACH_REASON_REPLACE, 2238 devAddr); 2239 break; 2240 } 2241 logd("Add the approver " + mExternalApproverManager.get(devAddr)); 2242 replyToMessage(message, WifiP2pManager.EXTERNAL_APPROVER_ATTACH, devAddr); 2243 break; 2244 } 2245 case WifiP2pManager.REMOVE_EXTERNAL_APPROVER: { 2246 Bundle extras = message.getData().getBundle( 2247 WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 2248 MacAddress devAddr = extras.getParcelable( 2249 WifiP2pManager.EXTRA_PARAM_KEY_PEER_ADDRESS); 2250 IBinder binder = extras.getBinder(WifiP2pManager.CALLING_BINDER); 2251 if (!checkExternalApproverCaller(message, binder, devAddr, 2252 "REMOVE_EXTERNAL_APPROVER")) { 2253 replyToMessage(message, 2254 WifiP2pManager.REMOVE_EXTERNAL_APPROVER_FAILED); 2255 break; 2256 } 2257 ApproverEntry entry = mExternalApproverManager.remove( 2258 binder, devAddr); 2259 if (null != entry) { 2260 logd("Remove the approver " + entry); 2261 replyToMessage(entry.getMessage(), 2262 WifiP2pManager.EXTERNAL_APPROVER_DETACH, 2263 ExternalApproverRequestListener.APPROVER_DETACH_REASON_REMOVE, 2264 devAddr); 2265 break; 2266 } 2267 replyToMessage(message, WifiP2pManager.REMOVE_EXTERNAL_APPROVER_SUCCEEDED); 2268 break; 2269 } 2270 case WifiP2pManager.SET_VENDOR_ELEMENTS: { 2271 if (!isFeatureSupported(WifiP2pManager.FEATURE_SET_VENDOR_ELEMENTS)) { 2272 replyToMessage(message, WifiP2pManager.SET_VENDOR_ELEMENTS_FAILED, 2273 WifiP2pManager.ERROR); 2274 break; 2275 } 2276 if (!mWifiPermissionsUtil.checkConfigOverridePermission( 2277 message.sendingUid)) { 2278 loge(" Uid " + message.sendingUid 2279 + " has no config override permission"); 2280 replyToMessage(message, WifiP2pManager.SET_VENDOR_ELEMENTS_FAILED); 2281 break; 2282 } 2283 if (!SdkLevel.isAtLeastS() 2284 || !checkNearbyDevicesPermission(message, "SET_VENDOR_ELEMENTS")) { 2285 replyToMessage(message, WifiP2pManager.SET_VENDOR_ELEMENTS_FAILED); 2286 break; 2287 } 2288 Bundle extras = message.getData() 2289 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 2290 ArrayList<ScanResult.InformationElement> ies = 2291 extras.getParcelableArrayList( 2292 WifiP2pManager.EXTRA_PARAM_KEY_INFORMATION_ELEMENT_LIST); 2293 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 2294 if (!updateVendorElements(packageName, ies)) { 2295 replyToMessage(message, WifiP2pManager.SET_VENDOR_ELEMENTS_FAILED); 2296 break; 2297 } 2298 replyToMessage(message, WifiP2pManager.SET_VENDOR_ELEMENTS_SUCCEEDED); 2299 break; 2300 } 2301 default: 2302 loge("Unhandled message " + message); 2303 return NOT_HANDLED; 2304 } 2305 return HANDLED; 2306 } 2307 } 2308 2309 class P2pNotSupportedState extends State { 2310 @Override processMessage(Message message)2311 public boolean processMessage(Message message) { 2312 logSmMessage(getName(), message); 2313 switch (message.what) { 2314 case WifiP2pManager.DISCOVER_PEERS: 2315 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 2316 WifiP2pManager.P2P_UNSUPPORTED); 2317 break; 2318 case WifiP2pManager.STOP_DISCOVERY: 2319 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, 2320 WifiP2pManager.P2P_UNSUPPORTED); 2321 break; 2322 case WifiP2pManager.DISCOVER_SERVICES: 2323 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 2324 WifiP2pManager.P2P_UNSUPPORTED); 2325 break; 2326 case WifiP2pManager.CONNECT: 2327 replyToMessage(message, WifiP2pManager.CONNECT_FAILED, 2328 WifiP2pManager.P2P_UNSUPPORTED); 2329 break; 2330 case WifiP2pManager.CANCEL_CONNECT: 2331 replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED, 2332 WifiP2pManager.P2P_UNSUPPORTED); 2333 break; 2334 case WifiP2pManager.CREATE_GROUP: 2335 replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, 2336 WifiP2pManager.P2P_UNSUPPORTED); 2337 break; 2338 case WifiP2pManager.REMOVE_GROUP: 2339 replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, 2340 WifiP2pManager.P2P_UNSUPPORTED); 2341 break; 2342 case WifiP2pManager.ADD_LOCAL_SERVICE: 2343 replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED, 2344 WifiP2pManager.P2P_UNSUPPORTED); 2345 break; 2346 case WifiP2pManager.REMOVE_LOCAL_SERVICE: 2347 replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED, 2348 WifiP2pManager.P2P_UNSUPPORTED); 2349 break; 2350 case WifiP2pManager.CLEAR_LOCAL_SERVICES: 2351 replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED, 2352 WifiP2pManager.P2P_UNSUPPORTED); 2353 break; 2354 case WifiP2pManager.ADD_SERVICE_REQUEST: 2355 replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED, 2356 WifiP2pManager.P2P_UNSUPPORTED); 2357 break; 2358 case WifiP2pManager.REMOVE_SERVICE_REQUEST: 2359 replyToMessage(message, 2360 WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED, 2361 WifiP2pManager.P2P_UNSUPPORTED); 2362 break; 2363 case WifiP2pManager.CLEAR_SERVICE_REQUESTS: 2364 replyToMessage(message, 2365 WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED, 2366 WifiP2pManager.P2P_UNSUPPORTED); 2367 break; 2368 case WifiP2pManager.SET_DEVICE_NAME: 2369 replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, 2370 WifiP2pManager.P2P_UNSUPPORTED); 2371 break; 2372 case WifiP2pManager.DELETE_PERSISTENT_GROUP: 2373 replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, 2374 WifiP2pManager.P2P_UNSUPPORTED); 2375 break; 2376 case WifiP2pManager.SET_WFD_INFO: 2377 if (!getWfdPermission(message.sendingUid)) { 2378 loge("No WFD permission, uid = " + message.sendingUid); 2379 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 2380 WifiP2pManager.ERROR); 2381 } else { 2382 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 2383 WifiP2pManager.P2P_UNSUPPORTED); 2384 } 2385 break; 2386 case WifiP2pManager.START_WPS: 2387 replyToMessage(message, WifiP2pManager.START_WPS_FAILED, 2388 WifiP2pManager.P2P_UNSUPPORTED); 2389 break; 2390 case WifiP2pManager.START_LISTEN: 2391 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED, 2392 WifiP2pManager.P2P_UNSUPPORTED); 2393 break; 2394 case WifiP2pManager.STOP_LISTEN: 2395 replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED, 2396 WifiP2pManager.P2P_UNSUPPORTED); 2397 break; 2398 case WifiP2pManager.FACTORY_RESET: 2399 replyToMessage(message, WifiP2pManager.FACTORY_RESET_FAILED, 2400 WifiP2pManager.P2P_UNSUPPORTED); 2401 break; 2402 case WifiP2pManager.REMOVE_CLIENT: 2403 replyToMessage(message, WifiP2pManager.REMOVE_CLIENT_FAILED, 2404 WifiP2pManager.P2P_UNSUPPORTED); 2405 break; 2406 case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: 2407 replyToMessage(message, WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_FAILED, 2408 WifiP2pManager.P2P_UNSUPPORTED); 2409 break; 2410 case WifiP2pManager.SET_VENDOR_ELEMENTS: 2411 replyToMessage(message, WifiP2pManager.SET_VENDOR_ELEMENTS_FAILED, 2412 WifiP2pManager.P2P_UNSUPPORTED); 2413 break; 2414 2415 default: 2416 return NOT_HANDLED; 2417 } 2418 return HANDLED; 2419 } 2420 } 2421 2422 class P2pDisablingState extends State { 2423 @Override enter()2424 public void enter() { 2425 logSmStateName(this.getName(), 2426 getCurrentState() != null ? getCurrentState().getName() : ""); 2427 sendMessageDelayed(obtainMessage(DISABLE_P2P_TIMED_OUT, 2428 ++sDisableP2pTimeoutIndex, 0), DISABLE_P2P_WAIT_TIME_MS); 2429 } 2430 2431 @Override processMessage(Message message)2432 public boolean processMessage(Message message) { 2433 logSmMessage(getName(), message); 2434 switch (message.what) { 2435 case WifiP2pMonitor.SUP_DISCONNECTION_EVENT: 2436 if (mVerboseLoggingEnabled) logd("p2p socket connection lost"); 2437 smTransition(this, mP2pDisabledState); 2438 break; 2439 case ENABLE_P2P: 2440 case DISABLE_P2P: 2441 case REMOVE_CLIENT_INFO: 2442 deferMessage(message); 2443 break; 2444 case DISABLE_P2P_TIMED_OUT: 2445 if (sDisableP2pTimeoutIndex == message.arg1) { 2446 loge("P2p disable timed out"); 2447 smTransition(this, mP2pDisabledState); 2448 } 2449 break; 2450 default: 2451 return NOT_HANDLED; 2452 } 2453 return HANDLED; 2454 } 2455 } 2456 2457 class P2pDisabledContainerState extends State { // split due to b/220588514 2458 @Override enter()2459 public void enter() { 2460 logSmStateName(this.getName(), 2461 getCurrentState() != null ? getCurrentState().getName() : ""); 2462 mInterfaceName = null; // reset iface name on disable. 2463 mActiveClients.clear(); 2464 clearP2pInternalDataIfNecessary(); 2465 if (mIsBootComplete) { 2466 updateThisDevice(WifiP2pDevice.UNAVAILABLE); 2467 } 2468 resetWifiP2pInfo(); 2469 mGroup = null; 2470 } 2471 } 2472 2473 class P2pDisabledState extends State { setupInterfaceFeatures()2474 private void setupInterfaceFeatures() { 2475 if (mWifiGlobals.isP2pMacRandomizationSupported()) { 2476 Log.i(TAG, "Supported feature: P2P MAC randomization"); 2477 mWifiNative.setMacRandomization(true); 2478 } else { 2479 mWifiNative.setMacRandomization(false); 2480 } 2481 } 2482 takeBugReportInterfaceFailureIfNeeded(String bugTitle, String bugDetail)2483 private void takeBugReportInterfaceFailureIfNeeded(String bugTitle, String bugDetail) { 2484 if (mWifiInjector.getDeviceConfigFacade().isInterfaceFailureBugreportEnabled()) { 2485 mWifiInjector.getWifiDiagnostics().takeBugReport(bugTitle, bugDetail); 2486 } 2487 } 2488 setupInterface()2489 private boolean setupInterface() { 2490 if (!isWifiP2pAvailable()) { 2491 Log.e(TAG, "Ignore P2P enable since wifi is " + mIsWifiEnabled 2492 + ", P2P disallowed by admin=" + mIsP2pDisallowedByAdmin); 2493 return false; 2494 } 2495 WorkSource requestorWs = createMergedRequestorWs(); 2496 mInterfaceName = mWifiNative.setupInterface((String ifaceName) -> { 2497 sendMessage(DISABLE_P2P); 2498 checkAndSendP2pStateChangedBroadcast(); 2499 }, getHandler(), requestorWs); 2500 if (mInterfaceName == null) { 2501 String errorMsg = "Failed to setup interface for P2P"; 2502 Log.e(TAG, errorMsg); 2503 if (!mHalDeviceManager.isItPossibleToCreateIface( 2504 HalDeviceManager.HDM_CREATE_IFACE_P2P, requestorWs)) { 2505 Log.w(TAG, "Interface resource is not available"); 2506 } else { 2507 takeBugReportInterfaceFailureIfNeeded( 2508 "Wi-Fi BugReport (P2P interface failure)", errorMsg); 2509 } 2510 return false; 2511 } 2512 setupInterfaceFeatures(); 2513 try { 2514 mNetdWrapper.setInterfaceUp(mInterfaceName); 2515 } catch (IllegalStateException ie) { 2516 loge("Unable to change interface settings: " + ie); 2517 } 2518 registerForWifiMonitorEvents(); 2519 return true; 2520 } 2521 2522 @Override processMessage(Message message)2523 public boolean processMessage(Message message) { 2524 logSmMessage(getName(), message); 2525 boolean wasInWaitingState = WaitingState.wasMessageInWaitingState(message); 2526 switch (message.what) { 2527 case ENABLE_P2P: { 2528 if (mActiveClients.isEmpty()) { 2529 Log.i(TAG, "No active client, ignore ENABLE_P2P."); 2530 // If this is a re-executed command triggered by user reply, then reset 2531 // InterfaceConflictManager so it isn't stuck waiting for the 2532 // re-executed command. 2533 if (wasInWaitingState) { 2534 mInterfaceConflictManager.reset(); 2535 } 2536 break; 2537 } 2538 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 2539 if (TextUtils.isEmpty(packageName)) { 2540 Log.i(TAG, "No valid package name, ignore ENABLE_P2P"); 2541 break; 2542 } 2543 int proceedWithOperation = 2544 mInterfaceConflictManager.manageInterfaceConflictForStateMachine( 2545 TAG, message, mP2pStateMachine, mWaitingState, 2546 mP2pDisabledState, HalDeviceManager.HDM_CREATE_IFACE_P2P, 2547 createRequestorWs(message.sendingUid, packageName), 2548 false /* bypassDialog */); 2549 if (proceedWithOperation == InterfaceConflictManager.ICM_ABORT_COMMAND) { 2550 Log.e(TAG, "User refused to set up P2P"); 2551 updateThisDevice(WifiP2pDevice.UNAVAILABLE); 2552 } else if (proceedWithOperation 2553 == InterfaceConflictManager.ICM_EXECUTE_COMMAND) { 2554 if (setupInterface()) { 2555 smTransition(this, mInactiveState); 2556 } 2557 } // else InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER: nop 2558 break; 2559 } 2560 case REMOVE_CLIENT_INFO: { 2561 if (!(message.obj instanceof IBinder)) { 2562 loge("Invalid obj when REMOVE_CLIENT_INFO"); 2563 break; 2564 } 2565 IBinder b = (IBinder) message.obj; 2566 // client service info is clear before enter disable p2p, 2567 // just need to remove it from list 2568 Messenger m = mClientChannelList.remove(b); 2569 ClientInfo clientInfo = mClientInfoList.remove(m); 2570 if (clientInfo != null) { 2571 logd("Remove client - " + clientInfo.mPackageName); 2572 } 2573 detachExternalApproverFromClient(b); 2574 break; 2575 } 2576 default: { 2577 // only handle commands from clients and only commands 2578 // which require P2P to be active. 2579 if (!needsActiveP2p(message.what)) { 2580 return NOT_HANDLED; 2581 } 2582 // If P2P is not ready, it might be disabled due 2583 // to another interface, ex. turn on softap from 2584 // the quicksettings. 2585 // As the new priority scheme, the foreground app 2586 // might be able to use P2P, so just try to enable 2587 // it. 2588 // Check & re-enable P2P if needed. 2589 // P2P interface will be created if all of the below are true: 2590 // a) Wifi is enabled. 2591 // b) There is at least 1 client app which invoked initialize(). 2592 // c) There is no impact to create another P2P interface 2593 // OR there is impact but user input isn't required 2594 // OR there is impact and user input is required and the user approved 2595 // the interface creation. 2596 if (mVerboseLoggingEnabled) { 2597 Log.d(TAG, "Wifi enabled=" + mIsWifiEnabled 2598 + ", P2P disallowed by admin=" + mIsP2pDisallowedByAdmin 2599 + ", Number of clients=" + mDeathDataByBinder.size() 2600 + " wasInWaitingState: " + wasInWaitingState); 2601 } 2602 if (!isWifiP2pAvailable() || mDeathDataByBinder.isEmpty()) { 2603 // If this is a re-executed command triggered by user reply, then reset 2604 // InterfaceConflictManager so it isn't stuck waiting for the 2605 // re-executed command. 2606 if (wasInWaitingState) { 2607 mInterfaceConflictManager.reset(); 2608 } 2609 return NOT_HANDLED; 2610 } 2611 2612 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 2613 if (TextUtils.isEmpty(packageName)) { 2614 Log.i(TAG, "No valid package name, do not set up the P2P interface"); 2615 return NOT_HANDLED; 2616 } 2617 int proceedWithOperation = 2618 mInterfaceConflictManager.manageInterfaceConflictForStateMachine( 2619 TAG, message, mP2pStateMachine, mWaitingState, 2620 mP2pDisabledState, HalDeviceManager.HDM_CREATE_IFACE_P2P, 2621 createRequestorWs(message.sendingUid, packageName), 2622 false /* bypassDialog */); 2623 if (proceedWithOperation == InterfaceConflictManager.ICM_ABORT_COMMAND) { 2624 Log.e(TAG, "User refused to set up P2P"); 2625 updateThisDevice(WifiP2pDevice.UNAVAILABLE); 2626 return NOT_HANDLED; 2627 } else if (proceedWithOperation 2628 == InterfaceConflictManager.ICM_EXECUTE_COMMAND) { 2629 if (!setupInterface()) return NOT_HANDLED; 2630 deferMessage(message); 2631 smTransition(this, mInactiveState); 2632 } // else InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER: nop 2633 break; 2634 } 2635 } 2636 return HANDLED; 2637 } 2638 } 2639 2640 class P2pEnabledState extends State { 2641 @Override enter()2642 public void enter() { 2643 logSmStateName(this.getName(), 2644 getCurrentState() != null ? getCurrentState().getName() : ""); 2645 2646 if (isPendingFactoryReset()) { 2647 factoryReset(Process.SYSTEM_UID); 2648 } 2649 2650 checkCoexUnsafeChannels(); 2651 2652 sendP2pConnectionChangedBroadcast(); 2653 initializeP2pSettings(); 2654 if (mTetheringManager != null) { 2655 mTetheringManager.registerTetheringEventCallback(getHandler()::post, 2656 mTetheringEventCallback); 2657 } 2658 } 2659 2660 @Override processMessage(Message message)2661 public boolean processMessage(Message message) { 2662 logSmMessage(getName(), message); 2663 switch (message.what) { 2664 case WifiP2pMonitor.SUP_DISCONNECTION_EVENT: 2665 loge("Unexpected loss of p2p socket connection"); 2666 smTransition(this, mP2pDisabledState); 2667 break; 2668 case ENABLE_P2P: 2669 if (!mWifiNative.replaceRequestorWs(createMergedRequestorWs())) { 2670 Log.e(TAG, "Failed to replace requestorWs"); 2671 } 2672 break; 2673 case DISABLE_P2P: 2674 if (mPeers.clear()) { 2675 sendPeersChangedBroadcast(); 2676 } 2677 if (mGroups.clear()) sendP2pPersistentGroupsChangedBroadcast(); 2678 // clear services list for all clients since interface will teardown soon. 2679 clearServicesForAllClients(); 2680 mWifiMonitor.stopMonitoring(mInterfaceName); 2681 mWifiNative.teardownInterface(); 2682 smTransition(this, mP2pDisablingState); 2683 break; 2684 case REMOVE_CLIENT_INFO: 2685 if (!(message.obj instanceof IBinder)) { 2686 break; 2687 } 2688 IBinder b = (IBinder) message.obj; 2689 // clear client info and remove it from list 2690 clearClientInfo(mClientChannelList.get(b)); 2691 mClientChannelList.remove(b); 2692 if (!mWifiNative.replaceRequestorWs(createMergedRequestorWs())) { 2693 Log.e(TAG, "Failed to replace requestorWs"); 2694 } 2695 detachExternalApproverFromClient(b); 2696 break; 2697 case WifiP2pManager.SET_WFD_INFO: 2698 { 2699 WifiP2pWfdInfo d = (WifiP2pWfdInfo) message.obj; 2700 if (!getWfdPermission(message.sendingUid)) { 2701 loge("No WFD permission, uid = " + message.sendingUid); 2702 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 2703 WifiP2pManager.ERROR); 2704 } else if (d != null && setWfdInfo(d)) { 2705 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_SUCCEEDED); 2706 } else { 2707 replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, 2708 WifiP2pManager.ERROR); 2709 } 2710 break; 2711 } 2712 case BLOCK_DISCOVERY: 2713 boolean blocked = (message.arg1 == ENABLED); 2714 if (mDiscoveryBlocked == blocked) break; 2715 mDiscoveryBlocked = blocked; 2716 if (blocked && mDiscoveryStarted) { 2717 mWifiNative.p2pStopFind(); 2718 mDiscoveryPostponed = true; 2719 } 2720 if (!blocked && mDiscoveryPostponed) { 2721 mDiscoveryPostponed = false; 2722 if (p2pFind(DISCOVER_TIMEOUT_S)) { 2723 sendP2pDiscoveryChangedBroadcast(true); 2724 } 2725 } 2726 if (blocked && mWifiChannel != null) { 2727 mWifiChannel.replyToMessage(message, message.arg2); 2728 } 2729 break; 2730 case WifiP2pManager.DISCOVER_PEERS: { 2731 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 2732 if (packageName == null) { 2733 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 2734 WifiP2pManager.ERROR); 2735 break; 2736 } 2737 int scanType = message.arg1; 2738 int uid = message.sendingUid; 2739 Bundle extras = message.getData() 2740 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 2741 int freq = extras.getInt( 2742 WifiP2pManager.EXTRA_PARAM_KEY_PEER_DISCOVERY_FREQ, 2743 WifiP2pManager.WIFI_P2P_SCAN_FREQ_UNSPECIFIED); 2744 boolean hasPermission = false; 2745 if (scanType != WifiP2pManager.WIFI_P2P_SCAN_FULL 2746 && !isFeatureSupported(WifiP2pManager.FEATURE_FLEXIBLE_DISCOVERY)) { 2747 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 2748 WifiP2pManager.ERROR); 2749 } 2750 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 2751 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 2752 packageName, 2753 getCallingFeatureId(message.sendingUid, message.replyTo), 2754 uid, true); 2755 } else { 2756 hasPermission = checkNearbyDevicesPermission(uid, packageName, 2757 extras, "DISCOVER_PEERS", message.obj); 2758 } 2759 2760 if (!hasPermission) { 2761 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 2762 WifiP2pManager.ERROR); 2763 // remain at this state. 2764 break; 2765 } 2766 if (mDiscoveryBlocked) { 2767 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 2768 WifiP2pManager.BUSY); 2769 break; 2770 } 2771 int apiType = WifiManager.API_P2P_DISCOVER_PEERS; 2772 if (scanType == WifiP2pManager.WIFI_P2P_SCAN_SOCIAL) { 2773 apiType = WifiManager.API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS; 2774 } else if (scanType == WifiP2pManager.WIFI_P2P_SCAN_SINGLE_FREQ) { 2775 apiType = WifiManager.API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY; 2776 } 2777 mLastCallerInfoManager.put(apiType, Process.myTid(), uid, 0, packageName, 2778 true); 2779 // do not send service discovery request while normal find operation. 2780 clearSupplicantServiceRequest(); 2781 Log.e(TAG, "-------discover_peers before p2pFind"); 2782 if (p2pFind(scanType, freq, DISCOVER_TIMEOUT_S)) { 2783 mWifiP2pMetrics.incrementPeerScans(); 2784 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED); 2785 sendP2pDiscoveryChangedBroadcast(true); 2786 } else { 2787 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 2788 WifiP2pManager.ERROR); 2789 } 2790 break; 2791 } 2792 case WifiP2pMonitor.P2P_FIND_STOPPED_EVENT: 2793 mWifiNative.removeVendorElements(); 2794 sendP2pDiscoveryChangedBroadcast(false); 2795 break; 2796 case WifiP2pManager.STOP_DISCOVERY: 2797 mLastCallerInfoManager.put(WifiManager.API_P2P_STOP_PEER_DISCOVERY, 2798 Process.myTid(), message.sendingUid, 0, 2799 getCallingPkgName(message.sendingUid, message.replyTo), true); 2800 if (mWifiNative.p2pStopFind()) { 2801 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED); 2802 } else { 2803 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, 2804 WifiP2pManager.ERROR); 2805 } 2806 break; 2807 case WifiP2pManager.DISCOVER_SERVICES: { 2808 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 2809 if (packageName == null) { 2810 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 2811 WifiP2pManager.ERROR); 2812 break; 2813 } 2814 int uid = message.sendingUid; 2815 Bundle extras = message.getData() 2816 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 2817 boolean hasPermission = false; 2818 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 2819 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 2820 packageName, 2821 getCallingFeatureId(message.sendingUid, message.replyTo), 2822 uid, true); 2823 } else { 2824 hasPermission = checkNearbyDevicesPermission(uid, packageName, 2825 extras, "DISCOVER_SERVICES", message.obj); 2826 } 2827 if (!hasPermission) { 2828 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 2829 WifiP2pManager.ERROR); 2830 // remain at this state. 2831 break; 2832 } 2833 if (mDiscoveryBlocked) { 2834 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 2835 WifiP2pManager.BUSY); 2836 break; 2837 } 2838 if (mVerboseLoggingEnabled) logd(getName() + " discover services"); 2839 if (!updateSupplicantServiceRequest()) { 2840 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 2841 WifiP2pManager.NO_SERVICE_REQUESTS); 2842 break; 2843 } 2844 if (p2pFind(DISCOVER_TIMEOUT_S)) { 2845 sendP2pDiscoveryChangedBroadcast(true); 2846 mWifiP2pMetrics.incrementServiceScans(); 2847 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_SUCCEEDED); 2848 } else { 2849 replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, 2850 WifiP2pManager.ERROR); 2851 } 2852 break; 2853 } 2854 case WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT: 2855 if (message.obj == null) { 2856 Log.e(TAG, "Illegal argument(s)"); 2857 break; 2858 } 2859 WifiP2pDevice device = (WifiP2pDevice) message.obj; 2860 if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break; 2861 mPeers.updateSupplicantDetails(device); 2862 sendPeersChangedBroadcast(); 2863 break; 2864 case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: 2865 if (message.obj == null) { 2866 Log.e(TAG, "Illegal argument(s)"); 2867 break; 2868 } 2869 device = (WifiP2pDevice) message.obj; 2870 // Gets current details for the one removed 2871 device = mPeers.remove(device.deviceAddress); 2872 if (device != null) { 2873 sendPeersChangedBroadcast(); 2874 } 2875 break; 2876 case WifiP2pManager.ADD_LOCAL_SERVICE: { 2877 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 2878 if (packageName == null) { 2879 replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED); 2880 break; 2881 } 2882 int uid = message.sendingUid; 2883 Bundle extras = message.getData() 2884 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 2885 boolean hasPermission; 2886 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 2887 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 2888 packageName, 2889 getCallingFeatureId(message.sendingUid, message.replyTo), 2890 uid, false); 2891 } else { 2892 hasPermission = checkNearbyDevicesPermission(uid, packageName, 2893 extras, "ADD_LOCAL_SERVICE", message.obj); 2894 } 2895 if (!hasPermission) { 2896 replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED); 2897 // remain at this state. 2898 break; 2899 } 2900 if (mVerboseLoggingEnabled) logd(getName() + " add service"); 2901 WifiP2pServiceInfo servInfo = 2902 extras.getParcelable(WifiP2pManager.EXTRA_PARAM_KEY_SERVICE_INFO); 2903 if (addLocalService(message.replyTo, servInfo)) { 2904 replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_SUCCEEDED); 2905 } else { 2906 replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED); 2907 } 2908 break; 2909 } 2910 case WifiP2pManager.REMOVE_LOCAL_SERVICE: 2911 if (mVerboseLoggingEnabled) logd(getName() + " remove service"); 2912 WifiP2pServiceInfo servInfo = (WifiP2pServiceInfo) message.obj; 2913 removeLocalService(message.replyTo, servInfo); 2914 replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_SUCCEEDED); 2915 break; 2916 case WifiP2pManager.CLEAR_LOCAL_SERVICES: 2917 if (mVerboseLoggingEnabled) logd(getName() + " clear service"); 2918 clearLocalServices(message.replyTo); 2919 replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_SUCCEEDED); 2920 break; 2921 case WifiP2pManager.ADD_SERVICE_REQUEST: 2922 if (mVerboseLoggingEnabled) logd(getName() + " add service request"); 2923 if (!addServiceRequest(message.replyTo, 2924 (WifiP2pServiceRequest) message.obj)) { 2925 replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED); 2926 break; 2927 } 2928 replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_SUCCEEDED); 2929 break; 2930 case WifiP2pManager.REMOVE_SERVICE_REQUEST: 2931 if (mVerboseLoggingEnabled) logd(getName() + " remove service request"); 2932 removeServiceRequest(message.replyTo, (WifiP2pServiceRequest) message.obj); 2933 replyToMessage(message, WifiP2pManager.REMOVE_SERVICE_REQUEST_SUCCEEDED); 2934 break; 2935 case WifiP2pManager.CLEAR_SERVICE_REQUESTS: 2936 if (mVerboseLoggingEnabled) logd(getName() + " clear service request"); 2937 clearServiceRequests(message.replyTo); 2938 replyToMessage(message, WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED); 2939 break; 2940 case WifiP2pMonitor.P2P_SERV_DISC_RESP_EVENT: 2941 if (mVerboseLoggingEnabled) { 2942 logd(getName() + " receive service response"); 2943 } 2944 if (message.obj == null) { 2945 Log.e(TAG, "Illegal argument(s)"); 2946 break; 2947 } 2948 List<WifiP2pServiceResponse> sdRespList = 2949 (List<WifiP2pServiceResponse>) message.obj; 2950 for (WifiP2pServiceResponse resp : sdRespList) { 2951 WifiP2pDevice dev = 2952 mPeers.get(resp.getSrcDevice().deviceAddress); 2953 resp.setSrcDevice(dev); 2954 sendServiceResponse(resp); 2955 } 2956 break; 2957 case WifiP2pManager.DELETE_PERSISTENT_GROUP: 2958 if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( 2959 message.sendingUid)) { 2960 loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," 2961 + " or OVERRIDE_WIFI_CONFIG permission, uid = " 2962 + message.sendingUid); 2963 replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED, 2964 WifiP2pManager.ERROR); 2965 break; 2966 } 2967 if (mVerboseLoggingEnabled) logd(getName() + " delete persistent group"); 2968 mGroups.remove(message.arg1); 2969 mWifiP2pMetrics.updatePersistentGroup(mGroups); 2970 replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_SUCCEEDED); 2971 break; 2972 case SET_MIRACAST_MODE: 2973 mWifiNative.setMiracastMode(message.arg1); 2974 break; 2975 case WifiP2pManager.START_LISTEN: 2976 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 2977 if (packageName == null) { 2978 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); 2979 break; 2980 } 2981 int uid = message.sendingUid; 2982 Bundle extras = message.getData() 2983 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 2984 boolean hasPermission; 2985 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 2986 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 2987 packageName, 2988 getCallingFeatureId(message.sendingUid, message.replyTo), 2989 uid, true); 2990 } else { 2991 hasPermission = checkNearbyDevicesPermission(uid, packageName, 2992 extras, "START_LISTEN", message.obj); 2993 } 2994 if (!hasPermission) { 2995 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); 2996 break; 2997 } 2998 mLastCallerInfoManager.put(WifiManager.API_P2P_START_LISTENING, 2999 Process.myTid(), uid, 0, packageName, true); 3000 if (mVerboseLoggingEnabled) logd(getName() + " start listen mode"); 3001 mWifiNative.p2pStopFind(); 3002 if (mWifiNative.p2pExtListen(true, 3003 mContext.getResources().getInteger( 3004 R.integer.config_wifiP2pExtListenPeriodMs), 3005 mContext.getResources().getInteger( 3006 R.integer.config_wifiP2pExtListenIntervalMs))) { 3007 replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED); 3008 sendP2pListenChangedBroadcast(true); 3009 } else { 3010 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); 3011 } 3012 break; 3013 case WifiP2pManager.STOP_LISTEN: 3014 mLastCallerInfoManager.put(WifiManager.API_P2P_STOP_LISTENING, 3015 Process.myTid(), message.sendingUid, 0, 3016 getCallingPkgName(message.sendingUid, message.replyTo), true); 3017 if (mVerboseLoggingEnabled) logd(getName() + " stop listen mode"); 3018 if (mWifiNative.p2pExtListen(false, 0, 0)) { 3019 replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); 3020 sendP2pListenChangedBroadcast(false); 3021 } else { 3022 replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); 3023 } 3024 mWifiNative.p2pStopFind(); 3025 break; 3026 case WifiP2pManager.SET_CHANNEL: 3027 if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( 3028 message.sendingUid)) { 3029 loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," 3030 + " or OVERRIDE_WIFI_CONFIG permission, uid = " 3031 + message.sendingUid); 3032 replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED, 3033 WifiP2pManager.ERROR); 3034 break; 3035 } 3036 if (message.obj == null) { 3037 Log.e(TAG, "Illegal arguments(s)"); 3038 break; 3039 } 3040 mLastCallerInfoManager.put(WifiManager.API_P2P_SET_CHANNELS, 3041 Process.myTid(), message.sendingUid, 0, 3042 getCallingPkgName(message.sendingUid, message.replyTo), true); 3043 Bundle p2pChannels = (Bundle) message.obj; 3044 mUserListenChannel = p2pChannels.getInt("lc", 0); 3045 mUserOperatingChannel = p2pChannels.getInt("oc", 0); 3046 if (updateP2pChannels()) { 3047 replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED); 3048 } else { 3049 replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED); 3050 } 3051 break; 3052 case WifiP2pManager.GET_HANDOVER_REQUEST: 3053 Bundle requestBundle = new Bundle(); 3054 requestBundle.putString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE, 3055 mWifiNative.getNfcHandoverRequest()); 3056 replyToMessage(message, WifiP2pManager.RESPONSE_GET_HANDOVER_MESSAGE, 3057 requestBundle); 3058 break; 3059 case WifiP2pManager.GET_HANDOVER_SELECT: 3060 Bundle selectBundle = new Bundle(); 3061 selectBundle.putString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE, 3062 mWifiNative.getNfcHandoverSelect()); 3063 replyToMessage(message, WifiP2pManager.RESPONSE_GET_HANDOVER_MESSAGE, 3064 selectBundle); 3065 break; 3066 case UPDATE_P2P_DISALLOWED_CHANNELS: 3067 mCoexUnsafeChannels.clear(); 3068 if (null != message.obj) { 3069 mCoexUnsafeChannels.addAll((List<CoexUnsafeChannel>) message.obj); 3070 } 3071 updateP2pChannels(); 3072 break; 3073 default: 3074 return NOT_HANDLED; 3075 } 3076 return HANDLED; 3077 } 3078 3079 @Override exit()3080 public void exit() { 3081 sendP2pDiscoveryChangedBroadcast(false); 3082 sendP2pListenChangedBroadcast(false); 3083 mUserListenChannel = 0; 3084 mUserOperatingChannel = 0; 3085 mCoexUnsafeChannels.clear(); 3086 if (mTetheringManager != null) { 3087 mTetheringManager.unregisterTetheringEventCallback(mTetheringEventCallback); 3088 } 3089 } 3090 } 3091 3092 class InactiveState extends State { 3093 @Override enter()3094 public void enter() { 3095 logSmStateName(this.getName(), 3096 getCurrentState() != null ? getCurrentState().getName() : ""); 3097 mPeerAuthorizingTimestamp.clear(); 3098 mSavedPeerConfig.invalidate(); 3099 mDetailedState = NetworkInfo.DetailedState.IDLE; 3100 scheduleIdleShutdown(); 3101 } 3102 3103 @Override exit()3104 public void exit() { 3105 cancelIdleShutdown(); 3106 } 3107 3108 @Override processMessage(Message message)3109 public boolean processMessage(Message message) { 3110 logSmMessage(getName(), message); 3111 // Re-schedule the shutdown timer since we got the new operation. 3112 // only handle commands from clients. 3113 if (message.what > Protocol.BASE_WIFI_P2P_MANAGER 3114 && message.what < Protocol.BASE_WIFI_P2P_SERVICE) { 3115 scheduleIdleShutdown(); 3116 } 3117 switch (message.what) { 3118 case WifiP2pManager.CONNECT: { 3119 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 3120 if (packageName == null) { 3121 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 3122 break; 3123 } 3124 int uid = message.sendingUid; 3125 Bundle extras = message.getData() 3126 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 3127 boolean hasPermission = false; 3128 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 3129 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 3130 packageName, 3131 getCallingFeatureId(message.sendingUid, message.replyTo), 3132 uid, false); 3133 } else { 3134 hasPermission = checkNearbyDevicesPermission(uid, packageName, 3135 extras, "CONNECT", message.obj); 3136 } 3137 if (!hasPermission) { 3138 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 3139 // remain at this state. 3140 break; 3141 } 3142 mLastCallerInfoManager.put(WifiManager.API_P2P_CONNECT, 3143 Process.myTid(), uid, 0, packageName, true); 3144 if (mVerboseLoggingEnabled) logd(getName() + " sending connect"); 3145 WifiP2pConfig config = (WifiP2pConfig) 3146 extras.getParcelable(WifiP2pManager.EXTRA_PARAM_KEY_CONFIG); 3147 3148 boolean isConnectFailed = false; 3149 if (isConfigValidAsGroup(config)) { 3150 mAutonomousGroup = false; 3151 mWifiNative.p2pStopFind(); 3152 if (mVerboseLoggingEnabled) { 3153 logd("FAST_CONNECTION GC band freq: " + getGroupOwnerBandToString( 3154 config.groupOwnerBand)); 3155 } 3156 if (mWifiNative.p2pGroupAdd(config, true)) { 3157 reportConnectionEventTakeBugReportIfOverlapped( 3158 P2pConnectionEvent.CONNECTION_FAST, 3159 config, WifiMetricsProto.GroupEvent.GROUP_CLIENT, uid); 3160 smTransition(this, mGroupNegotiationState); 3161 } else { 3162 loge("Cannot join a group with config."); 3163 isConnectFailed = true; 3164 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 3165 } 3166 } else { 3167 if (isConfigInvalid(config)) { 3168 loge("Dropping connect request " + config); 3169 isConnectFailed = true; 3170 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 3171 } else { 3172 mAutonomousGroup = false; 3173 mWifiNative.p2pStopFind(); 3174 if (reinvokePersistentGroup(config, false)) { 3175 mWifiP2pMetrics.startConnectionEvent( 3176 P2pConnectionEvent.CONNECTION_REINVOKE, 3177 config, GroupEvent.GROUP_UNKNOWN, uid); 3178 smTransition(this, mGroupNegotiationState); 3179 } else { 3180 mWifiP2pMetrics.startConnectionEvent( 3181 P2pConnectionEvent.CONNECTION_FRESH, 3182 config, GroupEvent.GROUP_UNKNOWN, uid); 3183 smTransition(this, mProvisionDiscoveryState); 3184 } 3185 } 3186 } 3187 3188 if (!isConnectFailed) { 3189 mSavedPeerConfig = config; 3190 mPeers.updateStatus(mSavedPeerConfig.deviceAddress, 3191 WifiP2pDevice.INVITED); 3192 sendPeersChangedBroadcast(); 3193 replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); 3194 } 3195 break; 3196 } 3197 case WifiP2pManager.STOP_DISCOVERY: 3198 mLastCallerInfoManager.put(WifiManager.API_P2P_STOP_PEER_DISCOVERY, 3199 Process.myTid(), message.sendingUid, 0, 3200 getCallingPkgName(message.sendingUid, message.replyTo), true); 3201 if (mWifiNative.p2pStopFind()) { 3202 // When discovery stops in inactive state, flush to clear 3203 // state peer data 3204 mWifiNative.p2pFlush(); 3205 mServiceDiscReqId = null; 3206 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED); 3207 } else { 3208 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, 3209 WifiP2pManager.ERROR); 3210 } 3211 break; 3212 case CMD_P2P_IDLE_SHUTDOWN: 3213 Log.d(TAG, "IdleShutDown message received"); 3214 sendMessage(DISABLE_P2P); 3215 break; 3216 case WifiP2pMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT: 3217 WifiP2pConfig config = (WifiP2pConfig) message.obj; 3218 if (isConfigInvalid(config)) { 3219 loge("Dropping GO neg request " + config); 3220 break; 3221 } 3222 mSavedPeerConfig = config; 3223 mAutonomousGroup = false; 3224 mJoinExistingGroup = false; 3225 mWifiP2pMetrics.startConnectionEvent( 3226 P2pConnectionEvent.CONNECTION_FRESH, 3227 config, GroupEvent.GROUP_UNKNOWN, Process.SYSTEM_UID); 3228 smTransition(this, mUserAuthorizingNegotiationRequestState); 3229 break; 3230 case WifiP2pMonitor.P2P_INVITATION_RECEIVED_EVENT: 3231 if (message.obj == null) { 3232 Log.e(TAG, "Invalid argument(s)"); 3233 break; 3234 } 3235 WifiP2pGroup group = (WifiP2pGroup) message.obj; 3236 WifiP2pDevice owner = group.getOwner(); 3237 if (owner == null) { 3238 int id = group.getNetworkId(); 3239 if (id < 0) { 3240 loge("Ignored invitation from null owner"); 3241 break; 3242 } 3243 3244 String addr = mGroups.getOwnerAddr(id); 3245 if (addr != null) { 3246 group.setOwner(new WifiP2pDevice(addr)); 3247 owner = group.getOwner(); 3248 } else { 3249 loge("Ignored invitation from null owner"); 3250 break; 3251 } 3252 } 3253 config = new WifiP2pConfig(); 3254 config.deviceAddress = group.getOwner().deviceAddress; 3255 if (isConfigInvalid(config)) { 3256 loge("Dropping invitation request " + config); 3257 break; 3258 } 3259 mSavedPeerConfig = config; 3260 3261 // Check if we have the owner in peer list and use appropriate 3262 // wps method. Default is to use PBC. 3263 if (owner != null && ((owner = mPeers.get(owner.deviceAddress)) != null)) { 3264 if (owner.wpsPbcSupported()) { 3265 mSavedPeerConfig.wps.setup = WpsInfo.PBC; 3266 } else if (owner.wpsKeypadSupported()) { 3267 mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; 3268 } else if (owner.wpsDisplaySupported()) { 3269 mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; 3270 } 3271 } 3272 3273 mAutonomousGroup = false; 3274 mJoinExistingGroup = true; 3275 mWifiP2pMetrics.startConnectionEvent( 3276 P2pConnectionEvent.CONNECTION_FRESH, 3277 config, GroupEvent.GROUP_UNKNOWN, Process.SYSTEM_UID); 3278 smTransition(this, mUserAuthorizingInviteRequestState); 3279 break; 3280 case WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: 3281 case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: 3282 // We let the supplicant handle the provision discovery response 3283 // and wait instead for the GO_NEGOTIATION_REQUEST_EVENT. 3284 // Handling provision discovery and issuing a p2p_connect before 3285 // group negotiation comes through causes issues 3286 break; 3287 case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: 3288 if (message.obj == null) { 3289 Log.e(TAG, "Illegal argument(s)"); 3290 break; 3291 } 3292 WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj; 3293 WifiP2pDevice device = provDisc.device; 3294 if (device == null) { 3295 loge("Device entry is null"); 3296 break; 3297 } 3298 mSavedPeerConfig = new WifiP2pConfig(); 3299 mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; 3300 mSavedPeerConfig.deviceAddress = device.deviceAddress; 3301 mSavedPeerConfig.wps.pin = provDisc.pin; 3302 3303 notifyP2pProvDiscShowPinRequest(provDisc.pin, device.deviceAddress); 3304 mPeers.updateStatus(device.deviceAddress, WifiP2pDevice.INVITED); 3305 sendPeersChangedBroadcast(); 3306 smTransition(this, mUserAuthorizingNegotiationRequestState); 3307 break; 3308 case WifiP2pManager.CREATE_GROUP: { 3309 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 3310 if (packageName == null) { 3311 replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, 3312 WifiP2pManager.ERROR); 3313 break; 3314 } 3315 int uid = message.sendingUid; 3316 Bundle extras = message.getData() 3317 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 3318 boolean hasPermission; 3319 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 3320 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 3321 packageName, 3322 getCallingFeatureId(message.sendingUid, message.replyTo), 3323 uid, false); 3324 } else { 3325 hasPermission = checkNearbyDevicesPermission(uid, packageName, 3326 extras, "CREATE_GROUP", message.obj); 3327 } 3328 if (!hasPermission) { 3329 replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, 3330 WifiP2pManager.ERROR); 3331 // remain at this state. 3332 break; 3333 } 3334 mAutonomousGroup = true; 3335 int netId = message.arg1; 3336 config = extras.getParcelable(WifiP2pManager.EXTRA_PARAM_KEY_CONFIG); 3337 mLastCallerInfoManager.put(config == null 3338 ? WifiManager.API_P2P_CREATE_GROUP 3339 : WifiManager.API_P2P_CREATE_GROUP_P2P_CONFIG, 3340 Process.myTid(), uid, 0, packageName, true); 3341 boolean ret = false; 3342 if (config != null) { 3343 if (isConfigValidAsGroup(config)) { 3344 if (mVerboseLoggingEnabled) { 3345 logd("FAST_CONNECTION GO band freq: " 3346 + getGroupOwnerBandToString(config.groupOwnerBand)); 3347 } 3348 reportConnectionEventTakeBugReportIfOverlapped( 3349 P2pConnectionEvent.CONNECTION_FAST, 3350 config, GroupEvent.GROUP_OWNER, uid); 3351 ret = mWifiNative.p2pGroupAdd(config, false); 3352 } 3353 } else if (netId == WifiP2pGroup.NETWORK_ID_PERSISTENT) { 3354 // check if the go persistent group is present. 3355 netId = mGroups.getNetworkId(mThisDevice.deviceAddress); 3356 if (netId != -1) { 3357 mWifiP2pMetrics.startConnectionEvent( 3358 P2pConnectionEvent.CONNECTION_REINVOKE, 3359 null, GroupEvent.GROUP_OWNER, uid); 3360 ret = mWifiNative.p2pGroupAdd(netId); 3361 } else { 3362 mWifiP2pMetrics.startConnectionEvent( 3363 P2pConnectionEvent.CONNECTION_LOCAL, 3364 null, GroupEvent.GROUP_OWNER, uid); 3365 ret = mWifiNative.p2pGroupAdd(true); 3366 } 3367 } else { 3368 mWifiP2pMetrics.startConnectionEvent( 3369 P2pConnectionEvent.CONNECTION_LOCAL, 3370 null, GroupEvent.GROUP_OWNER, uid); 3371 ret = mWifiNative.p2pGroupAdd(false); 3372 } 3373 3374 if (ret) { 3375 replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED); 3376 smTransition(this, mGroupNegotiationState); 3377 } else { 3378 replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, 3379 WifiP2pManager.ERROR); 3380 // remain at this state. 3381 String errorMsg = "P2P group creating failed"; 3382 if (mVerboseLoggingEnabled) logd(getName() + errorMsg); 3383 if (mWifiP2pMetrics.isP2pFastConnectionType()) { 3384 takeBugReportP2pFailureIfNeeded("Wi-Fi BugReport (P2P " 3385 + mWifiP2pMetrics.getP2pGroupRoleString() 3386 + " creation failure)", errorMsg); 3387 } 3388 mWifiP2pMetrics.endConnectionEvent( 3389 P2pConnectionEvent.CLF_CREATE_GROUP_FAILED); 3390 } 3391 break; 3392 } 3393 case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: 3394 if (message.obj == null) { 3395 Log.e(TAG, "Invalid argument(s)"); 3396 break; 3397 } 3398 mGroup = (WifiP2pGroup) message.obj; 3399 if (mVerboseLoggingEnabled) logd(getName() + " group started"); 3400 if (mGroup.isGroupOwner() 3401 && EMPTY_DEVICE_ADDRESS.equals(mGroup.getOwner().deviceAddress)) { 3402 // wpa_supplicant doesn't set own device address to go_dev_addr. 3403 mGroup.getOwner().deviceAddress = mThisDevice.deviceAddress; 3404 } 3405 // We hit this scenario when a persistent group is reinvoked 3406 if (mGroup.getNetworkId() == WifiP2pGroup.NETWORK_ID_PERSISTENT) { 3407 mAutonomousGroup = false; 3408 deferMessage(message); 3409 smTransition(this, mGroupNegotiationState); 3410 } else { 3411 loge("Unexpected group creation, remove " + mGroup); 3412 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 3413 } 3414 break; 3415 case WifiP2pManager.START_LISTEN: 3416 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 3417 if (packageName == null) { 3418 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); 3419 break; 3420 } 3421 int uid = message.sendingUid; 3422 Bundle extras = message.getData() 3423 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 3424 boolean hasPermission; 3425 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 3426 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 3427 packageName, 3428 getCallingFeatureId(message.sendingUid, message.replyTo), 3429 uid, true); 3430 } else { 3431 hasPermission = checkNearbyDevicesPermission(uid, packageName, 3432 extras, "START_LISTEN", message.obj); 3433 } 3434 if (!hasPermission) { 3435 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); 3436 break; 3437 } 3438 mLastCallerInfoManager.put(WifiManager.API_P2P_START_LISTENING, 3439 Process.myTid(), uid, 0, packageName, true); 3440 if (mVerboseLoggingEnabled) logd(getName() + " start listen mode"); 3441 mWifiNative.p2pStopFind(); 3442 if (mWifiNative.p2pExtListen(true, 3443 mContext.getResources().getInteger( 3444 R.integer.config_wifiP2pExtListenPeriodMs), 3445 mContext.getResources().getInteger( 3446 R.integer.config_wifiP2pExtListenIntervalMs))) { 3447 replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED); 3448 sendP2pListenChangedBroadcast(true); 3449 } else { 3450 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); 3451 } 3452 break; 3453 case WifiP2pManager.STOP_LISTEN: 3454 mLastCallerInfoManager.put(WifiManager.API_P2P_STOP_LISTENING, 3455 Process.myTid(), message.sendingUid, 0, 3456 getCallingPkgName(message.sendingUid, message.replyTo), true); 3457 if (mVerboseLoggingEnabled) logd(getName() + " stop listen mode"); 3458 if (mWifiNative.p2pExtListen(false, 0, 0)) { 3459 replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); 3460 sendP2pListenChangedBroadcast(false); 3461 } else { 3462 replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); 3463 } 3464 mWifiNative.p2pStopFind(); 3465 break; 3466 case WifiP2pManager.SET_CHANNEL: 3467 if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( 3468 message.sendingUid)) { 3469 loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," 3470 + " or OVERRIDE_WIFI_CONFIG permission, uid = " 3471 + message.sendingUid); 3472 replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED, 3473 WifiP2pManager.ERROR); 3474 break; 3475 } 3476 if (message.obj == null) { 3477 Log.e(TAG, "Illegal arguments(s)"); 3478 break; 3479 } 3480 mLastCallerInfoManager.put(WifiManager.API_P2P_SET_CHANNELS, 3481 Process.myTid(), message.sendingUid, 0, 3482 getCallingPkgName(message.sendingUid, message.replyTo), true); 3483 Bundle p2pChannels = (Bundle) message.obj; 3484 mUserListenChannel = p2pChannels.getInt("lc", 0); 3485 mUserOperatingChannel = p2pChannels.getInt("oc", 0); 3486 if (updateP2pChannels()) { 3487 replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED); 3488 } else { 3489 replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED); 3490 } 3491 break; 3492 case WifiP2pManager.INITIATOR_REPORT_NFC_HANDOVER: 3493 String handoverSelect = null; 3494 3495 if (message.obj != null) { 3496 handoverSelect = ((Bundle) message.obj) 3497 .getString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE); 3498 } 3499 3500 if (handoverSelect != null 3501 && mWifiNative.initiatorReportNfcHandover(handoverSelect)) { 3502 replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_SUCCEEDED); 3503 smTransition(this, mGroupCreatingState); 3504 } else { 3505 replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED); 3506 } 3507 break; 3508 case WifiP2pManager.RESPONDER_REPORT_NFC_HANDOVER: 3509 String handoverRequest = null; 3510 3511 if (message.obj != null) { 3512 handoverRequest = ((Bundle) message.obj) 3513 .getString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE); 3514 } 3515 3516 if (handoverRequest != null 3517 && mWifiNative.responderReportNfcHandover(handoverRequest)) { 3518 replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_SUCCEEDED); 3519 smTransition(this, mGroupCreatingState); 3520 } else { 3521 replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED); 3522 } 3523 break; 3524 default: 3525 return NOT_HANDLED; 3526 } 3527 return HANDLED; 3528 } 3529 } 3530 3531 class GroupCreatingState extends State { 3532 @Override enter()3533 public void enter() { 3534 logSmStateName(this.getName(), 3535 getCurrentState() != null ? getCurrentState().getName() : ""); 3536 if (SdkLevel.isAtLeastT()) { 3537 mDetailedState = NetworkInfo.DetailedState.CONNECTING; 3538 sendP2pConnectionChangedBroadcast(); 3539 } 3540 sendMessageDelayed(obtainMessage(GROUP_CREATING_TIMED_OUT, 3541 ++sGroupCreatingTimeoutIndex, 0), GROUP_CREATING_WAIT_TIME_MS); 3542 } 3543 3544 @Override processMessage(Message message)3545 public boolean processMessage(Message message) { 3546 logSmMessage(getName(), message); 3547 boolean ret = HANDLED; 3548 switch (message.what) { 3549 case GROUP_CREATING_TIMED_OUT: 3550 if (sGroupCreatingTimeoutIndex == message.arg1) { 3551 String errorMsg = "P2P group negotiation timed out"; 3552 if (mVerboseLoggingEnabled) logd(getName() + errorMsg); 3553 if (mWifiP2pMetrics.isP2pFastConnectionType()) { 3554 takeBugReportP2pFailureIfNeeded("Wi-Fi BugReport (P2P " 3555 + mWifiP2pMetrics.getP2pGroupRoleString() 3556 + " creation failure)", errorMsg); 3557 } 3558 mWifiP2pMetrics.endConnectionEvent( 3559 P2pConnectionEvent.CLF_TIMEOUT); 3560 handleGroupCreationFailure(); 3561 smTransition(this, mInactiveState); 3562 } 3563 break; 3564 case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: 3565 if (message.obj == null) { 3566 Log.e(TAG, "Illegal argument(s)"); 3567 break; 3568 } 3569 WifiP2pDevice device = (WifiP2pDevice) message.obj; 3570 if (!mSavedPeerConfig.deviceAddress.equals(device.deviceAddress)) { 3571 if (mVerboseLoggingEnabled) { 3572 logd("mSavedPeerConfig " + mSavedPeerConfig.deviceAddress 3573 + "device " + device.deviceAddress); 3574 } 3575 // Do the regular device lost handling 3576 ret = NOT_HANDLED; 3577 break; 3578 } 3579 // Do nothing 3580 if (mVerboseLoggingEnabled) logd("Add device to lost list " + device); 3581 mPeersLostDuringConnection.updateSupplicantDetails(device); 3582 break; 3583 case WifiP2pManager.DISCOVER_PEERS: 3584 // Discovery will break negotiation 3585 replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, 3586 WifiP2pManager.BUSY); 3587 break; 3588 case WifiP2pManager.STOP_DISCOVERY: 3589 // Stop discovery will clear pending TX action and cause disconnection. 3590 replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, 3591 WifiP2pManager.BUSY); 3592 break; 3593 case WifiP2pManager.START_LISTEN: 3594 replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED, 3595 WifiP2pManager.BUSY); 3596 break; 3597 case WifiP2pManager.STOP_LISTEN: 3598 if (mVerboseLoggingEnabled) { 3599 logd(getName() + " stop listen mode"); 3600 } 3601 if (mWifiNative.p2pExtListen(false, 0, 0)) { 3602 replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); 3603 } else { 3604 replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); 3605 } 3606 break; 3607 case WifiP2pManager.CANCEL_CONNECT: 3608 // Do a supplicant p2p_cancel which only cancels an ongoing 3609 // group negotiation. This will fail for a pending provision 3610 // discovery or for a pending user action, but at the framework 3611 // level, we always treat cancel as succeeded and enter 3612 // an inactive state 3613 mLastCallerInfoManager.put(WifiManager.API_P2P_CANCEL_CONNECT, 3614 Process.myTid(), message.sendingUid, 0, 3615 getCallingPkgName(message.sendingUid, message.replyTo), true); 3616 mWifiNative.p2pCancelConnect(); 3617 mWifiP2pMetrics.endConnectionEvent( 3618 P2pConnectionEvent.CLF_CANCEL); 3619 // Notify the peer about the rejection. 3620 if (mSavedPeerConfig != null) { 3621 mWifiNative.p2pStopFind(); 3622 sendP2pRejection(); 3623 } 3624 handleGroupCreationFailure(); 3625 smTransition(this, mInactiveState); 3626 replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED); 3627 break; 3628 case WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT: 3629 // We hit this scenario when NFC handover is invoked. 3630 mAutonomousGroup = false; 3631 smTransition(this, mGroupNegotiationState); 3632 break; 3633 default: 3634 ret = NOT_HANDLED; 3635 } 3636 return ret; 3637 } 3638 } 3639 3640 class UserAuthorizingNegotiationRequestState extends State { 3641 @Override enter()3642 public void enter() { 3643 logSmStateName(this.getName(), 3644 getCurrentState() != null ? getCurrentState().getName() : ""); 3645 if (mSavedPeerConfig.wps.setup == WpsInfo.PBC 3646 || TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) { 3647 notifyInvitationReceived( 3648 WifiP2pManager.ExternalApproverRequestListener 3649 .REQUEST_TYPE_NEGOTIATION); 3650 } 3651 } 3652 3653 @Override processMessage(Message message)3654 public boolean processMessage(Message message) { 3655 logSmMessage(getName(), message); 3656 switch (message.what) { 3657 case PEER_CONNECTION_USER_ACCEPT: 3658 mWifiNative.p2pStopFind(); 3659 p2pConnectWithPinDisplay(mSavedPeerConfig, 3660 P2P_CONNECT_TRIGGER_GROUP_NEG_REQ); 3661 mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED); 3662 sendPeersChangedBroadcast(); 3663 smTransition(this, mGroupNegotiationState); 3664 break; 3665 case PEER_CONNECTION_USER_REJECT: 3666 if (mVerboseLoggingEnabled) { 3667 logd("User rejected negotiation " + mSavedPeerConfig); 3668 } 3669 if (mSavedPeerConfig != null) { 3670 WifiP2pDevice dev = fetchCurrentDeviceDetails(mSavedPeerConfig); 3671 boolean join = (dev != null && dev.isGroupOwner()) 3672 || mJoinExistingGroup; 3673 if (mVerboseLoggingEnabled) { 3674 logd("User rejected negotiation, join = " + join 3675 + " peer = " + mSavedPeerConfig); 3676 } 3677 mSavedRejectedPeerConfig = new WifiP2pConfig(mSavedPeerConfig); 3678 if (join) { 3679 mWifiNative.p2pCancelConnect(); 3680 mWifiNative.p2pStopFind(); 3681 sendP2pConnectionChangedBroadcast(); 3682 } 3683 sendP2pRejection(); 3684 mSavedPeerConfig.invalidate(); 3685 } else { 3686 mWifiNative.p2pCancelConnect(); 3687 handleGroupCreationFailure(); 3688 } 3689 smTransition(this, mInactiveState); 3690 break; 3691 case PEER_CONNECTION_USER_CONFIRM: 3692 mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; 3693 mSavedPeerConfig.groupOwnerIntent = 3694 selectGroupOwnerIntentIfNecessary(mSavedPeerConfig); 3695 mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP); 3696 smTransition(this, mGroupNegotiationState); 3697 break; 3698 case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: 3699 loge("provision discovery failed status: " + message.arg1); 3700 handleGroupCreationFailure(); 3701 smTransition(this, mInactiveState); 3702 break; 3703 case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: { 3704 if (!handleSetConnectionResult(message, 3705 WifiP2pManager.ExternalApproverRequestListener 3706 .REQUEST_TYPE_NEGOTIATION)) { 3707 replyToMessage(message, 3708 WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_FAILED, 3709 WifiP2pManager.ERROR); 3710 break; 3711 } 3712 replyToMessage(message, 3713 WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_SUCCEEDED); 3714 break; 3715 } 3716 default: 3717 return NOT_HANDLED; 3718 } 3719 return HANDLED; 3720 } 3721 3722 @Override exit()3723 public void exit() { 3724 if (null != mInvitationDialogHandle) { 3725 mInvitationDialogHandle.dismissDialog(); 3726 mInvitationDialogHandle = null; 3727 } 3728 if (null != mLegacyInvitationDialog) { 3729 mLegacyInvitationDialog.dismiss(); 3730 mLegacyInvitationDialog = null; 3731 } 3732 } 3733 } 3734 3735 class UserAuthorizingInviteRequestState extends State { 3736 @Override enter()3737 public void enter() { 3738 logSmStateName(this.getName(), 3739 getCurrentState() != null ? getCurrentState().getName() : ""); 3740 notifyInvitationReceived( 3741 WifiP2pManager.ExternalApproverRequestListener.REQUEST_TYPE_INVITATION); 3742 } 3743 3744 @Override processMessage(Message message)3745 public boolean processMessage(Message message) { 3746 logSmMessage(getName(), message); 3747 switch (message.what) { 3748 case PEER_CONNECTION_USER_ACCEPT: 3749 mWifiNative.p2pStopFind(); 3750 if (!reinvokePersistentGroup(mSavedPeerConfig, true)) { 3751 // Do negotiation when persistence fails 3752 p2pConnectWithPinDisplay(mSavedPeerConfig, 3753 P2P_CONNECT_TRIGGER_INVITATION_REQ); 3754 } 3755 mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED); 3756 sendPeersChangedBroadcast(); 3757 smTransition(this, mGroupNegotiationState); 3758 break; 3759 case PEER_CONNECTION_USER_REJECT: 3760 if (mVerboseLoggingEnabled) { 3761 logd("User rejected invitation " + mSavedPeerConfig); 3762 } 3763 smTransition(this, mInactiveState); 3764 break; 3765 case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: 3766 loge("provision discovery failed status: " + message.arg1); 3767 handleGroupCreationFailure(); 3768 smTransition(this, mInactiveState); 3769 break; 3770 case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: 3771 if (!handleSetConnectionResult(message, 3772 WifiP2pManager.ExternalApproverRequestListener 3773 .REQUEST_TYPE_INVITATION)) { 3774 replyToMessage(message, 3775 WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_FAILED, 3776 WifiP2pManager.ERROR); 3777 break; 3778 } 3779 replyToMessage(message, 3780 WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_SUCCEEDED); 3781 break; 3782 default: 3783 return NOT_HANDLED; 3784 } 3785 return HANDLED; 3786 } 3787 3788 @Override exit()3789 public void exit() { 3790 if (null != mInvitationDialogHandle) { 3791 mInvitationDialogHandle.dismissDialog(); 3792 mInvitationDialogHandle = null; 3793 } 3794 if (null != mLegacyInvitationDialog) { 3795 mLegacyInvitationDialog.dismiss(); 3796 mLegacyInvitationDialog = null; 3797 } 3798 } 3799 } 3800 3801 class ProvisionDiscoveryState extends State { 3802 @Override enter()3803 public void enter() { 3804 logSmStateName(this.getName(), 3805 getCurrentState() != null ? getCurrentState().getName() : ""); 3806 mWifiNative.p2pProvisionDiscovery(mSavedPeerConfig); 3807 } 3808 3809 @Override processMessage(Message message)3810 public boolean processMessage(Message message) { 3811 logSmMessage(getName(), message); 3812 WifiP2pProvDiscEvent provDisc = null; 3813 WifiP2pDevice device = null; 3814 switch (message.what) { 3815 case WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT: 3816 if (message.obj == null) { 3817 Log.e(TAG, "Invalid argument(s)"); 3818 break; 3819 } 3820 provDisc = (WifiP2pProvDiscEvent) message.obj; 3821 device = provDisc.device; 3822 if (device != null 3823 && !device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) { 3824 break; 3825 } 3826 if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) { 3827 if (mVerboseLoggingEnabled) { 3828 logd("Found a match " + mSavedPeerConfig); 3829 } 3830 p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_OTHER); 3831 smTransition(this, mGroupNegotiationState); 3832 } 3833 break; 3834 case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: 3835 if (message.obj == null) { 3836 Log.e(TAG, "Illegal argument(s)"); 3837 break; 3838 } 3839 provDisc = (WifiP2pProvDiscEvent) message.obj; 3840 device = provDisc.device; 3841 if (device != null 3842 && !device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) { 3843 break; 3844 } 3845 if (mSavedPeerConfig.wps.setup == WpsInfo.KEYPAD) { 3846 if (mVerboseLoggingEnabled) { 3847 logd("Found a match " + mSavedPeerConfig); 3848 } 3849 // we already have the pin 3850 if (!TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) { 3851 p2pConnectWithPinDisplay(mSavedPeerConfig, 3852 P2P_CONNECT_TRIGGER_OTHER); 3853 smTransition(this, mGroupNegotiationState); 3854 } else { 3855 mJoinExistingGroup = false; 3856 smTransition(this, mUserAuthorizingNegotiationRequestState); 3857 } 3858 } 3859 break; 3860 case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: 3861 if (message.obj == null) { 3862 Log.e(TAG, "Illegal argument(s)"); 3863 break; 3864 } 3865 provDisc = (WifiP2pProvDiscEvent) message.obj; 3866 device = provDisc.device; 3867 if (device == null) { 3868 Log.e(TAG, "Invalid device"); 3869 break; 3870 } 3871 if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) { 3872 break; 3873 } 3874 if (mSavedPeerConfig.wps.setup == WpsInfo.DISPLAY) { 3875 if (mVerboseLoggingEnabled) { 3876 logd("Found a match " + mSavedPeerConfig); 3877 } 3878 mSavedPeerConfig.wps.pin = provDisc.pin; 3879 p2pConnectWithPinDisplay(mSavedPeerConfig, P2P_CONNECT_TRIGGER_OTHER); 3880 notifyInvitationSent(provDisc.pin, device.deviceAddress); 3881 smTransition(this, mGroupNegotiationState); 3882 } 3883 break; 3884 case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: 3885 loge("provision discovery failed status: " + message.arg1); 3886 3887 // Saved peer information is used in handleGroupCreationFailure(). 3888 if (!handleProvDiscFailure( 3889 (WifiP2pProvDiscEvent) message.obj, false)) { 3890 break; 3891 } 3892 3893 mWifiNative.p2pCancelConnect(); 3894 mWifiP2pMetrics.endConnectionEvent( 3895 P2pConnectionEvent.CLF_PROV_DISC_FAIL); 3896 handleGroupCreationFailure(); 3897 smTransition(this, mInactiveState); 3898 break; 3899 default: 3900 return NOT_HANDLED; 3901 } 3902 return HANDLED; 3903 } 3904 } 3905 3906 class GroupNegotiationState extends State { 3907 @Override enter()3908 public void enter() { 3909 logSmStateName(this.getName(), 3910 getCurrentState() != null ? getCurrentState().getName() : ""); 3911 } 3912 3913 @Override processMessage(Message message)3914 public boolean processMessage(Message message) { 3915 logSmMessage(getName(), message); 3916 switch (message.what) { 3917 // We ignore these right now, since we get a GROUP_STARTED notification 3918 // afterwards 3919 case WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT: 3920 case WifiP2pMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT: 3921 if (mVerboseLoggingEnabled) logd(getName() + " go success"); 3922 break; 3923 case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: 3924 if (message.obj == null) { 3925 Log.e(TAG, "Illegal argument(s)"); 3926 break; 3927 } 3928 mGroup = (WifiP2pGroup) message.obj; 3929 if (mVerboseLoggingEnabled) logd(getName() + " group started"); 3930 if (mGroup.isGroupOwner() 3931 && EMPTY_DEVICE_ADDRESS.equals(mGroup.getOwner().deviceAddress)) { 3932 // wpa_supplicant doesn't set own device address to go_dev_addr. 3933 mGroup.getOwner().deviceAddress = mThisDevice.deviceAddress; 3934 } 3935 if (mGroup.getNetworkId() == WifiP2pGroup.NETWORK_ID_PERSISTENT) { 3936 // update cache information and set network id to mGroup. 3937 updatePersistentNetworks(RELOAD); 3938 String devAddr = mGroup.getOwner().deviceAddress; 3939 mGroup.setNetworkId(mGroups.getNetworkId(devAddr, 3940 mGroup.getNetworkName())); 3941 } 3942 3943 if (mGroup.isGroupOwner()) { 3944 // Setting an idle time out on GO causes issues with certain scenarios 3945 // on clients where it can be off-channel for longer and with the power 3946 // save modes used. 3947 // TODO: Verify multi-channel scenarios and supplicant behavior are 3948 // better before adding a time out in future 3949 // Set group idle timeout of 10 sec, to avoid GO beaconing incase of any 3950 // failure during 4-way Handshake. 3951 if (!mAutonomousGroup) { 3952 mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 3953 GROUP_IDLE_TIME_S); 3954 } 3955 // {@link com.android.server.connectivity.Tethering} listens to 3956 // {@link WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION} 3957 // events and takes over the DHCP server management automatically. 3958 // Because tethering service introduces random IP range, P2P could not 3959 // hard-coded group owner IP and needs to wait for tethering completion. 3960 // As a result, P2P sends a unicast intent to tether service to trigger 3961 // the whole flow before entering GroupCreatedState. 3962 setWifiP2pInfoOnGroupFormation(null); 3963 if (!sendP2pTetherRequestBroadcast()) { 3964 loge("Cannot start tethering, remove " + mGroup); 3965 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 3966 } 3967 break; 3968 } 3969 3970 mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S); 3971 startIpClient(mGroup.getInterface(), getHandler(), 3972 mSavedPeerConfig.getGroupClientIpProvisioningMode(), 3973 mGroup.p2pClientEapolIpInfo); 3974 WifiP2pDevice groupOwner = mGroup.getOwner(); 3975 WifiP2pDevice peer = mPeers.get(groupOwner.deviceAddress); 3976 if (peer != null) { 3977 // update group owner details with peer details found at discovery 3978 groupOwner.updateSupplicantDetails(peer); 3979 mPeers.updateStatus(groupOwner.deviceAddress, 3980 WifiP2pDevice.CONNECTED); 3981 sendPeersChangedBroadcast(); 3982 } else { 3983 // A supplicant bug can lead to reporting an invalid 3984 // group owner address (all zeroes) at times. Avoid a 3985 // crash, but continue group creation since it is not 3986 // essential. 3987 logw("Unknown group owner " + groupOwner); 3988 } 3989 smTransition(this, mGroupCreatedState); 3990 break; 3991 case TETHER_INTERFACE_STATE_CHANGED: 3992 if (mGroup == null) break; 3993 if (!mGroup.isGroupOwner()) break; 3994 if (TextUtils.isEmpty(mGroup.getInterface())) break; 3995 3996 final ArrayList<String> interfaces = (ArrayList<String>) message.obj; 3997 if (interfaces == null) break; 3998 if (!interfaces.contains(mGroup.getInterface())) break; 3999 4000 Log.d(TAG, "tether " + mGroup.getInterface() + " ready"); 4001 smTransition(this, mGroupCreatedState); 4002 break; 4003 case WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: 4004 P2pStatus status = (P2pStatus) message.obj; 4005 if (status == P2pStatus.NO_COMMON_CHANNEL) { 4006 smTransition(this, mFrequencyConflictState); 4007 break; 4008 } 4009 // continue with group removal handling 4010 case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: 4011 String errorMsg = "P2P group is removed"; 4012 if (mVerboseLoggingEnabled) logd(getName() + errorMsg); 4013 if (mWifiP2pMetrics.isP2pFastConnectionType()) { 4014 takeBugReportP2pFailureIfNeeded("Wi-Fi BugReport (P2P " 4015 + mWifiP2pMetrics.getP2pGroupRoleString() 4016 + " negotiation failure)", errorMsg); 4017 } 4018 mWifiP2pMetrics.endConnectionEvent( 4019 P2pConnectionEvent.CLF_GROUP_REMOVED); 4020 handleGroupCreationFailure(); 4021 smTransition(this, mInactiveState); 4022 break; 4023 case WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: 4024 // A group formation failure is always followed by 4025 // a group removed event. Flushing things at group formation 4026 // failure causes supplicant issues. Ignore right now. 4027 status = (P2pStatus) message.obj; 4028 if (status == P2pStatus.NO_COMMON_CHANNEL) { 4029 smTransition(this, mFrequencyConflictState); 4030 break; 4031 } 4032 break; 4033 case WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT: 4034 status = (P2pStatus) message.obj; 4035 if (status == P2pStatus.SUCCESS) { 4036 // invocation was succeeded. 4037 // wait P2P_GROUP_STARTED_EVENT. 4038 break; 4039 } 4040 loge("Invitation result " + status); 4041 if (status == P2pStatus.UNKNOWN_P2P_GROUP) { 4042 // target device has already removed the credential. 4043 // So, remove this credential accordingly. 4044 int netId = mSavedPeerConfig.netId; 4045 if (netId >= 0) { 4046 if (mVerboseLoggingEnabled) { 4047 logd("Remove unknown client from the list"); 4048 } 4049 removeClientFromList(netId, mSavedPeerConfig.deviceAddress, true); 4050 } 4051 4052 // Reinvocation has failed, try group negotiation 4053 mSavedPeerConfig.netId = WifiP2pGroup.NETWORK_ID_PERSISTENT; 4054 if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) { 4055 p2pConnectWithPinDisplay(mSavedPeerConfig, 4056 P2P_CONNECT_TRIGGER_OTHER); 4057 } else { 4058 // Non-PBC method needs to exchange PIN by provision discovery. 4059 smTransition(this, mProvisionDiscoveryState); 4060 } 4061 } else if (status == P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE) { 4062 mSavedPeerConfig.netId = WifiP2pGroup.NETWORK_ID_PERSISTENT; 4063 // Devices setting persistent_reconnect to 0 in wpa_supplicant 4064 // always defer the invocation request and return 4065 // "information is currently unavailable" error. 4066 // So, try another way to connect for interoperability. 4067 if (!mContext.getResources().getBoolean(R.bool 4068 .config_p2pWaitForPeerInviteOnInviteStatusInfoUnavailable)) { 4069 mWifiP2pMetrics 4070 .setFallbackToNegotiationOnInviteStatusInfoUnavailable(); 4071 p2pConnectWithPinDisplay(mSavedPeerConfig, 4072 P2P_CONNECT_TRIGGER_OTHER); 4073 } 4074 } else if (status == P2pStatus.NO_COMMON_CHANNEL) { 4075 smTransition(this, mFrequencyConflictState); 4076 } else { 4077 mWifiP2pMetrics.endConnectionEvent( 4078 P2pConnectionEvent.CLF_INVITATION_FAIL); 4079 handleGroupCreationFailure(); 4080 smTransition(this, mInactiveState); 4081 } 4082 break; 4083 case WifiP2pMonitor.AP_STA_CONNECTED_EVENT: 4084 case WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT: 4085 // Group owner needs to wait for tethering completion before 4086 // moving to GroupCreatedState. If native layer reports STA event 4087 // earlier, defer it. 4088 if (mGroup != null && mGroup.isGroupOwner()) { 4089 deferMessage(message); 4090 break; 4091 } 4092 break; 4093 case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: 4094 if (!handleSetConnectionResultForInvitationSent(message)) { 4095 replyToMessage(message, 4096 WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_FAILED, 4097 WifiP2pManager.ERROR); 4098 break; 4099 } 4100 replyToMessage(message, 4101 WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_SUCCEEDED); 4102 break; 4103 default: 4104 return NOT_HANDLED; 4105 } 4106 return HANDLED; 4107 } 4108 } 4109 4110 class FrequencyConflictState extends State { 4111 private WifiDialogManager.DialogHandle mFrequencyConflictDialog; 4112 private AlertDialog mFrequencyConflictDialogPreT; 4113 4114 @Override enter()4115 public void enter() { 4116 logSmStateName(this.getName(), 4117 getCurrentState() != null ? getCurrentState().getName() : ""); 4118 notifyFrequencyConflict(); 4119 } 4120 showFrequencyConflictDialogPreT()4121 private void showFrequencyConflictDialogPreT() { 4122 Resources r = mContext.getResources(); 4123 AlertDialog dialog = mFrameworkFacade.makeAlertDialogBuilder(mContext) 4124 .setMessage(r.getString(R.string.wifi_p2p_frequency_conflict_message, 4125 getDeviceName(mSavedPeerConfig.deviceAddress))) 4126 .setPositiveButton(r.getString(R.string.dlg_ok), (dialog1, which) -> 4127 sendMessage(DROP_WIFI_USER_ACCEPT)) 4128 .setNegativeButton(r.getString(R.string.decline), (dialog2, which) -> 4129 sendMessage(DROP_WIFI_USER_REJECT)) 4130 .setOnCancelListener(arg0 -> sendMessage(DROP_WIFI_USER_REJECT)) 4131 .create(); 4132 dialog.setCanceledOnTouchOutside(false); 4133 4134 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 4135 dialog.getWindow().addSystemFlags( 4136 WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); 4137 dialog.show(); 4138 mFrequencyConflictDialogPreT = dialog; 4139 } 4140 showFrequencyConflictDialog()4141 private void showFrequencyConflictDialog() { 4142 Resources r = mContext.getResources(); 4143 WifiDialogManager.DialogHandle dialog = mWifiInjector.getWifiDialogManager() 4144 .createSimpleDialog( 4145 null /* title */, 4146 r.getString(R.string.wifi_p2p_frequency_conflict_message, 4147 getDeviceName(mSavedPeerConfig.deviceAddress)), 4148 r.getString(R.string.dlg_ok), 4149 r.getString(R.string.decline), 4150 null /* neutralButtonText */, 4151 new WifiDialogManager.SimpleDialogCallback() { 4152 @Override 4153 public void onPositiveButtonClicked() { 4154 sendMessage(DROP_WIFI_USER_ACCEPT); 4155 } 4156 4157 @Override 4158 public void onNegativeButtonClicked() { 4159 sendMessage(DROP_WIFI_USER_REJECT); 4160 } 4161 4162 @Override 4163 public void onNeutralButtonClicked() { 4164 // Not used 4165 sendMessage(DROP_WIFI_USER_REJECT); 4166 } 4167 4168 @Override 4169 public void onCancelled() { 4170 sendMessage(DROP_WIFI_USER_REJECT); 4171 } 4172 }, 4173 new WifiThreadRunner(getHandler())); 4174 mFrequencyConflictDialog = dialog; 4175 dialog.launchDialog(); 4176 } 4177 notifyFrequencyConflict()4178 private void notifyFrequencyConflict() { 4179 logd("Notify frequency conflict"); 4180 if (!SdkLevel.isAtLeastT()) { 4181 showFrequencyConflictDialogPreT(); 4182 } else { 4183 showFrequencyConflictDialog(); 4184 } 4185 } 4186 4187 @Override processMessage(Message message)4188 public boolean processMessage(Message message) { 4189 logSmMessage(getName(), message); 4190 switch (message.what) { 4191 case WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT: 4192 case WifiP2pMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT: 4193 loge(getName() + "group sucess during freq conflict!"); 4194 break; 4195 case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: 4196 loge(getName() + "group started after freq conflict, handle anyway"); 4197 deferMessage(message); 4198 smTransition(this, mGroupNegotiationState); 4199 break; 4200 case WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: 4201 case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: 4202 case WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: 4203 // Ignore failures since we retry again 4204 break; 4205 case DROP_WIFI_USER_REJECT: 4206 // User rejected dropping wifi in favour of p2p 4207 mFrequencyConflictDialog = null; 4208 mFrequencyConflictDialogPreT = null; 4209 mWifiP2pMetrics.endConnectionEvent( 4210 P2pConnectionEvent.CLF_USER_REJECT); 4211 handleGroupCreationFailure(); 4212 smTransition(this, mInactiveState); 4213 break; 4214 case DROP_WIFI_USER_ACCEPT: 4215 mFrequencyConflictDialog = null; 4216 mFrequencyConflictDialogPreT = null; 4217 // User accepted dropping wifi in favour of p2p 4218 sendDisconnectWifiRequest(true); 4219 break; 4220 case DISCONNECT_WIFI_RESPONSE: 4221 // Got a response from ClientModeImpl, retry p2p 4222 if (mVerboseLoggingEnabled) { 4223 logd(getName() + "Wifi disconnected, retry p2p"); 4224 } 4225 smTransition(this, mInactiveState); 4226 p2pReconnect(); 4227 break; 4228 default: 4229 return NOT_HANDLED; 4230 } 4231 return HANDLED; 4232 } 4233 exit()4234 public void exit() { 4235 if (mFrequencyConflictDialogPreT != null) { 4236 mFrequencyConflictDialogPreT.dismiss(); 4237 } 4238 if (mFrequencyConflictDialog != null) { 4239 mFrequencyConflictDialog.dismissDialog(); 4240 } 4241 } 4242 } 4243 4244 class GroupCreatedState extends State { 4245 @Override enter()4246 public void enter() { 4247 logSmStateName(this.getName(), 4248 getCurrentState() != null ? getCurrentState().getName() : ""); 4249 // Once connected, peer config details are invalid 4250 mSavedPeerConfig.invalidate(); 4251 mDetailedState = NetworkInfo.DetailedState.CONNECTED; 4252 4253 updateThisDevice(WifiP2pDevice.CONNECTED); 4254 4255 // DHCP server has already been started if I am a group owner 4256 if (mGroup.isGroupOwner()) { 4257 Inet4Address addr = getInterfaceAddress(mGroup.getInterface()); 4258 if (addr != null) { 4259 setWifiP2pInfoOnGroupFormation(addr.getHostAddress()); 4260 Log.d(TAG, "Group owner address: " + addr.getHostAddress() 4261 + " at " + mGroup.getInterface()); 4262 } else { 4263 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 4264 } 4265 } 4266 4267 // In case of a negotiation group, connection changed is sent 4268 // after a client joins. For autonomous, send now 4269 if (mAutonomousGroup) { 4270 sendP2pConnectionChangedBroadcast(); 4271 } 4272 4273 mWifiP2pMetrics.endConnectionEvent( 4274 P2pConnectionEvent.CLF_NONE); 4275 mWifiP2pMetrics.startGroupEvent(mGroup); 4276 } 4277 4278 @Override processMessage(Message message)4279 public boolean processMessage(Message message) { 4280 logSmMessage(getName(), message); 4281 WifiP2pDevice device; 4282 String deviceAddress; 4283 switch (message.what) { 4284 case WifiP2pMonitor.AP_STA_CONNECTED_EVENT: 4285 if (message.obj == null) { 4286 Log.e(TAG, "Illegal argument(s)"); 4287 break; 4288 } 4289 device = (WifiP2pDevice) message.obj; 4290 deviceAddress = device.deviceAddress; 4291 // Clear timeout that was set when group was started. 4292 mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0); 4293 if (deviceAddress != null) { 4294 if (mPeers.get(deviceAddress) != null) { 4295 mGroup.addClient(mPeers.get(deviceAddress)); 4296 } else { 4297 mGroup.addClient(deviceAddress); 4298 } 4299 mPeers.updateStatus(deviceAddress, WifiP2pDevice.CONNECTED); 4300 if (mVerboseLoggingEnabled) logd(getName() + " ap sta connected"); 4301 // When a peer is connected, flush it. 4302 mPeerAuthorizingTimestamp.remove(deviceAddress); 4303 sendPeersChangedBroadcast(); 4304 mWifiP2pMetrics.updateGroupEvent(mGroup); 4305 } else { 4306 loge("Connect on null device address, ignore"); 4307 } 4308 sendP2pConnectionChangedBroadcast(); 4309 break; 4310 case WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT: 4311 if (message.obj == null) { 4312 Log.e(TAG, "Illegal argument(s)"); 4313 break; 4314 } 4315 device = (WifiP2pDevice) message.obj; 4316 deviceAddress = device.deviceAddress; 4317 if (deviceAddress != null) { 4318 mPeers.updateStatus(deviceAddress, WifiP2pDevice.AVAILABLE); 4319 if (mGroup.removeClient(deviceAddress)) { 4320 if (mVerboseLoggingEnabled) { 4321 logd("Removed client " + deviceAddress); 4322 } 4323 if (!mAutonomousGroup && mGroup.isClientListEmpty()) { 4324 logd("Client list empty, remove non-persistent p2p group"); 4325 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 4326 // We end up sending connection changed broadcast 4327 // when this happens at exit() 4328 } else { 4329 // Notify when a client disconnects from group 4330 sendP2pConnectionChangedBroadcast(); 4331 } 4332 mWifiP2pMetrics.updateGroupEvent(mGroup); 4333 } else { 4334 if (mVerboseLoggingEnabled) { 4335 logd("Failed to remove client " + deviceAddress); 4336 } 4337 for (WifiP2pDevice c : mGroup.getClientList()) { 4338 if (mVerboseLoggingEnabled) { 4339 logd("client " + c.deviceAddress); 4340 } 4341 } 4342 } 4343 sendPeersChangedBroadcast(); 4344 if (mVerboseLoggingEnabled) logd(getName() + " ap sta disconnected"); 4345 } else { 4346 loge("Disconnect on unknown device: " + device); 4347 } 4348 break; 4349 case IPC_PRE_DHCP_ACTION: 4350 mWifiNative.setP2pPowerSave(mGroup.getInterface(), false); 4351 try { 4352 mIpClient.completedPreDhcpAction(); 4353 } catch (RemoteException e) { 4354 e.rethrowFromSystemServer(); 4355 } 4356 break; 4357 case IPC_POST_DHCP_ACTION: 4358 mWifiNative.setP2pPowerSave(mGroup.getInterface(), true); 4359 break; 4360 case IPC_DHCP_RESULTS: 4361 mDhcpResultsParcelable = (DhcpResultsParcelable) message.obj; 4362 if (mDhcpResultsParcelable == null) { 4363 break; 4364 } 4365 4366 if (mVerboseLoggingEnabled) { 4367 logd("mDhcpResultsParcelable: " + mDhcpResultsParcelable); 4368 } 4369 if (mDhcpResultsParcelable.serverAddress != null) { 4370 setWifiP2pInfoOnGroupFormation(mDhcpResultsParcelable.serverAddress); 4371 } else { 4372 // In case of static IP (IP address received via EAPOL-Key exchange), 4373 // the DHCP server address is null. So look for the gateway address. 4374 InetAddress addr = 4375 mDhcpResultsParcelable.baseConfiguration.getGateway(); 4376 if (addr != null) { 4377 setWifiP2pInfoOnGroupFormation(addr.getHostAddress()); 4378 } 4379 } 4380 try { 4381 final String ifname = mGroup.getInterface(); 4382 if (mDhcpResultsParcelable != null) { 4383 mNetdWrapper.addInterfaceToLocalNetwork( 4384 ifname, 4385 mDhcpResultsParcelable.baseConfiguration.getRoutes(ifname)); 4386 } 4387 } catch (Exception e) { 4388 loge("Failed to add iface to local network " + e); 4389 } 4390 sendP2pConnectionChangedBroadcast(); 4391 break; 4392 case IPC_PROVISIONING_SUCCESS: 4393 if (mSavedPeerConfig.getGroupClientIpProvisioningMode() 4394 != GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL) { 4395 break; 4396 } 4397 4398 LinkProperties linkProperties = (LinkProperties) message.obj; 4399 if (mVerboseLoggingEnabled) { 4400 logd("IP provisioning result " + linkProperties); 4401 } 4402 try { 4403 mNetdWrapper.addInterfaceToLocalNetwork( 4404 mGroup.getInterface(), 4405 linkProperties.getRoutes()); 4406 } catch (Exception e) { 4407 loge("Failed to add iface to local network " + e); 4408 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 4409 } 4410 4411 byte[] goInterfaceMacAddress = mGroup.interfaceAddress; 4412 if (goInterfaceMacAddress == null) { 4413 setWifiP2pInfoOnGroupFormationWithInetAddress(null); 4414 sendP2pConnectionChangedBroadcast(); 4415 break; 4416 } 4417 4418 byte[] goIpv6Address = MacAddress.fromBytes(goInterfaceMacAddress) 4419 .getLinkLocalIpv6FromEui48Mac().getAddress(); 4420 try { 4421 InetAddress goIp = Inet6Address.getByAddress(null, goIpv6Address, 4422 NetworkInterface.getByName(mGroup.getInterface())); 4423 setWifiP2pInfoOnGroupFormationWithInetAddress(goIp); 4424 sendP2pConnectionChangedBroadcast(); 4425 } catch (UnknownHostException | SocketException e) { 4426 loge("Unable to retrieve link-local IPv6 address of group owner " 4427 + e); 4428 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 4429 } 4430 break; 4431 case IPC_PROVISIONING_FAILURE: 4432 loge("IP provisioning failed"); 4433 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 4434 break; 4435 case WifiP2pManager.REMOVE_GROUP: 4436 mLastCallerInfoManager.put(WifiManager.API_P2P_REMOVE_GROUP, 4437 Process.myTid(), message.sendingUid, 0, 4438 getCallingPkgName(message.sendingUid, message.replyTo), true); 4439 if (mVerboseLoggingEnabled) logd(getName() + " remove group"); 4440 if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) { 4441 smTransition(this, mOngoingGroupRemovalState); 4442 replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED); 4443 } else { 4444 handleGroupRemoved(); 4445 smTransition(this, mInactiveState); 4446 replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, 4447 WifiP2pManager.ERROR); 4448 } 4449 break; 4450 case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: 4451 // We do not listen to NETWORK_DISCONNECTION_EVENT for group removal 4452 // handling since supplicant actually tries to reconnect after a temporary 4453 // disconnect until group idle time out. Eventually, a group removal event 4454 // will come when group has been removed. 4455 // 4456 // When there are connectivity issues during temporary disconnect, 4457 // the application will also just remove the group. 4458 // 4459 // Treating network disconnection as group removal causes race conditions 4460 // since supplicant would still maintain the group at that stage. 4461 if (mVerboseLoggingEnabled) logd(getName() + " group removed"); 4462 handleGroupRemoved(); 4463 smTransition(this, mInactiveState); 4464 break; 4465 case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: 4466 if (message.obj == null) { 4467 Log.e(TAG, "Illegal argument(s)"); 4468 return NOT_HANDLED; 4469 } 4470 device = (WifiP2pDevice) message.obj; 4471 if (!mGroup.contains(device)) { 4472 // do the regular device lost handling 4473 return NOT_HANDLED; 4474 } 4475 // Device loss for a connected device indicates 4476 // it is not in discovery any more 4477 if (mVerboseLoggingEnabled) logd("Add device to lost list " + device); 4478 mPeersLostDuringConnection.updateSupplicantDetails(device); 4479 return HANDLED; 4480 case DISABLE_P2P: 4481 sendMessage(WifiP2pManager.REMOVE_GROUP); 4482 deferMessage(message); 4483 break; 4484 // This allows any client to join the GO during the 4485 // WPS window 4486 case WifiP2pManager.START_WPS: 4487 WpsInfo wps = (WpsInfo) message.obj; 4488 if (wps == null) { 4489 replyToMessage(message, WifiP2pManager.START_WPS_FAILED); 4490 break; 4491 } 4492 boolean ret = true; 4493 if (wps.setup == WpsInfo.PBC) { 4494 ret = mWifiNative.startWpsPbc(mGroup.getInterface(), null); 4495 } else { 4496 if (wps.pin == null) { 4497 String pin = mWifiNative.startWpsPinDisplay( 4498 mGroup.getInterface(), null); 4499 try { 4500 Integer.parseInt(pin); 4501 notifyInvitationSent(pin, "any"); 4502 } catch (NumberFormatException ignore) { 4503 ret = false; 4504 } 4505 } else { 4506 ret = mWifiNative.startWpsPinKeypad(mGroup.getInterface(), 4507 wps.pin); 4508 } 4509 } 4510 replyToMessage(message, ret ? WifiP2pManager.START_WPS_SUCCEEDED : 4511 WifiP2pManager.START_WPS_FAILED); 4512 break; 4513 case WifiP2pManager.CONNECT: { 4514 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 4515 if (packageName == null) { 4516 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 4517 break; 4518 } 4519 int uid = message.sendingUid; 4520 Bundle extras = message.getData() 4521 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 4522 boolean hasPermission = false; 4523 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 4524 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 4525 packageName, 4526 getCallingFeatureId(message.sendingUid, message.replyTo), 4527 uid, false); 4528 } else { 4529 hasPermission = checkNearbyDevicesPermission(uid, packageName, 4530 extras, "CONNECT", message.obj); 4531 } 4532 if (!hasPermission) { 4533 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 4534 // remain at this state. 4535 break; 4536 } 4537 mLastCallerInfoManager.put(WifiManager.API_P2P_CONNECT, 4538 Process.myTid(), uid, 0, packageName, true); 4539 WifiP2pConfig config = (WifiP2pConfig) 4540 extras.getParcelable(WifiP2pManager.EXTRA_PARAM_KEY_CONFIG); 4541 if (isConfigInvalid(config)) { 4542 loge("Dropping connect request " + config); 4543 replyToMessage(message, WifiP2pManager.CONNECT_FAILED); 4544 break; 4545 } 4546 logd("Inviting device : " + config.deviceAddress); 4547 mSavedPeerConfig = config; 4548 if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) { 4549 mPeers.updateStatus(config.deviceAddress, WifiP2pDevice.INVITED); 4550 sendPeersChangedBroadcast(); 4551 replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); 4552 } else { 4553 replyToMessage(message, WifiP2pManager.CONNECT_FAILED, 4554 WifiP2pManager.ERROR); 4555 } 4556 // TODO: figure out updating the status to declined 4557 // when invitation is rejected 4558 break; 4559 } 4560 case WifiP2pMonitor.P2P_INVITATION_RESULT_EVENT: 4561 P2pStatus status = (P2pStatus) message.obj; 4562 if (status == P2pStatus.SUCCESS) { 4563 // invocation was succeeded. 4564 break; 4565 } 4566 loge("Invitation result " + status); 4567 if (status == P2pStatus.UNKNOWN_P2P_GROUP) { 4568 // target device has already removed the credential. 4569 // So, remove this credential accordingly. 4570 int netId = mGroup.getNetworkId(); 4571 if (netId >= 0) { 4572 if (mVerboseLoggingEnabled) { 4573 logd("Remove unknown client from the list"); 4574 } 4575 removeClientFromList(netId, mSavedPeerConfig.deviceAddress, false); 4576 // try invitation. 4577 p2pReconnect(); 4578 } 4579 } 4580 break; 4581 case WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: 4582 case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: 4583 case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: 4584 WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj; 4585 WifiP2pConfig newPeerConfig = new WifiP2pConfig(); 4586 if (provDisc != null && provDisc.device != null) { 4587 if (TextUtils.isEmpty(provDisc.device.deviceAddress)) { 4588 break; 4589 } 4590 newPeerConfig.deviceAddress = provDisc.device.deviceAddress; 4591 } 4592 if (message.what == WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) { 4593 newPeerConfig.wps.setup = WpsInfo.KEYPAD; 4594 } else if (message.what == WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) { 4595 newPeerConfig.wps.setup = WpsInfo.DISPLAY; 4596 newPeerConfig.wps.pin = provDisc.pin; 4597 } else { 4598 newPeerConfig.wps.setup = WpsInfo.PBC; 4599 } 4600 4601 if (isPeerAuthorizing(newPeerConfig.deviceAddress)) { 4602 Log.i(TAG, "Ignore duplicate provision discovery request from " 4603 + newPeerConfig.deviceAddress); 4604 break; 4605 } 4606 mSavedPeerConfig = newPeerConfig; 4607 mPeerAuthorizingTimestamp.put(mSavedPeerConfig.deviceAddress, 4608 mClock.getElapsedSinceBootMillis()); 4609 4610 // According to section 3.2.3 in SPEC, only GO can handle group join. 4611 // Multiple groups is not supported, ignore this discovery for GC. 4612 if (mGroup.isGroupOwner()) { 4613 smTransition(this, mUserAuthorizingJoinState); 4614 } else { 4615 if (mVerboseLoggingEnabled) { 4616 logd("Ignore provision discovery for GC"); 4617 } 4618 } 4619 break; 4620 case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: 4621 loge("Duplicate group creation event notice, ignore"); 4622 break; 4623 case WifiP2pManager.CANCEL_CONNECT: 4624 mLastCallerInfoManager.put(WifiManager.API_P2P_CANCEL_CONNECT, 4625 Process.myTid(), message.sendingUid, 0, 4626 getCallingPkgName(message.sendingUid, message.replyTo), true); 4627 mWifiNative.p2pCancelConnect(); 4628 mWifiP2pMetrics.endConnectionEvent( 4629 P2pConnectionEvent.CLF_CANCEL); 4630 4631 ArrayList<WifiP2pDevice> invitingPeers = new ArrayList<>(); 4632 mPeers.getDeviceList().forEach(dev -> { 4633 if (dev.status == WifiP2pDevice.INVITED) { 4634 invitingPeers.add(dev); 4635 } 4636 }); 4637 if (mPeers.remove(new WifiP2pDeviceList(invitingPeers))) { 4638 sendPeersChangedBroadcast(); 4639 } 4640 4641 replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED); 4642 break; 4643 case WifiP2pMonitor.P2P_FREQUENCY_CHANGED_EVENT: 4644 if (mGroup != null) { 4645 mGroup.setFrequency(message.arg1); 4646 sendP2pConnectionChangedBroadcast(); 4647 } 4648 break; 4649 case WifiP2pManager.REMOVE_CLIENT: { 4650 if (!isFeatureSupported(WifiP2pManager.FEATURE_GROUP_CLIENT_REMOVAL)) { 4651 replyToMessage(message, WifiP2pManager.REMOVE_CLIENT_FAILED, 4652 WifiP2pManager.ERROR); 4653 break; 4654 } 4655 if (mVerboseLoggingEnabled) logd(getName() + " remove client"); 4656 MacAddress peerAddress = (MacAddress) message.obj; 4657 4658 if (peerAddress != null 4659 && mWifiNative.removeClient(peerAddress.toString())) { 4660 replyToMessage(message, WifiP2pManager.REMOVE_CLIENT_SUCCEEDED); 4661 } else { 4662 replyToMessage(message, WifiP2pManager.REMOVE_CLIENT_FAILED, 4663 WifiP2pManager.ERROR); 4664 } 4665 break; 4666 } 4667 case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: 4668 if (!handleSetConnectionResultForInvitationSent(message)) { 4669 replyToMessage(message, 4670 WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_FAILED, 4671 WifiP2pManager.ERROR); 4672 break; 4673 } 4674 replyToMessage(message, 4675 WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_SUCCEEDED); 4676 break; 4677 case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: 4678 loge("provision discovery failed status: " + message.arg1); 4679 handleProvDiscFailure((WifiP2pProvDiscEvent) message.obj, true); 4680 break; 4681 default: 4682 return NOT_HANDLED; 4683 } 4684 return HANDLED; 4685 } 4686 exit()4687 public void exit() { 4688 // The group is still there and handling incoming request, 4689 // no need to update P2P connection information. 4690 if (mGroup != null) return; 4691 4692 mWifiP2pMetrics.endGroupEvent(); 4693 updateThisDevice(WifiP2pDevice.AVAILABLE); 4694 resetWifiP2pInfo(); 4695 mDetailedState = NetworkInfo.DetailedState.DISCONNECTED; 4696 sendP2pConnectionChangedBroadcast(); 4697 // Ensure tethering service to stop tethering. 4698 sendP2pTetherRequestBroadcast(); 4699 } 4700 } 4701 4702 class UserAuthorizingJoinState extends State { 4703 @Override enter()4704 public void enter() { 4705 logSmStateName(this.getName(), 4706 getCurrentState() != null ? getCurrentState().getName() : ""); 4707 notifyInvitationReceived( 4708 WifiP2pManager.ExternalApproverRequestListener.REQUEST_TYPE_JOIN); 4709 } 4710 4711 @Override processMessage(Message message)4712 public boolean processMessage(Message message) { 4713 logSmMessage(getName(), message); 4714 switch (message.what) { 4715 case WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: 4716 case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: 4717 case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: 4718 // Ignore more client requests 4719 break; 4720 case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: 4721 loge("provision discovery failed status: " + message.arg1); 4722 if (!handleProvDiscFailure( 4723 (WifiP2pProvDiscEvent) message.obj, true)) { 4724 break; 4725 } 4726 smTransition(this, mGroupCreatedState); 4727 break; 4728 case PEER_CONNECTION_USER_ACCEPT: 4729 // Stop discovery to avoid failure due to channel switch 4730 mWifiNative.p2pStopFind(); 4731 if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) { 4732 mWifiNative.startWpsPbc(mGroup.getInterface(), null); 4733 } else { 4734 mWifiNative.startWpsPinKeypad(mGroup.getInterface(), 4735 mSavedPeerConfig.wps.pin); 4736 } 4737 smTransition(this, mGroupCreatedState); 4738 break; 4739 case PEER_CONNECTION_USER_REJECT: 4740 if (mVerboseLoggingEnabled) logd("User rejected incoming request"); 4741 mSavedPeerConfig.invalidate(); 4742 smTransition(this, mGroupCreatedState); 4743 break; 4744 case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: 4745 if (!handleSetConnectionResult(message, 4746 WifiP2pManager.ExternalApproverRequestListener.REQUEST_TYPE_JOIN)) { 4747 replyToMessage(message, 4748 WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_FAILED, 4749 WifiP2pManager.ERROR); 4750 break; 4751 } 4752 replyToMessage(message, 4753 WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_SUCCEEDED); 4754 break; 4755 default: 4756 return NOT_HANDLED; 4757 } 4758 return HANDLED; 4759 } 4760 4761 @Override exit()4762 public void exit() { 4763 if (null != mInvitationDialogHandle) { 4764 mInvitationDialogHandle.dismissDialog(); 4765 mInvitationDialogHandle = null; 4766 } 4767 if (null != mLegacyInvitationDialog) { 4768 mLegacyInvitationDialog.dismiss(); 4769 mLegacyInvitationDialog = null; 4770 } 4771 } 4772 } 4773 4774 class OngoingGroupRemovalState extends State { 4775 @Override enter()4776 public void enter() { 4777 logSmStateName(this.getName(), 4778 getCurrentState() != null ? getCurrentState().getName() : ""); 4779 } 4780 4781 @Override processMessage(Message message)4782 public boolean processMessage(Message message) { 4783 logSmMessage(getName(), message); 4784 switch (message.what) { 4785 // Group removal ongoing. Multiple calls 4786 // end up removing persisted network. Do nothing. 4787 case WifiP2pManager.REMOVE_GROUP: 4788 replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED); 4789 break; 4790 // Parent state will transition out of this state 4791 // when removal is complete 4792 default: 4793 return NOT_HANDLED; 4794 } 4795 return HANDLED; 4796 } 4797 } 4798 4799 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)4800 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4801 super.dump(fd, pw, args); 4802 pw.println("mWifiP2pInfo " + mWifiP2pInfo); 4803 pw.println("mGroup " + mGroup); 4804 pw.println("mSavedPeerConfig " + mSavedPeerConfig); 4805 pw.println("mGroups " + mGroups); 4806 pw.println(); 4807 } 4808 isWifiP2pAvailable()4809 private boolean isWifiP2pAvailable() { 4810 return mIsWifiEnabled && !mIsP2pDisallowedByAdmin; 4811 } 4812 checkAndSendP2pStateChangedBroadcast()4813 private void checkAndSendP2pStateChangedBroadcast() { 4814 Log.d(TAG, "Wifi enabled=" + mIsWifiEnabled + ", P2P disallowed by admin=" 4815 + mIsP2pDisallowedByAdmin); 4816 boolean wifiP2pAvailable = isWifiP2pAvailable(); 4817 if (mLastP2pState != wifiP2pAvailable) { 4818 mLastP2pState = wifiP2pAvailable; 4819 sendP2pStateChangedBroadcast(mLastP2pState); 4820 } 4821 } 4822 sendP2pStateChangedBroadcast(boolean enabled)4823 private void sendP2pStateChangedBroadcast(boolean enabled) { 4824 final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); 4825 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4826 if (enabled) { 4827 intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE, 4828 WifiP2pManager.WIFI_P2P_STATE_ENABLED); 4829 } else { 4830 intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE, 4831 WifiP2pManager.WIFI_P2P_STATE_DISABLED); 4832 } 4833 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4834 } 4835 sendP2pDiscoveryChangedBroadcast(boolean started)4836 private void sendP2pDiscoveryChangedBroadcast(boolean started) { 4837 if (mDiscoveryStarted == started) return; 4838 mDiscoveryStarted = started; 4839 4840 if (mVerboseLoggingEnabled) logd("discovery change broadcast " + started); 4841 4842 final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION); 4843 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4844 intent.putExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, started 4845 ? WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED : 4846 WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED); 4847 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4848 } 4849 sendP2pListenChangedBroadcast(boolean started)4850 private void sendP2pListenChangedBroadcast(boolean started) { 4851 if (mListenStarted == started) return; 4852 4853 mListenStarted = started; 4854 if (mVerboseLoggingEnabled) logd("wifi p2p listen change broadcast " + started); 4855 4856 final Intent intent = new Intent(WifiP2pManager.ACTION_WIFI_P2P_LISTEN_STATE_CHANGED); 4857 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4858 intent.putExtra(WifiP2pManager.EXTRA_LISTEN_STATE, started 4859 ? WifiP2pManager.WIFI_P2P_LISTEN_STARTED : 4860 WifiP2pManager.WIFI_P2P_LISTEN_STOPPED); 4861 sendBroadcastMultiplePermissions(intent); 4862 } 4863 4864 // TODO(b/193460475): Remove when tooling supports SystemApi to public API. 4865 @SuppressLint("NewApi") sendBroadcastMultiplePermissions(Intent intent)4866 private void sendBroadcastMultiplePermissions(Intent intent) { 4867 Context context = mContext.createContextAsUser(UserHandle.ALL, 0); 4868 String[] permissions = RECEIVER_PERMISSIONS_FOR_BROADCAST; 4869 boolean isLocationModeEnabled = mWifiPermissionsUtil.isLocationModeEnabled(); 4870 if (!isLocationModeEnabled) { 4871 permissions = RECEIVER_PERMISSIONS_FOR_BROADCAST_LOCATION_OFF; 4872 } 4873 context.sendBroadcastWithMultiplePermissions( 4874 intent, permissions); 4875 if (SdkLevel.isAtLeastT()) { 4876 // on Android T or later, also send broadcasts to apps that have NEARBY_WIFI_DEVICES 4877 String[] requiredPermissions = new String[] { 4878 android.Manifest.permission.NEARBY_WIFI_DEVICES, 4879 android.Manifest.permission.ACCESS_WIFI_STATE 4880 }; 4881 BroadcastOptions broadcastOptions = mWifiInjector.makeBroadcastOptions(); 4882 broadcastOptions.setRequireAllOfPermissions(requiredPermissions); 4883 if (isLocationModeEnabled) { 4884 broadcastOptions.setRequireNoneOfPermissions( 4885 new String[] {android.Manifest.permission.ACCESS_FINE_LOCATION}); 4886 } 4887 context.sendBroadcast(intent, null, broadcastOptions.toBundle()); 4888 } 4889 } 4890 sendThisDeviceChangedBroadcast()4891 private void sendThisDeviceChangedBroadcast() { 4892 final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); 4893 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4894 intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE, 4895 eraseOwnDeviceAddress(mThisDevice)); 4896 sendBroadcastMultiplePermissions(intent); 4897 } 4898 sendPeersChangedBroadcast()4899 private void sendPeersChangedBroadcast() { 4900 final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); 4901 intent.putExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST, new WifiP2pDeviceList(mPeers)); 4902 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4903 sendBroadcastMultiplePermissions(intent); 4904 } 4905 sendP2pConnectionChangedBroadcast()4906 private void sendP2pConnectionChangedBroadcast() { 4907 if (mVerboseLoggingEnabled) logd("sending p2p connection changed broadcast"); 4908 Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 4909 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4910 // P2pConnectionEvent.CONNECTION_FAST connection type is only triggered as a result 4911 // of user interaction, so mark the broadcast as foreground. 4912 if (mWifiP2pMetrics.isP2pFastConnectionType()) { 4913 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 4914 } 4915 intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo)); 4916 intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, makeNetworkInfo()); 4917 intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, eraseOwnDeviceAddress(mGroup)); 4918 sendBroadcastMultiplePermissions(intent); 4919 if (mWifiChannel != null) { 4920 mWifiChannel.sendMessage(WifiP2pServiceImpl.P2P_CONNECTION_CHANGED, 4921 makeNetworkInfo()); 4922 } else { 4923 loge("sendP2pConnectionChangedBroadcast(): WifiChannel is null"); 4924 } 4925 } 4926 isPlatformOrTargetSdkLessThanT(String packageName, int uid)4927 private boolean isPlatformOrTargetSdkLessThanT(String packageName, int uid) { 4928 if (!SdkLevel.isAtLeastT()) { 4929 return true; 4930 } 4931 return mWifiPermissionsUtil.isTargetSdkLessThan(packageName, 4932 Build.VERSION_CODES.TIRAMISU, uid); 4933 } 4934 checkNearbyDevicesPermission(Message message, String cmd)4935 private boolean checkNearbyDevicesPermission(Message message, String cmd) { 4936 if (null == message) return false; 4937 if (null == message.obj) return false; 4938 4939 String packageName = getCallingPkgName(message.sendingUid, message.replyTo); 4940 if (packageName == null) { 4941 return false; 4942 } 4943 int uid = message.sendingUid; 4944 Bundle extras = message.getData() 4945 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 4946 return checkNearbyDevicesPermission(uid, packageName, extras, cmd, message.obj); 4947 } 4948 checkNearbyDevicesPermission(int uid, String packageName, Bundle extras, String message, Object attributionSource)4949 private boolean checkNearbyDevicesPermission(int uid, String packageName, Bundle extras, 4950 String message, Object attributionSource) { 4951 if (extras != null 4952 && extras.getBoolean(WifiP2pManager.EXTRA_PARAM_KEY_INTERNAL_MESSAGE)) { 4953 // bypass permission check for internal call. 4954 return true; 4955 } 4956 try { 4957 mWifiPermissionsUtil.checkPackage(uid, packageName); 4958 } catch (SecurityException e) { 4959 loge("checkPackage failed"); 4960 return false; 4961 } 4962 return mWifiPermissionsUtil.checkNearbyDevicesPermission( 4963 SdkLevel.isAtLeastS() ? (AttributionSource) attributionSource : null, true, 4964 TAG + " " + message); 4965 } 4966 isPackageExisted(String pkgName)4967 private boolean isPackageExisted(String pkgName) { 4968 PackageManager pm = mContext.getPackageManager(); 4969 try { 4970 PackageInfo info = pm.getPackageInfo(pkgName, PackageManager.GET_META_DATA); 4971 } catch (PackageManager.NameNotFoundException e) { 4972 return false; 4973 } 4974 return true; 4975 } 4976 findTetheringServicePackage()4977 private String findTetheringServicePackage() { 4978 ArrayList<String> possiblePackageNames = new ArrayList<>(); 4979 // AOSP 4980 possiblePackageNames.add("com.android.networkstack.tethering"); 4981 // mainline release 4982 possiblePackageNames.add("com.google.android.networkstack.tethering"); 4983 // Android Go 4984 possiblePackageNames.add("com.android.networkstack.tethering.inprocess"); 4985 4986 for (String pkgName: possiblePackageNames) { 4987 if (isPackageExisted(pkgName)) { 4988 Log.d(TAG, "Tethering service package: " + pkgName); 4989 return pkgName; 4990 } 4991 } 4992 Log.w(TAG, "Cannot find tethering service package!"); 4993 return null; 4994 } 4995 sendP2pTetherRequestBroadcast()4996 private boolean sendP2pTetherRequestBroadcast() { 4997 String tetheringServicePackage = findTetheringServicePackage(); 4998 if (TextUtils.isEmpty(tetheringServicePackage)) return false; 4999 Log.i(TAG, "sending p2p tether request broadcast to " 5000 + tetheringServicePackage); 5001 5002 final String[] receiverPermissionsForTetheringRequest = { 5003 android.Manifest.permission.TETHER_PRIVILEGED 5004 }; 5005 Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 5006 intent.setPackage(tetheringServicePackage); 5007 // P2pConnectionEvent.CONNECTION_FAST connection type is only triggered as a result 5008 // of user interaction, so mark the broadcast as foreground. 5009 if (mWifiP2pMetrics.isP2pFastConnectionType()) { 5010 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 5011 } 5012 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5013 intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo)); 5014 intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, makeNetworkInfo()); 5015 intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, eraseOwnDeviceAddress(mGroup)); 5016 5017 Context context = mContext.createContextAsUser(UserHandle.ALL, 0); 5018 context.sendBroadcastWithMultiplePermissions( 5019 intent, receiverPermissionsForTetheringRequest); 5020 return true; 5021 } 5022 sendP2pPersistentGroupsChangedBroadcast()5023 private void sendP2pPersistentGroupsChangedBroadcast() { 5024 if (mVerboseLoggingEnabled) logd("sending p2p persistent groups changed broadcast"); 5025 Intent intent = new Intent(WifiP2pManager.ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED); 5026 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5027 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5028 } 5029 sendP2pRequestChangedBroadcast(boolean accepted)5030 private void sendP2pRequestChangedBroadcast(boolean accepted) { 5031 if (mVerboseLoggingEnabled) logd("sending p2p request changed broadcast"); 5032 Intent intent = new Intent(WifiP2pManager.ACTION_WIFI_P2P_REQUEST_RESPONSE_CHANGED); 5033 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 5034 | Intent.FLAG_RECEIVER_REPLACE_PENDING); 5035 intent.putExtra(WifiP2pManager.EXTRA_REQUEST_RESPONSE, accepted); 5036 if (accepted) { 5037 intent.putExtra(WifiP2pManager.EXTRA_REQUEST_CONFIG, mSavedPeerConfig); 5038 } else { 5039 intent.putExtra(WifiP2pManager.EXTRA_REQUEST_CONFIG, mSavedRejectedPeerConfig); 5040 } 5041 5042 Context context = mContext.createContextAsUser(UserHandle.ALL, 0); 5043 context.sendBroadcastWithMultiplePermissions( 5044 intent, RECEIVER_PERMISSIONS_FOR_BROADCAST); 5045 } 5046 addRowToDialog(ViewGroup group, int stringId, String value)5047 private void addRowToDialog(ViewGroup group, int stringId, String value) { 5048 Resources r = mContext.getResources(); 5049 View row = LayoutInflater.from(mContext).cloneInContext(mContext) 5050 .inflate(R.layout.wifi_p2p_dialog_row, group, false); 5051 ((TextView) row.findViewById(R.id.name)).setText(r.getString(stringId)); 5052 ((TextView) row.findViewById(R.id.value)).setText(value); 5053 group.addView(row); 5054 } 5055 5056 // Legacy dialog behavior to avoid WifiDialogActivity invoking onPause() of pre-T 5057 // Settings/Apps, which might trigger P2P teardown. showInvitationSentDialogPreT(@onNull String deviceName, @Nullable String pin)5058 private void showInvitationSentDialogPreT(@NonNull String deviceName, 5059 @Nullable String pin) { 5060 Resources r = mContext.getResources(); 5061 5062 final View textEntryView = LayoutInflater.from(mContext).cloneInContext(mContext) 5063 .inflate(R.layout.wifi_p2p_dialog, null); 5064 5065 ViewGroup group = textEntryView.findViewById(R.id.info); 5066 addRowToDialog(group, R.string.wifi_p2p_to_message, deviceName); 5067 addRowToDialog(group, R.string.wifi_p2p_show_pin_message, pin); 5068 5069 AlertDialog dialog = mFrameworkFacade.makeAlertDialogBuilder(mContext) 5070 .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title)) 5071 .setView(textEntryView) 5072 .setPositiveButton(r.getString(R.string.ok), null) 5073 .create(); 5074 dialog.setCanceledOnTouchOutside(false); 5075 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 5076 dialog.getWindow().addSystemFlags( 5077 WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); 5078 dialog.show(); 5079 } 5080 showInvitationSentDialog(@onNull String deviceName, @Nullable String pin)5081 private void showInvitationSentDialog(@NonNull String deviceName, @Nullable String pin) { 5082 int displayId = mDeathDataByBinder.values().stream() 5083 .filter(d -> d.mDisplayId != Display.DEFAULT_DISPLAY) 5084 .findAny() 5085 .map((dhd) -> dhd.mDisplayId) 5086 .orElse(Display.DEFAULT_DISPLAY); 5087 WifiDialogManager.DialogHandle dialogHandle = mWifiInjector.getWifiDialogManager() 5088 .createP2pInvitationSentDialog(deviceName, pin, displayId); 5089 if (dialogHandle == null) { 5090 loge("Could not create invitation sent dialog!"); 5091 return; 5092 } 5093 dialogHandle.launchDialog(); 5094 } 5095 notifyInvitationSent(String pin, String peerAddress)5096 private void notifyInvitationSent(String pin, String peerAddress) { 5097 ApproverEntry entry = mExternalApproverManager.get(MacAddress.fromString(peerAddress)); 5098 if (null == entry) { 5099 logd("No approver found for " + peerAddress 5100 + " check the wildcard address approver."); 5101 entry = mExternalApproverManager.get(MacAddress.BROADCAST_ADDRESS); 5102 } 5103 if (null != entry) { 5104 logd("Received invitation - Send WPS PIN event to the approver " + entry); 5105 Bundle extras = new Bundle(); 5106 extras.putParcelable(WifiP2pManager.EXTRA_PARAM_KEY_PEER_ADDRESS, 5107 entry.getAddress()); 5108 extras.putString(WifiP2pManager.EXTRA_PARAM_KEY_WPS_PIN, pin); 5109 replyToMessage(entry.getMessage(), WifiP2pManager.EXTERNAL_APPROVER_PIN_GENERATED, 5110 extras); 5111 return; 5112 } 5113 String deviceName = getDeviceName(peerAddress); 5114 if (!SdkLevel.isAtLeastT()) { 5115 showInvitationSentDialogPreT(deviceName, pin); 5116 } else { 5117 showInvitationSentDialog(deviceName, pin); 5118 } 5119 } 5120 5121 // Legacy dialog behavior to avoid WifiDialogActivity invoking onPause() of pre-T 5122 // Settings/Apps, which might trigger P2P teardown. showP2pProvDiscShowPinRequestDialogPreT(String deviceName, String pin)5123 private void showP2pProvDiscShowPinRequestDialogPreT(String deviceName, String pin) { 5124 Resources r = mContext.getResources(); 5125 final View textEntryView = LayoutInflater.from(mContext).cloneInContext(mContext) 5126 .inflate(R.layout.wifi_p2p_dialog, null); 5127 5128 ViewGroup group = textEntryView.findViewById(R.id.info); 5129 addRowToDialog(group, R.string.wifi_p2p_to_message, deviceName); 5130 addRowToDialog(group, R.string.wifi_p2p_show_pin_message, pin); 5131 5132 AlertDialog dialog = mFrameworkFacade.makeAlertDialogBuilder(mContext) 5133 .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title)) 5134 .setView(textEntryView) 5135 .setPositiveButton(r.getString(R.string.accept), 5136 (dialog1, which) -> sendMessage(PEER_CONNECTION_USER_CONFIRM)) 5137 .create(); 5138 dialog.setCanceledOnTouchOutside(false); 5139 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 5140 dialog.getWindow().addSystemFlags( 5141 WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); 5142 dialog.show(); 5143 } 5144 showP2pProvDiscShowPinRequestDialog(String deviceName, String pin)5145 private void showP2pProvDiscShowPinRequestDialog(String deviceName, String pin) { 5146 int displayId = mDeathDataByBinder.values().stream() 5147 .filter(d -> d.mDisplayId != Display.DEFAULT_DISPLAY) 5148 .findAny() 5149 .map((dhd) -> dhd.mDisplayId) 5150 .orElse(Display.DEFAULT_DISPLAY); 5151 // TODO(b/222115086): This dialog only makes sense for the prov disc receiver. 5152 // Use WifiDialogManager.createP2pInvitationSentDialog(...) for 5153 // the initiator. 5154 mWifiInjector.getWifiDialogManager().createP2pInvitationReceivedDialog( 5155 deviceName, 5156 false /* isPinRequested */, 5157 pin, 5158 displayId, 5159 new WifiDialogManager.P2pInvitationReceivedDialogCallback() { 5160 @Override 5161 public void onAccepted(@Nullable String optionalPin) { 5162 sendMessage(PEER_CONNECTION_USER_CONFIRM); 5163 } 5164 5165 @Override 5166 public void onDeclined() { 5167 // Do nothing 5168 // TODO(b/222115086): Do the correct "decline" behavior. 5169 } 5170 }, 5171 new WifiThreadRunner(getHandler())).launchDialog(); 5172 } 5173 notifyP2pProvDiscShowPinRequest(String pin, String peerAddress)5174 private void notifyP2pProvDiscShowPinRequest(String pin, String peerAddress) { 5175 ExternalApproverManager.ApproverEntry entry = mExternalApproverManager.get( 5176 MacAddress.fromString(peerAddress)); 5177 if (null == entry) { 5178 logd("No approver found for " + peerAddress 5179 + " check the wildcard address approver."); 5180 entry = mExternalApproverManager.get(MacAddress.BROADCAST_ADDRESS); 5181 } 5182 if (null != entry) { 5183 logd("Received provision discovery request - Send request from " 5184 + mSavedPeerConfig.deviceAddress + " to the approver " + entry); 5185 Bundle extras = new Bundle(); 5186 extras.putParcelable(WifiP2pManager.EXTRA_PARAM_KEY_DEVICE, 5187 mPeers.get(mSavedPeerConfig.deviceAddress)); 5188 extras.putParcelable(WifiP2pManager.EXTRA_PARAM_KEY_CONFIG, mSavedPeerConfig); 5189 replyToMessage(entry.getMessage(), 5190 WifiP2pManager.EXTERNAL_APPROVER_CONNECTION_REQUESTED, 5191 WifiP2pManager.ExternalApproverRequestListener.REQUEST_TYPE_NEGOTIATION, 5192 extras); 5193 return; 5194 } 5195 String deviceName = getDeviceName(peerAddress); 5196 if (!SdkLevel.isAtLeastT()) { 5197 showP2pProvDiscShowPinRequestDialogPreT(deviceName, pin); 5198 } else { 5199 showP2pProvDiscShowPinRequestDialog(deviceName, pin); 5200 } 5201 } 5202 5203 // Legacy dialog behavior to avoid WifiDialogActivity invoking onPause() of pre-T 5204 // Settings/Apps, which might trigger P2P teardown. showInvitationReceivedDialogPreT()5205 private void showInvitationReceivedDialogPreT() { 5206 Resources r = mContext.getResources(); 5207 final WpsInfo wps = mSavedPeerConfig.wps; 5208 final View textEntryView = LayoutInflater.from(mContext).cloneInContext(mContext) 5209 .inflate(R.layout.wifi_p2p_dialog, null); 5210 5211 ViewGroup group = textEntryView.findViewById(R.id.info); 5212 addRowToDialog(group, R.string.wifi_p2p_from_message, getDeviceName( 5213 mSavedPeerConfig.deviceAddress)); 5214 5215 final EditText pin = textEntryView.findViewById(R.id.wifi_p2p_wps_pin); 5216 5217 mLegacyInvitationDialog = mFrameworkFacade.makeAlertDialogBuilder(mContext) 5218 .setTitle(r.getString(R.string.wifi_p2p_invitation_to_connect_title)) 5219 .setView(textEntryView) 5220 .setPositiveButton(r.getString(R.string.accept), (dialog1, which) -> { 5221 if (wps.setup == WpsInfo.KEYPAD) { 5222 mSavedPeerConfig.wps.pin = pin.getText().toString(); 5223 } 5224 if (mVerboseLoggingEnabled) { 5225 logd(getName() + " accept invitation " + mSavedPeerConfig); 5226 } 5227 sendMessage(PEER_CONNECTION_USER_ACCEPT); 5228 }) 5229 .setNegativeButton(r.getString(R.string.decline), (dialog2, which) -> { 5230 if (mVerboseLoggingEnabled) logd(getName() + " ignore connect"); 5231 sendMessage(PEER_CONNECTION_USER_REJECT); 5232 }) 5233 .setOnCancelListener(arg0 -> { 5234 if (mVerboseLoggingEnabled) logd(getName() + " ignore connect"); 5235 sendMessage(PEER_CONNECTION_USER_REJECT); 5236 }) 5237 .create(); 5238 mLegacyInvitationDialog.setCanceledOnTouchOutside(false); 5239 5240 // make the enter pin area or the display pin area visible 5241 switch (wps.setup) { 5242 case WpsInfo.KEYPAD: 5243 if (mVerboseLoggingEnabled) logd("Enter pin section visible"); 5244 textEntryView.findViewById(R.id.enter_pin_section).setVisibility(View.VISIBLE); 5245 break; 5246 case WpsInfo.DISPLAY: 5247 if (mVerboseLoggingEnabled) logd("Shown pin section visible"); 5248 addRowToDialog(group, R.string.wifi_p2p_show_pin_message, wps.pin); 5249 break; 5250 default: 5251 break; 5252 } 5253 5254 if ((r.getConfiguration().uiMode & Configuration.UI_MODE_TYPE_APPLIANCE) 5255 == Configuration.UI_MODE_TYPE_APPLIANCE) { 5256 mLegacyInvitationDialog.setOnKeyListener((dialog3, keyCode, event) -> { 5257 if (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) { 5258 sendMessage(PEER_CONNECTION_USER_ACCEPT); 5259 dialog3.dismiss(); 5260 return true; 5261 } 5262 return false; 5263 }); 5264 } 5265 5266 mLegacyInvitationDialog.getWindow().setType( 5267 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 5268 mLegacyInvitationDialog.getWindow().addSystemFlags( 5269 WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS); 5270 mLegacyInvitationDialog.show(); 5271 } 5272 showInvitationReceivedDialog()5273 private void showInvitationReceivedDialog() { 5274 String deviceName = getDeviceName(mSavedPeerConfig.deviceAddress); 5275 boolean isPinRequested = false; 5276 String displayPin = null; 5277 5278 int displayId = mDeathDataByBinder.values().stream() 5279 .filter(d -> d.mDisplayId != Display.DEFAULT_DISPLAY) 5280 .findAny() 5281 .map((dhd) -> dhd.mDisplayId) 5282 .orElse(Display.DEFAULT_DISPLAY); 5283 final WpsInfo wps = mSavedPeerConfig.wps; 5284 switch (wps.setup) { 5285 case WpsInfo.KEYPAD: 5286 isPinRequested = true; 5287 break; 5288 case WpsInfo.DISPLAY: 5289 displayPin = wps.pin; 5290 break; 5291 default: 5292 break; 5293 } 5294 5295 WifiDialogManager.P2pInvitationReceivedDialogCallback callback = 5296 new WifiDialogManager.P2pInvitationReceivedDialogCallback() { 5297 @Override 5298 public void onAccepted(@Nullable String optionalPin) { 5299 if (optionalPin != null) { 5300 mSavedPeerConfig.wps.pin = optionalPin; 5301 } 5302 if (mVerboseLoggingEnabled) { 5303 logd(getName() + " accept invitation " + mSavedPeerConfig); 5304 } 5305 sendMessage(PEER_CONNECTION_USER_ACCEPT); 5306 mInvitationDialogHandle = null; 5307 } 5308 5309 @Override 5310 public void onDeclined() { 5311 if (mVerboseLoggingEnabled) { 5312 logd(getName() + " ignore connect"); 5313 } 5314 sendMessage(PEER_CONNECTION_USER_REJECT); 5315 mInvitationDialogHandle = null; 5316 } 5317 }; 5318 5319 mInvitationDialogHandle = 5320 mWifiInjector.getWifiDialogManager().createP2pInvitationReceivedDialog( 5321 deviceName, 5322 isPinRequested, 5323 displayPin, 5324 displayId, 5325 callback, 5326 new WifiThreadRunner(getHandler())); 5327 mInvitationDialogHandle.launchDialog(mContext.getResources().getInteger( 5328 R.integer.config_p2pInvitationReceivedDialogTimeoutMs)); 5329 } 5330 notifyInvitationReceived( @ifiP2pManager.ExternalApproverRequestListener.RequestType int requestType)5331 private void notifyInvitationReceived( 5332 @WifiP2pManager.ExternalApproverRequestListener.RequestType int requestType) { 5333 ApproverEntry entry = mExternalApproverManager.get( 5334 MacAddress.fromString(mSavedPeerConfig.deviceAddress)); 5335 if (null == entry) { 5336 logd("No approver found for " + mSavedPeerConfig.deviceAddress 5337 + " check the wildcard address approver."); 5338 entry = mExternalApproverManager.get(MacAddress.BROADCAST_ADDRESS); 5339 } 5340 if (null != entry) { 5341 logd("Received Invitation request - Send request " + requestType + " from " 5342 + mSavedPeerConfig.deviceAddress + " to the approver " + entry); 5343 Bundle extras = new Bundle(); 5344 extras.putParcelable(WifiP2pManager.EXTRA_PARAM_KEY_DEVICE, 5345 mPeers.get(mSavedPeerConfig.deviceAddress)); 5346 extras.putParcelable(WifiP2pManager.EXTRA_PARAM_KEY_CONFIG, mSavedPeerConfig); 5347 replyToMessage(entry.getMessage(), 5348 WifiP2pManager.EXTERNAL_APPROVER_CONNECTION_REQUESTED, 5349 requestType, extras); 5350 return; 5351 } 5352 if (!SdkLevel.isAtLeastT()) { 5353 showInvitationReceivedDialogPreT(); 5354 } else { 5355 showInvitationReceivedDialog(); 5356 } 5357 } 5358 5359 /** 5360 * This method unifies the persisent group list, cleans up unused 5361 * networks and if required, updates corresponding broadcast receivers 5362 * @param reload if true, reload the group list from scratch 5363 * and send broadcast message with fresh list 5364 */ updatePersistentNetworks(boolean reload)5365 private void updatePersistentNetworks(boolean reload) { 5366 if (reload) mGroups.clear(); 5367 5368 // Save in all cases, including when reload was requested, but 5369 // no network has been found. 5370 if (mWifiNative.p2pListNetworks(mGroups) || reload) { 5371 for (WifiP2pGroup group : mGroups.getGroupList()) { 5372 if (group.getOwner() == null) { 5373 Log.d(TAG, "group.getOwner() null"); 5374 continue; 5375 } 5376 if (Objects.equals(mThisDevice.deviceAddress, group.getOwner().deviceAddress)) { 5377 group.setOwner(mThisDevice); 5378 } 5379 } 5380 mWifiNative.saveConfig(); 5381 mWifiP2pMetrics.updatePersistentGroup(mGroups); 5382 sendP2pPersistentGroupsChangedBroadcast(); 5383 } 5384 } 5385 5386 /** 5387 * A config is valid if it has a peer address that has already been 5388 * discovered 5389 * @param WifiP2pConfig config to be validated 5390 * @return true if it is invalid, false otherwise 5391 */ isConfigInvalid(WifiP2pConfig config)5392 private boolean isConfigInvalid(WifiP2pConfig config) { 5393 if (config == null) return true; 5394 if (TextUtils.isEmpty(config.deviceAddress)) return true; 5395 return mPeers.get(config.deviceAddress) == null; 5396 } 5397 5398 /** 5399 * Check the network name complies standard SSID naming rules. 5400 * 5401 * The network name of a group is also the broadcasting SSID, 5402 * as a result, the network name must complies standard SSID naming 5403 * rules. 5404 */ isValidNetworkName(String networkName)5405 private boolean isValidNetworkName(String networkName) { 5406 if (TextUtils.isEmpty(networkName)) return false; 5407 5408 byte[] ssidBytes = networkName.getBytes(StandardCharsets.UTF_8); 5409 if (ssidBytes.length < MIN_NETWORK_NAME_BYTES) return false; 5410 return ssidBytes.length <= MAX_NETWORK_NAME_BYTES; 5411 } 5412 5413 /** 5414 * A config is valid as a group if it has network name and passphrase. 5415 * Supplicant can construct a group on the fly for creating a group with specified config 5416 * or join a group without negotiation and WPS. 5417 * @param WifiP2pConfig config to be validated 5418 * @return true if it is valid, false otherwise 5419 */ isConfigValidAsGroup(WifiP2pConfig config)5420 private boolean isConfigValidAsGroup(WifiP2pConfig config) { 5421 if (config == null) return false; 5422 if (TextUtils.isEmpty(config.deviceAddress)) return false; 5423 return isValidNetworkName(config.networkName) 5424 && !TextUtils.isEmpty(config.passphrase); 5425 } 5426 fetchCurrentDeviceDetails(WifiP2pConfig config)5427 private WifiP2pDevice fetchCurrentDeviceDetails(WifiP2pConfig config) { 5428 if (config == null) return null; 5429 // Fetch & update group capability from supplicant on the device 5430 int gc = mWifiNative.getGroupCapability(config.deviceAddress); 5431 // TODO: The supplicant does not provide group capability changes as an event. 5432 // Having it pushed as an event would avoid polling for this information right 5433 // before a connection 5434 mPeers.updateGroupCapability(config.deviceAddress, gc); 5435 return mPeers.get(config.deviceAddress); 5436 } 5437 5438 /** 5439 * Erase the MAC address of our interface if it is present in a given device, to prevent 5440 * apps from having access to persistent identifiers. 5441 * 5442 * @param device a device possibly having the same physical address as the wlan interface. 5443 * @return a copy of the input, possibly with the device address erased. 5444 */ eraseOwnDeviceAddress(WifiP2pDevice device)5445 private WifiP2pDevice eraseOwnDeviceAddress(WifiP2pDevice device) { 5446 if (device == null) { 5447 return null; 5448 } 5449 WifiP2pDevice result = new WifiP2pDevice(device); 5450 if (device.deviceAddress != null 5451 && mThisDevice.deviceAddress != null 5452 && device.deviceAddress.length() > 0 5453 && mThisDevice.deviceAddress.equals(device.deviceAddress)) { 5454 result.deviceAddress = ANONYMIZED_DEVICE_ADDRESS; 5455 } 5456 return result; 5457 } 5458 5459 /** 5460 * Erase the MAC address of our interface if it is set as the device address for any of the 5461 * devices in a group. 5462 * 5463 * @param group a p2p group containing p2p devices. 5464 * @return a copy of the input, with any devices corresponding to our wlan interface having 5465 * their device address erased. 5466 */ eraseOwnDeviceAddress(WifiP2pGroup group)5467 private WifiP2pGroup eraseOwnDeviceAddress(WifiP2pGroup group) { 5468 if (group == null) { 5469 return null; 5470 } 5471 5472 WifiP2pGroup result = new WifiP2pGroup(group); 5473 5474 // Create copies of the clients so they're not shared with the original object. 5475 for (WifiP2pDevice originalDevice : group.getClientList()) { 5476 result.removeClient(originalDevice); 5477 result.addClient(eraseOwnDeviceAddress(originalDevice)); 5478 } 5479 5480 WifiP2pDevice groupOwner = group.getOwner(); 5481 result.setOwner(eraseOwnDeviceAddress(groupOwner)); 5482 5483 return result; 5484 } 5485 5486 /** 5487 * Erase the MAC address of our interface if it is present in a given device, to prevent 5488 * apps from having access to persistent identifiers. If the requesting party holds the 5489 * {@link Manifest.permission.LOCAL_MAC_ADDRESS} permission, the address is not erased. 5490 * 5491 * @param device a device possibly having the same physical address as the wlan interface. 5492 * @param uid the user id of the app that requested the information. 5493 * @return a copy of the input, possibly with the device address erased. 5494 */ maybeEraseOwnDeviceAddress(WifiP2pDevice device, int uid)5495 private WifiP2pDevice maybeEraseOwnDeviceAddress(WifiP2pDevice device, int uid) { 5496 if (device == null) { 5497 return null; 5498 } 5499 if (mWifiPermissionsUtil.checkLocalMacAddressPermission(uid)) { 5500 // Calling app holds the LOCAL_MAC_ADDRESS permission, and is allowed to see this 5501 // device's MAC. 5502 return new WifiP2pDevice(device); 5503 } 5504 if (mVerboseLoggingEnabled) { 5505 Log.i(TAG, "Uid " + uid + " does not have local mac address permission"); 5506 } 5507 return eraseOwnDeviceAddress(device); 5508 } 5509 5510 /** 5511 * Erase the MAC address of our interface if it is set as the device address for any of the 5512 * devices in a group. If the requesting party holds the 5513 * {@link Manifest.permission.LOCAL_MAC_ADDRESS} permission, the address is not erased. 5514 * 5515 * @param group a p2p group containing p2p devices. 5516 * @param uid the user id of the app that requested the information. 5517 * @return a copy of the input, with any devices corresponding to our wlan interface having 5518 * their device address erased. If the requesting app holds the LOCAL_MAC_ADDRESS 5519 * permission, this method returns a copy of the input. 5520 */ maybeEraseOwnDeviceAddress(WifiP2pGroup group, int uid)5521 private WifiP2pGroup maybeEraseOwnDeviceAddress(WifiP2pGroup group, int uid) { 5522 if (group == null) { 5523 return null; 5524 } 5525 if (mWifiPermissionsUtil.checkLocalMacAddressPermission(uid)) { 5526 // Calling app holds the LOCAL_MAC_ADDRESS permission, and is allowed to see this 5527 // device's MAC. 5528 return new WifiP2pGroup(group); 5529 } 5530 if (mVerboseLoggingEnabled) { 5531 Log.i(TAG, "Uid " + uid + " does not have local mac address permission"); 5532 } 5533 return eraseOwnDeviceAddress(group); 5534 } 5535 5536 /** 5537 * Erase the MAC address of our interface if it is set as the device address for any of the 5538 * devices in a list of groups. If the requesting party holds the 5539 * {@link Manifest.permission.LOCAL_MAC_ADDRESS} permission, the address is not erased. 5540 * 5541 * @param groupList a list of p2p groups containing p2p devices. 5542 * @param uid the user id of the app that requested the information. 5543 * @return a copy of the input, with any devices corresponding to our wlan interface having 5544 * their device address erased. If the requesting app holds the LOCAL_MAC_ADDRESS 5545 * permission, this method returns a copy of the input. 5546 */ maybeEraseOwnDeviceAddress(WifiP2pGroupList groupList, int uid)5547 private WifiP2pGroupList maybeEraseOwnDeviceAddress(WifiP2pGroupList groupList, int uid) { 5548 if (groupList == null) { 5549 return null; 5550 } 5551 WifiP2pGroupList result = new WifiP2pGroupList(); 5552 for (WifiP2pGroup group : groupList.getGroupList()) { 5553 result.add(maybeEraseOwnDeviceAddress(group, uid)); 5554 } 5555 return result; 5556 } 5557 5558 /** 5559 * Start a p2p group negotiation and display pin if necessary 5560 * @param config for the peer 5561 */ p2pConnectWithPinDisplay(WifiP2pConfig config, int triggerType)5562 private void p2pConnectWithPinDisplay(WifiP2pConfig config, int triggerType) { 5563 if (config == null) { 5564 Log.e(TAG, "Illegal argument(s)"); 5565 return; 5566 } 5567 WifiP2pDevice dev = fetchCurrentDeviceDetails(config); 5568 if (dev == null) { 5569 Log.e(TAG, "Invalid device"); 5570 return; 5571 } 5572 config.groupOwnerIntent = selectGroupOwnerIntentIfNecessary(config); 5573 boolean action; 5574 if (triggerType == P2P_CONNECT_TRIGGER_INVITATION_REQ 5575 || config.isJoinExistingGroup()) { 5576 // The group owner won't report it is a Group Owner always. 5577 // If this is called from the invitation path, the sender should be in 5578 // a group, and the target should be a group owner. 5579 action = JOIN_GROUP; 5580 } else { 5581 action = dev.isGroupOwner() ? JOIN_GROUP : FORM_GROUP; 5582 } 5583 5584 String pin = mWifiNative.p2pConnect(config, action); 5585 try { 5586 Integer.parseInt(pin); 5587 mSavedPeerConfig.wps.pin = pin; 5588 notifyInvitationSent(pin, config.deviceAddress); 5589 } catch (NumberFormatException ignore) { 5590 // do nothing if p2pConnect did not return a pin 5591 } 5592 } 5593 5594 /** 5595 * Reinvoke a persistent group. 5596 * 5597 * @param config for the peer 5598 * @return true on success, false on failure 5599 */ reinvokePersistentGroup(WifiP2pConfig config, boolean isInvited)5600 private boolean reinvokePersistentGroup(WifiP2pConfig config, boolean isInvited) { 5601 if (config == null) { 5602 Log.e(TAG, "Illegal argument(s)"); 5603 return false; 5604 } 5605 WifiP2pDevice dev = fetchCurrentDeviceDetails(config); 5606 if (dev == null) { 5607 Log.e(TAG, "Invalid device"); 5608 return false; 5609 } 5610 // The group owner won't report it is a Group Owner always. 5611 // If this is called from the invitation path, the sender should be in 5612 // a group, and the target should be a group owner. 5613 boolean join = dev.isGroupOwner() || isInvited 5614 || config.isJoinExistingGroup(); 5615 String ssid = mWifiNative.p2pGetSsid(dev.deviceAddress); 5616 if (mVerboseLoggingEnabled) logd("target ssid is " + ssid + " join:" + join); 5617 5618 if (join && dev.isGroupLimit()) { 5619 if (mVerboseLoggingEnabled) logd("target device reaches group limit."); 5620 5621 // if the target group has reached the limit, 5622 // try group formation. 5623 join = false; 5624 } else if (join) { 5625 int netId = mGroups.getNetworkId(dev.deviceAddress, ssid); 5626 if (isInvited && netId < 0) { 5627 netId = mGroups.getNetworkId(dev.deviceAddress); 5628 } 5629 if (netId >= 0) { 5630 // Skip WPS and start 4way handshake immediately. 5631 return mWifiNative.p2pGroupAdd(netId); 5632 } 5633 } 5634 5635 if (!join && dev.isDeviceLimit()) { 5636 loge("target device reaches the device limit."); 5637 return false; 5638 } 5639 5640 if (!join && dev.isInvitationCapable()) { 5641 int netId = WifiP2pGroup.NETWORK_ID_PERSISTENT; 5642 if (config.netId >= 0) { 5643 if (config.deviceAddress.equals(mGroups.getOwnerAddr(config.netId))) { 5644 netId = config.netId; 5645 } 5646 } else { 5647 netId = mGroups.getNetworkId(dev.deviceAddress); 5648 } 5649 if (netId < 0) { 5650 netId = getNetworkIdFromClientList(dev.deviceAddress); 5651 } 5652 if (mVerboseLoggingEnabled) { 5653 logd("netId related with " + dev.deviceAddress + " = " + netId); 5654 } 5655 if (netId >= 0) { 5656 // Invoke the persistent group. 5657 if (mWifiNative.p2pReinvoke(netId, dev.deviceAddress)) { 5658 // Save network id. It'll be used when an invitation 5659 // result event is received. 5660 config.netId = netId; 5661 return true; 5662 } else { 5663 loge("p2pReinvoke() failed, update networks"); 5664 updatePersistentNetworks(RELOAD); 5665 return false; 5666 } 5667 } 5668 } 5669 return false; 5670 } 5671 5672 /** 5673 * Return the network id of the group owner profile which has the p2p client with 5674 * the specified device address in it's client list. 5675 * If more than one persistent group of the same address is present in its client 5676 * lists, return the first one. 5677 * 5678 * @param deviceAddress p2p device address. 5679 * @return the network id. if not found, return -1. 5680 */ getNetworkIdFromClientList(String deviceAddress)5681 private int getNetworkIdFromClientList(String deviceAddress) { 5682 if (deviceAddress == null) return -1; 5683 5684 Collection<WifiP2pGroup> groups = mGroups.getGroupList(); 5685 for (WifiP2pGroup group : groups) { 5686 int netId = group.getNetworkId(); 5687 String[] p2pClientList = getClientList(netId); 5688 if (p2pClientList == null) continue; 5689 for (String client : p2pClientList) { 5690 if (deviceAddress.equalsIgnoreCase(client)) { 5691 return netId; 5692 } 5693 } 5694 } 5695 return -1; 5696 } 5697 5698 /** 5699 * Return p2p client list associated with the specified network id. 5700 * @param netId network id. 5701 * @return p2p client list. if not found, return null. 5702 */ getClientList(int netId)5703 private String[] getClientList(int netId) { 5704 String p2pClients = mWifiNative.getP2pClientList(netId); 5705 if (p2pClients == null) { 5706 return null; 5707 } 5708 return p2pClients.split(" "); 5709 } 5710 5711 /** 5712 * Remove the specified p2p client from the specified profile. 5713 * @param netId network id of the profile. 5714 * @param addr p2p client address to be removed. 5715 * @param isRemovable if true, remove the specified profile if its client 5716 * list becomes empty. 5717 * @return whether removing the specified p2p client is successful or not. 5718 */ removeClientFromList(int netId, String addr, boolean isRemovable)5719 private boolean removeClientFromList(int netId, String addr, boolean isRemovable) { 5720 StringBuilder modifiedClientList = new StringBuilder(); 5721 String[] currentClientList = getClientList(netId); 5722 boolean isClientRemoved = false; 5723 if (currentClientList != null) { 5724 for (String client : currentClientList) { 5725 if (!client.equalsIgnoreCase(addr)) { 5726 modifiedClientList.append(" "); 5727 modifiedClientList.append(client); 5728 } else { 5729 isClientRemoved = true; 5730 } 5731 } 5732 } 5733 if (modifiedClientList.length() == 0 && isRemovable) { 5734 // the client list is empty. so remove it. 5735 if (mVerboseLoggingEnabled) logd("Remove unknown network"); 5736 mGroups.remove(netId); 5737 mWifiP2pMetrics.updatePersistentGroup(mGroups); 5738 return true; 5739 } 5740 5741 if (!isClientRemoved) { 5742 // specified p2p client is not found. already removed. 5743 return false; 5744 } 5745 5746 if (mVerboseLoggingEnabled) logd("Modified client list: " + modifiedClientList); 5747 if (modifiedClientList.length() == 0) { 5748 modifiedClientList.append("\"\""); 5749 } 5750 mWifiNative.setP2pClientList(netId, modifiedClientList.toString()); 5751 mWifiNative.saveConfig(); 5752 return true; 5753 } 5754 getInterfaceAddress(String interfaceName)5755 private Inet4Address getInterfaceAddress(String interfaceName) { 5756 NetworkInterface iface; 5757 try { 5758 iface = NetworkInterface.getByName(interfaceName); 5759 } catch (SocketException ex) { 5760 Log.w(TAG, "Could not obtain address of network interface " 5761 + interfaceName, ex); 5762 return null; 5763 } 5764 if (null == iface) { 5765 Log.w(TAG, "Could not obtain interface " + interfaceName); 5766 return null; 5767 } 5768 Enumeration<InetAddress> addrs = iface.getInetAddresses(); 5769 while (addrs.hasMoreElements()) { 5770 InetAddress addr = addrs.nextElement(); 5771 if (addr instanceof Inet4Address) { 5772 return (Inet4Address) addr; 5773 } 5774 } 5775 Log.w(TAG, "Could not obtain address of network interface " 5776 + interfaceName + " because it had no IPv4 addresses."); 5777 return null; 5778 } 5779 setWifiP2pInfoOnGroupFormation(String serverAddress)5780 private void setWifiP2pInfoOnGroupFormation(String serverAddress) { 5781 InetAddress serverInetAddress = serverAddress == null 5782 ? null 5783 : InetAddresses.parseNumericAddress(serverAddress); 5784 setWifiP2pInfoOnGroupFormationWithInetAddress(serverInetAddress); 5785 } 5786 setWifiP2pInfoOnGroupFormationWithInetAddress(InetAddress serverAddress)5787 private void setWifiP2pInfoOnGroupFormationWithInetAddress(InetAddress serverAddress) { 5788 mWifiP2pInfo.groupFormed = true; 5789 mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner(); 5790 mWifiP2pInfo.groupOwnerAddress = serverAddress; 5791 } 5792 resetWifiP2pInfo()5793 private void resetWifiP2pInfo() { 5794 mWifiP2pInfo.groupFormed = false; 5795 mWifiP2pInfo.isGroupOwner = false; 5796 mWifiP2pInfo.groupOwnerAddress = null; 5797 } 5798 getDeviceName(String deviceAddress)5799 private String getDeviceName(String deviceAddress) { 5800 WifiP2pDevice d = mPeers.get(deviceAddress); 5801 if (d != null) { 5802 return d.deviceName; 5803 } 5804 // Treat the address as name if there is no match 5805 return deviceAddress; 5806 } 5807 getPersistedDeviceName()5808 private String getPersistedDeviceName() { 5809 String deviceName = mSettingsConfigStore.get(WIFI_P2P_DEVICE_NAME); 5810 if (!TextUtils.isEmpty(deviceName)) return deviceName; 5811 5812 // If a default device is already generated and not expired, just return it. 5813 long expirationTime = mLastDefaultDeviceNameGeneratingTimeMillis 5814 + DEFAULT_DEVICE_NAME_LIFE_TIME_MILLIS; 5815 if (!TextUtils.isEmpty(mDefaultDeviceName) 5816 && expirationTime > mClock.getElapsedSinceBootMillis()) { 5817 logd("Return the persistent device name: " + mDefaultDeviceName); 5818 return mDefaultDeviceName; 5819 } 5820 5821 String prefix = mWifiGlobals.getWifiP2pDeviceNamePrefix(); 5822 if (DEVICE_NAME_PREFIX_LENGTH_MAX < prefix.getBytes(StandardCharsets.UTF_8).length 5823 || 0 == prefix.getBytes(StandardCharsets.UTF_8).length) { 5824 logw("The length of default device name prefix is invalid" 5825 + ", fallback to default name."); 5826 prefix = DEFAULT_DEVICE_NAME_PREFIX; 5827 } 5828 // The length of remaining bytes is at least {@link #DEVICE_NAME_POSTFIX_LENGTH_MIN}. 5829 int remainingBytes = 5830 DEVICE_NAME_LENGTH_MAX - prefix.getBytes(StandardCharsets.UTF_8).length; 5831 5832 int numDigits = mWifiGlobals.getWifiP2pDeviceNamePostfixNumDigits(); 5833 if (numDigits > remainingBytes) { 5834 logw("The postfix length exceeds the remaining byte number" 5835 + ", use the smaller one."); 5836 numDigits = remainingBytes; 5837 } 5838 5839 String postfix; 5840 if (numDigits >= DEVICE_NAME_POSTFIX_LENGTH_MIN) { 5841 postfix = StringUtil.generateRandomNumberString(numDigits); 5842 } else if (!SdkLevel.isAtLeastT()) { 5843 // We use the 4 digits of the ANDROID_ID to have a friendly 5844 // default that has low likelihood of collision with a peer 5845 String id = mFrameworkFacade.getSecureStringSetting(mContext, 5846 Settings.Secure.ANDROID_ID); 5847 postfix = id.substring(0, 4); 5848 } else { 5849 postfix = StringUtil.generateRandomString(4); 5850 } 5851 mDefaultDeviceName = prefix + postfix; 5852 mLastDefaultDeviceNameGeneratingTimeMillis = mClock.getElapsedSinceBootMillis(); 5853 logd("the default device name: " + mDefaultDeviceName); 5854 return mDefaultDeviceName; 5855 } 5856 generateP2pSsidPostfix(String devName)5857 private String generateP2pSsidPostfix(String devName) { 5858 if (TextUtils.isEmpty(devName)) return "-"; 5859 5860 StringBuilder sb = new StringBuilder("-"); 5861 Charset charset = Charset.forName("UTF-8"); 5862 byte[] rawBytes = devName.getBytes(charset); 5863 if (rawBytes.length <= GROUP_NAME_POSTFIX_LENGTH_MAX) { 5864 sb.append(devName); 5865 } else { 5866 CharsetDecoder decoder = charset.newDecoder(); 5867 ByteBuffer bb = ByteBuffer.wrap(rawBytes, 0, GROUP_NAME_POSTFIX_LENGTH_MAX); 5868 CharBuffer cb = CharBuffer.allocate(GROUP_NAME_POSTFIX_LENGTH_MAX); 5869 5870 // Ignore an incomplete character 5871 decoder.onMalformedInput(CodingErrorAction.IGNORE); 5872 decoder.decode(bb, cb, true); 5873 decoder.flush(cb); 5874 sb.append(new String(cb.array(), 0, cb.position())); 5875 } 5876 Log.i(TAG, "P2P SSID postfix: " + sb 5877 + " len=" + sb.toString().length() 5878 + " bytes=" + sb.toString().getBytes(charset).length); 5879 return sb.toString(); 5880 } 5881 setAndPersistDeviceName(String devName)5882 private boolean setAndPersistDeviceName(String devName) { 5883 if (TextUtils.isEmpty(devName)) return false; 5884 if (devName.getBytes(Charset.forName("UTF-8")).length > DEVICE_NAME_LENGTH_MAX) { 5885 return false; 5886 } 5887 5888 if (mInterfaceName != null) { 5889 String postfix = generateP2pSsidPostfix(devName); 5890 // Order important: postfix is used when a group is formed 5891 // and the group name will be reported back. If setDeviceName() 5892 // fails, it won't be a big deal. 5893 if (!mWifiNative.setP2pSsidPostfix(postfix)) { 5894 loge("Failed to set SSID postfix " + postfix); 5895 return false; 5896 } 5897 if (!mWifiNative.setDeviceName(devName)) { 5898 loge("Failed to set device name " + devName); 5899 // Try to restore the postfix. 5900 mWifiNative.setP2pSsidPostfix(generateP2pSsidPostfix(mThisDevice.deviceName)); 5901 return false; 5902 } 5903 } 5904 5905 mThisDevice.deviceName = devName; 5906 mSettingsConfigStore.put(WIFI_P2P_DEVICE_NAME, devName); 5907 sendThisDeviceChangedBroadcast(); 5908 return true; 5909 } 5910 setWfdInfo(WifiP2pWfdInfo wfdInfo)5911 private boolean setWfdInfo(WifiP2pWfdInfo wfdInfo) { 5912 final boolean enabled = wfdInfo.isEnabled(); 5913 if (!mWifiNative.setWfdEnable(enabled)) { 5914 loge("Failed to set wfd enable: " + enabled); 5915 return false; 5916 } 5917 5918 if (enabled) { 5919 if (!mWifiNative.setWfdDeviceInfo(wfdInfo.getDeviceInfoHex())) { 5920 loge("Failed to set wfd properties"); 5921 return false; 5922 } 5923 if (!setWfdR2InfoIfNecessary(wfdInfo)) { 5924 loge("Failed to set wfd r2 properties"); 5925 return false; 5926 } 5927 } 5928 mThisDevice.wfdInfo = wfdInfo; 5929 sendThisDeviceChangedBroadcast(); 5930 return true; 5931 } 5932 setWfdR2InfoIfNecessary(WifiP2pWfdInfo wfdInfo)5933 private boolean setWfdR2InfoIfNecessary(WifiP2pWfdInfo wfdInfo) { 5934 if (!SdkLevel.isAtLeastS()) return true; 5935 if (!wfdInfo.isR2Supported()) return true; 5936 return mWifiNative.setWfdR2DeviceInfo(wfdInfo.getR2DeviceInfoHex()); 5937 } 5938 configureEapolIpAddressAllocationParamsIfEnabled()5939 private void configureEapolIpAddressAllocationParamsIfEnabled() { 5940 if (!mContext.getResources() 5941 .getBoolean(R.bool.config_wifiP2pGoIpAddressAllocationInEapolFrames)) { 5942 return; 5943 } 5944 try { 5945 String ipAddressStart = mContext.getResources() 5946 .getString(R.string.config_wifiP2pGoEapolIpAddressRangeStart); 5947 String ipAddressEnd = mContext.getResources() 5948 .getString(R.string.config_wifiP2pGoEapolIpAddressRangeEnd); 5949 if (TextUtils.isEmpty(ipAddressStart) || TextUtils.isEmpty(ipAddressEnd)) { 5950 ipAddressStart = GO_EAPOL_IP_RANGE_DEFAULT_START_ADDRESS; 5951 ipAddressEnd = GO_EAPOL_IP_RANGE_DEFAULT_END_ADDRESS; 5952 } 5953 if (mVerboseLoggingEnabled) { 5954 Log.i(TAG, "EAPOL IP addresses range start: " + ipAddressStart 5955 + ", End: " + ipAddressEnd); 5956 } 5957 5958 // Convert the IP from string format to int 5959 InetAddress ipAddressGo = InetAddresses 5960 .parseNumericAddress(GO_EAPOL_IP_ADDRESS); 5961 InetAddress subnetMask = InetAddresses.parseNumericAddress( 5962 GO_EAPOL_IP_SUBNET_MASK); 5963 InetAddress ipAddressRangeStart = 5964 InetAddresses.parseNumericAddress(ipAddressStart); 5965 InetAddress ipAddressRangeEnd = 5966 InetAddresses.parseNumericAddress(ipAddressEnd); 5967 if (!mWifiNative.configureEapolIpAddressAllocationParams( 5968 inet4AddressToIntHTL((Inet4Address) ipAddressGo), 5969 inet4AddressToIntHTL((Inet4Address) subnetMask), 5970 inet4AddressToIntHTL((Inet4Address) ipAddressRangeStart), 5971 inet4AddressToIntHTL((Inet4Address) ipAddressRangeEnd))) { 5972 loge("Failed to configure EAPOL IP address params in the native service"); 5973 } 5974 } catch (Exception e) { 5975 loge("Failed to configure EAPOL IP address params " + e); 5976 } 5977 5978 } 5979 initializeP2pSettings()5980 private void initializeP2pSettings() { 5981 mThisDevice.deviceName = getPersistedDeviceName(); 5982 mThisDevice.primaryDeviceType = mContext.getResources().getString( 5983 R.string.config_wifi_p2p_device_type); 5984 5985 mWifiNative.setDeviceName(mThisDevice.deviceName); 5986 // DIRECT-XY-DEVICENAME (XY is randomly generated) 5987 mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName); 5988 mWifiNative.setP2pDeviceType(mThisDevice.primaryDeviceType); 5989 // Supplicant defaults to using virtual display with display 5990 // which refers to a remote display. Use physical_display 5991 mWifiNative.setConfigMethods("virtual_push_button physical_display keypad"); 5992 5993 mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress(); 5994 if (!mWifiGlobals.isP2pMacRandomizationSupported()) { 5995 mSettingsConfigStore.put(WIFI_P2P_DEVICE_ADDRESS, mThisDevice.deviceAddress); 5996 } 5997 updateThisDevice(WifiP2pDevice.AVAILABLE); 5998 mWifiNative.p2pFlush(); 5999 mWifiNative.p2pServiceFlush(); 6000 mServiceTransactionId = 0; 6001 mServiceDiscReqId = null; 6002 6003 if (null != mThisDevice.wfdInfo) { 6004 setWfdInfo(mThisDevice.wfdInfo); 6005 } 6006 6007 updatePersistentNetworks(RELOAD); 6008 6009 configureEapolIpAddressAllocationParamsIfEnabled(); 6010 6011 enableVerboseLogging(mSettingsConfigStore.get(WIFI_VERBOSE_LOGGING_ENABLED)); 6012 if (mVerboseLoggingEnabled) { 6013 logd("Initialized p2p settings - DeviceAddress: " 6014 + mThisDevice.deviceAddress); 6015 } 6016 } 6017 updateThisDevice(int status)6018 private void updateThisDevice(int status) { 6019 mThisDevice.status = status; 6020 sendThisDeviceChangedBroadcast(); 6021 } 6022 handleProvDiscFailure(WifiP2pProvDiscEvent pdEvent, boolean invalidateSavedPeer)6023 private boolean handleProvDiscFailure(WifiP2pProvDiscEvent pdEvent, 6024 boolean invalidateSavedPeer) { 6025 if (TextUtils.isEmpty(pdEvent.device.deviceAddress)) return false; 6026 if (!pdEvent.device.deviceAddress.equals( 6027 mSavedPeerConfig.deviceAddress)) { 6028 return false; 6029 } 6030 6031 if (null != mInvitationDialogHandle) { 6032 mInvitationDialogHandle.dismissDialog(); 6033 mInvitationDialogHandle = null; 6034 } 6035 if (null != mLegacyInvitationDialog) { 6036 mLegacyInvitationDialog.dismiss(); 6037 mLegacyInvitationDialog = null; 6038 } 6039 if (invalidateSavedPeer) { 6040 mSavedPeerConfig.invalidate(); 6041 } 6042 return true; 6043 } 6044 handleGroupCreationFailure()6045 private void handleGroupCreationFailure() { 6046 // A group is formed, but the tethering request is not proceed. 6047 if (null != mGroup) { 6048 // Clear any timeout that was set. This is essential for devices 6049 // that reuse the main p2p interface for a created group. 6050 mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0); 6051 mWifiNative.p2pGroupRemove(mGroup.getInterface()); 6052 mGroup = null; 6053 } 6054 resetWifiP2pInfo(); 6055 mDetailedState = NetworkInfo.DetailedState.FAILED; 6056 sendP2pConnectionChangedBroadcast(); 6057 6058 // Remove only the peer we failed to connect to so that other devices discovered 6059 // that have not timed out still remain in list for connection 6060 boolean peersChanged = mPeers.remove(mPeersLostDuringConnection); 6061 if (!TextUtils.isEmpty(mSavedPeerConfig.deviceAddress) 6062 && mPeers.remove(mSavedPeerConfig.deviceAddress) != null) { 6063 peersChanged = true; 6064 } 6065 if (peersChanged) { 6066 sendPeersChangedBroadcast(); 6067 } 6068 6069 mPeersLostDuringConnection.clear(); 6070 mServiceDiscReqId = null; 6071 6072 Bundle extras = new Bundle(); 6073 extras.putBoolean(WifiP2pManager.EXTRA_PARAM_KEY_INTERNAL_MESSAGE, true); 6074 Message msg = Message.obtain(); 6075 msg.sendingUid = Process.myUid(); 6076 msg.what = WifiP2pManager.DISCOVER_PEERS; 6077 msg.getData().putBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE, extras); 6078 sendMessage(msg); 6079 6080 sendDisconnectWifiRequest(false); 6081 } 6082 handleGroupRemoved()6083 private void handleGroupRemoved() { 6084 if (mGroup.isGroupOwner()) { 6085 // {@link com.android.server.connectivity.Tethering} listens to 6086 // {@link WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION} 6087 // events and takes over the DHCP server management automatically. 6088 } else { 6089 if (mVerboseLoggingEnabled) logd("stop IpClient"); 6090 stopIpClient(); 6091 try { 6092 mNetdWrapper.removeInterfaceFromLocalNetwork(mGroup.getInterface()); 6093 } catch (IllegalStateException e) { 6094 loge("Failed to remove iface from local network " + e); 6095 } 6096 } 6097 6098 try { 6099 mNetdWrapper.clearInterfaceAddresses(mGroup.getInterface()); 6100 } catch (Exception e) { 6101 loge("Failed to clear addresses " + e); 6102 } 6103 6104 // Clear any timeout that was set. This is essential for devices 6105 // that reuse the main p2p interface for a created group. 6106 mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0); 6107 mWifiNative.p2pFlush(); 6108 6109 boolean peersChanged = false; 6110 // Remove only peers part of the group, so that other devices discovered 6111 // that have not timed out still remain in list for connection 6112 for (WifiP2pDevice d : mGroup.getClientList()) { 6113 if (mPeers.remove(d)) peersChanged = true; 6114 } 6115 if (mPeers.remove(mGroup.getOwner())) peersChanged = true; 6116 if (mPeers.remove(mPeersLostDuringConnection)) peersChanged = true; 6117 if (peersChanged) { 6118 sendPeersChangedBroadcast(); 6119 } 6120 6121 mGroup = null; 6122 mPeersLostDuringConnection.clear(); 6123 mServiceDiscReqId = null; 6124 6125 sendDisconnectWifiRequest(false); 6126 } 6127 sendDisconnectWifiRequest(boolean disableWifi)6128 private void sendDisconnectWifiRequest(boolean disableWifi) { 6129 if (null == mWifiChannel) { 6130 loge("WifiChannel is null, ignore DISCONNECT_WIFI_REQUEST " + disableWifi); 6131 return; 6132 } 6133 if (mTemporarilyDisconnectedWifi == disableWifi) return; 6134 6135 mWifiChannel.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST, 6136 disableWifi ? 1 : 0); 6137 mTemporarilyDisconnectedWifi = disableWifi; 6138 } 6139 replyToMessage(Message msg, int what)6140 private void replyToMessage(Message msg, int what) { 6141 // State machine initiated requests can have replyTo set to null 6142 // indicating there are no recipients, we ignore those reply actions 6143 if (msg.replyTo == null) return; 6144 Message dstMsg = obtainMessage(msg); 6145 dstMsg.what = what; 6146 mReplyChannel.replyToMessage(msg, dstMsg); 6147 } 6148 replyToMessage(Message msg, int what, int arg1)6149 private void replyToMessage(Message msg, int what, int arg1) { 6150 if (msg.replyTo == null) return; 6151 Message dstMsg = obtainMessage(msg); 6152 dstMsg.what = what; 6153 dstMsg.arg1 = arg1; 6154 mReplyChannel.replyToMessage(msg, dstMsg); 6155 } 6156 replyToMessage(Message msg, int what, Object obj)6157 private void replyToMessage(Message msg, int what, Object obj) { 6158 if (msg.replyTo == null) return; 6159 Message dstMsg = obtainMessage(msg); 6160 dstMsg.what = what; 6161 dstMsg.obj = obj; 6162 mReplyChannel.replyToMessage(msg, dstMsg); 6163 } 6164 replyToMessage(Message msg, int what, int arg1, Object obj)6165 private void replyToMessage(Message msg, int what, int arg1, Object obj) { 6166 if (msg.replyTo == null) return; 6167 Message dstMsg = obtainMessage(msg); 6168 dstMsg.what = what; 6169 dstMsg.arg1 = arg1; 6170 dstMsg.obj = obj; 6171 mReplyChannel.replyToMessage(msg, dstMsg); 6172 } 6173 obtainMessage(Message srcMsg)6174 private Message obtainMessage(Message srcMsg) { 6175 // arg2 on the source message has a hash code that needs to 6176 // be retained in replies see WifiP2pManager for details 6177 Message msg = Message.obtain(); 6178 msg.arg2 = srcMsg.arg2; 6179 return msg; 6180 } 6181 6182 @Override logd(String s)6183 protected void logd(String s) { 6184 Log.d(TAG, s); 6185 } 6186 6187 @Override loge(String s)6188 protected void loge(String s) { 6189 Log.e(TAG, s); 6190 } 6191 6192 /** 6193 * Update service discovery request to wpa_supplicant. 6194 */ updateSupplicantServiceRequest()6195 private boolean updateSupplicantServiceRequest() { 6196 clearSupplicantServiceRequest(); 6197 StringBuffer sb = new StringBuffer(); 6198 for (ClientInfo c: mClientInfoList.values()) { 6199 WifiP2pServiceRequest req; 6200 for (int i = 0; i < c.mReqList.size(); i++) { 6201 req = c.mReqList.valueAt(i); 6202 if (req != null) { 6203 sb.append(req.getSupplicantQuery()); 6204 } 6205 } 6206 } 6207 if (sb.length() == 0) { 6208 return false; 6209 } 6210 6211 mServiceDiscReqId = mWifiNative.p2pServDiscReq("00:00:00:00:00:00", sb.toString()); 6212 return mServiceDiscReqId != null; 6213 } 6214 6215 /** 6216 * Clear service discovery request in wpa_supplicant 6217 */ clearSupplicantServiceRequest()6218 private void clearSupplicantServiceRequest() { 6219 if (mServiceDiscReqId == null) return; 6220 6221 mWifiNative.p2pServDiscCancelReq(mServiceDiscReqId); 6222 mServiceDiscReqId = null; 6223 } 6224 addServiceRequest(Messenger m, WifiP2pServiceRequest req)6225 private boolean addServiceRequest(Messenger m, WifiP2pServiceRequest req) { 6226 if (m == null || req == null) { 6227 Log.e(TAG, "Illegal argument(s)"); 6228 return false; 6229 } 6230 // TODO: We could track individual service adds separately and avoid 6231 // having to do update all service requests on every new request 6232 clearClientDeadChannels(); 6233 6234 ClientInfo clientInfo = getClientInfo(m, false); 6235 if (clientInfo == null) { 6236 return false; 6237 } 6238 6239 ++mServiceTransactionId; 6240 // The Wi-Fi p2p spec says transaction id should be 1 byte and non-zero. 6241 if (mServiceTransactionId == 256) mServiceTransactionId = 1; 6242 req.setTransactionId((mServiceTransactionId)); 6243 clientInfo.mReqList.put(mServiceTransactionId, req); 6244 if (mServiceDiscReqId == null) { 6245 return true; 6246 } 6247 return updateSupplicantServiceRequest(); 6248 } 6249 removeServiceRequest(Messenger m, WifiP2pServiceRequest req)6250 private void removeServiceRequest(Messenger m, WifiP2pServiceRequest req) { 6251 if (m == null || req == null) { 6252 Log.e(TAG, "Illegal argument(s)"); 6253 } 6254 6255 ClientInfo clientInfo = getClientInfo(m, false); 6256 if (clientInfo == null) { 6257 return; 6258 } 6259 6260 // Application does not have transaction id information 6261 // go through stored requests to remove 6262 boolean removed = false; 6263 for (int i = 0; i < clientInfo.mReqList.size(); i++) { 6264 if (req.equals(clientInfo.mReqList.valueAt(i))) { 6265 removed = true; 6266 clientInfo.mReqList.removeAt(i); 6267 break; 6268 } 6269 } 6270 6271 if (!removed) return; 6272 6273 if (mServiceDiscReqId == null) { 6274 return; 6275 } 6276 6277 updateSupplicantServiceRequest(); 6278 } 6279 clearServiceRequests(Messenger m)6280 private void clearServiceRequests(Messenger m) { 6281 if (m == null) { 6282 Log.e(TAG, "Illegal argument(s)"); 6283 return; 6284 } 6285 6286 ClientInfo clientInfo = getClientInfo(m, false); 6287 if (clientInfo == null) { 6288 return; 6289 } 6290 6291 if (clientInfo.mReqList.size() == 0) { 6292 return; 6293 } 6294 6295 clientInfo.mReqList.clear(); 6296 6297 if (mServiceDiscReqId == null) { 6298 return; 6299 } 6300 6301 updateSupplicantServiceRequest(); 6302 } 6303 addLocalService(Messenger m, WifiP2pServiceInfo servInfo)6304 private boolean addLocalService(Messenger m, WifiP2pServiceInfo servInfo) { 6305 if (m == null || servInfo == null) { 6306 Log.e(TAG, "Illegal arguments"); 6307 return false; 6308 } 6309 6310 clearClientDeadChannels(); 6311 6312 ClientInfo clientInfo = getClientInfo(m, false); 6313 6314 if (clientInfo == null) { 6315 return false; 6316 } 6317 6318 if (!clientInfo.mServList.add(servInfo)) { 6319 return false; 6320 } 6321 6322 if (!mWifiNative.p2pServiceAdd(servInfo)) { 6323 clientInfo.mServList.remove(servInfo); 6324 return false; 6325 } 6326 6327 return true; 6328 } 6329 removeLocalService(Messenger m, WifiP2pServiceInfo servInfo)6330 private void removeLocalService(Messenger m, WifiP2pServiceInfo servInfo) { 6331 if (m == null || servInfo == null) { 6332 Log.e(TAG, "Illegal arguments"); 6333 return; 6334 } 6335 6336 ClientInfo clientInfo = getClientInfo(m, false); 6337 if (clientInfo == null) { 6338 return; 6339 } 6340 6341 mWifiNative.p2pServiceDel(servInfo); 6342 clientInfo.mServList.remove(servInfo); 6343 } 6344 clearLocalServices(Messenger m)6345 private void clearLocalServices(Messenger m) { 6346 if (m == null) { 6347 Log.e(TAG, "Illegal argument(s)"); 6348 return; 6349 } 6350 6351 ClientInfo clientInfo = getClientInfo(m, false); 6352 if (clientInfo == null) { 6353 return; 6354 } 6355 6356 for (WifiP2pServiceInfo servInfo: clientInfo.mServList) { 6357 mWifiNative.p2pServiceDel(servInfo); 6358 } 6359 6360 clientInfo.mServList.clear(); 6361 } 6362 clearClientInfo(Messenger m)6363 private void clearClientInfo(Messenger m) { 6364 // update wpa_supplicant service info 6365 clearLocalServices(m); 6366 clearServiceRequests(m); 6367 // remove client from client list 6368 ClientInfo clientInfo = mClientInfoList.remove(m); 6369 if (clientInfo != null) { 6370 logd("Client:" + clientInfo.mPackageName + " is removed"); 6371 } 6372 } 6373 6374 /** 6375 * Send the service response to the WifiP2pManager.Channel. 6376 * @param WifiP2pServiceResponse response to service discovery 6377 */ sendServiceResponse(WifiP2pServiceResponse resp)6378 private void sendServiceResponse(WifiP2pServiceResponse resp) { 6379 if (resp == null) { 6380 Log.e(TAG, "sendServiceResponse with null response"); 6381 return; 6382 } 6383 for (ClientInfo c : mClientInfoList.values()) { 6384 WifiP2pServiceRequest req = c.mReqList.get(resp.getTransactionId()); 6385 if (req != null) { 6386 Message msg = Message.obtain(); 6387 msg.what = WifiP2pManager.RESPONSE_SERVICE; 6388 msg.arg1 = 0; 6389 msg.arg2 = 0; 6390 msg.obj = resp; 6391 if (c.mMessenger == null) { 6392 continue; 6393 } 6394 try { 6395 c.mMessenger.send(msg); 6396 } catch (RemoteException e) { 6397 if (mVerboseLoggingEnabled) logd("detect dead channel"); 6398 clearClientInfo(c.mMessenger); 6399 return; 6400 } 6401 } 6402 } 6403 } 6404 6405 /** 6406 * We don't get notifications of clients that have gone away. 6407 * We detect this actively when services are added and throw 6408 * them away. 6409 * 6410 * TODO: This can be done better with full async channels. 6411 */ clearClientDeadChannels()6412 private void clearClientDeadChannels() { 6413 ArrayList<Messenger> deadClients = new ArrayList<Messenger>(); 6414 6415 for (ClientInfo c : mClientInfoList.values()) { 6416 Message msg = Message.obtain(); 6417 msg.what = WifiP2pManager.PING; 6418 msg.arg1 = 0; 6419 msg.arg2 = 0; 6420 msg.obj = null; 6421 if (c.mMessenger == null) { 6422 continue; 6423 } 6424 try { 6425 c.mMessenger.send(msg); 6426 } catch (RemoteException e) { 6427 if (mVerboseLoggingEnabled) logd("detect dead channel"); 6428 deadClients.add(c.mMessenger); 6429 } 6430 } 6431 6432 for (Messenger m : deadClients) { 6433 clearClientInfo(m); 6434 } 6435 } 6436 6437 /** 6438 * Return the specified ClientInfo. 6439 * @param m Messenger 6440 * @param createIfNotExist if true and the specified channel info does not exist, 6441 * create new client info. 6442 * @return the specified ClientInfo. 6443 */ getClientInfo(Messenger m, boolean createIfNotExist)6444 private ClientInfo getClientInfo(Messenger m, boolean createIfNotExist) { 6445 ClientInfo clientInfo = mClientInfoList.get(m); 6446 if (clientInfo == null && createIfNotExist) { 6447 if (mVerboseLoggingEnabled) logd("add a new client"); 6448 clientInfo = new ClientInfo(m); 6449 mClientInfoList.put(m, clientInfo); 6450 } 6451 6452 return clientInfo; 6453 } 6454 6455 /** 6456 * Enforces permissions on the caller who is requesting for P2p Peers 6457 * @param pkgName Package name of the caller 6458 * @param featureId Feature in the package of the caller 6459 * @param uid of the caller 6460 * @return WifiP2pDeviceList the peer list 6461 */ getPeers(String pkgName, @Nullable String featureId, int uid, Bundle extras, Object attributionSource)6462 private WifiP2pDeviceList getPeers(String pkgName, @Nullable String featureId, int uid, 6463 Bundle extras, Object attributionSource) { 6464 // getPeers() is guaranteed to be invoked after Wifi Service is up 6465 // This ensures getInstance() will return a non-null object now 6466 boolean hasPermission = false; 6467 if (isPlatformOrTargetSdkLessThanT(pkgName, uid)) { 6468 hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( 6469 pkgName, featureId, uid, true); 6470 } else { 6471 hasPermission = checkNearbyDevicesPermission(uid, pkgName, 6472 extras, "getPeers", attributionSource); 6473 } 6474 if (hasPermission) { 6475 return new WifiP2pDeviceList(mPeers); 6476 } else { 6477 return new WifiP2pDeviceList(); 6478 } 6479 } 6480 setPendingFactoryReset(boolean pending)6481 private void setPendingFactoryReset(boolean pending) { 6482 mSettingsConfigStore.put(WIFI_P2P_PENDING_FACTORY_RESET, pending); 6483 } 6484 isPendingFactoryReset()6485 private boolean isPendingFactoryReset() { 6486 return mSettingsConfigStore.get(WIFI_P2P_PENDING_FACTORY_RESET); 6487 } 6488 6489 /** 6490 * Enforces permissions on the caller who is requesting factory reset. 6491 * @param pkg Bundle containing the calling package string. 6492 * @param uid The caller uid. 6493 */ factoryReset(int uid)6494 private boolean factoryReset(int uid) { 6495 String pkgName = mContext.getPackageManager().getNameForUid(uid); 6496 6497 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) return false; 6498 6499 if (mUserManager.hasUserRestrictionForUser( 6500 UserManager.DISALLOW_NETWORK_RESET, UserHandle.getUserHandleForUid(uid)) 6501 || mUserManager.hasUserRestrictionForUser( 6502 UserManager.DISALLOW_CONFIG_WIFI, UserHandle.getUserHandleForUid(uid))) { 6503 return false; 6504 } 6505 6506 Log.i(TAG, "factoryReset uid=" + uid + " pkg=" + pkgName); 6507 6508 if (mInterfaceName != null) { 6509 if (mWifiNative.p2pListNetworks(mGroups)) { 6510 for (WifiP2pGroup group : mGroups.getGroupList()) { 6511 mWifiNative.removeP2pNetwork(group.getNetworkId()); 6512 } 6513 } 6514 // reload will save native config and broadcast changed event. 6515 updatePersistentNetworks(true); 6516 setPendingFactoryReset(false); 6517 Log.i(TAG, "factoryReset: de-init P2P interface."); 6518 sendMessage(DISABLE_P2P); 6519 } else { 6520 setPendingFactoryReset(true); 6521 } 6522 return true; 6523 } 6524 updateVendorElements( String packageName, ArrayList<ScanResult.InformationElement> vendorElements)6525 private boolean updateVendorElements( 6526 String packageName, ArrayList<ScanResult.InformationElement> vendorElements) { 6527 if (TextUtils.isEmpty(packageName)) return false; 6528 if (null == vendorElements || 0 == vendorElements.size()) { 6529 if (mVerboseLoggingEnabled) logd("Clear vendor elements for " + packageName); 6530 mVendorElements.remove(packageName); 6531 } else { 6532 if (mVerboseLoggingEnabled) logd("Update vendor elements for " + packageName); 6533 6534 if (vendorElements.stream() 6535 .anyMatch(ie -> ie.id != ScanResult.InformationElement.EID_VSA)) { 6536 loge("received InformationElement which is not a Vendor Specific IE (VSIE)." 6537 + "VSIEs have an ID = 221."); 6538 return false; 6539 } 6540 6541 mVendorElements.put(packageName, new HashSet<>(vendorElements)); 6542 6543 Set<ScanResult.InformationElement> aggregatedVendorElements = new HashSet<>(); 6544 mVendorElements.forEach((k, v) -> aggregatedVendorElements.addAll(v)); 6545 // The total bytes of an IE is EID (1 byte) + length (1 byte) + payload length. 6546 int totalBytes = aggregatedVendorElements.stream() 6547 .mapToInt(ie -> (2 + ie.bytes.length)).sum(); 6548 if (totalBytes > WifiP2pManager.getP2pMaxAllowedVendorElementsLengthBytes()) { 6549 mVendorElements.forEach((k, v) -> { 6550 Log.w(TAG, "package=" + k + " VSIE size=" 6551 + v.stream().mapToInt(ie -> ie.bytes.length).sum()); 6552 }); 6553 mVendorElements.remove(packageName); 6554 return false; 6555 } 6556 } 6557 return true; 6558 } 6559 p2pFind(int timeout)6560 private boolean p2pFind(int timeout) { 6561 return p2pFind( 6562 WifiP2pManager.WIFI_P2P_SCAN_FULL, 6563 WifiP2pManager.WIFI_P2P_SCAN_FREQ_UNSPECIFIED, timeout); 6564 } 6565 p2pFind(@ifiP2pManager.WifiP2pScanType int scanType, int freq, int timeout)6566 private boolean p2pFind(@WifiP2pManager.WifiP2pScanType int scanType, int freq, 6567 int timeout) { 6568 if (isFeatureSupported(WifiP2pManager.FEATURE_SET_VENDOR_ELEMENTS)) { 6569 Set<ScanResult.InformationElement> aggregatedVendorElements = new HashSet<>(); 6570 mVendorElements.forEach((k, v) -> aggregatedVendorElements.addAll(v)); 6571 if (!mWifiNative.setVendorElements(aggregatedVendorElements)) { 6572 Log.w(TAG, "cannot set vendor elements to the native service."); 6573 // Don't block p2p find or it might affect regular P2P functinalities. 6574 mWifiNative.removeVendorElements(); 6575 } 6576 } 6577 if (scanType == WifiP2pManager.WIFI_P2P_SCAN_FULL) { 6578 return mWifiNative.p2pFind(timeout); 6579 } else if (scanType == WifiP2pManager.WIFI_P2P_SCAN_SOCIAL 6580 && freq == WifiP2pManager.WIFI_P2P_SCAN_FREQ_UNSPECIFIED) { 6581 return mWifiNative.p2pFind(scanType, freq, timeout); 6582 } else if (scanType == WifiP2pManager.WIFI_P2P_SCAN_SINGLE_FREQ 6583 && freq != WifiP2pManager.WIFI_P2P_SCAN_FREQ_UNSPECIFIED) { 6584 return mWifiNative.p2pFind(scanType, freq, timeout); 6585 } 6586 return false; 6587 } 6588 p2pReconnect()6589 void p2pReconnect() { 6590 Bundle extras = new Bundle(); 6591 extras.putParcelable(WifiP2pManager.EXTRA_PARAM_KEY_CONFIG, 6592 mSavedPeerConfig); 6593 extras.putBoolean( 6594 WifiP2pManager.EXTRA_PARAM_KEY_INTERNAL_MESSAGE, true); 6595 final Message msg = obtainMessage(WifiP2pManager.CONNECT); 6596 msg.getData().putBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE, extras); 6597 msg.sendingUid = Process.myUid(); 6598 sendMessage(msg); 6599 } 6600 6601 /** 6602 * Get calling package string from Client HashMap 6603 * 6604 * @param uid The uid of the caller package 6605 * @param replyMessenger AsyncChannel handler in caller 6606 */ getCallingPkgName(int uid, Messenger replyMessenger)6607 private String getCallingPkgName(int uid, Messenger replyMessenger) { 6608 ClientInfo clientInfo = mClientInfoList.get(replyMessenger); 6609 if (clientInfo != null) { 6610 return clientInfo.mPackageName; 6611 } 6612 if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) return mContext.getOpPackageName(); 6613 return null; 6614 } 6615 6616 /** 6617 * Get calling feature id from Client HashMap 6618 * 6619 * @param uid The uid of the caller 6620 * @param replyMessenger AsyncChannel handler in caller 6621 */ getCallingFeatureId(int uid, Messenger replyMessenger)6622 private String getCallingFeatureId(int uid, Messenger replyMessenger) { 6623 ClientInfo clientInfo = mClientInfoList.get(replyMessenger); 6624 if (clientInfo != null) { 6625 return clientInfo.mFeatureId; 6626 } 6627 if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) return mContext.getAttributionTag(); 6628 return null; 6629 } 6630 6631 /** 6632 * Clear all of p2p local service request/response for all p2p clients 6633 */ clearServicesForAllClients()6634 private void clearServicesForAllClients() { 6635 for (ClientInfo c : mClientInfoList.values()) { 6636 clearLocalServices(c.mMessenger); 6637 clearServiceRequests(c.mMessenger); 6638 } 6639 } 6640 selectGroupOwnerIntentIfNecessary(WifiP2pConfig config)6641 private int selectGroupOwnerIntentIfNecessary(WifiP2pConfig config) { 6642 int intent = config.groupOwnerIntent; 6643 // return the legacy default value for invalid values. 6644 if (intent != WifiP2pConfig.GROUP_OWNER_INTENT_AUTO) { 6645 if (intent < WifiP2pConfig.GROUP_OWNER_INTENT_MIN 6646 || intent > WifiP2pConfig.GROUP_OWNER_INTENT_MAX) { 6647 intent = DEFAULT_GROUP_OWNER_INTENT; 6648 } 6649 return intent; 6650 } 6651 6652 WifiManager wifiManager = mContext.getSystemService(WifiManager.class); 6653 6654 WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 6655 Log.d(TAG, "WifiInfo: " + wifiInfo); 6656 int freq = wifiInfo.getFrequency(); 6657 /* 6658 * GO intent table 6659 * STA Freq 2.4GHz/5GHz DBS 5GHz/6GHz DBS GO intent 6660 * N/A X X 6 (default) 6661 * 2.4 GHz X X 7 6662 * 5 GHz X No 8 6663 * 5 GHz X Yes 9 6664 * 6 GHz X No 11 6665 * 6 Ghz X Yes 12 6666 */ 6667 if (wifiInfo.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID) { 6668 intent = DEFAULT_GROUP_OWNER_INTENT; 6669 } else if (ScanResult.is24GHz(freq)) { 6670 intent = 7; 6671 } else if (ScanResult.is5GHz(freq)) { 6672 if (mWifiNative.is5g6gDbsSupported()) { 6673 intent = 9; 6674 } else { 6675 intent = 8; 6676 } 6677 } else if (ScanResult.is6GHz(freq)) { 6678 if (mWifiNative.is5g6gDbsSupported()) { 6679 intent = 12; 6680 } else { 6681 intent = 11; 6682 } 6683 } else { 6684 intent = DEFAULT_GROUP_OWNER_INTENT; 6685 } 6686 Log.i(TAG, "change GO intent value from " 6687 + config.groupOwnerIntent + " to " + intent); 6688 return intent; 6689 } 6690 updateP2pChannels()6691 private boolean updateP2pChannels() { 6692 Log.d(TAG, "Set P2P listen channel to " + mUserListenChannel); 6693 if (!mWifiNative.p2pSetListenChannel(mUserListenChannel)) { 6694 Log.e(TAG, "Cannot set listen channel."); 6695 return false; 6696 } 6697 6698 Log.d(TAG, "Set P2P operating channel to " + mUserOperatingChannel 6699 + ", unsafe channels: " 6700 + mCoexUnsafeChannels.stream() 6701 .map(Object::toString).collect(Collectors.joining(","))); 6702 if (!mWifiNative.p2pSetOperatingChannel(mUserOperatingChannel, mCoexUnsafeChannels)) { 6703 Log.e(TAG, "Cannot set operate channel."); 6704 return false; 6705 } 6706 return true; 6707 } 6708 checkExternalApproverCaller(Message message, IBinder binder, MacAddress devAddr, String cmd)6709 private boolean checkExternalApproverCaller(Message message, 6710 IBinder binder, MacAddress devAddr, String cmd) { 6711 Bundle extras = message.getData() 6712 .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 6713 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission( 6714 message.sendingUid)) { 6715 loge("Permission violation - no MANAGE_WIFI_NETWORK_SELECTION," 6716 + " permission, uid = " + message.sendingUid); 6717 return false; 6718 } 6719 if (!checkNearbyDevicesPermission(message, cmd)) { 6720 loge("Permission violation - no NEARBY_WIFI_DEVICES permission" 6721 + ", uid = " + message.sendingUid); 6722 return false; 6723 } 6724 if (null == binder) { 6725 loge("No valid binder for this approver."); 6726 return false; 6727 } 6728 if (null == devAddr) { 6729 loge("No device address for this approver."); 6730 return false; 6731 } 6732 return true; 6733 } 6734 detachExternalApproverFromClient(IBinder binder)6735 private void detachExternalApproverFromClient(IBinder binder) { 6736 if (null == binder) return; 6737 6738 logd("Detach approvers for " + binder); 6739 List<ApproverEntry> entries = mExternalApproverManager.get(binder); 6740 entries.forEach(e -> { 6741 logd("Detach the approver " + e); 6742 replyToMessage( 6743 e.getMessage(), WifiP2pManager.EXTERNAL_APPROVER_DETACH, 6744 ExternalApproverRequestListener.APPROVER_DETACH_REASON_CLOSE, 6745 e.getAddress()); 6746 }); 6747 mExternalApproverManager.removeAll(binder); 6748 } 6749 detachExternalApproverFromPeer()6750 private void detachExternalApproverFromPeer() { 6751 if (TextUtils.isEmpty(mSavedPeerConfig.deviceAddress)) return; 6752 6753 ApproverEntry entry = mExternalApproverManager.remove( 6754 MacAddress.fromString(mSavedPeerConfig.deviceAddress)); 6755 if (null == entry) { 6756 logd("No approver found for " + mSavedPeerConfig.deviceAddress 6757 + " check the wildcard address approver."); 6758 entry = mExternalApproverManager.remove(MacAddress.BROADCAST_ADDRESS); 6759 } 6760 if (null == entry) return; 6761 6762 logd("Detach the approver " + entry); 6763 replyToMessage(entry.getMessage(), WifiP2pManager.EXTERNAL_APPROVER_DETACH, 6764 ExternalApproverRequestListener.APPROVER_DETACH_REASON_REMOVE, 6765 entry.getAddress()); 6766 } 6767 handleSetConnectionResultCommon(@onNull Message message)6768 private boolean handleSetConnectionResultCommon(@NonNull Message message) { 6769 Bundle extras = message.getData().getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 6770 MacAddress devAddr = extras.getParcelable( 6771 WifiP2pManager.EXTRA_PARAM_KEY_PEER_ADDRESS); 6772 IBinder binder = extras.getBinder(WifiP2pManager.CALLING_BINDER); 6773 if (!checkExternalApproverCaller(message, binder, devAddr, 6774 "SET_CONNECTION_REQUEST_RESULT")) { 6775 return false; 6776 } 6777 6778 if (!devAddr.equals(MacAddress.fromString(mSavedPeerConfig.deviceAddress))) { 6779 logd("Saved peer address is different from " + devAddr); 6780 return false; 6781 } 6782 6783 ApproverEntry entry = mExternalApproverManager.get(binder, devAddr); 6784 if (null == entry) { 6785 logd("No approver found for " + devAddr 6786 + " check the wildcard address approver."); 6787 entry = mExternalApproverManager.get(binder, MacAddress.BROADCAST_ADDRESS); 6788 } 6789 if (null == entry) return false; 6790 if (!entry.getKey().equals(binder)) { 6791 loge("Ignore connection result from a client" 6792 + " which is different from the existing approver."); 6793 return false; 6794 } 6795 return true; 6796 } 6797 handleSetConnectionResult(@onNull Message message, @WifiP2pManager.ExternalApproverRequestListener.RequestType int requestType)6798 private boolean handleSetConnectionResult(@NonNull Message message, 6799 @WifiP2pManager.ExternalApproverRequestListener.RequestType int requestType) { 6800 if (!handleSetConnectionResultCommon(message)) return false; 6801 6802 logd("handle connection result from the approver, result= " + message.arg1); 6803 // For deferring result, the approver should be removed first to avoid notifying 6804 // the application again. 6805 if (WifiP2pManager.CONNECTION_REQUEST_DEFER_TO_SERVICE == message.arg1) { 6806 detachExternalApproverFromPeer(); 6807 notifyInvitationReceived(requestType); 6808 return true; 6809 } else if (WifiP2pManager.CONNECTION_REQUEST_DEFER_SHOW_PIN_TO_SERVICE 6810 == message.arg1 6811 && WifiP2pManager.ExternalApproverRequestListener.REQUEST_TYPE_NEGOTIATION 6812 == requestType 6813 && WpsInfo.KEYPAD == mSavedPeerConfig.wps.setup) { 6814 detachExternalApproverFromPeer(); 6815 notifyP2pProvDiscShowPinRequest(mSavedPeerConfig.wps.pin, 6816 mSavedPeerConfig.deviceAddress); 6817 return true; 6818 } 6819 6820 if (WifiP2pManager.CONNECTION_REQUEST_ACCEPT == message.arg1) { 6821 if (WifiP2pManager.ExternalApproverRequestListener.REQUEST_TYPE_NEGOTIATION 6822 == requestType 6823 && WpsInfo.KEYPAD == mSavedPeerConfig.wps.setup) { 6824 sendMessage(PEER_CONNECTION_USER_CONFIRM); 6825 } else { 6826 Bundle extras = message.getData().getBundle( 6827 WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); 6828 String pin = extras.getString( 6829 WifiP2pManager.EXTRA_PARAM_KEY_WPS_PIN); 6830 if (!TextUtils.isEmpty(pin)) { 6831 mSavedPeerConfig.wps.pin = pin; 6832 } 6833 sendMessage(PEER_CONNECTION_USER_ACCEPT); 6834 } 6835 } else if (WifiP2pManager.CONNECTION_REQUEST_REJECT == message.arg1) { 6836 sendMessage(PEER_CONNECTION_USER_REJECT); 6837 } else { 6838 Log.w(TAG, "Invalid connection result: " + message.arg1 6839 + ", config: " + mSavedPeerConfig); 6840 return false; 6841 } 6842 detachExternalApproverFromPeer(); 6843 return true; 6844 } 6845 handleSetConnectionResultForInvitationSent(@onNull Message message)6846 private boolean handleSetConnectionResultForInvitationSent(@NonNull Message message) { 6847 if (!handleSetConnectionResultCommon(message)) return false; 6848 6849 logd("handle connection result for pin from the approver, result= " + message.arg1); 6850 // For deferring result, the approver should be removed first to avoid notifying 6851 // the application again. 6852 if (WifiP2pManager.CONNECTION_REQUEST_DEFER_SHOW_PIN_TO_SERVICE == message.arg1) { 6853 detachExternalApproverFromPeer(); 6854 notifyInvitationSent(mSavedPeerConfig.wps.pin, 6855 mSavedPeerConfig.deviceAddress); 6856 return true; 6857 } 6858 Log.w(TAG, "Invalid connection result: " + message.arg1); 6859 return false; 6860 } 6861 isFeatureSupported(long feature)6862 private boolean isFeatureSupported(long feature) { 6863 return (getSupportedFeatures() & feature) == feature; 6864 } 6865 sendP2pRejection()6866 private void sendP2pRejection() { 6867 if (TextUtils.isEmpty(mSavedPeerConfig.deviceAddress)) return; 6868 6869 mWifiNative.p2pReject(mSavedPeerConfig.deviceAddress); 6870 // p2pReject() only updates the peer state, but not sends this 6871 // to the peer, trigger provision discovery to notify the peer. 6872 mWifiNative.p2pProvisionDiscovery(mSavedPeerConfig); 6873 } 6874 isPeerAuthorizing(String deviceAddress)6875 private boolean isPeerAuthorizing(String deviceAddress) { 6876 Long timestamp = mPeerAuthorizingTimestamp.get(deviceAddress); 6877 if (null == timestamp) return false; 6878 6879 int timeoutMs = mContext.getResources().getInteger( 6880 R.integer.config_wifiP2pJoinRequestAuthorizingTimeoutMs); 6881 if (mClock.getElapsedSinceBootMillis() > timestamp + timeoutMs) { 6882 return false; 6883 } 6884 6885 return true; 6886 } 6887 } 6888 6889 /** 6890 * Information about a particular client and we track the service discovery requests 6891 * and the local services registered by the client. 6892 */ 6893 private static class ClientInfo { 6894 6895 // A reference to WifiP2pManager.Channel handler. 6896 // The response of this request is notified to WifiP2pManager.Channel handler 6897 private final Messenger mMessenger; 6898 private String mPackageName; 6899 @Nullable private String mFeatureId; 6900 6901 // A service discovery request list. 6902 private final SparseArray<WifiP2pServiceRequest> mReqList = new SparseArray<>(); 6903 6904 // A local service information list. 6905 private final List<WifiP2pServiceInfo> mServList = new ArrayList<>(); 6906 ClientInfo(Messenger m)6907 private ClientInfo(Messenger m) { 6908 mMessenger = m; 6909 mPackageName = null; 6910 mFeatureId = null; 6911 } 6912 } 6913 6914 /** 6915 * Check that the UID has one of the following permissions: 6916 * {@link android.Manifest.permission.NETWORK_SETTINGS} 6917 * {@link android.Manifest.permission.NETWORK_STACK} 6918 * {@link android.Manifest.permission.OVERRIDE_WIFI_CONFIG} 6919 * 6920 * @param uid the UID to check 6921 * @return whether the UID has any of the above permissions 6922 */ checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission(int uid)6923 private boolean checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission(int uid) { 6924 return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 6925 || mWifiPermissionsUtil.checkNetworkStackPermission(uid) 6926 || mWifiPermissionsUtil.checkConfigOverridePermission(uid); 6927 } 6928 6929 /** 6930 * Check that the UID has one of the following permissions: 6931 * {@link android.Manifest.permission.NETWORK_SETTINGS} 6932 * {@link android.Manifest.permission.NETWORK_STACK} 6933 * {@link android.Manifest.permission.READ_WIFI_CREDENTIAL} 6934 * 6935 * @param uid the UID to check 6936 * @return whether the UID has any of the above permissions 6937 */ checkNetworkSettingsOrNetworkStackOrReadWifiCredentialPermission(int uid)6938 private boolean checkNetworkSettingsOrNetworkStackOrReadWifiCredentialPermission(int uid) { 6939 return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 6940 || mWifiPermissionsUtil.checkNetworkStackPermission(uid) 6941 || mWifiPermissionsUtil.checkReadWifiCredentialPermission(uid); 6942 } 6943 } 6944