Android通过WindowManager.LayoutParams修改Activity窗口亮度流程

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_38059988/article/details/119883438

源码path

frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
frameworks/base/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
frameworks/base/services/core/java/com/android/server/wm/Session.java
frameworks/base/core/java/android/view/Choreographer.java
out/soong/.intermediates/frameworks/base/framework-minus-apex/android_common/xref31/srcjars.xref/android/view/IWindowSession.java

一、应用层实现

首先,在需要修改屏幕亮度的应用Activity(常见的如视频播放界面)中,通过以下代码来设置WindowManager中LayoutParams的screenBrightness属性,放在哪个位置取决于应用场景。

	/**
     * set brightness for current window.
     *
     * @param brightness, range:0~255(int)
     */
    public void setCurrentScreenBrightness(int brightness) {
        WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
        layoutParams.screenBrightness = Float.valueOf(brightness / 255.0f);
        getWindow().setAttributes(layoutParams);
    }

二、relayoutWindow()

当窗口属性发生了变化,App收到Vsync信号后,会回调Choreographer.CALLBACK_TRAVERSAL,然后开始如下的调用栈,由于这里我们主要关心和窗口亮度修改有关的部分,所以这里只是简单的阐述。
Choreographter.onVsync();

Choreographer.doFrame();

ViewRootImpl.doTraversal();

ViewRootImpl.performTraversals();

ViewRootImpl.relayoutWindow();
在这个方法中,会通过由binder调用的Session.java实现的IWindowSession.java中的relayout方法,进而调用WindowManagerService的relauoutWindow()将当前Window的Attr传给WindowManagerService。

ViewRootImpl.java:

int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params,
                (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
                insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
                mTmpFrame, mTmpRect, mTmpRect, mTmpRect, mPendingBackDropFrame,
                mPendingDisplayCutout, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
                mTempControls, mSurfaceSize, mBlastSurfaceControl);

Session.java:

@Override
    public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
            Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
            Rect outStableInsets, Rect outBackdropFrame,
            DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
            SurfaceControl outSurfaceControl, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
            SurfaceControl outBLASTSurfaceControl) {
        ...
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
        //调用WMS的relayoutWindow()
        int res = mService.relayoutWindow(this, window, seq, attrs,
                requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
                outFrame, outContentInsets, outVisibleInsets,
                outStableInsets, outBackdropFrame, cutout,
                mergedConfiguration, outSurfaceControl, outInsetsState, outActiveControls,
                outSurfaceSize, outBLASTSurfaceControl);
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        ...
    }

WindowManagerService.java:

public int relayoutWindow(Session session, IWindow client, int seq, LayoutParams attrs,...) {
...
if (configChanged) {
	Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,"relayoutWindow: postNewConfigurationToHandler");
	displayContent.sendNewConfiguration();
	//进入DisplayContent中的sendNewConfigureration
	Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
...
	return result;
}

DisplayContent.java:

void sendNewConfiguration() {
	...
	if (mWaitingForConfig) {
		mWaitingForConfig = false;
		mWmService.mLastFinishedFreezeSource = "config-unchanged";
		setLayoutNeeded();
		mWmService.mWindowPlacerLocked.performSurfacePlacement();
		//进入WindowPlacerLocked中的performSurfacePlacement();
    }
}

三、performSurfacePlacement()

在mWmService.mWindowPlacerLocked.performSurfacePlacement()方法中,在确保WMS中mForceRemove中无对象后,调用RootWindowContainer中的performSurfacePlacement开始刷新界面。

WindowSurfacePlacer.java:

private void performSurfacePlacementLoop() {
        ...
        if (!mService.mForceRemoves.isEmpty()) {
            // Wait a little bit for things to settle down, and off we go.
            while (!mService.mForceRemoves.isEmpty()) {
                final WindowState ws = mService.mForceRemoves.remove(0);
                Slog.i(TAG, "Force removing: " + ws);
                ws.removeImmediately();
            }
            Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
            Object tmp = new Object();
            synchronized (tmp) {
                try {
                    tmp.wait(250);
                } catch (InterruptedException e) {
                }
            }
        }
        try {
            mService.mRoot.performSurfacePlacement();
            //进入RootWindowContainer中的performSurfacePlacement()
            ...
        }
        ...
    }

RootWindowContainer.java:

 	void performSurfacePlacement() {
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");
        try {
            performSurfacePlacementNoTrace();
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }

    // "Something has changed!  Let's make it correct now."
    // TODO: Super crazy long method that should be broken down...
    void performSurfacePlacementNoTrace() {
        ...
        //步骤一
        try {
            applySurfaceChangesTransaction();
        } catch (RuntimeException e) {
            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
        } finally {
            mWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
        }
        
        ...
        //步骤二
        if (!mWmService.mDisplayFrozen) {
            final float brightnessOverride = mScreenBrightnessOverride < PowerManager.BRIGHTNESS_MIN
                    || mScreenBrightnessOverride > PowerManager.BRIGHTNESS_MAX
                    ? PowerManager.BRIGHTNESS_INVALID_FLOAT : mScreenBrightnessOverride;
            int brightnessFloatAsIntBits = Float.floatToIntBits(brightnessOverride);
            // Post these on a handler such that we don't call into power manager service while
            // holding the window manager lock to avoid lock contention with power manager lock.
            mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightnessFloatAsIntBits,
                    0).sendToTarget();
            mHandler.obtainMessage(SET_USER_ACTIVITY_TIMEOUT, mUserActivityTimeout).sendToTarget();
        }
        ...
}
步骤一

步骤一主要用于遍历窗口以及判断亮度值是否有效。

RootWindowContainer.java:

private void applySurfaceChangesTransaction(boolean recoveringMemory) {
        ...
        final int count = mChildren.size();
        for (int j = 0; j < count; ++j) {
            final DisplayContent dc = mChildren.get(j);
            dc.applySurfaceChangesTransaction(recoveringMemory);
            //进入到DisplayContent中的applySurfaceChangesTransaction()
        }
        ...
}
    

DisplayContent.java:

void applySurfaceChangesTransaction(boolean recoveringMemory) {
       ...
       Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
       try {
           forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
           //进入到mApplySurfaceChangesTransaction中遍历窗口
        } finally {
           Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
	   ...
    }
private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
        ...   
        final RootWindowContainer root = mWmService.mRoot;
        ...     
        mTmpApplySurfaceChangesTransactionState.displayHasContent |=
                    root.handleNotObscuredLocked(w,
                            mTmpApplySurfaceChangesTransactionState.obscured,
                            mTmpApplySurfaceChangesTransactionState.syswin);  
		//进入RootWindowContainer中的handleNotObscuredLocked方法,此时syswin为默认值false 
		 
        ...      
};
/**
     * @param w WindowState this method is applied to.
     * @param obscured True if there is a window on top of this obscuring the display.
     * @param syswin System window?
     * @return True when the display contains content to show the user. When false, the display
     *          manager may choose to mirror or blank the display.
     */
    boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) {
        final WindowManager.LayoutParams attrs = w.mAttrs;
        ...
        if (w.mHasSurface && canBeSeen) {
          ...
          	//当syswin为fasle且在应用中设置的screenBrightness属性有效
          	//则将mScreenBrightnessOverride赋值为应用设置的亮度属性值
            if (!syswin && w.mAttrs.screenBrightness >= 0
                    && Float.isNaN(mScreenBrightnessOverride)) {
                mScreenBrightnessOverride = w.mAttrs.screenBrightness;
            }
            final int type = attrs.type;
            // This function assumes that the contents of the default display are processed first
            ...
            
        return displayHasContent;
    }
步骤二

步骤二主要用于更新亮度值并继续往底层传递。

DisplayContent.java:

//步骤二
        if (!mWmService.mDisplayFrozen) {
            final float brightnessOverride = mScreenBrightnessOverride < PowerManager.BRIGHTNESS_MIN
                    || mScreenBrightnessOverride > PowerManager.BRIGHTNESS_MAX
                    ? PowerManager.BRIGHTNESS_INVALID_FLOAT : mScreenBrightnessOverride;
            int brightnessFloatAsIntBits = Float.floatToIntBits(brightnessOverride);
            // Post these on a handler such that we don't call into power manager service while
            // holding the window manager lock to avoid lock contention with power manager lock.
            mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightnessFloatAsIntBits,
                    0).sendToTarget();
            //如mScreenBrightnessOverride有效则发送有效值Handler消息,无效则发送无效值
        }
        ...
}
private final class MyHandler extends Handler {

        public MyHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SET_SCREEN_BRIGHTNESS_OVERRIDE:
                    mWmService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
                            Float.intBitsToFloat(msg.arg1));
                    break;
                    //收到消息后,会调用PowerManagerService中的etScreenBrightnessOverrideFromWindowManager()方法
                ...
            }
 }

PowerManagerService.java:

@VisibleForTesting
    final class LocalService extends PowerManagerInternal {
        @Override
        public void setScreenBrightnessOverrideFromWindowManager(float screenBrightness) {
            if (screenBrightness < PowerManager.BRIGHTNESS_MIN
                    || screenBrightness > PowerManager.BRIGHTNESS_MAX) {
                screenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
            }
//当传入的screenBrightness有效,调用setScreenBrightnessOverrideFromWindowManagerInternal()
            setScreenBrightnessOverrideFromWindowManagerInternal(screenBrightness);
        }
 }
private void setScreenBrightnessOverrideFromWindowManagerInternal(float brightness) {
        synchronized (mLock) {
            if (!BrightnessSynchronizer.floatEquals(mScreenBrightnessOverrideFromWindowManager,
                    brightness)) {
                mScreenBrightnessOverrideFromWindowManager = brightness;
                mDirty |= DIRTY_SETTINGS;
                updatePowerStateLocked();
                //更新电源状态
            }
        }
}
/**
     * Updates the global power state based on dirty bits recorded in mDirty.
     *
     * This is the main function that performs power state transitions.
     * We centralize them here so that we can recompute the power state completely
     * each time something important changes, and ensure that we do it the same
     * way each time.  The point is to gather all of the transition logic here.
     */
    private void updatePowerStateLocked() {
        if (!mSystemReady || mDirty == 0) {
            return;
        }
        ...
        try {
        ...
            // Phase 3: Update display power state.
            final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
		...
		}
}
/**
     * Updates the display power state asynchronously.
     * When the update is finished, mDisplayReady will be set to true.  The display
     * controller posts a message to tell us when the actual display power state
     * has been updated so we come back here to double-check and finish up.
     *
     * This function recalculates the display power state each time.
     *
     * @return True if the display became ready.
     */
    private boolean updateDisplayPowerStateLocked(int dirty) {
        final boolean oldDisplayReady = mDisplayReady;
        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
                | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
                | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |
                DIRTY_QUIESCENT)) != 0) {
            if ((dirty & DIRTY_QUIESCENT) != 0) {
                sQuiescent = false;
            }

            mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();

            // Determine appropriate screen brightness and auto-brightness adjustments.
            final boolean autoBrightness;
            final float screenBrightnessOverride;
            if (!mBootCompleted) {
                // Keep the brightness steady during boot. This requires the
                // bootloader brightness and the default brightness to be identical.
                autoBrightness = false;
                screenBrightnessOverride = mScreenBrightnessSettingDefault;
            } else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
                autoBrightness = false;
                screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
            } else {
                autoBrightness = (mScreenBrightnessModeSetting ==
                        Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
                screenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
            }

            // Update display power request.
            mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;
            mDisplayPowerRequest.useAutoBrightness = autoBrightness;
            mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
            mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();

            updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);

            if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
                mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
                if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0
                        && !mDrawWakeLockOverrideFromSidekick) {
                    if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
                        mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
                    }
                    if (mDisplayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) {
                        mDisplayPowerRequest.dozeScreenState = Display.STATE_ON;
                    }
                }
                mDisplayPowerRequest.dozeScreenBrightness =
                        mDozeScreenBrightnessOverrideFromDreamManagerFloat;
            } else {
                mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
                mDisplayPowerRequest.dozeScreenBrightness =
                        PowerManager.BRIGHTNESS_INVALID_FLOAT;
            }

            mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
                    mRequestWaitForNegativeProximity);
            mRequestWaitForNegativeProximity = false;

            ...
        }
        return mDisplayReady && !oldDisplayReady;
    }

四、后续调用

至此,改变窗口亮度最关键的部分就算走完了,再往下走就是常规的电源管理流程,依次为:

DisplayManagerService.requestPowerState()DisplayPowerController.requestPowerState()DisplayPowerController.sendUpdatePowerStateLocked()DisplayPowerController.sendUpdatePowerStateLocked().mHandler.sendMessage(MSG_UPDATE_POWER_STATE);DisplayPowerController.DisplayControllerHandler.handleMessage(MSG_UPDATE_POWER_STATE)DisplayPowerController.updatePowerState();DisplayPowerController.animateScreenBrightness(brightness, 0);RampAnimator.animateTo();DisplayPowerState.FloatProperty<DisplayPowerState>.setValue();DisplayPowerState.setScreenBriightness();DisplayPowerState.scheduleScreenUpdate();DisplayPowerState.postScreenUpdateThreadSafe(). mHandler.post(mScreenUpdateRunnable);DisplayPowerState.mScreenUpdateRunnable.mPhotonicModulator.setState(mScreenState, brightnessState);DisplayBlanker.requestDisplayState(state, brightnessState);DisplayManagerService.requestDisplayState();DisplayManagerService.requestGlobalDisplayStateInternal(state, brightness);DisplayManagerService.applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);DisplayManagerService.updateDisplayStateLocked();LocalDisplayAdapter.requestDisplayStateLocked();LocalDisplayAdapter.requestDisplayStateLocked.setDisplayBrightness(brightnessState);LightsService.setBrightness(float brightness);LightsService.setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);LightsService.setLightUnchecked(color, mode, onMS, offMS, brightnessMode);LightsService.setLight_native(mHwLight.id, color, mode, onMS, offMS, brightnessMode);

至此,应用层到Framework的java部分全部结束。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值