Home | History | Annotate | Download | only in wm
      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 
     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 
     90     void startAnimation(Transaction t, Animation anim) {
     91         startAnimation(t, anim, null /* position */);
     92     }
     93 
     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 
    103     private void onAnimationFinished() {
    104     }
    105 
    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 
    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      */
    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
    137     public Transaction getPendingTransaction() {
    138         return mAppToken.getPendingTransaction();
    139     }
    140 
    141     @Override
    142     public void commitPendingTransaction() {
    143         mAppToken.commitPendingTransaction();
    144     }
    145 
    146     @Override
    147     public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
    148         t.setLayer(leash, Integer.MAX_VALUE);
    149     }
    150 
    151     @Override
    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
    160     public Builder makeAnimationLeash() {
    161         return mAppToken.makeSurface();
    162     }
    163 
    164     @Override
    165     public SurfaceControl getSurfaceControl() {
    166         return mSurfaceControl;
    167     }
    168 
    169     @Override
    170     public SurfaceControl getAnimationLeashParent() {
    171         return mAppToken.getAppAnimationLayer();
    172     }
    173 
    174     @Override
    175     public SurfaceControl getParentSurfaceControl() {
    176         return mAppToken.getParentSurfaceControl();
    177     }
    178 
    179     @Override
    180     public int getSurfaceWidth() {
    181         return mWidth;
    182     }
    183 
    184     @Override
    185     public int getSurfaceHeight() {
    186         return mHeight;
    187     }
    188 }
    189