• 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 
17 package android.view;
18 
19 import static android.view.InsetsController.DEBUG;
20 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CONTROLLED;
21 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
22 
23 import android.annotation.NonNull;
24 import android.content.res.CompatibilityInfo;
25 import android.os.Handler;
26 import android.os.IBinder;
27 import android.os.RemoteException;
28 import android.util.Log;
29 import android.view.inputmethod.InputMethodManager;
30 
31 import java.util.List;
32 
33 /**
34  * Implements {@link InsetsController.Host} for {@link ViewRootImpl}s.
35  * @hide
36  */
37 public class ViewRootInsetsControllerHost implements InsetsController.Host {
38 
39     private final String TAG = "VRInsetsControllerHost";
40 
41     private final ViewRootImpl mViewRoot;
42     private SyncRtSurfaceTransactionApplier mApplier;
43 
ViewRootInsetsControllerHost(ViewRootImpl viewRoot)44     public ViewRootInsetsControllerHost(ViewRootImpl viewRoot) {
45         mViewRoot = viewRoot;
46     }
47 
48     @Override
getHandler()49     public Handler getHandler() {
50         return mViewRoot.mHandler;
51     }
52 
53     @Override
notifyInsetsChanged()54     public void notifyInsetsChanged() {
55         mViewRoot.notifyInsetsChanged();
56     }
57 
58     @Override
addOnPreDrawRunnable(Runnable r)59     public void addOnPreDrawRunnable(Runnable r) {
60         if (mViewRoot.mView == null) {
61             return;
62         }
63         mViewRoot.mView.getViewTreeObserver().addOnPreDrawListener(
64                 new ViewTreeObserver.OnPreDrawListener() {
65                     @Override
66                     public boolean onPreDraw() {
67                         mViewRoot.mView.getViewTreeObserver().removeOnPreDrawListener(this);
68                         r.run();
69                         return true;
70                     }
71                 });
72         mViewRoot.mView.invalidate();
73     }
74 
75     @Override
dispatchWindowInsetsAnimationPrepare(@onNull WindowInsetsAnimation animation)76     public void dispatchWindowInsetsAnimationPrepare(@NonNull WindowInsetsAnimation animation) {
77         if (mViewRoot.mView == null) {
78             return;
79         }
80         mViewRoot.mView.dispatchWindowInsetsAnimationPrepare(animation);
81     }
82 
83     @Override
dispatchWindowInsetsAnimationStart( @onNull WindowInsetsAnimation animation, @NonNull WindowInsetsAnimation.Bounds bounds)84     public WindowInsetsAnimation.Bounds dispatchWindowInsetsAnimationStart(
85             @NonNull WindowInsetsAnimation animation,
86             @NonNull WindowInsetsAnimation.Bounds bounds) {
87         if (mViewRoot.mView == null) {
88             return null;
89         }
90         if (DEBUG) Log.d(TAG, "windowInsetsAnimation started");
91         return mViewRoot.mView.dispatchWindowInsetsAnimationStart(animation, bounds);
92     }
93 
94     @Override
dispatchWindowInsetsAnimationProgress(@onNull WindowInsets insets, @NonNull List<WindowInsetsAnimation> runningAnimations)95     public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
96             @NonNull List<WindowInsetsAnimation> runningAnimations) {
97         if (mViewRoot.mView == null) {
98             // The view has already detached from window.
99             return null;
100         }
101         if (DEBUG) {
102             for (WindowInsetsAnimation anim : runningAnimations) {
103                 Log.d(TAG, "windowInsetsAnimation progress: "
104                         + anim.getInterpolatedFraction());
105             }
106         }
107         return mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets, runningAnimations);
108     }
109 
110     @Override
dispatchWindowInsetsAnimationEnd(@onNull WindowInsetsAnimation animation)111     public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
112         if (DEBUG) Log.d(TAG, "windowInsetsAnimation ended");
113         if (mViewRoot.mView == null) {
114             // The view has already detached from window.
115             return;
116         }
117         mViewRoot.mView.dispatchWindowInsetsAnimationEnd(animation);
118     }
119 
120     @Override
applySurfaceParams(SyncRtSurfaceTransactionApplier.SurfaceParams... params)121     public void applySurfaceParams(SyncRtSurfaceTransactionApplier.SurfaceParams... params) {
122         if (mViewRoot.mView == null) {
123             throw new IllegalStateException("View of the ViewRootImpl is not initiated.");
124         }
125         if (mApplier == null) {
126             mApplier = new SyncRtSurfaceTransactionApplier(mViewRoot.mView);
127         }
128         if (mViewRoot.mView.isHardwareAccelerated()) {
129             mApplier.scheduleApply(params);
130         } else {
131             // Window doesn't support hardware acceleration, no synchronization for now.
132             // TODO(b/149342281): use mViewRoot.mSurface.getNextFrameNumber() to sync on every
133             //  frame instead.
134             final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
135             mApplier.applyParams(t, params);
136             mApplier.applyTransaction(t, -1);
137         }
138     }
139 
140     @Override
postInsetsAnimationCallback(Runnable r)141     public void postInsetsAnimationCallback(Runnable r) {
142         mViewRoot.mChoreographer.postCallback(Choreographer.CALLBACK_INSETS_ANIMATION, r,
143                 null /* token */);
144     }
145 
146     @Override
updateCompatSysUiVisibility(int type, boolean visible, boolean hasControl)147     public void updateCompatSysUiVisibility(int type, boolean visible, boolean hasControl) {
148         mViewRoot.updateCompatSysUiVisibility(type, visible, hasControl);
149     }
150 
151     @Override
onInsetsModified(InsetsState insetsState)152     public void onInsetsModified(InsetsState insetsState) {
153         try {
154             if (mViewRoot.mAdded) {
155                 mViewRoot.mWindowSession.insetsModified(mViewRoot.mWindow, insetsState);
156             }
157         } catch (RemoteException e) {
158             Log.e(TAG, "Failed to call insetsModified", e);
159         }
160     }
161 
162     @Override
hasAnimationCallbacks()163     public boolean hasAnimationCallbacks() {
164         if (mViewRoot.mView == null) {
165             return false;
166         }
167         return mViewRoot.mView.hasWindowInsetsAnimationCallback();
168     }
169 
170     @Override
setSystemBarsAppearance(int appearance, int mask)171     public void setSystemBarsAppearance(int appearance, int mask) {
172         mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_APPEARANCE_CONTROLLED;
173         final InsetsFlags insetsFlags = mViewRoot.mWindowAttributes.insetsFlags;
174         if (insetsFlags.appearance != appearance) {
175             insetsFlags.appearance = (insetsFlags.appearance & ~mask) | (appearance & mask);
176             mViewRoot.mWindowAttributesChanged = true;
177             mViewRoot.scheduleTraversals();
178         }
179     }
180 
181     @Override
getSystemBarsAppearance()182     public int getSystemBarsAppearance() {
183         return mViewRoot.mWindowAttributes.insetsFlags.appearance;
184     }
185 
186     @Override
isSystemBarsAppearanceControlled()187     public boolean isSystemBarsAppearanceControlled() {
188         return (mViewRoot.mWindowAttributes.privateFlags & PRIVATE_FLAG_APPEARANCE_CONTROLLED) != 0;
189     }
190 
191     @Override
setSystemBarsBehavior(int behavior)192     public void setSystemBarsBehavior(int behavior) {
193         mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
194         if (mViewRoot.mWindowAttributes.insetsFlags.behavior != behavior) {
195             mViewRoot.mWindowAttributes.insetsFlags.behavior = behavior;
196             mViewRoot.mWindowAttributesChanged = true;
197             mViewRoot.scheduleTraversals();
198         }
199     }
200 
201     @Override
getSystemBarsBehavior()202     public int getSystemBarsBehavior() {
203         return mViewRoot.mWindowAttributes.insetsFlags.behavior;
204     }
205 
206     @Override
isSystemBarsBehaviorControlled()207     public boolean isSystemBarsBehaviorControlled() {
208         return (mViewRoot.mWindowAttributes.privateFlags & PRIVATE_FLAG_BEHAVIOR_CONTROLLED) != 0;
209     }
210 
211     @Override
releaseSurfaceControlFromRt(SurfaceControl surfaceControl)212     public void releaseSurfaceControlFromRt(SurfaceControl surfaceControl) {
213 
214          // At the time we receive new leashes (e.g. InsetsSourceConsumer is processing
215          // setControl) we need to release the old leash. But we may have already scheduled
216          // a SyncRtSurfaceTransaction applier to use it from the RenderThread. To avoid
217          // synchronization issues we also release from the RenderThread so this release
218          // happens after any existing items on the work queue.
219 
220         if (mViewRoot.mView != null && mViewRoot.mView.isHardwareAccelerated()) {
221             mViewRoot.registerRtFrameCallback(frame -> {
222                 surfaceControl.release();
223             });
224             // Make sure a frame gets scheduled.
225             mViewRoot.mView.invalidate();
226         } else {
227             surfaceControl.release();
228         }
229     }
230 
231     @Override
getInputMethodManager()232     public InputMethodManager getInputMethodManager() {
233         return mViewRoot.mContext.getSystemService(InputMethodManager.class);
234     }
235 
236     @Override
getRootViewTitle()237     public String getRootViewTitle() {
238         if (mViewRoot == null) {
239             return null;
240         }
241         return mViewRoot.getTitle().toString();
242     }
243 
244     @Override
dipToPx(int dips)245     public int dipToPx(int dips) {
246         if (mViewRoot != null) {
247             return mViewRoot.dipToPx(dips);
248         }
249         return 0;
250     }
251 
252     @Override
getWindowToken()253     public IBinder getWindowToken() {
254         if (mViewRoot == null) {
255             return null;
256         }
257         final View view = mViewRoot.getView();
258         if (view == null) {
259             return null;
260         }
261         return view.getWindowToken();
262     }
263 
264     @Override
getTranslator()265     public CompatibilityInfo.Translator getTranslator() {
266         if (mViewRoot != null) {
267             return mViewRoot.mTranslator;
268         }
269         return null;
270     }
271 }
272