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