6 展訊Sprd設定-電池-PowerController.onPowerSaveModeChanged 函式介面
阿新 • • 發佈:2018-11-21
0. 前言
- 展訊Sprd設定-電池-setPowerSaveMode
- 展訊Sprd設定-電池-省電白名單設定-appPowerSaveConfig.xml
- 展訊Sprd設定-電池-onPowerSaveModeChanging介面
- 展訊Sprd設定-電池-PowerController.exitPowerSaveMode函式介面
- 展訊Sprd設定-電池-PowerController.enterPowerSaveMode 函式介面
原始碼走讀的開始位置
- vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/PowerController.java
1. PowerController.handlePowerSaveModeChanged
package com.android.server.power; public class PowerController //extends IPowerController.Stub private List<PowerSaveHelper> mHelpers; // handle the power save mode changed private void handlePowerSaveModeChanged(int newMode) { if (mInitFinished && mPowerSaveMode == newMode) return; // notify helpers power save mode changing for (int i = 0; i < mHelpers.size(); i++) { PowerSaveHelper helper = mHelpers.get(i); helper.onPowerSaveModeChanging(newMode); } exitPowerSaveMode(mPowerSaveMode); enterPowerSaveMode(newMode); if (mPowerSaveMode != newMode) { Slog.e(TAG, "Something error!! mPowerSaveMode change fail!!old mode:" + mPowerSaveMode + " new mode:" + newMode); } // notify helpers power save mode changed for (int i = 0; i < mHelpers.size(); i++) { PowerSaveHelper helper = mHelpers.get(i); helper.onPowerSaveModeChanged(newMode); } }
其中註冊監聽的類分別為下面
[email protected]:/home/suhuazhi/8.1/op54# grep -irn "onPowerSaveModeChanged" vendor/sprd/platform/frameworks/
vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/GpsConstraintHelper.java:171: void onPowerSaveModeChanged(int mode) {
vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/PowerGuruHelper.java:189: void onPowerSaveModeChanged(int mode) {
vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/BackgroundCleanHelper.java:404: void onPowerSaveModeChanged(int mode) {
vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/WakelockConstraintHelper.java:260: void onPowerSaveModeChanged(int mode) {
vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/PowerSaveHelper.java:48: void onPowerSaveModeChanged(int mode) {
vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/PowerController.java:3105: helper.onPowerSaveModeChanged(newMode);
vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/AppIdleHelper.java:201: void onPowerSaveModeChanged(int mode) {
2. PowerSaveHelper.onPowerSaveModeChanged
PowerSaveHelper.onPowerSaveModeChanged 中涉及的資訊量很大,每個不同的Helper類都值得進行深入單獨瞭解。這塊展訊做的很詳細尤其是應用狀態的細化,音樂程序、下載進行、前臺程序、使用者活動程序、錄音程序、應用的執行狀態等等。
public class AppState {
static final String TAG = "PowerController.AppState";
private final boolean DEBUG = true;
static final int TCP_TYPE_IPV4 = 0;
static final int TCP_TYPE_IPV6 = 1;
static final String NET_TCP_IPV4_PATH = "/proc/net/tcp";
static final String NET_TCP_IPV6_PATH = "/proc/net/tcp6";
// Audio type: 'IN' for recoder; 'OUT' for play music
public static int AUDIO_TYPE_NONE = 0;
public static int AUDIO_TYPE_IN = 1<<1;
public static int AUDIO_TYPE_OUT = 1<<2;
// 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
// if true, then track the count of Launch (MOVE_TO_FOREGROUND) during standby
boolean mTrackingLaunchCountWhenStandby;
int mLastLaunchCountWhenStandby;
int mLaunchCountWhenStandby;
boolean mStateChangedToFGDuringStandby;
boolean mStateChangedStudyDone;
// Process state: PROCESS_STATE_PERSISTENT / PROCESS_STATE_PERSISTENT_UI /...
int mProcState;
// timestamp when app enter a state that can be evaluated to be put to PowerGuru blacklist
long mBeginPowerGuruEvaluatedTimeStamp;
// timestamp when app enter a state that can be evaluated to enter standby
long mBeginEvaluatedTimeStamp;
String mPackageName;
int mUserId;
// The kernel user-ID that has been assigned to this application
int mUid;
// flags from ApplicationInfo
int mFlags;
// if this app is already set in PowerGuru constrained list
boolean mInPowerGuruBlackList;
// if this app is already set in App Idle state
boolean mInAppStandby;
// timestamp at entering AppStandby
long mBeginStanbyTimeStamp;
// Received bytes when starting Evaluated
// only for the app that its procState is < PROCESS_STATE_FOREGROUND_SERVICE
long mRxBytesWhenStartEvaluated;
// timestamp at recoding rxBytes
long mTimeStampForRxBytes;
// the socket stream for this app
ArrayList<String> mSocketStreams;
// if doing download
boolean mDoingDownload;
// download is checked using a time slice (default 30s)
// if the count of time slice using to complete detecting download
// is >= 1, then we can sure that user use this app doing download
// before standby
int mUsedTimeSliceCount;
// if set to true, this app is constrained for hold partial wake lock
boolean mWakeLockContrained;
// if set to true, then will not try to kill this app
boolean mAvoidKilling;
// if set to true, then this app is constraint for GPS access
boolean mGpsConstrained;
// if set to true, then this app has active notification when enter standby
boolean mHasNotification;
boolean mHasNoClearNotification;
// if set to true, then this app is playing music for a loop
boolean mPlayingMusic;
// if this a input method
boolean mIsEnabledInputMethod;
boolean mIsDefaultInputMethod;
// current audio type
int mAudioFlag;
// last time a playing music behavior is observed
long mLastTimePlayingMusicSeen;
// wakeup alarm info
long mStartRunningTime; // the start time of this running
long mRunningDuration; // the running duration of the app
int mTotalWakeupAlarmCount;
// gps request info
long mStartRequestGpsTime;
long mRequestGpsDuration;
int mRequestGpsCount; // the current request gps count
分別以下監聽事件
2.1 GpsConstraintHelper.onPowerSaveModeChanged
細節後續詳細研究,這裡是設定不同模式下,有個GPS超時後執行限制應用GPS行為的省電操作
package com.android.server.power;
public class GpsConstraintHelper extends PowerSaveHelper {
// the idle time (ms) for app that can be stopped
private long GPS_CONSTRAINT_IDLE_THRESHOLD = DEFAULT_GPS_CONSTRAINT_IDLE_THRESHOLD;
@Override
void onPowerSaveModeChanged(int mode) {
if (DEBUG) Slog.d(TAG, "Current PowerSaveMode:" + mode);
switch (mode) {
case PowerManagerEx.MODE_LOWPOWER: // 低電量模式
case PowerManagerEx.MODE_ULTRASAVING: // 超級省電模式
case PowerManagerEx.MODE_POWERSAVING:// 省電模式
GPS_CONSTRAINT_IDLE_THRESHOLD = mConstants.GPS_INACTIVE_TIMEOUT_LOWPOWER; // 5min
break;
case PowerManagerEx.MODE_PERFORMANCE:// 效能模式
case PowerManagerEx.MODE_SMART:// 智慧省電模式
GPS_CONSTRAINT_IDLE_THRESHOLD = mConstants.GPS_INACTIVE_TIMEOUT; // 30min
break;
}
}
- 限制APP使用GPS
import com.android.server.LocationManagerService;
/**
* appName: name of the app
* enable: ture: the app can access GPS. false: the app cannot access GPS
*/
public void noteGpsConstraintStateChanged(String appName, int uid, boolean enable) {
updateGpsConstraintAppList(appName, uid, enable);
if (mLocationService != null && mLocationService.needApplyAllProviderRequirements(appName, uid)) {
mLocationService.applyAllProviderRequirements();
}
}
- frameworks/base/services/core/java/com/android/server/LocationManagerService.java
// NOTE: Bug #627645 low power Feature BEG-->
public void applyAllProviderRequirements() {
synchronized (mLock) {
applyAllProviderRequirementsLocked();
}
}
public boolean needApplyAllProviderRequirements(String packageName, int uid) {
if (packageName == null) return false;
synchronized (mLock) {
for (LocationProviderInterface p : mProviders) {
// If provider is already disabled, don't need to do anything
if (p == null) {
continue;
}
ArrayList<UpdateRecord> records = mRecordsByProvider.get(p.getName());
if (records != null) {
for (UpdateRecord record : records) {
//Slog.d(TAG, "App: " + record.mReceiver.mIdentity.mPackageName
// + " uid:" + record.mReceiver.mIdentity.mUid + " has location request!!");
if ( packageName.equals(record.mReceiver.mIdentity.mPackageName)
&& uid == record.mReceiver.mIdentity.mUid) {
return true;
}
}
}
}
}
return false;
}
// <-- NOTE: Bug #627645 low power Feature END
2.2 PowerGuruHelper.onPowerSaveModeChanged
主要進行 AppState 中的狀態更新,黑白名單的智慧管理
package com.android.server.power;
// Class PowerGuruHelper to make decision of What apps should be put
// into the PowerGuru Constrained App List
public class PowerGuruHelper extends PowerSaveHelper{
//Config Value
//Max time in app bg state before to be added to powerguru blacklist
private long POWERGURU_TIMEOUT = (TEST ? 5 * 60 * 1000L : 20 * 60 * 1000L);
@Override
void onPowerSaveModeChanged(int mode) {
if (DEBUG) Slog.d(TAG, "Current PowerSaveMode:" + mode);
switch (mode) {
case PowerManagerEx.MODE_LOWPOWER:// 低電量模式
case PowerManagerEx.MODE_POWERSAVING:// 省電模式
case PowerManagerEx.MODE_ULTRASAVING:// 超級省電模式
POWERGURU_TIMEOUT = mConstants.POWERGURU_INACTIVE_TIMEOUT_LOWPOWER; //default (5 * 60 * 1000L);
break;
case PowerManagerEx.MODE_PERFORMANCE: // 效能模式
case PowerManagerEx.MODE_SMART: // 智慧省電模式
POWERGURU_TIMEOUT = mConstants.POWERGURU_INACTIVE_TIMEOUT; //default (20 * 60 * 1000L);
break;
}
}
- vendor\sprd\platform\frameworks\base\services\core\java\com\android\server\power\AppState.java
package com.android.server.power;
public class AppState {
static final String TAG = "PowerController.AppState";
// if this app is already set in PowerGuru constrained list
boolean mInPowerGuruBlackList;
public boolean updateAppPowerGuruState(boolean inBlacklist) {
mInPowerGuruBlackList = inBlacklist;
return true;
}
2.3 BackgroundCleanHelper.onPowerSaveModeChanged
package com.android.server.power;
public class BackgroundCleanHelper extends PowerSaveHelper {
// 當後臺清理,保留多少個應用
// when doing bg app clean, max launched app that can be kept
private int MAX_LAUNCHED_APP_KEEP = DEFAULT_MAX_LAUNCHED_APP_KEEP; //including the launcher app
/**
* This is MAX app will be keep, when doing background app clean
*/
int BG_MAX_LAUNCHED_APP_KEEP = 3;
int BG_MAX_LAUNCHED_APP_KEEP_LOWPOWER = 2;
@Override
void onPowerSaveModeChanged(int mode) {
if (DEBUG) Slog.d(TAG, "Current PowerSaveMode:" + mode);
int preMode = mPowerSaveMode;
mPowerSaveMode = mode;
//if (PowerManagerEx.MODE_ULTRASAVING == preMode
// && mode != preMode) {
// if (DEBUG) Slog.d(TAG, "Exit ultra saving mode kill com.sprd.powersavemodelauncher!");
// try {
// mActivityManager.forceStopPackage("com.sprd.powersavemodelauncher", UserHandle.myUserId());
// } catch (Exception e) {}
//}
switch (mode) {
case PowerManagerEx.MODE_ULTRASAVING:// 超級省電模式
List<String> ultramodeAppList = mPowerControllerInternal.getAppList_UltraMode();
try {
List<RunningAppProcessInfo> runAppList = mRunAppList;
mRunAppList = null;
if (runAppList == null) {
Slog.d(TAG, "mRunAppList is null ");
// 獲取正在執行的應用
runAppList = mActivityManager.getRunningAppProcesses();
}
for (int i=0;i<runAppList.size();i++) {
RunningAppProcessInfo info = runAppList.get(i);
// 不殺超級省電白名單
if (ultramodeAppList.contains(info.pkgList[0])) {
Slog.d(TAG, "pkgList[0]: " + info.pkgList[0] + " in ultramodeAppList, skip it");
continue;
}
// not app in whitelist
// 不殺白名單應用
if (inCommonWhiteAppList(info.pkgList[0])) {
Slog.d(TAG, "pkgList[0]: " + info.pkgList[0] + " in CommonWhiteAppList, skip it");
continue;
}
// 不殺 appState 狀態未知的應用
AppState appState = mAppStateInfoCollector.getAppState(info.pkgList[0], UserHandle.myUserId());
if (appState == null) {
Slog.d(TAG, "pkgList[0]: " + info.pkgList[0] + ", appState is null, skip it");
continue;
}
// 不殺輸入法應用
// avoid kill input method
if (appState.mIsEnabledInputMethod) {
Slog.d(TAG, "pkgList[0]: " + info.pkgList[0] + " mIsEnabledInputMethod, skip it");
continue;
}
boolean bFind = false;
// 是否為輸入法應用
if (isSystemApp(appState)) {
// 是否為超級省電的黑名單
for(String s : mBlackAppListForUltraSaving) {
if(info.pkgList[0].contains(s)) {
bFind = true;
Slog.d(TAG, "pkgList[0]: " + info.pkgList[0] + " is system app in black list");
break;
}
}
if (!bFind) {
Slog.d(TAG, "pkgList[0]: " + info.pkgList[0] + " is system app, skip it");
continue;
}
}
// 呼叫 ActivityManager.forceStopPackage 程序查殺
mActivityManager.forceStopPackage(info.pkgList[0], UserHandle.myUserId());
// do some cleaning for appState
if (appState != null) appState.clearLaunchInfo();
Slog.d(TAG, "enter ultrasaving mode, force stop:" + info.pkgList[0]);
}
} catch (RemoteException e) {
}
//no break
case PowerManagerEx.MODE_LOWPOWER:// 低電量模式
case PowerManagerEx.MODE_POWERSAVING: // 省電模式
MAX_LAUNCHED_APP_KEEP = mConstants.BG_MAX_LAUNCHED_APP_KEEP_LOWPOWER; //including the launcher app// 當前 2 個
break;
case PowerManagerEx.MODE_PERFORMANCE:// 效能模式
case PowerManagerEx.MODE_SMART:// 智慧省電模式
MAX_LAUNCHED_APP_KEEP = mConstants.BG_MAX_LAUNCHED_APP_KEEP; //including the launcher app// 當前 3 個
break;
}
// mPowerSaveMode = mode;
}
2.4 WakelockConstraintHelper.onPowerSaveModeChanged
package com.android.server.power;
// Class WakeLockConstrainHelper to make decision of What apps should be put
// into a wake lock constrained list
// 決定一段時間後是否將APP進行後臺喚醒限制
public class WakelockConstraintHelper extends PowerSaveHelper {
@Override
void onPowerSaveModeChanged(int mode) {
if (DEBUG) Slog.d(TAG, "Current PowerSaveMode:" + mode);
switch (mode) {
case PowerManagerEx.MODE_LOWPOWER:
case PowerManagerEx.MODE_ULTRASAVING:
WAKELOCK_CONSTRAIN_IDLE_THRESHOLD = mConstants.WAKELOCK_INACTIVE_TIMEOUT_LOWPOWER; // default 5min
WAKE_LOCK_DISABLE_THRESHOLD = mConstants.WAKELOCK_CONSTRAINT_DURATION_LOWPOWER; // default 5s
break;
case PowerManagerEx.MODE_POWERSAVING:
WAKELOCK_CONSTRAIN_IDLE_THRESHOLD = mConstants.WAKELOCK_INACTIVE_TIMEOUT_LOWPOWER; // default 5min
WAKE_LOCK_DISABLE_THRESHOLD = mConstants.WAKELOCK_CONSTRAINT_DURATION; //30S
break;
case PowerManagerEx.MODE_PERFORMANCE:
case PowerManagerEx.MODE_SMART:
WAKELOCK_CONSTRAIN_IDLE_THRESHOLD = mConstants.WAKELOCK_INACTIVE_TIMEOUT; // 20min
WAKE_LOCK_DISABLE_THRESHOLD = mConstants.WAKELOCK_CONSTRAINT_DURATION; //30S
break;
}
}
}
2.5 AppIdleHelper.onPowerSaveModeChanged
package com.android.server.power;
// Class AppIdleHelper to make decision of What apps should be put
// into AppIdle state
// 智慧更新APP idle 狀態
public class AppIdleHelper extends PowerSaveHelper{
@Override
void onPowerSaveModeChanged(int mode) {
if (DEBUG) Slog.d(TAG, "Current PowerSaveMode:" + mode);
switch (mode) {
case PowerManagerEx.MODE_LOWPOWER:
case PowerManagerEx.MODE_POWERSAVING:
case PowerManagerEx.MODE_ULTRASAVING:
APPSTANDBY_TIMEOUT = mConstants.APPIDLE_INACTIVE_TIMEOUT_LOWPOWER; // 5min
break;
case PowerManagerEx.MODE_PERFORMANCE:
case PowerManagerEx.MODE_SMART:
APPSTANDBY_TIMEOUT = mConstants.APPIDLE_INACTIVE_TIMEOUT; // 20min
break;
}
}
/*
* App cannot be constrained for App Idle:
* 1. system app (app.uid <= Process.FIRST_APPLICATION_UID, this is enough ???)
* 2. message app
* 3. non-message app, but doing Download
* 4. music app and is playing music
* 5. unknown app type, and its procState <= PROCESS_STATE_FOREGROUND_SERVICE
* 6. app in Doze white list
* 7. Carrier App
*/
private boolean canBeConstrained(AppState appState) {
int procState = appState.mProcState;
if (DEBUG_MORE) Slog.d(TAG, "appStandbyCanBeConstrained: uid:" + appState.mUid
+ " :" + appState.mPackageName + " procState:" + Util.ProcState2Str(procState)
+ " Group State:" + Util.AppState2Str(appState.mState));
// 系統應用不進行管控
// system app can not be constrained
if (appState.mUid <= Process.FIRST_APPLICATION_UID)
return false;
// 白名單應用不進行管控
if (inWhiteAppList(appState.mPackageName)) {
if (DEBUG) Slog.d(TAG, "appStandbyCanBeConstrained:" +appState.mPackageName +" in my whitelist");
return false;
} else if (mBlackList.contains(appState.mPackageName)) {
if (DEBUG) Slog.d(TAG, "appStandbyCanBeConstrained:" +appState.mPackageName +" in my blacklist");
return true;
}
// 社交即時類應用不進行管控
// message App can not be constrained
int appType = mPowerControllerInternal.getAppCategoryType(appState.mPackageName);
if (PowerDataBaseControl.MESSAGE == appType) {
if (DEBUG) Slog.d(TAG, "appStandbyCanBeConstrained: " + appState.mPackageName + " Message App");
return false;
}
// 應用程序不進行管控
// playing music App can not be constrained
if (PowerDataBaseControl.MUSIC == appType
/*&& procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE*/) {
if (mPowerControllerInternal.isPlayingMusic(appState)) {
if (DEBUG) Slog.d(TAG, "appStandbyCanBeConstrained: " + appState.mPackageName + " Music is playing");
return false;
}
}
if (PowerDataBaseControl.UNKNOWN != appType
&& procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
&& appState.mLaunchCount > 0) {
if (mPowerControllerInternal.isPlayingMusic(appState)) {
if (DEBUG) Slog.d(TAG, "appStandbyCanBeConstrained: " + appState.mPackageName + " Music is playing");
return false;
}
}
// doing download App can not be constrained
if (procState <= ActivityManager.PROCESS_STATE_SERVICE) {
// 正在進行下載的應用不進行管控,超級感興趣這個判斷
if (mPowerControllerInternal.isAppDoingDownload(appState)) {
if (DEBUG) Slog.d(TAG, "appStandbyCanBeConstrained: " + appState.mPackageName + " Doing Download");
return false;
}
}
// app type is unknown
// and procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
// can not be constrained
if (PowerDataBaseControl.UNKNOWN == appType
&& procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
&& appState.mLaunchCount > 0
&& !mPowerControllerInternal.isAdminApp(appState.mPackageName)) {
if (DEBUG) Slog.d(TAG, "appStandbyCanBeConstrained: " + appState.mPackageName + " UNKNOWN App type");
return false;
}
// Carrier App can not be constrained
if (isCarrierApp(appState.mPackageName)) {
if (DEBUG) Slog.d(TAG, "appStandbyCanBeConstrained: " + appState.mPackageName + " a Carrier App");
return false;
}
return true;
}
}