• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.app;
17 
18 import static android.view.WindowManagerGlobal.ADD_OKAY;
19 import static android.view.WindowManagerGlobal.ADD_TOO_MANY_TOKENS;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.content.Context;
24 import android.content.ContextWrapper;
25 import android.os.Bundle;
26 import android.os.IBinder;
27 import android.os.RemoteException;
28 import android.view.IWindowManager;
29 import android.view.WindowManagerGlobal;
30 import android.view.WindowManagerImpl;
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 public class WindowContext extends ContextWrapper {
46     private final WindowManagerImpl mWindowManager;
47     private final IWindowManager mWms;
48     private final WindowTokenClient mToken;
49     private boolean mOwnsToken;
50 
51     /**
52      * Default constructor. Will generate a {@link WindowTokenClient} and attach this context to
53      * the token.
54      *
55      * @param base Base {@link Context} for this new instance.
56      * @param type Window type to be used with this context.
57      * @hide
58      */
WindowContext(@onNull Context base, int type, @Nullable Bundle options)59     public WindowContext(@NonNull Context base, int type, @Nullable Bundle options) {
60         // Correct base context will be built once the token is resolved, so passing 'null' here.
61         super(null /* base */);
62 
63         mWms = WindowManagerGlobal.getWindowManagerService();
64         mToken = new WindowTokenClient();
65 
66         final ContextImpl contextImpl = createBaseWindowContext(base, mToken);
67         attachBaseContext(contextImpl);
68         contextImpl.setOuterContext(this);
69 
70         mToken.attachContext(this);
71 
72         mWindowManager = new WindowManagerImpl(this);
73         mWindowManager.setDefaultToken(mToken);
74 
75         int result;
76         try {
77             // Register the token with WindowManager. This will also call back with the current
78             // config back to the client.
79             result = mWms.addWindowTokenWithOptions(
80                     mToken, type, getDisplayId(), options, getPackageName());
81         }  catch (RemoteException e) {
82             mOwnsToken = false;
83             throw e.rethrowFromSystemServer();
84         }
85         if (result == ADD_TOO_MANY_TOKENS) {
86             throw new UnsupportedOperationException("createWindowContext failed! Too many unused "
87                     + "window contexts. Please see Context#createWindowContext documentation for "
88                     + "detail.");
89         }
90         mOwnsToken = result == ADD_OKAY;
91         Reference.reachabilityFence(this);
92     }
93 
createBaseWindowContext(Context outer, IBinder token)94     private static ContextImpl createBaseWindowContext(Context outer, IBinder token) {
95         final ContextImpl contextImpl = ContextImpl.getImpl(outer);
96         return contextImpl.createBaseWindowContext(token);
97     }
98 
99     @Override
getSystemService(String name)100     public Object getSystemService(String name) {
101         if (WINDOW_SERVICE.equals(name)) {
102             return mWindowManager;
103         }
104         return super.getSystemService(name);
105     }
106 
107     @Override
finalize()108     protected void finalize() throws Throwable {
109         release();
110         super.finalize();
111     }
112 
113     /** Used for test to invoke because we can't invoke finalize directly. */
114     @VisibleForTesting
release()115     public void release() {
116         if (mOwnsToken) {
117             try {
118                 mWms.removeWindowToken(mToken, getDisplayId());
119                 mOwnsToken = false;
120             } catch (RemoteException e) {
121                 throw e.rethrowFromSystemServer();
122             }
123         }
124         destroy();
125     }
126 
destroy()127     void destroy() {
128         final ContextImpl impl = (ContextImpl) getBaseContext();
129         impl.scheduleFinalCleanup(getClass().getName(), "WindowContext");
130         Reference.reachabilityFence(this);
131     }
132 }
133