`
k_lb
  • 浏览: 821583 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论
  • kitleer: 据我所知,国内有款ETL调度监控工具TaskCTL,支持ket ...
    kettle调度

settings里的 wifi流程

 
阅读更多
Wifi启动流程

(1)使能Wifi

要想使用Wifi模块,必须首先使能Wifi,当你第一次按下Wifi使能按钮时,WirelessSettings会实例化一个WifiEnabler对象,实例化代码如下:

packages/apps/settings/src/com/android/settings/WirelessSettings.java

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

……

CheckBoxPreferencewifi = (CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI);

mWifiEnabler= new WifiEnabler(this, wifi);

……

}

WifiEnabler类的定义大致如下,它实现了一个监听接口,当WifiEnabler对象被初始化后,它监听到你按键的动作,会调用响应函数 onPreferenceChange(),这个函数会调用WifiManager的setWifiEnabled()函数。

public class WifiEnabler implementsPreference.OnPreferenceChangeListener {

……

public boolean onPreferenceChange(Preference preference,Object value) {

booleanenable = (Boolean) value;

……

if (mWifiManager.setWifiEnabled(enable) ) {

mCheckBox.setEnabled(false);

……

}

……

}

我们都知道Wifimanager只是个服务代理,所以它会调用WifiService的setWifiEnabled()函数,而这个函数会调用 sendEnableMessage()函数,了解android消息处理机制的都知道,这个函数最终会给自己发送一个 MESSAGE_ENABLE_WIFI的消息,被WifiService里面定义的handlermessage()函数处理,会调用 setWifiEnabledBlocking()函数。下面是调用流程:

mWifiEnabler.onpreferencechange()=>mWifiManage.setWifienabled()=>mWifiService.setWifiEnabled()=>mWifiService.sendEnableMessage()=>mWifiService.handleMessage()=>mWifiService.setWifiEnabledBlocking().

在setWifiEnabledBlocking()函数中主要做如下工作:加载Wifi驱动,启动wpa_supplicant,注册广播接收器,启动WifiThread监听线程。代码如下:

……

if (enable) {

if (!mWifiStateTracker.loadDriver()) {

Slog.e(TAG, "Failed toload Wi-Fi driver.");

setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);

return false;

}

if (!mWifiStateTracker.startSupplicant()) {

mWifiStateTracker.unloadDriver();

Slog.e(TAG, "Failed tostart supplicant daemon.");

setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);

return false;

}

registerForBroadcasts();

mWifiStateTracker.startEventLoop();

……

至此,Wifi使能结束,自动进入扫描阶段。

(2) 扫描AP

当驱动加载成功后,如果配置文件的AP_SCAN = 1,扫描会自动开始,WifiMonitor将会从supplicant收到一个消息EVENT_DRIVER_STATE_CHANGED,调用 handleDriverEvent(),然后调用mWifiStateTracker.notifyDriverStarted(),该函数向消息队列添加EVENT_DRIVER_STATE_CHANGED,handlermessage()函数处理消息时调用scan()函数,并通过 WifiNative将扫描命令发送到wpa_supplicant。

Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java

private void handleDriverEvent(Stringstate) {

if (state == null) {

return;

}

if (state.equals("STOPPED")) {

mWifiStateTracker.notifyDriverStopped();

} else if (state.equals("STARTED")) {

mWifiStateTracker.notifyDriverStarted();

} else if (state.equals("HANGED")) {

mWifiStateTracker.notifyDriverHung();

}

}

Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

case EVENT_DRIVER_STATE_CHANGED:

switch(msg.arg1) {

case DRIVER_STARTED :

/**

*Set the number of allowed radio channels according

*to the system setting, since it gets reset by the

*driver upon changing to the STARTED state.

*/

setNumAllowedChannels();

synchronized (this) {

if (mRunState == RUN_STATE_STARTING) {

mRunState = RUN_STATE_RUNNING;

if (!mIsScanOnly) {

reconnectCommand();

} else {

// In somesituations, supplicant needs to be kickstarted to

// start thebackground scanning

scan(true);

}

}

}

break;

上面是启动Wifi时,自动进行的AP的扫描,用户当然也可以手动扫描AP,这部分实现在WifiService里面,WifiService通过startScan()接口函数发送扫描命令到supplicant。

Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

public boolean startScan(booleanforceActive) {

enforceChangePermission();

switch (mWifiStateTracker.getSupplicantState()) {

case DISCONNECTED:

case INACTIVE:

case SCANNING:

case DORMANT:

break;

default:

mWifiStateTracker.setScanResultHandling(

WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY);

break;

}

return mWifiStateTracker.scan(forceActive);

}

然后下面的流程同上面的自动扫描,我们来分析一下手动扫描从哪里开始的。我们应该知道手动扫描是通过菜单键的扫描键来响应的,而响应该动作的应该是 WifiSettings类中Scanner类的handlerMessage()函数,它调用WifiManager的 startScanActive(),这才调用WifiService的startScan()。

packages/apps/Settings/src/com/android/settings/wifiwifisettings.java

public boolean onCreateOptionsMenu(Menu menu) {

menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan)

.setIcon(R.drawable.ic_menu_scan_network);

menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)

.setIcon(android.R.drawable.ic_menu_manage);

return super.onCreateOptionsMenu(menu);

}

当按下菜单键时,WifiSettings就会调用这个函数绘制菜单。如果选择扫描按钮,WifiSettings会调用onOptionsItemSelected()。

packages/apps/Settings/src/com/android/settings/wifiwifisettings.java

public booleanonOptionsItemSelected(MenuItem item) {

switch (item.getItemId()) {

case MENU_ID_SCAN:

if(mWifiManager.isWifiEnabled()) {

mScanner.resume();

}

return true;

case MENU_ID_ADVANCED:

startActivity(new Intent(this,AdvancedSettings.class));

return true;

}

return super.onOptionsItemSelected(item);

}

private class Scanner extends Handler {

private int mRetry = 0;

void resume() {

if (!hasMessages(0) ) {

sendEmptyMessage(0);

}

}

void pause() {

mRetry = 0;

mAccessPoints.setProgress(false);

removeMessages(0);

}

@Override

public void handleMessage(Message message) {

if (mWifiManager.startScanActive() ){

mRetry = 0;

} else if (++mRetry >= 3) {

mRetry = 0;

Toast.makeText(WifiSettings.this, R.string.wifi_fail_to_scan,

Toast.LENGTH_LONG).show();

return;

}

mAccessPoints.setProgress(mRetry != 0);

sendEmptyMessageDelayed(0, 6000);

}

}

这里的mWifiManager.startScanActive()就会调用WifiService里的startScan()函数,下面的流程和上面的一样,这里不赘述。

当supplicant完成了这个扫描命令后,它会发送一个消息给上层,提醒他们扫描已经完成,WifiMonitor会接收到这消息,然后再发送给WifiStateTracker。

Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java

void handleEvent(int event, String remainder) {

switch (event) {

caseDISCONNECTED:

handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED,remainder);

break;

case CONNECTED:

handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder);

break;

case SCAN_RESULTS:

mWifiStateTracker.notifyScanResultsAvailable();

break;

case UNKNOWN:

break;

}

}

WifiStateTracker将会广播SCAN_RESULTS_AVAILABLE_ACTION消息:

Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

public voidhandleMessage(Message msg) {

Intent intent;

……

case EVENT_SCAN_RESULTS_AVAILABLE:

if(ActivityManagerNative.isSystemReady()) {

mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

}

sendScanResultsAvailable();

/**

* On receiving the first scanresults after connecting to

* the supplicant, switch scanmode over to passive.

*/

setScanMode(false);

break;

……

由于WifiSettings类注册了intent,能够处理SCAN_RESULTS_AVAILABLE_ACTION消息,它会调用handleEvent(),调用流程如下所示。

WifiSettings.handleEvent() =>WifiSettings.updateAccessPoints() => mWifiManager.getScanResults() => mService.getScanResults()=> mWifiStateTracker.scanResults() => WifiNative.scanResultsCommand()……

将获取AP列表的命令发送到supplicant,然后supplicant通过Socket发送扫描结果,由上层接收并显示。这和前面的消息获取流程基本相同。

(3)配置,连接AP

当用户选择一个活跃的AP时,WifiSettings响应打开一个对话框来配置AP,比如加密方法和连接AP的验证模式。配置好AP后,WifiService添加或更新网络连接到特定的AP。

packages/apps/settings/src/com/android/settings/wifi/WifiSetttings.java

public booleanonPreferenceTreeClick(PreferenceScreen screen, Preference preference) {

if (preference instanceof AccessPoint) {

mSelected = (AccessPoint) preference;

showDialog(mSelected, false);

} else if (preference == mAddNetwork) {

mSelected = null;

showDialog(null, true);

} else if (preference == mNotifyOpenNetworks) {

Secure.putInt(getContentResolver(),

Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,

mNotifyOpenNetworks.isChecked() ? 1 : 0);

} else {

return super.onPreferenceTreeClick(screen, preference);

}

return true;

}

配置好以后,当按下“Connect Press”时,WifiSettings通过发送LIST_NETWORK命令到supplicant来检查该网络是否配置。如果没有该网络或没有配置它,WifiService调用addorUpdateNetwork()函数来添加或更新网络,然后发送命令给supplicant,连接到这个网络。下面是从响应连接按钮到WifiService发送连接命令的代码:

packages/apps/settings/src/com/android/settings/wifi/WifiSetttings.java

public void onClick(DialogInterfacedialogInterface, int button) {

if (button == WifiDialog.BUTTON_FORGET && mSelected != null) {

forget(mSelected.networkId);

} else if (button == WifiDialog.BUTTON_SUBMIT && mDialog !=null) {

WifiConfiguration config = mDialog.getConfig();

if (config == null) {

if (mSelected != null&& !requireKeyStore(mSelected.getConfig())) {

connect(mSelected.networkId);

}

} else if (config.networkId != -1) {

if (mSelected != null) {

mWifiManager.updateNetwork(config);

saveNetworks();

}

} else {

int networkId =mWifiManager.addNetwork(config);

if (networkId != -1) {

mWifiManager.enableNetwork(networkId, false);

config.networkId =networkId;

if (mDialog.edit || requireKeyStore(config)){

saveNetworks();

} else {

connect(networkId);

}

}

}

}

}

Frameworks\base\wifi\java\android\net\wifi\WifiManager.java

public intupdateNetwork(WifiConfiguration config) {

if(config == null || config.networkId < 0) {

return -1;

}

return addOrUpdateNetwork(config);

}

private intaddOrUpdateNetwork(WifiConfiguration config) {

try {

return mService.addOrUpdateNetwork(config) ;

} catch (RemoteException e) {

return -1;

}

}

WifiService.addOrUpdateNetwork()通过调用mWifiStateTracker.setNetworkVariable()将连接命令发送到Wpa_supplicant。

(4)获取IP地址

当连接到supplicant后,WifiMonitor就会通知WifiStateTracker。

Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java

Public void Run(){

if (connectToSupplicant()) {

// Send a message indicatingthat it is now possible to send commands

// to the supplicant

mWifiStateTracker.notifySupplicantConnection();

} else {

mWifiStateTracker.notifySupplicantLost();

return;

}

……

}

WifiStateTracker发送EVENT_SUPPLICANT_CONNECTION消息到消息队列,这个消息有自己的handlermessage()函数处理,它会启动一个DHCP线程,而这个线程会一直等待一个消息事件,来启动DHCP协议分配IP地址。

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

void notifySupplicantConnection() {

sendEmptyMessage(EVENT_SUPPLICANT_CONNECTION);

}

public void handleMessage(Message msg) {

Intent intent;

switch (msg.what) {

case EVENT_SUPPLICANT_CONNECTION:

……

HandlerThread dhcpThread = newHandlerThread("DHCP Handler Thread");

dhcpThread.start();

mDhcpTarget = newDhcpHandler(dhcpThread.getLooper(), this);

……

……

}

当Wpa_supplicant连接到AP后,它会发送一个消息给上层来通知连接成功,WifiMonitor会接受到这个消息并上报给WifiStateTracker。

Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java

void handleEvent(int event, String remainder) {

switch (event) {

case DISCONNECTED:

handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED,remainder);

break;

case CONNECTED:

handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder);

break;

……

}

private voidhandleNetworkStateChange(NetworkInfo.DetailedState newState, String data) {

StringBSSID = null;

intnetworkId = -1;

if(newState == NetworkInfo.DetailedState.CONNECTED) {

Matcher match = mConnectedEventPattern.matcher(data);

if(!match.find()) {

if (Config.LOGD) Log.d(TAG, "Could not find BSSID in CONNECTEDevent string");

}else {

BSSID = match.group(1);

try {

networkId = Integer.parseInt(match.group(2));

} catch (NumberFormatException e) {

networkId = -1;

}

}

}

mWifiStateTracker.notifyStateChange(newState,BSSID, networkId);

}

void notifyStateChange(DetailedState newState, StringBSSID, int networkId) {

Messagemsg = Message.obtain(

this, EVENT_NETWORK_STATE_CHANGED,

newNetworkStateChangeResult(newState, BSSID, networkId));

msg.sendToTarget();

}

caseEVENT_NETWORK_STATE_CHANGED:

……

configureInterface();

……

private void configureInterface() {

checkPollTimer();

mLastSignalLevel = -1;

if(!mUseStaticIp) { //使用DHCP线程动态IP

if(!mHaveIpAddress && !mObtainingIpAddress) {

mObtainingIpAddress = true;

//发送启动DHCP线程获取IP

mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);

}

} else { //使用静态IP,IP信息从mDhcpInfo中获取

intevent;

if(NetworkUtils.configureInterface(mInterfaceName, mDhcpInfo)) {

mHaveIpAddress = true;

event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;

if (LOCAL_LOGD) Log.v(TAG, "Static IP configurationsucceeded");

}else {

mHaveIpAddress = false;

event = EVENT_INTERFACE_CONFIGURATION_FAILED;

if (LOCAL_LOGD) Log.v(TAG, "Static IP configuration failed");

}

sendEmptyMessage(event); //发送IP获得成功消息事件

}

}

DhcpThread获取EVENT_DHCP_START消息事件后,调用handleMessage()函数,启动DHCP获取IP地址的服务。

public void handleMessage(Message msg) {

intevent;

switch (msg.what) {

case EVENT_DHCP_START:

……

Log.d(TAG, "DhcpHandler: DHCP requeststarted");

//启动一个DHCPclient的精灵进程,为mInterfaceName请求分配一个IP地//址

if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo) ) {

event= EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;

if(LOCAL_LOGD) Log.v(TAG, "DhcpHandler: DHCP request succeeded");

} else {

event= EVENT_INTERFACE_CONFIGURATION_FAILED;

Log.i(TAG,"DhcpHandler: DHCP request failed: " +

NetworkUtils.getDhcpError());

}

……

}

这里调用了一个NetworkUtils.runDhcp()函数,NetworkUtils类是一个网络服务的辅助类,它主要定义了一些本地接口,这些接口会通过他们的JNI层android_net_NetUtils.cpp文件和DHCP client通信,并获取IP地址。

至此,IP地址获取完毕,Wifi启动流程结束。

分享到:
评论

相关推荐

    android wifi流程分析

    以下是对Android WiFi流程的详细分析: 1. **应用程序层**: - WIFI Settings应用程序位于`packages/apps/Settings/src/com/android/settings/wifi/`,提供了用户界面,让用户可以开启、关闭以及管理WiFi连接。 2...

    Android wifi流程

    ### Android WiFi架构与调用流程详解 #### 一、Android WiFi架构概览 在深入探讨Android WiFi的具体调用流程之前,我们首先需要了解其整体架构。Android系统的WiFi功能主要通过多层架构实现,包括Java应用层、Java...

    wifi流程分析[参考].pdf

    WiFi流程分析是软件开发中的一个重要环节,特别是在移动设备如Android智能手机和平板电脑中。这个过程涉及到系统的多个层次,包括应用程序层、系统服务层、JNI(Java Native Interface)以及硬件驱动层。以下是对...

    wifi流程分析.pdf

    1. **Java包中的Settings**:文档中提到了`packages/apps/Settings/src/com/android/settings/wifi`路径,表明Wi-Fi设置界面是在Android系统设置应用中实现的。这是一个用户界面,允许用户开启/关闭Wi-Fi,搜索和...

    Wifi android 框架 流程

    安卓Wifi框架流程详解 Wifi android 框架流程是一个复杂的过程,涉及到多个组件和模块。下面将详细解释Wifi android 框架流程的各个组件和模块。 一、Wifi 基本架构 Wifi_android 框架流程的基础架构包括用户空间...

    wifi方案流程.docx

    6. **应用层**:如Settings应用等,它们直接与WiFi服务交互,实现WiFi的开启、关闭、连接和管理等功能。 在系统启动过程中,WiFi服务是在SystemServer中启动的,相关代码位于`frameworks\base\services\java\...

    Android WIFI架构和控制流程

    - `packages/apps/Settings/src/com/android/settings/wifi/`:这部分是WIFI设置应用程序的源代码,用户可以通过这个应用来管理WIFI连接。 2. **驱动模块**:`wlan.ko`是WIFI驱动模块,它通过`wireless_ext`接口与...

    android wifi+蓝牙的工作流程

    ### Android上的WiFi与蓝牙工作流程详解 #### 一、引言 随着移动互联网技术的快速发展,智能手机已成为我们日常生活中不可或缺的一部分。其中,Android系统作为全球最大的移动操作系统之一,其内部的无线通信技术如...

    AndroidWIFI架构和控制流程.pdf

    Android WiFi架构和控制流程涉及到多个层次的组件和交互机制,主要分为用户空间程序、硬件抽象层、JNI接口、Java API以及驱动程序等部分。以下是详细的知识点解释: 1. **WiFi用户空间程序和库**: - `external/...

    android wifi框架

    `packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java`是Android系统中管理WiFi设置的核心类。此文件包含了多个类的变量定义,旨在处理各种WiFi相关的操作与事件。 - **`mFilter`**:`...

    wifi模块分析

    - **流程**: 在Settings中打开WiFi的具体流程如下: - 用户在Settings中选择打开WiFi。 - 触发事件传递给`WifiManager`。 - `WifiManager`调用`setWifiEnabled(true)`方法。 - 最终调用到`WifiService`中的相应...

    Android__WIFI模块分析

    - **Wifi Application**:主要位于`packages/apps/Settings/src/com/android/settings/wifi`,提供用户界面和交互逻辑。 - **Wifi Framework**:包含在`frameworks/base/wifi/java/android/net/wifi`和`frameworks/...

    win7 wifi热点

    内容部分提供了一些关键的命令行指令以及实现虚拟WiFi热点的基本流程: 1. **开启虚拟WiFi适配器**:首先,需要通过命令行工具启用虚拟WiFi适配器。这可以通过输入以下命令实现: ``` netsh wlan set ...

    android 数据业务流程分析

    当用户在“Settings---&gt;Mobilenetworks---&gt;Dataenabled”界面操作开启或关闭数据业务时,系统会触发一系列事件,并通过不同层次间的通信完成整个流程。这里涉及的关键层次包括: - **Telephony Frameworks层**:...

    斑马条码打印机和便携式打印机WIFI或蓝牙安桌源码

    `build.gradle`和`settings.gradle`文件定义了项目的构建规则和依赖项,其中可能包含了对Zebra SDK的引用。 `build`目录存储的是编译过程中生成的中间文件和最终的APK包。`.idea`目录包含了IntelliJ IDEA或Android ...

    Iphone12+PioneerX 测试流程介绍_202105(1).pptx

    4. 端口调试:在手机的Carrier Settings中调整Baseband Manager的Logging Settings至Mode,确保Service Center显示已连接。 5. 软件连接:在Pioneer X中点击自动检测,添加手机型号,然后连接并编辑测试计划。 ...

    intent示例

    在Android开发中,Intent是一种非常重要...通过实践和理解Intent的工作原理,开发者可以更灵活地控制应用程序的行为和流程。在实际开发中,Intent还常用于启动服务、广播接收器等场景,是Android开发中的核心概念之一。

    SystemIntentExample:如何打开手机设置(网络数据漫游设置或wifi设置)。 使用 Android Studio 完成

    intent.setAction("android.settings.WIFI_SETTINGS"); ``` 对于数据漫游设置: ```java intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setAction("android.provider.Settings.ACTION_DATA_ROAMING_...

    简单热点创建.zip

    3. **Android Settings应用**:在`packages/apps/Settings`目录下,热点设置界面的源码可以找到,包括开关按钮、配置选项等。当用户在设置中开启热点时,会调用`WifiP2pManager`的相关方法。 创建热点的流程大致...

    android系统原理及开发要点详解

     11.1.4 Settings中的WiFi设置 265  11.1.5 WiFi工作流程实例 265  11.2 蓝牙部分 267  11.2.1 蓝牙基本架构 268  11.2.2 蓝牙用户空间库bluez 269  11.2.3 bluez适配层 272  11.2.4 蓝牙的JNI和Java部分 272...

Global site tag (gtag.js) - Google Analytics