• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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;
18 
19 import static android.view.Display.DEFAULT_DISPLAY;
20 
21 import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation;
22 import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect;
23 
24 import android.app.Activity;
25 import android.content.Context;
26 import android.graphics.Rect;
27 import android.util.Log;
28 
29 import androidx.annotation.NonNull;
30 import androidx.window.common.DeviceStateManagerPostureProducer;
31 import androidx.window.common.DisplayFeature;
32 import androidx.window.common.ResourceConfigDisplayFeatureProducer;
33 import androidx.window.common.SettingsDevicePostureProducer;
34 import androidx.window.common.SettingsDisplayFeatureProducer;
35 import androidx.window.util.DataProducer;
36 import androidx.window.util.PriorityDataProducer;
37 
38 import java.util.ArrayList;
39 import java.util.List;
40 import java.util.Optional;
41 
42 /**
43  * Reference implementation of androidx.window.extensions OEM interface for use with
44  * WindowManager Jetpack.
45  *
46  * NOTE: This version is a work in progress and under active development. It MUST NOT be used in
47  * production builds since the interface can still change before reaching stable version.
48  * Please refer to {@link androidx.window.sidecar.SampleSidecarImpl} instead.
49  */
50 class SampleExtensionImpl extends StubExtension {
51     private static final String TAG = "SampleExtension";
52 
53     private final SettingsDevicePostureProducer mSettingsDevicePostureProducer;
54     private final DataProducer<Integer> mDevicePostureProducer;
55 
56     private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer;
57     private final DataProducer<List<DisplayFeature>> mDisplayFeatureProducer;
58 
SampleExtensionImpl(Context context)59     SampleExtensionImpl(Context context) {
60         mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context);
61         mDevicePostureProducer = new PriorityDataProducer<>(List.of(
62                 mSettingsDevicePostureProducer,
63                 new DeviceStateManagerPostureProducer(context)
64         ));
65 
66         mSettingsDisplayFeatureProducer = new SettingsDisplayFeatureProducer(context);
67         mDisplayFeatureProducer = new PriorityDataProducer<>(List.of(
68                 mSettingsDisplayFeatureProducer,
69                 new ResourceConfigDisplayFeatureProducer(context)
70         ));
71 
72         mDevicePostureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
73         mDisplayFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
74     }
75 
getFeatureState(DisplayFeature feature)76     private int getFeatureState(DisplayFeature feature) {
77         Integer featureState = feature.getState();
78         Optional<Integer> posture = mDevicePostureProducer.getData();
79         int fallbackPosture = posture.orElse(ExtensionFoldingFeature.STATE_FLAT);
80         return featureState == null ? fallbackPosture : featureState;
81     }
82 
onDisplayFeaturesChanged()83     private void onDisplayFeaturesChanged() {
84         for (Activity activity : getActivitiesListeningForLayoutChanges()) {
85             ExtensionWindowLayoutInfo newLayout = getWindowLayoutInfo(activity);
86             updateWindowLayout(activity, newLayout);
87         }
88     }
89 
90     @NonNull
getWindowLayoutInfo(@onNull Activity activity)91     private ExtensionWindowLayoutInfo getWindowLayoutInfo(@NonNull Activity activity) {
92         List<ExtensionDisplayFeature> displayFeatures = getDisplayFeatures(activity);
93         return new ExtensionWindowLayoutInfo(displayFeatures);
94     }
95 
getDisplayFeatures(@onNull Activity activity)96     private List<ExtensionDisplayFeature> getDisplayFeatures(@NonNull Activity activity) {
97         List<ExtensionDisplayFeature> features = new ArrayList<>();
98         int displayId = activity.getDisplay().getDisplayId();
99         if (displayId != DEFAULT_DISPLAY) {
100             Log.w(TAG, "This sample doesn't support display features on secondary displays");
101             return features;
102         }
103 
104         if (activity.isInMultiWindowMode()) {
105             // It is recommended not to report any display features in multi-window mode, since it
106             // won't be possible to synchronize the display feature positions with window movement.
107             return features;
108         }
109 
110         Optional<List<DisplayFeature>> storedFeatures = mDisplayFeatureProducer.getData();
111         if (storedFeatures.isPresent()) {
112 
113             for (DisplayFeature baseFeature : storedFeatures.get()) {
114                 Rect featureRect = baseFeature.getRect();
115                 rotateRectToDisplayRotation(displayId, featureRect);
116                 transformToWindowSpaceRect(activity, featureRect);
117 
118                 features.add(new ExtensionFoldingFeature(featureRect, baseFeature.getType(),
119                         getFeatureState(baseFeature)));
120             }
121         }
122         return features;
123     }
124 
125     @Override
onListenersChanged()126     protected void onListenersChanged() {
127         if (hasListeners()) {
128             mSettingsDevicePostureProducer.registerObserversIfNeeded();
129             mSettingsDisplayFeatureProducer.registerObserversIfNeeded();
130         } else {
131             mSettingsDevicePostureProducer.unregisterObserversIfNeeded();
132             mSettingsDisplayFeatureProducer.unregisterObserversIfNeeded();
133         }
134 
135         onDisplayFeaturesChanged();
136     }
137 }
138