Android7.0 PowerManagerService亮灭屏分析(三)
来源:互联网 发布:淘宝商家微淘怎么设置 编辑:程序博客网 时间:2024/05/22 14:15
在前面两部分已经对绘制windows与设置设备状态进行了详细讲解. 之后接着就该对亮度值进行设置, 实现亮屏动作了.
在DisplayPowerController中的animateScreenBrightness函数通过亮度渐变动画来将亮度设置到目标亮度.
// Brightness animation ramp rate in brightness units per second. private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40; //亮度渐变动画较慢的速率, 每秒变化40个亮度单位 mBrightnessRampRateFast = resources.getInteger( com.android.internal.R.integer.config_brightness_ramp_rate_fast); //从配置文件中获取较快的亮度速率 // Animate the screen brightness when the screen is on or dozing. // Skip the animation when the screen is off or suspended. if (!mPendingScreenOff) { if (state == Display.STATE_ON || state == Display.STATE_DOZE) { animateScreenBrightness(brightness, //当亮屏或doze状态时有亮度渐变动画 slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast); } else { animateScreenBrightness(brightness, 0); //灭屏时没有亮度渐变动画,直接将亮度设置为0 } }在animateScreenBrightness函数中调用动画mScreenBrightnessRampAnimator对亮度值处理, 而mScreenBrightnessRampAnimator是在initialize()函数中进行初始化的, 在构造函数中将DisplayPowerState和DisplayPowerState.SCREEN_BRIGHTNESS传输过去.
private void initialize() { //.... mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>( //泛型为DisplayPowerState mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS); mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener); //...} private void animateScreenBrightness(int target, int rate) { if (DEBUG) { Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate); } if (mScreenBrightnessRampAnimator.animateTo(target, rate)) { //动画处理亮度值 try { mBatteryStats.noteScreenBrightness(target); } catch (RemoteException ex) { // same process } } }
在RampAnimator的构造函数中将DisplayPowerState赋值给mObject, DisplayPowerState.SCREEN_BRIGHTNESS赋值给mProperty, 并且创建mChoreographer实例.
public RampAnimator(T object, IntProperty<T> property) { mObject = object; mProperty = property; mChoreographer = Choreographer.getInstance(); }
下面重点讲解animateTo函数.
public boolean animateTo(int target, int rate) { // Immediately jump to the target the first time. if (mFirstTime || rate <= 0) { //当第一次调用animateTo, 或者rate小于等于0时直接设置目标亮度. if (mFirstTime || target != mCurrentValue) { mFirstTime = false; //之后就不是第一次调用该函数 mRate = 0; //设置mRate为0 mTargetValue = target; //设置目标亮度为target mCurrentValue = target; mProperty.setValue(mObject, target); //调用DisplayPowerState.SCREEN_BRIGHTNESS设置亮度值 if (mAnimating) { mAnimating = false; cancelAnimationCallback(); } if (mListener != null) { mListener.onAnimationEnd(); //动画结束 } return true; } return false; } // Adjust the rate based on the closest target. // If a faster rate is specified, then use the new rate so that we converge // more rapidly based on the new request. // If a slower rate is specified, then use the new rate only if the current // value is somewhere in between the new and the old target meaning that // we will be ramping in a different direction to get there. // Otherwise, continue at the previous rate. if (!mAnimating || rate > mRate || (target <= mCurrentValue && mCurrentValue <= mTargetValue) || (mTargetValue <= mCurrentValue && mCurrentValue <= target)) { mRate = rate; //重新调节亮度速率 } final boolean changed = (mTargetValue != target); //如果当前亮度值不等于目标亮度值,说明亮度改变了 mTargetValue = target; //重新设置mTargetValue // Start animating. 开始动画 if (!mAnimating && target != mCurrentValue) { mAnimating = true; mAnimatedValue = mCurrentValue; mLastFrameTimeNanos = System.nanoTime(); postAnimationCallback(); } return changed; }在postAnimationCallback中调用Choreographer的postCallback函数处理, 调用完成后回调回mAnimationCallback的run函数
private void postAnimationCallback() { mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null); } private final Runnable mAnimationCallback = new Runnable() { @Override // Choreographer callback public void run() { final long frameTimeNanos = mChoreographer.getFrameTimeNanos(); final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos) * 0.000000001f; mLastFrameTimeNanos = frameTimeNanos; //记录最后一次的frameTimeNanos // Advance the animated value towards the target at the specified rate // and clamp to the target. This gives us the new current value but // we keep the animated value around to allow for fractional increments // towards the target. final float scale = ValueAnimator.getDurationScale(); if (scale == 0) { // Animation off. mAnimatedValue = mTargetValue; //让scale为0时, 表示动画停止了, 将mAnimatedValue设置为目标亮度 } else { final float amount = timeDelta * mRate / scale; //计算每一次需要变化的亮度值 if (mTargetValue > mCurrentValue) { mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue); //亮屏,每次增加亮度amount,不超过目标亮度 } else { mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue); //暗屏, 每次减少amount个亮度, 不超过目标亮度 } } final int oldCurrentValue = mCurrentValue; mCurrentValue = Math.round(mAnimatedValue); //获取当前要达到的亮度值 if (oldCurrentValue != mCurrentValue) { mProperty.setValue(mObject, mCurrentValue); //调用DisplayPowerState.SCREEN_BRIGHTNESS设置亮度值 } if (mTargetValue != mCurrentValue) { postAnimationCallback(); //如果还没有达到目标亮度,就会继续调用postAnimationCallback循环设置亮度值 } else { mAnimating = false; if (mListener != null) { mListener.onAnimationEnd(); //否则,亮度动画结束 } } } };DisplayPowerState.SCREEN_BRIGHTNESS的setValue函数是在DisplayPowerState中实现的.
public static final IntProperty<DisplayPowerState> SCREEN_BRIGHTNESS = new IntProperty<DisplayPowerState>("screenBrightness") { @Override public void setValue(DisplayPowerState object, int value) { object.setScreenBrightness(value); //调用DisplayPowerState的setScreenBrightness函数,设置亮度值 } @Override public Integer get(DisplayPowerState object) { return object.getScreenBrightness(); } }; public void setScreenBrightness(int brightness) { if (mScreenBrightness != brightness) { if (DEBUG) { Slog.d(TAG, "setScreenBrightness: brightness=" + brightness); } mScreenBrightness = brightness; //设置全局的亮度值 if (mScreenState != Display.STATE_OFF) { mScreenReady = false; scheduleScreenUpdate(); //如果不是灭屏状态,更新屏幕状态 } } }scheduleScreenUpdate函数最终通过Handler发送mScreenUpdateRunnable对象来更新亮度值. 从run函数中可以看出只有当mColorFadeLevel > 0f时才能给brightness设置亮度值, 所以说当windows没有绘制完成时就算mScreenBrightness有值不为0, 但是brightness仍然为0不能点亮屏幕.
private final Runnable mScreenUpdateRunnable = new Runnable() { @Override public void run() { mScreenUpdatePending = false; int brightness = mScreenState != Display.STATE_OFF && mColorFadeLevel > 0f ? mScreenBrightness : 0; //判断设置亮度值 if (mPhotonicModulator.setState(mScreenState, brightness)) { if (DEBUG) { Slog.d(TAG, "Screen ready"); } mScreenReady = true; invokeCleanListenerIfNeeded(); } else { if (DEBUG) { Slog.d(TAG, "Screen not ready"); } } } };之后的流程就与设置设置状态的流程相同了, 调用DisplayManagerService中DisplayBlanker的requestDisplayState函数.
DisplayBlanker blanker = new DisplayBlanker() { @Override public void requestDisplayState(int state, int brightness) { // The order of operations is important for legacy reasons. if (state == Display.STATE_OFF) { requestGlobalDisplayStateInternal(state, brightness); } callbacks.onDisplayStateChange(state); if (state != Display.STATE_OFF) { requestGlobalDisplayStateInternal(state, brightness); //亮屏调用设置状态,亮度 } } };
private void requestGlobalDisplayStateInternal(int state, int brightness) { if (state == Display.STATE_UNKNOWN) { state = Display.STATE_ON; } if (state == Display.STATE_OFF) { brightness = PowerManager.BRIGHTNESS_OFF; //灭屏设置屏幕亮度为0 } else if (brightness < 0) { brightness = PowerManager.BRIGHTNESS_DEFAULT; //屏幕亮度小于0,设置为默认亮度 } else if (brightness > PowerManager.BRIGHTNESS_ON) { brightness = PowerManager.BRIGHTNESS_ON; //屏幕亮度大于255设置最大亮度值255 } synchronized (mTempDisplayStateWorkQueue) { try { // Update the display state within the lock. // Note that we do not need to schedule traversals here although it // may happen as a side-effect of displays changing state. synchronized (mSyncRoot) { if (mGlobalDisplayState == state && mGlobalDisplayBrightness == brightness) { return; // no change 亮度与状态都没有改变就return } Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState(" + Display.stateToString(state) + ", brightness=" + brightness + ")"); mGlobalDisplayState = state; mGlobalDisplayBrightness = brightness; applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue); //应用全局状态 } // Setting the display power state can take hundreds of milliseconds // to complete so we defer the most expensive part of the work until // after we have exited the critical section to avoid blocking other // threads for a long time. for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) { mTempDisplayStateWorkQueue.get(i).run(); //运行mTempDisplayStateWorkQueue队列中的runnable } Trace.traceEnd(Trace.TRACE_TAG_POWER); } finally { mTempDisplayStateWorkQueue.clear(); } } }在applyGlobalDisplayStateLocked函数中获取所有的devices, 调用对应设备的requestDisplayStateLocked函数更新请求状态. 启动devices为LocalDisplayAdapter, 就会调用到该类的requestDisplayStateLocked获得runnable.
private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) { final int count = mDisplayDevices.size(); for (int i = 0; i < count; i++) { //遍历devices DisplayDevice device = mDisplayDevices.get(i); Runnable runnable = updateDisplayStateLocked(device); //获得devices中的runnable if (runnable != null) { workQueue.add(runnable); //将runnable加入workQueue队列, 即mTempDisplayStateWorkQueue队列 } } } private Runnable updateDisplayStateLocked(DisplayDevice device) { // Blank or unblank the display immediately to match the state requested // by the display power controller (if known). DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); //获取devices信息 if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) { return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness); //调用requestDisplayStateLocked函数 } return null; }
在requestDisplayStateLocked中主要的任务就是创建一个runnable返回到DisplayManagerService中,并且等待回调run函数.
@Override public Runnable requestDisplayStateLocked(final int state, final int brightness) { // Assume that the brightness is off if the display is being turned off. assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF; final boolean stateChanged = (mState != state); //状态是否改变 final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null; //亮度值是否改变 if (stateChanged || brightnessChanged) { //如果亮度值或者亮度状态发生改变就重新设置对应值 final int displayId = mBuiltInDisplayId; final IBinder token = getDisplayTokenLocked(); final int oldState = mState; if (stateChanged) { //设置亮度时.状态已经设置好,无变化 mState = state; updateDeviceInfoLocked(); } if (brightnessChanged) { mBrightness = brightness; //设置mBrightness } // Defer actually setting the display state until after we have exited // the critical section since it can take hundreds of milliseconds // to complete. return new Runnable() { //新建一个runnable返回 @Override public void run() { //在DisplayManagerService中调用run函数 // Exit a suspended state before making any changes. int currentState = oldState; if (Display.isSuspendedState(oldState) //判断设置是否还是在suspend状态 || oldState == Display.STATE_UNKNOWN) { if (!Display.isSuspendedState(state)) { setDisplayState(state); currentState = state; } else if (state == Display.STATE_DOZE_SUSPEND || oldState == Display.STATE_DOZE_SUSPEND) { setDisplayState(Display.STATE_DOZE); currentState = Display.STATE_DOZE; } else { return; // old state and new state is off } } // Apply brightness changes given that we are in a non-suspended state. if (brightnessChanged) { if (isPowerDebug()) { Slog.d(TAG, "set display brightness=" + brightness); } setDisplayBrightness(brightness); //设置屏幕亮度 } // Enter the final desired state, possibly suspended. if (state != currentState) { if(isPowerDebug()) { Slog.d(TAG, "set display state=" + state); } setDisplayState(state); } }
private void setDisplayBrightness(int brightness) { if (DEBUG) { Slog.d(TAG, "setDisplayBrightness(" + "id=" + displayId + ", brightness=" + brightness + ")"); } Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness(" + "id=" + displayId + ", brightness=" + brightness + ")"); try { mBacklight.setBrightness(brightness); //调用LightService设置亮度 } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } } }; } return null; }
@Override public void setBrightness(int brightness) { setBrightness(brightness, BRIGHTNESS_MODE_USER); //亮度模式默认为BRIGHTNESS_MODE_USER } @Override public void setBrightness(int brightness, int brightnessMode) { synchronized (this) { int color = brightness & 0x000000ff; color = 0xff000000 | (color << 16) | (color << 8) | color; //设置光颜色 setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode); } } private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) { if (!LightsUtilsFactory.getInstance().isBatteryOpenWhenNotificationCome(mId, color)){ if (!mLocked && (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS || mBrightnessMode != brightnessMode)) { if (DEBUG || isDebugNotifyLight()) Slog.v(TAG, "setLight #" + mId + ": color=#" + Integer.toHexString(color) + ": brightnessMode=" + brightnessMode); mLastColor = mColor; mColor = color; mMode = mode; mOnMS = onMS; mOffMS = offMS; mLastBrightnessMode = mBrightnessMode; mBrightnessMode = brightnessMode; Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x" + Integer.toHexString(color) + ")"); try { setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode); //调用jni层设置亮度 } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } } } }通过JNI调用com_android_server_lights_LightsService.cpp的setLight_native函数
static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr, jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode){ Devices* devices = (Devices*)ptr; light_state_t state; if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) { return ; } uint32_t version = devices->lights[light]->common.version; memset(&state, 0, sizeof(light_state_t)); if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) { if (light != LIGHT_INDEX_BACKLIGHT) { ALOGE("Cannot set low-persistence mode for non-backlight device."); return; } if (version < LIGHTS_DEVICE_API_VERSION_2_0) { // HAL impl has not been upgraded to support this. return; } } else { // Only set non-brightness settings when not in low-persistence mode state.color = colorARGB; state.flashMode = flashMode; state.flashOnMS = onMS; state.flashOffMS = offMS; } state.brightnessMode = brightnessMode; { ALOGD_IF_SLOW(50, "Excessive delay setting light"); //当设置亮度耗时大于50ms,就会输出该行log. devices->lights[light]->set_light(devices->lights[light], &state); }}之后调用BSP向亮度节点写入亮度值. 从而点亮屏幕.
灭屏流程分析
灭屏总览
在点击power键灭屏过程中,主要流程就是input对按键事件的传输,传送到上层处理。在PhoneWindowManager中判断是否为灭屏事件, 之后就是在power中进行对亮屏状态的处理,计算一系列的数值,并且与AMS,WMS等模块进行交互,最后调用底层LCD进行最终的设备状态与亮度的设置。灭屏流程与亮屏流程有很多共同流程,在这里只讲解灭屏的独特流程。
当wakefulness状态发生改变,AMS收到通知。如果亮屏操作,AMS就会通过函数comeOutOfSleepIfNeedLocked调用到ActivityStackSupervisor中,将sleep超时消息移除,如果抓的有partial锁,就将其释放,最后将在栈顶的activity显示出来。
当亮屏时通过InputManagerService将当前屏幕状态传入JNI中进行记录,当再次发生power键事件可以方便确认该事件是需要亮屏还是灭屏。
灭屏时首先在Notifier中通过PhoneWindowManager来通知keyguard系统开始灭屏。
灭屏动画
在PowerManagerService中获得屏幕的请求状态为OFF,即设置state为Display.STATE_OFF,在这里将performScreenOffTransition为true。
case DisplayPowerRequest.POLICY_OFF: state = Display.STATE_OFF; performScreenOffTransition = true; break;调用animateScreenStateChange进行处理屏幕状态。
// Animate the screen state change unless already animating. // The transition may be deferred, so after this point we will use the // actual state instead of the desired one. animateScreenStateChange(state, performScreenOffTransition); state = mPowerState.getScreenState();如果目标亮度不为STATE_ON,STATE_DOZE,STATE_DOZE_SUSPEND屏幕就要去睡眠了。
// Want screen off. mPendingScreenOff = true; if (mPowerState.getColorFadeLevel() == 0.0f) { // Turn the screen off. // A black surface is already hiding the contents of the screen. setScreenState(Display.STATE_OFF); mPendingScreenOff = false; mPowerState.dismissColorFadeResources(); } else if (performScreenOffTransition && mPowerState.prepareColorFade(mContext, mColorFadeFadesConfig ? ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN) && mPowerState.getScreenState() != Display.STATE_OFF) { // Perform the screen off animation. mColorFadeOffAnimator.start(); } else { // Skip the screen off animation and add a black surface to hide the // contents of the screen. mColorFadeOffAnimator.end(); }在这里就要判断ColorFadeLevel是不是0.0,由于亮屏时将ColorFadeLevel设置为1.0所以走else语句,如果performScreenOffTransition为true并且将ColorFade准备好了就开始灭屏动画将ColorFadeLevel从1.0渐变为0.0。但是前面知道将performScreenOffTransition设置为了false,所以就没有了灭屏动画,直接将ColorFadeLevel设置为0.0。之后就调用setScreenState设置状态。
发送灭屏广播
power是通过WindowManagerPolicy与PhoneWindowManager进行交互,当屏幕在finishedGoingToSleep时需要通知window进行更新手势监听,更新方向监听,更新锁屏超时时间。之后发送灭屏广播通知关心灭屏事件的模块。
到此为止亮灭屏流程讲解完毕.
- Android7.0 PowerManagerService亮灭屏分析(三)
- Android7.0 PowerManagerService亮灭屏分析(三)
- Android7.0 PowerManagerService亮灭屏分析(一)
- Android7.0 PowerManagerService亮灭屏分析(二)
- Android7.0 PowerManagerService亮灭屏分析(一)
- Android7.0 PowerManagerService亮灭屏分析(二)
- Android7.0 PowerManagerService(1) 启动过程
- Android7.0 PowerManagerService(4) Power按键流程
- Android7.0 PowerManagerService(1) 启动过程
- Android7.0 PowerManagerService Power按键流程
- Android7.0 PowerManagerService(1) 启动过程
- Android7.0 PowerManagerService(4) Power按键流程
- Android7.0 PowerManagerService(1) 启动过程
- Android7.0 PowerManagerService(4) Power按键流程
- Android7.0 PowerManagerService(2) WakeLock的使用及流程
- Android7.0 PowerManagerService(3) 核心函数updatePowerStateLocked的主要流程
- Android7.0 PowerManagerService(2) WakeLock的使用及流程
- Android7.0 PowerManagerService(3) 核心函数updatePowerStateLocked的主要流程
- 使用Eclipse将Android项目打Library包
- 深度学习之卷积神经网络学习摘录(一)
- [JS]JavaScript Offset
- SwiftyJSON源码分析
- Storm与Kafka集成
- Android7.0 PowerManagerService亮灭屏分析(三)
- 打包上架错误
- linux_echo_客户端
- java邮件提醒实现
- System Bar (Status Bar Navigation Bar)
- 在windows上部署phpwind
- 第六天(高婷我爱你)
- Android开发进阶—View的事件体系
- android系统移植(一) 总述