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