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 package android.window;
17 
18 import static android.view.WindowManagerImpl.createWindowContextWindowManager;
19 
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.UiContext;
23 import android.content.ComponentCallbacks;
24 import android.content.ComponentCallbacksController;
25 import android.content.Context;
26 import android.content.ContextWrapper;
27 import android.content.res.Configuration;
28 import android.os.Bundle;
29 import android.view.Display;
30 import android.view.WindowManager;
31 
32 import com.android.internal.annotations.VisibleForTesting;
33 
34 import java.lang.ref.Reference;
35 
36 /**
37  * {@link WindowContext} is a context for non-activity windows such as
38  * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} windows or system
39  * windows. Its resources and configuration are adjusted to the area of the display that will be
40  * used when a new window is added via {@link android.view.WindowManager#addView}.
41  *
42  * @see Context#createWindowContext(int, Bundle)
43  * @hide
44  */
45 @UiContext
46 public class WindowContext extends ContextWrapper implements WindowProvider {
47     private final WindowManager mWindowManager;
48     @WindowManager.LayoutParams.WindowType
49     private final int mType;
50     @Nullable
51     private final Bundle mOptions;
52     private final ComponentCallbacksController mCallbacksController =
53             new ComponentCallbacksController();
54     private final WindowContextController mController;
55 
56     /**
57      * Default implementation of {@link WindowContext}
58      * <p>
59      * Note that the users should call {@link Context#createWindowContext(Display, int, Bundle)}
60      * to create a {@link WindowContext} instead of using this constructor
61      * </p><p>
62      * Example usage:
63      * <pre class="prettyprint">
64      * Bundle options = new Bundle();
65      * options.put(KEY_ROOT_DISPLAY_AREA_ID, displayAreaInfo.rootDisplayAreaId);
66      * Context windowContext = context.createWindowContext(display, windowType, options);
67      * </pre></p>
68      *
69      * @param base    Base {@link Context} for this new instance.
70      * @param type    Window type to be used with this context.
71      * @param options A bundle used to pass window-related options.
72      * @see DisplayAreaInfo#rootDisplayAreaId
73      */
WindowContext(@onNull Context base, int type, @Nullable Bundle options)74     public WindowContext(@NonNull Context base, int type, @Nullable Bundle options) {
75         super(base);
76 
77         mType = type;
78         mOptions = options;
79         mWindowManager = createWindowContextWindowManager(this);
80         WindowTokenClient token = (WindowTokenClient) getWindowContextToken();
81         mController = new WindowContextController(token);
82 
83         Reference.reachabilityFence(this);
84     }
85 
86     /**
87      * Attaches this {@link WindowContext} to the {@link com.android.server.wm.DisplayArea}
88      * specified by {@code mType}, {@link #getDisplayId() display ID} and {@code mOptions}
89      * to receive configuration changes.
90      */
attachToDisplayArea()91     public void attachToDisplayArea() {
92         mController.attachToDisplayArea(mType, getDisplayId(), mOptions);
93     }
94 
95     @Override
getSystemService(String name)96     public Object getSystemService(String name) {
97         if (WINDOW_SERVICE.equals(name)) {
98             return mWindowManager;
99         }
100         return super.getSystemService(name);
101     }
102 
103     @Override
finalize()104     protected void finalize() throws Throwable {
105         release();
106         super.finalize();
107     }
108 
109     /** Used for test to invoke because we can't invoke finalize directly. */
110     @VisibleForTesting
release()111     public void release() {
112         mController.detachIfNeeded();
113         destroy();
114     }
115 
116     @Override
destroy()117     public void destroy() {
118         try {
119             mCallbacksController.clearCallbacks();
120             // Called to the base ContextImpl to do final clean-up.
121             getBaseContext().destroy();
122         } finally {
123             Reference.reachabilityFence(this);
124         }
125     }
126 
127     @Override
registerComponentCallbacks(@onNull ComponentCallbacks callback)128     public void registerComponentCallbacks(@NonNull ComponentCallbacks callback) {
129         mCallbacksController.registerCallbacks(callback);
130     }
131 
132     @Override
unregisterComponentCallbacks(@onNull ComponentCallbacks callback)133     public void unregisterComponentCallbacks(@NonNull ComponentCallbacks callback) {
134         mCallbacksController.unregisterCallbacks(callback);
135     }
136 
137     /** Dispatch {@link Configuration} to each {@link ComponentCallbacks}. */
dispatchConfigurationChanged(@onNull Configuration newConfig)138     void dispatchConfigurationChanged(@NonNull Configuration newConfig) {
139         mCallbacksController.dispatchConfigurationChanged(newConfig);
140     }
141 
142     @Override
getWindowType()143     public int getWindowType() {
144         return mType;
145     }
146 
147     @Nullable
148     @Override
getWindowContextOptions()149     public Bundle getWindowContextOptions() {
150         return mOptions;
151     }
152 }
153