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 com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 20 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 21 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 22 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; 23 import static com.android.server.wm.AppWindowThumbnailProto.HEIGHT; 24 import static com.android.server.wm.AppWindowThumbnailProto.SURFACE_ANIMATOR; 25 import static com.android.server.wm.AppWindowThumbnailProto.WIDTH; 26 27 import android.graphics.GraphicBuffer; 28 import android.graphics.PixelFormat; 29 import android.graphics.Point; 30 import android.os.Binder; 31 import android.util.Slog; 32 import android.util.proto.ProtoOutputStream; 33 import android.view.Surface; 34 import android.view.SurfaceControl; 35 import android.view.SurfaceControl.Builder; 36 import android.view.SurfaceControl.Transaction; 37 import android.view.animation.Animation; 38 39 import com.android.server.wm.SurfaceAnimator.Animatable; 40 41 /** 42 * Represents a surface that is displayed over an {@link AppWindowToken} 43 */ 44 class AppWindowThumbnail implements Animatable { 45 46 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowThumbnail" : TAG_WM; 47 48 private final AppWindowToken mAppToken; 49 private final SurfaceControl mSurfaceControl; 50 private final SurfaceAnimator mSurfaceAnimator; 51 private final int mWidth; 52 private final int mHeight; 53 AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader)54 AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader) { 55 mAppToken = appToken; 56 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, appToken.mService); 57 mWidth = thumbnailHeader.getWidth(); 58 mHeight = thumbnailHeader.getHeight(); 59 60 // Create a new surface for the thumbnail 61 WindowState window = appToken.findMainWindow(); 62 63 // TODO: This should be attached as a child to the app token, once the thumbnail animations 64 // use relative coordinates. Once we start animating task we can also consider attaching 65 // this to the task. 66 mSurfaceControl = appToken.makeSurface() 67 .setName("thumbnail anim: " + appToken.toString()) 68 .setSize(mWidth, mHeight) 69 .setFormat(PixelFormat.TRANSLUCENT) 70 .setMetadata(appToken.windowType, 71 window != null ? window.mOwnerUid : Binder.getCallingUid()) 72 .build(); 73 74 if (SHOW_TRANSACTIONS) { 75 Slog.i(TAG, " THUMBNAIL " + mSurfaceControl + ": CREATE"); 76 } 77 78 // Transfer the thumbnail to the surface 79 Surface drawSurface = new Surface(); 80 drawSurface.copyFrom(mSurfaceControl); 81 drawSurface.attachAndQueueBuffer(thumbnailHeader); 82 drawSurface.release(); 83 t.show(mSurfaceControl); 84 85 // We parent the thumbnail to the task, and just place it on top of anything else in the 86 // task. 87 t.setLayer(mSurfaceControl, Integer.MAX_VALUE); 88 } 89 startAnimation(Transaction t, Animation anim)90 void startAnimation(Transaction t, Animation anim) { 91 startAnimation(t, anim, null /* position */); 92 } 93 startAnimation(Transaction t, Animation anim, Point position)94 void startAnimation(Transaction t, Animation anim, Point position) { 95 anim.restrictDuration(MAX_ANIMATION_DURATION); 96 anim.scaleCurrentDuration(mAppToken.mService.getTransitionAnimationScaleLocked()); 97 mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter( 98 new WindowAnimationSpec(anim, position, 99 mAppToken.mService.mAppTransition.canSkipFirstFrame()), 100 mAppToken.mService.mSurfaceAnimationRunner), false /* hidden */); 101 } 102 onAnimationFinished()103 private void onAnimationFinished() { 104 } 105 setShowing(Transaction pendingTransaction, boolean show)106 void setShowing(Transaction pendingTransaction, boolean show) { 107 // TODO: Not needed anymore once thumbnail is attached to the app. 108 if (show) { 109 pendingTransaction.show(mSurfaceControl); 110 } else { 111 pendingTransaction.hide(mSurfaceControl); 112 } 113 } 114 destroy()115 void destroy() { 116 mSurfaceAnimator.cancelAnimation(); 117 mSurfaceControl.destroy(); 118 } 119 120 /** 121 * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link 122 * com.android.server.wm.AppWindowThumbnailProto}. 123 * 124 * @param proto Stream to write the AppWindowThumbnail object to. 125 * @param fieldId Field Id of the AppWindowThumbnail as defined in the parent message. 126 * @hide 127 */ writeToProto(ProtoOutputStream proto, long fieldId)128 void writeToProto(ProtoOutputStream proto, long fieldId) { 129 final long token = proto.start(fieldId); 130 proto.write(WIDTH, mWidth); 131 proto.write(HEIGHT, mHeight); 132 mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR); 133 proto.end(token); 134 } 135 136 @Override getPendingTransaction()137 public Transaction getPendingTransaction() { 138 return mAppToken.getPendingTransaction(); 139 } 140 141 @Override commitPendingTransaction()142 public void commitPendingTransaction() { 143 mAppToken.commitPendingTransaction(); 144 } 145 146 @Override onAnimationLeashCreated(Transaction t, SurfaceControl leash)147 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) { 148 t.setLayer(leash, Integer.MAX_VALUE); 149 } 150 151 @Override onAnimationLeashDestroyed(Transaction t)152 public void onAnimationLeashDestroyed(Transaction t) { 153 154 // TODO: Once attached to app token, we don't need to hide it immediately if thumbnail 155 // became visible. 156 t.hide(mSurfaceControl); 157 } 158 159 @Override makeAnimationLeash()160 public Builder makeAnimationLeash() { 161 return mAppToken.makeSurface(); 162 } 163 164 @Override getSurfaceControl()165 public SurfaceControl getSurfaceControl() { 166 return mSurfaceControl; 167 } 168 169 @Override getAnimationLeashParent()170 public SurfaceControl getAnimationLeashParent() { 171 return mAppToken.getAppAnimationLayer(); 172 } 173 174 @Override getParentSurfaceControl()175 public SurfaceControl getParentSurfaceControl() { 176 return mAppToken.getParentSurfaceControl(); 177 } 178 179 @Override getSurfaceWidth()180 public int getSurfaceWidth() { 181 return mWidth; 182 } 183 184 @Override getSurfaceHeight()185 public int getSurfaceHeight() { 186 return mHeight; 187 } 188 } 189