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