其实现在已经到了android-9了。但是这篇文档写的是android-8而且android-9的变化不是非常大,所以也懒得修改。
老架构,网上找的。8.0以后不一样了。
1. wifi.c没了,所有驱动相关的操作都通过treble架构移交厂商了
2.IPC方式变了,之前是socket与supplicant通信,现在是HIDL抽象的binder方式
3.扫描功能从supplicant中转移到android原生实现。
4.wpa_supplicant.conf去除,保存ap使用wificonfig.xml由android原生管理。(热点也是)
主要功能:
次要功能:
主要功能:
次要功能:
UI相关
主要功能:
次要功能:
谷歌在新发布的android-O平台上对framework进行了大量的更改,从wifi部分来看,主要体现在两个部分:
在android-O之前,framework上一共维护了20个状态.其中softAp相关的状态未列出.Android-O上删除了加载驱动相关的状态,将这部分实现迁移到C++部分.驱动加载成功后,会启动wpa_supplicant.图画的不好,凑合看吧
注:
红色部分为在android-O中删除的状态,下面会说这部分的处理在O中的变化,并且讨论变化的原因.
这部分的状态切换个刚开始没有看懂,因为ConnectModeState没有被显示的切换,调查发现状态机在切换过程中已经执行过ConnectModeState中的Enter和EXT,并且相应的在子状态DisconnectedState中无法处理的,会交给ConnectModeState(父状态)处理.
代码调用流程:
InitialState:
setOperationalMode->InitialState::ProcessMessage(CMD_START_SUPPLICANT)
->setupForClientMode()
->enableSupplicant()
->startMonitoring()
->transitionTo(mSupplicantStartingState)
加载驱动,启动wpa_supplicant,启动Monitor...
SupplicantStartingState:
setOperationalMode->InitialState::ProcessMessage(CMD_START_SUPPLICANT)
->setupForClientMode()
->enableSupplicant()
->startMonitoring()
->transitionTo(mSupplicantStartingState)
设置mac地址,初始化wps(Wi-Fi Protected Setup),发送wpa_supplicant状态变化广播...
SupplicantStartedState:
Enter()->setWifiState(WIFI_STATE_ENABLING)
->transitionTo(mDisconnectedState)
->setPowerSave();
设置相关参数,切换至DisconnectedState进行定期扫描...
DisconnectedState:
Enter()->processMessage(CMD_NO_NETWORKS_PERIODIC_SCAN)
->startScan()
->SupplicantStartedState::processMessage(CMD_START_SCAN)
->checkOrDeferScanAllowed()
->processMessage(CMD_START_SCAN)
->handleScanRequest()
->startScanNative()
进行定期扫描操作...
O的变化:
个人认为android-O的主要变化在于加载驱动这部分.按照逻辑,wifi启动先后顺序为:WifiService->load driver->start wpa_supplicant。所以认定driver的启动必然在wpa_supplicant启动之前完成.
setupForClientMode()->setupDriverForClientMode()
->Server::createClientInterface()
->SetupInterface()
根据上图,wifi在链接过程中先切换到ConnectModeState处理连接相关的消息,后直接切换至ObtainingIpState启动DHCP,后切换至同级状态ConnectedState.表示连接已经建立.
代码调用流程:
DisconnectedState:
connect->ConnectModeState::ProcessMessage(CONNECT_NETWORK)
->addOrUpdateNetwork()
->connectToUserSelectNetwork()
->getConfiguredNetwork()
->enableNetwork()
->startConnectToNetwork()
->ConnectModeState::ProcessMessage(CMD_START_CONNECT)
->connectToNetwork()
->ConnectModeState::ProcessMessage(NETWORK_CONNECTION_EVENT)
->sendNetworkStateChangeBroadcast()
->transitionTo(mObtainingIpState)
触发add_network,set_network,enable_network等一系列命令...
ObtainingIpState:
L2ConnectedState::Enter()->ObtainingIpState::Enter()
->StoppedState::ProcessMessage(CMD_START)
->StartedState::Enter()
->transitionTo(mRunningState)
->startIPv4()
->processMessage(CMD_START_DHCP)
->L2ConnectedState::ProcessMessage(
CMD_IP_CONFIGURATION_SUCCESSFUL)
->handleIPv4Success()
->transitionTo(mConnectedState)
L2已经链接成功,接下来启动DHCP分配IP地址.成功后切换至ConnectedState
O的变化:
根据对android-O的代码研究,google改变了wifi的连接方式:
传统方式:
现在的方式(目前的连接方式和之前的方式的差别):
Framework与wpa_supplicant直接的通信方式也有所变化.如下所示:
在之前的android版本中,framework和wpa_supplicant之间是通过socket进行通信而不是现在的binder通信方式.
个人认为这样修改有如下好处:
在ConnectedState下收到断开链接请求,交由父状态L2ConnectedState处理并切换至同级别状态DisconnectingState,在进入enter函数时发送延时消息,收到后切换至DisconnectedState.
代码调用流程:
L2ConnectedState:
disconnect->L2ConnectedState::ProcessMessage(CMD_DISCONNECT)
->disconnect()
->mSupplicantStaIfaceHal.disconnect()
->transitionTo(mDisconnectingState)
断开L2链接,切换至DisconnectingState.
DisconnectingState:
DisconnectingState::Enter()->ProcessMessage(CMD_DISCONNECTING_WATCHDOG_TIMER)
->handleNetworkDisconnect()
->stopRssiMonitoringOffload()
->stopIpManager()
->clearLinkProperties()
->transitionTo(mDisconnectedState);
停止RSSI,停止IPMananger,回收底层资源并切换到DisconnectedState.
根据结构所示, firmware部分完成了硬件射频的工作.根据调查,驱动程序主要是负责传递消息,将上层发送的消息和数据封装为固件消息发送给固件并反馈结果.此部分参考了broadcom的实现。
Linux设备驱动分为:字符设备,块设备,网络设备. 在WLAN模块中,wifi自然属于网络设备之列.
下图为网络设备在Linux系统中的层次结构.
在让人耳熟能详的TCP/IP协议栈之下就是网络设备的地盘.这里首先说明一下net_device中几个重要的属性.
struct net_device
{
//用于存放网络设备的设备名称;
char name[IFNAMSIZ]; --> wlan0
//网络设备的接口索引值,独一无二的网络设备标识符;
int ifindex; ---> ioctl的索引
//网络设备接口的最大传输单元;
unsigned mtu; --->1500
//硬件接口头长度;
unsigned short hard_header_len;
//网络设备接口的MAC地址;
unsigned char *dev_addr;
}
在android-O的最新架构中,scan命令不再由wpa_supplicant发送给driver,而是直由上层的netlinkMananger发送,这样省略了通过wpa这个中间件.个人理解google这次修改的原因是因为scan命令是一个十分频繁并且要求实时反馈的命令,总是通过wpa_supplicant发送该信息在内存和时间上都没有好处.并且scan命令不同于assoc, disassoc, reassoc等需要封装完整的数据包给driver,所以scan命令也具备从wpa_supplicant中独立出来的条件.
作为网络设备, 最重要的功能就是保证数据收发的稳定和高速。所有网络设备的数据收发如下
下图简要说明了数据收发过程中的代码调用.
DHCP为ipv4的NAT地址控制提供了有效的帮助,使得局域网内的ip地址可以精确的分配。
上图为DHCP的架构,其中还有ip地址租赁延长的消息没有体现出来。这里先不赘述。
这里不介绍wpa_supplicant的内容,出于一下原因:
1. Wpa_supplicant代码体积大, 但是很少出现问题
2. Wpa_supplicant是开源项目,可以从网上得到资料
3. 深入理解android wifi模块这本书对wpa_supplicant进行了系统的讲解.
Wifi的内容很多,不仅设计了802.11协议还夹杂了各类rfc安全协议.所以这里仅仅介绍STA功能中简单的代码架构,具体的每一处代码还需要继续研究.此外,在驱动程序中可以看到,数据收发数据无差别的适应方式应该涵盖了STA,P2P,SoftAp.而前期的交互中,SoftAp部分代码基本与STA和P2P独立, 而STA和P2P之间有着相近的函数调用.
Android-O的变化可以看出google在接下来的版本中会继续将framework中java部分的实现向C++迁移,同时java8的特性也在这一版本中体现.不仅体现了google对android不遗余力的优化.
http://weiguozhihui.blog.51cto.com/3060615/1584894
深入理解android WiFi、NFC、GPS卷
802.11权威指南