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