• 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.window;
17 
18 import android.annotation.NonNull;
19 import android.app.ActivityThread;
20 import android.app.IWindowToken;
21 import android.app.ResourcesManager;
22 import android.content.Context;
23 import android.content.res.Configuration;
24 import android.os.Bundle;
25 import android.os.IBinder;
26 
27 import java.lang.ref.WeakReference;
28 
29 /**
30  * This class is used to receive {@link Configuration} changes from the associated window manager
31  * node on the server side, and apply the change to the {@link Context#getResources() associated
32  * Resources} of the attached {@link Context}. It is also used as
33  * {@link Context#getWindowContextToken() the token of non-Activity UI Contexts}.
34  *
35  * @see WindowContext
36  * @see android.view.IWindowManager#registerWindowContextListener(IBinder, int, int, Bundle)
37  *
38  * @hide
39  */
40 public class WindowTokenClient extends IWindowToken.Stub {
41     /**
42      * Attached {@link Context} for this window token to update configuration and resources.
43      * Initialized by {@link #attachContext(Context)}.
44      */
45     private WeakReference<Context> mContextRef = null;
46 
47     private final ResourcesManager mResourcesManager = ResourcesManager.getInstance();
48 
49     /**
50      * Attaches {@code context} to this {@link WindowTokenClient}. Each {@link WindowTokenClient}
51      * can only attach one {@link Context}.
52      * <p>This method must be called before invoking
53      * {@link android.view.IWindowManager#registerWindowContextListener(IBinder, int, int,
54      * Bundle, boolean)}.<p/>
55      *
56      * @param context context to be attached
57      * @throws IllegalStateException if attached context has already existed.
58      */
attachContext(@onNull Context context)59     public void attachContext(@NonNull Context context) {
60         if (mContextRef != null) {
61             throw new IllegalStateException("Context is already attached.");
62         }
63         mContextRef = new WeakReference<>(context);
64     }
65 
66     @Override
onConfigurationChanged(Configuration newConfig, int newDisplayId)67     public void onConfigurationChanged(Configuration newConfig, int newDisplayId) {
68         final Context context = mContextRef.get();
69         if (context == null) {
70             return;
71         }
72         final int currentDisplayId = context.getDisplayId();
73         final boolean displayChanged = newDisplayId != currentDisplayId;
74         final Configuration config = context.getResources().getConfiguration();
75         final boolean configChanged = config.diff(newConfig) != 0;
76         if (displayChanged || configChanged) {
77             // TODO(ag/9789103): update resource manager logic to track non-activity tokens
78             mResourcesManager.updateResourcesForActivity(this, newConfig, newDisplayId);
79             if (context instanceof WindowContext) {
80                 ActivityThread.currentActivityThread().getHandler().post(
81                         () -> ((WindowContext) context).dispatchConfigurationChanged(newConfig));
82             }
83         }
84         if (displayChanged) {
85             context.updateDisplay(newDisplayId);
86         }
87     }
88 
89     @Override
onWindowTokenRemoved()90     public void onWindowTokenRemoved() {
91         final Context context = mContextRef.get();
92         if (context != null) {
93             context.destroy();
94             mContextRef.clear();
95         }
96     }
97 }
98