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

Commit 2248553b authored by Louis Chang's avatar Louis Chang Committed by Automerger Merge Worker
Browse files

RESTRICT AUTOMERGE Normalize home intent am: b2b4bc3f

parents ea34308e b2b4bc3f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2782,7 +2782,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        reparent(newTaskFrag, position);
    }

    private boolean isHomeIntent(Intent intent) {
    static boolean isHomeIntent(Intent intent) {
        return ACTION_MAIN.equals(intent.getAction())
                && (intent.hasCategory(CATEGORY_HOME)
                || intent.hasCategory(CATEGORY_SECONDARY_HOME))
+94 −1
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@ import static android.app.PendingIntent.FLAG_ONE_SHOT;
import static android.app.admin.DevicePolicyManager.EXTRA_RESTRICTION;
import static android.app.admin.DevicePolicyManager.POLICY_SUSPEND_PACKAGES;
import static android.content.Context.KEYGUARD_SERVICE;
import static android.content.Intent.ACTION_MAIN;
import static android.content.Intent.CATEGORY_HOME;
import static android.content.Intent.CATEGORY_SECONDARY_HOME;
import static android.content.Intent.EXTRA_INTENT;
import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static android.content.Intent.EXTRA_TASK_ID;
@@ -39,6 +42,7 @@ import android.app.ActivityOptions;
import android.app.KeyguardManager;
import android.app.TaskInfo;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentSender;
import android.content.Intent;
@@ -52,6 +56,7 @@ import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;
@@ -63,6 +68,7 @@ import com.android.server.LocalServices;
import com.android.server.am.ActivityManagerService;
import com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptResult;


/**
 * A class that contains activity intercepting logic for {@link ActivityStarter#startActivityLocked}
 * It's initialized via setStates and interception occurs via the intercept method.
@@ -71,6 +77,7 @@ import com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptResult
 * is no guarantee that other system services are already present.
 */
class ActivityStartInterceptor {
    private static final String TAG = "ActivityStartInterceptor";

    private final ActivityTaskManagerService mService;
    private final ActivityTaskSupervisor mSupervisor;
@@ -106,6 +113,11 @@ class ActivityStartInterceptor {
    Task mInTask;
    ActivityOptions mActivityOptions;

    /**
     * Whether the component is specified originally in the given Intent.
     */
    boolean mComponentSpecified;

    ActivityStartInterceptor(
            ActivityTaskManagerService service, ActivityTaskSupervisor supervisor) {
        this(service, supervisor, service.mRootWindowContainer, service.mContext);
@@ -144,6 +156,13 @@ class ActivityStartInterceptor {
        return new IntentSender(target);
    }

    // TODO: consolidate this method with the one below since this is used for test only.
    boolean intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType,
            Task inTask, int callingPid, int callingUid, ActivityOptions activityOptions) {
        return intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
                callingUid, activityOptions, false);
    }

    /**
     * Intercept the launch intent based on various signals. If an interception happened the
     * internal variables get assigned and need to be read explicitly by the caller.
@@ -151,7 +170,8 @@ class ActivityStartInterceptor {
     * @return true if an interception occurred
     */
    boolean intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType,
            Task inTask, int callingPid, int callingUid, ActivityOptions activityOptions) {
            Task inTask, int callingPid, int callingUid, ActivityOptions activityOptions,
            boolean componentSpecified) {
        mUserManager = UserManager.get(mServiceContext);

        mIntent = intent;
@@ -162,6 +182,7 @@ class ActivityStartInterceptor {
        mResolvedType = resolvedType;
        mInTask = inTask;
        mActivityOptions = activityOptions;
        mComponentSpecified = componentSpecified;

        if (interceptQuietProfileIfNeeded()) {
            // If work profile is turned off, skip the work challenge since the profile can only
@@ -184,6 +205,10 @@ class ActivityStartInterceptor {
        if (interceptLockedManagedProfileIfNeeded()) {
            return true;
        }
        if (interceptHomeIfNeeded()) {
            // Replace primary home intents if the home intent is not in the correct format.
            return true;
        }

        final SparseArray<ActivityInterceptorCallback> callbacks =
                mService.getActivityInterceptorCallbacks();
@@ -403,6 +428,74 @@ class ActivityStartInterceptor {
        return true;
    }

    private boolean interceptHomeIfNeeded() {
        if (mService.mRootWindowContainer == null) {
            return false;
        }

        boolean intercepted = false;
        if (!ACTION_MAIN.equals(mIntent.getAction()) || (!mIntent.hasCategory(CATEGORY_HOME)
                && !mIntent.hasCategory(CATEGORY_SECONDARY_HOME))) {
            // not a home intent
            return false;
        }

        if (mComponentSpecified) {
            final ComponentName homeComponent = mIntent.getComponent();
            final Intent homeIntent = mService.getHomeIntent();
            final ActivityInfo aInfo = mService.mRootWindowContainer.resolveHomeActivity(
                    mUserId, homeIntent);
            if (!aInfo.getComponentName().equals(homeComponent)) {
                // Do nothing if the intent is not for the default home component.
                return false;
            }
        }

        if (!ActivityRecord.isHomeIntent(mIntent) || mComponentSpecified) {
            // This is not a standard home intent, make it so if possible.
            normalizeHomeIntent();
            intercepted = true;
        }

        if (intercepted) {
            mCallingPid = mRealCallingPid;
            mCallingUid = mRealCallingUid;
            mResolvedType = null;

            mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId, /* flags= */ 0,
                    mRealCallingUid);
            mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, /*profilerInfo=*/
                    null);
        }
        return intercepted;
    }

    private void normalizeHomeIntent() {
        Slog.w(TAG, "The home Intent is not correctly formatted");
        if (mIntent.getCategories().size() > 1) {
            Slog.d(TAG, "Purge home intent categories");
            boolean isSecondaryHome = false;
            final Object[] categories = mIntent.getCategories().toArray();
            for (int i = categories.length - 1; i >= 0; i--) {
                final String category = (String) categories[i];
                if (CATEGORY_SECONDARY_HOME.equals(category)) {
                    isSecondaryHome = true;
                }
                mIntent.removeCategory(category);
            }
            mIntent.addCategory(isSecondaryHome ? CATEGORY_SECONDARY_HOME : CATEGORY_HOME);
        }
        if (mIntent.getType() != null || mIntent.getData() != null) {
            Slog.d(TAG, "Purge home intent data/type");
            mIntent.setType(null);
        }
        if (mComponentSpecified) {
            Slog.d(TAG, "Purge home intent component, " + mIntent.getComponent());
            mIntent.setComponent(null);
        }
        mIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
    }

    /**
     * Called when an activity is successfully launched.
     */
+1 −1
Original line number Diff line number Diff line
@@ -1057,7 +1057,7 @@ class ActivityStarter {
        mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage,
                callingFeatureId);
        if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
                callingUid, checkedOptions)) {
                callingUid, checkedOptions, request.componentSpecified)) {
            // activity start was intercepted, e.g. because the target user is currently in quiet
            // mode (turn off work) or the target application is suspended
            intent = mInterceptor.mIntent;
+12 −0
Original line number Diff line number Diff line
@@ -228,6 +228,18 @@ public class ActivityStartInterceptorTest {
        return dialogInfo;
    }

    @Test
    public void testInterceptIncorrectHomeIntent() {
        // Create a non-standard home intent
        final Intent homeIntent = new Intent(Intent.ACTION_MAIN);
        homeIntent.addCategory(Intent.CATEGORY_HOME);
        homeIntent.addCategory(Intent.CATEGORY_LAUNCHER);

        // Ensure the intent is intercepted and normalized to standard home intent.
        assertTrue(mInterceptor.intercept(homeIntent, null, mAInfo, null, null, 0, 0, null, false));
        assertTrue(ActivityRecord.isHomeIntent(homeIntent));
    }

    @Test
    public void testInterceptLockTaskModeViolationPackage() {
        when(mLockTaskController.isActivityAllowed(