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