1. 现象描述
处于deep idle下,默认唯品会为doze 的黑名单,按照doze机制,正常来说应该是被限制联网,实际测试发现存在deep idle状态进行联网。
2. 查看doze白名单和联网防火墙白名单
2.1 doze白名单
$ dumpsys deviceidle
Whitelist all app ids:
1000
1001
2000
2951
10054
10063
10071
10120
10136
10141
10165
10167
10169
2.2 联网防火墙白名单
dumpsys deviceidle step
Stepped to deep: IDLE
dumpsys netpolicy|grep -E "com.achievo.vipshop|10179"
UID=10179 state=5 (fg svc) rules=32 (ALLOW_ALL|NONE)
UID=10179 rules=32 (ALLOW_ALL|NONE)
2019-11-20T13:34:26:830 - Firewall rules changed for dozable; uids=[1000, 1001, 1068, 1073, 2000, 2951, 10054, 10063, 10068, 10071, 10072, 10114, 10120, 10136, 10141, 10165, 10167, 10169, 10179, 10189]; rules=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
3. 原因
3.1 查看唯品会的 adj 优先级
oom: max=1001 curRaw=200 setRaw=200 cur=200 set=200
com.achievo.vipshop的adj 为200
adb shell dumpsys activity processes com.achievo.vipshop
ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)
All known processes:
*APP* UID 10179 ProcessRecord{ebdade8 11280:com.achievo.vipshop.MqttService/u0a179}
user #0 uid=10179 gids={50179, 20179, 9997, 3002, 3003, 3001}
mRequiredAbi=armeabi instructionSet=arm
class=android.taobao.atlas.startup.AtlasBridgeApplication
dir=/data/app/com.achievo.vipshop-H8wnNWvEQxa2feN7cMF4KQ==/base.apk publicDir=/data/app/com.achievo.vipshop-H8wnNWvEQxa2feN7cMF4KQ==/base.apk data=/data/user/0/com.achievo.vipshop
packageList={com.achievo.vipshop}
compat={320dpi}
thread=android.app.IApplicationThread$Stub$Proxy@7620cb8
pid=11280 starting=false
lastActivityTime=-1h55m3s344ms lastPssTime=-41m41s555ms pssStatType=0 nextPssTime=+18m18s187ms
adjSeq=26756 lruSeq=6917 lastPss=42MB lastSwapPss=31MB lastCachedPss=0.00 lastCachedSwapPss=0.00
procStateMemTracker: best=1 (1=1 437.8939x)
cached=false empty=true
notCachedSinceIdle=true initialIdlePss=43148
oom: max=1001 curRaw=200 setRaw=200 cur=200 set=200
lastCompactTime=0 lastCompactAction=0 mCurSchedGroup=2 setSchedGroup=2 systemNoUi=false trimMemoryLevel=10
curProcState=5 mRepProcState=5 pssProcState=5 setProcState=5 lastStateTime=-2h36m1s729ms
mHasForegroundServices=true forcingToImportant=null
reportedInteraction=true time=-1h25m35s368ms fgInteractionTime=-22h2m39s627ms
hasStartedServices=true
startSeq=556
mountMode=DEFAULT
3.2 deep idle下仍旧允许联网的源码
public static final int FOREGROUND_THRESHOLD_STATE =
ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
/**
* Returns true if {@param procState} is considered foreground and as such will be allowed
* to access network when the device is in data saver mode. Otherwise, false.
* 如果为前台属性之上(procState 小于6)的第三方应用,则豁免
*/
public static boolean isProcStateAllowedWhileOnRestrictBackground(int procState) {
return procState <= FOREGROUND_THRESHOLD_STATE;// 6
}
3.3 adj 与进程状态的关系
adj 200 与 PROCESS_STATE 的算法关系
// This is a process only hosting components that are perceptible to the
// user, and we really want to avoid killing them, but they are not
// immediately visible. An example is background music playback.
static final int PERCEPTIBLE_APP_ADJ = 200;
/** @hide Process is hosting a foreground service. */
@UnsupportedAppUsage
public static final int PROCESS_STATE_FOREGROUND_SERVICE = 5;
/** @hide Process is hosting a foreground service due to a system binding. */
@UnsupportedAppUsage
public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6;
/** @hide Process is important to the user, and something they are aware of. */
public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 7;
} else if (app.getActiveInstrumentation() != null) {
// Don't want to kill running instrumentation.
adj = ProcessList.FOREGROUND_APP_ADJ; // adj 为 200
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.adjType = "instrumentation";
procState = PROCESS_STATE_FOREGROUND_SERVICE;// 进程状态为5
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
}