Update car launch params modifier.
Add missing parameter to CarLaunchParamsModifier
Update test for CarLaunchParamsModifier
Use source display for CarLaunchParamsModifier when allowed.
Test: atest CarServicesTest:CarLaunchParamsModifierTest
Bug: 152958720
Change-Id: I697d63ed26bc9a288afde2c57fba957eb4363b6d
diff --git a/src/com/android/internal/car/CarServiceHelperService.java b/src/com/android/internal/car/CarServiceHelperService.java
index 328a638..1a9097f 100644
--- a/src/com/android/internal/car/CarServiceHelperService.java
+++ b/src/com/android/internal/car/CarServiceHelperService.java
@@ -574,7 +574,7 @@
@Override
public void setDisplayAllowlistForUser(@UserIdInt int userId, int[] displayIds) {
- mCarLaunchParamsModifier.setDisplayAllowlistForUser(userId, displayIds);
+ mCarLaunchParamsModifier.setDisplayAllowListForUser(userId, displayIds);
}
@Override
diff --git a/src/com/android/server/wm/CarLaunchParamsModifier.java b/src/com/android/server/wm/CarLaunchParamsModifier.java
index c5cbe78..d706ec1 100644
--- a/src/com/android/server/wm/CarLaunchParamsModifier.java
+++ b/src/com/android/server/wm/CarLaunchParamsModifier.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import static com.android.server.wm.ActivityStarter.Request;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
@@ -194,7 +197,7 @@
* <p>The allowlist is kept only for profile user. Assigning the current user unassigns users
* for the given displays.
*/
- public void setDisplayAllowlistForUser(int userId, int[] displayIds) {
+ public void setDisplayAllowListForUser(int userId, int[] displayIds) {
if (DBG) {
Slog.d(TAG, "setDisplayAllowlistForUser userId:" + userId
+ " displays:" + displayIds);
@@ -265,10 +268,11 @@
* allowed, change to the 1st allowed display.</p>
*/
@Override
- public int onCalculate(Task task, ActivityInfo.WindowLayout layout, ActivityRecord activity,
- ActivityRecord source, ActivityOptions options, int phase,
- LaunchParamsController.LaunchParams currentParams,
- LaunchParamsController.LaunchParams outParams) {
+ @Result
+ public int onCalculate(@Nullable Task task, @Nullable ActivityInfo.WindowLayout layout,
+ @Nullable ActivityRecord activity, @Nullable ActivityRecord source,
+ ActivityOptions options, int phase, LaunchParamsController.LaunchParams currentParams,
+ LaunchParamsController.LaunchParams outParams, @Nullable Request request) {
int userId;
if (task != null) {
userId = task.mUserId;
@@ -349,7 +353,7 @@
break decision;
}
targetDisplayArea = getAlternativeDisplayAreaForPassengerLocked(
- userId, targetDisplayArea);
+ userId, activity, request);
}
if (targetDisplayArea != null && originalDisplayArea != targetDisplayArea) {
Slog.i(TAG, "Changed launching display, user:" + userId
@@ -364,21 +368,10 @@
@Nullable
private TaskDisplayArea getAlternativeDisplayAreaForPassengerLocked(int userId,
- TaskDisplayArea originalDisplayArea) {
- int displayId = mDefaultDisplayForProfileUser.get(userId, Display.INVALID_DISPLAY);
- if (displayId != Display.INVALID_DISPLAY) {
- return getDefaultTaskDisplayAreaOnDisplay(displayId);
- }
- // return the 1st passenger display area if it exists
- if (!mPassengerDisplays.isEmpty()) {
- Slog.w(TAG, "No default display area for user:" + userId
- + " reassign to 1st passenger display area");
- return getDefaultTaskDisplayAreaOnDisplay(mPassengerDisplays.get(0));
- }
- Slog.w(TAG, "No default display for user:" + userId
- + " and no passenger display, keep the requested display area:"
- + originalDisplayArea);
- return originalDisplayArea;
+ @NonNull ActivityRecord activityRecord, @Nullable Request request) {
+ TaskDisplayArea sourceDisplayArea = sourceDisplayArea(userId, activityRecord, request);
+
+ return sourceDisplayArea != null ? sourceDisplayArea : fallbackDisplayArea(userId);
}
@VisibleForTesting
@@ -390,4 +383,99 @@
}
return dc.getDefaultTaskDisplayArea();
}
+
+ /**
+ * Calculates the {@link TaskDisplayArea} for the source of the request. The source is
+ * calculated implicitly from the request or the activity record.
+ *
+ * @param userId ID of the current active user
+ * @param activityRecord {@link ActivityRecord} that is to be shown
+ * @param request {@link Request} data for showing the {@link ActivityRecord}
+ * @return {@link TaskDisplayArea} First non {@code null} candidate display area that is allowed
+ * for the user. It is allowed if the display has been added to the profile mapping.
+ */
+ @Nullable
+ private TaskDisplayArea sourceDisplayArea(int userId, @NonNull ActivityRecord activityRecord,
+ @Nullable Request request) {
+ List<WindowProcessController> candidateControllers = candidateControllers(activityRecord,
+ request);
+
+ for (int i = 0; i < candidateControllers.size(); i++) {
+ WindowProcessController controller = candidateControllers.get(i);
+ TaskDisplayArea candidate = controller.getTopActivityDisplayArea();
+ int displayId = candidate != null ? candidate.getDisplayId() : Display.INVALID_DISPLAY;
+ int userForDisplay = mDisplayToProfileUserMapping.get(displayId, UserHandle.USER_NULL);
+ if (userForDisplay == userId) {
+ return candidate;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Calculates a list of {@link WindowProcessController} that can calculate the
+ * {@link TaskDisplayArea} to house the {@link ActivityRecord}. Controllers are calculated since
+ * calculating the display can be expensive. The list is ordered in the
+ * following way
+ * <ol>
+ * <li>Controller for the activity record from the process name and app uid</li>
+ * <li>Controller for the activity that is launching the given record</li>
+ * <li>Controller for the actual process that is launching the record</li>
+ * </ol>
+ *
+ * @param activityRecord {@link ActivityRecord} that is to be shown
+ * @param request {@link Request} data for showing the {@link ActivityRecord}
+ * @return {@link List} of {@link WindowProcessController} ordered by preference to be shown
+ */
+ private List<WindowProcessController> candidateControllers(
+ @NonNull ActivityRecord activityRecord, @Nullable Request request) {
+ WindowProcessController firstController = mAtm.getProcessController(
+ activityRecord.getProcessName(), activityRecord.getUid());
+
+ WindowProcessController secondController = mAtm.getProcessController(
+ activityRecord.getLaunchedFromPid(), activityRecord.getLaunchedFromUid());
+
+ WindowProcessController thirdController = request == null ? null :
+ mAtm.getProcessController(request.realCallingPid, request.realCallingUid);
+
+ List<WindowProcessController> candidates = new ArrayList<>(3);
+
+ if (firstController != null) {
+ candidates.add(firstController);
+ }
+ if (secondController != null) {
+ candidates.add(secondController);
+ }
+ if (thirdController != null) {
+ candidates.add(thirdController);
+ }
+
+ return candidates;
+ }
+
+ /**
+ * Return a {@link TaskDisplayArea} that can be used if a source display area is not found.
+ * First check the default display for the user. If it is absent select the first passenger
+ * display if present. If both are absent return {@code null}
+ *
+ * @param userId ID of the active user
+ * @return {@link TaskDisplayArea} that is recommended when a display area is not specified
+ */
+ @Nullable
+ private TaskDisplayArea fallbackDisplayArea(int userId) {
+ int displayIdForUserProfile = mDefaultDisplayForProfileUser.get(userId,
+ Display.INVALID_DISPLAY);
+ if (displayIdForUserProfile != Display.INVALID_DISPLAY) {
+ int displayId = mDefaultDisplayForProfileUser.get(userId);
+ return getDefaultTaskDisplayAreaOnDisplay(displayId);
+ }
+
+ if (!mPassengerDisplays.isEmpty()) {
+ int displayId = mPassengerDisplays.get(0);
+ return getDefaultTaskDisplayAreaOnDisplay(displayId);
+ }
+
+ return null;
+ }
+
}
diff --git a/tests/src/com/android/server/wm/CarLaunchParamsModifierTest.java b/tests/src/com/android/server/wm/CarLaunchParamsModifierTest.java
index fe4138a..29fb540 100644
--- a/tests/src/com/android/server/wm/CarLaunchParamsModifierTest.java
+++ b/tests/src/com/android/server/wm/CarLaunchParamsModifierTest.java
@@ -24,6 +24,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import android.annotation.UserIdInt;
@@ -57,6 +59,11 @@
import java.util.Arrays;
+/**
+ * Tests for {@link CarLaunchParamsModifier}
+ * Build/Install/Run:
+ * atest CarServicesTest:CarLaunchParamsModifierTest
+ */
@RunWith(AndroidJUnit4.class)
public class CarLaunchParamsModifierTest {
private static final int PASSENGER_DISPLAY_ID_10 = 10;
@@ -176,7 +183,8 @@
mCurrentParams.mPreferredTaskDisplayArea = mModifier
.getDefaultTaskDisplayAreaOnDisplay(display.getDisplayId());
assertThat(mModifier.onCalculate(mTask, mWindowLayout, mActivityRecordActivity,
- mActivityRecordSource, mActivityOptions, 0, mCurrentParams, mOutParams))
+ mActivityRecordSource, mActivityOptions, 0, mCurrentParams, mOutParams,
+ null /* request */))
.isEqualTo(LaunchParamsController.LaunchParamsModifier.RESULT_SKIP);
}
@@ -190,7 +198,8 @@
.getDefaultTaskDisplayAreaOnDisplay(displayAssigned.getDisplayId());
mCurrentParams.mPreferredTaskDisplayArea = requestedTaskDisplayArea;
assertThat(mModifier.onCalculate(mTask, mWindowLayout, mActivityRecordActivity,
- mActivityRecordSource, mActivityOptions, 0, mCurrentParams, mOutParams))
+ mActivityRecordSource, mActivityOptions, 0, mCurrentParams, mOutParams,
+ null /* request */))
.isEqualTo(LaunchParamsController.LaunchParamsModifier.RESULT_DONE);
assertThat(mOutParams.mPreferredTaskDisplayArea).isEqualTo(assignedTaskDisplayArea);
}
@@ -200,7 +209,8 @@
mTask.mUserId = userId;
mCurrentParams.mPreferredTaskDisplayArea = null;
assertThat(mModifier.onCalculate(mTask, mWindowLayout, mActivityRecordActivity,
- mActivityRecordSource, mActivityOptions, 0, mCurrentParams, mOutParams))
+ mActivityRecordSource, mActivityOptions, 0, mCurrentParams, mOutParams,
+ null /* request */))
.isEqualTo(LaunchParamsController.LaunchParamsModifier.RESULT_DONE);
assertThat(mOutParams.mPreferredTaskDisplayArea).isEqualTo(expectedDisplayArea);
}
@@ -209,7 +219,8 @@
mTask.mUserId = userId;
mCurrentParams.mPreferredTaskDisplayArea = null;
assertThat(mModifier.onCalculate(mTask, mWindowLayout, mActivityRecordActivity,
- mActivityRecordSource, mActivityOptions, 0, mCurrentParams, mOutParams))
+ mActivityRecordSource, mActivityOptions, 0, mCurrentParams, mOutParams,
+ null /* request */))
.isEqualTo(LaunchParamsController.LaunchParamsModifier.RESULT_SKIP);
assertThat(mOutParams.mPreferredTaskDisplayArea).isNull();
}
@@ -281,7 +292,7 @@
mDisplay11ForPassenger.getDisplayId()});
final int passengerUserId = 100;
- mModifier.setDisplayAllowlistForUser(passengerUserId,
+ mModifier.setDisplayAllowListForUser(passengerUserId,
new int[]{mDisplay10ForPassenger.getDisplayId()});
assertDisplayIsAllowed(passengerUserId, mDisplay10ForPassenger);
@@ -293,13 +304,13 @@
mDisplay11ForPassenger.getDisplayId()});
int passengerUserId1 = 100;
- mModifier.setDisplayAllowlistForUser(passengerUserId1,
+ mModifier.setDisplayAllowListForUser(passengerUserId1,
new int[]{mDisplay11ForPassenger.getDisplayId()});
assertDisplayIsAllowed(passengerUserId1, mDisplay11ForPassenger);
int passengerUserId2 = 101;
- mModifier.setDisplayAllowlistForUser(passengerUserId2,
+ mModifier.setDisplayAllowListForUser(passengerUserId2,
new int[]{mDisplay11ForPassenger.getDisplayId()});
assertDisplayIsAllowed(passengerUserId2, mDisplay11ForPassenger);
@@ -313,7 +324,7 @@
mDisplay11ForPassenger.getDisplayId()});
final int passengerUserId = 100;
- mModifier.setDisplayAllowlistForUser(
+ mModifier.setDisplayAllowListForUser(
passengerUserId, new int[]{mDisplay10ForPassenger.getDisplayId()});
assertDisplayIsReassigned(passengerUserId, mDisplay0ForDriver, mDisplay10ForPassenger);
@@ -326,7 +337,7 @@
mDisplay11ForPassenger.getDisplayId()});
int passengerUserId = 100;
- mModifier.setDisplayAllowlistForUser(
+ mModifier.setDisplayAllowListForUser(
passengerUserId, new int[]{mDisplay11ForPassenger.getDisplayId()});
assertDisplayIsAllowed(passengerUserId, mDisplay11ForPassenger);
@@ -342,11 +353,11 @@
mDisplay11ForPassenger.getDisplayId()});
int passengerUserId = 100;
- mModifier.setDisplayAllowlistForUser(
+ mModifier.setDisplayAllowListForUser(
passengerUserId, new int[]{mDisplay11ForPassenger.getDisplayId()});
assertDisplayIsAllowed(passengerUserId, mDisplay11ForPassenger);
- mModifier.setDisplayAllowlistForUser(
+ mModifier.setDisplayAllowListForUser(
UserHandle.USER_SYSTEM, new int[]{mDisplay11ForPassenger.getDisplayId()});
assertDisplayIsReassigned(passengerUserId, mDisplay0ForDriver, mDisplay10ForPassenger);
@@ -359,7 +370,7 @@
mDisplay11ForPassenger.getDisplayId()});
final int passengerUserId = 100;
- mModifier.setDisplayAllowlistForUser(passengerUserId,
+ mModifier.setDisplayAllowListForUser(passengerUserId,
new int[]{mDisplay10ForPassenger.getDisplayId(),
mDisplay11ForPassenger.getDisplayId()});
@@ -378,7 +389,7 @@
mDisplay11ForPassenger.getDisplayId()});
final int passengerUserId = 100;
- mModifier.setDisplayAllowlistForUser(passengerUserId,
+ mModifier.setDisplayAllowListForUser(passengerUserId,
new int[]{mDisplay10ForPassenger.getDisplayId(),
mDisplay11ForPassenger.getDisplayId()});
@@ -397,7 +408,7 @@
mDisplay11ForPassenger.getDisplayId()});
final int passengerUserId = 100;
- mModifier.setDisplayAllowlistForUser(passengerUserId,
+ mModifier.setDisplayAllowListForUser(passengerUserId,
new int[]{mDisplay10ForPassenger.getDisplayId(),
mDisplay10ForPassenger.getDisplayId()});
@@ -412,7 +423,7 @@
final int wasDriver = 10;
final int wasPassenger = 11;
mModifier.handleCurrentUserSwitching(wasDriver);
- mModifier.setDisplayAllowlistForUser(wasPassenger,
+ mModifier.setDisplayAllowListForUser(wasPassenger,
new int[]{mDisplay10ForPassenger.getDisplayId(),
mDisplay11ForPassenger.getDisplayId()});
@@ -426,7 +437,7 @@
final int driver = wasPassenger;
final int passenger = wasDriver;
mModifier.handleCurrentUserSwitching(driver);
- mModifier.setDisplayAllowlistForUser(passenger,
+ mModifier.setDisplayAllowListForUser(passenger,
new int[]{mDisplay10ForPassenger.getDisplayId(),
mDisplay11ForPassenger.getDisplayId()});
@@ -453,7 +464,7 @@
public void testPreferSourceForPassenger() {
mModifier.setPassengerDisplays(new int[]{PASSENGER_DISPLAY_ID_10, PASSENGER_DISPLAY_ID_11});
int passengerUserId = 100;
- mModifier.setDisplayAllowlistForUser(passengerUserId,
+ mModifier.setDisplayAllowListForUser(passengerUserId,
new int[]{PASSENGER_DISPLAY_ID_10, PASSENGER_DISPLAY_ID_11});
when(mActivityRecordSource.getDisplayArea()).thenReturn(mDisplayArea11ForPassenger);
@@ -492,4 +503,117 @@
assertNoDisplayIsAssigned(UserHandle.USER_SYSTEM);
}
+
+ @Test
+ public void testSourceDisplayFromProcessDisplayIfAvailable() {
+ int userId = 10;
+ String processName = "processName";
+ int processUid = 11;
+ when(mActivityRecordActivity.getProcessName())
+ .thenReturn(processName);
+ when(mActivityRecordActivity.getUid())
+ .thenReturn(processUid);
+ mModifier.setPassengerDisplays(new int[]{mDisplay11ForPassenger.getDisplayId(),
+ mDisplay10ForPassenger.getDisplayId()});
+ mModifier.setDisplayAllowListForUser(userId,
+ new int[]{mDisplay10ForPassenger.getDisplayId()});
+ WindowProcessController controller = mock(WindowProcessController.class);
+ when(mActivityTaskManagerService.getProcessController(processName, processUid))
+ .thenReturn(controller);
+ when(controller.getTopActivityDisplayArea())
+ .thenReturn(mDisplayArea10ForPassenger);
+ mCurrentParams.mPreferredTaskDisplayArea = null;
+ mTask.mUserId = userId;
+
+ assertThat(mModifier.onCalculate(mTask, mWindowLayout, mActivityRecordActivity,
+ mActivityRecordSource, null, 0, mCurrentParams, mOutParams,
+ null /* request */))
+ .isEqualTo(TaskLaunchParamsModifier.RESULT_DONE);
+ assertThat(mOutParams.mPreferredTaskDisplayArea)
+ .isEqualTo(mDisplayArea10ForPassenger);
+ }
+
+ @Test
+ public void testSourceDisplayFromLaunchingDisplayIfAvailable() {
+ int userId = 10;
+ int launchedFromPid = 1324;
+ int launchedFromUid = 325;
+ when(mActivityRecordActivity.getLaunchedFromPid())
+ .thenReturn(launchedFromPid);
+ when(mActivityRecordActivity.getLaunchedFromUid())
+ .thenReturn(launchedFromUid);
+ mModifier.setPassengerDisplays(new int[]{mDisplay11ForPassenger.getDisplayId(),
+ mDisplay10ForPassenger.getDisplayId()});
+ mModifier.setDisplayAllowListForUser(userId,
+ new int[]{mDisplay10ForPassenger.getDisplayId()});
+ WindowProcessController controller = mock(WindowProcessController.class);
+ when(mActivityTaskManagerService.getProcessController(launchedFromPid, launchedFromUid))
+ .thenReturn(controller);
+ when(controller.getTopActivityDisplayArea())
+ .thenReturn(mDisplayArea10ForPassenger);
+ mCurrentParams.mPreferredTaskDisplayArea = null;
+ mTask.mUserId = 10;
+
+ assertThat(mModifier.onCalculate(mTask, mWindowLayout, mActivityRecordActivity,
+ mActivityRecordSource, null, 0, mCurrentParams, mOutParams,
+ null /* request */))
+ .isEqualTo(TaskLaunchParamsModifier.RESULT_DONE);
+ assertThat(mOutParams.mPreferredTaskDisplayArea)
+ .isEqualTo(mDisplayArea10ForPassenger);
+ }
+
+ @Test
+ public void testSourceDisplayFromCallingDisplayIfAvailable() {
+ int userId = 10;
+ ActivityStarter.Request request = fakeRequest();
+ mModifier.setPassengerDisplays(new int[]{mDisplay11ForPassenger.getDisplayId(),
+ mDisplay10ForPassenger.getDisplayId()});
+ mModifier.setDisplayAllowListForUser(userId,
+ new int[]{mDisplay10ForPassenger.getDisplayId()});
+ WindowProcessController controller = mock(WindowProcessController.class);
+ when(mActivityTaskManagerService.getProcessController(request.realCallingPid,
+ request.realCallingUid))
+ .thenReturn(controller);
+ when(controller.getTopActivityDisplayArea())
+ .thenReturn(mDisplayArea10ForPassenger);
+ mCurrentParams.mPreferredTaskDisplayArea = null;
+ mTask.mUserId = userId;
+
+ assertThat(mModifier.onCalculate(mTask, mWindowLayout, mActivityRecordActivity,
+ mActivityRecordSource, null, 0, mCurrentParams, mOutParams,
+ request))
+ .isEqualTo(TaskLaunchParamsModifier.RESULT_DONE);
+ assertThat(mOutParams.mPreferredTaskDisplayArea)
+ .isEqualTo(mDisplayArea10ForPassenger);
+ }
+
+ @Test
+ public void testSourceDisplayIgnoredIfNotInAllowList() {
+ ActivityStarter.Request request = fakeRequest();
+ mModifier.setPassengerDisplays(new int[]{mDisplay11ForPassenger.getDisplayId(),
+ mDisplay10ForPassenger.getDisplayId()});
+ WindowProcessController controller = mock(WindowProcessController.class);
+ when(mActivityTaskManagerService.getProcessController(anyString(), anyInt()))
+ .thenReturn(controller);
+ when(mActivityTaskManagerService.getProcessController(anyInt(), anyInt()))
+ .thenReturn(controller);
+ when(controller.getTopActivityDisplayArea())
+ .thenReturn(mDisplayArea10ForPassenger);
+ mCurrentParams.mPreferredTaskDisplayArea = null;
+ mTask.mUserId = 10;
+
+ assertThat(mModifier.onCalculate(mTask, mWindowLayout, mActivityRecordActivity,
+ mActivityRecordSource, null, 0, mCurrentParams, mOutParams,
+ request))
+ .isEqualTo(TaskLaunchParamsModifier.RESULT_DONE);
+ assertThat(mOutParams.mPreferredTaskDisplayArea)
+ .isEqualTo(mDisplayArea11ForPassenger);
+ }
+
+ private ActivityStarter.Request fakeRequest() {
+ ActivityStarter.Request request = new ActivityStarter.Request();
+ request.realCallingPid = 1324;
+ request.realCallingUid = 235;
+ return request;
+ }
}