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