举例,比如手机访问www.baidu.com,手机的ip为192.168.2.2,代理服务器的ip为192.168.3.4,端口为8087。
代理服务器这边socket监听8087端口,手机和代理服务器建立socket连接,把http请求的内容通过socket发送到代理服务器,代理服务器解析出Host。
得到host=www.baidu.com和port=80,然后解析www.baidu.com对应的ip=220.181.38.148,建立socket连接,把http请求的内容通过socket发送到220.181.38.148。同理把返回的内容发送回手机。
目前发现有两种代理方式,1是wifi代理,2是全局代理。
本来打算写全部的流程,但是从设置到wifi涉及到内容实在太多了,我追了两天,所以尽量列重点,忽略不重要到。
一般是设置中选择wifi长按,填入代理服务器,端口等。定位到实现代码
packages/apps/Settings/src/com/android/settings/wifi/WifiConfigController.java
关于远程调用,安卓系统很多都是基于binder,一般不直接调用binder,而是使用AIDL(接口定义语言)和ide工具生成封装好的代码。这里出现了一个新的远程调用的方式:Messenger。可能很多人不了解,因为一般只有系统framework有使用且使用不算多。本质上来说其实现也是基于binder实现跨进程调用,和AIDL个人总结有如下不同:
1:不用定义aidl文件。
2:Messenger只提供了一个方法进行进程间通信,send(Message msg)方法,发送一个Message,没有返回值,要拿到返回值,需要把client的Messenger作为msg.replyTo参数传递过去,service端处理完之后,在调用客户端的Messenger的send(Message msg)方法把返回值传递回client,这个过程是异步的。而AIDL你可以自己指定方法,指定返回值,它获取返回值是同步的。而AIDL调用默认是同步的,当然其实也可以异步。以上是针对客户端来说。
3:使用AIDL的时候,service端每收到一个client端的请求时,就会启动一个线程(非主线程)去执行相应的操作。而Messenger,service端收到的请求是放在Handler的MessageQueue里面,Handler大家都用过,它需要绑定一个Thread,然后不断poll message执行相关操作,这个过程是同步执行的。
4:Messenger需要和Handler绑定使用。
这里简单说下,有兴趣的可以自己写写例子熟悉使用。
WifiManager.java,sAsyncChanne内部封装的就是Messenger,就不展开了。
/frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java,获取WifiConfiguration,调用mWifiConfigStore.saveNetwork
WifiNative调用到wpa_ctrl,整个流程比较复杂。大概流程如下,把配置信息保存到wpa_supplicant,之后触发一些广播,主要的有:
WifiManager.LINK_CONFIGURATION_CHANGED_ACTION和WifiManager.NETWORK_STATE_CHANGED_ACTION
/frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java注册了广播接收者
结合我们之前的dns流程一文,其中有个关键的类RouteSelector,
submit->//WifiSettings.java,新增wifi或者修改ip、代理等保存
== save->//WifiManager.java,内部封装Messenger远程调用
==== handleMessage->//WifiService.java,接收远程调用
====== sendMessage->//WifiStateMachine.java,获取WifiConfiguration
======== saveNetwork->//WifiConfigStore.java
========== addOrUpdateNetworkNative-> //新增或者更新wifi
============ writeIpAndProxyConfigurationsOnChange-> //把远程传进来的ip、代理等写入当前进程的WifiConfiguration
========== enableNetwork/saveConfig -> //把配置信息保存到wpa_supplicant,之后触发一些广播
…
handleConnectivityChange->接收处理LINK_CONFIGURATION_CHANGED_ACTION
handleConnect->接收处理NETWORK_STATE_CHANGED_ACTION
==== handleApplyDefaultProxy-> //全局代理的优先级应该比wifi代理高
====== sendProxyBroadcast-> //发送广播Proxy.PROXY_CHANGE_ACTION
======== broadcastIntentLocked->//接收处理Proxy.PROXY_CHANGE_ACTION,ActivityManagerService.java
========== setHttpProxy->//ApplicationThread的setHttpProxy,回到应用进程执行,ActivityThread.java
============ setHttpProxySystemProperty->//Proxy.java,设置java环境变量,存储http、https的代理host、port。
//应用进程启动情况下
handleBindApplication->//ActivityThread.java
== getProxy->//跨进程调用ConnectivityService.java
==== setHttpProxySystemProperty->//Proxy.java
====== setHttpProxySystemProperty->//Proxy.java
SettingsObserver->//ConnectivityService.java,监听Settings.Global.HTTP_PROXY
handleDeprecatedGlobalHttpProxy->//解析出host,port
==setGlobalProxy->//Settings.Global.GLOBAL_HTTP_PROXY_HOST存储host
====sendProxyBroadcast->//发送广播Proxy.PROXY_CHANGE_ACTION
======broadcastIntentLocked->//接收处理Proxy.PROXY_CHANGE_ACTION,ActivityManagerService.java
========setHttpProxy->//ApplicationThread的setHttpProxy,回到应用进程执行,ActivityThread.java
==========setHttpProxySystemProperty->//Proxy.java,设置java环境变量,存储http、https的代理host、port。
//应用进程启动情况下
handleBindApplication->//ActivityThread.java
==getProxy->//跨进程调用ConnectivityService.java
====setHttpProxySystemProperty->//Proxy.java
======setHttpProxySystemProperty->//Proxy.java
…略过
RouteSelector->//构造函数
==resetNextProxy->//根据uri获取代理
====select->//ProxySelectorImpl.java
======selectOneProxy->//解析url的请求类型,查找设置的java环境变量中的代理host和port
========lookupProxy->//返回proxy
==========nextProxy->//发起网络请求前先检查是否设置代理
============resetNextInetSocketAddress->//获取dns,如果有设置代理,替换host和port为代理服务器。
结合分析知道系统调用的是WifiManager.save(WifiConfiguration config, ActionListener listener),这是个隐藏方法,在sdk中无法直接引用,但是可以反射或者直接binder调用远程进程。
经过分析流程,发现其实主要是更新设置的代理到远程服务,而WifiManager有一个函数updateNetwork(WifiConfiguration config)可以实现该功能,而且还可以少构造一个参数。更新之后,怎么使其生效呢?还记得两个广播吗?我们想办法触发其中一个广播即可。
所以先断开连接再连接,触发广播,使代理立即生效。
代码如下:
添加权限
通过以上代码可以设置wifi代理,可以把其他应用的http(s)代理到设置的代理服务器。
检测代理和绕过代理以及反检测和反绕过待续。
当设置的代理无法连通时,会跳过代理。
HttpURLConnectionImpl.java
RouteSelector.java,把不能连通的ip加入路由表
举例,比如手机访问www.baidu.com,手机的ip为192.168.2.2,代理服务器的ip为192.168.3.4,端口为8087。
代理服务器这边socket监听8087端口,手机和代理服务器建立socket连接,把http请求的内容通过socket发送到代理服务器,代理服务器解析出Host。
得到host=www.baidu.com和port=80,然后解析www.baidu.com对应的ip=220.181.38.148,建立socket连接,把http请求的内容通过socket发送到220.181.38.148。同理把返回的内容发送回手机。
目前发现有两种代理方式,1是wifi代理,2是全局代理。
手机设置wifi代理
本来打算写全部的流程,但是从设置到wifi涉及到内容实在太多了,我追了两天,所以尽量列重点,忽略不重要到。
一般是设置中选择wifi长按,填入代理服务器,端口等。定位到实现代码
packages/apps/Settings/src/com/android/settings/wifi/WifiConfigController.java
public WifiConfigController(
WifiConfigUiBase parent, View view, AccessPoint accessPoint, boolean edit) {
...
WifiInfo info = mAccessPoint.getInfo();
if (info != null && info.getLinkSpeed() != -1) {
addRow(group, R.string.wifi_speed, info.getLinkSpeed() + WifiInfo.LINK_SPEED_UNITS);
}
addRow(group, R.string.wifi_security, mAccessPoint.getSecurityString(false));
boolean showAdvancedFields = false;
if (mAccessPoint.networkId != INVALID_NETWORK_ID) {
WifiConfiguration config = mAccessPoint.getConfig();
if (config.ipAssignment == IpAssignment.STATIC) {
mIpSettingsSpinner.setSelection(STATIC_IP);
showAdvancedFields = true;
} else {
mIpSettingsSpinner.setSelection(DHCP);
}
//Display IP addresses
for(InetAddress a : config.linkProperties.getAddresses()) {
addRow(group, R.string.wifi_ip_address, a.getHostAddress());
}
//构造函数,从设置中取出状态,是否设置代理
if (config.proxySettings == ProxySettings.STATIC) {
mProxySettingsSpinner.setSelection(PROXY_STATIC);
showAdvancedFields = true;
} else if (config.proxySettings == ProxySettings.PAC) {
mProxySettingsSpinner.setVisibility(View.GONE);
TextView textView = (TextView)mView.findViewById(R.id.proxy_pac_info);
textView.setVisibility(View.VISIBLE);
textView.setText(context.getString(R.string.proxy_url) +
config.linkProperties.getHttpProxy().getPacFileUrl());
showAdvancedFields = true;
} else {
mProxySettingsSpinner.setSelection(PROXY_NONE);
}
}
...
public WifiConfigController(
WifiConfigUiBase parent, View view, AccessPoint accessPoint, boolean edit) {
...
WifiInfo info = mAccessPoint.getInfo();
if (info != null && info.getLinkSpeed() != -1) {
addRow(group, R.string.wifi_speed, info.getLinkSpeed() + WifiInfo.LINK_SPEED_UNITS);
}
addRow(group, R.string.wifi_security, mAccessPoint.getSecurityString(false));
boolean showAdvancedFields = false;
if (mAccessPoint.networkId != INVALID_NETWORK_ID) {
WifiConfiguration config = mAccessPoint.getConfig();
if (config.ipAssignment == IpAssignment.STATIC) {
mIpSettingsSpinner.setSelection(STATIC_IP);
showAdvancedFields = true;
} else {
mIpSettingsSpinner.setSelection(DHCP);
}
//Display IP addresses
for(InetAddress a : config.linkProperties.getAddresses()) {
addRow(group, R.string.wifi_ip_address, a.getHostAddress());
}
//构造函数,从设置中取出状态,是否设置代理
if (config.proxySettings == ProxySettings.STATIC) {
mProxySettingsSpinner.setSelection(PROXY_STATIC);
showAdvancedFields = true;
} else if (config.proxySettings == ProxySettings.PAC) {
mProxySettingsSpinner.setVisibility(View.GONE);
TextView textView = (TextView)mView.findViewById(R.id.proxy_pac_info);
textView.setVisibility(View.VISIBLE);
textView.setText(context.getString(R.string.proxy_url) +
config.linkProperties.getHttpProxy().getPacFileUrl());
showAdvancedFields = true;
} else {
mProxySettingsSpinner.setSelection(PROXY_NONE);
}
}
...
当设置代理的时候,显示给用户
//展示代理信息
private void showProxyFields() {
WifiConfiguration config = null;
mView.findViewById(R.id.proxy_settings_fields).setVisibility(View.VISIBLE);
if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
config = mAccessPoint.getConfig();
}
if (mProxySettingsSpinner.getSelectedItemPosition() == PROXY_STATIC) {
mView.findViewById(R.id.proxy_warning_limited_support).setVisibility(View.VISIBLE);
mView.findViewById(R.id.proxy_fields).setVisibility(View.VISIBLE);
if (mProxyHostView == null) {
mProxyHostView = (TextView) mView.findViewById(R.id.proxy_hostname);
mProxyHostView.addTextChangedListener(this);
mProxyPortView = (TextView) mView.findViewById(R.id.proxy_port);
mProxyPortView.addTextChangedListener(this);
mProxyExclusionListView = (TextView) mView.findViewById(R.id.proxy_exclusionlist);
mProxyExclusionListView.addTextChangedListener(this);
}
if (config != null) {
//获取设置过的代理信息
ProxyProperties proxyProperties = config.linkProperties.getHttpProxy();
if (proxyProperties != null) {
mProxyHostView.setText(proxyProperties.getHost());
mProxyPortView.setText(Integer.toString(proxyProperties.getPort()));
mProxyExclusionListView.setText(proxyProperties.getExclusionList());
}
}
} else {
mView.findViewById(R.id.proxy_warning_limited_support).setVisibility(View.GONE);
mView.findViewById(R.id.proxy_fields).setVisibility(View.GONE);
}
}
//保存代理设置
private boolean ipAndProxyFieldsAreValid() {
mLinkProperties.clear();
mIpAssignment = (mIpSettingsSpinner != null &&
mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) ?
IpAssignment.STATIC : IpAssignment.DHCP;
if (mIpAssignment == IpAssignment.STATIC) {
int result = validateIpConfigFields(mLinkProperties);
if (result != 0) {
return false;
}
}
mProxySettings = (mProxySettingsSpinner != null &&
mProxySettingsSpinner.getSelectedItemPosition() == PROXY_STATIC) ?
ProxySettings.STATIC : ProxySettings.NONE;
if (mProxySettings == ProxySettings.STATIC && mProxyHostView != null) {
String host = mProxyHostView.getText().toString();
String portStr = mProxyPortView.getText().toString();
String exclusionList = mProxyExclusionListView.getText().toString();
int port = 0;
int result = 0;
try {
port = Integer.parseInt(portStr);
//验证host和port是否正确
result = ProxySelector.validate(host, portStr, exclusionList);
} catch (NumberFormatException e) {
result = R.string.proxy_error_invalid_port;
}
if (result == 0) {
ProxyProperties proxyProperties= new ProxyProperties(host, port, exclusionList);
mLinkProperties.setHttpProxy(proxyProperties);
} else {
return false;
}
}
return true;
}
//展示代理信息
private void showProxyFields() {
WifiConfiguration config = null;
mView.findViewById(R.id.proxy_settings_fields).setVisibility(View.VISIBLE);
if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
config = mAccessPoint.getConfig();
}
if (mProxySettingsSpinner.getSelectedItemPosition() == PROXY_STATIC) {
mView.findViewById(R.id.proxy_warning_limited_support).setVisibility(View.VISIBLE);
mView.findViewById(R.id.proxy_fields).setVisibility(View.VISIBLE);
if (mProxyHostView == null) {
mProxyHostView = (TextView) mView.findViewById(R.id.proxy_hostname);
mProxyHostView.addTextChangedListener(this);
mProxyPortView = (TextView) mView.findViewById(R.id.proxy_port);
mProxyPortView.addTextChangedListener(this);
mProxyExclusionListView = (TextView) mView.findViewById(R.id.proxy_exclusionlist);
mProxyExclusionListView.addTextChangedListener(this);
}
if (config != null) {
//获取设置过的代理信息
ProxyProperties proxyProperties = config.linkProperties.getHttpProxy();
if (proxyProperties != null) {
mProxyHostView.setText(proxyProperties.getHost());
mProxyPortView.setText(Integer.toString(proxyProperties.getPort()));
mProxyExclusionListView.setText(proxyProperties.getExclusionList());
}
}
} else {
mView.findViewById(R.id.proxy_warning_limited_support).setVisibility(View.GONE);
mView.findViewById(R.id.proxy_fields).setVisibility(View.GONE);
}
}
//保存代理设置
private boolean ipAndProxyFieldsAreValid() {
mLinkProperties.clear();
mIpAssignment = (mIpSettingsSpinner != null &&
mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) ?
IpAssignment.STATIC : IpAssignment.DHCP;
if (mIpAssignment == IpAssignment.STATIC) {
int result = validateIpConfigFields(mLinkProperties);
if (result != 0) {
return false;
}
}
mProxySettings = (mProxySettingsSpinner != null &&
mProxySettingsSpinner.getSelectedItemPosition() == PROXY_STATIC) ?
ProxySettings.STATIC : ProxySettings.NONE;
if (mProxySettings == ProxySettings.STATIC && mProxyHostView != null) {
String host = mProxyHostView.getText().toString();
String portStr = mProxyPortView.getText().toString();
String exclusionList = mProxyExclusionListView.getText().toString();
int port = 0;
int result = 0;
try {
port = Integer.parseInt(portStr);
//验证host和port是否正确
result = ProxySelector.validate(host, portStr, exclusionList);
} catch (NumberFormatException e) {
result = R.string.proxy_error_invalid_port;
}
if (result == 0) {
ProxyProperties proxyProperties= new ProxyProperties(host, port, exclusionList);
mLinkProperties.setHttpProxy(proxyProperties);
} else {
return false;
}
}
return true;
}
保存和获取都是通过LinkProperties操作ProxyProperties,而ProxyProperties只是赋值和获取,没有其他操作。
public void setHttpProxy(ProxyProperties proxy) {
mHttpProxy = proxy;
}
public ProxyProperties getHttpProxy() {
return mHttpProxy;
}
public void setHttpProxy(ProxyProperties proxy) {
mHttpProxy = proxy;
}
public ProxyProperties getHttpProxy() {
return mHttpProxy;
}
WifiConfigController属于WifiDialog,WifiDialog 是我们长按时弹出到设置ip、代理等的窗口。WifiDialog 属于packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java
//当添加新的网络或者编辑保存触发,远程调用mWifiManager.save
/* package */ void submit(WifiConfigController configController) {
final WifiConfiguration config = configController.getConfig();
if (config == null) {
if (mSelectedAccessPoint != null
&& mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {
mWifiManager.connect(mSelectedAccessPoint.networkId,
mConnectListener);
}
} else if (config.networkId != INVALID_NETWORK_ID) {
if (mSelectedAccessPoint != null) {
mWifiManager.save(config, mSaveListener);
}
} else {
if (configController.isEdit()) {
mWifiManager.save(config, mSaveListener);
} else {
mWifiManager.connect(config, mConnectListener);
}
}
if (mWifiManager.isWifiEnabled()) {
mScanner.resume();
}
updateAccessPoints();
}
//当添加新的网络或者编辑保存触发,远程调用mWifiManager.save
/* package */ void submit(WifiConfigController configController) {
final WifiConfiguration config = configController.getConfig();
if (config == null) {
if (mSelectedAccessPoint != null
&& mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {
mWifiManager.connect(mSelectedAccessPoint.networkId,
mConnectListener);
}
} else if (config.networkId != INVALID_NETWORK_ID) {
if (mSelectedAccessPoint != null) {
mWifiManager.save(config, mSaveListener);
}
} else {
if (configController.isEdit()) {
mWifiManager.save(config, mSaveListener);
} else {
mWifiManager.connect(config, mConnectListener);
}
}
if (mWifiManager.isWifiEnabled()) {
mScanner.resume();
}
updateAccessPoints();
}
关于远程调用,安卓系统很多都是基于binder,一般不直接调用binder,而是使用AIDL(接口定义语言)和ide工具生成封装好的代码。这里出现了一个新的远程调用的方式:Messenger。可能很多人不了解,因为一般只有系统framework有使用且使用不算多。本质上来说其实现也是基于binder实现跨进程调用,和AIDL个人总结有如下不同:
1:不用定义aidl文件。
2:Messenger只提供了一个方法进行进程间通信,send(Message msg)方法,发送一个Message,没有返回值,要拿到返回值,需要把client的Messenger作为msg.replyTo参数传递过去,service端处理完之后,在调用客户端的Messenger的send(Message msg)方法把返回值传递回client,这个过程是异步的。而AIDL你可以自己指定方法,指定返回值,它获取返回值是同步的。而AIDL调用默认是同步的,当然其实也可以异步。以上是针对客户端来说。
3:使用AIDL的时候,service端每收到一个client端的请求时,就会启动一个线程(非主线程)去执行相应的操作。而Messenger,service端收到的请求是放在Handler的MessageQueue里面,Handler大家都用过,它需要绑定一个Thread,然后不断poll message执行相关操作,这个过程是同步执行的。
4:Messenger需要和Handler绑定使用。
这里简单说下,有兴趣的可以自己写写例子熟悉使用。
WifiManager.java,sAsyncChanne内部封装的就是Messenger,就不展开了。
public void save(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
validateChannel();
sAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
}
public void save(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
validateChannel();
sAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
}
远程调用frameworks/base/services/java/com/android/server/wifi/WifiService.java,调用mWifiStateMachine.sendMessage
case WifiManager.CONNECT_NETWORK:
case WifiManager.SAVE_NETWORK: {
WifiConfiguration config = (WifiConfiguration) msg.obj;
int networkId = msg.arg1;
if (config != null && config.isValid()) {
// This is restricted because there is no UI for the user to
// monitor/control PAC.
if (config.proxySettings != ProxySettings.PAC) {
if (DBG) Slog.d(TAG, "Connect with config" + config);
//继续传递msg
mWifiStateMachine.sendMessage(Message.obtain(msg));
} else {
Slog.e(TAG, "ClientHandler.handleMessage cannot process msg with PAC");
if (msg.what == WifiManager.CONNECT_NETWORK) {
replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
} else {
replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED);
}
}
} else if (config == null
&& networkId != WifiConfiguration.INVALID_NETWORK_ID) {
if (DBG) Slog.d(TAG, "Connect with networkId" + networkId);
mWifiStateMachine.sendMessage(Message.obtain(msg));
} else {
Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg);
if (msg.what == WifiManager.CONNECT_NETWORK) {
replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
} else {
replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED);
}
}
break;
}
case WifiManager.CONNECT_NETWORK:
case WifiManager.SAVE_NETWORK: {
WifiConfiguration config = (WifiConfiguration) msg.obj;
int networkId = msg.arg1;
if (config != null && config.isValid()) {
// This is restricted because there is no UI for the user to
// monitor/control PAC.
if (config.proxySettings != ProxySettings.PAC) {
if (DBG) Slog.d(TAG, "Connect with config" + config);
//继续传递msg
mWifiStateMachine.sendMessage(Message.obtain(msg));
} else {
Slog.e(TAG, "ClientHandler.handleMessage cannot process msg with PAC");
if (msg.what == WifiManager.CONNECT_NETWORK) {
replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
} else {
replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED);
}
}
} else if (config == null
&& networkId != WifiConfiguration.INVALID_NETWORK_ID) {
if (DBG) Slog.d(TAG, "Connect with networkId" + networkId);
mWifiStateMachine.sendMessage(Message.obtain(msg));
} else {
Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg);
if (msg.what == WifiManager.CONNECT_NETWORK) {
replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
} else {
replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED);
}
}
break;
}
/frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java,获取WifiConfiguration,调用mWifiConfigStore.saveNetwork
case WifiManager.SAVE_NETWORK:
config = (WifiConfiguration) message.obj;
NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config);
if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED);
} else {
loge("Failed to save network");
replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,
WifiManager.ERROR);
}
break;
case WifiManager.SAVE_NETWORK:
config = (WifiConfiguration) message.obj;
NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config);
if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED);
} else {
loge("Failed to save network");
replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,
WifiManager.ERROR);
}
break;
/frameworks/base/wifi/java/android/net/wifi/WifiConfigStore.java
NetworkUpdateResult saveNetwork(WifiConfiguration config) {
if (VDBG) localLog("saveNetwork", config.networkId);
// A new network cannot have null SSID
if (config == null || (config.networkId == INVALID_NETWORK_ID &&
config.SSID == null)) {
return new NetworkUpdateResult(INVALID_NETWORK_ID);
}
boolean newNetwork = (config.networkId == INVALID_NETWORK_ID);
//新增或者更新
NetworkUpdateResult result = addOrUpdateNetworkNative(config);
int netId = result.getNetworkId();
/* enable a new network */
if (newNetwork && netId != INVALID_NETWORK_ID) {
//新增wifi,断开的当前连接的wifi,再连接指定wifi
mWifiNative.enableNetwork(netId, false);
mConfiguredNetworks.get(netId).status = Status.ENABLED;
}
//mWifiNative的调用会到wpa_ctrl,很复杂,就不列出了
mWifiNative.saveConfig();
sendConfiguredNetworksChangedBroadcast(config, result.isNewNetwork() ?
WifiManager.CHANGE_REASON_ADDED : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
return result;
}
//主要是保存ip、代理
private NetworkUpdateResult addOrUpdateNetworkNative(WifiConfiguration config) {
...
//获取当前连接
WifiConfiguration currentConfig = mConfiguredNetworks.get(netId);
if (currentConfig == null) {
currentConfig = new WifiConfiguration();
currentConfig.ipAssignment = IpAssignment.DHCP;
currentConfig.proxySettings = ProxySettings.NONE;
currentConfig.networkId = netId;
}
readNetworkVariables(currentConfig);
mConfiguredNetworks.put(netId, currentConfig);
mNetworkIds.put(configKey(currentConfig), netId);
//把远程传进来的ip、代理等写入当前进程的WifiConfiguration
NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(currentConfig, config);
result.setIsNewNetwork(newNetwork);
result.setNetworkId(netId);
return result;
}
NetworkUpdateResult saveNetwork(WifiConfiguration config) {
if (VDBG) localLog("saveNetwork", config.networkId);
// A new network cannot have null SSID
if (config == null || (config.networkId == INVALID_NETWORK_ID &&
config.SSID == null)) {
return new NetworkUpdateResult(INVALID_NETWORK_ID);
}
boolean newNetwork = (config.networkId == INVALID_NETWORK_ID);
//新增或者更新
NetworkUpdateResult result = addOrUpdateNetworkNative(config);
int netId = result.getNetworkId();
/* enable a new network */
if (newNetwork && netId != INVALID_NETWORK_ID) {
//新增wifi,断开的当前连接的wifi,再连接指定wifi
mWifiNative.enableNetwork(netId, false);
mConfiguredNetworks.get(netId).status = Status.ENABLED;
}
//mWifiNative的调用会到wpa_ctrl,很复杂,就不列出了
mWifiNative.saveConfig();
sendConfiguredNetworksChangedBroadcast(config, result.isNewNetwork() ?
WifiManager.CHANGE_REASON_ADDED : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
return result;
}
//主要是保存ip、代理
private NetworkUpdateResult addOrUpdateNetworkNative(WifiConfiguration config) {
...
//获取当前连接
WifiConfiguration currentConfig = mConfiguredNetworks.get(netId);
if (currentConfig == null) {
currentConfig = new WifiConfiguration();
currentConfig.ipAssignment = IpAssignment.DHCP;
currentConfig.proxySettings = ProxySettings.NONE;
currentConfig.networkId = netId;
}
readNetworkVariables(currentConfig);
mConfiguredNetworks.put(netId, currentConfig);
mNetworkIds.put(configKey(currentConfig), netId);
//把远程传进来的ip、代理等写入当前进程的WifiConfiguration
NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(currentConfig, config);
result.setIsNewNetwork(newNetwork);
result.setNetworkId(netId);
return result;
}
WifiNative调用到wpa_ctrl,整个流程比较复杂。大概流程如下,把配置信息保存到wpa_supplicant,之后触发一些广播,主要的有:
WifiManager.LINK_CONFIGURATION_CHANGED_ACTION和WifiManager.NETWORK_STATE_CHANGED_ACTION
/frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java注册了广播接收者
private class WifiStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
...
Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED,
new NetworkInfo(mNetworkInfo));
msg.sendToTarget();
} else if (intent.getAction().equals(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION)) {
mLinkProperties = intent.getParcelableExtra(WifiManager.EXTRA_LINK_PROPERTIES);
Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
msg.sendToTarget();
}
}
}
private class WifiStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
...
Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED,
new NetworkInfo(mNetworkInfo));
msg.sendToTarget();
} else if (intent.getAction().equals(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION)) {
mLinkProperties = intent.getParcelableExtra(WifiManager.EXTRA_LINK_PROPERTIES);
Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
msg.sendToTarget();
}
}
}
在
frameworks/base/services/java/com/android/server/ConnectivityService.java内
private static class DefaultNetworkFactory implements NetworkFactory {
...
@Override
public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config) {
switch (config.radio) {
case TYPE_WIFI:
return new WifiStateTracker(targetNetworkType, config.name);
...
}
}
}
//构造函数内
try {
tracker = netFactory.createTracker(targetNetworkType, config);
mNetTrackers[targetNetworkType] = tracker;
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Problem creating " + getNetworkTypeName(targetNetworkType)
+ " tracker: " + e);
continue;
}
tracker.startMonitoring(context, mTrackerHandler);
private static class DefaultNetworkFactory implements NetworkFactory {
...
@Override
public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config) {
switch (config.radio) {
case TYPE_WIFI:
return new WifiStateTracker(targetNetworkType, config.name);
...
}
}
}
//构造函数内
try {
tracker = netFactory.createTracker(targetNetworkType, config);
mNetTrackers[targetNetworkType] = tracker;
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Problem creating " + getNetworkTypeName(targetNetworkType)
+ " tracker: " + e);
continue;
}
tracker.startMonitoring(context, mTrackerHandler);
内部类
private class NetworkStateTrackerHandler extends Handler {
public NetworkStateTrackerHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
NetworkInfo info;
switch (msg.what) {
case NetworkStateTracker.EVENT_STATE_CHANGED: {
info = (NetworkInfo) msg.obj;
NetworkInfo.State state = info.getState();
...
} else if (state == NetworkInfo.State.CONNECTED) {
//调用handleConnectivityChange
handleConnect(info);
}
if (mLockdownTracker != null) {
mLockdownTracker.onNetworkInfoChanged(info);
}
break;
}
case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: {
info = (NetworkInfo) msg.obj;
handleConnectivityChange(info.getType(), false);
break;
}
...
}
}
}
}
//EVENT_CONFIGURATION_CHANGED和EVENT_STATE_CHANGED最后都会调用到
private void handleConnectivityChange(int netType, boolean doReset) {
...
if (mNetConfigs[netType].isDefault()) {
handleApplyDefaultProxy(newLp.getHttpProxy());
}
...
}
//所以应该全局代理的优先级比wifi代理高
private void handleApplyDefaultProxy(ProxyProperties proxy) {
...
if (mGlobalProxy != null) return;
if (!mDefaultProxyDisabled) {
sendProxyBroadcast(proxy);
}
}
}
//从这里和后面的全局代理有重叠,就不继续了
private void sendProxyBroadcast(ProxyProperties proxy) {
if (proxy == null) proxy = new ProxyProperties("", 0, "");
if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
if (DBG) log("sending Proxy Broadcast for " + proxy);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
final long ident = Binder.clearCallingIdentity();
try {
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private class NetworkStateTrackerHandler extends Handler {
public NetworkStateTrackerHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
NetworkInfo info;
switch (msg.what) {
case NetworkStateTracker.EVENT_STATE_CHANGED: {
info = (NetworkInfo) msg.obj;
NetworkInfo.State state = info.getState();
...
} else if (state == NetworkInfo.State.CONNECTED) {
//调用handleConnectivityChange
handleConnect(info);
}
if (mLockdownTracker != null) {
mLockdownTracker.onNetworkInfoChanged(info);
}
break;
}
case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: {
info = (NetworkInfo) msg.obj;
handleConnectivityChange(info.getType(), false);
break;
}
...
}
}
}
}
//EVENT_CONFIGURATION_CHANGED和EVENT_STATE_CHANGED最后都会调用到
private void handleConnectivityChange(int netType, boolean doReset) {
...
if (mNetConfigs[netType].isDefault()) {
handleApplyDefaultProxy(newLp.getHttpProxy());
}
...
}
//所以应该全局代理的优先级比wifi代理高
private void handleApplyDefaultProxy(ProxyProperties proxy) {
...
if (mGlobalProxy != null) return;
if (!mDefaultProxyDisabled) {
sendProxyBroadcast(proxy);
}
}
}
//从这里和后面的全局代理有重叠,就不继续了
private void sendProxyBroadcast(ProxyProperties proxy) {
if (proxy == null) proxy = new ProxyProperties("", 0, "");
if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
if (DBG) log("sending Proxy Broadcast for " + proxy);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
final long ident = Binder.clearCallingIdentity();
try {
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
wifi代理分析到sendProxyBroadcast,因为后面的流程和全局代理一致。
通过设置Settings.Global.GLOBAL_HTTP_PROXY_HOST/Settings.Global.HTTP_PROXY代理
在frameworks/base/services/java/com/android/server/ConnectivityService.java中注册了监听器
//注册监听器
mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
mSettingsObserver.observe(mContext);
//实现
private static class SettingsObserver extends ContentObserver {
private int mWhat;
private Handler mHandler;
SettingsObserver(Handler handler, int what) {
super(handler);
mHandler = handler;
mWhat = what;
}
void observe(Context context) {
ContentResolver resolver = context.getContentResolver();
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.HTTP_PROXY), false, this);
}
//当修改Settings.Global.HTTP_PROXY时触发
@Override
public void onChange(boolean selfChange) {
mHandler.obtainMessage(mWhat).sendToTarget();
}
}
//内部handler的部分代码
case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
handleDeprecatedGlobalHttpProxy();
break;
}
//取出设置的http代理,封装
private void handleDeprecatedGlobalHttpProxy() {
String proxy = Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.HTTP_PROXY);
if (!TextUtils.isEmpty(proxy)) {
String data[] = proxy.split(":");
if (data.length == 0) {
return;
}
String proxyHost = data[0];
int proxyPort = 8080;
if (data.length > 1) {
try {
proxyPort = Integer.parseInt(data[1]);
} catch (NumberFormatException e) {
return;
}
}
ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
setGlobalProxy(p);
}
}
//解析出host和port,用Settings.Global.GLOBAL_HTTP_PROXY_HOST存储
public void setGlobalProxy(ProxyProperties proxyProperties) {
enforceConnectivityInternalPermission();
synchronized (mProxyLock) {
if (proxyProperties == mGlobalProxy) return;
if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
String host = "";
int port = 0;
String exclList = "";
String pacFileUrl = "";
if (proxyProperties != null && (!TextUtils.isEmpty(proxyProperties.getHost()) ||
!TextUtils.isEmpty(proxyProperties.getPacFileUrl()))) {
if (!proxyProperties.isValid()) {
if (DBG)
log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
return;
}
mGlobalProxy = new ProxyProperties(proxyProperties);
host = mGlobalProxy.getHost();
port = mGlobalProxy.getPort();
exclList = mGlobalProxy.getExclusionList();
if (proxyProperties.getPacFileUrl() != null) {
pacFileUrl = proxyProperties.getPacFileUrl();
}
} else {
mGlobalProxy = null;
}
ContentResolver res = mContext.getContentResolver();
final long token = Binder.clearCallingIdentity();
try {
//保存host和port
Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, host);
Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
exclList);
Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
} finally {
Binder.restoreCallingIdentity(token);
}
}
if (mGlobalProxy == null) {
proxyProperties = mDefaultProxy;
}
//发送通知
sendProxyBroadcast(proxyProperties);
}
//发送广播Proxy.PROXY_CHANGE_ACTION
private void sendProxyBroadcast(ProxyProperties proxy) {
if (proxy == null) proxy = new ProxyProperties("", 0, "");
if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
if (DBG) log("sending Proxy Broadcast for " + proxy);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
final long ident = Binder.clearCallingIdentity();
try {
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
//注册监听器
mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
mSettingsObserver.observe(mContext);
//实现
private static class SettingsObserver extends ContentObserver {
private int mWhat;
private Handler mHandler;
SettingsObserver(Handler handler, int what) {
super(handler);
mHandler = handler;
mWhat = what;
}
void observe(Context context) {
ContentResolver resolver = context.getContentResolver();
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.HTTP_PROXY), false, this);
}
//当修改Settings.Global.HTTP_PROXY时触发
@Override
public void onChange(boolean selfChange) {
mHandler.obtainMessage(mWhat).sendToTarget();
}
}
//内部handler的部分代码
case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
handleDeprecatedGlobalHttpProxy();
break;
}
//取出设置的http代理,封装
private void handleDeprecatedGlobalHttpProxy() {
String proxy = Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.HTTP_PROXY);
if (!TextUtils.isEmpty(proxy)) {
String data[] = proxy.split(":");
if (data.length == 0) {
return;
}
String proxyHost = data[0];
int proxyPort = 8080;
if (data.length > 1) {
try {
proxyPort = Integer.parseInt(data[1]);
} catch (NumberFormatException e) {
return;
}
}
ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
setGlobalProxy(p);
}
}
//解析出host和port,用Settings.Global.GLOBAL_HTTP_PROXY_HOST存储
public void setGlobalProxy(ProxyProperties proxyProperties) {
enforceConnectivityInternalPermission();
synchronized (mProxyLock) {
if (proxyProperties == mGlobalProxy) return;
if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
String host = "";
int port = 0;
String exclList = "";
String pacFileUrl = "";
if (proxyProperties != null && (!TextUtils.isEmpty(proxyProperties.getHost()) ||
!TextUtils.isEmpty(proxyProperties.getPacFileUrl()))) {
if (!proxyProperties.isValid()) {
if (DBG)
log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
return;
}
mGlobalProxy = new ProxyProperties(proxyProperties);
host = mGlobalProxy.getHost();
port = mGlobalProxy.getPort();
exclList = mGlobalProxy.getExclusionList();
if (proxyProperties.getPacFileUrl() != null) {
pacFileUrl = proxyProperties.getPacFileUrl();
}
} else {
mGlobalProxy = null;
}
ContentResolver res = mContext.getContentResolver();
final long token = Binder.clearCallingIdentity();
try {
//保存host和port
Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, host);
Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
exclList);
Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
} finally {
Binder.restoreCallingIdentity(token);
}
}
if (mGlobalProxy == null) {
proxyProperties = mDefaultProxy;
}
//发送通知
sendProxyBroadcast(proxyProperties);
}
//发送广播Proxy.PROXY_CHANGE_ACTION
private void sendProxyBroadcast(ProxyProperties proxy) {
if (proxy == null) proxy = new ProxyProperties("", 0, "");
if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
if (DBG) log("sending Proxy Broadcast for " + proxy);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
final long ident = Binder.clearCallingIdentity();
try {
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
调用
frameworks/base/core/java/android/app/ContextImpl.java
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-6-23 17:18
被卓桐编辑
,原因: