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 android.app.ActivityThread;
20 import android.app.Application;
21 import android.content.Context;
22 
23 import androidx.annotation.NonNull;
24 import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
25 import androidx.window.common.RawFoldingFeatureProducer;
26 import androidx.window.extensions.area.WindowAreaComponent;
27 import androidx.window.extensions.area.WindowAreaComponentImpl;
28 import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
29 import androidx.window.extensions.embedding.SplitController;
30 import androidx.window.extensions.layout.WindowLayoutComponent;
31 import androidx.window.extensions.layout.WindowLayoutComponentImpl;
32 
33 import java.util.Objects;
34 
35 
36 /**
37  * The reference implementation of {@link WindowExtensions} that implements the initial API version.
38  */
39 public class WindowExtensionsImpl implements WindowExtensions {
40 
41     private final Object mLock = new Object();
42     private volatile DeviceStateManagerFoldingFeatureProducer mFoldingFeatureProducer;
43     private volatile WindowLayoutComponentImpl mWindowLayoutComponent;
44     private volatile SplitController mSplitController;
45     private volatile WindowAreaComponent mWindowAreaComponent;
46 
47     // TODO(b/241126279) Introduce constants to better version functionality
48     @Override
getVendorApiLevel()49     public int getVendorApiLevel() {
50         return 4;
51     }
52 
53     @NonNull
getApplication()54     private Application getApplication() {
55         return Objects.requireNonNull(ActivityThread.currentApplication());
56     }
57 
58     @NonNull
getFoldingFeatureProducer()59     private DeviceStateManagerFoldingFeatureProducer getFoldingFeatureProducer() {
60         if (mFoldingFeatureProducer == null) {
61             synchronized (mLock) {
62                 if (mFoldingFeatureProducer == null) {
63                     Context context = getApplication();
64                     RawFoldingFeatureProducer foldingFeatureProducer =
65                             new RawFoldingFeatureProducer(context);
66                     mFoldingFeatureProducer =
67                             new DeviceStateManagerFoldingFeatureProducer(context,
68                                     foldingFeatureProducer);
69                 }
70             }
71         }
72         return mFoldingFeatureProducer;
73     }
74 
75     @NonNull
getWindowLayoutComponentImpl()76     private WindowLayoutComponentImpl getWindowLayoutComponentImpl() {
77         if (mWindowLayoutComponent == null) {
78             synchronized (mLock) {
79                 if (mWindowLayoutComponent == null) {
80                     Context context = getApplication();
81                     DeviceStateManagerFoldingFeatureProducer producer =
82                             getFoldingFeatureProducer();
83                     mWindowLayoutComponent = new WindowLayoutComponentImpl(context, producer);
84                 }
85             }
86         }
87         return mWindowLayoutComponent;
88     }
89 
90     /**
91      * Returns a reference implementation of {@link WindowLayoutComponent} if available,
92      * {@code null} otherwise. The implementation must match the API level reported in
93      * {@link WindowExtensions#getWindowLayoutComponent()}.
94      * @return {@link WindowLayoutComponent} OEM implementation
95      */
96     @Override
getWindowLayoutComponent()97     public WindowLayoutComponent getWindowLayoutComponent() {
98         return getWindowLayoutComponentImpl();
99     }
100 
101     /**
102      * Returns a reference implementation of {@link ActivityEmbeddingComponent} if available,
103      * {@code null} otherwise. The implementation must match the API level reported in
104      * {@link WindowExtensions#getWindowLayoutComponent()}.
105      * @return {@link ActivityEmbeddingComponent} OEM implementation.
106      */
107     @NonNull
getActivityEmbeddingComponent()108     public ActivityEmbeddingComponent getActivityEmbeddingComponent() {
109         if (mSplitController == null) {
110             synchronized (mLock) {
111                 if (mSplitController == null) {
112                     mSplitController = new SplitController(
113                             getWindowLayoutComponentImpl(),
114                             getFoldingFeatureProducer()
115                     );
116                 }
117             }
118         }
119         return mSplitController;
120     }
121 
122     /**
123      * Returns a reference implementation of {@link WindowAreaComponent} if available,
124      * {@code null} otherwise. The implementation must match the API level reported in
125      * {@link WindowExtensions#getWindowAreaComponent()}.
126      * @return {@link WindowAreaComponent} OEM implementation.
127      */
getWindowAreaComponent()128     public WindowAreaComponent getWindowAreaComponent() {
129         if (mWindowAreaComponent == null) {
130             synchronized (mLock) {
131                 if (mWindowAreaComponent == null) {
132                     Context context = ActivityThread.currentApplication();
133                     mWindowAreaComponent =
134                             new WindowAreaComponentImpl(context);
135                 }
136             }
137         }
138         return mWindowAreaComponent;
139     }
140 }
141