一,首先介绍下APP状态监听的两个入口:
1.UsageStatsService 收集,汇总和保留应用程序使用情况数据的服务。
2.IUidObserver 监听进程状态变化
我们做的App状态监听都是基于这连个入口展开
二,框架搭建
AppState.java APP状态的对象类,每个APP都作为一个单独的对象处理
AppStateInfoCollector.java APP状态管理类
PowerController.java 省电管理统筹管理类
Util.java 工具类
三,UsageStatsService 相关类介绍,以及源码修改
UsageEvents.java 实现了内部类Event,主要用于记录app的event
UsageStatsManagerInternal.java 抽象类,在UsageStatsService.java中实现
UsageStatsManager.java UsageStatsService的管理类
因为我们新建了PowerController.java作为省电管理统筹管理类,所以我们需要UsageStatsService给我们暴露出一个接口来实时获取到APP状态的变化
所以先在UsageStatsManagerInternal.java中添加一个抽象类AppStateEventChangeListener,添加onAppStateEventChanged()抽象方法,并添加抽象监听接口和取消监听的接口
//add by lzq for power 20200915 start
public abstract void addAppStateEventChangeListener(
AppStateEventChangeListener listener);
public abstract void removeAppStateEventChangeListener(
AppStateEventChangeListener listener);
public static abstract class AppStateEventChangeListener {
public abstract void onAppStateEventChanged(String packageName, int userId, int stateEvent);
}
//add by lzq for power 20200915 end
UsageStatsService的内部类LocalService继承了UsageStatsManagerInternal,所以需要在LocalService中实现这俩抽象方法
/*add by lzq for power 20200916 start*/
@Override
public void addAppStateEventChangeListener(AppStateEventChangeListener listener) {
if (mPowerControllerHelper != null)
mPowerControllerHelper.addAppStateEventChangeListener(listener);
}
@Override
public void removeAppStateEventChangeListener(AppStateEventChangeListener listener) {
if (mPowerControllerHelper != null)
mPowerControllerHelper.removeAppStateEventChangeListener(listener);
}
/*add by lzq for power 20200916 end*/
PowerControllerHelper是在UsageStatsService中添加的一个内部类,作为UsageStatsService和PowerController的中间桥梁
/*add by lzq for power 20200916 start*/
private PowerControllerHelper mPowerControllerHelper;
private final class PowerControllerHelper {
static final int MSG_INFORM_APP_STATE = MSG_UID_STATE_CHANGED + 2;
private ArrayList<UsageStatsManagerInternal.AppStateEventChangeListener>
mAppStateEventListeners = new ArrayList<>();
public boolean reportEvent(UsageEvents.Event event, int userId, long elapsedRealtime) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_APP_STATE, userId, event.mEventType, event.mPackage));
return true;
}
public void informAppStateEventChangeListeners(String packageName, int userId, int state) {
synchronized (mAppStateEventListeners) {
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;
}
public void addAppStateEventChangeListener(UsageStatsManagerInternal.AppStateEventChangeListener listener) {
synchronized (mAppStateEventListeners) {
if (!mAppStateEventListeners.contains(listener)) {
mAppStateEventListeners.add(listener);
}
}
}
public void removeAppStateEventChangeListener(
UsageStatsManagerInternal.AppStateEventChangeListener listener) {
synchronized (mAppStateEventListeners) {
mAppStateEventListeners.remove(listener);
}
}
}
/*add by lzq for power 20200916 end*/
让PowerController.java继承UsageStatsManagerInternal.AppStateEventChangeListener,实现onAppStateEventChanged()方法,注册监听
mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class);
// register
mUsageStatsInternal.addAppStateEventChangeListener(this);
当UsageStatsService监听到app状态变化的时候,调用PowerControllerHelper的reportEvent()
void reportEvent(Event event, int userId) {
......
/*add by lzq for power 20200916 start*/
if (mPowerControllerHelper != null) {
mPowerControllerHelper.reportEvent(event, userId, elapsedRealtime);
}
/*add by lzq for power 20200916 end*/
......
}
在reportEvent()发送MSG_INFORM_APP_STATE信息,调用informAppStateEventChangeListeners(),这里调用接口onAppStateEventChanged(),而我们的PowerController.java实现了这个接口,这就是UsageStatsService和我们的PowerController一个大致交互流程
四,IUidObserver介绍以及进程主要状态介绍
IUidObserver 有五个方法,一般我们只需要关注onUidGone(进程被杀调用)和onUidStateChanged(进程创建和进程状态变化,都会被调用)
/** {@hide} */
oneway interface IUidObserver {
// WARNING: when these transactions are updated, check if they are any callers on the native
// side. If so, make sure they are using the correct transaction ids and arguments.
// If a transaction which will also be used on the native side is being inserted, add it to
// below block of transactions.
// Since these transactions are also called from native code, these must be kept in sync with
// the ones in frameworks/native/include/binder/IActivityManager.h
// =============== Beginning of transactions used on native side as well ======================
/**
* Report that there are no longer any processes running for a uid.
*/
void onUidGone(int uid, boolean disabled);
/**
* Report that a uid is now active (no longer idle).
*/
void onUidActive(int uid);
/**
* Report that a uid is idle -- it has either been running in the background for
* a sufficient period of time, or all of its processes have gone away.
*/
void onUidIdle(int uid, boolean disabled);
/**
* General report of a state change of an uid.
*
* @param uid The uid for which the state change is being reported.
* @param procState The updated process state for the uid.
* @param procStateSeq The sequence no. associated with process state change of the uid,
* see UidRecord.procStateSeq for details.
*/
void onUidStateChanged(int uid, int procState, long procStateSeq);
// =============== End of transactions used on native side as well ============================
/**
* Report when the cached state of a uid has changed.
* If true, a uid has become cached -- that is, it has some active processes that are
* all in the cached state. It should be doing as little as possible at this point.
* If false, that a uid is no longer cached. This will only be called after
* onUidCached() has been reported true. It will happen when either one of its actively
* running processes is no longer cached, or it no longer has any actively running processes.
*/
void onUidCachedChanged(int uid, boolean cached);
}
进程主要状态,这些变量定义在ActivityManager.java中
/** @hide Not a real process state. */
public static final int PROCESS_STATE_UNKNOWN = -1;//Not a real process state
/** @hide Process is a persistent system process. */
public static final int PROCESS_STATE_PERSISTENT = 0;//persistent系统进程
/** @hide Process is a persistent system process and is doing UI. */
public static final int PROCESS_STATE_PERSISTENT_UI = 1;//persistent系统进程,并正在执行UI操作
/** @hide Process is hosting the current top activities. Note that this covers
* all activities that are visible to the user. */
@UnsupportedAppUsage
public static final int PROCESS_STATE_TOP = 2;//拥有当前用户可见的top Activity
/** @hide Process is hosting a foreground service with location type. */
public static final int PROCESS_STATE_FOREGROUND_SERVICE_LOCATION = 3;//进程正在托管具有位置类型的前台服务
/** @hide Process is bound to a TOP app. This is ranked below SERVICE_LOCATION so that
* it doesn't get the capability of location access while-in-use. */
public static final int PROCESS_STATE_BOUND_TOP = 4;//进程绑定到TOP应用程序。 它的排名低于SERVICE_LOCATION,因此在使用中无法获得位置访问的功能。
/** @hide Process is hosting a foreground service. */
@UnsupportedAppUsage
public static final int PROCESS_STATE_FOREGROUND_SERVICE = 5;//拥有一个前台Service
/** @hide Process is hosting a foreground service due to a system binding. */
@UnsupportedAppUsage
public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6;//拥有一个前台Service,且由系统绑定
/** @hide Process is important to the user, and something they are aware of. */
public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 7;//对用户很重要的进程,用户可感知其存在
/** @hide Process is important to the user, but not something they are aware of. */
@UnsupportedAppUsage
public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 8;//进程对用户很重要,但对用户而言并不重要
/** @hide Process is in the background transient so we will try to keep running. */
public static final int PROCESS_STATE_TRANSIENT_BACKGROUND = 9;//进程处于后台过渡状态,因此我们将尝试继续运行
/** @hide Process is in the background running a backup/restore operation. */
public static final int PROCESS_STATE_BACKUP = 10;//后台进程,正在运行backup/restore操作
/** @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
* operations state. */
@UnsupportedAppUsage
public static final int PROCESS_STATE_SERVICE = 11;//后台进程,且正在运行service
/** @hide Process is in the background running a receiver. Note 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. */
@UnsupportedAppUsage
public static final int PROCESS_STATE_RECEIVER = 12;//后台进程,且正在运行receiver
/** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */
public static final int PROCESS_STATE_TOP_SLEEPING = 13;//拥有当前用户可见的top Activity,but while device is sleeping.
/** @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 = 14;//后台进程,但无法执行restore,因此尽量避免kill该进程
/** @hide Process is in the background but hosts the home activity. */
@UnsupportedAppUsage
public static final int PROCESS_STATE_HOME = 15;//后台进程,且拥有home Activity
/** @hide Process is in the background but hosts the last shown activity. */
public static final int PROCESS_STATE_LAST_ACTIVITY = 16;//后台进程,且拥有上一次显示的Activity
/** @hide Process is being cached for later use and contains activities. */
@UnsupportedAppUsage
public static final int PROCESS_STATE_CACHED_ACTIVITY = 17;//进程处于cached状态,且内含Activity
/** @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_CLIENT = 18;//进程处于cached状态,且为另一个cached进程(内含Activity)的client进程
/** @hide Process is being cached for later use and has an activity that corresponds
* to an existing recent task. */
public static final int PROCESS_STATE_CACHED_RECENT = 19;//进程被缓存以供以后使用,并且具有与现有的最近task相对应的activity
/** @hide Process is being cached for later use and is empty. */
public static final int PROCESS_STATE_CACHED_EMPTY = 20;//进程处于cached状态,且为空进程
/** @hide Process does not exist. */
public static final int PROCESS_STATE_NONEXISTENT = 21;//不存在的进程
五,AppState.java介绍
public class AppState {
static final String TAG = "PowerController.AppState";
private final boolean DEBUG = true;
String mPackageName;
int mUserId;
// The kernel user-ID that has been assigned to this application
int mUid;
// flags from ApplicationInfo
int mFlags;
// App status, BG/FG/USER ACTIVE/...
int mState;
int mLastState;
// the launch count during current running, will clear when app is force stopped by BgClean
int mLaunchCount;
// the total launch count from system boot up
int mTotalLaunchCount;
// the last using time during current running, will clear when app is force stopped by BgClean
long mLastTimeUsed; // elapsed time instead
// the last launch time during current running, will clear when app is force stopped by BgClean
long mLastLaunchTime; // elapsed time instead
// Process state: PROCESS_STATE_PERSISTENT / PROCESS_STATE_PERSISTENT_UI /...
int mProcState;
// if this app is visible
boolean mVisible;
long mLastVisibleTime;
long mLastStopTime;
long mLastInvisibleTime;
// if set to true, then will not try to kill this app
boolean mAvoidKilling;
// if this app need using gps,
// such as doing a navigation or location tracker (sports)
boolean mNeedUsingGps;
long mStartRunningTime; // the start time of this running
long mRunningDuration; // the running duration of the app
public AppState (String packageName, int userId, int uid, int state, int procState, int flags) {
mPackageName = packageName;
mUserId = userId;
mUid = uid;
mState = state;
mProcState = procState;
mFlags = flags;
mLastState = mState;
if (Event.MOVE_TO_FOREGROUND == state) {
mLaunchCount = 1;
mTotalLaunchCount = 1;
mLastLaunchTime = SystemClock.elapsedRealtime();
} else {
mLaunchCount = 0;
mTotalLaunchCount = 0;
mLastLaunchTime = 0;
}
if (Event.SYSTEM_INTERACTION != state)
mLastTimeUsed = SystemClock.elapsedRealtime();
else
mLastTimeUsed = 0;
mAvoidKilling = false;
mVisible = false;
mLastVisibleTime = 0;
mLastStopTime = 0;
mLastInvisibleTime = 0;
mNeedUsingGps = false;
mStartRunningTime = SystemClock.elapsedRealtime();
mRunningDuration = 0;
}
// return the old state
public int updateAppState(int state) {
int oldState = mState;
mLastState = mState;
mState = state;
if (Event.MOVE_TO_FOREGROUND == mState) {
mLaunchCount++;
mTotalLaunchCount++;
mLastLaunchTime = SystemClock.elapsedRealtime();
}
// if target app exit
if (mProcState == ActivityManager.PROCESS_STATE_CACHED_EMPTY
&& Event.NONE == mState) {
if (mStartRunningTime > 0)
mRunningDuration += (SystemClock.elapsedRealtime() - mStartRunningTime);
// clear mStartRunningTime
mStartRunningTime = 0;
} else if (mStartRunningTime == 0) {
mStartRunningTime = SystemClock.elapsedRealtime();
}
return oldState;
}
// To clear the information about a launched app
public void clearLaunchInfo() {
mProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
mState = Event.NONE;
mLastState = mState;
mLaunchCount = 0;
mLastLaunchTime = 0;
mLastTimeUsed = 0;
mAvoidKilling = false;
mLastStopTime = SystemClock.elapsedRealtime();
}
}
六,AppStateInfoCollector.java
AppStateInfoCollector作为AppState的管理收集类,通过PowerController获取到app状态的变化,从而管理AppState
主要方法介绍:
reportAppStateEventInfo()
负责接收通过UsageStatsService-->PowerController更新的app信息
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;
}
reportAppProcStateInfo()
负责接收通过IUidObserver更新的app信息
public boolean reportAppProcStateInfo(String packageName, int uid, int procState) {
int userId = UserHandle.getUserId(uid);
ArrayMap<String, AppState> mAppStateInfoList = getAppStateInfoList(userId);
//update mAppStateInfoList
int index = mAppStateInfoList.indexOfKey(packageName);
AppState appState = null;
boolean ret = true;
//if (DEBUG) Slog.d(TAG, "- reportAppProcStateInfo() E -");
if (index >= 0) {
appState = mAppStateInfoList.valueAt(index);
// update procState
appState.mProcState = procState;
if (uid != appState.mUid) appState.mUid = uid;
ret = false;
} else {
if (DEBUG) Slog.d(TAG, "reportAppProcStateInfo: appName:" + packageName + " uid:" + uid + " is not exist, create it");
appState = buildAppState(packageName, userId, Event.NONE);
mAppStateInfoList.put(packageName, appState);
}
return ret;
}
buildAppState()
创建新的AppState
private AppState buildAppState(String packageName, int userId, int stateEvent) {
ApplicationInfo app = null;
int uid = 0;
int procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
int flags = 0;
try {
app = AppGlobals.getPackageManager().
getApplicationInfo(packageName, 0, userId);
} catch (RemoteException e) {
// can't happen; package manager is process-local
}
if (app != null) {
uid = app.uid;
flags = app.flags;
synchronized (mUidStateLock) {
procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
}
}
AppState retVal = new AppState(packageName, userId, uid, stateEvent, procState, flags);
// check if is input method
//retVal.mIsEnabledInputMethod = isEnabledIMEApp(packageName);
//if (DEBUG) Slog.d(TAG, "- buildAppState() :" + packageName);
return retVal;
}
七,PowerController.java
统筹管理Power
1.PowerController extends UsageStatsManagerInternal.AppStateEventChangeListener
实现onAppStateEventChanged,接收UsageStatsService的信息
public void onAppStateEventChanged(String packageName, int userId, int state) {
if (state == UsageEvents.Event.STANDBY_BUCKET_CHANGED || packageName == null) {
if (DEBUG) Slog.d(TAG, " ignore event: STANDBY_BUCKET_CHANGED or null packageName for " + packageName);
return;
}
android.util.Log.i("lzq", " onAppStateEventChanged packageName : " + packageName + "-- userId :" + userId + "-- state : " +state);
msgHandler.sendMessage(msgHandler.obtainMessage(MSG_APP_STATE_CHANGED, userId, state, packageName));
}
发送MSG_APP_STATE_CHANGED,调用handleAppStateChanged(),主要负责通知AppStateInfoCollector.java的reportAppStateEventInfo去更新app信息
private void handleAppStateChanged(String packageName, int userId, int state) {
int oldState = state;
AppState appState = mAppStateInfoCollector.getAppState(packageName, userId);
if (DEBUG) Slog.d(TAG, "- handleAppStateChanged() E -");
/*if (mAppStatsCollectEnabled && mAppStatsServiceLoader != null) {
mAppStatsServiceLoader.reportAppStateChanged(packageName, userId, state);
}*/
if (appState != null) {
oldState = appState.mState;
if (oldState == state)
return;
}
if (mAppStateInfoCollector.reportAppStateEventInfo(packageName, userId, state)) {
// Note: Bug 698133 appIdle fail -->BEG
// Ugly: we have to check if doing special test
// is special test, then
//checkSpecialTesting(packageName);
// Note: Bug 698133 appIdle fail <--END
}
if (DEBUG) Slog.d(TAG, "packageName:" + packageName + " state:" + Util.AppState2Str(state)+ " user:" + userId);
// get new app state
appState = mAppStateInfoCollector.getAppState(packageName, userId);
if (appState == null) {
Slog.w(TAG, "null appState for packageName:" + packageName + " state:" + Util.AppState2Str(state)+ " user:" + userId);
return;
}
}
2.实现了IUidObserver
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override public void onUidStateChanged(int uid, int procState, long procStateSeq) throws RemoteException {
synchronized (mUidStateLock) {
updateUidStateLocked(uid, procState);
}
mAppStateInfoCollector.updateUidState(uid, procState);
}
@Override public void onUidGone(int uid, boolean disabled) throws RemoteException {
synchronized (mUidStateLock) {
removeUidStateLocked(uid);
}
mAppStateInfoCollector.removeUidState(uid);
}
@Override public void onUidActive(int uid) throws RemoteException {
}
@Override public void onUidIdle(int uid, boolean disabled) throws RemoteException {
}
@Override public void onUidCachedChanged(int uid, boolean cached) throws RemoteException {
}
};
当app进程变化的时候,onUidStateChanged就会被调用,然后调用updateUidStateLocked()
private void updateUidStateLocked(int uid, int uidState) {
final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
if (oldUidState != uidState) {
String appName = null;
// state changed, push updated rules
mUidState.put(uid, uidState);
try {
appName = AppGlobals.getPackageManager().getNameForUid(uid);
} catch (RemoteException e) {
// can't happen; package manager is process-local
}
//android.util.Log.i("lzq", " updateUidStateLocked packageName : " + appName + "-- oldUidState :" + oldUidState + "-- uidState : " + uidState + " uid : " + uid);
if (DEBUG) Slog.d(TAG, "updateUidStateLocked: packageName:" + appName + ", uid:" + uid
+ " state change from " + Util.ProcState2Str(oldUidState) + " to " + Util.ProcState2Str(uidState));
if (uidState == ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
if (DEBUG)
Slog.d(TAG, "updateUidStateLocked: packageName:" + appName + ", uid:" + uid + " changed from non-cached to cached_empty, just return!");
return;
}
if ((null != appName) ) {
msgHandler.sendMessage(msgHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, uidState, appName));
}
}
}
这里主要是发送MSG_UID_STATE_CHANGED信息,调用handleProcStateChanged()
case MSG_UID_STATE_CHANGED:
handleProcStateChanged((String)msg.obj, msg.arg1, msg.arg2);
break;
private void handleProcStateChanged(String appName, int uid, int procState) {
if (DEBUG) Slog.d(TAG, "- handleProcstateChanged() E - packageName:" + appName
+ " uid:" + uid + " procState:" + Util.ProcState2Str(procState));
/*if (mAppStatsCollectEnabled && mAppStatsServiceLoader != null) {
mAppStatsServiceLoader.reportAppProcStateChanged(appName, uid, procState);
}*/
if (mAppStateInfoCollector.reportAppProcStateInfo(appName, uid, procState)) {
// Note: Bug 698133 appIdle fail -->BEG
// Ugly: we have to check if doing special test
// is special test, then
//checkSpecialTesting(appName);
// Note: Bug 698133 appIdle fail <--END
}
int userId = UserHandle.getUserId(uid);
AppState appState = mAppStateInfoCollector.getAppState(appName, userId);
if (appState == null) {
Slog.w(TAG, "null appState for packageName:" + appName
+ " uid:" + uid + " procState:" + Util.ProcState2Str(procState));
return;
}
// if app is stopped, notify WakelockConstraintHelper
if (appState.mProcState == ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
appState.updateAppState(Event.NONE);
appState.clearLaunchInfo();
//mWakelockConstraintHelper.noteAppStopped(appState);
}
}
调用AppStateInfoCollector的reportAppProcStateInfo()来更新app的信息