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