blob: a27a1125977287cf14ce3467fc9608618769ef9f [file] [log] [blame]
Alan Viverette3da604b2020-06-10 18:34:39 +00001/*
2 * Copyright (C) 2017 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 com.android.server.wm;
18
19import static android.view.SurfaceControl.METADATA_OWNER_UID;
20import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;
21
22import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
23import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
24import static com.android.server.wm.WindowContainerThumbnailProto.HEIGHT;
25import static com.android.server.wm.WindowContainerThumbnailProto.SURFACE_ANIMATOR;
26import static com.android.server.wm.WindowContainerThumbnailProto.WIDTH;
27import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
28import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
29import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
30
31import android.graphics.GraphicBuffer;
32import android.graphics.PixelFormat;
33import android.graphics.Point;
34import android.os.Process;
35import android.util.proto.ProtoOutputStream;
36import android.view.Surface;
37import android.view.SurfaceControl;
38import android.view.SurfaceControl.Builder;
39import android.view.SurfaceControl.Transaction;
40import android.view.animation.Animation;
41
42import com.android.server.protolog.common.ProtoLog;
43import com.android.server.wm.SurfaceAnimator.Animatable;
44import com.android.server.wm.SurfaceAnimator.AnimationType;
45
46import java.util.function.Supplier;
47
48/**
49 * Represents a surface that is displayed over a subclass of {@link WindowContainer}
50 */
51class WindowContainerThumbnail implements Animatable {
52
53 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainerThumbnail" : TAG_WM;
54
55 private final WindowContainer mWindowContainer;
56 private SurfaceControl mSurfaceControl;
57 private final SurfaceAnimator mSurfaceAnimator;
58 private final int mWidth;
59 private final int mHeight;
60 private final boolean mRelative;
61
62 WindowContainerThumbnail(Supplier<Surface> surfaceFactory, Transaction t,
63 WindowContainer container, GraphicBuffer thumbnailHeader) {
64 this(surfaceFactory, t, container, thumbnailHeader, false /* relative */);
65 }
66
67 /**
68 * @param t Transaction to create the thumbnail in.
69 * @param container The sub-class of {@link WindowContainer} to associate this thumbnail with.
70 * @param thumbnailHeader A thumbnail or placeholder for thumbnail to initialize with.
71 * @param relative Whether this thumbnail will be a child of the container (and thus positioned
72 * relative to it) or not.
73 */
74 WindowContainerThumbnail(Supplier<Surface> surfaceFactory, Transaction t,
75 WindowContainer container, GraphicBuffer thumbnailHeader, boolean relative) {
76 this(t, container, thumbnailHeader, relative, surfaceFactory.get(), null);
77 }
78
79 WindowContainerThumbnail(Transaction t, WindowContainer container,
80 GraphicBuffer thumbnailHeader, boolean relative, Surface drawSurface,
81 SurfaceAnimator animator) {
82 mWindowContainer = container;
83 mRelative = relative;
84 if (animator != null) {
85 mSurfaceAnimator = animator;
86 } else {
87 // We can't use a delegating constructor since we need to
88 // reference this::onAnimationFinished
89 mSurfaceAnimator =
90 new SurfaceAnimator(this, this::onAnimationFinished /* animationFinishedCallback */,
91 container.mWmService);
92 }
93 mWidth = thumbnailHeader.getWidth();
94 mHeight = thumbnailHeader.getHeight();
95
96 // Create a new surface for the thumbnail
97 // TODO: This should be attached as a child to the app token, once the thumbnail animations
98 // use relative coordinates. Once we start animating task we can also consider attaching
99 // this to the task.
100 mSurfaceControl = mWindowContainer.makeChildSurface(mWindowContainer.getTopChild())
101 .setName("thumbnail anim: " + mWindowContainer.toString())
102 .setBufferSize(mWidth, mHeight)
103 .setFormat(PixelFormat.TRANSLUCENT)
104 .setMetadata(METADATA_WINDOW_TYPE, mWindowContainer.getWindowingMode())
105 .setMetadata(METADATA_OWNER_UID, Process.myUid())
106 .build();
107
108 ProtoLog.i(WM_SHOW_TRANSACTIONS, " THUMBNAIL %s: CREATE", mSurfaceControl);
109
110 // Transfer the thumbnail to the surface
111 drawSurface.copyFrom(mSurfaceControl);
112 drawSurface.attachAndQueueBuffer(thumbnailHeader);
113 drawSurface.release();
114 t.show(mSurfaceControl);
115
116 // We parent the thumbnail to the container, and just place it on top of anything else in
117 // the container.
118 t.setLayer(mSurfaceControl, Integer.MAX_VALUE);
119 if (relative) {
120 t.reparent(mSurfaceControl, mWindowContainer.getSurfaceControl());
121 }
122 }
123
124 void startAnimation(Transaction t, Animation anim) {
125 startAnimation(t, anim, null /* position */);
126 }
127
128 void startAnimation(Transaction t, Animation anim, Point position) {
129 anim.restrictDuration(MAX_ANIMATION_DURATION);
130 anim.scaleCurrentDuration(mWindowContainer.mWmService.getTransitionAnimationScaleLocked());
131 mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
132 new WindowAnimationSpec(anim, position,
133 mWindowContainer.getDisplayContent().mAppTransition.canSkipFirstFrame(),
134 mWindowContainer.getDisplayContent().getWindowCornerRadius()),
135 mWindowContainer.mWmService.mSurfaceAnimationRunner), false /* hidden */,
136 ANIMATION_TYPE_RECENTS, null /* animationFinishedCallback */);
137 }
138
139 /**
140 * Start animation with existing adapter.
141 */
142 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
143 mSurfaceAnimator.startAnimation(t, anim, hidden, ANIMATION_TYPE_RECENTS,
144 null /* animationFinishedCallback */);
145 }
146
147 private void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
148 }
149
150 void setShowing(Transaction pendingTransaction, boolean show) {
151 // TODO: Not needed anymore once thumbnail is attached to the app.
152 if (show) {
153 pendingTransaction.show(mSurfaceControl);
154 } else {
155 pendingTransaction.hide(mSurfaceControl);
156 }
157 }
158
159 void destroy() {
160 mSurfaceAnimator.cancelAnimation();
161 getPendingTransaction().remove(mSurfaceControl);
162 mSurfaceControl = null;
163 }
164
165 /**
166 * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
167 * com.android.server.wm.WindowContainerThumbnailProto}.
168 *
169 * @param proto Stream to write the WindowContainerThumbnailProto object to.
170 * @param fieldId Field Id of the WindowContainerThumbnailProto as defined in the parent
171 * message.
172 * @hide
173 */
174 void dumpDebug(ProtoOutputStream proto, long fieldId) {
175 final long token = proto.start(fieldId);
176 proto.write(WIDTH, mWidth);
177 proto.write(HEIGHT, mHeight);
178 if (mSurfaceAnimator.isAnimating()) {
179 mSurfaceAnimator.dumpDebug(proto, SURFACE_ANIMATOR);
180 }
181 proto.end(token);
182 }
183
184 @Override
185 public Transaction getPendingTransaction() {
186 return mWindowContainer.getPendingTransaction();
187 }
188
189 @Override
190 public void commitPendingTransaction() {
191 mWindowContainer.commitPendingTransaction();
192 }
193
194 @Override
195 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
196 t.setLayer(leash, Integer.MAX_VALUE);
197 if (mRelative) {
198 t.reparent(leash, mWindowContainer.getSurfaceControl());
199 }
200 }
201
202 @Override
203 public void onAnimationLeashLost(Transaction t) {
204
205 // TODO: Once attached to app token, we don't need to hide it immediately if thumbnail
206 // became visible.
207 t.hide(mSurfaceControl);
208 }
209
210 @Override
211 public Builder makeAnimationLeash() {
212 return mWindowContainer.makeChildSurface(mWindowContainer.getTopChild());
213 }
214
215 @Override
216 public SurfaceControl getSurfaceControl() {
217 return mSurfaceControl;
218 }
219
220 @Override
221 public SurfaceControl getAnimationLeashParent() {
222 return mWindowContainer.getAnimationLeashParent();
223 }
224
225 @Override
226 public SurfaceControl getParentSurfaceControl() {
227 return mWindowContainer.getParentSurfaceControl();
228 }
229
230 @Override
231 public int getSurfaceWidth() {
232 return mWidth;
233 }
234
235 @Override
236 public int getSurfaceHeight() {
237 return mHeight;
238 }
239}