上文讲到WIFI的启动流程,当然接着便扫描热点(AP),然后显示扫描到的AP、配置AP(填写IP地址等信息)、连接AP、获取IP地址、最后就是想要的上网咯!
一、扫描热点(AP)
上文启动WIFI成功后:// Success!
setWifiEnabledState(eventualWifiState, uid);
private void setWifiEnabledState(int wifiState, int uid) {
// Broadcast
final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
}
当使能成功后,会广播发送WIFI_STATE_CHANGED_ACTION 这个Intent 通知外界WIFI已经成功使能了。WifiLayer 创建的时候就会向Android 注册接收WIFI_STATE_CHANGED_ACTION,因此它会收到该Intent,从而开始扫描。
WifiSetting.java:
protected void onCreate(Bundle savedInstanceState) {
mWifiLayer.onCreate();
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
WifiLayer.java:
public void onCreate() {
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
}
public void onResume() {
mContext.registerReceiver(mReceiver, mIntentFilter);
if (isWifiEnabled()) {
// Kick start the continual scan
queueContinuousScan();
}
}
以上就是WifiLayer.java注册接收的部分事件。接收部分事件处理有:
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
handleNetworkStateChanged(
(NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO),
intent.getStringExtra(WifiManager.EXTRA_BSSID));
} else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
handleScanResultsAvailable();
} ……
else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN));
}
}
};
从可接受的事件看,当WIFI_STATE_CHANGED_ACTION时,对应的处理函数有:
handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN));
private void handleWifiStateChanged(int wifiState) {
attemptScan();
…………
}
public void attemptScan() {
if (!mWifiManager.startScanActive()) {
postAttemptScan();
}
}
WifiManager.java:
public boolean startScanActive() {
return mService.startScan(true);
}
-------AIDL-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
WifiService.java:
public boolean startScan(boolean forceActive) {
…………
return WifiNative.scanCommand(forceActive);
}
---------JNI---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
android_net_wifi_wifi.cpp:
{ "scanCommand", "(Z)Z", (void*) android_net_wifi_scanCommand },
static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz, jboolean forceActive)
{
…………
result = doBooleanCommand("SCAN", "OK");
}
static jboolean doBooleanCommand(const char *cmd, const char *expect)
{
if (doCommand(cmd, reply, sizeof(reply)) != 0) {
return (jboolean)JNI_FALSE;
}
}
static int doCommand(const char *cmd, char *replybuf, int replybuflen)
{
if (::wifi_command(cmd, replybuf, &reply_len) != 0)
return -1;
…………
}
-------HAL------------------------------------------------------------------------------------------------------------------------------------------------------------------------
wifi.c:
int wifi_command(const char *command, char *reply, size_t *reply_len)
{
return wifi_send_command(ctrl_conn, command, reply, reply_len);
}
int wifi_send_command(struct wpa_ctrl *ctrl, const char *cmd, char *reply, size_t *reply_len)
{
ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), reply, reply_len, NULL);
…………
}
wpa_ctrl.c:
int wpa_ctrl_request()在wpa_ctrl.c中其实就是执行SCAN命令。
二、显示扫描的AP
当扫描成后,WifiMonitor 中的MonitorThread 会被执行来出来这个事件:
void handleEvent(int event, String remainder) {
switch (event) {
case SCAN_RESULTS:
mWifiStateTracker.notifyScanResultsAvailable();
->sendEmptyMessage(EVENT_SCAN_RESULTS_AVAILABLE);
break;
}
WifiStateTracker.java
public void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_SCAN_RESULTS_AVAILABLE:
if (ActivityManagerNative.isSystemReady()) {
mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
}
}
WifiLayer注册接收SCAN_RESULTS_AVAILABLE_ACTION这个Intent:
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION))
{
handleScanResultsAvailable();
}
handleScanResultsAvailable();
-> list = mWifiManager.getScanResults();
-> mCallback.onAccessPointSetChanged(ap, true);
handleScanResultsAvailable()中首先会去拿到SCAN的结果(最终是往wpa_supplicant中发送SCAN_RESULT命令并读取返回值来实现的),对每一个扫描返回的AP,WifiLayer会回调WifiSetting的onAccessPointSetChanged函数,从而最终把该AP加到GUI显示列表中。
三、配置AP
当用户在 WifiSettings 界面上选择了一个AP 后,会显示配置AP 参数的一个对话框:
public boolean onPreferenceTreeClick()
->showAccessPointDialog(state, AccessPointDialog.MODE_INFO);
->AccessPointDialog dialog =
new AccessPointDialog(this, mWifiLayer);
showDialog(dialog);
当用户在AccessPointDialog中选择好加密方式和输入密钥之后,再点击连接按钮,Android就会去连接这个AP。
四、连接AP
在AccessPointDialog.java中点击连接后会执行:
public void onClick(DialogInterface dialog, int which) {
handleConnect();
-> mWifiLayer.connectToNetwork(mState);
-> // Need WifiConfiguration for the AP
WifiConfiguration config = findConfiguredNetwork(state);
config = addConfiguration(state, 0);
managerEnableNetwork(state, false)
->mWifiManager.enableNetwork()
->mService.enalbeNetwork()
->WifiNative.enableNetworkCommand()
接下去就JNI { "enableNetworkCommand", "(IZ)Z", (void*) android_net_wifi_enableNetworkCommand },最终就是向wpa_supplicant发送连接命令
五、获取IP地址
当wpa_supplicant成功连接上AP之后,它会向控制通道发送事件通知连接上AP了,从而wifi_wait_for_event函数会接收到该事件,由此WifiMonitor中的MonitorThread会被执行来出来这个事件:
void handleEvent(int event, String remainder) {
switch (event) {
case CONNECTED:
handleNetworkStateChange();
-> mWifiStateTracker.notifyStateChange(newState, BSSID, networkId);
->msg.sendToTarget();
break;
}
WifiStateTracker.java
public void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_NETWORK_STATE_CHANGED:
sendNetworkStateChangeBroadcast(mWifiInfo.getBSSID());
}
}
WifiStateTracker中注册的对Wifi相关数据库的观察者if(changed) 则启动:
private void configureInterface()
-> mDhcpTarget.sendEmptyMessage();
private class DhcpHandler extends Handler
handleMessage()
->switch (msg.what) {
case EVENT_DHCP_START:
Target.sendEmptyMessage(event);
DhcpHandler会发送EVENT_DHCP_START消息启动DHCP去获取IP地址,当DHCP拿到IP地址之后,会发送EVENT_INTERFACE_CONFIGURATION_SUCCEEDED的消息,然后WifiStateTacker中的handleMessage会处理这样的消息
case EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:
sendNetworkStateChangeBroadcast(mWifiInfo.getBSSID());
-> Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-> mContext.sendStickyBroadcast(intent);
这次带上完整的IP地址信息。WifiLayer中注册了此Intent的接受者,会调用handleNetworkStateChanged进行处理。最后就可以自由的上网了