Decide on navigation to task by policy in Virtual Device
Adds the implementation to allow or block navigation to a
new task in the policy controller for a virtual device. Will
only change behavior if the cross navigation allow or block
list is included and the navigation does not occur from
the default display.
Bug: 223915401
Test: atest WmTests:DisplayWindowPolicyControllerHelperTests
atest CtsVirtualDevicesTestCases
atest WmTests:ActivityStarterTests
Added test in ag/17503735
Change-Id: I3dfb9dd93c0edf4634320c52a3fc40c4bf473085
This commit is contained in:
@@ -109,6 +109,13 @@ public abstract class DisplayWindowPolicyController {
|
||||
public abstract boolean canContainActivities(@NonNull List<ActivityInfo> activities,
|
||||
@WindowConfiguration.WindowingMode int windowingMode);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the given new task can be launched on this virtual display.
|
||||
*/
|
||||
public abstract boolean canActivityBeLaunched(@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
|
||||
* window flags that we’re interested in.
|
||||
|
||||
@@ -76,6 +76,10 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
@NonNull
|
||||
private final ArraySet<UserHandle> mAllowedUsers;
|
||||
@Nullable
|
||||
private final ArraySet<ComponentName> mAllowedCrossTaskNavigations;
|
||||
@Nullable
|
||||
private final ArraySet<ComponentName> mBlockedCrossTaskNavigations;
|
||||
@Nullable
|
||||
private final ArraySet<ComponentName> mAllowedActivities;
|
||||
@Nullable
|
||||
private final ArraySet<ComponentName> mBlockedActivities;
|
||||
@@ -100,6 +104,10 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
* @param windowFlags The window flags that this controller is interested in.
|
||||
* @param systemWindowFlags The system window flags that this controller is interested in.
|
||||
* @param allowedUsers The set of users that are allowed to stream in this display.
|
||||
* @param allowedCrossTaskNavigations The set of components explicitly allowed to navigate
|
||||
* across tasks on this device.
|
||||
* @param blockedCrossTaskNavigations The set of components explicitly blocked from
|
||||
* navigating across tasks on this device.
|
||||
* @param allowedActivities The set of activities explicitly allowed to stream on this device.
|
||||
* Used only if the {@code activityPolicy} is
|
||||
* {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_BLOCKED}.
|
||||
@@ -115,6 +123,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
*/
|
||||
public GenericWindowPolicyController(int windowFlags, int systemWindowFlags,
|
||||
@NonNull ArraySet<UserHandle> allowedUsers,
|
||||
@NonNull Set<ComponentName> allowedCrossTaskNavigations,
|
||||
@NonNull Set<ComponentName> blockedCrossTaskNavigations,
|
||||
@NonNull Set<ComponentName> allowedActivities,
|
||||
@NonNull Set<ComponentName> blockedActivities,
|
||||
@ActivityPolicy int defaultActivityPolicy,
|
||||
@@ -122,6 +132,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
@NonNull Consumer<ActivityInfo> activityBlockedCallback) {
|
||||
super();
|
||||
mAllowedUsers = allowedUsers;
|
||||
mAllowedCrossTaskNavigations = new ArraySet<>(allowedCrossTaskNavigations);
|
||||
mBlockedCrossTaskNavigations = new ArraySet<>(blockedCrossTaskNavigations);
|
||||
mAllowedActivities = new ArraySet<>(allowedActivities);
|
||||
mBlockedActivities = new ArraySet<>(blockedActivities);
|
||||
mDefaultActivityPolicy = defaultActivityPolicy;
|
||||
@@ -153,6 +165,46 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canActivityBeLaunched(ActivityInfo activityInfo,
|
||||
@WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
|
||||
boolean isNewTask) {
|
||||
if (!isWindowingModeSupported(windowingMode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ComponentName activityComponent = activityInfo.getComponentName();
|
||||
if (BLOCKED_APP_STREAMING_COMPONENT.equals(activityComponent)) {
|
||||
// The error dialog alerting users that streaming is blocked is always allowed.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!canContainActivity(activityInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) {
|
||||
mActivityBlockedCallback.accept(activityInfo);
|
||||
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.accept(activityInfo);
|
||||
return false;
|
||||
}
|
||||
if (isNewTask && !mAllowedCrossTaskNavigations.isEmpty()
|
||||
&& !mAllowedCrossTaskNavigations.contains(activityComponent)) {
|
||||
Slog.d(TAG, "Virtual device not allowing cross task navigation of "
|
||||
+ activityComponent);
|
||||
mActivityBlockedCallback.accept(activityInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean keepActivityOnWindowFlagsChanged(ActivityInfo activityInfo, int windowFlags,
|
||||
int systemWindowFlags) {
|
||||
|
||||
@@ -528,6 +528,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
|
||||
new GenericWindowPolicyController(FLAG_SECURE,
|
||||
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
|
||||
getAllowedUserHandles(),
|
||||
mParams.getAllowedCrossTaskNavigations(),
|
||||
mParams.getBlockedCrossTaskNavigations(),
|
||||
mParams.getAllowedActivities(),
|
||||
mParams.getBlockedActivities(),
|
||||
mParams.getDefaultActivityPolicy(),
|
||||
|
||||
@@ -135,7 +135,6 @@ import com.android.server.wm.LaunchParamsController.LaunchParams;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@@ -2036,12 +2035,13 @@ class ActivityStarter {
|
||||
final DisplayContent displayContent = mRootWindowContainer.getDisplayContentOrCreate(
|
||||
mPreferredTaskDisplayArea.getDisplayId());
|
||||
if (displayContent != null && displayContent.mDwpcHelper.hasController()) {
|
||||
final ArrayList<ActivityInfo> activities = new ArrayList<>();
|
||||
activities.add(r.info);
|
||||
final int targetWindowingMode = (targetTask != null)
|
||||
? targetTask.getWindowingMode() : displayContent.getWindowingMode();
|
||||
final int launchingFromDisplayId =
|
||||
mSourceRecord != null ? mSourceRecord.getDisplayId() : DEFAULT_DISPLAY;
|
||||
if (!displayContent.mDwpcHelper
|
||||
.canContainActivities(activities, targetWindowingMode)) {
|
||||
.canActivityBeLaunched(r.info, targetWindowingMode, launchingFromDisplayId,
|
||||
newTask)) {
|
||||
Slog.w(TAG, "Abort to launch " + r.info.getComponentName()
|
||||
+ " on display area " + mPreferredTaskDisplayArea);
|
||||
return START_ABORTED;
|
||||
|
||||
@@ -74,6 +74,19 @@ class DisplayWindowPolicyControllerHelper {
|
||||
return mDisplayWindowPolicyController.canContainActivities(activities, windowingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DisplayWindowPolicyController#canActivityBeLaunched(ActivityInfo, int, int, boolean)
|
||||
*/
|
||||
public boolean canActivityBeLaunched(ActivityInfo activityInfo,
|
||||
@WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
|
||||
boolean isNewTask) {
|
||||
if (mDisplayWindowPolicyController == null) {
|
||||
return true;
|
||||
}
|
||||
return mDisplayWindowPolicyController.canActivityBeLaunched(activityInfo, windowingMode,
|
||||
launchingFromDisplayId, isNewTask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DisplayWindowPolicyController#keepActivityOnWindowFlagsChanged(ActivityInfo, int, int)
|
||||
*/
|
||||
|
||||
@@ -75,6 +75,8 @@ public class VirtualAudioControllerTest {
|
||||
FLAG_SECURE,
|
||||
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
|
||||
/* allowedUsers= */ new ArraySet<>(),
|
||||
/* allowedCrossTaskNavigations= */ new ArraySet<>(),
|
||||
/* blockedCrossTaskNavigations= */ new ArraySet<>(),
|
||||
/* allowedActivities= */ new ArraySet<>(),
|
||||
/* blockedActivities= */ new ArraySet<>(),
|
||||
VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED,
|
||||
|
||||
@@ -170,7 +170,7 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanContainActivities() {
|
||||
public void testCanActivityBeLaunched() {
|
||||
ActivityStarter starter = new ActivityStarter(mock(ActivityStartController.class), mAtm,
|
||||
mSupervisor, mock(ActivityStartInterceptor.class));
|
||||
final Task task = new TaskBuilder(mSupervisor).setDisplay(mSecondaryDisplay).build();
|
||||
@@ -203,6 +203,13 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
|
||||
int mTopActivityUid = UserHandle.USER_NULL;
|
||||
ArraySet<Integer> mRunningUids = new ArraySet<>();
|
||||
|
||||
@Override
|
||||
public boolean canActivityBeLaunched(@NonNull ActivityInfo activity,
|
||||
@WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
|
||||
boolean isNewTask) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
|
||||
@WindowConfiguration.WindowingMode int windowingMode) {
|
||||
|
||||
Reference in New Issue
Block a user