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

Commit c6002344 authored by Sunny Goyal's avatar Sunny Goyal Committed by Automerger Merge Worker
Browse files

Adding home animation support for non-system Launcher am: 30ac97d9

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/12150115

Change-Id: I225841557201a377e74c1b380beeea65faa30a61
parents 74baee14 30ac97d9
Loading
Loading
Loading
Loading
+135 −3
Original line number Diff line number Diff line
@@ -15,14 +15,35 @@
 */
package com.android.quickstep;

import static android.content.Intent.EXTRA_COMPONENT_NAME;
import static android.content.Intent.EXTRA_USER;

import static com.android.launcher3.GestureNavContract.EXTRA_GESTURE_CONTRACT;
import static com.android.launcher3.GestureNavContract.EXTRA_ICON_POSITION;
import static com.android.launcher3.GestureNavContract.EXTRA_ICON_SURFACE;
import static com.android.launcher3.GestureNavContract.EXTRA_REMOTE_CALLBACK;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;

import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.ParcelUuid;
import android.os.UserHandle;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;

import androidx.annotation.NonNull;

@@ -32,19 +53,33 @@ import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.SpringAnimationBuilder;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.util.TransformParams.BuilderProxy;
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;

import java.lang.ref.WeakReference;
import java.util.UUID;
import java.util.function.Consumer;

/**
 * Handles the navigation gestures when a 3rd party launcher is the default home activity.
 */
@TargetApi(Build.VERSION_CODES.R)
public class FallbackSwipeHandler extends
        BaseSwipeUpHandlerV2<RecentsActivity, FallbackRecentsView> {

    /**
     * Message used for receiving gesture nav contract information. We use a static messenger to
     * avoid leaking too make binders in case the receiving launcher does not handle the contract
     * properly.
     */
    private static StaticMessageReceiver sMessageReceiver = null;

    private FallbackHomeAnimationFactory mActiveAnimationFactory;
    private final boolean mRunningOverHome;

@@ -89,7 +124,9 @@ public class FallbackSwipeHandler extends
    protected HomeAnimationFactory createHomeAnimationFactory(long duration) {
        mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration);
        ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
        mContext.startActivity(new Intent(mGestureState.getHomeIntent()), options.toBundle());
        Intent intent = new Intent(mGestureState.getHomeIntent());
        mActiveAnimationFactory.addGestureContract(intent);
        mContext.startActivity(intent, options.toBundle());
        return mActiveAnimationFactory;
    }

@@ -130,15 +167,19 @@ public class FallbackSwipeHandler extends
    }

    private class FallbackHomeAnimationFactory extends HomeAnimationFactory {

        private final Rect mTempRect = new Rect();
        private final TransformParams mHomeAlphaParams = new TransformParams();
        private final AnimatedFloat mHomeAlpha;

        private final AnimatedFloat mVerticalShiftForScale = new AnimatedFloat();

        private final AnimatedFloat mRecentsAlpha = new AnimatedFloat();

        private final RectF mTargetRect = new RectF();
        private SurfaceControl mSurfaceControl;

        private final long mDuration;

        private RectFSpringAnim mSpringAnim;
        FallbackHomeAnimationFactory(long duration) {
            mDuration = duration;

@@ -161,6 +202,15 @@ public class FallbackSwipeHandler extends
                    this::updateRecentsActivityTransformDuringHomeAnim);
        }

        @NonNull
        @Override
        public RectF getWindowTargetRect() {
            if (mTargetRect.isEmpty()) {
                mTargetRect.set(super.getWindowTargetRect());
            }
            return mTargetRect;
        }

        private void updateRecentsActivityTransformDuringHomeAnim(SurfaceParams.Builder builder,
                RemoteAnimationTargetCompat app, TransformParams params) {
            builder.withAlpha(mRecentsAlpha.value);
@@ -217,5 +267,87 @@ public class FallbackSwipeHandler extends
                        .start();
            }
        }

        @Override
        public void setAnimation(RectFSpringAnim anim) {
            mSpringAnim = anim;
        }

        private void onMessageReceived(Message msg) {
            try {
                Bundle data = msg.getData();
                RectF position = data.getParcelable(EXTRA_ICON_POSITION);
                if (!position.isEmpty()) {
                    mSurfaceControl = data.getParcelable(EXTRA_ICON_SURFACE);
                    mTargetRect.set(position);
                    if (mSpringAnim != null) {
                        mSpringAnim.onTargetPositionChanged();
                    }
                }
            } catch (Exception e) {
                // Ignore
            }
        }

        @Override
        public void update(RectF currentRect, float progress, float radius) {
            if (mSurfaceControl != null) {
                currentRect.roundOut(mTempRect);
                Transaction t = new Transaction();
                t.setGeometry(mSurfaceControl, null, mTempRect, Surface.ROTATION_0);
                t.apply();
            }
        }

        private void addGestureContract(Intent intent) {
            if (mRunningOverHome || mGestureState.getRunningTask() == null) {
                return;
            }

            TaskKey key = new TaskKey(mGestureState.getRunningTask());
            if (key.getComponent() != null) {
                if (sMessageReceiver == null) {
                    sMessageReceiver = new StaticMessageReceiver();
                }

                Bundle gestureNavContract = new Bundle();
                gestureNavContract.putParcelable(EXTRA_COMPONENT_NAME, key.getComponent());
                gestureNavContract.putParcelable(EXTRA_USER, UserHandle.of(key.userId));
                gestureNavContract.putParcelable(EXTRA_REMOTE_CALLBACK,
                        sMessageReceiver.newCallback(this::onMessageReceived));
                intent.putExtra(EXTRA_GESTURE_CONTRACT, gestureNavContract);
            }
        }
    }

    private static class StaticMessageReceiver implements Handler.Callback {

        private final Messenger mMessenger =
                new Messenger(new Handler(Looper.getMainLooper(), this));

        private ParcelUuid mCurrentUID = new ParcelUuid(UUID.randomUUID());
        private WeakReference<Consumer<Message>> mCurrentCallback = new WeakReference<>(null);

        public Message newCallback(Consumer<Message> callback) {
            mCurrentUID = new ParcelUuid(UUID.randomUUID());
            mCurrentCallback = new WeakReference<>(callback);

            Message msg = Message.obtain();
            msg.replyTo = mMessenger;
            msg.obj = mCurrentUID;
            return msg;
        }

        @Override
        public boolean handleMessage(@NonNull Message message) {
            if (mCurrentUID.equals(message.obj)) {
                Consumer<Message> consumer = mCurrentCallback.get();
                if (consumer != null) {
                    consumer.accept(message);
                    return true;
                }
            }
            return false;
        }
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -110,6 +110,13 @@ public abstract class BaseQuickstepLauncher extends Launcher
                .getHighResLoadingState().setVisible(true);
    }

    @Override
    protected void handleGestureContract(Intent intent) {
        if (FeatureFlags.SEPARATE_RECENTS_ACTIVITY.get()) {
            super.handleGestureContract(intent);
        }
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
+19 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<com.android.launcher3.views.FloatingSurfaceView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
+6 −3
Original line number Diff line number Diff line
@@ -62,7 +62,8 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
            TYPE_ALL_APPS_EDU,

            TYPE_TASK_MENU,
            TYPE_OPTIONS_POPUP
            TYPE_OPTIONS_POPUP,
            TYPE_ICON_SURFACE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface FloatingViewType {}
@@ -80,16 +81,18 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
    // Popups related to quickstep UI
    public static final int TYPE_TASK_MENU = 1 << 10;
    public static final int TYPE_OPTIONS_POPUP = 1 << 11;
    public static final int TYPE_ICON_SURFACE = 1 << 12;

    public static final int TYPE_ALL = TYPE_FOLDER | TYPE_ACTION_POPUP
            | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET
            | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE | TYPE_TASK_MENU
            | TYPE_OPTIONS_POPUP | TYPE_SNACKBAR | TYPE_LISTENER | TYPE_ALL_APPS_EDU;
            | TYPE_OPTIONS_POPUP | TYPE_SNACKBAR | TYPE_LISTENER | TYPE_ALL_APPS_EDU
            | TYPE_ICON_SURFACE;

    // Type of popups which should be kept open during launcher rebind
    public static final int TYPE_REBIND_SAFE = TYPE_WIDGETS_FULL_SHEET
            | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
            | TYPE_ALL_APPS_EDU;
            | TYPE_ALL_APPS_EDU | TYPE_ICON_SURFACE;

    // Usually we show the back button when a floating view is open. Instead, hide for these types.
    public static final int TYPE_HIDE_BACK_BUTTON = TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
+10 −4
Original line number Diff line number Diff line
@@ -614,6 +614,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
    @Override
    public void setIconVisible(boolean visible) {
        mIsIconVisible = visible;
        if (!mIsIconVisible) {
            resetIconScale();
        }
        Drawable icon = visible ? mIcon : new ColorDrawable(Color.TRANSPARENT);
        applyCompoundDrawables(icon);
    }
@@ -753,11 +756,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,

    @Override
    public SafeCloseable prepareDrawDragView() {
        if (getIcon() instanceof FastBitmapDrawable) {
            FastBitmapDrawable icon = (FastBitmapDrawable) getIcon();
            icon.setScale(1f);
        }
        resetIconScale();
        setForceHideDot(true);
        return () -> { };
    }

    private void resetIconScale() {
        if (mIcon instanceof FastBitmapDrawable) {
            ((FastBitmapDrawable) mIcon).setScale(1f);
        }
    }
}
Loading