Home | History | Annotate | Download | only in wm
      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.Surface.ROTATION_180;
     20 import static android.view.Surface.ROTATION_270;
     21 import static android.view.Surface.ROTATION_90;
     22 import static com.android.server.wm.DisplayFramesProto.STABLE_BOUNDS;
     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 
     30 import com.android.server.wm.utils.WmDisplayCutout;
     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     public final int mDisplayId;
     40 
     41     /**
     42      * The current size of the screen; really; extends into the overscan area of the screen and
     43      * doesn't account for any system elements like the status bar.
     44      */
     45     public final Rect mOverscan = new Rect();
     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     /** Like mOverscan*, but allowed to move into the overscan region where appropriate. */
     54     public final Rect mRestrictedOverscan = new Rect();
     55 
     56     /**
     57      * The current size of the screen; these may be different than (0,0)-(dw,dh) if the status bar
     58      * can't be hidden; in that case it effectively carves out that area of the display from all
     59      * other windows.
     60      */
     61     public final Rect mRestricted = new Rect();
     62 
     63     /**
     64      * During layout, the current screen borders accounting for any currently visible system UI
     65      * elements.
     66      */
     67     public final Rect mSystem = new Rect();
     68 
     69     /** For applications requesting stable content insets, these are them. */
     70     public final Rect mStable = new Rect();
     71 
     72     /**
     73      * For applications requesting stable content insets but have also set the fullscreen window
     74      * flag, these are the stable dimensions without the status bar.
     75      */
     76     public final Rect mStableFullscreen = new Rect();
     77 
     78     /**
     79      * During layout, the current screen borders with all outer decoration (status bar, input method
     80      * dock) accounted for.
     81      */
     82     public final Rect mCurrent = new Rect();
     83 
     84     /**
     85      * During layout, the frame in which content should be displayed to the user, accounting for all
     86      * screen decoration except for any space they deem as available for other content. This is
     87      * usually the same as mCurrent*, but may be larger if the screen decor has supplied content
     88      * insets.
     89      */
     90     public final Rect mContent = new Rect();
     91 
     92     /**
     93      * During layout, the frame in which voice content should be displayed to the user, accounting
     94      * for all screen decoration except for any space they deem as available for other content.
     95      */
     96     public final Rect mVoiceContent = new Rect();
     97 
     98     /** During layout, the current screen borders along which input method windows are placed. */
     99     public final Rect mDock = new Rect();
    100 
    101     /** The display cutout used for layout (after rotation) */
    102     @NonNull public WmDisplayCutout mDisplayCutout = WmDisplayCutout.NO_CUTOUT;
    103 
    104     /** The cutout as supplied by display info */
    105     @NonNull public WmDisplayCutout mDisplayInfoCutout = WmDisplayCutout.NO_CUTOUT;
    106 
    107     /**
    108      * During layout, the frame that is display-cutout safe, i.e. that does not intersect with it.
    109      */
    110     public final Rect mDisplayCutoutSafe = new Rect();
    111 
    112     private final Rect mDisplayInfoOverscan = new Rect();
    113     private final Rect mRotatedDisplayInfoOverscan = new Rect();
    114     public int mDisplayWidth;
    115     public int mDisplayHeight;
    116 
    117     public int mRotation;
    118 
    119     public DisplayFrames(int displayId, DisplayInfo info, WmDisplayCutout displayCutout) {
    120         mDisplayId = displayId;
    121         onDisplayInfoUpdated(info, displayCutout);
    122     }
    123 
    124     public void onDisplayInfoUpdated(DisplayInfo info, WmDisplayCutout displayCutout) {
    125         mDisplayWidth = info.logicalWidth;
    126         mDisplayHeight = info.logicalHeight;
    127         mRotation = info.rotation;
    128         mDisplayInfoOverscan.set(
    129                 info.overscanLeft, info.overscanTop, info.overscanRight, info.overscanBottom);
    130         mDisplayInfoCutout = displayCutout != null ? displayCutout : WmDisplayCutout.NO_CUTOUT;
    131     }
    132 
    133     public void onBeginLayout() {
    134         switch (mRotation) {
    135             case ROTATION_90:
    136                 mRotatedDisplayInfoOverscan.left = mDisplayInfoOverscan.top;
    137                 mRotatedDisplayInfoOverscan.top = mDisplayInfoOverscan.right;
    138                 mRotatedDisplayInfoOverscan.right = mDisplayInfoOverscan.bottom;
    139                 mRotatedDisplayInfoOverscan.bottom = mDisplayInfoOverscan.left;
    140                 break;
    141             case ROTATION_180:
    142                 mRotatedDisplayInfoOverscan.left = mDisplayInfoOverscan.right;
    143                 mRotatedDisplayInfoOverscan.top = mDisplayInfoOverscan.bottom;
    144                 mRotatedDisplayInfoOverscan.right = mDisplayInfoOverscan.left;
    145                 mRotatedDisplayInfoOverscan.bottom = mDisplayInfoOverscan.top;
    146                 break;
    147             case ROTATION_270:
    148                 mRotatedDisplayInfoOverscan.left = mDisplayInfoOverscan.bottom;
    149                 mRotatedDisplayInfoOverscan.top = mDisplayInfoOverscan.left;
    150                 mRotatedDisplayInfoOverscan.right = mDisplayInfoOverscan.top;
    151                 mRotatedDisplayInfoOverscan.bottom = mDisplayInfoOverscan.right;
    152                 break;
    153             default:
    154                 mRotatedDisplayInfoOverscan.set(mDisplayInfoOverscan);
    155                 break;
    156         }
    157 
    158         mRestrictedOverscan.set(0, 0, mDisplayWidth, mDisplayHeight);
    159         mOverscan.set(mRestrictedOverscan);
    160         mSystem.set(mRestrictedOverscan);
    161         mUnrestricted.set(mRotatedDisplayInfoOverscan);
    162         mUnrestricted.right = mDisplayWidth - mUnrestricted.right;
    163         mUnrestricted.bottom = mDisplayHeight - mUnrestricted.bottom;
    164         mRestricted.set(mUnrestricted);
    165         mDock.set(mUnrestricted);
    166         mContent.set(mUnrestricted);
    167         mVoiceContent.set(mUnrestricted);
    168         mStable.set(mUnrestricted);
    169         mStableFullscreen.set(mUnrestricted);
    170         mCurrent.set(mUnrestricted);
    171 
    172         mDisplayCutout = mDisplayInfoCutout;
    173         mDisplayCutoutSafe.set(Integer.MIN_VALUE, Integer.MIN_VALUE,
    174                 Integer.MAX_VALUE, Integer.MAX_VALUE);
    175         if (!mDisplayCutout.getDisplayCutout().isEmpty()) {
    176             final DisplayCutout c = mDisplayCutout.getDisplayCutout();
    177             if (c.getSafeInsetLeft() > 0) {
    178                 mDisplayCutoutSafe.left = mRestrictedOverscan.left + c.getSafeInsetLeft();
    179             }
    180             if (c.getSafeInsetTop() > 0) {
    181                 mDisplayCutoutSafe.top = mRestrictedOverscan.top + c.getSafeInsetTop();
    182             }
    183             if (c.getSafeInsetRight() > 0) {
    184                 mDisplayCutoutSafe.right = mRestrictedOverscan.right - c.getSafeInsetRight();
    185             }
    186             if (c.getSafeInsetBottom() > 0) {
    187                 mDisplayCutoutSafe.bottom = mRestrictedOverscan.bottom - c.getSafeInsetBottom();
    188             }
    189         }
    190     }
    191 
    192     public int getInputMethodWindowVisibleHeight() {
    193         return mDock.bottom - mCurrent.bottom;
    194     }
    195 
    196     public void writeToProto(ProtoOutputStream proto, long fieldId) {
    197         final long token = proto.start(fieldId);
    198         mStable.writeToProto(proto, STABLE_BOUNDS);
    199         proto.end(token);
    200     }
    201 
    202     public void dump(String prefix, PrintWriter pw) {
    203         pw.println(prefix + "DisplayFrames w=" + mDisplayWidth + " h=" + mDisplayHeight
    204                 + " r=" + mRotation);
    205         final String myPrefix = prefix + "  ";
    206         dumpFrame(mStable, "mStable", myPrefix, pw);
    207         dumpFrame(mStableFullscreen, "mStableFullscreen", myPrefix, pw);
    208         dumpFrame(mDock, "mDock", myPrefix, pw);
    209         dumpFrame(mCurrent, "mCurrent", myPrefix, pw);
    210         dumpFrame(mSystem, "mSystem", myPrefix, pw);
    211         dumpFrame(mContent, "mContent", myPrefix, pw);
    212         dumpFrame(mVoiceContent, "mVoiceContent", myPrefix, pw);
    213         dumpFrame(mOverscan, "mOverscan", myPrefix, pw);
    214         dumpFrame(mRestrictedOverscan, "mRestrictedOverscan", myPrefix, pw);
    215         dumpFrame(mRestricted, "mRestricted", myPrefix, pw);
    216         dumpFrame(mUnrestricted, "mUnrestricted", myPrefix, pw);
    217         dumpFrame(mDisplayInfoOverscan, "mDisplayInfoOverscan", myPrefix, pw);
    218         dumpFrame(mRotatedDisplayInfoOverscan, "mRotatedDisplayInfoOverscan", myPrefix, pw);
    219         pw.println(myPrefix + "mDisplayCutout=" + mDisplayCutout);
    220     }
    221 
    222     private void dumpFrame(Rect frame, String name, String prefix, PrintWriter pw) {
    223         pw.print(prefix + name + "="); frame.printShortString(pw); pw.println();
    224     }
    225 }
    226