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