• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.sidecar;
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.app.ActivityThread;
26 import android.content.Context;
27 import android.graphics.Rect;
28 import android.os.IBinder;
29 import android.util.Log;
30 
31 import androidx.annotation.NonNull;
32 import androidx.window.common.DeviceStateManagerPostureProducer;
33 import androidx.window.common.DisplayFeature;
34 import androidx.window.common.ResourceConfigDisplayFeatureProducer;
35 import androidx.window.common.SettingsDevicePostureProducer;
36 import androidx.window.common.SettingsDisplayFeatureProducer;
37 import androidx.window.util.DataProducer;
38 import androidx.window.util.PriorityDataProducer;
39 
40 import java.util.ArrayList;
41 import java.util.List;
42 import java.util.Optional;
43 
44 /**
45  * Reference implementation of androidx.window.sidecar OEM interface for use with
46  * WindowManager Jetpack.
47  */
48 class SampleSidecarImpl extends StubSidecar {
49     private static final String TAG = "SampleSidecar";
50 
51     private final SettingsDevicePostureProducer mSettingsDevicePostureProducer;
52     private final DataProducer<Integer> mDevicePostureProducer;
53 
54     private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer;
55     private final DataProducer<List<DisplayFeature>> mDisplayFeatureProducer;
56 
SampleSidecarImpl(Context context)57     SampleSidecarImpl(Context context) {
58         mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context);
59         mDevicePostureProducer = new PriorityDataProducer<>(List.of(
60                 mSettingsDevicePostureProducer,
61                 new DeviceStateManagerPostureProducer(context)
62         ));
63 
64         mSettingsDisplayFeatureProducer = new SettingsDisplayFeatureProducer(context);
65         mDisplayFeatureProducer = new PriorityDataProducer<>(List.of(
66                 mSettingsDisplayFeatureProducer,
67                 new ResourceConfigDisplayFeatureProducer(context)
68         ));
69 
70         mDevicePostureProducer.addDataChangedCallback(this::onDevicePostureChanged);
71         mDisplayFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
72     }
73 
onDevicePostureChanged()74     private void onDevicePostureChanged() {
75         updateDeviceState(getDeviceState());
76     }
77 
onDisplayFeaturesChanged()78     private void onDisplayFeaturesChanged() {
79         for (IBinder windowToken : getWindowsListeningForLayoutChanges()) {
80             SidecarWindowLayoutInfo newLayout = getWindowLayoutInfo(windowToken);
81             updateWindowLayout(windowToken, newLayout);
82         }
83     }
84 
85     @NonNull
86     @Override
getDeviceState()87     public SidecarDeviceState getDeviceState() {
88         Optional<Integer> posture = mDevicePostureProducer.getData();
89 
90         SidecarDeviceState deviceState = new SidecarDeviceState();
91         deviceState.posture = posture.orElse(SidecarDeviceState.POSTURE_UNKNOWN);
92         return deviceState;
93     }
94 
95     @NonNull
96     @Override
getWindowLayoutInfo(@onNull IBinder windowToken)97     public SidecarWindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken) {
98         Activity activity = ActivityThread.currentActivityThread().getActivity(windowToken);
99         SidecarWindowLayoutInfo windowLayoutInfo = new SidecarWindowLayoutInfo();
100         if (activity == null) {
101             return windowLayoutInfo;
102         }
103         windowLayoutInfo.displayFeatures = getDisplayFeatures(activity);
104         return windowLayoutInfo;
105     }
106 
getDisplayFeatures(@onNull Activity activity)107     private List<SidecarDisplayFeature> getDisplayFeatures(@NonNull Activity activity) {
108         List<SidecarDisplayFeature> features = new ArrayList<SidecarDisplayFeature>();
109         int displayId = activity.getDisplay().getDisplayId();
110         if (displayId != DEFAULT_DISPLAY) {
111             Log.w(TAG, "This sample doesn't support display features on secondary displays");
112             return features;
113         }
114 
115         if (activity.isInMultiWindowMode()) {
116             // It is recommended not to report any display features in multi-window mode, since it
117             // won't be possible to synchronize the display feature positions with window movement.
118             return features;
119         }
120 
121         Optional<List<DisplayFeature>> storedFeatures = mDisplayFeatureProducer.getData();
122         if (storedFeatures.isPresent()) {
123             for (DisplayFeature baseFeature : storedFeatures.get()) {
124                 SidecarDisplayFeature feature = new SidecarDisplayFeature();
125                 Rect featureRect = baseFeature.getRect();
126                 rotateRectToDisplayRotation(displayId, featureRect);
127                 transformToWindowSpaceRect(activity, featureRect);
128                 feature.setRect(featureRect);
129                 feature.setType(baseFeature.getType());
130                 features.add(feature);
131             }
132         }
133         return features;
134     }
135 
136     @Override
onListenersChanged()137     protected void onListenersChanged() {
138         if (hasListeners()) {
139             mSettingsDevicePostureProducer.registerObserversIfNeeded();
140             mSettingsDisplayFeatureProducer.registerObserversIfNeeded();
141         } else {
142             mSettingsDevicePostureProducer.unregisterObserversIfNeeded();
143             mSettingsDisplayFeatureProducer.unregisterObserversIfNeeded();
144         }
145     }
146 }
147