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

Commit f31b5dc0 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Enforce onActivityReparentedToTask" into tm-qpr-dev

parents 41fb1179 2d6dabd2
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import static java.util.Objects.requireNonNull;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
@@ -322,9 +323,10 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
                        + " is not in a task belong to the organizer app.");
                return null;
            }
            if (task.isAllowedToEmbedActivity(activity, mOrganizerUid) != EMBEDDING_ALLOWED) {
            if (task.isAllowedToEmbedActivity(activity, mOrganizerUid) != EMBEDDING_ALLOWED
                    || !task.isAllowedToEmbedActivityInTrustedMode(activity, mOrganizerUid)) {
                Slog.d(TAG, "Reparent activity=" + activity.token
                        + " is not allowed to be embedded.");
                        + " is not allowed to be embedded in trusted mode.");
                return null;
            }

@@ -350,7 +352,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
                    activity.token, task.mTaskId);
            return new TaskFragmentTransaction.Change(TYPE_ACTIVITY_REPARENTED_TO_TASK)
                    .setTaskId(task.mTaskId)
                    .setActivityIntent(activity.intent)
                    .setActivityIntent(trimIntent(activity.intent))
                    .setActivityToken(activityToken);
        }

@@ -1095,4 +1097,15 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
            return false;
        }
    }

    /**
     * Trims the given Intent to only those that are needed to for embedding rules. This helps to
     * make it safer for cross-uid embedding even if we only send the Intent for trusted embedding.
     */
    private static Intent trimIntent(@NonNull Intent intent) {
        return new Intent()
                .setComponent(intent.getComponent())
                .setPackage(intent.getPackage())
                .setAction(intent.getAction());
    }
}
+74 −2
Original line number Diff line number Diff line
@@ -62,10 +62,12 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -403,7 +405,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        final TaskFragmentTransaction.Change change = changes.get(0);
        assertEquals(TYPE_ACTIVITY_REPARENTED_TO_TASK, change.getType());
        assertEquals(task.mTaskId, change.getTaskId());
        assertEquals(activity.intent, change.getActivityIntent());
        assertIntentsEqualForOrganizer(activity.intent, change.getActivityIntent());
        assertNotEquals(activity.token, change.getActivityToken());
        mTransaction.reparentActivityToTaskFragment(mFragmentToken, change.getActivityToken());
        assertApplyTransactionAllowed(mTransaction);
@@ -414,6 +416,62 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
                change.getActivityToken()));
    }

    @Test
    public void testOnActivityReparentedToTask_untrustedEmbed_notReported() {
        final int pid = Binder.getCallingPid();
        final int uid = Binder.getCallingUid();
        mTaskFragment.setTaskFragmentOrganizer(mOrganizer.getOrganizerToken(), uid,
                DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME);
        mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
        final Task task = createTask(mDisplayContent);
        task.addChild(mTaskFragment, POSITION_TOP);
        final ActivityRecord activity = createActivityRecord(task);

        // Make sure the activity is embedded in untrusted mode.
        activity.info.applicationInfo.uid = uid + 1;
        doReturn(pid + 1).when(activity).getPid();
        task.effectiveUid = uid;
        doReturn(EMBEDDING_ALLOWED).when(task).isAllowedToEmbedActivity(activity, uid);
        doReturn(false).when(task).isAllowedToEmbedActivityInTrustedMode(activity, uid);
        doReturn(true).when(task).isAllowedToEmbedActivityInUntrustedMode(activity);

        // Notify organizer if it was embedded before entered Pip.
        // Create a temporary token since the activity doesn't belong to the same process.
        clearInvocations(mOrganizer);
        activity.mLastTaskFragmentOrganizerBeforePip = mIOrganizer;
        mController.onActivityReparentedToTask(activity);
        mController.dispatchPendingEvents();

        // Disallow organizer to reparent activity that is untrusted embedded.
        verify(mOrganizer, never()).onTransactionReady(mTransactionCaptor.capture());
    }

    @Test
    public void testOnActivityReparentedToTask_trimReportedIntent() {
        // Make sure the activity pid/uid is the same as the organizer caller.
        final int pid = Binder.getCallingPid();
        final int uid = Binder.getCallingUid();
        final ActivityRecord activity = createActivityRecord(mDisplayContent);
        final Task task = activity.getTask();
        activity.info.applicationInfo.uid = uid;
        doReturn(pid).when(activity).getPid();
        task.effectiveUid = uid;
        activity.mLastTaskFragmentOrganizerBeforePip = mIOrganizer;

        // Test the Intent trim in #assertIntentTrimmed
        activity.intent.setComponent(new ComponentName("TestPackage", "TestClass"))
                .setPackage("TestPackage")
                .setAction("TestAction")
                .setData(mock(Uri.class))
                .putExtra("Test", 123)
                .setFlags(10);

        mController.onActivityReparentedToTask(activity);
        mController.dispatchPendingEvents();

        assertActivityReparentedToTaskTransaction(task.mTaskId, activity.intent, activity.token);
    }

    @Test
    public void testRegisterRemoteAnimations() {
        mController.registerRemoteAnimations(mIOrganizer, TASK_ID, mDefinition);
@@ -1425,7 +1483,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        final TaskFragmentTransaction.Change change = changes.remove(0);
        assertEquals(TYPE_ACTIVITY_REPARENTED_TO_TASK, change.getType());
        assertEquals(taskId, change.getTaskId());
        assertEquals(intent, change.getActivityIntent());
        assertIntentsEqualForOrganizer(intent, change.getActivityIntent());
        assertIntentTrimmed(change.getActivityIntent());
        assertEquals(activityToken, change.getActivityToken());
    }

@@ -1452,4 +1511,17 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        mockParent.lastActiveTime = 100;
        doReturn(true).when(mockParent).shouldBeVisible(any());
    }

    private static void assertIntentsEqualForOrganizer(@NonNull Intent expected,
            @NonNull Intent actual) {
        assertEquals(expected.getComponent(), actual.getComponent());
        assertEquals(expected.getPackage(), actual.getPackage());
        assertEquals(expected.getAction(), actual.getAction());
    }

    private static void assertIntentTrimmed(@NonNull Intent intent) {
        assertNull(intent.getData());
        assertNull(intent.getExtras());
        assertEquals(0, intent.getFlags());
    }
}