转载:

Android SoftAp支持 (一)

Android SoftAp支持 (二)

java测试用例

WifiAP将wifi作为AP

一、概要介绍

1.JAVA API部分

frameworks/base/wifi/java/android/net/wifi/WifiManager.java

public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {  mService.setWifiApEnabled(wifiConfig, enabled);}public int getWifiApState() {  return mService.getWifiApEnabledState();}public boolean isWifiApEnabled() {  return getWifiApState() == WIFI_AP_STATE_ENABLED;}public WifiConfiguration getWifiApConfiguration() {  return mService.getWifiApConfiguration();}public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {  mService.setWifiApConfiguration(wifiConfig);  return true;}

2.服务器端进程

frameworks/base/services/java/com/android/server/WifiService.java

public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {  mWifiStateMachine.setWifiApEnabled(wifiConfig, enabled);}public int getWifiApEnabledState() {  return mWifiStateMachine.syncGetWifiApState();}public WifiConfiguration getWifiApConfiguration() {  return mWifiStateMachine.syncGetWifiApConfiguration();}public void setWifiApConfiguration(WifiConfiguration wifiConfig) {  mWifiStateMachine.setWifiApConfiguration(wifiConfig);}
消息循环,状态机

frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java

public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enable) {  if (enable) {    sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0));    sendMessage(obtainMessage(CMD_START_AP, wifiConfig));  } else {    sendMessage(CMD_STOP_AP);    sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_DISABLED, 0));  }}public void setWifiApConfiguration(WifiConfiguration config) {  mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);}public WifiConfiguration syncGetWifiApConfiguration() {  Message resultMsg = mWifiApConfigChannel.sendMessageSynchronously(CMD_REQUEST_AP_CONFIG);  WifiConfiguration ret = (WifiConfiguration) resultMsg.obj;  resultMsg.recycle();  return ret;}public int syncGetWifiApState() {  return mWifiApState.get();}public String syncGetWifiApStateByName() {  switch (mWifiApState.get()) {    case WIFI_AP_STATE_DISABLING:      return "disabling";    case WIFI_AP_STATE_DISABLED:      return "disabled";    case WIFI_AP_STATE_ENABLING:      return "enabling";    case WIFI_AP_STATE_ENABLED:      return "enabled";    case WIFI_AP_STATE_FAILED:      return "failed";    default:      return "[invalid state]";  }}class SoftApStartingState extends State {  @Override  public void enter() {    if (DBG) log(getName() + "\n");    EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());    final Message message = getCurrentMessage();    if (message.what == CMD_START_AP) {      final WifiConfiguration config = (WifiConfiguration) message.obj;      if (config == null) {        mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);      } else {         mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);         startSoftApWithConfig(config);  //开启Ap功能      }    } else {       throw new RuntimeException("Illegal transition to SoftApStartingState: " + message);    }  }  @Override  public boolean processMessage(Message message) {    if (DBG) log(getName() + message.toString() + "\n");    switch(message.what) {      case WifiStateMachine.CMD_RESPONSE_AP_CONFIG:        WifiConfiguration config = (WifiConfiguration) message.obj;        if (config != null) {          startSoftApWithConfig(config); //开启Ap功能        } else {           loge("Softap config is null!");           sendMessage(CMD_START_AP_FAILURE);        }        break;      case CMD_START_AP_SUCCESS:        setWifiApState(WIFI_AP_STATE_ENABLED);        transitionTo(mSoftApStartedState);        break;    }  }}private void startSoftApWithConfig(final WifiConfiguration config) {  new Thread(new Runnable() {    public void run() {      try {        mNwService.startAccessPoint(config, mInterfaceName);      } catch (Exception e) {         loge("Exception in softap start " + e);         try {           mNwService.stopAccessPoint(mInterfaceName); //开启Ap功能           mNwService.startAccessPoint(config, mInterfaceName); //开启Ap功能         } catch (Exception e1) {            loge("Exception in softap re-start " + e1);            sendMessage(CMD_START_AP_FAILURE);            return;         }      }      if (DBG) log("Soft AP start successful");      sendMessage(CMD_START_AP_SUCCESS);    }  }).start();}
3.NMS进程

frameworks/base/services/java/com/android/server/NetworkManagementService.java

public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface) {  mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);  try {    wifiFirmwareReload(wlanIface, "AP");    if (wifiConfig == null) {      mConnector.execute("softap", "set", wlanIface);/*mConnector = new NativeDaemonConnector(                new NetdCallbackReceiver(), "netd", 10, NETD_TAG, 160);*/    } else {       mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,       getSecurityType(wifiConfig), wifiConfig.preSharedKey);    }    mConnector.execute("softap", "startap");  } catch (NativeDaemonConnectorException e) {     throw e.rethrowAsParcelableException();  }}
4.netd进程

system/netd/CommandListener.cpp

int CommandListener::SoftapCmd::runCommand(SocketClient *cli,                                        int argc, char **argv) {  if (!strcmp(argv[1], "startap")) {    rc = sSoftapCtrl->startSoftap();  } else if (!strcmp(argv[1], "stopap")) {     rc = sSoftapCtrl->stopSoftap();  } else if (!strcmp(argv[1], "fwreload")) {     rc = sSoftapCtrl->fwReloadSoftap(argc, argv);  } else if (!strcmp(argv[1], "clients")) {     rc = sSoftapCtrl->clientsSoftap(&retbuf);     if (!rc) {       cli->sendMsg(ResponseCode::CommandOkay, retbuf, false);       free(retbuf);       return 0;     }  } else if (!strcmp(argv[1], "status")) {     asprintf(&retbuf, "Softap service %s", (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped"));     cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false);     free(retbuf);     return 0;  } else if (!strcmp(argv[1], "set")) {     rc = sSoftapCtrl->setSoftap(argc, argv);  } else {     cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false);     return 0;  }}
system/netd/SoftapController.cpp
int SoftapController::setSoftap(int argc, char *argv[]) {  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 (!strcmp(argv[4], "open")) {       asprintf(&fbuf, "%s", wbuf);    }  } else {     asprintf(&fbuf, "%s", wbuf);  }  //static const char HOSTAPD_CONF_FILE[]    = "/data/misc/wifi/hostapd.conf";  //配置文件/data/misc/wifi/hostapd.conf  fd = open(HOSTAPD_CONF_FILE, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW, 0660);  if (write(fd, fbuf, strlen(fbuf)) < 0) {    ALOGE("Cannot write to \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));    ret = -1;  }}int SoftapController::startSoftap() {  if ((pid = fork()) < 0) {    ALOGE("fork failed (%s)", strerror(errno));    return -1;  }  if (!pid) {    ensure_entropy_file_exists();    if (execl("/system/bin/hostapd", "/system/bin/hostapd",                  "-e", WIFI_ENTROPY_FILE,                  HOSTAPD_CONF_FILE, (char *) NULL)) {      ALOGE("execl failed (%s)", strerror(errno));    }    ALOGE("Should never get here!");    return -1;  } else {     mPid = pid;     ALOGD("Softap startap - Ok");     usleep(AP_BSS_START_DELAY);  }}

补充:

dnsmasq及dhcp相关

system/netd/TetherController.cpp

iptables相关

system/netd/NetdConstants.cpp

5.hostapd进程

external/wpa_supplicant_8/hostapd/main.c

int main(int argc, char *argv[]){}

external/wpa_supplicant_8/src/ap/hostapd.c

鉴权相关

external/wpa_supplicant_8/hostapd/src/ap/wpa_auth.c

二、测试

基于NT667-Android4.2平台

1.加载wifi驱动

uid=0 gid=0@android:/system/lib/modules # isnmod 8812au.ko

2.运行AP功能

hostapd -e /data/misc/wifi/entropy.bin /data/misc/wifi/hostapd.conf

vi /data/misc/wifi/hostapd.conf

interface=wlan0driver=nl80211ctrl_interface=/data/misc/wifi/hostapdssid=TanKaiSoftAP#wpa_passphrase=0123456789channel=6ieee80211n=1wpa=0#wpa=2rsn_pairwise=CCMPwpa_psk=20c7dff358c6481bd7278907adb988b8ca7217bc407674b18a59b5c7f81bcc09

至此,可以搜索到SofrAP热点并连接上。

3.可以搜索到TanKaiSoftAP热点,并链接;卡在了获取IP地址这里

设置无线网卡IP

ifconfig wlan0 192.168.100.1 netmask 255.255.255.0

启动DHCP

dnsmasq --no-daemon --no-resolv --no-poll --dhcp-range=192.168.100.100,192.168.100.200,100h

当然也可以把相关配置写成文件再执行dnsmasq --conf-file=/*path*/dnsmasq.conf
至此,可以搜索到SoftAP并获取IP地址;但不能上外网。
5.可以获取IP地址,但不能上网;iptables设置

echo 1 > /proc/sys/net/ipv4/ip_forwardiptables -A FORWARD -i wlap0 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -i wlap0 -o eth0 -j ACCEPT iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

至此,软AP功能调通;手机连接具有软AP功能的电视可以正常访问外网。

三、wext驱动实现方式时的项目问题

我们使用的MTK平台SoftAP实现方式非Android标准;不使用hostapd,而且wifi驱动不是nl80211而是wext模式

WIFI的Linux驱动部分wext和nl80211

转载:

MTK启动无线热点的过程

1.驱动加载

cd /system/lib/modulesinsmod mt7601Uap.koifconfig ra0 10.10.10.1

配置文件

/system/etc/Wireless/RT2870AP/RT2870AP.dat

卸载驱动

ifconfig ra0 downrmmod mt7601Uap.ko

2.调试netd--ndc

转载:

Android 4.1 Netd详细分析(一)概述与应用实例

ndc是Android为Netd提供的一个测试工具。其主要功能有:

监视Netd中发生的事情。

支持通过命令行发送命令给Netd去执行。

ndc softap set ra0 TankaiMtk closendc softap startapdnsmasq --no-daemon --no-resolv --no-poll --dhcp-range=10.10.10.100,10.10.10.200,100hecho 1 > /proc/sys/net/ipv4/ip_forwardiptables -A FORWARD -i ra0 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -i ra0 -o eth0 -j ACCEPT iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADEndc softap stopapifconfig ra0 down

3.桥接

brctl addbr br0brctl addif br0 eth0brctl addif br0 ra0ifconfig eth0 0.0.0.0ifconfig ra0 0.0.0.0ip link set br0 upip addr add 192.168.5.234/24 brd + dev br0ip route add default via 192.168.5.254
移植brctl:

bridge-utils

运行报错:

add bridge failed: Package not installed

内核添加bridge支持:

linux-3.0/net/bridge/

make menuconfig

Networking support->Networking options->802.1d Ethernet Bridging








更多相关文章

  1. 在android下获取有线和无线IP地址的方法,经测试可用
  2. 圆角android
  3. framework——应用进程启动流程
  4. Android(安卓)Property System
  5. 搜集的android资源
  6. Android(安卓)ListView长按弹出CheckBox,实现全选,反选,批量删除功
  7. Android中实现输入图片地址浏览图片操作
  8. 整理 酷炫 Android(安卓)开源UI框架 刷新

随机推荐

  1. DNS解析域名:发现域名和IP不一致,访问了该
  2. Condition实现等待、唤醒
  3. 今年写技术博文的几点思考
  4. Android(安卓)数据存储---SharedPreferen
  5. java中的编码转化方式都有哪些?(大厂高频面
  6. Java并发原子类有哪些?如何使用?
  7. Eclipse中android插件的安装
  8. 我要改名字了
  9. Executor 如何使用?
  10. 文章汇总