Android中网络的整体架构如下:




NetworkmanagementService

此模块运行在SystemService中,负责Java层的实现机制,提供对上层的一些运行接口,当然,上层是通过一些抽象类实现进程间通讯进行访问的。


NetD

此模块是C++的Daemon,负责底层部分对于一些关键网络服务的管理。对上面Java服务提供接口,采用进程间通讯的方式。


Wpa_supplicant

此模块是提供WIFI支持的模块,不做详细描述了。在Android中是一个关键的底层服务。


Dnsmasq

此服务实现了DHCP Server,用于辅助Hostapd,实现IP的管理。


Hosted

此服务实现了WIFI AP的关键服务,直接控制底层设备,此服务正常运行后,其他终端可以搜索到AP,并连接。


以下是启动WIFI AP 的流程:



以下是代码说明:


NetworkManagementService

base/wifi/java/android/net/wifi/WifiStateMachine.javaprivate void startSoftApWithConfig(final WifiConfiguration config)


frameworks/base/services/java/com/android/server/NetworkManagementService.java // 网路管理服务

startAccessPoint {...}wifiFirmwareReload(wlanIface, "AP");mConnector.execute("softap", "set", wlanIface);mConnector.execute("softap", "startap");


system/netd/CommandListener.cpp // 通讯用得CommandListener

CommandListener::SoftapCmd::runCommand



NetD 服务

system/netd/SoftapController.cpp 

SoftapController::startSoftap()static const char HOSTAPD_CONF_FILE[]    = "/data/misc/wifi/hostapd.conf";#define WIFI_ENTROPY_FILE "/data/misc/wifi/entropy.bin"ensure_entropy_file_exists();  // 检查需要加密文件是否存在        if (execl("/system/bin/hostapd", "/system/bin/hostapd",  //启动Hostapd                  "-e", WIFI_ENTROPY_FILE,                  HOSTAPD_CONF_FILE, (char *) NULL)) {            ALOGE("execl failed (%s)", strerror(errno));}SoftapController::stopSoftap // 停止Hostapdkill(mPid, SIGTERM);  // 结束Hostapdwaitpid(mPid, NULL, 0) // 等待结束返回

system/netd/TetherController.cpp  // DHCP daemon 管理

startTethering() {..."system/bin/dnsmasq"  // 启动Dnsmasq后台进程...}

启动Hostapd

SoftapController::startSoftap()static const char HOSTAPD_CONF_FILE[]    = "/data/misc/wifi/hostapd.conf";#define WIFI_ENTROPY_FILE "/data/misc/wifi/entropy.bin"ensure_entropy_file_exists();  // 检查需要加密文件是否存在        if (execl("/system/bin/hostapd", "/system/bin/hostapd",  //启动Hostapd                  "-e", WIFI_ENTROPY_FILE,                  HOSTAPD_CONF_FILE, (char *) NULL)) {            ALOGE("execl failed (%s)", strerror(errno));}SoftapController::stopSoftap // 停止Hostapdkill(mPid, SIGTERM);  // 结束Hostapdwaitpid(mPid, NULL, 0) // 等待结束返回

WIFI AP 参数设置

int SoftapController::setSoftap(int argc, char *argv[]) {... property_get("wifi.interface", iface, "wlan0");    char *wbuf = NULL;    char *fbuf = NULL;    if (argc > 3) {        ssid = argv[3];    } else {        ssid = (char *)"AndroidAP";    }    asprintf(&wbuf, "interface=%s\ndriver=nl80211\nctrl_interface="            "/data/misc/wifi/hostapd\nssid=%s\nchannel=6\nieee80211n=1\n",            iface, ssid);    if (argc > 4) {        if (!strcmp(argv[4], "wpa-psk")) {            generatePsk(ssid, argv[5], psk_str);            asprintf(&fbuf, "%swpa=1\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf, psk_str);        } else if (!strcmp(argv[4], "wpa2-psk")) {            generatePsk(ssid, argv[5], psk_str);            asprintf(&fbuf, "%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", wbuf, psk_str);        } else if (!strncmp("wep", argv[4], 3)){            if((strlen(argv[5]) == 5) || (strlen(argv[5]) == 13))                asprintf(&fbuf, "%swep_default_key=0\nwep_key0=\"%s\"\n", wbuf,argv[5]);            else                asprintf(&fbuf, "%swep_default_key=0\nwep_key0=%s\n", wbuf,argv[5]);        } else if (!strcmp(argv[4], "open")) {            asprintf(&fbuf, "%s", wbuf);        }    } else {        asprintf(&fbuf, "%s", wbuf);    }    fd = open(HOSTAPD_CONF_FILE, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW, 0660);    if (fd < 0) {        ALOGE("Cannot update \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));        free(wbuf);        free(fbuf);        return -1;    }    if (write(fd, fbuf, strlen(fbuf)) < 0) {        ALOGE("Cannot write to \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));        ret = -1;    }    free(wbuf);    free(fbuf);     if (fchmod(fd, 0660) < 0) {        ALOGE("Error changing permissions of %s to 0660: %s",                HOSTAPD_CONF_FILE, strerror(errno));        close(fd);        unlink(HOSTAPD_CONF_FILE);        return -1;    }    if (fchown(fd, AID_SYSTEM, AID_WIFI) < 0) {        ALOGE("Error changing group ownership of %s to %d: %s",                HOSTAPD_CONF_FILE, AID_WIFI, strerror(errno));        close(fd);        unlink(HOSTAPD_CONF_FILE);        return -1;    }    close(fd);    return ret;}

PSK Key 的生成

wpa-psk和wpa2-psk 需要生成PSK

#include void SoftapController::generatePsk(char *ssid, char *passphrase, char *psk_str) {    unsigned char psk[SHA256_DIGEST_LENGTH];    int j;    // Use the PKCS#5 PBKDF2 with 4096 iterations    PKCS5_PBKDF2_HMAC_SHA1(passphrase, strlen(passphrase),            reinterpret_cast(ssid), strlen(ssid),            4096, SHA256_DIGEST_LENGTH, psk);    for (j=0; j < SHA256_DIGEST_LENGTH; j++) {        sprintf(&psk_str[j<<1], "%02x", psk[j]);    }    psk_str[j<<1] = '\0';}



重载Firmware的机制

hardware/libhardware_legacy/wifi/wifi.c   // wifi interface of HAL

system/netd/SoftapController.cpp wifi_change_fw_path 重载Firmware

hardware/libhardware_legacy/wifi/wifi.c wifi_change_fw_path  重载Firmware

重载固件用得设备节点定义

#define WIFI_DRIVER_FW_PATH_PARAM       "/sys/module/wlan/parameters/fwpath" (原始)   "/sys/module/bcmdhd/parameters/firmware_path" (k900)

固件文件的地址

WIFI_DRIVER_FW_PATH_AP  "/system/etc/firmware/fw_bcmdhd_apsta.bin" 文件地址

Dnsmasq 代码启动流程如下

接收内核消息:Iface added wlan0然后就会调用到notifyInterfaceAdded

NetworkManagementService.java

private voidnotifyInterfaceAdded(String iface) {        for(INetworkManagementEventObserverobs : mObservers) {            try{                obs.interfaceAdded(iface);//回调tethering. interfaceAdded            } catch(Exception ex) {                Slog.w(TAG, "Observer notifier failed", ex);            }        }    }


 

 

Tethering.java

public void interfaceAdded(String iface) {//被回调到的函数        if(VDBG) Log.d(TAG, "interfaceAdded "+ iface);        booleanfound = false;        booleanusb = false;        synchronized(mPublicSync) {            if(isWifi(iface)) {                found = true;            }            if(isUsb(iface)) {                found = true;                usb = true;            }            if(isBluetooth(iface)) {                found = true;            }            if(found == false) {                if(VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");                return;            }             TetherInterfaceSM sm = mIfaces.get(iface);            if(sm != null) {                if(VDBG) Log.d(TAG, "active iface ("+ iface + ") reported as added, ignoring");                return;            }            sm = newTetherInterfaceSM(iface, mLooper, usb);//创建TetherInterfaceSM对象,然后会生成InitialState对象,调用InitialState.enter            mIfaces.put(iface, sm);            sm.start();        }    }       classInitialState extendsState {            @Override            public voidenter() {                setAvailable(true);                setTethered(false);                sendTetherStateChangedBroadcast();//发送广播            }  private voidsendTetherStateChangedBroadcast() {        try{            if(!mConnService.isTetheringSupported()) return;        } catch(RemoteException e) {            return;        }        ArrayList availableList = newArrayList();        ArrayList activeList = newArrayList();        ArrayList erroredList = newArrayList();        booleanwifiTethered = false;        booleanusbTethered = false;        booleanbluetoothTethered = false;        synchronized(mPublicSync) {            Setifaces = mIfaces.keySet();            for(Object iface : ifaces) {                TetherInterfaceSM sm = mIfaces.get(iface);                if(sm != null) {                    if(sm.isErrored()) {                        erroredList.add((String)iface);                    } else if(sm.isAvailable()) {                        availableList.add((String)iface);                    } else if(sm.isTethered()) {                        if(isUsb((String)iface)) {                            usbTethered = true;                        } else if(isWifi((String)iface)) {                            wifiTethered = true;                      } else if(isBluetooth((String)iface)) {                            bluetoothTethered = true;                        }                        activeList.add((String)iface);                    }                }            }        }        Intent broadcast = newIntent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);//发送广播到WifiStateMachine        broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING|                Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);

WifiStateMachine.java

 mContext.registerReceiver(            newBroadcastReceiver() {                @Override                public voidonReceive(Context context, Intent intent) {                    ArrayList available = intent.getStringArrayListExtra(                            ConnectivityManager.EXTRA_AVAILABLE_TETHER);                    ArrayList active = intent.getStringArrayListExtra(                            ConnectivityManager.EXTRA_ACTIVE_TETHER);                    sendMessage(CMD_TETHER_STATE_CHANGE, newTetherStateChange(available, active));//发送消息                   CMD_TETHER_STATE_CHANGE                }            },newIntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));//接收到广播 classSoftApStartedState extendsState {        @Override        public voidenter() {            if(DBG) log(getName() + "\n");            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());        }        @Override        public booleanprocessMessage(Message message) {            if(DBG) log(getName() + message.toString() + "\n");            switch(message.what) {                case CMD_STOP_AP:                    if(DBG) log("Stopping Soft AP");                    setWifiApState(WIFI_AP_STATE_DISABLING);                     /* We have not tethered at this point, so we just shutdown soft Ap */                    try{                        mNwService.stopAccessPoint(mInterfaceName);                    } catch(Exception e) {                        loge("Exception in stopAccessPoint()");                    }                    transitionTo(mDriverLoadedState);                    break;                case CMD_START_AP:                    // Ignore a start on a running access point                    break;                    /* Fail client mode operation when soft AP is enabled */                case CMD_START_SUPPLICANT:                   loge("Cannot start supplicant with a running soft AP");                    setWifiState(WIFI_STATE_UNKNOWN);                    break;                case CMD_TETHER_STATE_CHANGE://接收CMD_TETHER_STATE_CHANGE                    TetherStateChange stateChange = (TetherStateChange) message.obj;                    if (startTethering(stateChange.available)) {//调用startTethering                        transitionTo(mTetheringState);                    }private boolean startTethering(ArrayList available) {        boolean wifiAvailable = false;        checkAndSetConnectivityInstance();        String[] wifiRegexs = mCm.getTetherableWifiRegexs();        for (String intf : available) {            for (String regex : wifiRegexs) {                if (intf.matches(regex)) {                    InterfaceConfiguration ifcg = null;                    try {                        ifcg = mNwService.getInterfaceConfig(intf);                        if (ifcg != null) {                            /* IP/netmask: 192.168.43.1/255.255.255.0 */                            ifcg.addr = new LinkAddress(NetworkUtils.numericToInetAddress(                                    "192.168.43.1"), 24);                            ifcg.interfaceFlags = "[up]";                            mNwService.setInterfaceConfig(intf, ifcg);                        }                    } catch (Exception e) {                        loge("Error configuring interface " + intf + ", :" + e);                        return false;                    }                    if(mCm.tether(intf) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {// 调用ConnectivityManager. tether                        loge("Error tethering on " + intf);                        return false;                    }

ConnectivityManager.java

 public int tether(String iface) {        try {            return mService.tether(iface);//调用ConnectivityService.tether        } catch (RemoteException e) {            return TETHER_ERROR_SERVICE_UNAVAIL;        }    }


ConnectivityService.java

// javadocfrom interface    public inttether(String iface) {        enforceTetherChangePermission();         if(isTetheringSupported()) {            return mTethering.tether(iface);//调用Tethering.tether        } else{            returnConnectivityManager.TETHER_ERROR_UNSUPPORTED;        }    }

Tethering.java (\\192.168.80.102\tomchen\8680v6\android\frameworks\base\services\java\com\android\server\connectivity)

public int tether(String iface)//调用这个函数

sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED);//发送消息

classInitialState extendsState { @Override public voidenter() { setAvailable(true); setTethered(false); sendTetherStateChangedBroadcast(); } @Override public booleanprocessMessage(Message message) { if(DBG) Log.d(TAG, "InitialState.processMessage what="+ message.what); booleanretValue = true; switch(message.what) { case CMD_TETHER_REQUESTED://接收消息 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED, TetherInterfaceSM.this); transitionTo(mStartingState);//转到etherModeAliveState break; classTetherModeAliveState extendsTetherMasterUtilState { boolean mTryCell= !WAIT_FOR_NETWORK_TO_SETTLE; @Override public voidenter() { turnOnMasterTetherSettings(); // may transition us out//进入状态的时候会被调 mTryCell= !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass // or crazy tests cases will fail chooseUpstreamType(mTryCell); mTryCell= !mTryCell; }


设置wlan0的IP地址

frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.javamNwService.setInterfaceConfigsystem/netd/CommandListener.cppelse if (!strcmp(argv[1], "setcfg")){...ifc_set_addr...}system/core/libnetutils/ifc_utils.cint ifc_set_addr(const char *name, in_addr_t addr)



Lenovo K900中使能Hostapd的方法

echo "/system/etc/firmware/fw_bcmdhd_apsta.bin"  > /sys/module/bcmdhd/parameters/firmware_path

ifconfig wlan0 up

hostapd -dd hostapd.conf

/system/bin/dnsmasq --keep-in-foreground --no-resolv --no-poll --dhcp-option-force=43,ANDROID_METERED  --pid-file --dhcp-script=/system/bin/dhcp_announce --dhcp-range=2,5,1h

更多相关文章

  1. 使用android studio 配置搭建应用介绍
  2. Android~Fragment的替代方案
  3. Android(安卓)通过module进行开发
  4. Android应用开发笔记(12):Android应用的自动升级、更新模块的实现
  5. Android(安卓)MP3项目
  6. 在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程
  7. Android运行时
  8. Android系统编译及单模块编译简介
  9. android添加底层核心服务

随机推荐

  1. android中刷新Invalidate和postInvalidat
  2. 《第一行代码:Android(第2版)》,作者郭霖
  3. 解决eclipse里android无法关联源码办法
  4. Android屏幕完美适配最全攻略(最权威的官
  5. Android成功刷到beagle board ^_^
  6. 【Cocos2d-x】Cocos2d-x跨Android平台搭
  7. Android AsyncTask完全解析
  8. android TextView XML的一些属性
  9. 五大媒体播放器的Android
  10. GridView或ListView 中android:drawSelec