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 package com.android.systemui.shared.recents.view; 17 18 import android.app.ActivityOptions; 19 import android.app.ActivityOptions.OnAnimationStartedListener; 20 import android.content.Context; 21 import android.graphics.Bitmap; 22 import android.graphics.Canvas; 23 import android.graphics.GraphicBuffer; 24 import android.graphics.Picture; 25 import android.os.Bundle; 26 import android.os.Handler; 27 import android.os.IRemoteCallback; 28 import android.os.RemoteException; 29 import android.view.View; 30 31 import java.util.function.Consumer; 32 33 /** 34 * A helper class to create transitions to/from an App to Recents. 35 */ 36 public class RecentsTransition { 37 38 /** 39 * Creates a new transition aspect scaled transition activity options. 40 */ createAspectScaleAnimation(Context context, Handler handler, boolean scaleUp, AppTransitionAnimationSpecsFuture animationSpecsFuture, final Runnable animationStartCallback)41 public static ActivityOptions createAspectScaleAnimation(Context context, Handler handler, 42 boolean scaleUp, AppTransitionAnimationSpecsFuture animationSpecsFuture, 43 final Runnable animationStartCallback) { 44 final OnAnimationStartedListener animStartedListener = new OnAnimationStartedListener() { 45 private boolean mHandled; 46 47 @Override 48 public void onAnimationStarted() { 49 // OnAnimationStartedListener can be called numerous times, so debounce here to 50 // prevent multiple callbacks 51 if (mHandled) { 52 return; 53 } 54 mHandled = true; 55 56 if (animationStartCallback != null) { 57 animationStartCallback.run(); 58 } 59 } 60 }; 61 final ActivityOptions opts = ActivityOptions.makeMultiThumbFutureAspectScaleAnimation( 62 context, handler, 63 animationSpecsFuture != null ? animationSpecsFuture.getFuture() : null, 64 animStartedListener, scaleUp); 65 return opts; 66 } 67 68 /** 69 * Wraps a animation-start callback in a binder that can be called from window manager. 70 */ wrapStartedListener(final Handler handler, final Runnable animationStartCallback)71 public static IRemoteCallback wrapStartedListener(final Handler handler, 72 final Runnable animationStartCallback) { 73 if (animationStartCallback == null) { 74 return null; 75 } 76 return new IRemoteCallback.Stub() { 77 @Override 78 public void sendResult(Bundle data) throws RemoteException { 79 handler.post(animationStartCallback); 80 } 81 }; 82 } 83 84 /** 85 * @return a {@link GraphicBuffer} with the {@param view} drawn into it. Result can be null if 86 * we were unable to allocate a hardware bitmap. 87 */ 88 public static Bitmap drawViewIntoHardwareBitmap(int width, int height, final View view, 89 final float scale, final int eraseColor) { 90 return createHardwareBitmap(width, height, new Consumer<Canvas>() { 91 @Override 92 public void accept(Canvas c) { 93 c.scale(scale, scale); 94 if (eraseColor != 0) { 95 c.drawColor(eraseColor); 96 } 97 if (view != null) { 98 view.draw(c); 99 } 100 } 101 }); 102 } 103 104 /** 105 * @return a hardware {@link Bitmap} after being drawn with the {@param consumer}. Result can be 106 * null if we were unable to allocate a hardware bitmap. 107 */ 108 public static Bitmap createHardwareBitmap(int width, int height, Consumer<Canvas> consumer) { 109 final Picture picture = new Picture(); 110 final Canvas canvas = picture.beginRecording(width, height); 111 consumer.accept(canvas); 112 picture.endRecording(); 113 return Bitmap.createBitmap(picture); 114 } 115 } 116