Android Wifi State保存
2016-04-19 17:47
281 查看
在Android系统中,在关开机之后发现Wifi仍然保持着关机之前的状态,就很好奇Wifi State是保存在那里的。如果是保存在Settings应用中的话,则必须要打开Settings才能触发保存的状态。但是Wifi是开机进入home界面之后就触发了。所以肯定在App层下面,framework层。
要追查追查Wifi State,想到了每次打开关闭wifi需要调用的WifiManger.setWifiEnabled(),下面我们将一步一步追查。
在Settings app中,在那里去触发wifi自动打开的呢,要看WiFiEnabler.java,它主要控制wifi开关控件switch。setSwitch函数是初始化WifiEnabler时调用的去打开的。onCheckedChanged函数是switch控件状态改变时,会调用的灰调函数。
可以看到setSwitch函数初始化switch时,是通过WifiManger.getWifiState()去获取的。这说明Wifi State保存在更底层。在onCheckedChanged函数中,每当wifi状态改变时,通过WiFiManager.setWifiEnabled函数去向framework设置。设置时,Wifi State也要随着更改并保存。
接下来我们就看下WifiManager.setWifiEnabled函数。mService是IWifiManager的new出的对象。通过aidl调用到WifiService.java
我们继续看WiFiService.java,在setWifiEnabled中调用WifiStateMachine.setWifiEnabled,调用wifi状态机去loaddriver、初始化supplicant等打开wifi的操作。注意在下面有一句handleWifiToggled(enable),这个函数继续向下追有persistwifiState函数。这个函数有一句Settings.Global.putInt,这里就是保存Wifi State的地方。Settings.Global.putInt类似于Android中SharedPreference。
到这里我们已经知道保存Wifi State的地方了,但是开机时怎么去触发的呢。那我们继续在wifiService.java文件中找,看看什么时候去读取mPersistWiFiSate的状态的。看出有getPersistedWifiState返回Wifi State,在checkAndStartWifi中有调用。就说明Wifi State最初的状态是有checkAndStartWifi获取,并进行了Wifi状态的初始化。
为什么开机时,会调用checkAndStartWifi呢。这是因为WiFiService为system service,在开机时会被添加启动起来。我们来看SystemServer.java,调用checkAndStartWifi函数对Wifi进行初始化。
要追查追查Wifi State,想到了每次打开关闭wifi需要调用的WifiManger.setWifiEnabled(),下面我们将一步一步追查。
在Settings app中,在那里去触发wifi自动打开的呢,要看WiFiEnabler.java,它主要控制wifi开关控件switch。setSwitch函数是初始化WifiEnabler时调用的去打开的。onCheckedChanged函数是switch控件状态改变时,会调用的灰调函数。
public void setSwitch(Switch switch_) { if (mSwitch == switch_) return; mSwitch.setOnCheckedChangeListener(null); mSwitch = switch_; mSwitch.setOnCheckedChangeListener(this); final int wifiState = mWifiManager.getWifiState(); boolean isEnabled = wifiState == WifiManager.WIFI_STATE_ENABLED; boolean isDisabled = wifiState == WifiManager.WIFI_STATE_DISABLED; mSwitch.setChecked(isEnabled); mSwitch.setEnabled(isEnabled || isDisabled); } public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (mWifiManager.setWifiEnabled(isChecked)) { // Intent has been taken into account, disable until new state is active mSwitch.setEnabled(false); } else { // Error Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show(); } }
可以看到setSwitch函数初始化switch时,是通过WifiManger.getWifiState()去获取的。这说明Wifi State保存在更底层。在onCheckedChanged函数中,每当wifi状态改变时,通过WiFiManager.setWifiEnabled函数去向framework设置。设置时,Wifi State也要随着更改并保存。
接下来我们就看下WifiManager.setWifiEnabled函数。mService是IWifiManager的new出的对象。通过aidl调用到WifiService.java
public boolean setWifiEnabled(boolean enabled) { try { mService.setWifiEnabled(enabled); } catch (RemoteException e) { return false; } }
我们继续看WiFiService.java,在setWifiEnabled中调用WifiStateMachine.setWifiEnabled,调用wifi状态机去loaddriver、初始化supplicant等打开wifi的操作。注意在下面有一句handleWifiToggled(enable),这个函数继续向下追有persistwifiState函数。这个函数有一句Settings.Global.putInt,这里就是保存Wifi State的地方。Settings.Global.putInt类似于Android中SharedPreference。
public synchronized boolean setWifiEnabled(boolean enable) { if (enable) { reportStartWorkSource(); } mWifiStateMachine.setWifiEnabled(enable); long ident = Binder.clearCallingIdentity(); try { handleWifiToggled(enable); } finally { Binder.restoreCallingIdentity(ident); } return true; } private void handleWifiToggled(boolean wifiEnabled) { boolean airplaneEnabled = mAirplaneModeOn.get() && isAirplaneToggleable(); if (wifiEnabled) { if (airplaneEnabled) { persistWifiState(WIFI_ENABLED_AIRPLANE_OVERRIDE); } else { persistWifiState(WIFI_ENABLED); } } else { // When wifi state is disabled, we do not care // if airplane mode is on or not. The scenario of // wifi being disabled due to airplane mode being turned on // is handled handleAirplaneModeToggled() persistWifiState(WIFI_DISABLED); } } private void persistWifiState(int state) { final ContentResolver cr = mContext.getContentResolver(); mPersistWifiState.set(state); Settings.Global.putInt(cr, Settings.Global.WIFI_ON, state); }
到这里我们已经知道保存Wifi State的地方了,但是开机时怎么去触发的呢。那我们继续在wifiService.java文件中找,看看什么时候去读取mPersistWiFiSate的状态的。看出有getPersistedWifiState返回Wifi State,在checkAndStartWifi中有调用。就说明Wifi State最初的状态是有checkAndStartWifi获取,并进行了Wifi状态的初始化。
private int getPersistedWifiState() { final ContentResolver cr = mContext.getContentResolver(); try { return Settings.Global.getInt(cr, Settings.Global.WIFI_ON); } catch (Settings.SettingNotFoundException e) { Settings.Global.putInt(cr, Settings.Global.WIFI_ON, WIFI_DISABLED); return WIFI_DISABLED; } } public void checkAndStartWifi() { mAirplaneModeOn.set(isAirplaneModeOn()); mPersistWifiState.set(getPersistedWifiState()); /* Start if Wi-Fi should be enabled or the saved state indicates Wi-Fi was on */ boolean wifiEnabled = shouldWifiBeEnabled() || testAndClearWifiSavedState(); Slog.i(TAG, "WifiService starting up with Wi-Fi " +(wifiEnabled ? "enabled" : "disabled")); // If we are already disabled (could be due to airplane mode), avoid changing persist // state here if (wifiEnabled) setWifiEnabled(wifiEnabled); mWifiWatchdogStateMachine = WifiWatchdogStateMachine.makeWifiWatchdogStateMachine(mContext); }
为什么开机时,会调用checkAndStartWifi呢。这是因为WiFiService为system service,在开机时会被添加启动起来。我们来看SystemServer.java,调用checkAndStartWifi函数对Wifi进行初始化。
try { Slog.i(TAG, "Connectivity Service"); connectivity = new ConnectivityService( context, networkManagement, networkStats, networkPolicy); ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity); networkStats.bindConnectivityManager(connectivity); networkPolicy.bindConnectivityManager(connectivity); wifi.checkAndStartWifi(); wifiP2p.connectivityServiceReady(); } catch (Throwable e) { reportWtf("starting Connectivity Service", e); }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories