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