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

Commit e3bcbba9 authored by Louis Chang's avatar Louis Chang
Browse files

[conflict] RESTRICT AUTOMERGE Normalize home intent am: b2b4bc3f am: 2248553b

parents 77a55810 2248553b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2859,7 +2859,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 −2
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;
@@ -53,6 +57,7 @@ import android.os.IBinder;
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;
@@ -64,6 +69,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#execute()}
 * It's initialized via setStates and interception occurs via the intercept method.
@@ -72,6 +78,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;
@@ -108,6 +115,11 @@ class ActivityStartInterceptor {
    TaskFragment mInTaskFragment;
    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);
@@ -156,7 +168,6 @@ class ActivityStartInterceptor {
        return new IntentSender(target);
    }


    /**
     * A helper function to obtain the targeted {@link TaskFragment} during
     * {@link #intercept(Intent, ResolveInfo, ActivityInfo, String, Task, TaskFragment, int, int,
@@ -177,6 +188,14 @@ class ActivityStartInterceptor {
        return TaskFragment.fromTaskFragmentToken(taskFragToken, mService);
    }

    // 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, TaskFragment inTaskFragment, int callingPid, int callingUid,
            ActivityOptions activityOptions) {
        return intercept(intent, rInfo, aInfo, resolvedType, inTask, inTaskFragment, 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.
@@ -185,7 +204,7 @@ class ActivityStartInterceptor {
     */
    boolean intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType,
            Task inTask, TaskFragment inTaskFragment, int callingPid, int callingUid,
            ActivityOptions activityOptions) {
            ActivityOptions activityOptions, boolean componentSpecified) {
        mUserManager = UserManager.get(mServiceContext);

        mIntent = intent;
@@ -197,6 +216,7 @@ class ActivityStartInterceptor {
        mInTask = inTask;
        mInTaskFragment = inTaskFragment;
        mActivityOptions = activityOptions;
        mComponentSpecified = componentSpecified;

        if (interceptQuietProfileIfNeeded()) {
            // If work profile is turned off, skip the work challenge since the profile can only
@@ -219,6 +239,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();
@@ -447,6 +471,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
@@ -1068,7 +1068,7 @@ class ActivityStarter {
        mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage,
                callingFeatureId);
        if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, inTaskFragment,
                callingPid, callingUid, checkedOptions)) {
                callingPid, 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;
+13 −0
Original line number Diff line number Diff line
@@ -228,6 +228,19 @@ 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, null, 0, 0, null,
                false));
        assertTrue(ActivityRecord.isHomeIntent(homeIntent));
    }

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