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