1つは、最初にAPPステータス監視の2つの入り口を紹介します。
1. UsageStatsServiceは、アプリケーションの使用状況データを収集、集約、および保持するサービスです。
2.IUidObserverはプロセスステータスの変更を監視します
私たちが行うアプリステータスの監視は、この接続エントリに基づいています
次に、フレームワークが構築されます
AppState.java APP状態のオブジェクトクラス、各APPは個別のオブジェクトとして処理されます
AppStateInfoCollector.javaAPP状態管理クラス
PowerController.java省電力管理全体の管理クラス
Util.javaツールクラス
3、UsageStatsService関連クラスの概要、およびソースコードの変更
UsageEvents.javaは、主にアプリのイベントを記録するために使用される内部クラスEventを実装します
UsageStatsManagerInternal.java抽象クラス。UsageStatsService.javaに実装されています
UsageStatsManager.javaUsageStatsService管理クラス
PowerController.javaを省電力管理全体の管理クラスとして作成したため、APPステータスのリアルタイムの変更を取得するためのインターフェイスを公開するUsageStatsServiceが必要です。
したがって、最初に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を継承するため、これら2つの抽象メソッドを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とPowerControllerの間の中間ブリッジとしてUsageStatsServiceに追加される内部クラスです。
/*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は、アプリのステータスの変更を監視するときに、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には5つのメソッドがあり、通常は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;//不存在的进程
5、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();
}
}
6、AppStateInfoCollector.java
AppStateInfoCollectorは、AppStateの管理コレクションクラスとして、PowerControllerを介してアプリの状態の変更を取得し、AppStateを管理します。
主な方法の紹介:
reportAppStateEventInfo()
UsageStatsService-> PowerControllerを通じて更新されたアプリ情報を受信する責任があります
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を通じて更新されたアプリ情報を受信する責任があります
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
電力の全体的な管理
1.PowerControllerは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に通知してアプリ情報を更新する役割を果たします。
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 {
}
};
アプリのプロセスが変更されると、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()を呼び出して、アプリ情報を更新します