Android 8.1 PowerManagerService分析(四)——亮屏流程分析

本文深入分析了Android 8.1中亮屏流程,从Power键亮屏到插拔USB亮屏的原理。重点探讨了PowerManagerService(PMS)中的关键方法,包括PowerManager、Notifier的角色。当Power键按下时,PMS通过PowerManager类与Notifier交互,改变系统的wakefulness状态,并发送亮屏广播。Notifier在亮屏流程中起到中介作用,处理交互状态变化的通知与其他系统服务的交互。此外,文中还详细介绍了从灭屏到亮屏以及亮屏到灭屏时Notifier发送广播的过程。
摘要由CSDN通过智能技术生成

欢迎大家关注我的掘金帐号

我会在那里定期更新最新版本的Android Framework源码分析!

相关文章:
[Android Framework] 8.1 PowerManagerService分析(一)——PMS的启动
[Android Framework] 8.1 PowerManagerService分析(二) ——updatePowerStateLocked()方法
[Android Framework] 8.1 PowerManagerService分析(三)——WakeLock机制

本篇分析PMS中涉及到亮屏的部分,以及PMS相关的两个类:PowerManagerNotifier

1.亮屏流程

1.1.Power键亮屏

这里直接从PhoneWindowManager开始分析。按power键后,会触发PhoneWindowManager的interceptKeyBeforeQueueing()方法:

@Override
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
   
           .......
            case KeyEvent.KEYCODE_POWER: {
   
                cancelPendingAccessibilityShortcutAction();
                result &= ~ACTION_PASS_TO_USER;
                isWakeKey = false; // wake-up will be handled separately
                if (down) {
   
                    interceptPowerKeyDown(event, interactive);
                } else {
   
                    interceptPowerKeyUp(event, interactive, canceled);
                }
                break;
            }
            .......

在这个方法中,对Power键的按下和抬起做了处理,按下时,调用interceptPowerKeyDown():

private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
   
    // Hold a wake lock until the power key is released.
    if (!mPowerKeyWakeLock.isHeld()) {
   
       //1.申请一个唤醒锁,使CPU保持唤醒
        mPowerKeyWakeLock.acquire();
    }
   ......
if (!mPowerKeyHandled) {
   
       if (interactive) {
   
       ......
       } else {
   
    //2.进行亮屏处理
        wakeUpFromPowerKey(event.getDownTime());
    ........
        }
    }
}

在这个方法中,首先是申请了一个唤醒锁,然后会对一些特定功能进行处理,如截屏、结束通话,等等,然后如果此时处于非交互状态(interactive=false),进行亮屏操作。该锁实例化如下:

mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
            "PhoneWindowManager.mPowerKeyWakeLock");

申请锁流程在PowerManagerService分析第三篇中已经分析过了。继续看wakeUpFromPowerKey()方法:

private void wakeUpFromPowerKey(long eventTime) {
   
    //第三个参数为亮屏原因,因此如果是power键亮屏,则log中会出现android.policy:POWER
    wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
}

private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
   
    final boolean theaterModeEnabled = isTheaterModeEnabled();
    if (!wakeInTheaterMode && theaterModeEnabled) {
   
        return false;
    }
    if (theaterModeEnabled) {
   
        Settings.Global.putInt(mContext.getContentResolver(),
                Settings.Global.THEATER_MODE_ON, 0);
    }
    mPowerManager.wakeUp(wakeTime, reason);
    return true;
}

在这个方法中,首先判断是否允许在剧院模式下点亮屏幕(这个模式不常用,未进行详细分析),之后通过PowerManager在PMS进行屏幕的唤醒,先来看看PowerManager的wakeup()方法:

public void wakeUp(long time) {
   
    try {
   
        mService.wakeUp(time, "wakeUp", mContext.getOpPackageName());
    } catch (RemoteException e) {
   
        throw e.rethrowFromSystemServer();
    }
}

现在到PMS中继续分析流程:

@Override // Binder call
public void wakeUp(long eventTime, String reason, String opPackageName) {
   
    if (eventTime > SystemClock.uptimeMillis()) {
   
        throw new IllegalArgumentException("event time must not be in the future");
    }
    //权限检查
    mContext.enforceCallingOrSelfPermission(
            android.Manifest.permission.DEVICE_POWER, null);
    final int uid = Binder.getCallingUid();
    //清除IPC标志
    final long ident = Binder.clearCallingIdentity();
    try {
   
        //调用内部方法
        wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
    } finally {
   
        //重置IPC标志
        Binder.restoreCallingIdentity(ident);
    }
}

在PMS中暴露给Binder客户端的方法中,进行了权限的检查,然后调用wakeUpInternal()方法,该方法如下:

private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName,
        int opUid) {
   
    synchronized (mLock) {
   
        if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {
   
            updatePowerStateLocked();
        }
    }
}

这里又调用了wakeUpNoUpdateLocked()方法,如果这个方法返回true,则会执行updatePowerStateLocked()方法,如果返回false,则整个过程结束。这个方法在我们分析wakelock申请时提到过,如果申请的wakelock锁带有唤醒屏幕的标志,也只执行这个方法,因此,这个方法是唤醒屏幕的主要方法之一,来看看这个方法:

private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,
        String opPackageName, int opUid) {
   
    if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
            || !mBootCompleted || !mSystemReady) {
   
        return false;
    }
    try {
   
	//根据当前wakefulness状态打印log,这些log很有用
        switch (mWakefulness) {
   
            case WAKEFULNESS_ASLEEP:
                Slog.i(TAG, "Waking up from sleep (uid " + reasonUid +")...");
                break;
            case WAKEFULNESS_DREAMING:
                Slog.i(TAG, "Waking up from dream (uid " + reasonUid +")...");
                break;
            case WAKEFULNESS_DOZING:
                Slog.i(TAG, "Waking up from dozing (uid " + reasonUid +")...");
                break;
        }
        //设置最后一次亮屏时间,即该次的时间
        mLastWakeTime = eventTime;
        //设置wakefulness为WAKEFULNESS_AWAKE
        setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
        //Notifier中通知BatteryStatsService统计亮屏
        mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);
        //更新用户活动时间
        userActivityNoUpdateLocked(
                eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);
    } finally {
   
    }
    return true;
}

在这个方法中,Log中的reason需要注意一下:

  • Power键亮屏,则reason是PWM中传入的android.policy:POWER
  • 来电亮屏为android.server.am:TURN_ON;
  • USB插拔时为android.server.power:POWER

所以不管是哪种亮屏方式,最终都会在这里汇合的。之后通过setWakefulnessLocked()方法设置wakefulness,再通过Notifier进行处理和通知其他系统服务wakefulness的改变,最后更新用户活动的时间,重置下次超时灭屏时间。继续看看setWakefulnessLocked():

void setWakefulnessLocked(int wakefulness, int reason
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值