手机verifyfail怎么办

手机verifyfail怎么办

本文为看雪论坛优秀文章

看雪论坛作者ID:卓桐

首先简单说下HTTP代理的原理和实现

举例,比如手机访问www.baidu.com,手机的ip为192.168.2.2,代理服务器的ip为192.168.3.4,端口为8087。

代理服务器这边socket监听8087端口,手机和代理服务器建立socket连接,把http请求的内容通过socket发送到代理服务器,代理服务器解析出Host。

手机verifyfail怎么办

得到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

publicWifiConfigController(

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;

} elseif(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);

}

}

...

当设置代理的时候,显示给用户:

//展示代理信息

privatevoidshowProxyFields() {

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.getSelectedItemwww.58yuanyou.comPosition == 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);

}

}

//保存代理设置

privateboolean ipAndProxyFieldsAreValid() {

mLinkProperties.clear;

mIpAssignment = (mIpSettingsSpinner != null&&

mIpSettingsSpinner.getSelectedItemPosition == STATIC_IP) ?

IpAssignment.STATIC : IpAssignment.DHCP;

if(mIpAssignment == IpAssignment.STATIC) {

intresult = validateIpConfigFields(mLinkProperties);

if(result != 0) {

returnfalse;

}

}

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;

intport = 0;

intresult = 0;

try{

port = Integer.parseInt(portStr);

//验证host和port是否正确

result = ProxySelector.validate(host, portSXALPcdtr, exclusionList);

} catch(NumberFormatException e) {

result = R.string.proxy_error_invalid_port;

}

if(result == 0) {

ProxyProperties proxyProperties= newProxyProperties(host, port, exclusionList);

mLinkProperties.setHttpProxy(proxyProperties);

} else{

returnfalse;

}

}

returntrue;

}

保存和获取都是通过LinkProperties操作ProxyProperties,而ProxyProperties只是赋值和获取,没有其他操作。

publicvoidsetHttpProxy(ProxyProperties proxy){

mHttpProxy = proxy;

}

publicProxyProperties getHttpProxy{

returnmHttpProxy;

}

WifiConfigController属于WifiDialog,WifiDialog 是我们长按时弹出到设置IP、代理等的窗口。WifiDialog 属于packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java

//当添加新的网络或者编辑保存触发,远程调用mWifiManager.save

/* package */voidsubmit(WifiConfigController configController){

finalWifiConfiguration config = configController.getConfig;

if(config == null) {

if(mSelectedAccessPoint != null

&& mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {

mWifiManager.connect(mSelectedAccessPoint.networkId,

mConnectListener);

}

} elseif(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,就不展开了。

publicvoidsave(WifiConfiguration config, ActionListener listener) {

if(config == null) thrownewIllegalArgumentException("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

caseWifiManager.CONNECT_NETWORK:

caseWifiManager.SAVE_NETWORK: {

WifiConfiguration config = (WifiConfiguration) msg.obj;

intnetworkId = 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);

}

}

} elseif(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

caseWifiManager.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)) {

returnnewNetworkUpdateResult(INVALID_NETWORK_ID);

}

boolean newNetwork = (config.networkId == INVALID_NETWORK_ID);

//新增或者更新

NetworkUpdateResult result = addOrUpdateNetworkNative(config);

intnetId = 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);

returnresult;

}

//主要是保存ip、代理

privateNetworkUpdateResult addOrUpdateNetworkNative(WifiConfiguration config) {

...

//获取当前连接

WifiConfiguration currentConfig = mConfiguredNetworks.get(netId);

if(currentConfig == null) {

currentConfig = newWifiConfiguration;

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);

returnresult;

}

WifiNative调用到wpa_ctrl,整个流程比较复杂。大概流程如下,把配置信息保存到wpa_supplicant,之后触发一些广播,主要的有:

WifiManager.LINK_CONFIGURATION_CHANGED_ACTION和WifiManager.NETWORK_STATE_CHANGED_ACTION

/frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java注册了广播接收者。

privateclassWifiStateReceiverextendsBroadcastReceiver{

@Override

publicvoidonReceive(Context context, Intent intent){

if(intent.getAction.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {

...

Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED,

newNetworkInfo(mNetworkInfo));

msg.sendToTarget;

} elseif(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内

privatestaticclassDefaultNetworkFactoryimplementsNetworkFactory{

...

@Override

publicNetworkStateTracker createTracker(inttargetNetworkType, NetworkConfig config){

switch(config.radio) {

caseTYPE_WIFI:

returnnewWifiStateTracker(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);

内部类:

privateclassNetworkStateTrackerHandlerextendsHandler{

publicNetworkStateTrackerHandler(Looper looper){

super(looper);

}

@Override

publicvoidhandleMessage(Message msg){

NetworkInfo info;

switch(msg.what) {

caseNetworkStateTracker.EVENT_STATE_CHANGED: {

info = (NetworkInfo) msg.obj;

NetworkInfo.State state = info.getState;

...

} elseif(state == NetworkInfo.State.CONNECTED) {

//调用handleConnectivityChange

handleConnect(info);

}

if(mLockdownTracker != null) {

mLockdownTracker.onNetworkInfoChanged(info);

}

break;

}

caseNetworkStateTracker.EVENT_CONFIGURATION_CHANGED: {

info = (NetworkInfo) msg.obj;

handleConnectivityChange(info.getType, false);

break;

}

...

}

}

}

}

//EVENT_CONFIGURATION_CHANGED和EVENT_STATE_CHANGED最后都会调用到

privatevoidhandleConnectivityChange(intnetType, booleandoReset){

...

if(mNetConfigs[netType].isDefault) {

handleApplyDefaultProxy(newLp.getHttpProxy);

}

...

}

//所以应该全局代理的优先级比wifi代理高

privatevoidhandleApplyDefaultProxy(ProxyProperties proxy){

...

if(mGlobalProxy != null) return;

if(!mDefaultProxyDisabled) {

sendProxyBroadcast(proxy);

}

}

}

//从这里和后面的全局代理有重叠,就不继续了

privatevoidsendProxyBroadcast(ProxyProperties proxy){

if(proxy == null) proxy = newProxyProperties("", 0, "");

if(mPacManager.setCurrentProxyUrl(proxy)) return;

if(DBG) log("sending Proxy Broadcast for "+ proxy);

Intent intent = newIntent(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);

finallongident = 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 = newSettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);

mSettingsObserver.observe(mContext);

//实现

privatestaticclassSettingsObserverextendsContentObserver{

privateintmWhat;

privateHandler mHandler;

SettingsObserver(Handler handler, intwhat) {

super(handler);

mHandler = handler;

mWhat = what;

}

voidobserve(Context context){

ContentResolver resolver = context.getContentResolver;

resolver.registerContentObserver(Settings.Global.getUriFor(

Settings.Global.HTTP_PROXY), false, this);

}

//当修改Settings.Global.HTTP_PROXY时触发

@Override

publicvoidonChange(booleanselfChange){

mHandler.obtainMessage(mWhat).sendToTarget;

}

}

//内部handler的部分代码

caseEVENT_APPLY_GLOBAL_HTTP_PROXY: {

handleDeprecatedGlobalHttpProxy;

break;

}

//取出设置的http代理,封装

privatevoidhandleDeprecatedGlobalHttpProxy{

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];

intproxyPort = 8080;

if(data.length > 1) {

try{

proxyPort = Integer.parseInt(data[1]);

} catch(NumberFormatException e) {

return;

}

}

ProxyProperties p = newProxyProperties(data[0], proxyPort, "");

setGlobalProxy(p);

}

}

//解析出host和port,用Settings.Global.GLOBAL_HTTP_PROXY_HOST存储

publicvoidsetGlobalProxy(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 = "";

intport = 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 = newProxyProperties(proxyProperties);

host = mGlobalProxy.getHost;

port = mGlobalProxy.getPort;

exclList = mGlobalProxy.getExclusionList;

if(proxyProperties.getPacFileUrl != null) {

pacFileUrl = proxyProperties.getPacFileUrl;

}

} else{

mGlobalProxy = null;

}

ContentResolver res = mContext.getContentResolver;

finallongtoken = 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.restore原由网CallingIdentity(token);

}

}

if(mGlobalProxy == null) {

proxyProperties = mDefaultProxy;

}

//发送通知

sendProxyBroadcast(proxyProperties);

}

//发送广播Proxy.PROXY_CHANGE_ACTION

privatevoidsendProxyBroadcast(ProxyProperties proxy){

if(proxy == null) proxy = newProxyProperties("", 0, "");

if(mPacManager.setCurrentProxyUrl(proxy)) return;

if(DBG) log("sending Proxy Broadcast for "+ proxy);

Intent intent = newIntent(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);

finallongident = Binder.clearCallingIdentity;

try{

mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);

} finally{

Binder.restoreCallingIdentity(ident);

}

}

调用

frameworks/base/core/java/android/app/ContextImpl.java

@Override

publicvoidsendStickyBroadcastAsUser(Intent intent, UserHandle user) {

StringresolvedType = intent.resolveTypeIfNeeded(getContentResolver);

try{

intent.prepareToLeaveProcess;

ActivityManagerNative.getDefault.broadcastIntent(

mMainThread.getApplicationThread, intent, resolvedType, null,

Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, true, user.getIdentifier);

} catch(RemoteException e) {

}

}

最终调用到的是frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

publicfinalintbroadcastIntent(IApplicationThread caller,

Intent intent, String resolvedType, IIntentReceiver resultTo,

intresultCode, String resultData, Bundle map,

String requiredPermission, intappOp, booleanserialized, booleansticky, intuserId){

enforceNotIsolatedCaller("broadcastIntent");

synchronized(this) {

intent = verifyBroadcastLocked(intent);

finalProcessRecord callerApp = getRecordForAppLocked(caller);

finalintcallingPid = Binder.getCallingPid;

finalintcallingUid = Binder.getCallingUid;

finallongorigId = Binder.clearCallingIdentity;

intres = broadcastIntentLocked(callerApp,

callerApp != null? callerApp.info.packageName : null,

intent, resolvedType, resultTo,

resultCode, resultData, map, requiredPermission, appOp, serialized, sticky,

callingPid, callingUid, userId);

Binder.restoreCallingIdentity(origId);

returnres;

}

}

//接收处理Proxy.PROXY_CHANGE_ACTION

privatefinalintbroadcastIntentLocked(ProcessRecord callerApp,

String callerPackage, Intent intent, String resolvedType,

IIntentReceiver resultTo, intresultCode, String resultData,

Bundle map, String requiredPermission, intappOp,

booleanordered, booleansticky, intcallingPid, intcallingUid,

intuserId){

...

if(Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction)) {

ProxyProperties proxy = intent.getParcelableExtra("proxy");

mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));

}

...

}

//handler接收UPDATE_HTTP_PROXY_MSG,解析出host,port,调用ApplicationThread的setHttpProxy

caseUPDATE_HTTP_PROXY_MSG: {

ProxyProperties proxy = (ProxyProperties)msg.obj;

String host = "";

String port = "";

String exclList = "";

String pacFileUrl = null;

if(proxy != null) {

host = proxy.getHost;

port = Integer.toString(proxy.getPort);

exclList = proxy.getExclusionList;

pacFileUrl = proxy.getPacFileUrl;

}

synchronized(ActivityManagerService.this) {

for(inti = mLruProcesses.size - 1; i >= 0; i--) {

ProcessRecord r = mLruProcesses.get(i);

if(r.thread != null) {

try{

r.thread.setHttpProxy(host, port, exclList, pacFileUrl);

} catch(RemoteException ex) {

Slog.w(TAG, "Failed to update http proxy for: "+

r.info.processName);

}

}

}

}

} break;

注意这里是在system_server进程,调用ApplicationThread的setHttpProxy属于跨进程调用,通过binder机制,只后回到应用进程。(上面的代码是已启动的应用进程都调用一遍)

ApplicationThread属于frameworks/base/core/java/android/app/ActivityThread.java的内部类

publicvoidsetHttpProxy(Stringhost, Stringport, StringexclList, StringpacFileUrl) {

Proxy.setHttpProxySystemProperty(host, port, exclList, pacFileUrl);

}

frameworks/base/core/java/android/net/Proxy.java,设置java环境变量,存储HTTP、HTTPS的代理host、port。

publicstaticfinal voidsetHttpProxySystemProperty(Stringhost, Stringport, StringexclList,

StringpacFileUrl) {

if(exclList != null) exclList = exclList.replace(",", "|");

if(false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList);

if(host != null) {

System.setProperty("http.proxyHost", host);

System.setProperty("https.proxyHost", host);

} else{

System.clearProperty("http.proxyHost");

System.clearProperty("https.proxyHost");

}

if(port != null) {

System.setProperty("http.proxyPort", port);

System.setProperty("https.proxyPort", port);

} else{

System.clearProperty("http.proxyPort");

System.clearProperty("https.proxyPort");

}

if(exclList != null) {

System.setProperty("http.nonProxyHosts", exclList);

System.setProperty("https.nonProxyHosts", exclList);

} else{

System.clearProperty("http.nonProxyHosts");

System.clearProperty("https.nonProxyHosts");

}

if(!TextUtils.isEmpty(pacFileUrl)) {

ProxySelector.setDefault(newPacProxySelector);

} else{

ProxySelector.setDefault(sDefaultProxySelector);

}

}

以上就是设置全局代理的流程,但是如果应用进程没启动没怎么办,其实在应用进程创建执行application之前调用ConnectivityService.javagetProxy,Proxy.setHttpProxySystemProperty会调用上面的重载函数,达到一致的效果。

IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);

if(b != null) {

// In pre-boot mode (doing initial launch to collect password), not

// all systeXALPcdm is up. This includes the connectivity service, so don't

// crash if we can't get it.

IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);

try{

ProxyProperties proxyProperties = service.getProxy;

Proxy.setHttpProxySystemProperty(proxyProperties);

} catch(RemoteException e) {}

}

代理生效

结合我们之前的DNS流程一文,其中有个关键的类RouteSelector。

publicRouteSelector(Address address, URI uri, ProxySelector proxySelector, ConnectionPool pool,

Dns dns, RouteDatabase routeDatabase) {

this.address = address;

this.uri = uri;

this.proxySelector = proxySelector;

this.pool = pool;

this.dns = dns;

this.routeDatabase = routeDatabase;

this.postponedRoutes = newLinkedList<Route>;

//读取是否设置全局代理

resetNextProxy(uri, address.getProxy);

}

//proxy为null,使用全局或者wifi代理,非应用内代理

/** Resets {@link #nextProxy} to the first option. */

privatevoidresetNextProxy(URI uri, Proxy proxy) {

this.hasNextProxy = true; // This includes NO_PROXY!

if(proxy != null) {

this.userSpecifiedProxy = proxy;

} else{//根据uri获取代理

List<Proxy> proxyList = proxySelector.select(uri);

if(proxyList != null) {

this.proxySelectorProxies = proxyList.iterator;

}

}

}

ProxySelector为构造函数参入的参数,ProxySelector为抽象类,实现为ProxySelectorImpl。

private staticProxySelector defaultSelector = newProxySelectorImpl;

//入口

@Override public List<Proxy> select(URI uri) {

returnCollections.singletonList(selectOneProxy(uri));

}

//解析url的请求类型,查找设置的java环境变量中的代理host和port

private ProxyselectOneProxy(URI uri) {

if(uri == null) {

thrownewIllegalArgumentException("uri == null");

}

Stringscheme = uri.getScheme;

if(scheme == null) {

thrownewIllegalArgumentException("scheme == null");

}

int port = -1;

Proxyproxy = null;

StringnonProxyHostsKey = null;

boolean httpProxyOkay = true;

if("http".equalsIgnoreCase(scheme)) {

port = 80;

nonProxyHostsKey = "http.nonProxyHosts";

proxy = lookupProxy("http.proxyHost", "http.proxyPort", Proxy.Type.HTTP, port);

} elseif("https".equalsIgnoreCase(scheme)) {

port = 443;

nonProxyHostsKey = "https.nonProxyHosts"; // RI doesn't support this

proxy = lookupProxy("https.proxyHost", "https.proxyPort", Proxy.Type.HTTP, port);

} elseif("ftp".equalsIgnoreCase(scheme)) {

port = 80; // not 21 as you might guess

nonProxyHostsKey = "ftp.nonProxyHosts";

proxy = lookupProxy("ftp.proxyHost", "ftp.proxyPort", Proxy.Type.HTTP, port);

} elseif("socket".equalsIgnoreCase(scheme)) {

httpProxyOkay = false;

} else{

returnProxy.NO_PROXY;

}

if(nonProxyHostsKey != null

&& isNonProxyHost(uri.getHost, System.getProperty(nonProxyHostsKey))) {

returnProxy.NO_PROXY;

}

if(proxy != null) {

returnproxy;

}

if(httpProxyOkay) {

proxy = lookupProxy("proxyHost", "proxyPort", Proxy.Type.HTTP, port);

if(proxy != null) {

returnproxy;

}

}

proxy = lookupProxy("socksProxyHost", "socksProxyPort", Proxy.Type.SOCKS, 1080);

if(proxy != null) {

returnproxy;

}

returnProxy.NO_PROXY;

}

private ProxylookupProxy(StringhostKey, StringportKey, Proxy.Type type, int defaultPort) {

Stringhost = System.getProperty(hostKey);

if(host == null|| host.isEmpty) {

returnnull;

}

int port = getSystemPropertyInt(portKey, defaultPort);

returnnewProxy(type, InetSocketAddress.createUnresolved(host, port));

}

如此我们设置的全局/WiFi代理被封装成Proxy,之后结合上一篇文章:

//proxySelectorProxies不为null了

private ProxynextProxy {

// If the user specifies a proxy, try that and only that.

if(userSpecifiedProxy != null) {

hasNextProxy = false;

returnuserSpecifiedProxy;

}

// Try each of the ProxySelector choices until one connection succeeds. If none succeed

// then we'll try a direct connection below.

if(proxySelectorProxies != null) {

while(proxySelectorProxies.hasNext) {

Proxycandidate = proxySelectorProxies.next;

if(candidate.type != Proxy.Type.DIRECT) {

returncandidate;

}

}

}

// Finally try a direct connection.

hasNextProxy = false;

returnProxy.NO_PROXY;

}

//上篇文章dns入口,proxy不为空,类型为http

private voidresetNextInetSocketAddress(Proxyproxy) throws UnknownHostException {

socketAddresses = null; // Clear the addresses. Necessary if getAllByName below throws!

StringsocketHost;

if(proxy.type == Proxy.Type.DIRECT) {

socketHost = uri.getHost;

socketPort = getEffectivePort(uri);

} else{

SocketAddress proxyAddress = proxy.address;

if(!(proxyAddress instanceofInetSocketAddress)) {

thrownewIllegalArgumentException(

"Proxy.address is not an "+ "InetSocketAddress: "+ proxyAddress.getClass);

}

InetSocketAddress proxySocketAddress = (InetSocketAddress) proxyAddress;

//代理服务器的host

socketHost = proxySocketAddress.getHostName;

socketPort = proxySocketAddress.getPort;

}

// Try each address for best behavior in mixed IPv4/IPv6 environments.

socketAddresses = dns.getAllByName(socketHost);

nextSocketAddressIndex = 0;

}

至此两种设置代理的方式流程(其实3种,上篇文章应用进程内设置代理)以及代理如何生效分析完毕。

设置WiFi代理流程:

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

设置全局代理流程:Settings.Global.GLOBAL_HTTP_PROXY_HOST/Settings.Global.HTTP_PROXY

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为代理服务器。

代码实现设置WiFi代理

结合分析知道系统调用的是WifiManager.save(WifiConfiguration config,ActionListener listener),这是个隐藏方法,在sdk中无法直接引用,但是可以反射或者直接binder调用远程进程。

经过分析流程,发现其实主要是更新设置的代理到远程服务,而WifiManager有一个函数updateNetwork(WifiConfiguration config)可以实现该功能,而且还可以少构造一个参数。更新之后,怎么使其生效呢?还记得两个广播吗?我们想办法触发其中一个广播即可。

所以先断开连接再连接,触发广播,使代理立即生效。

代码如下:

privateWifiConfiguration getCurrentWifiConfiguration(WifiManager manager) {

if(manager == null|| !manager.isWifiEnabled)

returnnull;

List<WifiConfiguration> c//www.58yuanyou.comonfigurationList = manager.getConfiguredNetworks;

WifiConfiguration configuration = null;

int networkId = manager.getConnectionInfo.getNetworkId;

for(int i = 0; i < configurationList.size; ++i) {

WifiConfiguration wifiConfiguration = configurationList.get(i);

if(wifiConfiguration.networkId == networkId)

configuration = wifiConfiguration;

}

returnconfiguration;

}

//打印下设置过的代理

privatebooleangetWiFiProxySettings {

// 获得 WifiConfiguration

WifiManager manager = (WifiManager) this.getApplicationContext.getSystemService(Context.WIFI_SERVICE);

WifiConfiguration config = getCurrentWifiConfiguration(manager);

if(null== config)

returnfalse;

try{

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {//26

ProxyInfo httpProxy = config.getHttpProxy;

Log.e("zhuo", "httpProxy="+httpProxy);

}

// 从 WifiConfiguration 中获得 linkProperties

ObjectlinkProperties = getField(config, "linkProperties");

if(null== linkProperties)

returnfalse;

// 获得 getHttpProxy 方法

Class<?> proxyPropertiesClass = Class.forName("android.net.ProxyProperties");

Class<?> lpClass = Class.forName("android.net.LinkProperties");

Method getHttpProxy = lpClass.getDeclaredMethod("getHttpProxy");

getHttpProxy.setAccessible(true);

ObjectproxyProperties = getHttpProxy.invoke(linkProperties);

Log.e("zhuo", "proxyProperties="+proxyProperties);

returntrue;

} catch(Exception e) {

e.printStackTrace;

returnfalse;

}

}

//传入代理host和port

privatebooleansetWiFiProxySettings(Stringip, int port) {

// 获得 WifiConfiguration

WifiManager manager = (WifiManager) this.getApplicationContext.getSystemService(Context.WIFI_SERVICE);

WifiConfiguration config = getCurrentWifiConfiguration(manager);

if(null== config)

returnfalse;

try{

// 从 WifiConfiguration 中获得 linkProperties

ObjectlinkProperties = getField(config, "linkProperties");

if(null== linkProperties)

returnfalse;

// 获得 setHttpProxy 方法

Class<?> ProxyProperties = Class.forName("android.net.ProxyProperties");

Class<?> LinkProperties = Class.forName("android.net.LinkProperties");

Method setHttpProxy = LinkProperties.getDeclaredMethod("setHttpProxy", ProxyProperties);

setHttpProxy.setAccessible(true);

// 获得 ProxyProperties 构造方法

Constructor proxyPropertiesCtor = ProxyProperties.getConstructor(String.class, int.class, String.class);

// 创建 ProxyProperties 的对象

ObjectproxySettings = proxyPropertiesCtor.newInstance(ip, port, null);

// 反射调用 linkProperties 的 setHttpProxy 方法, 参数为 ProxyProperties

setHttpProxy.invoke(linkProperties, proxySettings);

setProxySettings("STATIC", config);

// 保存设置

manager.updateNetwork(config);

manager.disconnect;

manager.reconnect;//需先断开再连接

Log.e("zhuo", "保存Proxy设置成功");

returntrue;

} catch(Exception e) {

e.printStackTrace;

returnfalse;

}

}

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

添加权限。

通过以上代码可以设置WiFi代理,可以把其他应用的HTTP(S)代理到设置的代理服务器。

检测代理和绕过代理以及反检测和反绕过待续。

补充

当设置的代理无法连通时,会跳过代理。

HttpURLConnectionImpl.java:

privatebooleanexecute(booleanreadResponse)throwsIOException {

try{

httpEngine.sendRequest;

if(readResponse) {

httpEngine.readResponse;

}

returntrue;

} catch(IOException e) {

//捕获异常

if(handleFailure(e)) {

returnfalse;

} else{

throwe;

}

}

}

//routeSelector.connectFailed,把异常传递给RouteSelector

privatebooleanhandleFailure(IOException e)throwsIOException {

RouteSelector routeSelector = httpEngine.routeSelector;

if(routeSelector != null&& httpEngine.connection != null) {

routeSelector.connectFailed(httpEngine.connection, e);

}

OutputStream requestBody = httpEngine.getRequestBody;

booleancanRetryRequestBody = requestBody == null

|| requestBody instanceofRetryableOutputStream;

if(routeSelector == null&& httpEngine.connection == null// No connection.

|| routeSelector != null&& !routeSelector.hasNext // No more routes to attempt.

|| !isRecoverable(e)

|| !canRetryRequestBody) {

httpEngineFailure = e;

returnfalse;

}

httpEngine.release(true);

RetryableOutputStream retryableOutputStream = (RetryableOutputStream) requestBody;

httpEngine = newHttpEngine(method, rawRequestHeaders, null, retryableOutputStream);

httpEngine.routeSelector = routeSelector; // Keep the same routeSelector.

returntrue;

}

RouteSelector.java,把不能连通的IP加入路由表:

publicvoidconnectFailed(Connection connection, IOException failure) {

Route failedRoute = connection.getRoute;

if(failedRoute.getProxy.type != Proxy.Type.DIRECT && proxySelector != null) {

// Tell the proxy selector when we fail to connect on a fresh connection.

proxySelector.connectFailed(uri, failedRoute.getProxy.address, failure);

}

routeDatabase.failed(failedRoute, failure);

}

//再次进行网络请求,执行到routeDatabase.shouldPostpone,因为不能连通的代理已经在路由表(黑名单)中,所以继续调用自身,跳过了代理

publicConnection next(String method) throws IOException {

// Always prefer pooled connections over new connections.

for(Connection pooled; (pooled = pool.get(address)) != null; ) {

if(method.equals("GET") || pooled.isReadable) returnpooled;

pooled.close;

}

// Compute the next route to attempt.

if(!hasNextTlsMode) {

if(!hasNextInetSocketAddress) {

if(!hasNextProxy) {

if(!hasNextPostponed) {

thrownewNoSuchElementException;

}

returnnewConnection(nextPostponed);

}

lastProxy = nextProxy;

resetNextInetSocketAddress(lastProxy);

}

lastInetSocketAddress = nextInetSocketAddress;

resetNextTlsMode;

}

boolean modernTls = nextTlsMode == TLS_MODE_MODERN;

Route route = newRoute(address, lastProxy, lastInetSocketAddress, modernTls);

if(routeDatabase.shouldPostpone(route)) {

postponedRoutes.add(route);

// We will only recurse in order to skip previously failed routes. They will be

// tried last.

returnnext(method);

}

returnnewConnection(route);

}

手机verifyfail怎么办

看雪ID:卓桐

https://bbs.pediy.com/user-670707.htm

*本文由看雪论坛 卓桐 原创,转载请注明来自看雪社区

进阶安全圈,不得不读的一本书

内容版权声明:除非注明原创否则皆为转载,再次转载请注明出处。

文章标题: 手机verifyfail怎么办

文章地址: www.58yuanyou.com/baike/347381.html

相关推荐