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.InsetsSource.createId; 20 import static android.view.WindowInsets.Type.displayCutout; 21 22 import android.annotation.NonNull; 23 import android.graphics.Rect; 24 import android.util.proto.ProtoOutputStream; 25 import android.view.DisplayCutout; 26 import android.view.DisplayInfo; 27 import android.view.DisplayShape; 28 import android.view.InsetsState; 29 import android.view.PrivacyIndicatorBounds; 30 import android.view.RoundedCorners; 31 32 import java.io.PrintWriter; 33 34 /** 35 * Container class for all the display frames that affect how we do window layout on a display. 36 * @hide 37 */ 38 public class DisplayFrames { 39 40 private static final int ID_DISPLAY_CUTOUT_LEFT = createId(null, 0, displayCutout()); 41 private static final int ID_DISPLAY_CUTOUT_TOP = createId(null, 1, displayCutout()); 42 private static final int ID_DISPLAY_CUTOUT_RIGHT = createId(null, 2, displayCutout()); 43 private static final int ID_DISPLAY_CUTOUT_BOTTOM = createId(null, 3, displayCutout()); 44 45 public final InsetsState mInsetsState; 46 47 /** 48 * The current visible size of the screen; really; (ir)regardless of whether the status bar can 49 * be hidden but not extending into the overscan area. 50 */ 51 public final Rect mUnrestricted = new Rect(); 52 53 /** 54 * During layout, the frame that is display-cutout safe, i.e. that does not intersect with it. 55 */ 56 public final Rect mDisplayCutoutSafe = new Rect(); 57 58 public int mWidth; 59 public int mHeight; 60 61 public int mRotation; 62 DisplayFrames(InsetsState insetsState, DisplayInfo info, DisplayCutout cutout, RoundedCorners roundedCorners, PrivacyIndicatorBounds indicatorBounds, DisplayShape displayShape)63 public DisplayFrames(InsetsState insetsState, DisplayInfo info, DisplayCutout cutout, 64 RoundedCorners roundedCorners, PrivacyIndicatorBounds indicatorBounds, 65 DisplayShape displayShape) { 66 mInsetsState = insetsState; 67 update(info.rotation, info.logicalWidth, info.logicalHeight, cutout, roundedCorners, 68 indicatorBounds, displayShape); 69 } 70 DisplayFrames()71 DisplayFrames() { 72 mInsetsState = new InsetsState(); 73 } 74 75 /** 76 * This is called if the display info may be changed, e.g. rotation, size, insets. 77 * 78 * @return {@code true} if anything has been changed; {@code false} otherwise. 79 */ update(int rotation, int w, int h, @NonNull DisplayCutout displayCutout, @NonNull RoundedCorners roundedCorners, @NonNull PrivacyIndicatorBounds indicatorBounds, @NonNull DisplayShape displayShape)80 public boolean update(int rotation, int w, int h, @NonNull DisplayCutout displayCutout, 81 @NonNull RoundedCorners roundedCorners, 82 @NonNull PrivacyIndicatorBounds indicatorBounds, 83 @NonNull DisplayShape displayShape) { 84 final InsetsState state = mInsetsState; 85 final Rect safe = mDisplayCutoutSafe; 86 if (mRotation == rotation && mWidth == w && mHeight == h 87 && mInsetsState.getDisplayCutout().equals(displayCutout) 88 && state.getRoundedCorners().equals(roundedCorners) 89 && state.getPrivacyIndicatorBounds().equals(indicatorBounds)) { 90 return false; 91 } 92 mRotation = rotation; 93 mWidth = w; 94 mHeight = h; 95 final Rect u = mUnrestricted; 96 u.set(0, 0, w, h); 97 state.setDisplayFrame(u); 98 state.setDisplayCutout(displayCutout); 99 state.setRoundedCorners(roundedCorners); 100 state.setPrivacyIndicatorBounds(indicatorBounds); 101 state.setDisplayShape(displayShape); 102 state.getDisplayCutoutSafe(safe); 103 if (safe.left > u.left) { 104 state.getOrCreateSource(ID_DISPLAY_CUTOUT_LEFT, displayCutout()) 105 .setFrame(u.left, u.top, safe.left, u.bottom) 106 .updateSideHint(u); 107 } else { 108 state.removeSource(ID_DISPLAY_CUTOUT_LEFT); 109 } 110 if (safe.top > u.top) { 111 state.getOrCreateSource(ID_DISPLAY_CUTOUT_TOP, displayCutout()) 112 .setFrame(u.left, u.top, u.right, safe.top) 113 .updateSideHint(u); 114 } else { 115 state.removeSource(ID_DISPLAY_CUTOUT_TOP); 116 } 117 if (safe.right < u.right) { 118 state.getOrCreateSource(ID_DISPLAY_CUTOUT_RIGHT, displayCutout()) 119 .setFrame(safe.right, u.top, u.right, u.bottom) 120 .updateSideHint(u); 121 } else { 122 state.removeSource(ID_DISPLAY_CUTOUT_RIGHT); 123 } 124 if (safe.bottom < u.bottom) { 125 state.getOrCreateSource(ID_DISPLAY_CUTOUT_BOTTOM, displayCutout()) 126 .setFrame(u.left, safe.bottom, u.right, u.bottom) 127 .updateSideHint(u); 128 } else { 129 state.removeSource(ID_DISPLAY_CUTOUT_BOTTOM); 130 } 131 return true; 132 } 133 dumpDebug(ProtoOutputStream proto, long fieldId)134 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 135 final long token = proto.start(fieldId); 136 proto.end(token); 137 } 138 dump(String prefix, PrintWriter pw)139 public void dump(String prefix, PrintWriter pw) { 140 pw.println(prefix + "DisplayFrames w=" + mWidth + " h=" + mHeight + " r=" + mRotation); 141 } 142 } 143