Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 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 #define LOG_TAG "wifi"
     18 
     19 #include "jni.h"
     20 #include <ScopedUtfChars.h>
     21 #include <utils/misc.h>
     22 #include <android_runtime/AndroidRuntime.h>
     23 #include <utils/Log.h>
     24 #include <utils/String16.h>
     25 
     26 #include "wifi.h"
     27 
     28 #define WIFI_PKG_NAME "android/net/wifi/WifiNative"
     29 #define BUF_SIZE 256
     30 #define EVENT_BUF_SIZE 2048
     31 
     32 namespace android {
     33 
     34 static jint DBG = false;
     35 
     36 static int doCommand(const char *ifname, const char *cmd, char *replybuf, int replybuflen)
     37 {
     38     size_t reply_len = replybuflen - 1;
     39 
     40     if (::wifi_command(ifname, cmd, replybuf, &reply_len) != 0)
     41         return -1;
     42     else {
     43         // Strip off trailing newline
     44         if (reply_len > 0 && replybuf[reply_len-1] == '\n')
     45             replybuf[reply_len-1] = '\0';
     46         else
     47             replybuf[reply_len] = '\0';
     48         return 0;
     49     }
     50 }
     51 
     52 static jint doIntCommand(const char *ifname, const char* fmt, ...)
     53 {
     54     char buf[BUF_SIZE];
     55     va_list args;
     56     va_start(args, fmt);
     57     int byteCount = vsnprintf(buf, sizeof(buf), fmt, args);
     58     va_end(args);
     59     if (byteCount < 0 || byteCount >= BUF_SIZE) {
     60         return -1;
     61     }
     62     char reply[BUF_SIZE];
     63     if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) {
     64         return -1;
     65     }
     66     return static_cast<jint>(atoi(reply));
     67 }
     68 
     69 static jboolean doBooleanCommand(const char *ifname, const char* expect, const char* fmt, ...)
     70 {
     71     char buf[BUF_SIZE];
     72     va_list args;
     73     va_start(args, fmt);
     74     int byteCount = vsnprintf(buf, sizeof(buf), fmt, args);
     75     va_end(args);
     76     if (byteCount < 0 || byteCount >= BUF_SIZE) {
     77         return JNI_FALSE;
     78     }
     79     char reply[BUF_SIZE];
     80     if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) {
     81         return JNI_FALSE;
     82     }
     83     return (strcmp(reply, expect) == 0);
     84 }
     85 
     86 // Send a command to the supplicant, and return the reply as a String
     87 static jstring doStringCommand(JNIEnv* env, const char *ifname, const char* fmt, ...) {
     88     char buf[BUF_SIZE];
     89     va_list args;
     90     va_start(args, fmt);
     91     int byteCount = vsnprintf(buf, sizeof(buf), fmt, args);
     92     va_end(args);
     93     if (byteCount < 0 || byteCount >= BUF_SIZE) {
     94         return NULL;
     95     }
     96     char reply[4096];
     97     if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) {
     98         return NULL;
     99     }
    100     // TODO: why not just NewStringUTF?
    101     String16 str((char *)reply);
    102     return env->NewString((const jchar *)str.string(), str.size());
    103 }
    104 
    105 static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject)
    106 {
    107     return (jboolean)(::is_wifi_driver_loaded() == 1);
    108 }
    109 
    110 static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
    111 {
    112     return (jboolean)(::wifi_load_driver() == 0);
    113 }
    114 
    115 static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject)
    116 {
    117     return (jboolean)(::wifi_unload_driver() == 0);
    118 }
    119 
    120 static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject, jboolean p2pSupported)
    121 {
    122     return (jboolean)(::wifi_start_supplicant(p2pSupported) == 0);
    123 }
    124 
    125 static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject)
    126 {
    127     return (jboolean)(::wifi_stop_supplicant() == 0);
    128 }
    129 
    130 static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject, jstring jIface)
    131 {
    132     ScopedUtfChars ifname(env, jIface);
    133     return (jboolean)(::wifi_connect_to_supplicant(ifname.c_str()) == 0);
    134 }
    135 
    136 static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject, jstring jIface)
    137 {
    138     ScopedUtfChars ifname(env, jIface);
    139     ::wifi_close_supplicant_connection(ifname.c_str());
    140 }
    141 
    142 static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject, jstring jIface)
    143 {
    144     char buf[EVENT_BUF_SIZE];
    145     ScopedUtfChars ifname(env, jIface);
    146     int nread = ::wifi_wait_for_event(ifname.c_str(), buf, sizeof buf);
    147     if (nread > 0) {
    148         return env->NewStringUTF(buf);
    149     } else {
    150         return NULL;
    151     }
    152 }
    153 
    154 static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring jIface,
    155         jstring jCommand)
    156 {
    157     ScopedUtfChars ifname(env, jIface);
    158     ScopedUtfChars command(env, jCommand);
    159 
    160     if (command.c_str() == NULL) {
    161         return JNI_FALSE;
    162     }
    163     if (DBG) ALOGD("doBoolean: %s", command.c_str());
    164     return doBooleanCommand(ifname.c_str(), "OK", "%s", command.c_str());
    165 }
    166 
    167 static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring jIface,
    168         jstring jCommand)
    169 {
    170     ScopedUtfChars ifname(env, jIface);
    171     ScopedUtfChars command(env, jCommand);
    172 
    173     if (command.c_str() == NULL) {
    174         return -1;
    175     }
    176     if (DBG) ALOGD("doInt: %s", command.c_str());
    177     return doIntCommand(ifname.c_str(), "%s", command.c_str());
    178 }
    179 
    180 static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring jIface,
    181         jstring jCommand)
    182 {
    183     ScopedUtfChars ifname(env, jIface);
    184 
    185     ScopedUtfChars command(env, jCommand);
    186     if (command.c_str() == NULL) {
    187         return NULL;
    188     }
    189     if (DBG) ALOGD("doString: %s", command.c_str());
    190     return doStringCommand(env, ifname.c_str(), "%s", command.c_str());
    191 }
    192 
    193 
    194 
    195 // ----------------------------------------------------------------------------
    196 
    197 /*
    198  * JNI registration.
    199  */
    200 static JNINativeMethod gWifiMethods[] = {
    201     /* name, signature, funcPtr */
    202 
    203     { "loadDriver", "()Z",  (void *)android_net_wifi_loadDriver },
    204     { "isDriverLoaded", "()Z",  (void *)android_net_wifi_isDriverLoaded },
    205     { "unloadDriver", "()Z",  (void *)android_net_wifi_unloadDriver },
    206     { "startSupplicant", "(Z)Z",  (void *)android_net_wifi_startSupplicant },
    207     { "killSupplicant", "()Z",  (void *)android_net_wifi_killSupplicant },
    208     { "connectToSupplicant", "(Ljava/lang/String;)Z",
    209             (void *)android_net_wifi_connectToSupplicant },
    210     { "closeSupplicantConnection", "(Ljava/lang/String;)V",
    211             (void *)android_net_wifi_closeSupplicantConnection },
    212     { "waitForEvent", "(Ljava/lang/String;)Ljava/lang/String;",
    213             (void*) android_net_wifi_waitForEvent },
    214     { "doBooleanCommand", "(Ljava/lang/String;Ljava/lang/String;)Z",
    215             (void*) android_net_wifi_doBooleanCommand },
    216     { "doIntCommand", "(Ljava/lang/String;Ljava/lang/String;)I",
    217             (void*) android_net_wifi_doIntCommand },
    218     { "doStringCommand", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
    219             (void*) android_net_wifi_doStringCommand },
    220 };
    221 
    222 int register_android_net_wifi_WifiManager(JNIEnv* env)
    223 {
    224     return AndroidRuntime::registerNativeMethods(env,
    225             WIFI_PKG_NAME, gWifiMethods, NELEM(gWifiMethods));
    226 }
    227 
    228 }; // namespace android
    229