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