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