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

Commit 5705da8f authored by Issei Suzuki's avatar Issei Suzuki
Browse files

Transfer remote animation option from an intercepted activity.

While an activity starts, ActivityStartIntercepter may intercept it and
launch another activity. If this happens, we don't have chance to apply
pending remote animation of the intercepted activity.

The pending remote animation originally came from ActivityOption, so we
extract the remote animation from an ActivityOption of the intercepted
activity, and pipe it through to the activity being launched by the
ActivityStartIntercepter.

This also reverts commit a17263ae.

Bug: 222757698
Test: manual. Start YouTube app from the launcher and check animation.
Change-Id: Ice62f4ee3453a06362e3acf820ef22235656845c
parent cf4afcdd
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -264,7 +264,6 @@ import android.widget.Toast;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
+33 −19
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.policy;

import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.MODE_IGNORED;
@@ -58,8 +59,6 @@ import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PermissionInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -93,6 +92,7 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.wm.ActivityInterceptorCallback;
import com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo;
import com.android.server.wm.ActivityTaskManagerInternal;

import java.util.ArrayList;
@@ -115,7 +115,6 @@ public final class PermissionPolicyService extends SystemService {
    private static final String SYSTEM_PKG = "android";
    private static final boolean DEBUG = false;
    private static final long USER_SENSITIVE_UPDATE_DELAY_MS = 60000;
    private static final long ACTIVITY_START_DELAY_MS = 200;

    private final Object mLock = new Object();

@@ -155,8 +154,7 @@ public final class PermissionPolicyService extends SystemService {

    private List<String> mAppOpPermissions;

    private final Context mContext;
    private final Handler mHandler;
    private Context mContext;
    private PackageManagerInternal mPackageManagerInternal;
    private PermissionManagerServiceInternal mPermissionManagerInternal;
    private NotificationManagerInternal mNotificationManager;
@@ -167,7 +165,6 @@ public final class PermissionPolicyService extends SystemService {
        super(context);

        mContext = context;
        mHandler = new Handler(Looper.getMainLooper());
        mPackageManager = context.getPackageManager();
        mKeyguardManager = context.getSystemService(KeyguardManager.class);
        LocalServices.addService(PermissionPolicyInternal.class, new Internal());
@@ -1072,7 +1069,7 @@ public final class PermissionPolicyService extends SystemService {
                            clearNotificationReviewFlagsIfNeeded(activityInfo.packageName, user);
                        } else {
                            showNotificationPromptIfNeeded(activityInfo.packageName,
                                    taskInfo.userId, taskInfo.taskId);
                                    taskInfo.userId, taskInfo.taskId, info);
                        }
                    }
                };
@@ -1103,15 +1100,21 @@ public final class PermissionPolicyService extends SystemService {
            return true;
        }

        @Override
        public void showNotificationPromptIfNeeded(@NonNull String packageName, int userId,
                int taskId) {
            showNotificationPromptIfNeeded(packageName, userId, taskId, null /* info */);
        }

        void showNotificationPromptIfNeeded(@NonNull String packageName, int userId,
                int taskId, @Nullable ActivityInterceptorInfo info) {
            UserHandle user = UserHandle.of(userId);
            if (packageName == null || taskId == ActivityTaskManager.INVALID_TASK_ID
                    || !shouldForceShowNotificationPermissionRequest(packageName, user)) {
                return;
            }

            launchNotificationPermissionRequestDialog(packageName, user, taskId);
            launchNotificationPermissionRequestDialog(packageName, user, taskId, info);
        }

        @Override
@@ -1180,7 +1183,7 @@ public final class PermissionPolicyService extends SystemService {
        }

        private void launchNotificationPermissionRequestDialog(String pkgName, UserHandle user,
                int taskId) {
                int taskId, @Nullable ActivityInterceptorInfo info) {
            Intent grantPermission = mPackageManager
                    .buildRequestPermissionsIntent(new String[] { POST_NOTIFICATIONS });
            // Prevent the front-most activity entering pip due to overlay activity started on top.
@@ -1189,18 +1192,29 @@ public final class PermissionPolicyService extends SystemService {
                    ACTION_REQUEST_PERMISSIONS_FOR_OTHER);
            grantPermission.putExtra(Intent.EXTRA_PACKAGE_NAME, pkgName);

            ActivityOptions options = new ActivityOptions(new Bundle());
            final boolean remoteAnimation = info != null && info.checkedOptions != null
                    && info.checkedOptions.getAnimationType() == ANIM_REMOTE_ANIMATION
                    && info.clearOptionsAnimation != null;
            ActivityOptions options = remoteAnimation ? ActivityOptions.makeRemoteAnimation(
                        info.checkedOptions.getRemoteAnimationAdapter(),
                        info.checkedOptions.getRemoteTransition())
                    : new ActivityOptions(new Bundle());
            options.setTaskOverlay(true, false);
            options.setLaunchTaskId(taskId);
            mHandler.postDelayed(() -> {
            if (remoteAnimation) {
                // Remote animation set on the intercepted activity will be handled by the grant
                // permission activity, which is launched below. So we need to clear remote
                // animation from the intercepted activity and its siblings to prevent duplication.
                // This should trigger ActivityRecord#clearOptionsAnimationForSiblings for the
                // intercepted activity.
                info.clearOptionsAnimation.run();
            }
            try {
                    mContext.startActivityAsUser(
                            grantPermission, options.toBundle(), user);
                mContext.startActivityAsUser(grantPermission, options.toBundle(), user);
            } catch (Exception e) {
                Log.e(LOG_TAG, "couldn't start grant permission dialog"
                        + "for other package " + pkgName, e);
            }
            }, ACTIVITY_START_DELAY_MS);
        }

        @Override
+4 −1
Original line number Diff line number Diff line
@@ -108,11 +108,13 @@ public abstract class ActivityInterceptorCallback {
        public final int callingPid;
        public final int callingUid;
        public final ActivityOptions checkedOptions;
        public final @Nullable Runnable clearOptionsAnimation;

        public ActivityInterceptorInfo(int realCallingUid, int realCallingPid, int userId,
                String callingPackage, String callingFeatureId, Intent intent,
                ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType, int callingPid,
                int callingUid, ActivityOptions checkedOptions) {
                int callingUid, ActivityOptions checkedOptions,
                @Nullable Runnable clearOptionsAnimation) {
            this.realCallingUid = realCallingUid;
            this.realCallingPid = realCallingPid;
            this.userId = userId;
@@ -125,6 +127,7 @@ public abstract class ActivityInterceptorCallback {
            this.callingPid = callingPid;
            this.callingUid = callingUid;
            this.checkedOptions = checkedOptions;
            this.clearOptionsAnimation = clearOptionsAnimation;
        }
    }

+10 −8
Original line number Diff line number Diff line
@@ -4592,14 +4592,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            }
            applyOptionsAnimation(mPendingOptions, intent);
        }
        if (task == null) {
            clearOptionsAnimation();
        } else {
            // This will clear the options for all the ActivityRecords for this Task.
            task.forAllActivities((r) -> {
                r.clearOptionsAnimation();
            });
        }
        clearOptionsAnimationForSiblings();
    }

    /**
@@ -4786,6 +4779,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        mPendingRemoteTransition = null;
    }

    void clearOptionsAnimationForSiblings() {
        if (task == null) {
            clearOptionsAnimation();
        } else {
            // This will clear the options for all the ActivityRecords for this Task.
            task.forAllActivities(ActivityRecord::clearOptionsAnimation);
        }
    }

    ActivityOptions getOptions() {
        return mPendingOptions;
    }
+8 −6
Original line number Diff line number Diff line
@@ -188,7 +188,7 @@ class ActivityStartInterceptor {
        final SparseArray<ActivityInterceptorCallback> callbacks =
                mService.getActivityInterceptorCallbacks();
        final ActivityInterceptorCallback.ActivityInterceptorInfo interceptorInfo =
                getInterceptorInfo();
                getInterceptorInfo(null /* clearOptionsAnimation */);

        for (int i = 0; i < callbacks.size(); i++) {
            final ActivityInterceptorCallback callback = callbacks.valueAt(i);
@@ -406,20 +406,22 @@ class ActivityStartInterceptor {
    /**
     * Called when an activity is successfully launched.
     */
    void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo) {
    void onActivityLaunched(TaskInfo taskInfo, ActivityRecord r) {
        final SparseArray<ActivityInterceptorCallback> callbacks =
                mService.getActivityInterceptorCallbacks();
        ActivityInterceptorCallback.ActivityInterceptorInfo info = getInterceptorInfo();
        ActivityInterceptorCallback.ActivityInterceptorInfo info = getInterceptorInfo(
                r::clearOptionsAnimationForSiblings);
        for (int i = 0; i < callbacks.size(); i++) {
            final ActivityInterceptorCallback callback = callbacks.valueAt(i);
            callback.onActivityLaunched(taskInfo, activityInfo, info);
            callback.onActivityLaunched(taskInfo, r.info, info);
        }
    }

    private ActivityInterceptorCallback.ActivityInterceptorInfo getInterceptorInfo() {
    private ActivityInterceptorCallback.ActivityInterceptorInfo getInterceptorInfo(
            @Nullable Runnable clearOptionsAnimation) {
        return new ActivityInterceptorCallback.ActivityInterceptorInfo(mRealCallingUid,
                mRealCallingPid, mUserId, mCallingPackage, mCallingFeatureId, mIntent,
                mRInfo, mAInfo, mResolvedType, mCallingPid, mCallingUid,
                mActivityOptions);
                mActivityOptions, clearOptionsAnimation);
    }
}
Loading