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