1. AppStateInfoCollector.reportAppStateEventInfo
package com.android.server.power;
public class AppStateInfoCollector {
// return true: for new app state
// false: for others
public boolean reportAppStateEventInfo(String packageName, int userId, int stateEvent) {
ArrayMap<String, AppState> mAppStateInfoList = getAppStateInfoList(userId);
//update mAppStateInfoList
int index = mAppStateInfoList.indexOfKey(packageName);
AppState appState = null;
boolean ret = true;
if (DEBUG) Slog.d(TAG, "- reportAppStateEventInfo() E -");
if (index >= 0) {
appState = mAppStateInfoList.valueAt(index);
appState.updateAppState(stateEvent);
ret = false;
} else {
appState = buildAppState(packageName, userId, stateEvent);
mAppStateInfoList.put(packageName, appState);
}
return ret;
}
2. PowerController.handleAppStateChanged
package com.android.server.power;
public class PowerController //extends IPowerController.Stub
extends UsageStatsManagerInternal.AppStateEventChangeListener {
private void handleAppStateChanged(String packageName, int userId, int state) {
int oldState = state;
...
if (mAppStateInfoCollector.reportAppStateEventInfo(packageName, userId, state)) {
// Note: Bug 698133 appIdle cts fail -->BEG
// Ugly: we have to check if doing cts/gts test
// is cts/gts test, then
checkCtsGtsTesting(packageName);
// Note: Bug 698133 appIdle cts fail <--END
}
- 检查是否正在为CTS或gts测试
// Note: Bug 698133 appIdle cts fail -->BEG
// check if doing cts/gts test
private void checkCtsGtsTesting(String pkgName) {
// Ugly: we have to check if doing cts/gts test
// is cts/gts test, then
// 通过包名规则判断
if (mIgnoreProcStateForAppIdle && Util.isCts(pkgName)) {
if (DEBUG) Slog.d(TAG, "CTS/GTS app: " + pkgName + ", see as doing cts/gts test, clear mIgnoreProcStateForAppIdle!!");
try {
//LocalServices.getService(NetworkPolicyManagerInternal.class).setIgnoreProcStateForAppIdle(false);
PowerControllerHelper.getInstance(mContext).setIgnoreProcStateForAppIdle(false);
mIgnoreProcStateForAppIdle = false;
} catch (Exception e) {
Slog.d(TAG, "E:ignoreProcStateForAppIdle: " + e);
}
}
}
3. PowerController.onAppStateEventChanged MSG事件处理
//Message define
static final int MSG_APP_STATE_CHANGED = 0;
switch (msg.what) {
case MSG_APP_STATE_CHANGED:
handleAppStateChanged((String)msg.obj, msg.arg1, msg.arg2);
break;
public void onAppStateEventChanged(String packageName, int userId, int state) {
msgHandler.sendMessage(msgHandler.obtainMessage(MSG_APP_STATE_CHANGED, userId, state, packageName));
}
4. grep -irn “onAppStateEventChanged” frameworks/
查看事件触发位置
- root@69959bbb90c6:/home/suhuazhi/8.1/op54_int# grep -irn “onAppStateEventChanged” frameworks/
frameworks/base/services/usage/java/com/android/server/usage/UsageStatsService.java:1803: listener.onAppStateEventChanged(packageName, userId, state);
frameworks/base/core/java/android/app/usage/UsageStatsManagerInternal.java:148: public abstract void onAppStateEventChanged(String packageName, int userId, int stateEvent);
- frameworks/base/core/java/android/app/usage/UsageStatsManagerInternal.java
package android.app.usage;
/**
* UsageStatsManager local system service interface.
*
* {@hide} Only for use within the system server.
*/
public abstract class UsageStatsManagerInternal {
// 定义一个监听器
public static abstract class AppStateEventChangeListener {
public abstract void onAppStateEventChanged(String packageName, int userId, int stateEvent);
}
//
- frameworks/base/services/usage/java/com/android/server/usage/UsageStatsService.java
// inone add start by suhuazhi for powersave
public void informAppStateEventChangeListeners(String packageName, int userId, int state) {
for (UsageStatsManagerInternal.AppStateEventChangeListener listener : mAppStateEventListeners) {
listener.onAppStateEventChanged(packageName, userId, state);
}
}
// inone add end by suhuazhi for powersave
5. UsageStatsService.PowerControllerHelper.informAppStateEventChangeListeners
package com.android.server.usage;
/**
* A service that collects, aggregates, and persists application usage data.
* This data can be queried by apps that have been granted permission by AppOps.
*/
public class UsageStatsService extends SystemService implements
UserUsageStatsService.StatsUpdatedListener {
private final class PowerControllerHelper {
static final int MSG_INFORM_APP_STATE = MSG_ONE_TIME_CHECK_IDLE_STATES + 1;
public void informAppStateEventChangeListeners(String packageName, int userId, int state) {
for (UsageStatsManagerInternal.AppStateEventChangeListener listener : mAppStateEventListeners) {
listener.onAppStateEventChanged(packageName, userId, state);
}
}
public boolean handleMessage(Message msg) {
boolean ret = false;
switch (msg.what) {
case MSG_INFORM_APP_STATE:
informAppStateEventChangeListeners((String)msg.obj, msg.arg1, msg.arg2);
ret = true;
break;
}
return ret;
}
}
6. UsageStatsService.PowerControllerHelper.reportEvent
package com.android.server.usage;
/**
* A service that collects, aggregates, and persists application usage data.
* This data can be queried by apps that have been granted permission by AppOps.
*/
public class UsageStatsService extends SystemService implements
UserUsageStatsService.StatsUpdatedListener {
public boolean reportEvent(UsageEvents.Event event, int userId, boolean previouslyIdle, long elapsedRealtime) {
final boolean forceIdle = mAppIdleHistory.isForceIdleFlagSet(
event.mPackage, userId, elapsedRealtime);
if (!forceIdle
|| event.mEventType == Event.MOVE_TO_FOREGROUND
|| event.mEventType == Event.USER_INTERACTION) {
mAppIdleHistory.reportUsage(event.mPackage, userId, elapsedRealtime);
if (previouslyIdle) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
/* idle = */ 0, event.mPackage));
notifyBatteryStats(event.mPackage, userId, false);
}
}
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_APP_STATE, userId, event.mEventType, event.mPackage));
return true;
}
7. UsageStatsService.reportEvent
/**
* Called by the Binder stub.
*/
void reportEvent(UsageEvents.Event event, int userId) {
...
if (mPowerControllerHelper != null
&& mPowerControllerHelper.reportEvent(event, userId, previouslyIdle, elapsedRealtime)) {
return;
}
....
8. reportEvent触发事件源
8.1 进程前台和后台状态切换
if (resumed) {
if (mUsageStatsService != null) {
mUsageStatsService.reportEvent(component.realActivity, component.userId,
UsageEvents.Event.MOVE_TO_FOREGROUND);
}
....
} else {
if (mUsageStatsService != null) {
mUsageStatsService.reportEvent(component.realActivity, component.userId,
UsageEvents.Event.MOVE_TO_BACKGROUND);
}
......
}
8.1 SYSTEM_INTERACTION 状态变更
AcitivityManagerService#applyOomAdjLocked() -> ActivityManagerService#maybeUpdateUsageStatsLocked() -> mUsageStatsService.reportEvent(packages[i], app.userId, UsageEvents.Event.SYSTEM_INTERACTION);
if (eventType != UsageEvents.Event.SYSTEM_INTERACTION) {
usageStats.mLastTimeUsed = timeStamp;
}
8.3 /data/system/usagestats 数据存储
- 手机关机,具体见:UsageStatsService.java#shutdown
- 系统时间跳变(如人为修改系统时间或时间随网络校准)
- 一天结束时,因为daily下面xml文件存储一天的数据,此时需下次新建文件
- …
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<usagestats version="1" endTime="93054">
<packages>
<package lastTimeActive="92995" package="com.android.settings" timeActive="87841" lastEvent="2" />
<package lastTimeActive="93054" package="com.miui.home" timeActive="5076" lastEvent="1" />
</packages>
<configurations>
<config lastTimeActive="0" timeActive="0" count="1" active="true" fs="1065353216" locales="zh-CN" touch="3" key="1" keyHid="1" hardKeyHid="2" nav="1" navHid="2" ori="1" scrLay="268435810" ui="17" width="360" height="620" sw="360" density="480" />
</configurations>
<event-log>
<event time="0" package="com.android.settings" class="com.android.settings.UsageStatsActivity" type="2" />
<event time="61" package="com.miui.home" class="com.miui.home.launcher.Launcher" type="1" />
<event time="5137" package="com.miui.home" class="com.miui.home.launcher.Launcher" type="2" />
<event time="5154" package="com.android.settings" class="com.android.settings.MiuiSettings" type="1" />
<event time="92995" package="com.android.settings" class="com.android.settings.MiuiSettings" type="2" />
<event time="93054" package="com.miui.home" class="com.miui.home.launcher.Launcher" type="1" />
</event-log>
</usagestats>
XML中package的lastEvent字段,event-log的type字段,都是指上面介绍过的事件类型。但是注意,事件类型是有7种,但真正记录在XML中,除了4种(MOVE_TO_FOREGROUND,MOVE_TO_BACKGROUND,END_OF_DAY,CONTINUE_PREVIOUS_DAY)记录其int值,其他的事件(CONFIGURATION_CHANGE,SYSTEM_INTERACTION,USER_INTERACTION)都记录为0