版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_38059988/article/details/119883438
Android通过WindowManager.LayoutParams修改Activity窗口亮度流程
源码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属性,放在哪个位置取决于应用场景。
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);
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();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
...
return result;
}
DisplayContent.java:
void sendNewConfiguration() {
...
if (mWaitingForConfig) {
mWaitingForConfig = false;
mWmService.mLastFinishedFreezeSource = "config-unchanged";
setLayoutNeeded();
mWmService.mWindowPlacerLocked.performSurfacePlacement();
}
}
三、performSurfacePlacement()
在mWmService.mWindowPlacerLocked.performSurfacePlacement()方法中,在确保WMS中mForceRemove中无对象后,调用RootWindowContainer中的performSurfacePlacement开始刷新界面。
WindowSurfacePlacer.java:
private void performSurfacePlacementLoop() {
...
if (!mService.mForceRemoves.isEmpty()) {
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.java:
void performSurfacePlacement() {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");
try {
performSurfacePlacementNoTrace();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
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);
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.java:
void applySurfaceChangesTransaction(boolean recoveringMemory) {
...
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
try {
forAllWindows(mApplySurfaceChangesTransaction, true );
} 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);
...
};
boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) {
final WindowManager.LayoutParams attrs = w.mAttrs;
...
if (w.mHasSurface && canBeSeen) {
...
if (!syswin && w.mAttrs.screenBrightness >= 0
&& Float.isNaN(mScreenBrightnessOverride)) {
mScreenBrightnessOverride = w.mAttrs.screenBrightness;
}
final int type = attrs.type;
...
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);
mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightnessFloatAsIntBits,
0).sendToTarget();
}
...
}
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.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;
}
setScreenBrightnessOverrideFromWindowManagerInternal(screenBrightness);
}
}
private void setScreenBrightnessOverrideFromWindowManagerInternal(float brightness) {
synchronized (mLock) {
if (!BrightnessSynchronizer.floatEquals(mScreenBrightnessOverrideFromWindowManager,
brightness)) {
mScreenBrightnessOverrideFromWindowManager = brightness;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
...
try {
...
final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
...
}
}
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();
final boolean autoBrightness;
final float screenBrightnessOverride;
if (!mBootCompleted) {
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;
}
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部分全部结束。
|