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