1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT; 20 import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT; 21 import static android.view.InsetsState.ITYPE_RIGHT_DISPLAY_CUTOUT; 22 import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT; 23 24 import android.annotation.NonNull; 25 import android.graphics.Rect; 26 import android.util.proto.ProtoOutputStream; 27 import android.view.DisplayCutout; 28 import android.view.DisplayInfo; 29 import android.view.InsetsState; 30 import android.view.PrivacyIndicatorBounds; 31 import android.view.RoundedCorners; 32 33 import com.android.server.wm.utils.WmDisplayCutout; 34 35 import java.io.PrintWriter; 36 37 /** 38 * Container class for all the display frames that affect how we do window layout on a display. 39 * @hide 40 */ 41 public class DisplayFrames { 42 public final int mDisplayId; 43 44 public final InsetsState mInsetsState; 45 46 /** 47 * The current visible size of the screen; really; (ir)regardless of whether the status bar can 48 * be hidden but not extending into the overscan area. 49 */ 50 public final Rect mUnrestricted = new Rect(); 51 52 /** 53 * During layout, the frame that is display-cutout safe, i.e. that does not intersect with it. 54 */ 55 public final Rect mDisplayCutoutSafe = new Rect(); 56 57 public int mDisplayWidth; 58 public int mDisplayHeight; 59 60 public int mRotation; 61 DisplayFrames(int displayId, InsetsState insetsState, DisplayInfo info, WmDisplayCutout displayCutout, RoundedCorners roundedCorners, PrivacyIndicatorBounds indicatorBounds)62 public DisplayFrames(int displayId, InsetsState insetsState, DisplayInfo info, 63 WmDisplayCutout displayCutout, RoundedCorners roundedCorners, 64 PrivacyIndicatorBounds indicatorBounds) { 65 mDisplayId = displayId; 66 mInsetsState = insetsState; 67 onDisplayInfoUpdated(info, displayCutout, roundedCorners, indicatorBounds); 68 } 69 70 /** 71 * Update {@link DisplayFrames} when {@link DisplayInfo} is updated. 72 * 73 * @param info the updated {@link DisplayInfo}. 74 * @param displayCutout the updated {@link DisplayCutout}. 75 * @param roundedCorners the updated {@link RoundedCorners}. 76 * @return {@code true} if the insets state has been changed; {@code false} otherwise. 77 */ onDisplayInfoUpdated(DisplayInfo info, @NonNull WmDisplayCutout displayCutout, @NonNull RoundedCorners roundedCorners, @NonNull PrivacyIndicatorBounds indicatorBounds)78 public boolean onDisplayInfoUpdated(DisplayInfo info, @NonNull WmDisplayCutout displayCutout, 79 @NonNull RoundedCorners roundedCorners, 80 @NonNull PrivacyIndicatorBounds indicatorBounds) { 81 mRotation = info.rotation; 82 83 final InsetsState state = mInsetsState; 84 final Rect safe = mDisplayCutoutSafe; 85 final DisplayCutout cutout = displayCutout.getDisplayCutout(); 86 if (mDisplayWidth == info.logicalWidth && mDisplayHeight == info.logicalHeight 87 && state.getDisplayCutout().equals(cutout) 88 && state.getRoundedCorners().equals(roundedCorners) 89 && state.getPrivacyIndicatorBounds().equals(indicatorBounds)) { 90 return false; 91 } 92 mDisplayWidth = info.logicalWidth; 93 mDisplayHeight = info.logicalHeight; 94 final Rect unrestricted = mUnrestricted; 95 unrestricted.set(0, 0, mDisplayWidth, mDisplayHeight); 96 safe.set(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE); 97 state.setDisplayFrame(unrestricted); 98 state.setDisplayCutout(cutout); 99 state.setRoundedCorners(roundedCorners); 100 state.setPrivacyIndicatorBounds(indicatorBounds); 101 if (!cutout.isEmpty()) { 102 if (cutout.getSafeInsetLeft() > 0) { 103 safe.left = unrestricted.left + cutout.getSafeInsetLeft(); 104 } 105 if (cutout.getSafeInsetTop() > 0) { 106 safe.top = unrestricted.top + cutout.getSafeInsetTop(); 107 } 108 if (cutout.getSafeInsetRight() > 0) { 109 safe.right = unrestricted.right - cutout.getSafeInsetRight(); 110 } 111 if (cutout.getSafeInsetBottom() > 0) { 112 safe.bottom = unrestricted.bottom - cutout.getSafeInsetBottom(); 113 } 114 state.getSource(ITYPE_LEFT_DISPLAY_CUTOUT).setFrame( 115 unrestricted.left, unrestricted.top, safe.left, unrestricted.bottom); 116 state.getSource(ITYPE_TOP_DISPLAY_CUTOUT).setFrame( 117 unrestricted.left, unrestricted.top, unrestricted.right, safe.top); 118 state.getSource(ITYPE_RIGHT_DISPLAY_CUTOUT).setFrame( 119 safe.right, unrestricted.top, unrestricted.right, unrestricted.bottom); 120 state.getSource(ITYPE_BOTTOM_DISPLAY_CUTOUT).setFrame( 121 unrestricted.left, safe.bottom, unrestricted.right, unrestricted.bottom); 122 } else { 123 state.removeSource(ITYPE_LEFT_DISPLAY_CUTOUT); 124 state.removeSource(ITYPE_TOP_DISPLAY_CUTOUT); 125 state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT); 126 state.removeSource(ITYPE_BOTTOM_DISPLAY_CUTOUT); 127 } 128 return true; 129 } 130 dumpDebug(ProtoOutputStream proto, long fieldId)131 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 132 final long token = proto.start(fieldId); 133 proto.end(token); 134 } 135 dump(String prefix, PrintWriter pw)136 public void dump(String prefix, PrintWriter pw) { 137 pw.println(prefix + "DisplayFrames w=" + mDisplayWidth + " h=" + mDisplayHeight 138 + " r=" + mRotation); 139 } 140 } 141