1/*
2 * Copyright 2018 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
17package androidx.core.view;
18
19import static android.os.Build.VERSION.SDK_INT;
20
21import android.graphics.Rect;
22import android.view.DisplayCutout;
23
24import java.util.List;
25
26
27/**
28 * Represents the area of the display that is not functional for displaying content.
29 *
30 * <p>{@code DisplayCutoutCompat} instances are immutable.
31 */
32public final class DisplayCutoutCompat {
33
34    private final Object mDisplayCutout;
35
36    /**
37     * Creates a DisplayCutout instance.
38     *
39     * @param safeInsets the insets from each edge which avoid the display cutout as returned by
40     *                   {@link #getSafeInsetTop()} etc.
41     * @param boundingRects the bounding rects of the display cutouts as returned by
42     *               {@link #getBoundingRects()} ()}.
43     */
44    // TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE)
45    public DisplayCutoutCompat(Rect safeInsets, List<Rect> boundingRects) {
46        this(SDK_INT >= 28 ? new DisplayCutout(safeInsets, boundingRects) : null);
47    }
48
49    private DisplayCutoutCompat(Object displayCutout) {
50        mDisplayCutout = displayCutout;
51    }
52
53    /** Returns the inset from the top which avoids the display cutout in pixels. */
54    public int getSafeInsetTop() {
55        if (SDK_INT >= 28) {
56            return ((DisplayCutout) mDisplayCutout).getSafeInsetTop();
57        } else {
58            return 0;
59        }
60    }
61
62    /** Returns the inset from the bottom which avoids the display cutout in pixels. */
63    public int getSafeInsetBottom() {
64        if (SDK_INT >= 28) {
65            return ((DisplayCutout) mDisplayCutout).getSafeInsetBottom();
66        } else {
67            return 0;
68        }
69    }
70
71    /** Returns the inset from the left which avoids the display cutout in pixels. */
72    public int getSafeInsetLeft() {
73        if (SDK_INT >= 28) {
74            return ((DisplayCutout) mDisplayCutout).getSafeInsetLeft();
75        } else {
76            return 0;
77        }
78    }
79
80    /** Returns the inset from the right which avoids the display cutout in pixels. */
81    public int getSafeInsetRight() {
82        if (SDK_INT >= 28) {
83            return ((DisplayCutout) mDisplayCutout).getSafeInsetRight();
84        } else {
85            return 0;
86        }
87    }
88
89    /**
90     * Returns a list of {@code Rect}s, each of which is the bounding rectangle for a non-functional
91     * area on the display.
92     *
93     * There will be at most one non-functional area per short edge of the device, and none on
94     * the long edges.
95     *
96     * @return a list of bounding {@code Rect}s, one for each display cutout area.
97     */
98    public List<Rect> getBoundingRects() {
99        if (SDK_INT >= 28) {
100            return ((DisplayCutout) mDisplayCutout).getBoundingRects();
101        } else {
102            return null;
103        }
104    }
105
106    @Override
107    public boolean equals(Object o) {
108        if (this == o) {
109            return true;
110        }
111        if (o == null || getClass() != o.getClass()) {
112            return false;
113        }
114        DisplayCutoutCompat other = (DisplayCutoutCompat) o;
115        return mDisplayCutout == null ? other.mDisplayCutout == null
116                : mDisplayCutout.equals(other.mDisplayCutout);
117    }
118
119    @Override
120    public int hashCode() {
121        return mDisplayCutout == null ? 0 : mDisplayCutout.hashCode();
122    }
123
124    @Override
125    public String toString() {
126        return "DisplayCutoutCompat{" + mDisplayCutout + "}";
127    }
128
129    static DisplayCutoutCompat wrap(Object displayCutout) {
130        return displayCutout == null ? null : new DisplayCutoutCompat(displayCutout);
131    }
132}
133