IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android通过WindowManager.LayoutParams修改Activity窗口亮度流程 -> 正文阅读

[移动开发]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部分全部结束。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-26 12:13:18  更:2021-08-26 12:13:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年5日历 -2025/5/1 17:03:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码