Android P 亮屏慢分析

主要文件介绍

PowerManagerService.java:以下简称PMS或者PowerMS,主要处理系统中与power相关的计算,然后决策系统该如何反应。同时协调power如何与系统其他模块的交互,比如没有用户活动时屏幕变暗等。
DisplayPowerController.java:以下简称DPC或者DisplayPC,管理display设备状态,在DisplayManagerService.java(简称DMS)中实例化一个对象,以DMS为桥梁与PMS进行交互。主要处理距离传感器,亮灭屏动画,以及计算屏幕目标亮度值。通过异步回调机制来通知PMS那些事情发生了改变。同时也与WMS进行交互。
DisplayPowerState.java:以下简称DPS,power通过其与系统进行交互,如调用其它模块设置屏幕状态与亮度。仅在DPC中实例化一个对象,它算是DPC的一部分只不过将其独立出来了。
Notifier.java:将power状态的重要变化,通过广播发送出去,并且参与了与AMS,WMS,IMP的交互。
ColorFade.java:负责屏幕由关到开,由开到关的一些GL动画,由DPC进行控制。
AutomaticBrightnessController.java:主要处理光传感器,将底层上传的参数进行处理计算,将计算的新的亮度值传给DPC。
RampAnimator.java:处理屏幕亮度渐变动画。

 

快速分析

1.找到Screen on took 1224 ms log确认亮屏时间慢的点
2.搜索keenel powerkey确认驱动上传key时间,搜索waking up from sleep确认ap层接受到按键准备wake up时间,确认是不是input导致
3.搜索setpowermode或者 Set power mode,和Unblocked screen on after 1210 ms,前面时间长找sf owner.后面耗时需要找power来确认具体时间
4.通过csdn和案例看,sf耗时,很可能是sensor之类耗时

5.setpowermode耗时太久一般是kernel resuem有耗时,亮屏resume,灭屏suspend,具体检测可以参考MTK FAQ搜索set powermode,也可能是对SF做了修改导致

总结流程

1.power键home键产生并上报
2.上层接收到到键值,PowerManagerService执行相关处理
3.PMS更新全局电源状态,并开始唤醒屏幕和背光,并通知各个模块(如图形绘制Keyguard
4.调用surfaceflinger开始执行屏幕的和背光的操作
5.调用到驱动中的late_resume(在MTK 唤醒时间分析中已经介绍


亮屏流程log

打开PhoneWindowManager.java DEBUG_WAKEUP开关

1.驱动发出powerkey
HW keycode homekey

2.ap收到事件后,会走到 updatePowerStateLocked.并且打印waking up log
PowerManagerService : Waking up from sleep(uid=1000  reason=Android.policy:POWER)...

按键到power可以打印堆栈debug更好看

3.blocking screen然后 started waking up
displayPowerController: Blocking screen on until initial Contents have been draw
WIndowManager: Screen turning on...
WindowManager: Started waking up...

4.keyguard 开始draw
WindowManager: mKeyguardDelegar.ShowLisrener.onDraw.

5.uodateDisplayPowerStateLocked 执行 nativeSetDisplayPowerMode设置mode到2
SurfaceFlinger: Set power mode=2,type=0
SurfaceControl: Excessive delay in setPowerMode()  //这个要耗时大于200ms才会打印
Surfaceflinger: Finished set power mode=2. Type=0
这个时间差就是set power mode时间

6.finishWindowsDrawn 等待all window draw
WindowManager: All Windows Drawn

7.finishWindowsDrawn 以后执行 finishScreenTurningOn打印finishScreentueningon log
WindowManager: finishScreenTurningOn
DisplayPowerController:Unblocked screen on after 201 ms  //finishScreenTurningOn 到 listener.onScreenOn  到 MSG_SCREEN_ON_UNBLOCKED到unblockScreenon

8.PowerManagerService最后走 uodatePowerStateLocked.finishWakefulnessChangeIfNeededLocked()打印亮屏时间
PowerManagerService: Screen on took 224 ms  //是在wake up那里的时间相减得到
WindowManager: Finished waking up...

 

亮屏流程

流程主要有:
1.按键到power 
2.power启动keyguard
3.set power mode
4.亮屏设置亮度流程
5.Blocking screen on until流程

1.按键到power 

ap层开始是从PhoneWindowManager接收到home key event,然后一系列到PowerManagerService wakeup

要了解具体流程可以添加callback或者查看参考Link new Exception("print stack").printStackTrace();

PowerManagerService:    |----com.android.server.power.PowerManagerService.wakeUpNoUpdateLocked(PowerManagerService.java:1750)
PowerManagerService:    |----com.android.server.power.PowerManagerService.wakeUpInternal(PowerManagerService.java:1741)
PowerManagerService:    |----com.android.server.power.PowerManagerService.-wrap43(PowerManagerService.java)
PowerManagerService:    |----com.android.server.power.PowerManagerService$BinderService.wakeUp(PowerManagerService.java:4261)
PowerManagerService:    |----android.os.PowerManager.wakeUp(PowerManager.java:769)
PowerManagerService:    |----com.android.server.policy.PhoneWindowManager.wakeUp(PhoneWindowManager.java:7421)
PowerManagerService:    |----com.android.server.policy.PhoneWindowManager.interceptKeyBeforeQueueing(PhoneWindowManager.java:6874)
PowerManagerService:    |----com.android.server.wm.InputMonitor.interceptKeyBeforeQueueing(InputMonitor.java:465)
PowerManagerService:    |----com.android.server.input.InputManagerService.interceptKeyBeforeQueueing(InputManagerService.java:1897)
@/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
public void wakeUp(long eventTime, String reason, String opPackageName) {
    final long ident = Binder.clearCallingIdentity();
    try {
        wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}

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

private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,
        String opPackageName, int opUid) {
    if (DEBUG_SPEW) {
        Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + reasonUid);
    }
    try {
        switch (mWakefulness) {
            case WAKEFULNESS_ASLEEP:
                Slog.i(TAG, "Waking up from sleep (uid " + reasonUid +")...");   //powerkey亮屏打印这个log
                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;   //mLastWakeTime 开始时间,执行完最后的时间减去这个时间就是亮屏耗时
        setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);  

        mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);
        userActivityNoUpdateLocked(
                eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return true;
}

 

2.power启动keyguard

PowerManagerService.setWakefulnessLocked /  Notifier.onWakefulnessChangeStarted/
HandleEarlyInteractiveChange  /  mPolicy.startedWakingup /mkeyguardDelegate.onStartedWakingUp

在Notifier.java中与AMS,window,input进行交互,通知各模块手机状态发生了改变,根据屏幕状态各自进行处理, 最后发送亮灭屏广播, 通知关心的模块,Notify.java中的onWakefulnessChangeStarted方法列举一些重要的内容如下:

    private void setWakefulnessLocked(int wakefulness, int reason) {
        if (mWakefulness != wakefulness) {
            mWakefulness = wakefulness;
            mWakefulnessChanging = true;
            mDirty |= DIRTY_WAKEFULNESS;
            mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
        }
    }

@xref/frameworks/base/services/core/java/com/android/server/power/Notifier.java
public void onWakefulnessChangeStarted(final int wakefulness, int reason) {
    final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
    if (DEBUG) {
        Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
                + ", reason=" + reason + ", interactive=" + interactive);
    }

    mHandler.post(new Runnable() {
        @Override
        public void run() {
            mActivityManagerInternal.onWakefulnessChanged(wakefulness);
        }
    });

    // Handle any early interactive state changes.
    // Finish pending incomplete ones from a previous cycle.
    if (mInteractive != interactive) {


        // Notify battery stats.
        try {
            mBatteryStats.noteInteractive(interactive);
        } catch (RemoteException ex) { }

        // Handle early behaviors.
        mInteractive = interactive;
        mInteractiveChangeReason = reason;
        mInteractiveChanging = true;
        handleEarlyInteractiveChange(); //处理前期交互模式改变 ,如锁屏 Keyguard等
    }
}

private void handleEarlyInteractiveChange() {
    synchronized (mLock) {
        if (mInteractive) { 
            // Waking up...亮屏
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    // Note a SCREEN tron event is logged in PowerManagerService.
                    mPolicy.startedWakingUp();
                }
            });

            // Send interactive broadcast.
            mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
            mPendingWakeUpBroadcast = true;
            updatePendingBroadcastLocked();
        } else {
             mPolicy.startedGoingToSleep(why); //灭屏

        }
    }
}

public void startedWakingUp() {
    EventLog.writeEvent(70000, 1);
    if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");  //Started waking up

    synchronized (mLock) {
        mAwake = true;

        updateWakeGestureListenerLp();
        updateOrientationListenerLp();
        updateLockScreenTimeout();
    }

    if (mKeyguardDelegate != null) {
        mKeyguardDelegate.onStartedWakingUp();  //show keyguard
    }
}

@frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
public void onStartedWakingUp() {
    if (mKeyguardService != null) {
        if (DEBUG) Log.v(TAG, "onStartedWakingUp()");
        mKeyguardService.onStartedWakingUp();
    }
    mKeyguardState.interactiveState = INTERACTIVE_STATE_AWAKE;
}

public void onStartedWakingUp() {
    try {
        mService.onStartedWakingUp();
    } catch (RemoteException e) {
        Slog.w(TAG , "Remote Exception", e);
    }
}

@Override // Binder interface
public void onStartedWakingUp() {
    Trace.beginSection("KeyguardService.mBinder#onStartedWakingUp");
    checkPermission();
    mKeyguardViewMediator.onStartedWakingUp();
    Trace.endSection();
}
    
@/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java      
public void onStartedWakingUp() {
    Trace.beginSection("KeyguardViewMediator#onStartedWakingUp");

    // TODO: Rename all screen off/on references to interactive/sleeping
    synchronized (this) {
        mDeviceInteractive = true;
        cancelDoKeyguardLaterLocked();
        cancelDoKeyguardForChildProfilesLocked();
        if (DEBUG) Log.d(TAG, "onStartedWakingUp, seq = " + mDelayedShowingSequence);
        notifyStartedWakingUp();
    }
    KeyguardUpdateMonitor.getInstance(mContext).dispatchStartedWakingUp();
    maybeSendUserPresentBroadcast();
    Trace.endSection();
}
    
//notifyStartedWakingUp
private void handleNotifyStartedWakingUp() {
    Trace.beginSection("KeyguardViewMediator#handleMotifyStartedWakingUp");
    synchronized (KeyguardViewMediator.this) {
        if (DEBUG) Log.d(TAG, "handleNotifyWakingUp");
        mStatusBarKeyguardViewManager.onStartedWakingUp();
    }
    Trace.endSection();
}

public void onStartedWakingUp() {
    mDeviceInteractive = true;
    mStackScroller.setAnimationsEnabled(true);
    mVisualStabilityManager.setScreenOn(true);
    mNotificationPanel.setTouchDisabled(false);
    updateVisibleToUser();
}

3.set power mode 2

可以打印t.duration,来看执行了多久,如果这里耗时久,给SF onwer来check哪里慢

//frameworks/base/core/java/android/view/SurfaceControl.java   
public static void setDisplayPowerMode(IBinder displayToken, int mode) {
    if (displayToken == null) {
        throw new IllegalArgumentException("displayToken must not be null");
    }
    nativeSetDisplayPowerMode(displayToken, mode);
}

xref/frameworks/base/core/jni/android_view_SurfaceControl.cpp
static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenObj, jint mode) {
    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    if (token == NULL) return;

    android::base::Timer t;
    SurfaceComposerClient::setDisplayPowerMode(token, mode);
    if (t.duration() > 100ms) ALOGD("Excessive delay in setPowerMode()");
}

4.亮屏设置亮度流程
UodatepowerState  initialize
mBlanker.requestDisplayState  requestGlobalDisplayStateInternal
ApplyGlobalDisplayStateLocked
UpdateDisplayStateLocked
requestDisplayStateLocked setDisplayBrightness 
mBackLight.setBrightness

 

5.Blocking screen on until流程
UpdateDisplayPowerStateLocked    DisplayPowerController.requestPowerState
SendupdatePowerStateLocked
MSG_Update_Power_State
UodatePoWerState 
AnimateScreenStateChange setScreenState
BlockScreenOn  Blocking screen on until

private void updatePowerStateLocked() {
    if (!mSystemReady || mDirty == 0) {
        return;
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
    try {
        // Phase 0: Basic state updates.
        updateIsPoweredLocked(mDirty);
        updateStayOnLocked(mDirty);
        updateScreenBrightnessBoostLocked(mDirty);

        // Phase 1: Update wakefulness.
        // Loop because the wake lock and user activity computations are influenced
        // by changes in wakefulness.
        final long now = SystemClock.uptimeMillis();
        int dirtyPhase2 = 0;
        for (;;) {
            int dirtyPhase1 = mDirty;
            dirtyPhase2 |= dirtyPhase1;
            mDirty = 0;

            updateWakeLockSummaryLocked(dirtyPhase1);
            updateUserActivitySummaryLocked(now, dirtyPhase1);
            if (!updateWakefulnessLocked(dirtyPhase1)) {
                break;
            }
        }

        // Phase 2: Update display power state.
        boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);   //Blocking screen on until

        // Phase 3: Update dream state (depends on display ready signal).
        updateDreamLocked(dirtyPhase2, displayBecameReady);

        // Phase 4: Send notifications, if needed.
        finishWakefulnessChangeIfNeededLocked();  //最终会打印Screen on took 224 ms

        // Phase 5: Update suspend blocker.
        // Because we might release the last suspend blocker here, we need to make sure
        // we finished everything else first!
        updateSuspendBlockerLocked();
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
}

 

参考:

Android7.0 PowerManagerService亮灭屏分析(一)

Android7.0 PowerManagerService亮灭屏分析(三)

【android睡眠唤醒 二】MTK平台唤醒框架分解

Android 亮屏慢问题处理

Android 亮屏速度分析总结
 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值