Android 12系统源码_SystemUIDisplayPolicy构建状态栏和导航栏视图窗口区域坐标
Posted AFinalStone
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 12系统源码_SystemUIDisplayPolicy构建状态栏和导航栏视图窗口区域坐标相关的知识,希望对你有一定的参考价值。
前言
NavigationBar 和 StatusBar 都属于 SystemBar,也叫做 decor,就是说给 App 装饰的意思。在android12中,一般的window的是在 DisplayPolicy的layoutWindowLw方法中布局的,而导航栏和状态栏分别是在DisplayPolicy的layoutNavigationBar和layoutStatusBar方法中布局的。
一、简单认识Android12中的DisplayFrames
mDisplayId 是跟物理屏幕相关的,DEFAULT_DISPLAY 的值是 0,mDisplayWidth 是物理屏幕宽度,mDisplayHeight 是物理屏幕高度。
public class DisplayFrames
public final int mDisplayId;
public final InsetsState mInsetsState;
/**
* The current visible size of the screen; really; (ir)regardless of whether the status bar can
* be hidden but not extending into the overscan area.
*/
public final Rect mUnrestricted = new Rect();
/**
* During layout, the frame that is display-cutout safe, i.e. that does not intersect with it.
*/
public final Rect mDisplayCutoutSafe = new Rect();
public int mDisplayWidth;
public int mDisplayHeight;
public int mRotation;
public DisplayFrames(int displayId, InsetsState insetsState, DisplayInfo info,
WmDisplayCutout displayCutout, RoundedCorners roundedCorners,
PrivacyIndicatorBounds indicatorBounds)
mDisplayId = displayId;
mInsetsState = insetsState;
onDisplayInfoUpdated(info, displayCutout, roundedCorners, indicatorBounds);
/**
* Update @link DisplayFrames when @link DisplayInfo is updated.
*
* @param info the updated @link DisplayInfo.
* @param displayCutout the updated @link DisplayCutout.
* @param roundedCorners the updated @link RoundedCorners.
* @return @code true if the insets state has been changed; @code false otherwise.
*/
public boolean onDisplayInfoUpdated(DisplayInfo info, @NonNull WmDisplayCutout displayCutout,
@NonNull RoundedCorners roundedCorners,
@NonNull PrivacyIndicatorBounds indicatorBounds)
mRotation = info.rotation;
final InsetsState state = mInsetsState;
final Rect safe = mDisplayCutoutSafe;
final DisplayCutout cutout = displayCutout.getDisplayCutout();
if (mDisplayWidth == info.logicalWidth && mDisplayHeight == info.logicalHeight
&& state.getDisplayCutout().equals(cutout)
&& state.getRoundedCorners().equals(roundedCorners)
&& state.getPrivacyIndicatorBounds().equals(indicatorBounds))
return false;
mDisplayWidth = info.logicalWidth;
mDisplayHeight = info.logicalHeight;
final Rect unrestricted = mUnrestricted;
unrestricted.set(0, 0, mDisplayWidth, mDisplayHeight);
safe.set(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
state.setDisplayFrame(unrestricted);
state.setDisplayCutout(cutout);
state.setRoundedCorners(roundedCorners);
state.setPrivacyIndicatorBounds(indicatorBounds);
if (!cutout.isEmpty())
if (cutout.getSafeInsetLeft() > 0)
safe.left = unrestricted.left + cutout.getSafeInsetLeft();
if (cutout.getSafeInsetTop() > 0)
safe.top = unrestricted.top + cutout.getSafeInsetTop();
if (cutout.getSafeInsetRight() > 0)
safe.right = unrestricted.right - cutout.getSafeInsetRight();
if (cutout.getSafeInsetBottom() > 0)
safe.bottom = unrestricted.bottom - cutout.getSafeInsetBottom();
state.getSource(ITYPE_LEFT_DISPLAY_CUTOUT).setFrame(
unrestricted.left, unrestricted.top, safe.left, unrestricted.bottom);
state.getSource(ITYPE_TOP_DISPLAY_CUTOUT).setFrame(
unrestricted.left, unrestricted.top, unrestricted.right, safe.top);
state.getSource(ITYPE_RIGHT_DISPLAY_CUTOUT).setFrame(
safe.right, unrestricted.top, unrestricted.right, unrestricted.bottom);
state.getSource(ITYPE_BOTTOM_DISPLAY_CUTOUT).setFrame(
unrestricted.left, safe.bottom, unrestricted.right, unrestricted.bottom);
else
state.removeSource(ITYPE_LEFT_DISPLAY_CUTOUT);
state.removeSource(ITYPE_TOP_DISPLAY_CUTOUT);
state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT);
state.removeSource(ITYPE_BOTTOM_DISPLAY_CUTOUT);
return true;
public void dumpDebug(ProtoOutputStream proto, long fieldId)
final long token = proto.start(fieldId);
proto.end(token);
public void dump(String prefix, PrintWriter pw)
pw.println(prefix + "DisplayFrames w=" + mDisplayWidth + " h=" + mDisplayHeight
+ " r=" + mRotation);
二、构建SystemBar对应的视图窗口区域坐标对象
1、系统主要是在DisplayPolicy的layoutWindowLw() 方法中构建SystemBar对应的视图窗口区域坐标对象的。
frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java
public class DisplayPolicy
public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames)
Log.d("SystemBar", "DisplayPolicy_layoutWindowLw");
if (win == mNavigationBar && !INSETS_LAYOUT_GENERALIZATION)
Log.d("SystemBar", "DisplayPolicy_layoutNavigationBar");
mNavigationBarPosition = layoutNavigationBar(displayFrames,
mBarContentFrames.get(TYPE_NAVIGATION_BAR));
return;
if ((win == mStatusBar && !canReceiveInput(win)) && !INSETS_LAYOUT_GENERALIZATION)
Log.d("SystemBar", "DisplayPolicy_layoutStatusBar");
layoutStatusBar(displayFrames, mBarContentFrames.get(TYPE_STATUS_BAR));
return;
...代码省略...
layoutWindowLw方法中首先会判断win的类型,然后调用layoutNavigationBar方法和layoutStatusBar方法构建NavigationBar和StatusBar所对应的视图窗口区域坐标。
三、导航栏视图窗口区域坐标对象的构建
构建导航栏视图窗口区域坐标的layoutNavigationBar方法r如下所示。
public class DisplayPolicy
private int layoutNavigationBar(DisplayFrames displayFrames, Rect contentFrame)
if (mNavigationBar == null)
return NAV_BAR_INVALID;
final int uiMode = mDisplayContent.getConfiguration().uiMode;
final Rect navigationFrame = sTmpNavFrame;
// Force the navigation bar to its appropriate place and size. We need to do this directly,
// instead of relying on it to bubble up from the nav bar, because this needs to change
// atomically with screen rotations.
final int rotation = displayFrames.mRotation;
final int displayHeight = displayFrames.mDisplayHeight;
final int displayWidth = displayFrames.mDisplayWidth;
final int navBarPosition = navigationBarPosition(displayWidth, displayHeight, rotation);
getRotatedWindowBounds(displayFrames, mNavigationBar, navigationFrame);
final Rect cutoutSafeUnrestricted = sTmpRect;
cutoutSafeUnrestricted.set(displayFrames.mUnrestricted);
cutoutSafeUnrestricted.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
if (navBarPosition == NAV_BAR_BOTTOM)
// It's a system nav bar or a portrait screen; nav bar goes on bottom.
int temp_bottom = Math.min(cutoutSafeUnrestricted.bottom, navigationFrame.bottom);
int navigationBarFrameHeight = getNavigationBarFrameHeight(rotation, uiMode);
navigationFrame.top = temp_bottom - navigationBarFrameHeight;
Log.d("SystemBar","layoutNavigationBar temp_bottom=" + temp_bottom
+ " navigationBarFrameHeight=" + navigationBarFrameHeight
+ " navigationFrame.top=" + navigationFrame.top
);
else if (navBarPosition == NAV_BAR_RIGHT)
// Landscape screen; nav bar goes to the right.
navigationFrame.left = Math.min(cutoutSafeUnrestricted.right, navigationFrame.right)
- getNavigationBarWidth(rotation, uiMode, navBarPosition);
else if (navBarPosition == NAV_BAR_LEFT)
// Seascape screen; nav bar goes to the left.
navigationFrame.right = Math.max(cutoutSafeUnrestricted.left, navigationFrame.left)
+ getNavigationBarWidth(rotation, uiMode, navBarPosition);
// Compute the final frame.
final WindowFrames windowFrames = mNavigationBar.getLayoutingWindowFrames();
windowFrames.setFrames(navigationFrame /* parentFrame */,
navigationFrame /* displayFrame */);
mNavigationBar.computeFrameAndUpdateSourceFrame(displayFrames);
sTmpRect.set(windowFrames.mFrame);
sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
contentFrame.set(sTmpRect);
if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + navigationFrame);
return navBarPosition;
四、状态栏视图窗口区域坐标对象的构建
1、构建状态栏视图窗口区域坐标的layoutStatusBar方法r如下所示。
private void layoutStatusBar(DisplayFrames displayFrames, Rect contentFrame)
// decide where the status bar goes ahead of time
if (mStatusBar == null)
return;
// apply any status bar insets
getRotatedWindowBounds(displayFrames, mStatusBar, sTmpStatusFrame);
final WindowFrames windowFrames = mStatusBar.getLayoutingWindowFrames();
windowFrames.setFrames(sTmpStatusFrame /* parentFrame */,
sTmpStatusFrame /* displayFrame */);
// Let the status bar determine its size.
mStatusBar.computeFrameAndUpdateSourceFrame(displayFrames);
// For layout, the status bar is always at the top with our fixed height.
int statusBarBottom = displayFrames.mUnrestricted.top
+ mStatusBarHeightForRotation[displayFrames.mRotation];
if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top)
// Make sure that the zone we're avoiding for the cutout is at least as tall as the
// status bar; otherwise fullscreen apps will end up cutting halfway into the status
// bar.
displayFrames.mDisplayCutoutSafe.top = Math.max(displayFrames.mDisplayCutoutSafe.top,
statusBarBottom);
sTmpRect.set(windowFrames.mFrame);
sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
sTmpRect.top = windowFrames.mFrame.top; // Ignore top display cutout inset
sTmpRect.bottom = statusBarBottom; // Use collapsed status bar size
contentFrame.set(sTmpRect);
以上是关于Android 12系统源码_SystemUIDisplayPolicy构建状态栏和导航栏视图窗口区域坐标的主要内容,如果未能解决你的问题,请参考以下文章
Android系统源码阅读(12):InputChannel的注册过程
repo sync 更新源码 android-12.0.0_r34, fatal: 不能重置索引文件至版本 ‘v2.27^0‘。
repo sync 更新源码 android-12.0.0_r34, fatal: 不能重置索引文件至版本 ‘v2.27^0‘。
Repo下载编译AOSP源码:基于Ubuntu 21.04,android-12.1.0_r27