1 /*
2  * Copyright (C) 2019 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 package com.android.server.wm;
17 
18 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
19 import static com.android.server.wm.AnimationAdapterProto.REMOTE;
20 import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
21 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
22 
23 import android.annotation.NonNull;
24 import android.graphics.Point;
25 import android.os.SystemClock;
26 import android.util.proto.ProtoOutputStream;
27 import android.view.RemoteAnimationTarget;
28 import android.view.SurfaceControl;
29 
30 import com.android.internal.protolog.common.ProtoLog;
31 import com.android.server.wm.SurfaceAnimator.AnimationType;
32 
33 import java.io.PrintWriter;
34 import java.util.ArrayList;
35 import java.util.function.Consumer;
36 
37 /**
38  * An animation adapter for wallpaper windows.
39  */
40 class WallpaperAnimationAdapter implements AnimationAdapter {
41     private static final String TAG = "WallpaperAnimationAdapter";
42 
43     private final WallpaperWindowToken mWallpaperToken;
44     private SurfaceControl mCapturedLeash;
45     private SurfaceAnimator.OnAnimationFinishedCallback mCapturedLeashFinishCallback;
46     private @AnimationType int mLastAnimationType;
47 
48     private long mDurationHint;
49     private long mStatusBarTransitionDelay;
50 
51     private Consumer<WallpaperAnimationAdapter> mAnimationCanceledRunnable;
52     private RemoteAnimationTarget mTarget;
53 
WallpaperAnimationAdapter(WallpaperWindowToken wallpaperToken, long durationHint, long statusBarTransitionDelay, Consumer<WallpaperAnimationAdapter> animationCanceledRunnable)54     WallpaperAnimationAdapter(WallpaperWindowToken wallpaperToken,
55             long durationHint, long statusBarTransitionDelay,
56             Consumer<WallpaperAnimationAdapter> animationCanceledRunnable) {
57         mWallpaperToken = wallpaperToken;
58         mDurationHint = durationHint;
59         mStatusBarTransitionDelay = statusBarTransitionDelay;
60         mAnimationCanceledRunnable = animationCanceledRunnable;
61     }
62 
63     /**
64      * Creates and starts remote animations for all the visible wallpaper windows.
65      *
66      * @return RemoteAnimationTarget[] targets for all the visible wallpaper windows
67      */
startWallpaperAnimations(DisplayContent displayContent, long durationHint, long statusBarTransitionDelay, Consumer<WallpaperAnimationAdapter> animationCanceledRunnable, ArrayList<WallpaperAnimationAdapter> adaptersOut)68     public static RemoteAnimationTarget[] startWallpaperAnimations(DisplayContent displayContent,
69             long durationHint, long statusBarTransitionDelay,
70             Consumer<WallpaperAnimationAdapter> animationCanceledRunnable,
71             ArrayList<WallpaperAnimationAdapter> adaptersOut) {
72         if (!shouldStartWallpaperAnimation(displayContent)) {
73             ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS,
74                     "\tWallpaper of display=%s is not visible", displayContent);
75             return new RemoteAnimationTarget[0];
76         }
77         final ArrayList<RemoteAnimationTarget> targets = new ArrayList<>();
78         displayContent.forAllWallpaperWindows(wallpaperWindow -> {
79             final WallpaperAnimationAdapter wallpaperAdapter = new WallpaperAnimationAdapter(
80                     wallpaperWindow, durationHint, statusBarTransitionDelay,
81                     animationCanceledRunnable);
82             wallpaperWindow.startAnimation(wallpaperWindow.getPendingTransaction(),
83                     wallpaperAdapter, false /* hidden */, ANIMATION_TYPE_WINDOW_ANIMATION);
84             targets.add(wallpaperAdapter.createRemoteAnimationTarget());
85             adaptersOut.add(wallpaperAdapter);
86         });
87         return targets.toArray(new RemoteAnimationTarget[targets.size()]);
88     }
89 
shouldStartWallpaperAnimation(DisplayContent displayContent)90     static boolean shouldStartWallpaperAnimation(DisplayContent displayContent) {
91         return displayContent.mWallpaperController.isWallpaperVisible();
92     }
93 
94     /**
95      * Create a remote animation target for this animation adapter.
96      */
createRemoteAnimationTarget()97     RemoteAnimationTarget createRemoteAnimationTarget() {
98         mTarget = new RemoteAnimationTarget(-1, -1, getLeash(), false, null, null,
99                 mWallpaperToken.getPrefixOrderIndex(), new Point(), null, null,
100                 mWallpaperToken.getWindowConfiguration(), true, null, null, null, false);
101         return mTarget;
102     }
103 
104     /**
105      * @return the leash for this animation (only valid after the wallpaper window surface animation
106      * has started).
107      */
getLeash()108     SurfaceControl getLeash() {
109         return mCapturedLeash;
110     }
111 
112     /**
113      * @return the callback to call to clean up when the animation has finished.
114      */
getLeashFinishedCallback()115     SurfaceAnimator.OnAnimationFinishedCallback getLeashFinishedCallback() {
116         return mCapturedLeashFinishCallback;
117     }
118 
119     /**
120      * @return the type of animation.
121      */
getLastAnimationType()122     @AnimationType int getLastAnimationType() {
123         return mLastAnimationType;
124     }
125 
126     /**
127      * @return the wallpaper window
128      */
getToken()129     WallpaperWindowToken getToken() {
130         return mWallpaperToken;
131     }
132 
133     @Override
getShowWallpaper()134     public boolean getShowWallpaper() {
135         // Not used
136         return false;
137     }
138 
139     @Override
startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t, @AnimationType int type, @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback)140     public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t,
141             @AnimationType int type,
142             @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback) {
143         ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation");
144 
145         // Restore z-layering until client has a chance to modify it.
146         t.setLayer(animationLeash, mWallpaperToken.getPrefixOrderIndex());
147         mCapturedLeash = animationLeash;
148         mCapturedLeashFinishCallback = finishCallback;
149         mLastAnimationType = type;
150     }
151 
152     @Override
onAnimationCancelled(SurfaceControl animationLeash)153     public void onAnimationCancelled(SurfaceControl animationLeash) {
154         ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "onAnimationCancelled");
155         mAnimationCanceledRunnable.accept(this);
156     }
157 
158     @Override
getDurationHint()159     public long getDurationHint() {
160         return mDurationHint;
161     }
162 
163     @Override
getStatusBarTransitionsStartTime()164     public long getStatusBarTransitionsStartTime() {
165         return SystemClock.uptimeMillis() + mStatusBarTransitionDelay;
166     }
167 
168     @Override
dump(PrintWriter pw, String prefix)169     public void dump(PrintWriter pw, String prefix) {
170         pw.print(prefix);
171         pw.print("token=");
172         pw.println(mWallpaperToken);
173         if (mTarget != null) {
174             pw.print(prefix);
175             pw.println("Target:");
176             mTarget.dump(pw, prefix + "  ");
177         } else {
178             pw.print(prefix);
179             pw.println("Target: null");
180         }
181     }
182 
183     @Override
dumpDebug(ProtoOutputStream proto)184     public void dumpDebug(ProtoOutputStream proto) {
185         final long token = proto.start(REMOTE);
186         if (mTarget != null) {
187             mTarget.dumpDebug(proto, TARGET);
188         }
189         proto.end(token);
190     }
191 }
192