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

Commit 9d287d85 authored by Vladimir Komsiyski's avatar Vladimir Komsiyski Committed by Android (Google) Code Review
Browse files

Merge "Consolidate DWPC usages." into main

parents e9f00dc6 9b2b73e6
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -17,8 +17,10 @@
package android.window;

import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.Display.INVALID_DISPLAY;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.WindowConfiguration;
import android.content.ComponentName;
@@ -107,18 +109,38 @@ public abstract class DisplayWindowPolicyController {
    }

    /**
     * Returns {@code true} if the given activities can be displayed on this virtual display and
     * the windowing mode is supported.
     * Returns {@code true} if all of the given activities can be launched on this virtual display
     * in the configuration defined by the rest of the arguments.
     *
     * @see #canContainActivity
     */
    public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
            @WindowConfiguration.WindowingMode int windowingMode) {
        for (int i = 0; i < activities.size(); i++) {
            if (!canContainActivity(activities.get(i), windowingMode,
                    /*launchingFromDisplayId=*/ INVALID_DISPLAY, /*isNewTask=*/ false)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns {@code true} if the given activity can be launched on this virtual display in the
     * configuration defined by the rest of the arguments. If the given intent would be intercepted
     * by the display owner then this means that the activity cannot be launched.
     */
    public abstract boolean canContainActivities(@NonNull List<ActivityInfo> activities,
            @WindowConfiguration.WindowingMode int windowingMode);
    public abstract boolean canActivityBeLaunched(@NonNull ActivityInfo activityInfo,
            @Nullable Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
            int launchingFromDisplayId, boolean isNewTask);

    /**
     * Returns {@code true} if the given new task can be launched on this virtual display.
     * Returns {@code true} if the given activity can be launched on this virtual display in the
     * configuration defined by the rest of the arguments.
     */
    public abstract boolean canActivityBeLaunched(@NonNull ActivityInfo activityInfo, Intent intent,
            @WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
            boolean isNewTask);
    protected abstract boolean canContainActivity(@NonNull ActivityInfo activityInfo,
            @WindowConfiguration.WindowingMode int windowingMode,
            int launchingFromDisplayId, boolean isNewTask);

    /**
     * Called when an Activity window is layouted with the new changes where contains the
+54 −89
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.companion.virtual;

import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;

@@ -46,7 +47,6 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.BlockedAppStreamingActivity;

import java.util.List;
import java.util.Set;


@@ -219,28 +219,37 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
    }

    @Override
    public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
            @WindowConfiguration.WindowingMode int windowingMode) {
        if (!isWindowingModeSupported(windowingMode)) {
    public boolean canActivityBeLaunched(@NonNull ActivityInfo activityInfo,
            @Nullable Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
            int launchingFromDisplayId, boolean isNewTask) {
        if (!canContainActivity(activityInfo, windowingMode, launchingFromDisplayId, isNewTask)) {
            mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
            return false;
        }
        // Can't display all the activities if any of them don't want to be displayed.
        final int activityCount = activities.size();
        for (int i = 0; i < activityCount; i++) {
            final ActivityInfo aInfo = activities.get(i);
            if (!canContainActivity(aInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) {
                mActivityBlockedCallback.onActivityBlocked(mDisplayId, aInfo);
        if (mIntentListenerCallback != null && intent != null
                && mIntentListenerCallback.shouldInterceptIntent(intent)) {
            Slog.d(TAG, "Virtual device intercepting intent");
            return false;
        }
        }
        return true;
    }

    @Override
    public boolean canActivityBeLaunched(ActivityInfo activityInfo,
            Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
            int launchingFromDisplayId, boolean isNewTask) {
    public boolean canContainActivity(@NonNull ActivityInfo activityInfo,
            @WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
            boolean isNewTask) {
        if (!isWindowingModeSupported(windowingMode)) {
            Slog.d(TAG, "Virtual device doesn't support windowing mode " + windowingMode);
            return false;
        }
        if ((activityInfo.flags & FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES) == 0) {
            Slog.d(TAG, "Virtual device requires android:canDisplayOnRemoteDevices=true");
            return false;
        }
        final UserHandle activityUser =
                UserHandle.getUserHandleForUid(activityInfo.applicationInfo.uid);
        if (!mAllowedUsers.contains(activityUser)) {
            Slog.d(TAG, "Virtual device launch disallowed from user " + activityUser);
            return false;
        }

@@ -249,40 +258,36 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
            // The error dialog alerting users that streaming is blocked is always allowed.
            return true;
        }

        if (!canContainActivity(activityInfo, /* windowFlags= */  0, /* systemWindowFlags= */ 0)) {
            mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
        if (!activityMatchesDisplayCategory(activityInfo)) {
            Slog.d(TAG, "The activity's required display category '"
                    + activityInfo.requiredDisplayCategory
                    + "' not found on virtual display with the following categories: "
                    + mDisplayCategories);
            return false;
        }

        if (launchingFromDisplayId == Display.DEFAULT_DISPLAY) {
            return true;
        }
        if (isNewTask && !mBlockedCrossTaskNavigations.isEmpty()
                && mBlockedCrossTaskNavigations.contains(activityComponent)) {
            Slog.d(TAG, "Virtual device blocking cross task navigation of " + activityComponent);
            mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
        if ((mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED
                && mBlockedActivities.contains(activityComponent))
                || (mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_BLOCKED
                && !mAllowedActivities.contains(activityComponent))) {
            Slog.d(TAG, "Virtual device launch disallowed by policy: " + activityComponent);
            return false;
        }
        if (isNewTask && !mAllowedCrossTaskNavigations.isEmpty()
                && !mAllowedCrossTaskNavigations.contains(activityComponent)) {
            Slog.d(TAG, "Virtual device not allowing cross task navigation of "
        if (isNewTask && launchingFromDisplayId != DEFAULT_DISPLAY) {
            if ((!mBlockedCrossTaskNavigations.isEmpty()
                    && mBlockedCrossTaskNavigations.contains(activityComponent))
                    || ((!mAllowedCrossTaskNavigations.isEmpty()
                    && !mAllowedCrossTaskNavigations.contains(activityComponent)))) {
                Slog.d(TAG, "Virtual device cross task navigation disallowed by policy: "
                        + activityComponent);
            mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
                return false;
            }

        if (mIntentListenerCallback != null && intent != null
                && mIntentListenerCallback.shouldInterceptIntent(intent)) {
            Slog.d(TAG, "Virtual device has intercepted intent");
            return false;
        }

        return true;
    }


    @Override
    @SuppressWarnings("AndroidFrameworkRequiresPermission")
    public boolean keepActivityOnWindowFlagsChanged(ActivityInfo activityInfo, int windowFlags,
            int systemWindowFlags) {
        // The callback is fired only when windowFlags are changed. To let VirtualDevice owner
@@ -293,10 +298,17 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
                    activityInfo.applicationInfo.uid));
        }

        if (!canContainActivity(activityInfo, windowFlags, systemWindowFlags)) {
        if (!CompatChanges.isChangeEnabled(ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE,
                activityInfo.packageName,
                UserHandle.getUserHandleForUid(activityInfo.applicationInfo.uid))) {
            // TODO(b/201712607): Add checks for the apps that use SurfaceView#setSecure.
            if ((windowFlags & FLAG_SECURE) != 0
                    || (systemWindowFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
                mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
                return false;
            }
        }

        return true;
    }

@@ -368,53 +380,6 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController

    }

    private boolean canContainActivity(ActivityInfo activityInfo, int windowFlags,
            int systemWindowFlags) {
        if ((activityInfo.flags & FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES) == 0) {
            return false;
        }
        ComponentName activityComponent = activityInfo.getComponentName();
        if (BLOCKED_APP_STREAMING_COMPONENT.equals(activityComponent)) {
            // The error dialog alerting users that streaming is blocked is always allowed. Need to
            // run before the clauses below to ensure error dialog always shows up.
            return true;
        }
        if (!activityMatchesDisplayCategory(activityInfo)) {
            Slog.d(TAG, String.format(
                    "The activity's required display category: %s is not found on virtual display"
                            + " with the following categories: %s",
                    activityInfo.requiredDisplayCategory, mDisplayCategories.toString()));
            return false;
        }
        final UserHandle activityUser =
                UserHandle.getUserHandleForUid(activityInfo.applicationInfo.uid);
        if (!mAllowedUsers.contains(activityUser)) {
            Slog.d(TAG, "Virtual device activity not allowed from user " + activityUser);
            return false;
        }
        if (mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED
                && mBlockedActivities.contains(activityComponent)) {
            Slog.d(TAG, "Virtual device blocking launch of " + activityComponent);
            return false;
        }
        if (mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_BLOCKED
                && !mAllowedActivities.contains(activityComponent)) {
            Slog.d(TAG, activityComponent + " is not in the allowed list.");
            return false;
        }
        if (!CompatChanges.isChangeEnabled(ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE,
                activityInfo.packageName, activityUser)) {
            // TODO(b/201712607): Add checks for the apps that use SurfaceView#setSecure.
            if ((windowFlags & FLAG_SECURE) != 0) {
                return false;
            }
            if ((systemWindowFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
                return false;
            }
        }
        return true;
    }

    @VisibleForTesting
    int getRunningAppsChangedListenersSizeForTesting() {
        synchronized (mGenericWindowPolicyControllerLock) {
+20 −20
Original line number Diff line number Diff line
@@ -68,19 +68,15 @@ class DisplayWindowPolicyControllerHelper {
    }

    /**
     * @see DisplayWindowPolicyController#canContainActivities(List, int)
     * @see DisplayWindowPolicyController#canContainActivities
     */
    public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
            @WindowConfiguration.WindowingMode int windowingMode) {
        if (mDisplayWindowPolicyController == null) {
            for (int i = activities.size() - 1; i >= 0; i--) {
                final ActivityInfo aInfo = activities.get(i);
                if (aInfo.requiredDisplayCategory != null) {
                    Slog.e(TAG,
                            String.format("Activity with requiredDisplayCategory='%s' cannot be"
                                            + " displayed on display %d because that display does"
                                            + " not have a matching category",
                                    aInfo.requiredDisplayCategory, mDisplayContent.mDisplayId));
            for (int i = 0; i < activities.size(); ++i) {
                // Missing controller means that this display has no categories for activity launch
                // restriction.
                if (hasDisplayCategory(activities.get(i))) {
                    return false;
                }
            }
@@ -90,26 +86,31 @@ class DisplayWindowPolicyControllerHelper {
    }

    /**
     * @see DisplayWindowPolicyController#canActivityBeLaunched(ActivityInfo, int, int, boolean)
     * @see DisplayWindowPolicyController#canActivityBeLaunched
     */
    public boolean canActivityBeLaunched(ActivityInfo activityInfo,
            Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
            int launchingFromDisplayId, boolean isNewTask) {
        if (mDisplayWindowPolicyController == null) {
            if (activityInfo.requiredDisplayCategory != null) {
                Slog.e(TAG,
                        String.format("Activity with requiredDisplayCategory='%s' cannot be"
                                + " launched on display %d because that display does"
                                + " not have a matching category",
                                activityInfo.requiredDisplayCategory, mDisplayContent.mDisplayId));
                return false;
            }
            return true;
            // Missing controller means that this display has no categories for activity launch
            // restriction.
            return !hasDisplayCategory(activityInfo);
        }
        return mDisplayWindowPolicyController.canActivityBeLaunched(activityInfo, intent,
            windowingMode, launchingFromDisplayId, isNewTask);
    }

    private boolean hasDisplayCategory(ActivityInfo aInfo) {
        if (aInfo.requiredDisplayCategory != null) {
            Slog.d(TAG,
                    String.format("Checking activity launch with requiredDisplayCategory='%s' on"
                                    + " display %d, which doesn't have a matching category.",
                            aInfo.requiredDisplayCategory, mDisplayContent.mDisplayId));
            return true;
        }
        return false;
    }

    /**
     * @see DisplayWindowPolicyController#keepActivityOnWindowFlagsChanged(ActivityInfo, int, int)
     */
@@ -199,7 +200,6 @@ class DisplayWindowPolicyControllerHelper {
        return mDisplayWindowPolicyController.isEnteringPipAllowed(uid);
    }


    void dump(String prefix, PrintWriter pw) {
        if (mDisplayWindowPolicyController != null) {
            pw.println();
+37 −31

File changed.

Preview size limit exceeded, changes collapsed.

+10 −13
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.List;
import java.util.Set;

/**
@@ -106,7 +105,6 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
        assertEquals(uidAmount, mDwpc.mRunningUids.size());
        assertTrue(mDwpc.mRunningUids.contains(TEST_USER_0_ID) == expectedUid0);
        assertTrue(mDwpc.mRunningUids.contains(TEST_USER_1_ID) == expectedUid1);

    }

    private ActivityRecord launchActivityOnDisplay(DisplayContent display, int uid) {
@@ -197,6 +195,11 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {

    @Test
    public void testCanActivityBeLaunched_requiredDisplayCategory() {
        doReturn(null).when(mWm.mDisplayManagerInternal)
                .getDisplayWindowPolicyController(anyInt());
        mSecondaryDisplay = createNewDisplay();
        assertFalse(mSecondaryDisplay.mDwpcHelper.hasController());

        ActivityStarter starter = new ActivityStarter(mock(ActivityStartController.class), mAtm,
                mSupervisor, mock(ActivityStartInterceptor.class));
        final Task task = new TaskBuilder(mSupervisor).setDisplay(mSecondaryDisplay).build();
@@ -233,20 +236,14 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
        public boolean canActivityBeLaunched(@NonNull ActivityInfo activity, Intent intent,
                @WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
                boolean isNewTask) {
            return false;
            return canContainActivity(activity, windowingMode, launchingFromDisplayId, isNewTask);
        }

        @Override
        public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
                @WindowConfiguration.WindowingMode int windowingMode) {
            final int activityCount = activities.size();
            for (int i = 0; i < activityCount; i++) {
                final ActivityInfo aInfo = activities.get(i);
                if (aInfo.getComponentName().equals(DISALLOWED_ACTIVITY)) {
                    return false;
                }
            }
            return true;
        protected boolean canContainActivity(@NonNull ActivityInfo activity,
                @WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
                boolean isNewTask) {
            return !activity.getComponentName().equals(DISALLOWED_ACTIVITY);
        }

        @Override