Add a flag to protect headless user 0 multi-user model.
Test: unit test
Bug: 80305146
Change-Id: Ibb029072756e29b57c747152bb779a1037aca753
diff --git a/car-lib/src/android/car/user/CarUserManagerHelper.java b/car-lib/src/android/car/user/CarUserManagerHelper.java
index ece0ac2..45d2c7f 100644
--- a/car-lib/src/android/car/user/CarUserManagerHelper.java
+++ b/car-lib/src/android/car/user/CarUserManagerHelper.java
@@ -25,6 +25,7 @@
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
@@ -46,6 +47,7 @@
*/
public class CarUserManagerHelper {
private static final String TAG = "CarUserManagerHelper";
+ private static final String HEADLESS_SYSTEM_USER = "android.car.systemuser.headless";
private final Context mContext;
private final UserManager mUserManager;
private final ActivityManager mActivityManager;
@@ -88,6 +90,15 @@
}
/**
+ * Returns {@code true} if the system is in the headless user 0 model.
+ *
+ * @return {@boolean true} if headless system user.
+ */
+ public boolean isHeadlessSystemUser() {
+ return SystemProperties.getBoolean(HEADLESS_SYSTEM_USER, false);
+ }
+
+ /**
* Gets UserInfo for the system user.
*
* @return {@link UserInfo} for the system user.
@@ -145,7 +156,11 @@
* @return List of {@code UserInfo} for each user that is not the foreground user.
*/
public List<UserInfo> getAllSwitchableUsers() {
- return getAllUsersExceptSystemUserAndSpecifiedUser(getCurrentForegroundUserId());
+ if (isHeadlessSystemUser()) {
+ return getAllUsersExceptSystemUserAndSpecifiedUser(getCurrentForegroundUserId());
+ } else {
+ return getAllUsersExceptSpecifiedUser(getCurrentForegroundUserId());
+ }
}
/**
@@ -154,7 +169,11 @@
* @return List of {@code UserInfo} for users that associated with a real person.
*/
public List<UserInfo> getAllUsers() {
- return getAllUsersExceptSystemUserAndSpecifiedUser(UserHandle.USER_SYSTEM);
+ if (isHeadlessSystemUser()) {
+ return getAllUsersExceptSystemUserAndSpecifiedUser(UserHandle.USER_SYSTEM);
+ } else {
+ return mUserManager.getUsers(/* excludeDying= */true);
+ }
}
/**
@@ -163,17 +182,36 @@
* @return List of {@code UserInfo} for users that associated with a real person.
*/
public List<UserInfo> getAllUsersIncludingSystemUser() {
- return mUserManager.getUsers(/*excludeDying=*/true);
+ return mUserManager.getUsers(/* excludeDying= */true);
+ }
+
+ /**
+ * Get all the users except the one with userId passed in.
+ *
+ * @param userId of the user not to be returned.
+ * @return All users other than user with userId.
+ */
+ private List<UserInfo> getAllUsersExceptSpecifiedUser(int userId) {
+ List<UserInfo> users = mUserManager.getUsers(/* excludeDying= */true);
+
+ for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
+ UserInfo userInfo = iterator.next();
+ if (userInfo.id == userId) {
+ // Remove user with userId from the list.
+ iterator.remove();
+ }
+ }
+ return users;
}
/**
* Get all the users except system user and the one with userId passed in.
*
* @param userId of the user not to be returned.
- * @return All users other than user with userId.
+ * @return All users other than system user and user with userId.
*/
private List<UserInfo> getAllUsersExceptSystemUserAndSpecifiedUser(int userId) {
- List<UserInfo> users = mUserManager.getUsers(/*excludeDying=*/true);
+ List<UserInfo> users = mUserManager.getUsers(/* excludeDying= */true);
for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
UserInfo userInfo = iterator.next();
@@ -380,6 +418,20 @@
}
/**
+ * Switches (logs in) to another user given user id.
+ *
+ * @param id User id to switch to.
+ * @return {@code true} if user switching succeed.
+ */
+ public boolean switchToUserId(int id) {
+ if (id == UserHandle.USER_SYSTEM && isHeadlessSystemUser()) {
+ // System User doesn't associate with real person, can not be switched to.
+ return false;
+ }
+ return mActivityManager.switchUser(id);
+ }
+
+ /**
* Switches (logs in) to another user.
*
* @param userInfo User to switch to.
@@ -493,14 +545,6 @@
return bitmap;
}
- private boolean switchToUserId(int id) {
- if (id == UserHandle.USER_SYSTEM) {
- // System User doesn't associate with real person, can not be switched to.
- return false;
- }
- return mActivityManager.switchUser(id);
- }
-
private void unregisterReceiver() {
mContext.unregisterReceiver(mUserChangeReceiver);
}
diff --git a/tests/carservice_unit_test/src/com/android/car/CarUserManagerTest.java b/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
similarity index 91%
rename from tests/carservice_unit_test/src/com/android/car/CarUserManagerTest.java
rename to tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
index ff24b8e..3d9cce6 100644
--- a/tests/carservice_unit_test/src/com/android/car/CarUserManagerTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
@@ -31,6 +31,7 @@
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Handler;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.test.InstrumentationRegistry;
@@ -57,7 +58,7 @@
* 4. {@link CarUserManagerHelper.OnUsersUpdateListener} registers a listener for user updates.
*/
@RunWith(AndroidJUnit4.class)
-public class CarUserManagerTest {
+public class CarUserManagerHelperTest {
@Mock
private Context mContext;
@Mock
@@ -101,7 +102,8 @@
// System user will not be returned when calling get all users.
@Test
- public void testGetAllUsers_NotReturnSystemUser() {
+ public void testHeadlessUser0GetAllUsers_NotReturnSystemUser() {
+ SystemProperties.set("android.car.systemuser.headless", "true");
UserInfo otherUser1 = createUserInfoForId(10);
UserInfo otherUser2 = createUserInfoForId(11);
UserInfo otherUser3 = createUserInfoForId(12);
@@ -121,7 +123,8 @@
}
@Test
- public void testGetAllUsersWithActiveForegroundUser_NotReturnSystemUser() {
+ public void testHeadlessUser0GetAllUsersWithActiveForegroundUser_NotReturnSystemUser() {
+ SystemProperties.set("android.car.systemuser.headless", "true");
mCurrentProcessUser = createUserInfoForId(10);
UserInfo otherUser1 = createUserInfoForId(11);
@@ -142,7 +145,6 @@
.containsExactly(mCurrentProcessUser, otherUser1, otherUser2, otherUser3);
}
- // Get all users should exclude system user by default.
@Test
public void testGetAllSwitchableUsers() {
UserInfo user1 = createUserInfoForId(10);
@@ -170,6 +172,30 @@
assertThat(mHelper.getAllSwitchableUsers()).contains(user3);
}
+ // Get all users for headless user 0 model should exclude system user by default.
+ @Test
+ public void testHeadlessUser0GetAllSwitchableUsers() {
+ SystemProperties.set("android.car.systemuser.headless", "true");
+ UserInfo user1 = createUserInfoForId(10);
+ UserInfo user2 = createUserInfoForId(11);
+ UserInfo user3 = createUserInfoForId(12);
+
+ List<UserInfo> testUsers = new ArrayList<>();
+ testUsers.add(mSystemUser);
+ testUsers.add(user1);
+ testUsers.add(user2);
+ testUsers.add(user3);
+
+ when(mUserManager.getUsers(true)).thenReturn(new ArrayList<>(testUsers));
+
+ // Should return all 3 non-system users.
+ assertThat(mHelper.getAllUsers()).hasSize(3);
+
+ when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(user1);
+ // Should return user 10, 11 and 12.
+ assertThat(mHelper.getAllSwitchableUsers()).containsExactly(user1, user2, user3);
+ }
+
@Test
public void testUserCanBeRemoved() {
UserInfo testInfo = new UserInfo();
diff --git a/tests/robotests/src/com/android/car/users/CarUserManagerRoboTest.java b/tests/robotests/src/com/android/car/users/CarUserManagerHelperRoboTest.java
similarity index 93%
rename from tests/robotests/src/com/android/car/users/CarUserManagerRoboTest.java
rename to tests/robotests/src/com/android/car/users/CarUserManagerHelperRoboTest.java
index 977ee7c..9c39445 100644
--- a/tests/robotests/src/com/android/car/users/CarUserManagerRoboTest.java
+++ b/tests/robotests/src/com/android/car/users/CarUserManagerHelperRoboTest.java
@@ -43,7 +43,7 @@
@RunWith(CarServiceRobolectricTestRunner.class)
@Config(shadows = { ShadowActivityManager.class,
ShadowUserHandle.class, ShadowUserManager.class})
-public class CarUserManagerRoboTest {
+public class CarUserManagerHelperRoboTest {
@Mock
private Context mContext;
@@ -95,7 +95,7 @@
}
@Test
- public void testGetAllUsersExcludesCurrentProcessUser() {
+ public void testGetAllUsers() {
int currentProcessUserId = 12;
ShadowUserManager userManager = ShadowUserManager.getShadow();
userManager.setCurrentUser(currentProcessUserId);
@@ -111,10 +111,14 @@
userManager.addUserInfo(otherUser1);
userManager.addUserInfo(otherUser2);
- // Should return 3 users that don't have currentProcessUser id.
- assertThat(mHelper.getAllUsers()).hasSize(3);
- assertThat(mHelper.getAllUsers())
- .containsExactly(currentProcessUser, otherUser1, otherUser2);
+ if (mHelper.isHeadlessSystemUser()) {
+ // Should return 3 users that don't have system user id.
+ assertThat(mHelper.getAllUsers())
+ .containsExactly(currentProcessUser, otherUser1, otherUser2);
+ } else {
+ assertThat(mHelper.getAllUsers())
+ .containsExactly(systemUser, currentProcessUser, otherUser1, otherUser2);
+ }
}
@Test