Home | History | Annotate | Download | only in wifi
      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 android.net.wifi;
     18 
     19 import android.net.wifi.p2p.WifiP2pConfig;
     20 import android.net.wifi.p2p.WifiP2pGroup;
     21 import android.net.wifi.p2p.WifiP2pDevice;
     22 import android.util.Log;
     23 
     24 import java.io.InputStream;
     25 import java.lang.Process;
     26 import java.util.ArrayList;
     27 import java.util.List;
     28 
     29 /**
     30  * Native calls for sending requests to the supplicant daemon, and for
     31  * receiving asynchronous events. All methods of the form "xxxxCommand()"
     32  * must be single-threaded, to avoid requests and responses initiated
     33  * from multiple threads from being intermingled.
     34  * <p/>
     35  * Note that methods whose names are not of the form "xxxCommand()" do
     36  * not talk to the supplicant daemon.
     37  * Also, note that all WifiNative calls should happen in the
     38  * WifiStateTracker class except for waitForEvent() call which is
     39  * on a separate monitor channel for WifiMonitor
     40  *
     41  * TODO: clean up the API and move the functionality from JNI to here. We should
     42  * be able to get everything done with doBooleanCommand, doIntCommand and
     43  * doStringCommand native commands
     44  *
     45  * {@hide}
     46  */
     47 public class WifiNative {
     48 
     49     static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0;
     50     static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1;
     51     static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2;
     52 
     53     public native static String getErrorString(int errorCode);
     54 
     55     public native static boolean loadDriver();
     56 
     57     public native static boolean isDriverLoaded();
     58 
     59     public native static boolean unloadDriver();
     60 
     61     public native static boolean startSupplicant();
     62 
     63     public native static boolean startP2pSupplicant();
     64 
     65     /* Does a graceful shutdown of supplicant. Is a common stop function for both p2p and sta.
     66      *
     67      * Note that underneath we use a harsh-sounding "terminate" supplicant command
     68      * for a graceful stop and a mild-sounding "stop" interface
     69      * to kill the process
     70      */
     71     public native static boolean stopSupplicant();
     72 
     73     /* Sends a kill signal to supplicant. To be used when we have lost connection
     74        or when the supplicant is hung */
     75     public native static boolean killSupplicant();
     76 
     77     public native static boolean connectToSupplicant();
     78 
     79     public native static void closeSupplicantConnection();
     80 
     81     public native static boolean pingCommand();
     82 
     83     public native static boolean scanCommand(boolean forceActive);
     84 
     85     public native static boolean setScanModeCommand(boolean setActive);
     86 
     87     public native static String listNetworksCommand();
     88 
     89     public native static int addNetworkCommand();
     90 
     91     public native static boolean setNetworkVariableCommand(int netId, String name, String value);
     92 
     93     public native static String getNetworkVariableCommand(int netId, String name);
     94 
     95     public native static boolean removeNetworkCommand(int netId);
     96 
     97     public native static boolean enableNetworkCommand(int netId, boolean disableOthers);
     98 
     99     public native static boolean disableNetworkCommand(int netId);
    100 
    101     public native static boolean reconnectCommand();
    102 
    103     public native static boolean reassociateCommand();
    104 
    105     public native static boolean disconnectCommand();
    106 
    107     public native static String statusCommand();
    108 
    109     public native static String getMacAddressCommand();
    110 
    111     public native static String scanResultsCommand();
    112 
    113     public native static boolean startDriverCommand();
    114 
    115     public native static boolean stopDriverCommand();
    116 
    117 
    118     /**
    119      * Start filtering out Multicast V4 packets
    120      * @return {@code true} if the operation succeeded, {@code false} otherwise
    121      */
    122     public native static boolean startFilteringMulticastV4Packets();
    123 
    124     /**
    125      * Stop filtering out Multicast V4 packets.
    126      * @return {@code true} if the operation succeeded, {@code false} otherwise
    127      */
    128     public native static boolean stopFilteringMulticastV4Packets();
    129 
    130     /**
    131      * Start filtering out Multicast V6 packets
    132      * @return {@code true} if the operation succeeded, {@code false} otherwise
    133      */
    134     public native static boolean startFilteringMulticastV6Packets();
    135 
    136     /**
    137      * Stop filtering out Multicast V6 packets.
    138      * @return {@code true} if the operation succeeded, {@code false} otherwise
    139      */
    140     public native static boolean stopFilteringMulticastV6Packets();
    141 
    142     public native static boolean setPowerModeCommand(int mode);
    143 
    144     public native static int getBandCommand();
    145 
    146     public native static boolean setBandCommand(int band);
    147 
    148     public native static int getPowerModeCommand();
    149 
    150     /**
    151      * Sets the bluetooth coexistence mode.
    152      *
    153      * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED},
    154      *            {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or
    155      *            {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}.
    156      * @return Whether the mode was successfully set.
    157      */
    158     public native static boolean setBluetoothCoexistenceModeCommand(int mode);
    159 
    160     /**
    161      * Enable or disable Bluetooth coexistence scan mode. When this mode is on,
    162      * some of the low-level scan parameters used by the driver are changed to
    163      * reduce interference with A2DP streaming.
    164      *
    165      * @param isSet whether to enable or disable this mode
    166      * @return {@code true} if the command succeeded, {@code false} otherwise.
    167      */
    168     public native static boolean setBluetoothCoexistenceScanModeCommand(boolean setCoexScanMode);
    169 
    170     public native static boolean saveConfigCommand();
    171 
    172     public native static boolean reloadConfigCommand();
    173 
    174     public native static boolean setScanResultHandlingCommand(int mode);
    175 
    176     public native static boolean addToBlacklistCommand(String bssid);
    177 
    178     public native static boolean clearBlacklistCommand();
    179 
    180     public native static boolean startWpsPbcCommand(String bssid);
    181 
    182     public native static boolean startWpsWithPinFromAccessPointCommand(String bssid, String apPin);
    183 
    184     public native static String startWpsWithPinFromDeviceCommand(String bssid);
    185 
    186     public native static boolean setSuspendOptimizationsCommand(boolean enabled);
    187 
    188     public native static boolean setCountryCodeCommand(String countryCode);
    189 
    190     /**
    191      * Wait for the supplicant to send an event, returning the event string.
    192      * @return the event string sent by the supplicant.
    193      */
    194     public native static String waitForEvent();
    195 
    196     public native static void enableBackgroundScanCommand(boolean enable);
    197 
    198     public native static void setScanIntervalCommand(int scanInterval);
    199 
    200     private native static boolean doBooleanCommand(String command);
    201 
    202     private native static int doIntCommand(String command);
    203 
    204     private native static String doStringCommand(String command);
    205 
    206     /** Example output:
    207      * RSSI=-65
    208      * LINKSPEED=48
    209      * NOISE=9999
    210      * FREQUENCY=0
    211      */
    212     public static String signalPoll() {
    213         return doStringCommand("SIGNAL_POLL");
    214     }
    215 
    216     public static boolean wpsPbc() {
    217         return doBooleanCommand("WPS_PBC");
    218     }
    219 
    220     public static boolean wpsPin(String pin) {
    221         return doBooleanCommand("WPS_PIN any " + pin);
    222     }
    223 
    224     public static boolean setPersistentReconnect(boolean enabled) {
    225         int value = (enabled == true) ? 1 : 0;
    226         return WifiNative.doBooleanCommand("SET persistent_reconnect " + value);
    227     }
    228 
    229     public static boolean setDeviceName(String name) {
    230         return WifiNative.doBooleanCommand("SET device_name " + name);
    231     }
    232 
    233     public static boolean setDeviceType(String type) {
    234         return WifiNative.doBooleanCommand("SET device_type " + type);
    235     }
    236 
    237     public static boolean p2pFind() {
    238         return doBooleanCommand("P2P_FIND");
    239     }
    240 
    241     public static boolean p2pFind(int timeout) {
    242         if (timeout <= 0) {
    243             return p2pFind();
    244         }
    245         return doBooleanCommand("P2P_FIND " + timeout);
    246     }
    247 
    248     public static boolean p2pListen() {
    249         return doBooleanCommand("P2P_LISTEN");
    250     }
    251 
    252     public static boolean p2pListen(int timeout) {
    253         if (timeout <= 0) {
    254             return p2pListen();
    255         }
    256         return doBooleanCommand("P2P_LISTEN " + timeout);
    257     }
    258 
    259     public static boolean p2pFlush() {
    260         return doBooleanCommand("P2P_FLUSH");
    261     }
    262 
    263     /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad]
    264         [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */
    265     public static String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) {
    266         if (config == null) return null;
    267         List<String> args = new ArrayList<String>();
    268         WpsInfo wps = config.wps;
    269         args.add(config.deviceAddress);
    270 
    271         switch (wps.setup) {
    272             case WpsInfo.PBC:
    273                 args.add("pbc");
    274                 break;
    275             case WpsInfo.DISPLAY:
    276                 //TODO: pass the pin back for display
    277                 args.add("pin");
    278                 args.add("display");
    279                 break;
    280             case WpsInfo.KEYPAD:
    281                 args.add(wps.pin);
    282                 args.add("keypad");
    283                 break;
    284             case WpsInfo.LABEL:
    285                 args.add(wps.pin);
    286                 args.add("label");
    287             default:
    288                 break;
    289         }
    290 
    291         //TODO: Add persist behavior once the supplicant interaction is fixed for both
    292         // group and client scenarios
    293         /* Persist unless there is an explicit request to not do so*/
    294         //if (config.persist != WifiP2pConfig.Persist.NO) args.add("persistent");
    295 
    296         if (joinExistingGroup) args.add("join");
    297 
    298         int groupOwnerIntent = config.groupOwnerIntent;
    299         if (groupOwnerIntent < 0 || groupOwnerIntent > 15) {
    300             groupOwnerIntent = 3; //default value
    301         }
    302         args.add("go_intent=" + groupOwnerIntent);
    303 
    304         String command = "P2P_CONNECT ";
    305         for (String s : args) command += s + " ";
    306 
    307         return doStringCommand(command);
    308     }
    309 
    310     public static boolean p2pCancelConnect() {
    311         return doBooleanCommand("P2P_CANCEL");
    312     }
    313 
    314     public static boolean p2pGroupAdd() {
    315         return doBooleanCommand("P2P_GROUP_ADD");
    316     }
    317 
    318     public static boolean p2pGroupRemove(String iface) {
    319         if (iface == null) return false;
    320         return doBooleanCommand("P2P_GROUP_REMOVE " + iface);
    321     }
    322 
    323     public static boolean p2pReject(String deviceAddress) {
    324         return doBooleanCommand("P2P_REJECT " + deviceAddress);
    325     }
    326 
    327     /* Invite a peer to a group */
    328     public static boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {
    329         if (deviceAddress == null) return false;
    330 
    331         if (group == null) {
    332             return doBooleanCommand("P2P_INVITE peer=" + deviceAddress);
    333         } else {
    334             return doBooleanCommand("P2P_INVITE group=" + group.getInterface()
    335                     + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress);
    336         }
    337     }
    338 
    339     /* Reinvoke a persistent connection */
    340     public static boolean p2pReinvoke(int netId, String deviceAddress) {
    341         if (deviceAddress == null || netId < 0) return false;
    342 
    343         return doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + deviceAddress);
    344     }
    345 
    346 
    347     public static String p2pGetInterfaceAddress(String deviceAddress) {
    348         if (deviceAddress == null) return null;
    349 
    350         //  "p2p_peer deviceAddress" returns a multi-line result containing
    351         //      intended_addr=fa:7b:7a:42:82:13
    352         String peerInfo = p2pPeer(deviceAddress);
    353         if (peerInfo == null) return null;
    354         String[] tokens= peerInfo.split("\n");
    355 
    356         for (String token : tokens) {
    357             //TODO: update from interface_addr when wpa_supplicant implementation is fixed
    358             if (token.startsWith("intended_addr=")) {
    359                 String[] nameValue = token.split("=");
    360                 if (nameValue.length != 2) break;
    361                 return nameValue[1];
    362             }
    363         }
    364         return null;
    365     }
    366 
    367     public static String p2pGetDeviceAddress() {
    368         String status = statusCommand();
    369         if (status == null) return "";
    370 
    371         String[] tokens = status.split("\n");
    372         for (String token : tokens) {
    373             if (token.startsWith("p2p_device_address=")) {
    374                 String[] nameValue = token.split("=");
    375                 if (nameValue.length != 2) break;
    376                 return nameValue[1];
    377             }
    378         }
    379         return "";
    380     }
    381 
    382     public static String p2pPeer(String deviceAddress) {
    383         return doStringCommand("P2P_PEER " + deviceAddress);
    384     }
    385 }
    386