Android应用后台网络管控机制
Android应用后台网络管控机制
应用后台网络管控机制
概述
在维护手管应用时,经常遇到与应用后台网络控制相关的问题,在解决这些问题的过程中,学习了下应用后台网络控制的流程以及一些日志的分析方法,现在把它总结一下,方便自己以及他人的学习。
网络管控流程
对于后台网络管控主要的参与者如下:
safe:etworkManager
frameworks/base/services/core/java/com/android/server/net/etworkPolicyManagerService.java
frameworks/base/services/core/java/com/android/server/etworkManagementService.java注:这里其实还有个底层的网络守护进程的参与,但是我们这里不做太多描述,只描述框架层以上的逻辑。
在介绍总的流程时,先简单的介绍下etworkManager,顾名思义其是手管中用以控制网络管理的组件,而在应用后台管理时,主要有三种模式,如下。
从上图可以看出,三种模式中,智能模式其实是在应用规则前做了一层逻辑判断,但最终也是调用禁止或允许的接口,就不在赘述。
下面大致介绍下后台网络管控的流程。
public void updateBackgroundAppInfo(String pkgame, final int controlType, final int uid) {int uid_key = -1;//获取转换后的过滤uid值if (-1 != uid) {uid_key = uid;} else {//to do parse fensheng app uidLog.d(myTemp66, app install updateBackgroundAppInfo uid = -1);uid_key = transPkgToUid(mContext, pkgame);}//更新数据库boolean updateResult = trafficDataBase.updateAppControllType(uid, pkgame, controlType);Log.d(myTemp66, updateBackgroundAppInfo --> updateResult: updateResult pkgame: pkgame controlType: controlType uid: uid_key);if (TrafficCt.STATUS_VALUE_ITELLIGECE == controlType && updateResult) {//当为智能类型时,才用获取智能模式下的后台联网设置状态AppAlphameInfo alphameInfo = trafficAlphameManager.doQueryAlpmeApp(pkgame, TrafficCt.STATUS_BACKGROUD);Log.d(myTemp66, intelligence status: ());appBackGourndetControl(uid_key, alphameInfo.isWifiState(), alphameInfo.isMobileState());} else if (TrafficCt.STATUS_VALUE_REJECT == controlType && updateResult) {appBackGourndetControl(uid_key, false, false);(mContext, Mtj.CLICK_TRAFFIC_BGD_APP_BA, 后台联网应用禁止点击次数);} else if (TrafficCt.STATUS_VALUE_ALLOW == controlType && updateResult) {appBackGourndetControl(uid_key, true, true);(mContext, Mtj.CLICK_TRAFFIC_BGD_APP_ALLOW, 后台联网应用允许点击次数);}
}
首先,在用户修改模式后,etworkManager组件会调用updateBackgroundAppInfo()方法,而在这个方法中会调用updateAppControllType()方法去更新数据库,然后再调用appBackGourndetControl()去设置后台网络控制。
/*** 设置底层后台流量数据控制接口(通讯组接口)* @param uid 应用的UID* @param isWifiControl WIFI控制:true为打开,false为关闭* @param isMobileControl Mobile控制(与wifi类似)*/
public void appBackGourndetControl(int uid, boolean isWifiControl, boolean isMobileControl) {Log.i(TAG, appBackGourndetControl: uid: uid wifi: isWifiControl mobile: isMobileControl);if (isWifiControl) {//打开wifiif (!networkControllManager.isAppWifiBackgroundUsageOpened(uid)) {Log.d(TAG, appBackGourndetControl: change wifibackground open: uid);(uid);}} else {//关闭wifiif (networkControllManager.isAppWifiBackgroundUsageOpened(uid)) {Log.d(TAG, appBackGourndetControl: change wifibackground close: uid);(uid);}}if (isMobileControl) {//打开后台移动网络if (!networkControllManager.isAppMobileBackgroundUsageOpened(uid)) {Log.d(TAG, appBackGourndetControl: change mobilebackground open: uid);(uid);}} else {//关闭后台移动网络if (networkControllManager.isAppMobileBackgroundUsageOpened(uid)) {Log.d(TAG, appBackGourndetControl: change mobilebackground close: uid);(uid);}}
}public void closeAppWifiBackgroundUsage(String pkame) {int uid = PackageManagerUtil.getUid(pkame);Log.i(TAG, close uid= uid background wifi net);addUidPolicy(new Object[]{uid, getPolicyRejectAppBackgroundetWifi()});
}/*** 关闭网络.* @param args*/
private void addUidPolicy(Object... args) {Method addUidPolicyMethod = getAddUidPolicyMethod();try {addUidPolicyMethod.invoke(metWorkPolicyManager, args);} catch (IllegalAccessException e) {(TrafficCt.TRAFFIC_EXCEPTIO, TAG :addUidPolicy --> ());} catch (IllegalArgumentException e) {(TrafficCt.TRAFFIC_EXCEPTIO, TAG :addUidPolicy --> ());} catch (Exception e) {(TrafficCt.TRAFFIC_EXCEPTIO, TAG :addUidPolicy --> ());}
}
在appBackGourndetControl()方法中会通过etworkControllManager类去调用关闭后台联网的接口,最终通过反射调用到框架层etworkPolicyManagerService(PMS)类中的addUidPolicy()方法。
@Override
public void addUidPolicy(int uid, int policy) {(MAAGE_ETWORK_POLICY, TAG);if (!UserHandle.isApp(uid)) {throw new IllegalArgumentException(cannot apply policy to UID uid);}synchronized (mRulesLock) {final int oldPolicy = mUidPolicy.get(uid, POLICY_OE);policy |= oldPolicy;if (oldPolicy != policy) {setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);}}
}private void setUidPolicyUncheckedLocked(int uid, int policy, boolean persist) {mLastUidPolicy = getUidPolicy(uid);mUidPolicy.put(uid, policy);Slog.d(TAG, mLastUidPolicy mLastUidPolicy policy);updateRulesForUidWifiAndMobileLocked(uid);// uid policy changed, recompute rules and persist policy.updateRulesForDataUsageRestrictiLocked(uid);if (persist) {writePolicyLocked();}
}
在addUidPolicy()方法中,最主要的是调用了setUidPolicyUncheckedLocked()方法,在这方法中,flyme系统添加了updateRulesForUidWifiAndMobileLocked()方法,去设置对应UID进程的网络的规则变化。而对于应用前后台状态改变网络管理,最主要的是updateRulesForDataUsageRestrictiLocked()方法的管控,下面我们来看下该方法:
private void updateRulesForDataUsageRestrictiLocked(int uid, boolean uidDeleted) {...//获取进程的策略final int uidPolicy = mUidPolicy.get(uid, POLICY_OE);//获取进程旧规则final int oldUidRules = mUidRules.get(uid, RULE_OE);//判断应用进程的前后台状态final boolean isForeground = isUidForegroundOnRestrictBackgroundLocked(uid);//表示是否在黑名单final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUD) != 0;//表示是否在白名单final boolean isWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);//旧规则final int oldRule = oldUidRules & MASK_METERED_ETWORKS;//新规则int newRule = RULE_OE;// First step: define the new rule based on user restricti and foreground state.//第一步,根据用户设置与前后台状态定义新网络规则if (isForeground) {if (isBlacklisted || (mRestrictBackground && !isWhitelisted)) {//暂时允许规则newRule = RULE_TEMPORARY_ALLOW_METERED;} else if (isWhitelisted) {//允许规则newRule = RULE_ALLOW_METERED;}} else {if (isBlacklisted) {//拒绝规则newRule = RULE_REJECT_METERED;} else if (mRestrictBackground && isWhitelisted) {newRule = RULE_ALLOW_METERED;}}//获取新的进程规则int newUidRules = newRule | (oldUidRules & MASK_ALL_ETWORKS);if (LOGV) {Slog.i(TAG, updateRuleForRestrictBackgroundLocked( uid ) : isForeground= isForeground , isBlacklisted= isBlacklisted , isWhitelisted= isWhitelisted , oldRule= uidRulesToString(oldRule) , newRule= uidRulesToString(newRule) , newUidRules= uidRulesToString(newUidRules) , oldUidRules= uidRulesToString(oldUidRules));}if (!isForeground && (uidPolicy & POLICY_REJECT_APP_BACKGROUD_ET_MOBILE) != 0) {newUidRules |= RULE_REJECT_BACKGROUD_MOBILE;}if (!isForeground && (uidPolicy & POLICY_REJECT_APP_BACKGROUD_ET_WIFI) != 0) {newUidRules |= RULE_REJECT_BACKGROUD_WIFI;}boolean rulegBackgroundChanged = false;boolean ruleWifiBackgroundChanged = false;//第二步,根据状态的改变应用后台网控规则// Second step: apply bw changes based on change of state.//获取网络规则变化rulegBackgroundChanged = ((oldUidRules & RULE_REJECT_BACKGROUD_MOBILE)^ (newUidRules & RULE_REJECT_BACKGROUD_MOBILE)) != 0;ruleWifiBackgroundChanged = ((oldUidRules & RULE_REJECT_BACKGROUD_WIFI)^ (newUidRules & RULE_REJECT_BACKGROUD_WIFI)) != 0;Slog.i(TAG, rulegBackgroundChanged uid rulegBackgroundChanged);Slog.i(TAG, ruleWifiBackgroundChanged uid ruleWifiBackgroundChanged);if (rulegBackgroundChanged) {//获取移动数网络状态final boolean allow = (newUidRules & RULE_REJECT_BACKGROUD_MOBILE) == 0;Slog.i(TAG, rulegBackgroundChanged allow);try {//将规则设置到网络守护进程metworkManagerFlyme.setFirewallUidChainRule(uid, TYPE_MOBILE, allow);} catch (IllegalStateException e) {e.printStackTrace();} catch (RemoteException e) {e.printStackTrace();}}if (ruleWifiBackgroundChanged) {//获取无线网络状态final boolean allow = (newUidRules & RULE_REJECT_BACKGROUD_WIFI) == 0;Slog.i(TAG, ruleWifiBackgroundChanged allow);try {//将规则设置到网络守护进程metworkManagerFlyme.setFirewallUidChainRule(uid, TYPE_WIFI, allow);} catch (IllegalStateException e) {e.printStackTrace();} catch (RemoteException e) {e.printStackTrace();}}// @}if (newUidRules == RULE_OE) {mUidRules.delete(uid);} else {mUidRules.put(uid, newUidRules);}...//分发回调接口// Dispatch changed rule to existing (MSG_RULES_CHAGED, uid, newUidRules).sendToTarget();}
根据以上的代码,可以看到,后台网络控制主要分为两步:
- 第一步,根据用户设置与前后台状态定义新网络规则;
- 第二步,根据状态的改变应用后台网控规则;
- 第三步,回调状态改变消息。
在第一步里,有个判断进程前后台状态的方法isUidForegroundOnRestrictBackgroundLocked(),其最终调用的是isProcStateAllowedWhileOnRestrictBackgroundLocked()方法会根据进程的运状态去判断进程前后台的状态,当应用的状态小于等于所设定的值,系统即不认为应用处于后台状态,反之则是。
private boolean isUidForegroundOnRestrictBackgroundLocked(int uid) {final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);return isProcStateAllowedWhileOnRestrictBackgroundLocked(procState);
}static boolean isProcStateAllowedWhileOnRestrictBackgroundLocked(int procState) {// return procState <= ActivityManager.PROCESS_STATE_TOP;return procState <= ActivityManager.PROCESS_STATE_FOREGROUD_SERVICE;}
注:这里可能会是大多数应用现在无法被限制后台联网的原因,这是由于之前Google的GMS还未接入我们系统时,我们的设定的临界指是ActivityManager.PROCESS_STATE_TOP = 2,而接入Google的GMS后,由于要过CTS,用例要求我们需要将临界值修改为ActivityManager.PROCESS_STATE_FOREGROUD_SERVICE = 4;
这里需要提下:应用进入后台时,AMS通过Binder通知PMS, 然后PMS检测应用是否在后台(查看 AMS 传递过来的processState),在禁止后台联网情况下,应用若在后台,则禁止访问网络;否则就允许。这块的代码逻辑如下
final private IUidObserver mUidObserver = new IUidObserver.Stub() {@Override public void onUidStateChanged(int uid, int procState) throws RemoteException {Slog.i(TAG, onUidStateChanged uid= uid procState);synchronized (mRulesLock) {updateUidStateLocked(uid, procState);}updateetworkStats(uid, isUidStateForegroundLocked(procState));}@Override public void onUidGone(int uid) throws RemoteException {synchronized (mRulesLock) {removeUidStateLocked(uid);}updateetworkStats(uid, false);}@Override public void onUidActive(int uid) throws RemoteException {}@Override public void onUidIdle(int uid) throws RemoteException {}
};private void updateUidStateLocked(int uid, int uidState) {final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);if (oldUidState != uidState) {// state changed, push updated rulesmUidState.put(uid, uidState);updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState, uidState);if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)!= isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {if (isUidIdle(uid)) {updateRuleForAppIdleLocked(uid);}if (mDeviceIdleMode) {updateRuleForDeviceIdleLocked(uid);}if (mRestrictPower) {updateRuleForRestrictPowerLocked(uid);}updateRulesForPowerRestrictiLocked(uid);}}
}
第二步中,获取到的新规则会通过Binder通信,调用网络管理服务etworkManagementService(以下简称MS)中的setFirewallUidChainRule方法,如下:
public void setFirewallUidChainRule(int uid, int networkType, boolean allow) {//enforceSystemUid();final String MOBILE = mobile;final String WIFI = wifi;final String rule = allow ? allow : deny;final String chain = (networkType == 1) ? WIFI : MOBILE;try {//向网络守护进程发送执行事件(firewall, set_uid_fw_rule, uid, chain, rule);} catch (ativeDaemonConnectorException e) {throw e.rethrowAsParcelableException();}
}
紧接着MS会通过守护进程的连接者ativeDaemonConnector(DC)使用Socket通信向守护进程发送对应的事件,从而让底层去根据事件来做出对应的反馈。
注:这里的通信流程由于代码比较多,就不附上了,有兴趣的可以搜索源码中ativeDaemonConnector这个类去查看。
第三步,设置完规则后,PMS会回调进程网络规则改变的接口,通知整个Android该应用的规则改变,从而完成后台网络控制。
简单的绘制了下该过程的流程,如下。
日志分析
在分析这类网络问题的时候,学习了下日志分析方法,把它总结出来,以便学习查阅。
- 使用logreport抓取Log(包括etWork Log);
- 使用以下指令抓取应用的前后台状态oom_adj;
while [ 1 ];do date %Y-%m-%d-%H:%M:%S-%;adb shell dumpsys activity oom| sed -En -e /Proc .* trm:.*com.*\.youku/,/state: /p ;printf \n;sleep 1;done >oom_
注:这里的.youku需要换成指定应用的包名信息
- 使用以下指令抓取网络访问流量情况。
adb shell while [ 1 ];do cat /proc/net/xt_qtaguid/stats |grep \wlan0.*10081\;sleep 1;done
注:10081指的是应用进程的uid,根据不同的应用进行修改
Log
对于Log,最主要的是mainlog、netpolicy以及辅助的eventlog(用以查看应用前后台状态)。
分析mainlog时,首先从上层手管应用开始。
01-22 16:55:52.671 921 956 D myTemp66: 更新应用后台网络控制类型 记录已存在,更新 pkame=qqmusic, uid=10092
01-22 16:55:52.676 921 956 D myTemp66: updateBackgroundAppInfo --> updateResult:true pkgame:qqmusic controlType:0 uid:1009201-22 16:55:52.676 921 956 I TrafficControlImpl: appBackGourndetControl: uid:10092 wifi:false mobile:false
01-22 16:55:52.676 921 956 D TrafficControlImpl: appBackGourndetControl: change wifibackground close:10092
01-22 16:55:52.676 921 956 I trafficetworkControll: close uid=10092 background wifi net
01-22 16:55:52.715 921 956 D TrafficControlImpl: appBackGourndetControl: change mobilebackground close:10092
01-22 16:55:52.715 921 956 D trafficetworkControll: close uid=10092 background modern net
其中myTemp66指的是在修改模式后,手管去更新数据的打印日志,会根据更新的情况反馈不同的信息日志;TrafficControlImpl则是设置底层后台流量数据控制接口的日志;trafficetworkControll则是成功调用底层接口的标志,从这些log上我们可以了解上层应用逻辑是否存在问题。
其次是分析框架层日志。
//PMS检测到优酷进入后台,
01-22 16:55:5.926702 172 172 D WifiService: onReceive, action:android.intent.action.SCREE_OFF
01-22 16:55:5.92184 172 188 D etworkPolicy: rulegBackgroundChanged 10081 true
01-22 16:55:5.9228 172 188 D etworkPolicy: ruleWifiBackgroundChanged 10081 true
01-22 16:55:5.97140 172 188 D etworkPolicy: ruleWifiBackgroundChanged false // 禁止10081访问网络,并设定iptable
01-10 16:24:5.985761 21 172 I iptables: /system/bin/iptables -I wifi -m owner --uid-owner 10081 -j REJECT --reject-with icmp-net-prohibited// 但是很快又检测到 优酷到了前台,
01-22 16:55:54.067005 172 172 D WifiStateMachine: onReceive, action:android.intent.action.SCREE_O
01-22 16:55:54.082619 172 188 D etworkPolicy: rulegBackgroundChanged 10081 true
01-22 16:55:54.082675 172 188 D etworkPolicy: ruleWifiBackgroundChanged 10081 true
01-22 16:55:54.117942 172 188 D etworkPolicy: ruleWifiBackgroundChanged true // 设定 优酷 允许访问网络
01-22 16:55:54.1298 21 172 I iptables: /system/bin/iptables -D wifi -m owner --uid-owner 10081 -j REJECT --reject-with icmp-net-prohibited01-22 16:56:01.57 172 188 I etworkPolicy: onUidStateChanged uid=10081 2//前台进程UID状态
01-22 16:56:19.745 172 188 I etworkPolicy: onUidStateChanged uid=10081 //后台进程UID状态
etworkPolicy: ruleWifiBackgroundChanged/rulegBackgroundChanged false
通过这条日志,可以判断进程在后台时的wifi或移动数据的状态,true表示可以联网,false表示禁止联网。iptables: /system/bin/iptables -I wifi -m owner --uid-owner 10081 -j REJECT --reject-with icmp-net-prohibited
将联网信息设定到iptable中。通过以上日志就可以分析出,出问题应用进程在后台联网的状态。
然后再根据dump中的netpolicy日志中的UID=10081 policy=[]REJECT_APP_BACKGROUD_ET_MOBILE
进一步确认后台联网规则。
REJECT_APP_BACKGROUD_ET_WIFI
从以上日志里,基本上可以提炼出一个应用进程从上层到框架层的后台联网信息。
注:上面的日志最后两条,onUidStateChanged,表示的就是AMS向PMS发送进程状态改变的消息,最后一列的值表示进程在的状态值具体参考以下数据。
/** @hide Process is a persistent system process. */
public static final int PROCESS_STATE_PERSISTET = 0;/** @hide Process is a persistent system process and is doing UI. */
public static final int PROCESS_STATE_PERSISTET_UI = 1;/** @hide Process is hosting the current top activities. ote that this covers* all activities that are visible to the user. */
public static final int PROCESS_STATE_TOP = 2;/** @hide Process is hosting a foreground service due to a system binding. */
public static final int PROCESS_STATE_BOUD_FOREGROUD_SERVICE = ;/** @hide Process is hosting a foreground service. */
public static final int PROCESS_STATE_FOREGROUD_SERVICE = 4;/** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */
public static final int PROCESS_STATE_TOP_SLEEPIG = 5;/** @hide Process is important to the user, and something they are aware of. */
public static final int PROCESS_STATE_IMPORTAT_FOREGROUD = 6;/** @hide Process is important to the user, but not something they are aware of. */
public static final int PROCESS_STATE_IMPORTAT_BACKGROUD = 7;/** @hide Process is in the background running a backup/restore operation. */
public static final int PROCESS_STATE_BACKUP = 8;/** @hide Process is in the background, but it can t restore its state so we want* to try to avoid killing it. */
public static final int PROCESS_STATE_HEAVY_WEIGHT = 9;/** @hide Process is in the background running a service. Unlike oom_adj, this level* is used for both the normal running in background state and the executing* operati state. */
public static final int PROCESS_STATE_SERVICE = 10;/** @hide Process is in the background running a receiver. ote that from the* perspective of oom_adj receivers run at a higher foreground level, but for our* prioritization here that is not necessary and putting them below services means* many fewer changes in some process states as they receive broadcasts. */
public static final int PROCESS_STATE_RECEIVER = 11;/** @hide Process is in the background but hosts the home activity. */
public static final int PROCESS_STATE_HOME = 12;/** @hide Process is in the background but hosts the last shown activity. */
public static final int PROCESS_STATE_LAST_ACTIVITY = 1;/** @hide Process is being cached for later use and contains activities. */
public static final int PROCESS_STATE_CACHED_ACTIVITY = 14;/** @hide Process is being cached for later use and is a client of another cached* process that contains activities. */
public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIET = 15;/** @hide Process is being cached for later use and is empty. */
public static final int PROCESS_STATE_CACHED_EMPTY = 16;
oom_adj分析
oom_adj是dumpsys activity p 中表示应用进程状态的信息,以下是截取的QQ应用以及在机器的上的前后台信息。
QQ前台状态
2018-02-06-15:01:10-62598404
Proc # 0: fore T/A/T trm: 0 1625:mobileqq/u0a100 (top-activity)
oom: max=1001 curRaw=0 setRaw=0 cur=0 set=0
state: cur=T set=T lastPss=166MB lastSwapPss=11MB lastCachedPss=0.00
Proc # 6: vis F/ /T trm: 0 18259:mobileqq:TMAssistantDownloadSDKService/u0a100 (service)
mobileqq/tmdownloader.TMAssistantDownloadService<=Proc{1625:mobileqq/u0a100}
oom: max=1001 curRaw=100 setRaw=100 cur=100 set=100
state: cur=T set=T lastPss=21MB lastSwapPss=60KB lastCachedPss=0.00
Proc # 1: vis F/ /SB trm: 0 16285:mobileqq:MSF/u0a100 (service)
mobileqq/.msf.service.MsfService<=Proc{2121:mobileqq:qzone/u0a100}
oom: max=1001 curRaw=100 setRaw=100 cur=100 set=100
state: cur=SB set=SB lastPss=28MB lastSwapPss=4.MB lastCachedPss=0.00
Proc # 5: svc B/ /S trm: 0 2121:mobileqq:qzone/u0a100 (started-services)
oom: max=1001 curRaw=500 setRaw=500 cur=500 set=500
state: cur=S set=S lastPss=0.00 lastSwapPss=0.00 lastCachedPss=0.00QQ后台状态2018-02-06-15:01:11-698162429
Proc # 6: prcp F/ /SB trm: 0 18259:mobileqq:TMAssistantDownloadSDKService/u0a100 (service)
mobileqq/tmdownloader.TMAssistantDownloadService<=Proc{1625:mobileqq/u0a100}
oom: max=1001 curRaw=200 setRaw=200 cur=200 set=200
state: cur=SB set=SB lastPss=21MB lastSwapPss=60KB lastCachedPss=0.00
Proc # 2: prcp F/ /SB trm: 0 16285:mobileqq:MSF/u0a100 (service)
mobileqq/.msf.service.MsfService<=Proc{1625:mobileqq/u0a100}
oom: max=1001 curRaw=200 setRaw=200 cur=200 set=200
state: cur=SB set=SB lastPss=28MB lastSwapPss=4.MB lastCachedPss=0.00
Proc # 1: prcp F/S/SB trm: 0 1625:mobileqq/u0a100 (fg-service)
oom: max=1001 curRaw=200 setRaw=200 cur=200 set=200
state: cur=SB set=SB lastPss=166MB lastSwapPss=11MB lastCachedPss=0.00
Proc # 5: svc B/ /S trm: 0 2121:mobileqq:qzone/u0a100 (started-services)
oom: max=1001 curRaw=500 setRaw=500 cur=500 set=500
state: cur=S set=S lastPss=0.00 lastSwapPss=0.00 lastCachedPss=0.00前台状态
2018-02-06-15:55:22-7417581
Proc # 0: fore T/A/T trm: 0 2765:mm/u0a99 (top-activity)
oom: max=1001 curRaw=0 setRaw=0 cur=0 set=0
state: cur=T set=T lastPss=18MB lastSwapPss=8.8MB lastCachedPss=76MB
Proc # : vis F/ /SB trm: 0 14557:mm:push/u0a99 (service)
mm/.booter.CoreService<=Proc{2765:mm/u0a99}
oom: max=1001 curRaw=100 setRaw=100 cur=100 set=100
state: cur=SB set=SB lastPss=15MB lastSwapPss=.4MB lastCachedPss=0.00
Proc #6: svcb B/ /S trm: 0 24482:mm:sandbox/u0a99 (started-services)
oom: max=1001 curRaw=800 setRaw=800 cur=800 set=800
state: cur=S set=S lastPss=24MB lastSwapPss=08KB lastCachedPss=0.00
Proc # 5: cch B/ /CE trm: 0 25785:mm:appbrand0/u0a99 (cch-empty)
oom: max=1001 curRaw=900 setRaw=900 cur=900 set=900
state: cur=CE set=CE lastPss=14MB lastSwapPss=240KB lastCachedPss=14MB
Proc #19: cch2 B/ /CE trm: 0 25918:mm:tools/u0a99 (cch-empty)
oom: max=1001 curRaw=902 setRaw=902 cur=902 set=902
state: cur=CE set=CE lastPss=17MB lastSwapPss=255KB lastCachedPss=17MB后台状态
2018-02-06-15:55:2-80229592
Proc # : svc B/ /S trm: 0 14557:mm:push/u0a99 (started-services)
oom: max=1001 curRaw=500 setRaw=500 cur=500 set=500
state: cur=S set=S lastPss=15MB lastSwapPss=.4MB lastCachedPss=0.00
Proc # 1: prev B/ /S trm: 0 2765:mm/u0a99 (cch-started-ui-services)
oom: max=1001 curRaw=700 setRaw=700 cur=700 set=700
state: cur=S set=S lastPss=18MB lastSwapPss=8.8MB lastCachedPss=76MB
Proc #6: svcb B/ /S trm: 0 24482:mm:sandbox/u0a99 (started-services)
oom: max=1001 curRaw=800 setRaw=800 cur=800 set=800
state: cur=S set=S lastPss=24MB lastSwapPss=08KB lastCachedPss=0.00
Proc # 5: cch B/ /CE trm: 0 25785:mm:appbrand0/u0a99 (cch-empty)
oom: max=1001 curRaw=900 setRaw=900 cur=900 set=900
state: cur=CE set=CE lastPss=14MB lastSwapPss=240KB lastCachedPss=14MB
Proc #19: cch2 B/ /CE trm: 0 25918:mm:tools/u0a99 (cch-empty)
oom: max=1001 curRaw=902 setRaw=902 cur=902 set=902
state: cur=CE set=CE lastPss=17MB lastSwapPss=255KB lastCachedPss=17MB
从log中可以清楚的看到状态信息的变化,从这边的结果看,QQ是无法正常禁止后台联网,可以(可能第一个消息收的到,后面发的消息收不到)。而产生这个问题的原因是这样的,谷歌CTS要求我们的网控机制判断应用前后台的状态的临界点是ActivityManager.PROCESS_STATE_FOREGROUD_SERVICE = 4,qq退到后台的状态是ActivityManager.PROCESS_STATE_BOUD_FOREGROUD_SERVICE = ,不满足我们禁网的条件;退到后台的状态是ActivityManager.PROCESS_STATE_SERVICE = 10,满足禁网的条件,所以才会导致这样的问题。
因此以后遇到这类的问题,可以先从这步入手。
流量log
抓这个log主要是为了查看应用在后台联网时,是否有流量的使用,直接上图吧。
结语
基本上一个应用的后台联网问题,可以通过以上分析方法去分析,然后根据结果去对应的人设去处理,上述分析,如有问题或者疑问可以相互交流。
#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
下一篇:Dns执行流程和流量劫持
推荐阅读
留言与评论(共有 11 条评论) |
本站网友 dermes | 3分钟前 发表 |
52.676 921 956 D TrafficControlImpl | |
本站网友 你永远不懂我的心 | 13分钟前 发表 |
其最终调用的是isProcStateAllowedWhileOnRestrictBackgroundLocked()方法会根据进程的运状态去判断进程前后台的状态,当应用的状态小于等于所设定的值,系统即不认为应用处于后台状态,反之则是 | |
本站网友 taoshi | 24分钟前 发表 |
final int controlType | |
本站网友 不越狱安装软件 | 4分钟前 发表 |
addUidPolicy --> ());} catch (Exception e) {(TrafficCt.TRAFFIC_EXCEPTIO | |
本站网友 昆明地震 | 24分钟前 发表 |
55 | |
本站网友 王昌顺 | 13分钟前 发表 |
流量log 抓这个log主要是为了查看应用在后台联网时,是否有流量的使用,直接上图吧 | |
本站网友 康维多奶粉怎么样 | 15分钟前 发表 |
2-80229592 Proc # | |
本站网友 dnf华北二区 | 30分钟前 发表 |
第三步,设置完规则后,PMS会回调进程网络规则改变的接口,通知整个Android该应用的规则改变,从而完成后台网络控制 | |
本站网友 大话西游论坛 | 26分钟前 发表 |
52.676 921 956 D myTemp66 | |
本站网友 上海铁路网 | 19分钟前 发表 |
change wifibackground close |