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