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