1 /*
2  * Copyright (C) 2008 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 android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.net.wifi.p2p.WifiP2pConfig;
22 import android.net.wifi.p2p.WifiP2pDevice;
23 import android.net.wifi.p2p.WifiP2pGroup;
24 import android.net.wifi.p2p.WifiP2pProvDiscEvent;
25 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
26 import android.os.Handler;
27 import android.os.Message;
28 import android.util.ArraySet;
29 import android.util.Log;
30 import android.util.SparseArray;
31 
32 import com.android.internal.annotations.VisibleForTesting;
33 import com.android.internal.util.Protocol;
34 import com.android.server.wifi.p2p.WifiP2pServiceImpl.P2pStatus;
35 
36 import java.lang.annotation.Retention;
37 import java.lang.annotation.RetentionPolicy;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Set;
42 
43 /**
44  * Listens for events from the wpa_supplicant, and passes them on
45  * to the {@link WifiP2pServiceImpl} for handling.
46  */
47 public class WifiP2pMonitor {
48     private static final String TAG = "WifiP2pMonitor";
49 
50     /* Supplicant events reported to a state machine */
51     private static final int BASE = Protocol.BASE_WIFI_MONITOR;
52 
53     /* Connection to supplicant established */
54     public static final int SUP_CONNECTION_EVENT                 = BASE + 1;
55     /* Connection to supplicant lost */
56     public static final int SUP_DISCONNECTION_EVENT              = BASE + 2;
57 
58     /* P2P events */
59     public static final int P2P_DEVICE_FOUND_EVENT               = BASE + 21;
60     public static final int P2P_DEVICE_LOST_EVENT                = BASE + 22;
61     public static final int P2P_GO_NEGOTIATION_REQUEST_EVENT     = BASE + 23;
62     public static final int P2P_GO_NEGOTIATION_SUCCESS_EVENT     = BASE + 25;
63     public static final int P2P_GO_NEGOTIATION_FAILURE_EVENT     = BASE + 26;
64     public static final int P2P_GROUP_FORMATION_SUCCESS_EVENT    = BASE + 27;
65     public static final int P2P_GROUP_FORMATION_FAILURE_EVENT    = BASE + 28;
66     public static final int P2P_GROUP_STARTED_EVENT              = BASE + 29;
67     public static final int P2P_GROUP_REMOVED_EVENT              = BASE + 30;
68     public static final int P2P_INVITATION_RECEIVED_EVENT        = BASE + 31;
69     public static final int P2P_INVITATION_RESULT_EVENT          = BASE + 32;
70     public static final int P2P_PROV_DISC_PBC_REQ_EVENT          = BASE + 33;
71     public static final int P2P_PROV_DISC_PBC_RSP_EVENT          = BASE + 34;
72     public static final int P2P_PROV_DISC_ENTER_PIN_EVENT        = BASE + 35;
73     public static final int P2P_PROV_DISC_SHOW_PIN_EVENT         = BASE + 36;
74     public static final int P2P_FIND_STOPPED_EVENT               = BASE + 37;
75     public static final int P2P_SERV_DISC_RESP_EVENT             = BASE + 38;
76     public static final int P2P_PROV_DISC_FAILURE_EVENT          = BASE + 39;
77     public static final int P2P_FREQUENCY_CHANGED_EVENT          = BASE + 40;
78 
79     /* hostap events */
80     public static final int AP_STA_DISCONNECTED_EVENT            = BASE + 41;
81     public static final int AP_STA_CONNECTED_EVENT               = BASE + 42;
82 
83     public static final int PROV_DISC_STATUS_SUCCESS             = 0;
84     public static final int PROV_DISC_STATUS_TIMEOUT             = 1;
85     public static final int PROV_DISC_STATUS_REJECTED            = 2;
86     public static final int PROV_DISC_STATUS_TIMEOUT_JOIN        = 3;
87     public static final int PROV_DISC_STATUS_INFO_UNAVAILABLE    = 4;
88     public static final int PROV_DISC_STATUS_UNKNOWN             = 5;
89     @IntDef(prefix = {"PROV_DISC_STATUS_"}, value = {
90             PROV_DISC_STATUS_SUCCESS,
91             PROV_DISC_STATUS_TIMEOUT,
92             PROV_DISC_STATUS_REJECTED,
93             PROV_DISC_STATUS_TIMEOUT_JOIN,
94             PROV_DISC_STATUS_INFO_UNAVAILABLE,
95             PROV_DISC_STATUS_UNKNOWN})
96     @Retention(RetentionPolicy.SOURCE)
97     public @interface P2pProvDiscStatus {
98     }
99 
100     private boolean mVerboseLoggingEnabled = false;
101 
102     /**
103      * Enable verbose logging for all sub modules.
104      */
enableVerboseLogging(boolean verboseEnabled)105     public void enableVerboseLogging(boolean verboseEnabled) {
106         mVerboseLoggingEnabled = verboseEnabled;
107     }
108 
109     private final Map<String, SparseArray<Set<Handler>>> mHandlerMap = new HashMap<>();
110 
111     /**
112      * Registers a callback handler for the provided event.
113      */
registerHandler(String iface, int what, Handler handler)114     public synchronized void registerHandler(String iface, int what, Handler handler) {
115         SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface);
116         if (ifaceHandlers == null) {
117             ifaceHandlers = new SparseArray<>();
118             mHandlerMap.put(iface, ifaceHandlers);
119         }
120         Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(what);
121         if (ifaceWhatHandlers == null) {
122             ifaceWhatHandlers = new ArraySet<>();
123             ifaceHandlers.put(what, ifaceWhatHandlers);
124         }
125         ifaceWhatHandlers.add(handler);
126     }
127 
128     private final Map<String, Boolean> mMonitoringMap = new HashMap<>();
isMonitoring(String iface)129     private boolean isMonitoring(String iface) {
130         Boolean val = mMonitoringMap.get(iface);
131         if (val == null) {
132             return false;
133         } else {
134             return val.booleanValue();
135         }
136     }
137 
138     /**
139      * Enable/Disable monitoring for the provided iface.
140      *
141      * @param iface Name of the iface.
142      * @param enabled true to enable, false to disable.
143      */
144     @VisibleForTesting
setMonitoring(String iface, boolean enabled)145     public void setMonitoring(String iface, boolean enabled) {
146         mMonitoringMap.put(iface, enabled);
147     }
148 
149     /**
150      * Start Monitoring for wpa_supplicant events.
151      *
152      * @param iface Name of iface.
153      * TODO: Add unit tests for these once we remove the legacy code.
154      */
startMonitoring(String iface)155     public synchronized void startMonitoring(String iface) {
156         setMonitoring(iface, true);
157         broadcastSupplicantConnectionEvent(iface);
158     }
159 
160     /**
161      * Stop Monitoring for wpa_supplicant events.
162      *
163      * @param iface Name of iface.
164      * TODO: Add unit tests for these once we remove the legacy code.
165      */
stopMonitoring(String iface)166     public synchronized void stopMonitoring(String iface) {
167         if (mVerboseLoggingEnabled) Log.d(TAG, "stopMonitoring(" + iface + ")");
168         setMonitoring(iface, true);
169         broadcastSupplicantDisconnectionEvent(iface);
170         setMonitoring(iface, false);
171     }
172 
173     /**
174      * Similar functions to Handler#sendMessage that send the message to the registered handler
175      * for the given interface and message what.
176      * All of these should be called with the WifiMonitor class lock
177      */
sendMessage(String iface, int what)178     private void sendMessage(String iface, int what) {
179         sendMessage(iface, Message.obtain(null, what));
180     }
181 
sendMessage(String iface, int what, Object obj)182     private void sendMessage(String iface, int what, Object obj) {
183         sendMessage(iface, Message.obtain(null, what, obj));
184     }
185 
sendMessage(String iface, int what, int arg1)186     private void sendMessage(String iface, int what, int arg1) {
187         sendMessage(iface, Message.obtain(null, what, arg1, 0));
188     }
189 
sendMessage(String iface, int what, int arg1, int arg2)190     private void sendMessage(String iface, int what, int arg1, int arg2) {
191         sendMessage(iface, Message.obtain(null, what, arg1, arg2));
192     }
193 
sendMessage(String iface, int what, int arg1, int arg2, Object obj)194     private void sendMessage(String iface, int what, int arg1, int arg2, Object obj) {
195         sendMessage(iface, Message.obtain(null, what, arg1, arg2, obj));
196     }
197 
sendMessage(String iface, Message message)198     private void sendMessage(String iface, Message message) {
199         SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface);
200         if (iface != null && ifaceHandlers != null) {
201             if (isMonitoring(iface)) {
202                 Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(message.what);
203                 if (ifaceWhatHandlers != null) {
204                     for (Handler handler : ifaceWhatHandlers) {
205                         if (handler != null) {
206                             sendMessage(handler, Message.obtain(message));
207                         }
208                     }
209                 }
210             } else {
211                 if (mVerboseLoggingEnabled) {
212                     Log.d(TAG, "Dropping event because (" + iface + ") is stopped");
213                 }
214             }
215         } else {
216             if (mVerboseLoggingEnabled) {
217                 Log.d(TAG, "Sending to all monitors because there's no matching iface");
218             }
219             for (Map.Entry<String, SparseArray<Set<Handler>>> entry : mHandlerMap.entrySet()) {
220                 if (isMonitoring(entry.getKey())) {
221                     Set<Handler> ifaceWhatHandlers = entry.getValue().get(message.what);
222                     for (Handler handler : ifaceWhatHandlers) {
223                         if (handler != null) {
224                             sendMessage(handler, Message.obtain(message));
225                         }
226                     }
227                 }
228             }
229         }
230 
231         message.recycle();
232     }
233 
sendMessage(Handler handler, Message message)234     private void sendMessage(Handler handler, Message message) {
235         message.setTarget(handler);
236         message.sendToTarget();
237     }
238 
239     /**
240      * Broadcast the connection to wpa_supplicant event to all the handlers registered for
241      * this event.
242      *
243      * @param iface Name of iface on which this occurred.
244      */
broadcastSupplicantConnectionEvent(String iface)245     public void broadcastSupplicantConnectionEvent(String iface) {
246         sendMessage(iface, SUP_CONNECTION_EVENT);
247     }
248 
249     /**
250      * Broadcast the loss of connection to wpa_supplicant event to all the handlers registered for
251      * this event.
252      *
253      * @param iface Name of iface on which this occurred.
254      */
broadcastSupplicantDisconnectionEvent(String iface)255     public void broadcastSupplicantDisconnectionEvent(String iface) {
256         sendMessage(iface, SUP_DISCONNECTION_EVENT);
257     }
258 
259     /**
260      * Broadcast new p2p device discovered event to all handlers registered for this event.
261      *
262      * @param iface Name of iface on which this occurred.
263      * @param device Device that has been discovered during recent scan.
264      */
broadcastP2pDeviceFound(String iface, WifiP2pDevice device)265     public void broadcastP2pDeviceFound(String iface, WifiP2pDevice device) {
266         if (device != null) {
267             sendMessage(iface, P2P_DEVICE_FOUND_EVENT, device);
268         }
269     }
270 
271     /**
272      * Broadcast p2p device lost event to all handlers registered for this event.
273      *
274      * @param iface Name of iface on which this occurred.
275      * @param device Device that has been lost in recent scan.
276      */
broadcastP2pDeviceLost(String iface, WifiP2pDevice device)277     public void broadcastP2pDeviceLost(String iface, WifiP2pDevice device) {
278         if (device != null) {
279             sendMessage(iface, P2P_DEVICE_LOST_EVENT, device);
280         }
281     }
282 
283     /**
284      * Broadcast scan termination event to all handlers registered for this event.
285      *
286      * @param iface Name of iface on which this occurred.
287      */
broadcastP2pFindStopped(String iface)288     public void broadcastP2pFindStopped(String iface) {
289         sendMessage(iface, P2P_FIND_STOPPED_EVENT);
290     }
291 
292     /**
293      * Broadcast group owner negotiation request event to all handlers registered for this event.
294      *
295      * @param iface Name of iface on which this occurred.
296      * @param config P2p configuration.
297      */
broadcastP2pGoNegotiationRequest(String iface, WifiP2pConfig config)298     public void broadcastP2pGoNegotiationRequest(String iface, WifiP2pConfig config) {
299         if (config != null) {
300             sendMessage(iface, P2P_GO_NEGOTIATION_REQUEST_EVENT, config);
301         }
302     }
303 
304     /**
305      * Broadcast group owner negotiation success event to all handlers registered for this event.
306      *
307      * @param iface Name of iface on which this occurred.
308      */
broadcastP2pGoNegotiationSuccess(String iface)309     public void broadcastP2pGoNegotiationSuccess(String iface) {
310         sendMessage(iface, P2P_GO_NEGOTIATION_SUCCESS_EVENT);
311     }
312 
313     /**
314      * Broadcast group owner negotiation failure event to all handlers registered for this event.
315      *
316      * @param iface Name of iface on which this occurred.
317      * @param reason Failure reason.
318      */
broadcastP2pGoNegotiationFailure(String iface, P2pStatus reason)319     public void broadcastP2pGoNegotiationFailure(String iface, P2pStatus reason) {
320         sendMessage(iface, P2P_GO_NEGOTIATION_FAILURE_EVENT, reason);
321     }
322 
323     /**
324      * Broadcast group formation success event to all handlers registered for this event.
325      *
326      * @param iface Name of iface on which this occurred.
327      */
broadcastP2pGroupFormationSuccess(String iface)328     public void broadcastP2pGroupFormationSuccess(String iface) {
329         sendMessage(iface, P2P_GROUP_FORMATION_SUCCESS_EVENT);
330     }
331 
332     /**
333      * Broadcast group formation failure event to all handlers registered for this event.
334      *
335      * @param iface Name of iface on which this occurred.
336      * @param reason Failure reason.
337      */
broadcastP2pGroupFormationFailure(String iface, String reason)338     public void broadcastP2pGroupFormationFailure(String iface, String reason) {
339         P2pStatus err = P2pStatus.UNKNOWN;
340         if (reason.equals("FREQ_CONFLICT")) {
341             err = P2pStatus.NO_COMMON_CHANNEL;
342         }
343         sendMessage(iface, P2P_GROUP_FORMATION_FAILURE_EVENT, err);
344     }
345 
346     /**
347      * Broadcast group started event to all handlers registered for this event.
348      *
349      * @param iface Name of iface on which this occurred.
350      * @param group Started group.
351      */
broadcastP2pGroupStarted(String iface, WifiP2pGroup group)352     public void broadcastP2pGroupStarted(String iface, WifiP2pGroup group) {
353         if (group != null) {
354             sendMessage(iface, P2P_GROUP_STARTED_EVENT, group);
355         }
356     }
357 
358     /**
359      * Broadcast group removed event to all handlers registered for this event.
360      *
361      * @param iface Name of iface on which this occurred.
362      * @param group Removed group.
363      */
broadcastP2pGroupRemoved(String iface, WifiP2pGroup group)364     public void broadcastP2pGroupRemoved(String iface, WifiP2pGroup group) {
365         if (group != null) {
366             sendMessage(iface, P2P_GROUP_REMOVED_EVENT, group);
367         }
368     }
369 
370     /**
371      * Broadcast invitation received event to all handlers registered for this event.
372      *
373      * @param iface Name of iface on which this occurred.
374      * @param group Group to which invitation has been received.
375      */
broadcastP2pInvitationReceived(String iface, WifiP2pGroup group)376     public void broadcastP2pInvitationReceived(String iface, WifiP2pGroup group) {
377         if (group != null) {
378             sendMessage(iface, P2P_INVITATION_RECEIVED_EVENT, group);
379         }
380     }
381 
382     /**
383      * Broadcast invitation result event to all handlers registered for this event.
384      *
385      * @param iface Name of iface on which this occurred.
386      * @param result Result of invitation.
387      */
broadcastP2pInvitationResult(String iface, P2pStatus result)388     public void broadcastP2pInvitationResult(String iface, P2pStatus result) {
389         sendMessage(iface, P2P_INVITATION_RESULT_EVENT, result);
390     }
391 
392     /**
393      * Broadcast PB discovery request event to all handlers registered for this event.
394      *
395      * @param iface Name of iface on which this occurred.
396      * @param event Provision discovery request event.
397      */
broadcastP2pProvisionDiscoveryPbcRequest(String iface, WifiP2pProvDiscEvent event)398     public void broadcastP2pProvisionDiscoveryPbcRequest(String iface, WifiP2pProvDiscEvent event) {
399         if (event != null) {
400             sendMessage(iface, P2P_PROV_DISC_PBC_REQ_EVENT, event);
401         }
402     }
403 
404     /**
405      * Broadcast PB discovery response event to all handlers registered for this event.
406      *
407      * @param iface Name of iface on which this occurred.
408      * @param event Provision discovery response event.
409      */
broadcastP2pProvisionDiscoveryPbcResponse( String iface, WifiP2pProvDiscEvent event)410     public void broadcastP2pProvisionDiscoveryPbcResponse(
411             String iface, WifiP2pProvDiscEvent event) {
412         if (event != null) {
413             sendMessage(iface, P2P_PROV_DISC_PBC_RSP_EVENT, event);
414         }
415     }
416 
417     /**
418      * Broadcast PIN discovery request event to all handlers registered for this event.
419      *
420      * @param iface Name of iface on which this occurred.
421      * @param event Provision discovery request event.
422      */
broadcastP2pProvisionDiscoveryEnterPin(String iface, WifiP2pProvDiscEvent event)423     public void broadcastP2pProvisionDiscoveryEnterPin(String iface, WifiP2pProvDiscEvent event) {
424         if (event != null) {
425             sendMessage(iface, P2P_PROV_DISC_ENTER_PIN_EVENT, event);
426         }
427     }
428 
429     /**
430      * Broadcast PIN discovery response event to all handlers registered for this event.
431      *
432      * @param iface Name of iface on which this occurred.
433      * @param event Provision discovery response event.
434      */
broadcastP2pProvisionDiscoveryShowPin(String iface, WifiP2pProvDiscEvent event)435     public void broadcastP2pProvisionDiscoveryShowPin(String iface, WifiP2pProvDiscEvent event) {
436         if (event != null) {
437             sendMessage(iface, P2P_PROV_DISC_SHOW_PIN_EVENT, event);
438         }
439     }
440 
441     /**
442      * Broadcast P2P discovery failure event to all handlers registered for this event.
443      *
444      * @param iface Name of iface on which this occurred.
445      * @param status Indicate the reason of this failure.
446      * @param event The information about the provision discovery.
447      */
broadcastP2pProvisionDiscoveryFailure(@onNull String iface, @P2pProvDiscStatus int status, @NonNull WifiP2pProvDiscEvent event)448     public void broadcastP2pProvisionDiscoveryFailure(@NonNull String iface,
449             @P2pProvDiscStatus int status, @NonNull WifiP2pProvDiscEvent event) {
450         sendMessage(iface, P2P_PROV_DISC_FAILURE_EVENT, status, 0, event);
451     }
452 
453     /**
454      * Broadcast service discovery response event to all handlers registered for this event.
455      *
456      * @param iface Name of iface on which this occurred.
457      * @param services List of discovered services.
458      */
broadcastP2pServiceDiscoveryResponse( String iface, List<WifiP2pServiceResponse> services)459     public void broadcastP2pServiceDiscoveryResponse(
460             String iface, List<WifiP2pServiceResponse> services) {
461         sendMessage(iface, P2P_SERV_DISC_RESP_EVENT, services);
462     }
463 
464     /**
465      * Broadcast AP STA connection event.
466      *
467      * @param iface Name of iface on which this occurred.
468      */
broadcastP2pApStaConnected(String iface, WifiP2pDevice device)469     public void broadcastP2pApStaConnected(String iface, WifiP2pDevice device) {
470         sendMessage(iface, AP_STA_CONNECTED_EVENT, device);
471     }
472 
473     /**
474      * Broadcast AP STA disconnection event.
475      *
476      * @param iface Name of iface on which this occurred.
477      */
broadcastP2pApStaDisconnected(String iface, WifiP2pDevice device)478     public void broadcastP2pApStaDisconnected(String iface, WifiP2pDevice device) {
479         sendMessage(iface, AP_STA_DISCONNECTED_EVENT, device);
480     }
481 
482     /**
483      * Broadcast frequency changed event.
484      *
485      * @param iface Name of iface on which this occurred.
486      * @param frequency New operating frequency.
487      */
broadcastP2pFrequencyChanged(String iface, int frequency)488     public void broadcastP2pFrequencyChanged(String iface,  int frequency) {
489         sendMessage(iface, P2P_FREQUENCY_CHANGED_EVENT, frequency);
490     }
491 }
492