在文章MTK 唤醒时间分析中分析了内核中的主要的亮屏重要阶段,此篇文章结合上层的log一起来分析下整个系统的亮屏流程。整个流程可以分为如下几个部分:

  (1)power键(home键)产生并上报(在input子系统中已经介绍);

  (2)上层接收到到键值,PowerManagerService执行相关处理;

  (3)PMS更新全局电源状态,并开始唤醒屏幕和背光,并通知各个模块(如图形绘制Keyguard);

  (4)调用surfaceflinger开始执行屏幕的和背光的操作;

  (5)调用到驱动中的late_resume(在MTK 唤醒时间分析中已经介绍);

一、PMS接收键值过程及更新全局状态:

  当PowerMangerService接收到power键值后,会打印出调用的堆栈信息如下:

01-01 20:08:44.042224   981  1162 D PowerManagerService:    |----com.android.server.power.PowerManagerService.wakeUpNoUpdateLocked(PowerManagerService.java:1750)
01-01 20:08:44.042242   981   995 D NetworkPolicy: no need to update restrict data rules for uid 1000
01-01 20:08:44.042271   981  1162 D PowerManagerService:    |----com.android.server.power.PowerManagerService.wakeUpInternal(PowerManagerService.java:1741)
01-01 20:08:44.042282   981   995 D NetworkPolicy: no need to update restrict power rules for uid 1000
01-01 20:08:44.042374   981  1162 D PowerManagerService:    |----com.android.server.power.PowerManagerService.-wrap43(PowerManagerService.java)
01-01 20:08:44.042415   981  1162 D PowerManagerService:    |----com.android.server.power.PowerManagerService$BinderService.wakeUp(PowerManagerService.java:4261)
01-01 20:08:44.042458   981  1162 D PowerManagerService:    |----android.os.PowerManager.wakeUp(PowerManager.java:769)
01-01 20:08:44.042505   981  1162 D PowerManagerService:    |----com.android.server.policy.PhoneWindowManager.wakeUp(PhoneWindowManager.java:7421)
01-01 20:08:44.042548   981  1162 D PowerManagerService:    |----com.android.server.policy.PhoneWindowManager.interceptKeyBeforeQueueing(PhoneWindowManager.java:6874)
01-01 20:08:44.042579   981  1162 D PowerManagerService:    |----com.android.server.wm.InputMonitor.interceptKeyBeforeQueueing(InputMonitor.java:465)
01-01 20:08:44.042609   981  1162 D PowerManagerService:    |----com.android.server.input.InputManagerService.interceptKeyBeforeQueueing(InputManagerService.java:1897)

  从上面的log中可以清晰的看到键值被InputManagerService.java的interceptKeyBeforeQueueing方法接收到:

private WindowManagerCallbacks mWindowManagerCallbacks;
private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
}    

  interceptKeyBeforeQueueing会调用到PhoneManagerService(PhoneWindowManager.java)中相同的方法如下:

public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {case KeyEvent.KEYCODE_VOLUME_DOWN:case KeyEvent.KEYCODE_VOLUME_UP:...//一些列的键值判断处理case KeyEvent.KEYCODE_POWER: {result &= ~ACTION_PASS_TO_USER;isWakeKey = false; // wake-up will be handled separatelyif (down) {if(!isKeysTest()){interceptPowerKeyDown(event, interactive);}else{sendKey(KeyEvent.KEYCODE_POWER);}}break;}......case KeyEvent.KEYCODE_WAKEUP: {result &= ~ACTION_PASS_TO_USER;isWakeKey = true;break;}  if (isWakeKey) {wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");}return result;
}
    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;}

  上面代码经过一些列的键值判断后,最终会调用到wakeup代码如下:

    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.java中的wakeUp比较简单:

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

  最终会调用到PowerManagerService中的wakeUp做真正的唤醒工作:

        public void wakeUp(long eventTime, String reason, String opPackageName) {if (eventTime > SystemClock.uptimeMillis()) {throw new IllegalArgumentException("event time must not be in the future");}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 (mIPOShutdown && reason != PowerManager.WAKE_UP_REASON_SHUTDOWN)return;if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {updatePowerStateLocked();//更新电源状态}}}

  onWakefulnessChangeStarted中会调用notify的onWakefulnessChangeStarted发送亮屏广播,通知亮屏。

    private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,String opPackageName, int opUid) {Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");try {......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;setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);.....}
    private void setWakefulnessLocked(int wakefulness, int reason) {if (mWakefulness != wakefulness) {mWakefulness = wakefulness;mWakefulnessChanging = true;mDirty |= DIRTY_WAKEFULNESS;mNotifier.onWakefulnessChangeStarted(wakefulness, reason);//调用到notify中}}

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

    public void onWakefulnessChangeStarted(final int wakefulness, int reason) {......mActivityManagerInternal.onWakefulnessChanged(wakefulness); //与AMS交互处理mBatteryStats.noteInteractive(interactive);//唤醒battery状态  handleEarlyInteractiveChange(); //处理前期交互模式改变 ,如锁屏 Keyguard等......}

  当上述各个模块初始化完成后会重新调用到wakeUpInternal中的updatePowerStateLocked更新全局电源状态,并开始执行DisplayPowerController.java中的方法。

    private void updatePowerState() {int state;......int brightness = PowerManager.BRIGHTNESS_DEFAULT;// Apply the proximity sensor.if (mProximitySensor != null) {//获取psensor的状态}if (mScreenOffBecauseOfProximity) {state = Display.STATE_OFF;}//获取自动背光的状态值后,调用animateScreenBrightness开始执行背光操作animateScreenBrightness(brightness,slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);//判断亮屏前是否有未完成的任务,如图形是否绘制成功等// Grab a wake lock if we have unfinished business.if (!finished && !mUnfinishedBusiness) {if (DEBUG) {Slog.d(TAG, "Unfinished business...");}mCallbacks.acquireSuspendBlocker();mUnfinishedBusiness = true;}// Release the wake lock when we have no unfinished business.if (finished && mUnfinishedBusiness) {if (DEBUG) {Slog.d(TAG, "Finished business...");}mUnfinishedBusiness = false;mCallbacks.releaseSuspendBlocker();}// Record if dozing for future comparison.mDozing = state != Display.STATE_ON;}

  updatePowerState()中有很多的操作,上面的代码只列举了部分重要阶段的代码,上面的任务完成后,下面会调用到LocalDisplayAdapter.java真正的开始亮屏和亮背光的操作。

    LocalDisplayAdapter.javapublic Runnable requestDisplayStateLocked(final int state, final int brightness)private void setDisplayState(int state)blockScreenOn会等待windws绘制完成,unblockScreenOnprivate void setDisplayBrightness(int brightness)SurfaceControl.setDisplayPowerMode调用到surfacefligner的setPowerMode

二、surfaceflinger亮屏和亮背光

  在LocalDisplayAdapter中会通过相应的接口调用到surfacefligner的操作:

    //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);}

这样又调用到native层的接口:

//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,int mode, bool stateLockHeld) {ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),this);int32_t type = hw->getDisplayType();int currentMode = hw->getPowerMode();hw->setPowerMode(mode);if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {ALOGW("Trying to set power mode for virtual display");return;}//...这里做了很多工作,上面只列举了setPowerMode的部分
}
void HWCDisplay::setPowerMode(const int32_t& mode)
{// screen blanking based on early_suspend in the kernelHWC_LOGI("Display(%" PRId64 ") SetPowerMode(%d)", m_disp_id, mode);m_power_mode = mode;DisplayManager::getInstance().setDisplayPowerState(m_disp_id, mode);HWCDispatcher::getInstance().setPowerMode(m_disp_id, mode);DisplayManager::getInstance().setPowerMode(m_disp_id, mode);......}

这一块的代码都会被编译到hwcomposer.<platform>.so库中,之前部分平台此部分代码不开源,当前新的一些平台,这部分的代码已经开源,所以可以看到上面部分的代码,下面才是真正完成setPowerMode工作的函数体:

void DispDevice::setPowerMode(int dpy,int mode)
{if (HWCMediator::getInstance().m_features.control_fb){HWC_LOGD("DispDevice::setPowerMode() dpy:%d mode:%d", dpy, mode);char filename[32] = {0};//打开/dev/graphics/fb%d的节点进行ioctl的操作snprintf(filename, sizeof(filename), "/dev/graphics/fb%d", dpy);int fb_fd = open(filename, O_RDWR);if (fb_fd <= 0){HWC_LOGE("Failed to open fb%d device: %s", dpy, strerror(errno));return;}switch (mode){case HWC_POWER_MODE_OFF://灭屏{err = WDT_IOCTL(fb_fd, FBIOBLANK, FB_BLANK_POWERDOWN);break;}case HWC_POWER_MODE_NORMAL://亮屏{err = WDT_IOCTL(fb_fd, FBIOBLANK, FB_BLANK_UNBLANK);m_color_transform_info[dpy].resend_color_transform = true;break;}case HWC_POWER_MODE_DOZE:case HWC_POWER_MODE_DOZE_SUSPEND:{......}protectedClose(fb_fd);}
}

三、kernel resume work:

上面setPowerMode会直接通过fb0-x的节点调用到kernel的代码中:

//kernel-3.18/drivers/misc/mediatek/video/common/mtkfb.c
static struct fb_ops mtkfb_ops = {.owner = THIS_MODULE,.fb_ioctl = mtkfb_ioctl,
#ifdef CONFIG_COMPAT.fb_compat_ioctl = mtkfb_compat_ioctl,
#endif
#if defined(CONFIG_PM_AUTOSLEEP).fb_blank = mtkfb_blank,
#endif}static int mtkfb_blank(int blank_mode, struct fb_info *info)
{enum mtkfb_power_mode prev_pm = primary_display_get_power_mode();switch (blank_mode) {case FB_BLANK_UNBLANK:case FB_BLANK_NORMAL:DISPDBG("mtkfb_blank mtkfb_late_resume\n");if (bypass_blank) {DISPERR("FB_BLANK_UNBLANK bypass_blank %d\n", bypass_blank);break;}primary_display_set_power_mode(FB_RESUME);mtkfb_late_resume();//正式进入到late_resume相关屏的操作debug_print_power_mode_check(prev_pm, FB_RESUME);if (!lcd_fps)msleep(30);elsemsleep(2 * 100000 / lcd_fps);    /* Delay 2 frames. */break;

上面的流程MTK 唤醒时间分析一文中已经介绍。

到这里,整个流程就已经彻底贯通,流程图如下:

kernel部分的唤醒流程如下:

作者:frank_zyp 
您的支持是对博主最大的鼓励,感谢您的认真阅读。 
本文无所谓版权,欢迎转载。

【android睡眠唤醒 二】MTK平台唤醒框架分解相关推荐

  1. android 系统优化(20)---MTK 平台唤醒时间优化1

    MTK 平台唤醒流程: 一.唤醒流程: MTK平台唤醒流程是从power键或者其他按键按下开始,本文以mt6753n平台为例,通过分析kernel log来看驱动中整个唤醒的流程,上层的唤醒流程后续再 ...

  2. MTK驱动(46)---- Android CPU频率设置(MTK平台)

    Android CPU频率设置(MTK平台) 1.CPU 频率设置 主要设置CPU的最大和最小频率 mPerfServiceWrapper.userReg 注册 mPerfServiceWrapper ...

  3. MTK平台唤醒源分类

    SPM R12寄存器记录MCU的唤醒源,MCU被唤醒时log中会将具体唤醒源打印: #define R12_PCM_TIMER_EVENT (1U << 0) ----> SPM 定 ...

  4. mtk android 5.1 logo,Android ROM DIY之MTK平台手机通用移植

    在之前的文章中,我们讨论过ROM刷机原理,修改ROM包以及如何让ROM包获取root权限.那么接下来,我们谈谈MTK平台手机ROM移植的话题.如果你是ROM小白,那么建议可以先看看之前的文章. ROM ...

  5. Android P 9.0 MTK平台 增加以太网静态IP功能

    前言 朋友们,最近又开始搞 Android P了,同样的以太网静态 IP 是少不了的功能,今天我们就开始来整一下.之前弄6.0 和 8.1 的都 ok 了. 没想到 9.0 改动还是略微有点大的.来来 ...

  6. GPS之MTK平台代码小结以及gps协议注释

            分类:             通信硬件与通讯协议              2014-10-20 09:55     337人阅读     评论(0)     收藏     举报   ...

  7. Android睡眠唤醒机制--Kernel态

    Android睡眠唤醒机制--Kernel态 转载 2014年08月26日 14:31:41 标签: android / hibernate 193 一.简介 Android系统中定义了几种低功耗状态 ...

  8. Android睡眠唤醒机制--系统架构

    一.简介 Android在Linux内核原有的睡眠唤醒模块上基础上,主要增加了下面三个机制: • Wake Lock 唤醒锁机制:      • Early Suspend 预挂起机制:      • ...

  9. MTK平台TP驱动框架解析

    一,TP驱动代码的组成 MTK平台TP驱动主要包括两处文件: 1,kernel-3.18\drivers\input\touchscreen\mediatek\mtk_tpd.c 平台设备驱动,主要为 ...

最新文章

  1. 连续变量的转换:ECDF、Box-Cox、Yeo-Johnson
  2. [bzoj2527][Poi2011]Meteors_整体二分_树状数组
  3. Matplotlib实例教程(十二)箱形图
  4. c++ map 修改value_C++知识分享之STL容器:set 容器与 map 容器的简单应用
  5. 《浪潮之巅》九、十章笔记
  6. 日记2015.11.5
  7. android 65536 gradle,如何防止在Android Gradle中使用Multi-dex
  8. (超简单思路)U - C语言实验——单词统计
  9. [swift] LeetCode 96. Unique Binary Search Trees
  10. pytorch--- .zero_grad()
  11. 互联网项目文科程序员的自白
  12. Composite_组合模式_PHP语言描述
  13. mysql vc运行库,VC运行库版本 - robslove的个人页面 - OSCHINA - 中文开源技术交流社区...
  14. word给表头和图题按章节编号
  15. java 类方法中this_Java Eclipse 中 在类与方法调用中 (this)的用法
  16. 【原创】常用元器件选型目录-cayden(待续)
  17. C/C++编程学习 - 第19周 ③ 不与最大数相同的数字之和
  18. 5g理论速度_如何理解5G下载速度?
  19. 微信小程序070校园食堂订餐多商家带配送
  20. Android ViewBinding和DataBinding的几个使用方式 - 上

热门文章

  1. 4s团队项目前端layui整合使用步骤
  2. 计算机硬件是外观吗,计算机硬件从外观上看主要有主机箱.doc
  3. spring中c3p0配置 ---这是一位仁兄的经历
  4. unreal engine 4 如何创建地形、地表贴图。
  5. window 删除文件报错显示被程序占用 强制删除被占用的文件
  6. 数据结构-算法与算法描述
  7. 计算机视觉、模式识别、机器学习常用牛人主页链接
  8. CCS报错 creating output section XXXXXXXXX without SECTIONS specification 解决方法
  9. ubuntu安装网易云音乐 打不开, 或者不想使用root权限打开 尝试思路
  10. 查看win10系统的CUDA版本