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

Commit 04dc5968 authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Override all transitions from package start

When launching a notification, often the launch goes into a
service, broadcast or trampoline activity that starts another
activity, for which we loose the ability to control the animation
because we don't provide the activity options anymore.

This CL adds the ability to override all activity launches
originating from a certain package for a couple of seconds, such
that we have the ability to still control the animation from
SystemUI.

Test: go/wm-smoke
Test: Start stopwatch, press home, press notification
Test: atest PendingRemoteAnimationRegistryTest
Change-Id: I4d077c4ac4565f060e849e4b33920d2bf4a80d48
parent 6a9fb943
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -1105,6 +1105,11 @@ public class ActivityOptions {
        return mRemoteAnimationAdapter;
    }

    /** @hide */
    public void setRemoteAnimationAdapter(RemoteAnimationAdapter remoteAnimationAdapter) {
        mRemoteAnimationAdapter = remoteAnimationAdapter;
    }

    /** @hide */
    public static ActivityOptions fromBundle(Bundle bOptions) {
        return bOptions != null ? new ActivityOptions(bOptions) : null;
+8 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ import android.os.WorkSource;
import android.service.voice.IVoiceInteractionSession;
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationAdapter;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.IResultReceiver;
import com.android.internal.policy.IKeyguardDismissCallback;
@@ -696,4 +697,11 @@ interface IActivityManager {
      * Registers remote animations for a specific activity.
      */
     void registerRemoteAnimations(in IBinder token, in RemoteAnimationDefinition definition);

     /**
      * Registers a remote animation to be run for all activity starts from a certain package during
      * a short predefined amount of time.
      */
     void registerRemoteAnimationForNextActivityStart(in String packageName,
            in RemoteAnimationAdapter adapter);
}
+5 −5
Original line number Diff line number Diff line
@@ -77,11 +77,11 @@ public class ActivityLaunchAnimator {
        mStatusBar = statusBar;
    }

    public ActivityOptions getLaunchAnimation(
            ExpandableNotificationRow sourceNofitication) {
        AnimationRunner animationRunner = new AnimationRunner(sourceNofitication);
        return ActivityOptions.makeRemoteAnimation(
                new RemoteAnimationAdapter(animationRunner, 1000 /* Duration */, 0 /* delay */));
    public RemoteAnimationAdapter getLaunchAnimation(
            ExpandableNotificationRow sourceNotification) {
        AnimationRunner animationRunner = new AnimationRunner(sourceNotification);
        return new RemoteAnimationAdapter(animationRunner, ANIMATION_DURATION,
                0 /* statusBarTransitionDelay */);
    }

    public boolean isAnimationPending() {
+14 −8
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.RemoteAnimationAdapter;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewGroup;
@@ -2849,7 +2850,7 @@ public class StatusBar extends SystemUI implements DemoMode,
                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            int result = ActivityManager.START_CANCELED;
            ActivityOptions options = new ActivityOptions(getActivityOptions(
                    null /* sourceNotification */));
                    null /* remoteAnimation */));
            options.setDisallowEnterPictureInPictureWhileLaunching(
                    disallowEnterPictureInPictureWhileLaunching);
            if (intent == KeyguardBottomAreaView.INSECURE_CAMERA_INTENT) {
@@ -5001,11 +5002,15 @@ public class StatusBar extends SystemUI implements DemoMode,
                        fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
                                remoteInputText.toString());
                    }
                    RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(
                            row);
                    try {
                        ActivityManager.getService().registerRemoteAnimationForNextActivityStart(
                                intent.getCreatorPackage(), adapter);
                        launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
                                null, null, getActivityOptions(row));
                                null, null, getActivityOptions(adapter));
                        mActivityLaunchAnimator.setLaunchResult(launchResult);
                    } catch (PendingIntent.CanceledException e) {
                    } catch (RemoteException | PendingIntent.CanceledException e) {
                        // the stack trace isn't very helpful here.
                        // Just log the exception message.
                        Log.w(TAG, "Sending contentIntent failed: " + e);
@@ -5165,7 +5170,8 @@ public class StatusBar extends SystemUI implements DemoMode,
            AsyncTask.execute(() -> {
                int launchResult = TaskStackBuilder.create(mContext)
                        .addNextIntentWithParentStack(intent)
                        .startActivities(getActivityOptions(row),
                        .startActivities(getActivityOptions(
                                mActivityLaunchAnimator.getLaunchAnimation(row)),
                                new UserHandle(UserHandle.getUserId(appUid)));
                mActivityLaunchAnimator.setLaunchResult(launchResult);
                if (shouldCollapse()) {
@@ -5300,7 +5306,7 @@ public class StatusBar extends SystemUI implements DemoMode,
                }
                try {
                    intent.send(null, 0, null, null, null, null, getActivityOptions(
                            null /* sourceNotification */));
                            null /* animationAdapter */));
                } catch (PendingIntent.CanceledException e) {
                    // the stack trace isn't very helpful here.
                    // Just log the exception message.
@@ -5328,10 +5334,10 @@ public class StatusBar extends SystemUI implements DemoMode,
        return true;
    }

    protected Bundle getActivityOptions(ExpandableNotificationRow sourceNotification) {
    protected Bundle getActivityOptions(@Nullable RemoteAnimationAdapter animationAdapter) {
        ActivityOptions options;
        if (sourceNotification != null) {
            options = mActivityLaunchAnimator.getLaunchAnimation(sourceNotification);
        if (animationAdapter != null) {
            options = ActivityOptions.makeRemoteAnimation(animationAdapter);
        } else {
            options = ActivityOptions.makeBasic();
        }
+17 −0
Original line number Diff line number Diff line
@@ -381,6 +381,7 @@ import android.util.proto.ProtoUtils;
import android.view.Gravity;
import android.view.IRecentsAnimationRunner;
import android.view.LayoutInflater;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
import android.view.View;
import android.view.WindowManager;
@@ -26294,4 +26295,20 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
    }
    @Override
    public void registerRemoteAnimationForNextActivityStart(String packageName,
            RemoteAnimationAdapter adapter) throws RemoteException {
        enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
                "registerRemoteAnimationForNextActivityStart");
        synchronized (this) {
            final long origId = Binder.clearCallingIdentity();
            try {
                mActivityStartController.registerRemoteAnimationForNextActivityStart(packageName,
                        adapter);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    }
}
Loading