1 /*
2  * Copyright (C) 2024 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 package androidx.window.sidecar;
17 
18 import static android.view.Display.DEFAULT_DISPLAY;
19 
20 import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation;
21 import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect;
22 
23 import android.annotation.NonNull;
24 import android.app.Activity;
25 import android.app.ActivityThread;
26 import android.graphics.Rect;
27 import android.os.IBinder;
28 
29 import androidx.window.common.CommonFoldingFeature;
30 
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.List;
34 
35 /**
36  * A utility class for transforming between Sidecar and Extensions features.
37  */
38 class SidecarHelper {
39 
SidecarHelper()40     private SidecarHelper() {}
41 
42     /**
43      * Returns the {@link SidecarDeviceState} posture that is calculated for the first fold in
44      * the feature list. Sidecar devices only have one fold so we only pick the first one to
45      * determine the state.
46      * @param featureList the {@link CommonFoldingFeature} that are currently active.
47      * @return the {@link SidecarDeviceState} calculated from the {@link List} of
48      * {@link CommonFoldingFeature}.
49      */
50     @SuppressWarnings("deprecation")
deviceStateFromFeatureList(@onNull List<CommonFoldingFeature> featureList)51     private static int deviceStateFromFeatureList(@NonNull List<CommonFoldingFeature> featureList) {
52         for (int i = 0; i < featureList.size(); i++) {
53             final CommonFoldingFeature feature = featureList.get(i);
54             final int state = feature.getState();
55             switch (state) {
56                 case CommonFoldingFeature.COMMON_STATE_FLAT:
57                     return SidecarDeviceState.POSTURE_OPENED;
58                 case CommonFoldingFeature.COMMON_STATE_HALF_OPENED:
59                     return SidecarDeviceState.POSTURE_HALF_OPENED;
60                 case CommonFoldingFeature.COMMON_STATE_UNKNOWN:
61                     return SidecarDeviceState.POSTURE_UNKNOWN;
62                 case CommonFoldingFeature.COMMON_STATE_NO_FOLDING_FEATURES:
63                     return SidecarDeviceState.POSTURE_UNKNOWN;
64                 case CommonFoldingFeature.COMMON_STATE_USE_BASE_STATE:
65                     return SidecarDeviceState.POSTURE_UNKNOWN;
66             }
67         }
68         return SidecarDeviceState.POSTURE_UNKNOWN;
69     }
70 
71     /**
72      * Returns a {@link SidecarDeviceState} calculated from a {@link List} of
73      * {@link CommonFoldingFeature}s.
74      */
75     @SuppressWarnings("deprecation")
calculateDeviceState( @onNull List<CommonFoldingFeature> featureList)76     static SidecarDeviceState calculateDeviceState(
77             @NonNull List<CommonFoldingFeature> featureList) {
78         final SidecarDeviceState deviceState = new SidecarDeviceState();
79         deviceState.posture = deviceStateFromFeatureList(featureList);
80         return deviceState;
81     }
82 
83     @SuppressWarnings("deprecation")
calculateDisplayFeatures( @onNull Activity activity, @NonNull List<CommonFoldingFeature> featureList )84     private static List<SidecarDisplayFeature> calculateDisplayFeatures(
85             @NonNull Activity activity,
86             @NonNull List<CommonFoldingFeature> featureList
87     ) {
88         final int displayId = activity.getDisplay().getDisplayId();
89         if (displayId != DEFAULT_DISPLAY) {
90             return Collections.emptyList();
91         }
92 
93         if (activity.isInMultiWindowMode()) {
94             // It is recommended not to report any display features in multi-window mode, since it
95             // won't be possible to synchronize the display feature positions with window movement.
96             return Collections.emptyList();
97         }
98 
99         final List<SidecarDisplayFeature> features = new ArrayList<>();
100         final int rotation = activity.getResources().getConfiguration().windowConfiguration
101                 .getDisplayRotation();
102         for (CommonFoldingFeature baseFeature : featureList) {
103             final SidecarDisplayFeature feature = new SidecarDisplayFeature();
104             final Rect featureRect = baseFeature.getRect();
105             rotateRectToDisplayRotation(displayId, rotation, featureRect);
106             transformToWindowSpaceRect(activity, featureRect);
107             feature.setRect(featureRect);
108             feature.setType(baseFeature.getType());
109             features.add(feature);
110         }
111         return Collections.unmodifiableList(features);
112     }
113 
114     /**
115      * Returns a {@link SidecarWindowLayoutInfo} calculated from the {@link List} of
116      * {@link CommonFoldingFeature}.
117      */
118     @SuppressWarnings("deprecation")
calculateWindowLayoutInfo(@onNull IBinder windowToken, @NonNull List<CommonFoldingFeature> featureList)119     static SidecarWindowLayoutInfo calculateWindowLayoutInfo(@NonNull IBinder windowToken,
120             @NonNull List<CommonFoldingFeature> featureList) {
121         final Activity activity = ActivityThread.currentActivityThread().getActivity(windowToken);
122         final SidecarWindowLayoutInfo windowLayoutInfo = new SidecarWindowLayoutInfo();
123         if (activity == null) {
124             return windowLayoutInfo;
125         }
126         windowLayoutInfo.displayFeatures = calculateDisplayFeatures(activity, featureList);
127         return windowLayoutInfo;
128     }
129 }
130