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