Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64bac9f0 authored by Josh Tsuji's avatar Josh Tsuji Committed by Android (Google) Code Review
Browse files

Merge "ActivityView animations!"

parents 884ae809 750ba7b3
Loading
Loading
Loading
Loading
+0 −4
Original line number Original line Diff line number Diff line
@@ -1223,10 +1223,6 @@
    <dimen name="bubble_dismiss_slop">16dp</dimen>
    <dimen name="bubble_dismiss_slop">16dp</dimen>
    <!-- Height of button allowing users to adjust settings for bubbles. -->
    <!-- Height of button allowing users to adjust settings for bubbles. -->
    <dimen name="bubble_manage_button_height">48dp</dimen>
    <dimen name="bubble_manage_button_height">48dp</dimen>
    <!-- How far, horizontally, to animate the expanded view over when animating in/out. -->
    <dimen name="bubble_expanded_animate_x_distance">100dp</dimen>
    <!-- How far, vertically, to animate the expanded view over when animating in/out. -->
    <dimen name="bubble_expanded_animate_y_distance">500dp</dimen>
    <!-- Max width of the message bubble-->
    <!-- Max width of the message bubble-->
    <dimen name="bubble_message_max_width">144dp</dimen>
    <dimen name="bubble_message_max_width">144dp</dimen>
    <!-- Min width of the message bubble -->
    <!-- Min width of the message bubble -->
+103 −10
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.graphics.PixelFormat.TRANSPARENT;
import static android.graphics.PixelFormat.TRANSPARENT;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.ViewRootImpl.sNewInsetsMode;
import static android.view.ViewRootImpl.sNewInsetsMode;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
@@ -33,7 +34,6 @@ import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_EXPAND
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;


import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SuppressLint;
import android.app.ActivityOptions;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager;
@@ -46,6 +46,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.Point;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.ShapeDrawable;
@@ -55,12 +56,19 @@ import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Log;
import android.view.Gravity;
import android.view.Gravity;
import android.view.SurfaceControl;
import android.view.SurfaceView;
import android.view.View;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.WindowInsets;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.LinearLayout;


import androidx.annotation.Nullable;

import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.systemui.Dependency;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.R;
@@ -88,6 +96,7 @@ public class BubbleExpandedView extends LinearLayout {
    // The triangle pointing to the expanded view
    // The triangle pointing to the expanded view
    private View mPointerView;
    private View mPointerView;
    private int mPointerMargin;
    private int mPointerMargin;
    @Nullable private int[] mExpandedViewContainerLocation;


    private AlphaOptimizedButton mSettingsIcon;
    private AlphaOptimizedButton mSettingsIcon;


@@ -121,6 +130,16 @@ public class BubbleExpandedView extends LinearLayout {
    private View mVirtualImeView;
    private View mVirtualImeView;
    private WindowManager mVirtualDisplayWindowManager;
    private WindowManager mVirtualDisplayWindowManager;
    private boolean mImeShowing = false;
    private boolean mImeShowing = false;
    private float mCornerRadius = 0f;

    /**
     * Container for the ActivityView that has a solid, round-rect background that shows if the
     * ActivityView hasn't loaded.
     */
    private FrameLayout mActivityViewContainer = new FrameLayout(getContext());

    /** The SurfaceView that the ActivityView draws to. */
    @Nullable private SurfaceView mActivitySurface;


    private ActivityView.StateCallback mStateCallback = new ActivityView.StateCallback() {
    private ActivityView.StateCallback mStateCallback = new ActivityView.StateCallback() {
        @Override
        @Override
@@ -269,7 +288,28 @@ public class BubbleExpandedView extends LinearLayout {


        // Set ActivityView's alpha value as zero, since there is no view content to be shown.
        // Set ActivityView's alpha value as zero, since there is no view content to be shown.
        setContentVisibility(false);
        setContentVisibility(false);
        addView(mActivityView);

        mActivityViewContainer.setBackgroundColor(Color.WHITE);
        mActivityViewContainer.setOutlineProvider(new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), mCornerRadius);
            }
        });
        mActivityViewContainer.setClipToOutline(true);
        mActivityViewContainer.addView(mActivityView);
        mActivityViewContainer.setLayoutParams(
                new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
        addView(mActivityViewContainer);

        if (mActivityView != null
                && mActivityView.getChildCount() > 0
                && mActivityView.getChildAt(0) instanceof SurfaceView) {
            // Retrieve the surface from the ActivityView so we can screenshot it and change its
            // z-ordering. This should always be possible, since ActivityView's constructor adds the
            // SurfaceView as its first child.
            mActivitySurface = (SurfaceView) mActivityView.getChildAt(0);
        }


        // Expanded stack layout, top to bottom:
        // Expanded stack layout, top to bottom:
        // Expanded view container
        // Expanded view container
@@ -327,6 +367,40 @@ public class BubbleExpandedView extends LinearLayout {
        return mBubble != null ? mBubble.getKey() : "null";
        return mBubble != null ? mBubble.getKey() : "null";
    }
    }


    /**
     * Asks the ActivityView's surface to draw on top of all other views in the window. This is
     * useful for ordering surfaces during animations, but should otherwise be set to false so that
     * bubbles and menus can draw over the ActivityView.
     */
    void setSurfaceZOrderedOnTop(boolean onTop) {
        if (mActivitySurface == null) {
            return;
        }

        mActivitySurface.setZOrderedOnTop(onTop, true);
    }

    /** Return a GraphicBuffer with the contents of the ActivityView's underlying surface. */
    @Nullable
    SurfaceControl.ScreenshotHardwareBuffer snapshotActivitySurface() {
        if (mActivitySurface == null) {
            return null;
        }

        return SurfaceControl.captureLayers(
                mActivitySurface.getSurfaceControl(),
                new Rect(0, 0, mActivityView.getWidth(), mActivityView.getHeight()),
                1 /* scale */);
    }

    int[] getActivityViewLocationOnScreen() {
        if (mActivityView != null) {
            return mActivityView.getLocationOnScreen();
        } else {
            return new int[]{0, 0};
        }
    }

    void setManageClickListener(OnClickListener manageClickListener) {
    void setManageClickListener(OnClickListener manageClickListener) {
        findViewById(R.id.settings_button).setOnClickListener(manageClickListener);
        findViewById(R.id.settings_button).setOnClickListener(manageClickListener);
    }
    }
@@ -345,12 +419,12 @@ public class BubbleExpandedView extends LinearLayout {
    void applyThemeAttrs() {
    void applyThemeAttrs() {
        final TypedArray ta = mContext.obtainStyledAttributes(
        final TypedArray ta = mContext.obtainStyledAttributes(
                new int[] {android.R.attr.dialogCornerRadius});
                new int[] {android.R.attr.dialogCornerRadius});
        float cornerRadius = ta.getDimensionPixelSize(0, 0);
        mCornerRadius = ta.getDimensionPixelSize(0, 0);
        ta.recycle();
        ta.recycle();


        if (mActivityView != null && ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
        if (mActivityView != null && ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
                mContext.getResources())) {
                mContext.getResources())) {
            mActivityView.setCornerRadius(cornerRadius);
            mActivityView.setCornerRadius(mCornerRadius);
        }
        }
    }
    }


@@ -398,6 +472,7 @@ public class BubbleExpandedView extends LinearLayout {
        mPointerView.setAlpha(alpha);
        mPointerView.setAlpha(alpha);
        if (mActivityView != null) {
        if (mActivityView != null) {
            mActivityView.setAlpha(alpha);
            mActivityView.setAlpha(alpha);
            mActivityView.bringToFront();
        }
        }
    }
    }


@@ -557,6 +632,11 @@ public class BubbleExpandedView extends LinearLayout {
        if (DEBUG_BUBBLE_EXPANDED_VIEW) {
        if (DEBUG_BUBBLE_EXPANDED_VIEW) {
            Log.d(TAG, "updateHeight: bubble=" + getBubbleKey());
            Log.d(TAG, "updateHeight: bubble=" + getBubbleKey());
        }
        }

        if (mExpandedViewContainerLocation == null) {
            return;
        }

        if (usingActivityView()) {
        if (usingActivityView()) {
            float desiredHeight = mOverflowHeight;
            float desiredHeight = mOverflowHeight;
            if (!mIsOverflow) {
            if (!mIsOverflow) {
@@ -564,7 +644,7 @@ public class BubbleExpandedView extends LinearLayout {
            }
            }
            float height = Math.min(desiredHeight, getMaxExpandedHeight());
            float height = Math.min(desiredHeight, getMaxExpandedHeight());
            height = Math.max(height, mIsOverflow? mOverflowHeight : mMinHeight);
            height = Math.max(height, mIsOverflow? mOverflowHeight : mMinHeight);
            LayoutParams lp = (LayoutParams) mActivityView.getLayoutParams();
            ViewGroup.LayoutParams lp = mActivityView.getLayoutParams();
            mNeedsNewHeight = lp.height != height;
            mNeedsNewHeight = lp.height != height;
            if (!mKeyboardVisible) {
            if (!mKeyboardVisible) {
                // If the keyboard is visible... don't adjust the height because that will cause
                // If the keyboard is visible... don't adjust the height because that will cause
@@ -574,7 +654,8 @@ public class BubbleExpandedView extends LinearLayout {
                mNeedsNewHeight = false;
                mNeedsNewHeight = false;
            }
            }
            if (DEBUG_BUBBLE_EXPANDED_VIEW) {
            if (DEBUG_BUBBLE_EXPANDED_VIEW) {
                Log.d(TAG, "updateHeight: bubble=" + getBubbleKey() + " height=" + height
                Log.d(TAG, "updateHeight: bubble=" + getBubbleKey()
                        + " height=" + height
                        + " mNeedsNewHeight=" + mNeedsNewHeight);
                        + " mNeedsNewHeight=" + mNeedsNewHeight);
            }
            }
        }
        }
@@ -582,29 +663,41 @@ public class BubbleExpandedView extends LinearLayout {


    private int getMaxExpandedHeight() {
    private int getMaxExpandedHeight() {
        mWindowManager.getDefaultDisplay().getRealSize(mDisplaySize);
        mWindowManager.getDefaultDisplay().getRealSize(mDisplaySize);
        int[] windowLocation = mActivityView.getLocationOnScreen();
        int bottomInset = getRootWindowInsets() != null
        int bottomInset = getRootWindowInsets() != null
                ? getRootWindowInsets().getStableInsetBottom()
                ? getRootWindowInsets().getStableInsetBottom()
                : 0;
                : 0;
        return mDisplaySize.y - windowLocation[1] - mSettingsIconHeight - mPointerHeight

        return mDisplaySize.y
                - mExpandedViewContainerLocation[1]
                - getPaddingTop()
                - getPaddingBottom()
                - mSettingsIconHeight
                - mPointerHeight
                - mPointerMargin - bottomInset;
                - mPointerMargin - bottomInset;
    }
    }


    /**
    /**
     * Update appearance of the expanded view being displayed.
     * Update appearance of the expanded view being displayed.
     *
     * @param containerLocationOnScreen The location on-screen of the container the expanded view is
     *                                  added to. This allows us to calculate max height without
     *                                  waiting for layout.
     */
     */
    public void updateView() {
    public void updateView(int[] containerLocationOnScreen) {
        if (DEBUG_BUBBLE_EXPANDED_VIEW) {
        if (DEBUG_BUBBLE_EXPANDED_VIEW) {
            Log.d(TAG, "updateView: bubble="
            Log.d(TAG, "updateView: bubble="
                    + getBubbleKey());
                    + getBubbleKey());
        }
        }

        mExpandedViewContainerLocation = containerLocationOnScreen;

        if (usingActivityView()
        if (usingActivityView()
                && mActivityView.getVisibility() == VISIBLE
                && mActivityView.getVisibility() == VISIBLE
                && mActivityView.isAttachedToWindow()) {
                && mActivityView.isAttachedToWindow()) {
            mActivityView.onLocationChanged();
            mActivityView.onLocationChanged();
        }
            updateHeight();
            updateHeight();
        }
        }
    }


    /**
    /**
     * Set the x position that the tip of the triangle should point to.
     * Set the x position that the tip of the triangle should point to.
+372 −97

File changed.

Preview size limit exceeded, changes collapsed.

+137 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.systemui.bubbles.animation;

import android.graphics.Matrix;

import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.FloatPropertyCompat;

/**
 * Matrix whose scale properties can be animated using physics animations, via the {@link #SCALE_X}
 * and {@link #SCALE_Y} FloatProperties.
 *
 * This is useful when you need to perform a scale animation with a pivot point, since pivot points
 * are not supported by standard View scale operations but are supported by matrices.
 *
 * NOTE: DynamicAnimation assumes that all custom properties are denominated in pixels, and thus
 * considers 1 to be the smallest user-visible change for custom properties. This means that if you
 * animate {@link #SCALE_X} and {@link #SCALE_Y} to 3f, for example, the animation would have only
 * three frames.
 *
 * To work around this, whenever animating to a desired scale value, animate to the value returned
 * by {@link #getAnimatableValueForScaleFactor} instead. The SCALE_X and SCALE_Y properties will
 * convert that (larger) value into the appropriate scale factor when scaling the matrix.
 */
public class AnimatableScaleMatrix extends Matrix {

    /**
     * The X value of the scale.
     *
     * NOTE: This must be set or animated to the value returned by
     * {@link #getAnimatableValueForScaleFactor}, not the desired scale factor itself.
     */
    public static final FloatPropertyCompat<AnimatableScaleMatrix> SCALE_X =
            new FloatPropertyCompat<AnimatableScaleMatrix>("matrixScaleX") {
        @Override
        public float getValue(AnimatableScaleMatrix object) {
            return getAnimatableValueForScaleFactor(object.mScaleX);
        }

        @Override
        public void setValue(AnimatableScaleMatrix object, float value) {
            object.setScaleX(value * DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE);
        }
    };

    /**
     * The Y value of the scale.
     *
     * NOTE: This must be set or animated to the value returned by
     * {@link #getAnimatableValueForScaleFactor}, not the desired scale factor itself.
     */
    public static final FloatPropertyCompat<AnimatableScaleMatrix> SCALE_Y =
            new FloatPropertyCompat<AnimatableScaleMatrix>("matrixScaleY") {
                @Override
                public float getValue(AnimatableScaleMatrix object) {
                    return getAnimatableValueForScaleFactor(object.mScaleY);
                }

                @Override
                public void setValue(AnimatableScaleMatrix object, float value) {
                    object.setScaleY(value * DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE);
                }
            };

    private float mScaleX = 1f;
    private float mScaleY = 1f;

    private float mPivotX = 0f;
    private float mPivotY = 0f;

    /**
     * Return the value to animate SCALE_X or SCALE_Y to in order to achieve the desired scale
     * factor.
     */
    public static float getAnimatableValueForScaleFactor(float scale) {
        return scale * (1f / DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE);
    }

    @Override
    public void setScale(float sx, float sy, float px, float py) {
        mScaleX = sx;
        mScaleY = sy;
        mPivotX = px;
        mPivotY = py;
        super.setScale(mScaleX, mScaleY, mPivotX, mPivotY);
    }

    public void setScaleX(float scaleX) {
        mScaleX = scaleX;
        super.setScale(mScaleX, mScaleY, mPivotX, mPivotY);
    }

    public void setScaleY(float scaleY) {
        mScaleY = scaleY;
        super.setScale(mScaleX, mScaleY, mPivotX, mPivotY);
    }

    public void setPivotX(float pivotX) {
        mPivotX = pivotX;
        super.setScale(mScaleX, mScaleY, mPivotX, mPivotY);
    }

    public void setPivotY(float pivotY) {
        mPivotY = pivotY;
        super.setScale(mScaleX, mScaleY, mPivotX, mPivotY);
    }

    public float getScaleX() {
        return mScaleX;
    }

    public float getScaleY() {
        return mScaleY;
    }

    public float getPivotX() {
        return mPivotX;
    }

    public float getPivotY() {
        return mPivotY;
    }
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -56,7 +56,7 @@ public class ExpandedAnimationController
    private static final int ANIMATE_TRANSLATION_FACTOR = 4;
    private static final int ANIMATE_TRANSLATION_FACTOR = 4;


    /** Duration of the expand/collapse target path animation. */
    /** Duration of the expand/collapse target path animation. */
    private static final int EXPAND_COLLAPSE_TARGET_ANIM_DURATION = 175;
    public static final int EXPAND_COLLAPSE_TARGET_ANIM_DURATION = 175;


    /** Stiffness for the expand/collapse path-following animation. */
    /** Stiffness for the expand/collapse path-following animation. */
    private static final int EXPAND_COLLAPSE_ANIM_STIFFNESS = 1000;
    private static final int EXPAND_COLLAPSE_ANIM_STIFFNESS = 1000;
Loading