• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.server.wm;
18 
19 import static android.view.SurfaceControl.METADATA_OWNER_UID;
20 import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;
21 
22 import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
23 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
24 import static com.android.server.wm.WindowContainerThumbnailProto.HEIGHT;
25 import static com.android.server.wm.WindowContainerThumbnailProto.SURFACE_ANIMATOR;
26 import static com.android.server.wm.WindowContainerThumbnailProto.WIDTH;
27 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
28 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
29 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
30 
31 import android.graphics.GraphicBuffer;
32 import android.graphics.PixelFormat;
33 import android.graphics.Point;
34 import android.os.Process;
35 import android.util.proto.ProtoOutputStream;
36 import android.view.Surface;
37 import android.view.SurfaceControl;
38 import android.view.SurfaceControl.Builder;
39 import android.view.SurfaceControl.Transaction;
40 import android.view.animation.Animation;
41 
42 import com.android.server.protolog.common.ProtoLog;
43 import com.android.server.wm.SurfaceAnimator.Animatable;
44 import com.android.server.wm.SurfaceAnimator.AnimationType;
45 
46 import java.util.function.Supplier;
47 
48 /**
49  * Represents a surface that is displayed over a subclass of {@link WindowContainer}
50  */
51 class 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 
WindowContainerThumbnail(Supplier<Surface> surfaceFactory, Transaction t, WindowContainer container, GraphicBuffer thumbnailHeader)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      */
WindowContainerThumbnail(Supplier<Surface> surfaceFactory, Transaction t, WindowContainer container, GraphicBuffer thumbnailHeader, boolean relative)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 
WindowContainerThumbnail(Transaction t, WindowContainer container, GraphicBuffer thumbnailHeader, boolean relative, Surface drawSurface, SurfaceAnimator animator)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                 .setCallsite("WindowContainerThumbnail")
107                 .build();
108 
109         ProtoLog.i(WM_SHOW_TRANSACTIONS, "  THUMBNAIL %s: CREATE", mSurfaceControl);
110 
111         // Transfer the thumbnail to the surface
112         drawSurface.copyFrom(mSurfaceControl);
113         drawSurface.attachAndQueueBuffer(thumbnailHeader);
114         drawSurface.release();
115         t.show(mSurfaceControl);
116 
117         // We parent the thumbnail to the container, and just place it on top of anything else in
118         // the container.
119         t.setLayer(mSurfaceControl, Integer.MAX_VALUE);
120         if (relative) {
121             t.reparent(mSurfaceControl, mWindowContainer.getSurfaceControl());
122         }
123     }
124 
startAnimation(Transaction t, Animation anim)125     void startAnimation(Transaction t, Animation anim) {
126         startAnimation(t, anim, null /* position */);
127     }
128 
startAnimation(Transaction t, Animation anim, Point position)129     void startAnimation(Transaction t, Animation anim, Point position) {
130         anim.restrictDuration(MAX_ANIMATION_DURATION);
131         anim.scaleCurrentDuration(mWindowContainer.mWmService.getTransitionAnimationScaleLocked());
132         mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
133                 new WindowAnimationSpec(anim, position,
134                         mWindowContainer.getDisplayContent().mAppTransition.canSkipFirstFrame(),
135                         mWindowContainer.getDisplayContent().getWindowCornerRadius()),
136                 mWindowContainer.mWmService.mSurfaceAnimationRunner), false /* hidden */,
137                 ANIMATION_TYPE_RECENTS);
138     }
139 
140     /**
141      * Start animation with existing adapter.
142      */
startAnimation(Transaction t, AnimationAdapter anim, boolean hidden)143     void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
144         mSurfaceAnimator.startAnimation(t, anim, hidden, ANIMATION_TYPE_RECENTS);
145     }
146 
onAnimationFinished(@nimationType int type, AnimationAdapter anim)147     private void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
148     }
149 
setShowing(Transaction pendingTransaction, boolean show)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 
destroy()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      */
dumpDebug(ProtoOutputStream proto, long fieldId)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
getPendingTransaction()185     public Transaction getPendingTransaction() {
186         return mWindowContainer.getPendingTransaction();
187     }
188 
189     @Override
commitPendingTransaction()190     public void commitPendingTransaction() {
191         mWindowContainer.commitPendingTransaction();
192     }
193 
194     @Override
onAnimationLeashCreated(Transaction t, SurfaceControl leash)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
onAnimationLeashLost(Transaction t)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
makeAnimationLeash()211     public Builder makeAnimationLeash() {
212         return mWindowContainer.makeChildSurface(mWindowContainer.getTopChild());
213     }
214 
215     @Override
getSurfaceControl()216     public SurfaceControl getSurfaceControl() {
217         return mSurfaceControl;
218     }
219 
220     @Override
getAnimationLeashParent()221     public SurfaceControl getAnimationLeashParent() {
222         return mWindowContainer.getAnimationLeashParent();
223     }
224 
225     @Override
getParentSurfaceControl()226     public SurfaceControl getParentSurfaceControl() {
227         return mWindowContainer.getParentSurfaceControl();
228     }
229 
230     @Override
getSurfaceWidth()231     public int getSurfaceWidth() {
232         return mWidth;
233     }
234 
235     @Override
getSurfaceHeight()236     public int getSurfaceHeight() {
237         return mHeight;
238     }
239 }
240