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 unrestricted = mUnrestricted; 96 unrestricted.set(0, 0, w, h); 97 state.setDisplayFrame(unrestricted); 98 state.setDisplayCutout(displayCutout); 99 state.setRoundedCorners(roundedCorners); 100 state.setPrivacyIndicatorBounds(indicatorBounds); 101 state.setDisplayShape(displayShape); 102 state.getDisplayCutoutSafe(safe); 103 if (safe.left > unrestricted.left) { 104 state.getOrCreateSource(ID_DISPLAY_CUTOUT_LEFT, displayCutout()).setFrame( 105 unrestricted.left, unrestricted.top, safe.left, unrestricted.bottom); 106 } else { 107 state.removeSource(ID_DISPLAY_CUTOUT_LEFT); 108 } 109 if (safe.top > unrestricted.top) { 110 state.getOrCreateSource(ID_DISPLAY_CUTOUT_TOP, displayCutout()).setFrame( 111 unrestricted.left, unrestricted.top, unrestricted.right, safe.top); 112 } else { 113 state.removeSource(ID_DISPLAY_CUTOUT_TOP); 114 } 115 if (safe.right < unrestricted.right) { 116 state.getOrCreateSource(ID_DISPLAY_CUTOUT_RIGHT, displayCutout()).setFrame( 117 safe.right, unrestricted.top, unrestricted.right, unrestricted.bottom); 118 } else { 119 state.removeSource(ID_DISPLAY_CUTOUT_RIGHT); 120 } 121 if (safe.bottom < unrestricted.bottom) { 122 state.getOrCreateSource(ID_DISPLAY_CUTOUT_BOTTOM, displayCutout()).setFrame( 123 unrestricted.left, safe.bottom, unrestricted.right, unrestricted.bottom); 124 } else { 125 state.removeSource(ID_DISPLAY_CUTOUT_BOTTOM); 126 } 127 return true; 128 } 129 dumpDebug(ProtoOutputStream proto, long fieldId)130 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 131 final long token = proto.start(fieldId); 132 proto.end(token); 133 } 134 dump(String prefix, PrintWriter pw)135 public void dump(String prefix, PrintWriter pw) { 136 pw.println(prefix + "DisplayFrames w=" + mWidth + " h=" + mHeight + " r=" + mRotation); 137 } 138 } 139