blob: bbbf11d2a7a28052e6ee5b9affbcb7ddcd825248 [file] [log] [blame]
Jorim Jaggi988f6682017-11-17 17:46:43 +01001/*
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
Evan Rosky485df202018-12-06 14:11:12 -080019import static android.view.SurfaceControl.METADATA_OWNER_UID;
20import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;
21
Vishnu Naire86bd982018-11-28 13:23:17 -080022import static com.android.server.wm.AppWindowThumbnailProto.HEIGHT;
23import static com.android.server.wm.AppWindowThumbnailProto.SURFACE_ANIMATOR;
24import static com.android.server.wm.AppWindowThumbnailProto.WIDTH;
Jorim Jaggi988f6682017-11-17 17:46:43 +010025import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
26import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
27import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
28import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
29
30import android.graphics.GraphicBuffer;
31import android.graphics.PixelFormat;
32import android.graphics.Point;
33import android.os.Binder;
34import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080035import android.util.proto.ProtoOutputStream;
Jorim Jaggi988f6682017-11-17 17:46:43 +010036import 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.wm.SurfaceAnimator.Animatable;
43
44/**
45 * Represents a surface that is displayed over an {@link AppWindowToken}
46 */
47class AppWindowThumbnail implements Animatable {
48
49 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowThumbnail" : TAG_WM;
50
51 private final AppWindowToken mAppToken;
52 private final SurfaceControl mSurfaceControl;
53 private final SurfaceAnimator mSurfaceAnimator;
54 private final int mWidth;
55 private final int mHeight;
Evan Rosky2289ba12018-11-19 18:28:18 -080056 private final boolean mRelative;
Jorim Jaggi988f6682017-11-17 17:46:43 +010057
58 AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader) {
Evan Rosky2289ba12018-11-19 18:28:18 -080059 this(t, appToken, thumbnailHeader, false /* relative */);
60 }
61
62 /**
63 * @param t Transaction to create the thumbnail in.
64 * @param appToken {@link AppWindowToken} to associate this thumbnail with.
65 * @param thumbnailHeader A thumbnail or placeholder for thumbnail to initialize with.
66 * @param relative Whether this thumbnail will be a child of appToken (and thus positioned
67 * relative to it) or not.
68 */
69 AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader,
70 boolean relative) {
Jorim Jaggi988f6682017-11-17 17:46:43 +010071 mAppToken = appToken;
Evan Rosky2289ba12018-11-19 18:28:18 -080072 mRelative = relative;
Wale Ogunwale8b19de92018-11-29 19:58:26 -080073 mSurfaceAnimator =
74 new SurfaceAnimator(this, this::onAnimationFinished, appToken.mWmService);
Jorim Jaggi988f6682017-11-17 17:46:43 +010075 mWidth = thumbnailHeader.getWidth();
76 mHeight = thumbnailHeader.getHeight();
77
78 // Create a new surface for the thumbnail
79 WindowState window = appToken.findMainWindow();
80
81 // TODO: This should be attached as a child to the app token, once the thumbnail animations
82 // use relative coordinates. Once we start animating task we can also consider attaching
83 // this to the task.
84 mSurfaceControl = appToken.makeSurface()
85 .setName("thumbnail anim: " + appToken.toString())
Vishnu Naire86bd982018-11-28 13:23:17 -080086 .setBufferSize(mWidth, mHeight)
Jorim Jaggi988f6682017-11-17 17:46:43 +010087 .setFormat(PixelFormat.TRANSLUCENT)
Evan Rosky485df202018-12-06 14:11:12 -080088 .setMetadata(METADATA_WINDOW_TYPE, appToken.windowType)
89 .setMetadata(METADATA_OWNER_UID,
Jorim Jaggi988f6682017-11-17 17:46:43 +010090 window != null ? window.mOwnerUid : Binder.getCallingUid())
91 .build();
92
93 if (SHOW_TRANSACTIONS) {
94 Slog.i(TAG, " THUMBNAIL " + mSurfaceControl + ": CREATE");
95 }
96
97 // Transfer the thumbnail to the surface
98 Surface drawSurface = new Surface();
99 drawSurface.copyFrom(mSurfaceControl);
100 drawSurface.attachAndQueueBuffer(thumbnailHeader);
101 drawSurface.release();
102 t.show(mSurfaceControl);
103
104 // We parent the thumbnail to the task, and just place it on top of anything else in the
105 // task.
106 t.setLayer(mSurfaceControl, Integer.MAX_VALUE);
Evan Rosky2289ba12018-11-19 18:28:18 -0800107 if (relative) {
108 t.reparent(mSurfaceControl, appToken.getSurfaceControl());
109 }
Jorim Jaggi988f6682017-11-17 17:46:43 +0100110 }
111
112 void startAnimation(Transaction t, Animation anim) {
Tony Mak64b8d562017-12-28 17:44:02 +0000113 startAnimation(t, anim, null /* position */);
114 }
115
116 void startAnimation(Transaction t, Animation anim, Point position) {
Jorim Jaggi988f6682017-11-17 17:46:43 +0100117 anim.restrictDuration(MAX_ANIMATION_DURATION);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800118 anim.scaleCurrentDuration(mAppToken.mWmService.getTransitionAnimationScaleLocked());
chaviw23012112017-12-20 15:29:04 -0800119 mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
Tony Mak64b8d562017-12-28 17:44:02 +0000120 new WindowAnimationSpec(anim, position,
Lucas Dupin3e1dc202018-12-02 15:14:20 -0800121 mAppToken.getDisplayContent().mAppTransition.canSkipFirstFrame(),
122 mAppToken.mWmService.mWindowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800123 mAppToken.mWmService.mSurfaceAnimationRunner), false /* hidden */);
Jorim Jaggi988f6682017-11-17 17:46:43 +0100124 }
125
Evan Rosky2289ba12018-11-19 18:28:18 -0800126 /**
127 * Start animation with existing adapter.
128 */
129 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
130 mSurfaceAnimator.startAnimation(t, anim, hidden);
131 }
132
Jorim Jaggi988f6682017-11-17 17:46:43 +0100133 private void onAnimationFinished() {
134 }
135
136 void setShowing(Transaction pendingTransaction, boolean show) {
Jorim Jaggi2e3c31d2017-11-20 19:49:00 +0100137 // TODO: Not needed anymore once thumbnail is attached to the app.
Jorim Jaggi988f6682017-11-17 17:46:43 +0100138 if (show) {
139 pendingTransaction.show(mSurfaceControl);
140 } else {
141 pendingTransaction.hide(mSurfaceControl);
142 }
143 }
144
145 void destroy() {
146 mSurfaceAnimator.cancelAnimation();
Evan Rosky25b56192019-02-06 16:10:56 -0800147 getPendingTransaction().remove(mSurfaceControl);
Jorim Jaggi988f6682017-11-17 17:46:43 +0100148 }
149
Vishnu Nair04ab4392018-01-10 11:00:06 -0800150 /**
151 * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
Yi Jin6c6e9ca2018-03-20 16:53:35 -0700152 * com.android.server.wm.AppWindowThumbnailProto}.
Vishnu Nair04ab4392018-01-10 11:00:06 -0800153 *
154 * @param proto Stream to write the AppWindowThumbnail object to.
155 * @param fieldId Field Id of the AppWindowThumbnail as defined in the parent message.
156 * @hide
157 */
158 void writeToProto(ProtoOutputStream proto, long fieldId) {
159 final long token = proto.start(fieldId);
160 proto.write(WIDTH, mWidth);
161 proto.write(HEIGHT, mHeight);
Nataniel Borges023ecb52019-01-16 14:15:43 -0800162 if (mSurfaceAnimator.isAnimating()) {
163 mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR);
164 }
Vishnu Nair04ab4392018-01-10 11:00:06 -0800165 proto.end(token);
166 }
167
Jorim Jaggi988f6682017-11-17 17:46:43 +0100168 @Override
169 public Transaction getPendingTransaction() {
170 return mAppToken.getPendingTransaction();
171 }
172
173 @Override
174 public void commitPendingTransaction() {
175 mAppToken.commitPendingTransaction();
176 }
177
178 @Override
Jorim Jaggi988f6682017-11-17 17:46:43 +0100179 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
180 t.setLayer(leash, Integer.MAX_VALUE);
Evan Rosky2289ba12018-11-19 18:28:18 -0800181 if (mRelative) {
182 t.reparent(leash, mAppToken.getSurfaceControl());
183 }
Jorim Jaggi988f6682017-11-17 17:46:43 +0100184 }
185
186 @Override
187 public void onAnimationLeashDestroyed(Transaction t) {
Jorim Jaggi2e3c31d2017-11-20 19:49:00 +0100188
189 // TODO: Once attached to app token, we don't need to hide it immediately if thumbnail
190 // became visible.
Jorim Jaggi988f6682017-11-17 17:46:43 +0100191 t.hide(mSurfaceControl);
192 }
193
194 @Override
195 public Builder makeAnimationLeash() {
Jorim Jaggi596a1992017-12-29 14:48:02 +0100196 return mAppToken.makeSurface();
Jorim Jaggi988f6682017-11-17 17:46:43 +0100197 }
198
199 @Override
200 public SurfaceControl getSurfaceControl() {
201 return mSurfaceControl;
202 }
203
204 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +0100205 public SurfaceControl getAnimationLeashParent() {
206 return mAppToken.getAppAnimationLayer();
207 }
208
209 @Override
Jorim Jaggi988f6682017-11-17 17:46:43 +0100210 public SurfaceControl getParentSurfaceControl() {
211 return mAppToken.getParentSurfaceControl();
212 }
213
214 @Override
215 public int getSurfaceWidth() {
216 return mWidth;
217 }
218
219 @Override
220 public int getSurfaceHeight() {
221 return mHeight;
222 }
223}