该系列文章总纲链接:专题总纲目录 Android Framework 总纲
本章关键点总结 & 说明:
本章节主要关注➕ 以上思维导图即可。该章节 主要是 对 PMS 启动的分析,从systemServer启动 到 构造器、systemReady、、接口userActicity、接口gotoSleep的 一个简要的整体分析。
1 PowerManagerService启动
PowerManagerService负责Andorid系统中电源管理方面的工作。作为系统核心服务之一,PowerManagerService与其他服务及HAL层等都有交互关系,同时 因为很多服务都会涉及它,因此启动会比较早一些,在SystemServer的startBootstrapServices中就启动了,代码如下:
private void startBootstrapServices() {
//...
anager needs to be started early because other services need it.
// Native daemons may be watching for it to be registered so it must be ready
// to handle incoming binder calls immediately (including being able to verify
// the permissions for those calls).
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
//...
}
因此 整个分析就基于此,接下来看PowerManagerService的构造器,代码实现如下:
public PowerManagerService(Context context) {
super(context);
mContext = context;
//创建处理消息的线程和Handler对象
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
synchronized (mLock) {
//创建对象mWakeLockSuspendBlocker和mDisplaySuspendBlocker
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
mHalAutoSuspendModeEnabled = false;
mHalInteractiveModeEnabled = true;
//注意:这里共有4种状态
// WAKEFULNESS_AWAKE 正常运行状态
// WAKEFULNESS_DREAMING 正在播放屏保状态
// WAKEFULNESS_DOZING 处于doze状态,此时只有“低耗电”的屏保可以运行,其他进程均被挂起
// WAKEFULNESS_ASLEEP 休眠状态,只能被wakeup唤醒
mWakefulness = WAKEFULNESS_AWAKE;//设置PowerManagerService的状态
nativeInit();//进入PMS的native层调用
nativeSetAutoSuspend(false);
nativeSetInteractive(true);
}
}
@1 createSuspendBlockerLocked分析
这里创建对象mWakeLockSuspendBlocker和mDisplaySuspendBlocker的createSuspendBlockerLocked方法实现如下:
private SuspendBlocker createSuspendBlockerLocked(String name) {
SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
mSuspendBlockers.add(suspendBlocker);
return suspendBlocker;
}
这里创建了SuspendBlockerImpl类型的对象,接下来主要是SuspendBlockerImpl的acquire方法和release方法的实现,核心代码实现如下:
@Override
public void acquire() {
synchronized (this) {
mReferenceCount += 1;
if (mReferenceCount == 1) {
nativeAcquireSuspendBlocker(mName);
}
}
}
@Override
public void release() {
synchronized (this) {
mReferenceCount -= 1;
if (mReferenceCount == 0) {
nativeReleaseSuspendBlocker(mName);
} else if (mReferenceCount < 0) {
mReferenceCount = 0;
}
}
}
这里两个关键方法nativeAcquireSuspendBlocker和 nativeReleaseSuspendBlocker在native层的实现,代码如下:
static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}
static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
release_wake_lock(name.c_str());
}
继续分析acquire_wake_lock 和 release_wake_lock的实现,代码如下:
int acquire_wake_lock(int lock, const char* id)
{
initialize_fds();
if (g_error) return g_error;
int fd;
if (lock == PARTIAL_WAKE_LOCK) {
fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
}
else {
return EINVAL;
}
return write(fd, id, strlen(id));
}
int release_wake_lock(const char* id)
{
initialize_fds();
if (g_error) return g_error;
ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));
return len >= 0;
}
这里实际上是通过向驱动中写入数据来实现功能的,所写的数据就是创建变量时传递的PowerManagerService.WakeLocks和PowerManagerService.Display,同时 文件句柄的创建是通过方法initialize_fds来实现的,代码如下:
const char * const OLD_PATHS[] = {
"/sys/android_power/acquire_partial_wake_lock",
"/sys/android_power/release_wake_lock",
};
const char * const NEW_PATHS[] = {
"/sys/power/wake_lock",
"/sys/power/wake_unlock",
};
//...
static inline void initialize_fds(void)
{
//pthread_once(&g_initialized, open_file_descriptors);
if (g_initialized == 0) {
//文件操作open 相关
if(open_file_descriptors(NEW_PATHS) < 0)
open_file_descriptors(OLD_PATHS);
g_initialized = 1;
}
}
说明:
Android防止系统休眠的方式是通过向设备节点"/sys/power/wake_lock"写入数据
- 如果写的是PowerManagerService.WakeLocks,系统将不能休眠,但屏幕会关闭
- 如果写的是PowerManagerService.Display,系统将不能休眠,同时屏幕也不会关闭
如果系统要恢复休眠,则向"/sys/power/wake_unlock"写入同样的字符串就可以了。
@2 nativeInit分析
native层的代码实现如下:
static void nativeInit(JNIEnv* env, jobject obj) {
gPowerManagerServiceObj = env->NewGlobalRef(obj);
status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID,
(hw_module_t const**)&gPowerModule);
if (!err) {
gPowerModule->init(gPowerModule);
}
//...
}
这里主要是装载Power模块,然后执行它的init方法。
2 PowerManagerService的systemReady方法
同时在startOtherServices中执行 最后的systemReady方法,代码如下:
private void startOtherServices() {
final Context context = mSystemContext;
//...
try {
// TODO: use boot phase
mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
} catch (Throwable e) {
reportWtf("making Power Manager Service ready", e);
}
//...
}
继续看systemReady的代码实现,如下:
public void systemReady(IAppOpsService appOps) {
synchronized (mLock) {
mSystemReady = true;
mAppOps = appOps;
//获得DreamManager的引用
mDreamManager = getLocalService(DreamManagerInternal.class);
//获得DisplayManager的引用
mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
mPolicy = getLocalService(WindowManagerPolicy.class);
//获得BatteryManager的引用
mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
//获取最大、最小、默认的屏幕亮度值
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
//获取sensorManager引用,用于和SensorService(native服务,管理 传感器设备)交互
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
//获取BatteryStatsService引用
mBatteryStats = BatteryStatsService.getService();
//创建Notifier,广播和Power相关的变化,屏幕的打开和关闭
mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
mPolicy);
//获取 检测无线充电的对象
mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
mHandler);
//监听系统设置变化的对象
mSettingsObserver = new SettingsObserver(mHandler);
//获取LightsService的引用
mLightsManager = getLocalService(LightsManager.class);
mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
//初始化显示模块电源管理模块
mDisplayManagerInternal.initPowerManagement(
mDisplayPowerCallbacks, mHandler, sensorManager);
// Register for broadcasts from other components of the system.
//监听其他广播的intent,很多都和电源管理有关
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);//电量变更通知
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DREAMING_STARTED);//屏保启动通知
filter.addAction(Intent.ACTION_DREAMING_STOPPED);//屏保关闭通知
mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);//用户切换通知
mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DOCK_EVENT);//Dock插拔事件通知
mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);
//监听系统设置Setting的变化
final ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ENABLED),
false, mSettingsObserver, UserHandle.USER_ALL);
//监听更多setting的变化...
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.THEATER_MODE_ON),
false, mSettingsObserver, UserHandle.USER_ALL);
readConfigurationLocked();
updateSettingsLocked();
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
}
}
3 接口userActivity分析
PowerManager(简称PM)是PowerManagerService(后简称PMS)的代理类,这里接口userActivity用于用户进程向PMS报告用户影响系统休眠的活动,比如:用户点击屏幕时,系统会调用该方法userActivity告诉PMS用户点击的时间,这样PMS将更新内部保存的时间值,从而推迟系统休眠的时间,userActivity实现如下:
@Override // Binder call
public void userActivity(long eventTime, int event, int flags) {
final long now = SystemClock.uptimeMillis();
//权限检测 & 异常处理
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
userActivityInternal(eventTime, event, flags, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
继续分析userActivityInternal,内部实现如下:
private void userActivityInternal(long eventTime, int event, int flags, int uid) {
synchronized (mLock) {
if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {
updatePowerStateLocked();
}
}
}
这里关键两行代码:userActivityNoUpdateLocked的判定和执行updatePowerStateLocked,其中userActivityNoUpdateLocked只是将参数保存在内部变量中,并不采取任何操作,代码实现如下:
private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {
//...
try {
if (eventTime > mLastInteractivePowerHintTime) {
powerHintInternal(POWER_HINT_INTERACTION, 0);
mLastInteractivePowerHintTime = eventTime;
}
mNotifier.onUserActivity(event, uid);//发出通知
if (mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
return false;//如果系统处于休眠或doze模式,返回
}
/*关键变量
mLastUserActivityTimeNoChangeLights
mLastUserActivityTime
mDirty
将会作为是否执行睡眠/唤醒操作的依据
*/
if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
if (eventTime > mLastUserActivityTimeNoChangeLights
&& eventTime > mLastUserActivityTime) {
//记录userActivity方法的时间
mLastUserActivityTimeNoChangeLights = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
return true;
}
} else {
if (eventTime > mLastUserActivityTime) {
//记录userActivity方法的时间
mLastUserActivityTime = eventTime;
//记录用户的操作类型
mDirty |= DIRTY_USER_ACTIVITY;
return true;
}
}
}
//...
return false;
}
接下来 调用 updatePowerStateLocked开始更新 休眠 or 唤醒状态我们会在下一节中专门分析该方法此处先略过。
4 接口gotoSleep分析
gotoSleep接口是用来强制系统进入休眠模式。当系统一段时间无操作时,将调用gotoSleep接口来进入该模式,PMS的接口gotoSleep实现如下:
@Override // Binder call
public void goToSleep(long eventTime, int reason, int flags) {
//...
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
goToSleepInternal(eventTime, reason, flags, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
这里主要调用了方法goToSleepInternal,代码实现如下:
private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
synchronized (mLock) {
if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
updatePowerStateLocked();
}
}
}
继续分析关键方法goToSleepNoUpdateLocked的实现,代码如下:
// This method is called goToSleep for historical reasons but we actually start
// dozing before really going to sleep.
@SuppressWarnings("deprecation")
private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
if (eventTime < mLastWakeTime
|| mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
try {
//打印日志...
//更新成员变量 值
mLastSleepTime = eventTime;
mSandmanSummoned = true;
setWakefulnessLocked(WAKEFULNESS_DOZING, reason);
// Report the number of wake locks that will be cleared by going to sleep.
int numWakeLocksCleared = 0;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.FULL_WAKE_LOCK:
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
case PowerManager.SCREEN_DIM_WAKE_LOCK:
numWakeLocksCleared += 1;
break;
}
}
//打印EventLog 日志
EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
// Skip dozing if requested.
if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
reallyGoToSleepNoUpdateLocked(eventTime, uid);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
这里执行了setWakefulnessLocked,代码如下:
private void setWakefulnessLocked(int wakefulness, int reason) {
if (mWakefulness != wakefulness) {
finishWakefulnessChangeLocked();
mWakefulness = wakefulness;
mWakefulnessChanging = true;
mDirty |= DIRTY_WAKEFULNESS;
mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
}
}
这里的核心操作是修改了成员变量的值,在这之后发送了休眠的通知。接下来 调用 updatePowerStateLocked开始更新 休眠 or 唤醒状态我们会在 本模块 第3 4 5 节中专门分析该方法,因此 此处先略过。