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 android.annotation.Nullable;
20 import android.app.Activity;
21 import android.app.Application;
22 import android.content.Context;
23 import android.hardware.devicestate.DeviceStateManager;
24 import android.os.Bundle;
25 import android.os.IBinder;
26 
27 import androidx.annotation.NonNull;
28 import androidx.window.common.CommonFoldingFeature;
29 import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
30 import androidx.window.common.EmptyLifecycleCallbacksAdapter;
31 import androidx.window.common.RawFoldingFeatureProducer;
32 import androidx.window.util.BaseDataProducer;
33 
34 import java.util.ArrayList;
35 import java.util.List;
36 
37 /**
38  * Reference implementation of androidx.window.sidecar OEM interface for use with
39  * WindowManager Jetpack.
40  */
41 class SampleSidecarImpl extends StubSidecar {
42     private List<CommonFoldingFeature> mStoredFeatures = new ArrayList<>();
43 
SampleSidecarImpl(Context context)44     SampleSidecarImpl(Context context) {
45         ((Application) context.getApplicationContext())
46                 .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged());
47         RawFoldingFeatureProducer settingsFeatureProducer = new RawFoldingFeatureProducer(context);
48         BaseDataProducer<List<CommonFoldingFeature>> foldingFeatureProducer =
49                 new DeviceStateManagerFoldingFeatureProducer(context,
50                         settingsFeatureProducer,
51                         context.getSystemService(DeviceStateManager.class));
52 
53         foldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
54     }
55 
setStoredFeatures(List<CommonFoldingFeature> storedFeatures)56     private void setStoredFeatures(List<CommonFoldingFeature> storedFeatures) {
57         mStoredFeatures = storedFeatures;
58     }
59 
onDisplayFeaturesChanged(List<CommonFoldingFeature> storedFeatures)60     private void onDisplayFeaturesChanged(List<CommonFoldingFeature> storedFeatures) {
61         setStoredFeatures(storedFeatures);
62         updateDeviceState(getDeviceState());
63         for (IBinder windowToken : getWindowsListeningForLayoutChanges()) {
64             SidecarWindowLayoutInfo newLayout = getWindowLayoutInfo(windowToken);
65             updateWindowLayout(windowToken, newLayout);
66         }
67     }
68 
69     @NonNull
70     @Override
getDeviceState()71     public SidecarDeviceState getDeviceState() {
72         return SidecarHelper.calculateDeviceState(mStoredFeatures);
73     }
74 
75     @NonNull
76     @Override
getWindowLayoutInfo(@onNull IBinder windowToken)77     public SidecarWindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken) {
78         return SidecarHelper.calculateWindowLayoutInfo(windowToken, mStoredFeatures);
79     }
80 
81     @Override
onListenersChanged()82     protected void onListenersChanged() {
83         if (hasListeners()) {
84             onDisplayFeaturesChanged(mStoredFeatures);
85         }
86     }
87 
88     private final class NotifyOnConfigurationChanged extends EmptyLifecycleCallbacksAdapter {
89         @Override
onActivityCreated(@onNull Activity activity, @Nullable Bundle savedInstanceState)90         public void onActivityCreated(@NonNull Activity activity,
91                 @Nullable Bundle savedInstanceState) {
92             super.onActivityCreated(activity, savedInstanceState);
93             onDisplayFeaturesChangedForActivity(activity);
94         }
95 
96         @Override
onActivityConfigurationChanged(@onNull Activity activity)97         public void onActivityConfigurationChanged(@NonNull Activity activity) {
98             super.onActivityConfigurationChanged(activity);
99             onDisplayFeaturesChangedForActivity(activity);
100         }
101 
onDisplayFeaturesChangedForActivity(@onNull Activity activity)102         private void onDisplayFeaturesChangedForActivity(@NonNull Activity activity) {
103             IBinder token = activity.getWindow().getAttributes().token;
104             if (token == null || mWindowLayoutChangeListenerTokens.contains(token)) {
105                 onDisplayFeaturesChanged(mStoredFeatures);
106             }
107         }
108     }
109 }
110