1 /*
2  * Copyright 2021 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 androidx.window.extensions.layout;
18 
19 import android.app.Activity;
20 import android.content.Context;
21 import android.os.Bundle;
22 import android.view.Display;
23 
24 import androidx.annotation.UiContext;
25 import androidx.window.extensions.RequiresVendorApiLevel;
26 import androidx.window.extensions.WindowExtensions;
27 import androidx.window.extensions.core.util.function.Consumer;
28 
29 import org.jspecify.annotations.NonNull;
30 
31 /**
32  * The interface definition that will be used by the WindowManager library to get custom
33  * OEM-provided information about the window that isn't covered by platform APIs. Exposes methods
34  * to listen to changes in the {@link WindowLayoutInfo}. A {@link WindowLayoutInfo} contains a list
35  * of {@link DisplayFeature}s.
36  * <p>
37  * Currently {@link FoldingFeature} is the only {@link DisplayFeature}. A {@link FoldingFeature}
38  * exposes the state of a hinge and the relative bounds within the window. Developers can
39  * optimize their UI to support a {@link FoldingFeature} by avoiding it and placing content in
40  * relevant logical areas.
41  *
42  * <p>This interface should be implemented by OEM and deployed to the target devices.
43  * @see WindowExtensions#getWindowLayoutComponent()
44  */
45 public interface WindowLayoutComponent {
46     /**
47      * @deprecated Use {@link #addWindowLayoutInfoListener(Context, Consumer)}
48      * starting with vendor API level 2. Only used if
49      * {@link #addWindowLayoutInfoListener(Context, Consumer)} can't be
50      * called on vendor API level 1.
51      */
52     @RequiresVendorApiLevel(level = 1, deprecatedSince = 2)
53     @Deprecated
addWindowLayoutInfoListener(@onNull Activity activity, java.util.function.@NonNull Consumer<WindowLayoutInfo> consumer)54     void addWindowLayoutInfoListener(@NonNull Activity activity,
55             java.util.function.@NonNull Consumer<WindowLayoutInfo> consumer);
56 
57     /**
58      * @deprecated Use {@link #removeWindowLayoutInfoListener(Consumer)} starting with
59      * vendor API level 2. Only used if {@link #removeWindowLayoutInfoListener(Consumer)} can't
60      * be called on vendor API level 1.
61      */
62     @RequiresVendorApiLevel(level = 1, deprecatedSince = 2)
63     @Deprecated
removeWindowLayoutInfoListener( java.util.function.@onNull Consumer<WindowLayoutInfo> consumer)64     void removeWindowLayoutInfoListener(
65             java.util.function.@NonNull Consumer<WindowLayoutInfo> consumer);
66 
67     /**
68      * Adds a listener interested in receiving updates to {@link WindowLayoutInfo}.
69      * Use {@link WindowLayoutComponent#removeWindowLayoutInfoListener} to remove listener.
70      * <p>
71      * A {@link Context} or a Consumer instance can only be registered once.
72      * Registering the same {@link Context} or Consumer more than once will result in
73      * a noop.
74      *
75      * @param context a {@link UiContext} that corresponds to a window or an area on the
76      *                      screen - an {@link Activity}, a {@link Context} created with
77      *                      {@link Context#createWindowContext(Display, int, Bundle)}, or
78      *                      {@link android.inputmethodservice.InputMethodService}.
79      * @param consumer interested in receiving updates to {@link WindowLayoutInfo}
80      */
81     @RequiresVendorApiLevel(level = 2)
82     @SuppressWarnings("PairedRegistration")
83     // The paired method for unregistering is also removeWindowLayoutInfoListener.
addWindowLayoutInfoListener(@iContext @onNull Context context, @NonNull Consumer<WindowLayoutInfo> consumer)84     default void addWindowLayoutInfoListener(@UiContext @NonNull Context context,
85             @NonNull Consumer<WindowLayoutInfo> consumer) {
86         throw new UnsupportedOperationException("This method must not be called unless there is a"
87                 + " corresponding override implementation on the device.");
88     }
89 
90     /**
91      * Removes a listener no longer interested in receiving updates.
92      *
93      * @param consumer no longer interested in receiving updates to {@link WindowLayoutInfo}
94      */
95     @RequiresVendorApiLevel(level = 2)
removeWindowLayoutInfoListener(@onNull Consumer<WindowLayoutInfo> consumer)96     default void removeWindowLayoutInfoListener(@NonNull Consumer<WindowLayoutInfo> consumer) {
97         throw new UnsupportedOperationException("This method must not be called unless there is a"
98                 + " corresponding override implementation on the device.");
99     }
100 
101     /**
102      * Returns the {@link SupportedWindowFeatures} for the device. This value will not change
103      * over time.
104      * @see WindowLayoutComponent#addWindowLayoutInfoListener(Context, Consumer) to register a
105      * listener for features that impact the window.
106      */
107     @RequiresVendorApiLevel(level = 6)
getSupportedWindowFeatures()108     default @NonNull SupportedWindowFeatures getSupportedWindowFeatures() {
109         throw new UnsupportedOperationException("This method will not be called unless there is a"
110                 + " corresponding override implementation on the device");
111     }
112 
113     /**
114      * Returns the current {@link WindowLayoutInfo} for the given {@link Context}.
115      * <p>
116      * This API provides a convenient way to access the current {@link WindowLayoutInfo} without
117      * registering a listener via {@link #addWindowLayoutInfoListener(Context, Consumer)}. It
118      * simplifies the retrieval of {@link WindowLayoutInfo} in scenarios like
119      * {@link Activity#onCreate(Bundle)}.
120      *
121      * @param context a {@link Context} that corresponds to a window or an area on the screen.
122      *                This can be an {@link Activity}, a {@link Context} created with
123      *                {@link Context#createWindowContext(Display, int, Bundle)}, or an
124      *                {@link android.inputmethodservice.InputMethodService}.
125      * @return the current {@link WindowLayoutInfo} for the given {@link Context}.
126      */
127     @RequiresVendorApiLevel(level = 9)
getCurrentWindowLayoutInfo( @iContext @onNull Context context)128     default @NonNull WindowLayoutInfo getCurrentWindowLayoutInfo(
129             @UiContext @NonNull Context context) {
130         throw new UnsupportedOperationException("This method will not be called unless there is a"
131                 + " corresponding override implementation on the device");
132     }
133 }
134