原 试谈android中WIFI源码
网上关于如何用代码设置wifi的文章一搜一大堆,小蒋在此就不再添乱了,我就试着给大家谈一谈wifi的源码吧。
首先,我还是得从代码入手,下面是设置打开wifi的相关代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
private
WifiManager mWifiManager;
public
WifiAdmin(Context context){
//取得WifiManager对象
mWifiManager=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
//取得WifiInfo对象
mWifiInfo=mWifiManager.getConnectionInfo();
}
//打开wifi
public
void
openWifi(){
if (!mWifiManager.isWifiEnabled()){
mWifiManager.setWifiEnabled( true );
}
}
|
首先找到WifiManager.java(frameworks/base/wifi/java/android/net/wifi),里面有
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public
class
WifiManager {
IWifiManager mService;
/**
* Enable or disable Wi-Fi.
* @param enabled {@code true} to enable, {@code false} to disable.
* @return {@code true} if the operation succeeds (or if the existing state
* is the same as the requested state).
*/
public
boolean
setWifiEnabled( boolean
enabled) {
try
{
return
mService.setWifiEnabled(enabled);
} catch
(RemoteException e) {
return
false ;
}
}
}
|
IWifiManager也是什么东西呢?在frameworks/base/wifi/java/android/net/wifi里面你会发现一个叫做IWifiManager.aidl的文件
1
2
3
4
5
6
7
|
interface
IWifiManager
{
boolean
setWifiEnabled( boolean
enable);
}
|
这是一个aidl文件,如果有不懂的请看我的其他文章,这个interface会在WifiService.java里面实现(frameworks/base/services/java/com/android/server)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
/**
* WifiService handles remote WiFi operation requests by implementing
* the IWifiManager interface. It also creates a WifiMonitor to listen
* for Wifi-related events.
*
* @hide
*/
public
class
WifiService extends
IWifiManager.Stub {
private
final
WifiHandler mWifiHandler;
private
Context mContext;
private
static
PowerManager.WakeLock sWakeLock;
/**
* see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
* @param enable {@code true} to enable, {@code false} to disable.
* @return {@code true} if the enable/disable operation was
* started or is already in the queue.
*/
public
boolean
setWifiEnabled( boolean
enable) {
enforceChangePermission();
if
(mWifiHandler == null ) return
false ;
synchronized
(mWifiHandler) {
// caller may not have WAKE_LOCK permission - it's not required here
long
ident = Binder.clearCallingIdentity();
sWakeLock.acquire();
Binder.restoreCallingIdentity(ident);
mLastEnableUid = Binder.getCallingUid();
// set a flag if the user is enabling Wifi while in airplane mode
mAirplaneModeOverwridden = (enable && isAirplaneModeOn() && isAirplaneToggleable());
sendEnableMessage(enable, true , Binder.getCallingUid());
}
return
true ;
}
private
void
enforceChangePermission() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
"WifiService" );
}
|
enforceCallingOrSelfPermission(..,..)函数就是检查是否具有权限,若没有则抛出异常。Binder.clearCallingIdentity()和Binder.restoreCallingIdentity()这两个方法,它的主要作用是暂时获得系统权限,acquire函数就是申请一把锁,以后释放。后面的sendEnableMessage函数
1
2
3
4
5
6
|
private
void
sendEnableMessage( boolean
enable, boolean
persist, int
uid) {
Message msg = Message.obtain(mWifiHandler,
(enable ? MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI),
(persist ? 1
: 0 ), uid);
msg.sendToTarget();
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/**
* Handler that allows posting to the WifiThread.
*/
private
class
WifiHandler extends
Handler {
public
WifiHandler(Looper looper) {
super (looper);
}
@Override
public
void
handleMessage(Message msg) {
switch
(msg.what) {
case
MESSAGE_ENABLE_WIFI:
setWifiEnabledBlocking( true , msg.arg1 == 1 , msg.arg2);
if
(mWifiWatchdogService == null ) {
mWifiWatchdogService = new
WifiWatchdogService(mContext, mWifiStateTracker);
}
sWakeLock.release();
break ;
}
}
}
|
这里的msg.arg2就是uid,看下里面的setWifiEnabledBlocking函数,此代码段为代码段一!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
/**
* Enables/disables Wi-Fi synchronously.
* @param enable {@code true} to turn Wi-Fi on, {@code false} to turn it off.
* @param persist {@code true} if the setting should be persisted.
* @param uid The UID of the process making the request.
* @return {@code true} if the operation succeeds (or if the existing state
* is the same as the requested state)
*/
private
boolean
setWifiEnabledBlocking( boolean
enable, boolean
persist, int
uid) {
final
int
eventualWifiState = enable ? WIFI_STATE_ENABLED : WIFI_STATE_DISABLED;
final
int
wifiState = mWifiStateTracker.getWifiState();
if
(wifiState == eventualWifiState) {
return
true ;
}
if
(enable && isAirplaneModeOn() && !mAirplaneModeOverwridden) {
return
false ;
}
/**
* Multiple calls to unregisterReceiver() cause exception and a system crash.
* This can happen if a supplicant is lost (or firmware crash occurs) and user indicates
* disable wifi at the same time.
* Avoid doing a disable when the current Wifi state is UNKNOWN
* TODO: Handle driver load fail and supplicant lost as seperate states
*/
if
((wifiState == WIFI_STATE_UNKNOWN) && !enable) {
return
false ;
}
/**
* Fail Wifi if AP is enabled
* TODO: Deprecate WIFI_STATE_UNKNOWN and rename it
* WIFI_STATE_FAILED
*/
if
((mWifiApState == WIFI_AP_STATE_ENABLED) && enable) {
setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
return
false ;
}
setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid);
if
(enable) {
if
(!mWifiStateTracker.loadDriver()) {
Slog.e(TAG, "Failed to load Wi-Fi driver." );
setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
return
false ;
}
if
(!mWifiStateTracker.startSupplicant()) {
mWifiStateTracker.unloadDriver();
Slog.e(TAG, "Failed to start supplicant daemon." );
setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
return
false ;
}
registerForBroadcasts();
mWifiStateTracker.startEventLoop();
}
}
|
1
2
3
|
public
synchronized
boolean
loadDriver() {
return
WifiNative.loadDriver();
}
|
1
2
3
|
public
synchronized
boolean
startSupplicant() {
return
WifiNative.startSupplicant();
}
|
这调用了WifiNative的loadDriver与startSupplicant函数,注意,所有的WifiNative中的调用都需要发生在WifiStateTracker类中,除了waitForEvent()
1
2
3
4
5
6
|
public
class
WifiNative {
public
native
static
boolean
loadDriver();
public
native
static
boolean
startSupplicant();
}
|
这个native里面的调用是为了发送请求到supplicant daemon以及从获取异步事件。这个loadDriver实际上是通过JNI去实现的,实现于android_net_wifi_WIFI.cpp(frameworks/base/core/jni)
1
2
3
4
5
6
7
8
|
static
jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject clazz)
{
return
(jboolean)(::wifi_load_driver() == 0);
}
static
jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject clazz)
{
return
(jboolean)(::wifi_start_supplicant() == 0);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
int
wifi_load_driver()
{
char
driver_status[PROPERTY_VALUE_MAX];
int
count = 100; /* wait at most 20 seconds for completion */
if
(check_driver_loaded()) {
return
0;
}
if
(insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
return
-1;
if
( strcmp (FIRMWARE_LOADER, "" ) == 0) {
usleep(WIFI_DRIVER_LOADER_DELAY);
property_set(DRIVER_PROP_NAME, "ok" );
}
else
{
property_set( "ctl.start" , FIRMWARE_LOADER);
}
sched_yield();
while
(count-- > 0) {
if
(property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
if
( strcmp (driver_status, "ok" ) == 0)
return
0;
else
if
( strcmp (DRIVER_PROP_NAME, "failed" ) == 0) {
wifi_unload_driver();
return
-1;
}
}
usleep(200000);
}
property_set(DRIVER_PROP_NAME, "timeout" );
wifi_unload_driver();
return
-1;
}
int
wifi_unload_driver()
{
int
count = 20; /* wait at most 10 seconds for completion */
if
(rmmod(DRIVER_MODULE_NAME) == 0) {
while
(count-- > 0) {
if
(!check_driver_loaded())
break ;
usleep(500000);
}
if
(count) {
return
0;
}
return
-1;
} else
return
-1;
}
|
这些都是驱动相关的信息,下面的是startSupplicant函数的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
int
wifi_start_supplicant()
{
char
supp_status[PROPERTY_VALUE_MAX] = { '\0' };
int
count = 200; /* wait at most 20 seconds for completion */
#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
const
prop_info *pi;
unsigned serial = 0;
#endif
/* Check whether already running */
if
(property_get(SUPP_PROP_NAME, supp_status, NULL)
&& strcmp (supp_status, "running" ) == 0) {
return
0;
}
/* Before starting the daemon, make sure its config file exists */
if
(ensure_config_file_exists() < 0) {
LOGE( "Wi-Fi will not be enabled" );
return
-1;
}
/* Clear out any stale socket files that might be left over. */
wpa_ctrl_cleanup();
#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
/*
* Get a reference to the status property, so we can distinguish
* the case where it goes stopped => running => stopped (i.e.,
* it start up, but fails right away) from the case in which
* it starts in the stopped state and never manages to start
* running at all.
*/
pi = __system_property_find(SUPP_PROP_NAME);
if
(pi != NULL) {
serial = pi->serial;
}
#endif
property_set( "ctl.start" , SUPPLICANT_NAME);
sched_yield();
while
(count-- > 0) {
#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
if
(pi == NULL) {
pi = __system_property_find(SUPP_PROP_NAME);
}
if
(pi != NULL) {
__system_property_read(pi, NULL, supp_status);
if
( strcmp (supp_status, "running" ) == 0) {
return
0;
} else
if
(pi->serial != serial &&
strcmp (supp_status, "stopped" ) == 0) {
return
-1;
}
}
#else
if
(property_get(SUPP_PROP_NAME, supp_status, NULL)) {
if
( strcmp (supp_status, "running" ) == 0)
return
0;
}
#endif
usleep(100000);
}
return
-1;
}
|
这段代码是属于启动supplicant服务。
现在继续回到代码段一,往下走是setWifiEnabledState函数,此处为代码段二!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
private
void
setWifiEnabledState( int
wifiState, int
uid) {
final
int
previousWifiState = mWifiStateTracker.getWifiState();
long
ident = Binder.clearCallingIdentity();
try
{
if
(wifiState == WIFI_STATE_ENABLED) {
mBatteryStats.noteWifiOn();
} else
if
(wifiState == WIFI_STATE_DISABLED) {
mBatteryStats.noteWifiOff();
}
} catch
(RemoteException e) {
} finally
{
Binder.restoreCallingIdentity(ident);
}
// Update state
mWifiStateTracker.setWifiState(wifiState);
// Broadcast
final
Intent intent = new
Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);
intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState);
mContext.sendStickyBroadcast(intent);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
final
class
BatteryStatsService extends
IBatteryStats.Stub {
final
BatteryStatsImpl mStats;
public
void
noteWifiOn() {
enforceCallingPermission();
synchronized
(mStats) {
mStats.noteWifiOnLocked();
}
}
}
|
查找BatteryStateImpl.java(freameworks/base/core/java/com/android/internal/os)
1
2
3
4
5
6
7
8
9
10
|
public
void
noteWifiOnLocked() {
if
(!mWifiOn) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_ON_FLAG;
if
(DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
+ Integer.toHexString(mHistoryCur.states));
addHistoryRecordLocked(SystemClock.elapsedRealtime());
mWifiOn = true ;
mWifiOnTimer.startRunningLocked( this );
}
}
|
1
2
3
|
public
void
setWifiState( int
wifiState) {
mWifiState.set(wifiState);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
/**
* One of {@link WifiManager#WIFI_STATE_DISABLED},
* {@link WifiManager#WIFI_STATE_DISABLING},
* {@link WifiManager#WIFI_STATE_ENABLED},
* {@link WifiManager#WIFI_STATE_ENABLING},
* {@link WifiManager#WIFI_STATE_UNKNOWN}
*
* getWifiState() is not synchronized to make sure it's always fast,
* even when the instance lock is held on other slow operations.
* Use a atomic variable for state.
*/
private
final
AtomicInteger mWifiState = new
AtomicInteger(WIFI_STATE_UNKNOWN);
|
AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。再接着看代码段二,就是讲wifi事件广播出去,通知监听此事件的事务。然而在wifisettings.java(packages/apps/settings/src/com/android/settings/wifi)里面会监听到此事件。
1
2
3
4
5
6
7
8
9
|
private
void
handleEvent(Intent intent) {
String action = intent.getAction();
if
(WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN));
} else
if
(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
updateAccessPoints();
}
}
|
1
2
3
4
5
6
7
8
9
|
private
void
updateWifiState( int
state) {
if
(state == WifiManager.WIFI_STATE_ENABLED) {
mScanner.resume();
updateAccessPoints();
} else
{
mScanner.pause();
mAccessPoints.removeAll();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
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 );
}
|
1
2
3
4
5
6
7
8
|
public
boolean
startScanActive() {
try
{
mService.startScan( true );
return
true ;
} catch
(RemoteException e) {
return
false ;
}
}
|
1
2
3
4
5
6
|
public
void
startScan( boolean
forceActive) {
enforceChangePermission();
if
(mWifiHandler == null ) return ;
Message.obtain(mWifiHandler, MESSAGE_START_SCAN, forceActive ? 1
: 0 , 0 ).sendToTarget();
}
|
发送消息到wifiHandler,那么看下对应的响应,此处为代码段四!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
case
MESSAGE_START_SCAN:
boolean
forceActive = (msg.arg1 == 1 );
switch
(mWifiStateTracker.getSupplicantState()) {
case
DISCONNECTED:
case
INACTIVE:
case
SCANNING:
case
DORMANT:
break ;
default :
mWifiStateTracker.setScanResultHandling(
WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY);
break ;
}
mWifiStateTracker.scan(forceActive);
break ;
|
1
2
3
|
public
SupplicantState getSupplicantState() {
return
mWifiInfo.getSupplicantState();
}
|
1
2
3
|
public
SupplicantState getSupplicantState() {
return
mSupplicantState;
}
|
这个返回的是supplicantState与AP协商后的详细状态。(Return the detailed state of the supplicant's negotiation with an access point)。接着看代码段四,下面遇到两个函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public
synchronized
boolean
scan( boolean
forceActive) {
if
(mWifiState.get() != WIFI_STATE_ENABLED || isDriverStopped()) {
return
false ;
}
return
WifiNative.scanCommand(forceActive);
}
/**
* Specifies whether the supplicant or driver
* take care of initiating scan and doing AP selection
*
* @param mode
* SUPPL_SCAN_HANDLING_NORMAL
* SUPPL_SCAN_HANDLING_LIST_ONLY
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
public
synchronized
boolean
setScanResultHandling( int
mode) {
if
(mWifiState.get() != WIFI_STATE_ENABLED) {
return
false ;
}
return
WifiNative.setScanResultHandlingCommand(mode);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
static
jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz, jboolean forceActive)
{
jboolean result;
// Ignore any error from setting the scan mode.
// The scan will still work.
if
(forceActive && !sScanModeActive)
doSetScanMode( true );
result = doBooleanCommand( "SCAN" , "OK" );
if
(forceActive && !sScanModeActive)
doSetScanMode(sScanModeActive);
return
result;
}
|
1
2
3
4
|
static
jboolean doSetScanMode(jboolean setActive)
{
return
doBooleanCommand((setActive ? "DRIVER SCAN-ACTIVE"
: "DRIVER SCAN-PASSIVE" ), "OK" );
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
static
jboolean doBooleanCommand( const
char
*cmd, const
char
*expect)
{
char
reply[256];
if
(doCommand(cmd, reply, sizeof (reply)) != 0) {
return
(jboolean)JNI_FALSE;
} else
{
return
(jboolean)( strcmp (reply, expect) == 0);
}
}
static
int
doCommand( const
char
*cmd, char
*replybuf, int
replybuflen)
{
size_t
reply_len = replybuflen - 1;
if
(::wifi_command(cmd, replybuf, &reply_len) != 0)
return
-1;
else
{
// Strip off trailing newline
if
(reply_len > 0 && replybuf[reply_len-1] == '\n' )
replybuf[reply_len-1] = '\0' ;
else
replybuf[reply_len] = '\0' ;
return
0;
}
}
|
1
2
3
4
|
int
wifi_command( const
char
*command, char
*reply, size_t
*reply_len)
{
return
wifi_send_command(ctrl_conn, command, reply, reply_len);
}
|
接下来看看wifi_send_command函数,在wifi.c里面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
int
wifi_send_command( struct
wpa_ctrl *ctrl, const
char
*cmd, char
*reply, size_t
*reply_len)
{
int
ret;
if
(ctrl_conn == NULL) {
LOGV( "Not connected to wpa_supplicant - \"%s\" command dropped.\n" , cmd);
return
-1;
}
ret = wpa_ctrl_request(ctrl, cmd, strlen (cmd), reply, reply_len, NULL);
if
(ret == -2) {
LOGD( "'%s' command timed out.\n" , cmd);
return
-2;
} else
if
(ret < 0 || strncmp (reply, "FAIL" , 4) == 0) {
return
-1;
}
if
( strncmp (cmd, "PING" , 4) == 0) {
reply[*reply_len] = '\0' ;
}
return
0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
struct
wpa_ctrl {
#ifdef CONFIG_CTRL_IFACE_UDP
int
s;
struct
sockaddr_in local;
struct
sockaddr_in dest;
char
*cookie;
#endif /* CONFIG_CTRL_IFACE_UDP */
#ifdef CONFIG_CTRL_IFACE_UNIX
int
s;
struct
sockaddr_un local;
struct
sockaddr_un dest;
#endif /* CONFIG_CTRL_IFACE_UNIX */
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
HANDLE
pipe;
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
};
|
wpa_ctrl_request,这个函数存放在wpa_ctrl.c(external/wpa_supplicant)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
int
wpa_ctrl_request( struct
wpa_ctrl *ctrl, const
char
*cmd, size_t
cmd_len,
char
*reply, size_t
*reply_len,
void
(*msg_cb)( char
*msg, size_t
len))
{
struct
timeval tv;
int
res;
fd_set rfds;
const
char
*_cmd;
char
*cmd_buf = NULL;
size_t
_cmd_len;
#ifdef CONFIG_CTRL_IFACE_UDP
if
(ctrl->cookie) {
char
*pos;
_cmd_len = strlen (ctrl->cookie) + 1 + cmd_len;
cmd_buf = os_malloc(_cmd_len );
if
(cmd_buf == NULL)
return
-1;
_cmd = cmd_buf;
pos = cmd_buf;
strcpy (pos, ctrl->cookie);
pos += strlen (ctrl->cookie);
*pos++ = ' ' ;
memcpy (pos, cmd, cmd_len);
} else
#endif /* CONFIG_CTRL_IFACE_UDP */
{
_cmd = cmd;
_cmd_len = cmd_len;
}
if
(send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
os_free(cmd_buf);
return
-1;
}
os_free(cmd_buf);
for
(;;) {
#ifdef ANDROID
tv.tv_sec = 10;
#else
tv.tv_sec = 2;
#endif
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(ctrl->s, &rfds);
res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
if
(FD_ISSET(ctrl->s, &rfds)) {
res = recv(ctrl->s, reply, *reply_len, 0);
if
(res < 0)
return
res;
if
(res > 0 && reply[0] == '<' ) {
/* This is an unsolicited message from
* wpa_supplicant, not the reply to the
* request. Use msg_cb to report this to the
* caller. */
if
(msg_cb) {
/* Make sure the message is nul
* terminated. */
if
(( size_t ) res == *reply_len)
res = (*reply_len) - 1;
reply[res] = '\0' ;
msg_cb(reply, res);
}
continue ;
}
*reply_len = res;
break ;
} else
{
return
-2;
}
}
return
0;
}
|
现在回到代码段三,后面有个update函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
private
void
updateAccessPoints() {
List<AccessPoint> accessPoints = new
ArrayList<AccessPoint>();
List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
if
(configs != null ) {
mLastPriority = 0 ;
for
(WifiConfiguration config : configs) {
if
(config.priority > mLastPriority) {
mLastPriority = config.priority;
}
// Shift the status to make enableNetworks() more efficient.
if
(config.status == Status.CURRENT) {
config.status = Status.ENABLED;
} else
if
(mResetNetworks && config.status == Status.DISABLED) {
config.status = Status.CURRENT;
}
AccessPoint accessPoint = new
AccessPoint( this , config);
accessPoint.update(mLastInfo, mLastState);
accessPoints.add(accessPoint);
}
}
List<ScanResult> results = mWifiManager.getScanResults();
if
(results != null ) {
for
(ScanResult result : results) {
// Ignore hidden and ad-hoc networks.
if
(result.SSID == null
|| result.SSID.length() == 0
||
result.capabilities.contains( "[IBSS]" )) {
continue ;
}
boolean
found = false ;
for
(AccessPoint accessPoint : accessPoints) {
if
(accessPoint.update(result)) {
found = true ;
}
}
if
(!found) {
accessPoints.add( new
AccessPoint( this , result));
}
}
}
mAccessPoints.removeAll();
for
(AccessPoint accessPoint : accessPoints) {
mAccessPoints.addPreference(accessPoint);
}
}
|
源码下载:http://yxwojia.lingw.net/article-6510203-1.html
