• Home
  • History
  • Annotate
  • 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 android.window;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.content.Context;
22 import android.os.Bundle;
23 import android.os.IBinder;
24 import android.os.RemoteException;
25 import android.view.IWindowManager;
26 import android.view.WindowManager.LayoutParams.WindowType;
27 import android.view.WindowManagerGlobal;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 
31 /**
32  * The controller to manage {@link WindowContext}, such as attaching to a window manager node or
33  * detaching from the current attached node. The user must call
34  * {@link #attachToDisplayArea(int, int, Bundle)}, call {@link #attachToWindowToken(IBinder)}
35  * after that if necessary, and then call {@link #detachIfNeeded()} for release.
36  *
37  * @hide
38  */
39 public class WindowContextController {
40     private final IWindowManager mWms;
41     /**
42      * {@code true} to indicate that the {@code mToken} is associated with a
43      * {@link com.android.server.wm.DisplayArea}. Note that {@code mToken} is able to attach a
44      * WindowToken after this flag sets to {@code true}.
45      */
46     @VisibleForTesting
47     public boolean mAttachedToDisplayArea;
48     @NonNull
49     private final IBinder mToken;
50 
51     /**
52      * Window Context Controller constructor
53      *
54      * @param token The token used to attach to a window manager node. It is usually from
55      *              {@link Context#getWindowContextToken()}.
56      */
57     public WindowContextController(@NonNull IBinder token) {
58         mToken = token;
59         mWms = WindowManagerGlobal.getWindowManagerService();
60     }
61 
62     /** Used for test only. DO NOT USE it in production code. */
63     @VisibleForTesting
64     public WindowContextController(@NonNull IBinder token, IWindowManager mockWms) {
65         mToken = token;
66         mWms = mockWms;
67     }
68 
69     /**
70      * Attaches the {@code mToken} to a {@link com.android.server.wm.DisplayArea}.
71      *
72      * @param type The window type of the {@link WindowContext}
73      * @param displayId The {@link Context#getDisplayId() ID of display} to associate with
74      * @param options The window context launched option
75      * @throws IllegalStateException if the {@code mToken} has already been attached to a
76      * DisplayArea.
77      */
78     public void attachToDisplayArea(@WindowType int type, int displayId, @Nullable Bundle options) {
79         if (mAttachedToDisplayArea) {
80             throw new IllegalStateException("A Window Context can be only attached to "
81                     + "a DisplayArea once.");
82         }
83         try {
84             mAttachedToDisplayArea = mWms.attachWindowContextToDisplayArea(mToken, type, displayId,
85                     options);
86         }  catch (RemoteException e) {
87             throw e.rethrowFromSystemServer();
88         }
89     }
90 
91     /**
92      * Switches to attach the window context to a window token.
93      * <p>
94      * Note that the context should have been attached to a
95      * {@link com.android.server.wm.DisplayArea} by {@link #attachToDisplayArea(int, int, Bundle)}
96      * before attaching to a window token, and the window token's type must match the window
97      * context's type.
98      * </p><p>
99      * A {@link WindowContext} can only attach to a specific window manager node, which is either a
100      * {@link com.android.server.wm.DisplayArea} by calling
101      * {@link #attachToDisplayArea(int, int, Bundle)} or the latest attached {@code windowToken}
102      * although this API is allowed to be called multiple times.
103      * </p>
104      * @throws IllegalStateException if the {@code mClientToken} has not yet attached to
105      * a {@link com.android.server.wm.DisplayArea} by
106      * {@link #attachToDisplayArea(int, int, Bundle)}.
107      *
108      * @see WindowProviderService#attachToWindowToken(IBinder))
109      * @see IWindowManager#attachWindowContextToWindowToken(IBinder, IBinder)
110      */
111     public void attachToWindowToken(IBinder windowToken) {
112         if (!mAttachedToDisplayArea) {
113             throw new IllegalStateException("The Window Context should have been attached"
114                     + " to a DisplayArea.");
115         }
116         try {
117             mWms.attachWindowContextToWindowToken(mToken, windowToken);
118         } catch (RemoteException e) {
119             throw e.rethrowFromSystemServer();
120         }
121     }
122 
123     /** Detaches the window context from the node it's currently associated with. */
124     public void detachIfNeeded() {
125         if (mAttachedToDisplayArea) {
126             try {
127                 mWms.detachWindowContextFromWindowContainer(mToken);
128                 mAttachedToDisplayArea = false;
129             } catch (RemoteException e) {
130                 throw e.rethrowFromSystemServer();
131             }
132         }
133     }
134 }
135