Refactored CarUserService calls to removeUserOrSetEphemeral().
Test: atest com.android.car.user.CarUserServiceTest \
android.car.apitest.CarDevicePolicyManagerTest#testRemoveUser_whenDisallowed
Fixes: 170887769
Change-Id: If797ace64c0fa0262116f649212bbcb1d61e2046
diff --git a/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java b/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java
index efdd4e9..150ab73 100644
--- a/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java
+++ b/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java
@@ -24,13 +24,10 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
-import android.car.test.util.AndroidHelper;
import android.car.test.util.UserTestingHelper;
import android.car.test.util.UserTestingHelper.UserInfoBuilder;
import android.car.test.util.Visitor;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.pm.UserInfo.UserInfoFlag;
@@ -40,6 +37,7 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.UserManager.RemoveResult;
import android.util.Log;
import java.util.List;
@@ -178,44 +176,19 @@
}
/**
- * Mocks a successful call to {@code UserManager#removeUserOrSetEphemeral(int)}.
- */
- public static void mockUmRemoveUserOrSetEphemeral(@NonNull UserManager um,
- @NonNull UserInfo user) {
- mockUmRemoveUserOrSetEphemeral(um, user, /* listener= */ null);
- }
-
- /**
- * Mocks a successful call to {@code UserManager#removeUserOrSetEphemeral(int)}, including the
- * respective {@code receiver} notification.
- */
- public static void mockUmRemoveUserOrSetEphemeral(@NonNull Context context,
- @NonNull UserManager um, @NonNull BroadcastReceiver receiver, @NonNull UserInfo user) {
- mockUmRemoveUserOrSetEphemeral(um, user, (u) -> {
- int userId = u.id;
- Intent intent = new Intent(Intent.ACTION_USER_REMOVED);
- intent.putExtra(Intent.EXTRA_USER_ID, userId);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
- intent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
- Log.v(TAG, "mockUmRemoveUserOrSetEphemeral(): broadcasting "
- + AndroidHelper.toString(intent) + " to " + receiver);
- receiver.onReceive(context, intent);
- });
- }
-
- /**
* Mocks a successful call to {@code UserManager#removeUserOrSetEphemeral(int)}, and notifies
* {@code listener} when it's called.
*/
public static void mockUmRemoveUserOrSetEphemeral(@NonNull UserManager um,
- @NonNull UserInfo user, @Nullable Visitor<UserInfo> listener) {
+ @NonNull UserInfo user, boolean evenWhenDisallowed, @RemoveResult int result,
+ @Nullable Visitor<UserInfo> listener) {
int userId = user.id;
- when(um.removeUserOrSetEphemeral(userId)).thenAnswer((inv) -> {
+ when(um.removeUserOrSetEphemeral(userId, evenWhenDisallowed)).thenAnswer((inv) -> {
if (listener != null) {
Log.v(TAG, "mockUmRemoveUserOrSetEphemeral(" + user + "): notifying " + listener);
listener.visit(user);
}
- return UserManager.REMOVE_RESULT_REMOVED;
+ return result;
});
}
diff --git a/service/src/com/android/car/user/CarUserService.java b/service/src/com/android/car/user/CarUserService.java
index 5f3daf5..e05be5e 100644
--- a/service/src/com/android/car/user/CarUserService.java
+++ b/service/src/com/android/car/user/CarUserService.java
@@ -1144,7 +1144,12 @@
// First remove user from android and then remove from HAL because HAL remove user is one
// way call.
- int result = mUserManager.removeUserOrSetEphemeral(userId);
+ // TODO(b/170887769): rename hasCallerRestrictions to fromCarDevicePolicyManager (or use an
+ // int / enum to indicate if it's called from CarUserManager or CarDevicePolicyManager), as
+ // it's counter-intuitive that it's "allowed even when disallowed" when it
+ // "has caller restrictions"
+ boolean evenWhenDisallowed = hasCallerRestrictions;
+ int result = mUserManager.removeUserOrSetEphemeral(userId, evenWhenDisallowed);
if (result == UserManager.REMOVE_RESULT_ERROR) {
return logAndGetResults(userId, UserRemovalResult.STATUS_ANDROID_FAILURE);
}
diff --git a/tests/android_car_api_test/src/android/car/apitest/CarApiTestBase.java b/tests/android_car_api_test/src/android/car/apitest/CarApiTestBase.java
index f16c689..624443c 100644
--- a/tests/android_car_api_test/src/android/car/apitest/CarApiTestBase.java
+++ b/tests/android_car_api_test/src/android/car/apitest/CarApiTestBase.java
@@ -84,7 +84,7 @@
private Car mCar;
private CarUserManager mCarUserManager;
- private UserManager mUserManager;
+ protected UserManager mUserManager;
protected final DefaultServiceConnectionListener mConnectionListener =
new DefaultServiceConnectionListener();
@@ -92,7 +92,7 @@
private final List<Integer> mUsersToRemove = new ArrayList<>();
@Before
- public final void connectToCar() throws Exception {
+ public final void setFixturesAndConnectToCar() throws Exception {
mCar = Car.createCar(getContext(), mConnectionListener);
mCar.connect();
mConnectionListener.waitForConnection(DEFAULT_WAIT_TIMEOUT_MS);
diff --git a/tests/android_car_api_test/src/android/car/apitest/CarDevicePolicyManagerTest.java b/tests/android_car_api_test/src/android/car/apitest/CarDevicePolicyManagerTest.java
index de74561..e75be34 100644
--- a/tests/android_car_api_test/src/android/car/apitest/CarDevicePolicyManagerTest.java
+++ b/tests/android_car_api_test/src/android/car/apitest/CarDevicePolicyManagerTest.java
@@ -32,6 +32,7 @@
import android.content.pm.UserInfo;
import android.os.PowerManager;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Log;
import org.junit.Before;
@@ -68,6 +69,16 @@
}
@Test
+ public void testRemoveUser_whenDisallowed() throws Exception {
+ try {
+ testRemoveUser();
+ } finally {
+ mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, false,
+ UserHandle.SYSTEM);
+ }
+ }
+
+ @Test
public void testRemoveUser_currentUserSetEphemeral() throws Exception {
int startUser = ActivityManager.getCurrentUser();
UserInfo user = createUser(
diff --git a/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java b/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
index e358129..7d84b30 100644
--- a/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
@@ -36,6 +36,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -103,6 +104,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.UserManager.RemoveResult;
import android.sysprop.CarProperties;
import android.util.Log;
import android.util.SparseArray;
@@ -785,12 +787,11 @@
UserInfo currentUser = mRegularUser;
mockExistingUsersAndCurrentUser(mExistingUsers, currentUser);
UserInfo removeUser = mRegularUser;
- when(mMockedUserManager.removeUserOrSetEphemeral(removeUser.id)).thenReturn(
- UserManager.REMOVE_RESULT_SET_EPHEMERAL);
+ mockRemoveUserNoCallback(removeUser, UserManager.REMOVE_RESULT_SET_EPHEMERAL);
UserRemovalResult result = mCarUserService.removeUser(removeUser.id);
- assertThat(result.getStatus()).isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL);
+ assertUserRemovalResultStatus(result, UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL);
assertNoHalUserRemoval();
}
@@ -799,13 +800,11 @@
UserInfo currentUser = mRegularUser;
mockExistingUsersAndCurrentUser(mExistingUsers, currentUser);
UserInfo removeUser = mRegularUser;
- when(mMockedUserManager.removeUserOrSetEphemeral(removeUser.id)).thenReturn(
- UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED);
- mockRemoveUser(removeUser);
+ mockRemoveUser(removeUser, UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED);
UserRemovalResult result = mCarUserService.removeUser(removeUser.id);
- assertThat(result.getStatus()).isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL);
+ assertUserRemovalResultStatus(result, UserRemovalResult.STATUS_SUCCESSFUL);
assertHalRemove(currentUser, removeUser);
}
@@ -815,14 +814,13 @@
List<UserInfo> existingUsers = Arrays.asList(mAdminUser, mRegularUser);
mockExistingUsersAndCurrentUser(existingUsers, currentUser);
UserInfo removeUser = mAdminUser;
- when(mMockedUserManager.removeUserOrSetEphemeral(removeUser.id)).thenReturn(
- UserManager.REMOVE_RESULT_SET_EPHEMERAL);
+ mockRemoveUserNoCallback(removeUser, UserManager.REMOVE_RESULT_SET_EPHEMERAL);
UserRemovalResult result = mCarUserService.removeUser(mAdminUser.id,
NO_CALLER_RESTRICTIONS);
- assertThat(result.getStatus())
- .isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_SET_EPHEMERAL);
+ assertUserRemovalResultStatus(result,
+ UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_SET_EPHEMERAL);
assertNoHalUserRemoval();
}
@@ -831,8 +829,7 @@
UserRemovalResult result = mCarUserService.removeUser(15,
NO_CALLER_RESTRICTIONS);
- assertThat(result.getStatus())
- .isEqualTo(UserRemovalResult.STATUS_USER_DOES_NOT_EXIST);
+ assertUserRemovalResultStatus(result, UserRemovalResult.STATUS_USER_DOES_NOT_EXIST);
}
@Test
@@ -847,8 +844,8 @@
UserRemovalResult result = mCarUserService.removeUser(mAdminUser.id,
NO_CALLER_RESTRICTIONS);
- assertThat(result.getStatus())
- .isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED);
+ assertUserRemovalResultStatus(result,
+ UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED);
assertHalRemove(currentUser, removeUser);
}
@@ -864,7 +861,7 @@
UserRemovalResult result = mCarUserService.removeUser(removeUser.id,
NO_CALLER_RESTRICTIONS);
- assertThat(result.getStatus()).isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL);
+ assertUserRemovalResultStatus(result, UserRemovalResult.STATUS_SUCCESSFUL);
assertHalRemove(currentUser, removeUser);
}
@@ -878,7 +875,7 @@
UserRemovalResult result = mCarUserService.removeUser(removeUser.id,
NO_CALLER_RESTRICTIONS);
- assertThat(result.getStatus()).isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL);
+ assertUserRemovalResultStatus(result, UserRemovalResult.STATUS_SUCCESSFUL);
assertHalRemove(currentUser, removeUser);
}
@@ -892,7 +889,7 @@
UserRemovalResult result = mCarUserService.removeUser(removeUser.id,
NO_CALLER_RESTRICTIONS);
- assertThat(result.getStatus()).isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL);
+ assertUserRemovalResultStatus(result, UserRemovalResult.STATUS_SUCCESSFUL);
verify(mUserHal, never()).removeUser(any());
}
@@ -900,13 +897,12 @@
public void testRemoveUser_androidFailure() throws Exception {
mockExistingUsersAndCurrentUser(mAdminUser);
int targetUserId = mRegularUser.id;
- when(mMockedUserManager.removeUserOrSetEphemeral(targetUserId)).thenReturn(
- UserManager.REMOVE_RESULT_ERROR);
+ mockRemoveUser(new UserInfoBuilder(targetUserId).build(), UserManager.REMOVE_RESULT_ERROR);
UserRemovalResult result = mCarUserService.removeUser(targetUserId,
NO_CALLER_RESTRICTIONS);
- assertThat(result.getStatus()).isEqualTo(UserRemovalResult.STATUS_ANDROID_FAILURE);
+ assertUserRemovalResultStatus(result, UserRemovalResult.STATUS_ANDROID_FAILURE);
}
@Test
@@ -915,7 +911,7 @@
UserInfo removeUser = mAdminUser;
mockGetCallingUserHandle(currentUser.id);
mockExistingUsersAndCurrentUser(mExistingUsers, currentUser);
- mockRemoveUser(removeUser);
+ mockRemoveUser(removeUser, /* evenWhenDisallowed= */ true);
assertThrows(SecurityException.class, () -> mCarUserService.removeUser(removeUser.id,
HAS_CALLER_RESTRICTIONS));
@@ -927,7 +923,7 @@
UserInfo removeUser = mAnotherRegularUser;
mockGetCallingUserHandle(currentUser.id);
mockExistingUsersAndCurrentUser(mExistingUsers, currentUser);
- mockRemoveUser(removeUser);
+ mockRemoveUser(removeUser, /* evenWhenDisallowed= */ true);
assertThrows(SecurityException.class, () -> mCarUserService.removeUser(removeUser.id,
HAS_CALLER_RESTRICTIONS));
@@ -939,14 +935,13 @@
UserInfo removeUser = mRegularUser;
mockGetCallingUserHandle(currentUser.id);
mockExistingUsersAndCurrentUser(mExistingUsers, currentUser);
- when(mMockedUserManager.removeUserOrSetEphemeral(removeUser.id)).thenReturn(
+ mockRemoveUserNoCallback(removeUser, /* evenWhenDisallowed= */ true,
UserManager.REMOVE_RESULT_SET_EPHEMERAL);
UserRemovalResult result = mCarUserService.removeUser(removeUser.id,
HAS_CALLER_RESTRICTIONS);
- assertThat(result.getStatus())
- .isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL);
+ assertUserRemovalResultStatus(result, UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL);
assertNoHalUserRemoval();
}
@@ -956,13 +951,13 @@
UserInfo removeUser = mAnotherAdminUser;
mockGetCallingUserHandle(currentUser.id);
mockExistingUsersAndCurrentUser(mExistingUsers, currentUser);
- mockRemoveUser(removeUser);
+ mockRemoveUser(removeUser, /* evenWhenDisallowed= */ true);
UserRemovalResult result = mCarUserService.removeUser(removeUser.id,
HAS_CALLER_RESTRICTIONS);
- assertThat(result.getStatus()).isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL);
- assertHalRemove(currentUser, removeUser);
+ assertUserRemovalResultStatus(result, UserRemovalResult.STATUS_SUCCESSFUL);
+ assertHalRemove(currentUser, removeUser, /* evenWhenDisallowed= */ true);
}
@Test
@@ -971,13 +966,13 @@
UserInfo removeUser = mRegularUser;
mockGetCallingUserHandle(currentUser.id);
mockExistingUsersAndCurrentUser(mExistingUsers, currentUser);
- mockRemoveUser(removeUser);
+ mockRemoveUser(removeUser, /* evenWhenDisallowed= */ true);
UserRemovalResult result = mCarUserService.removeUser(removeUser.id,
HAS_CALLER_RESTRICTIONS);
- assertThat(result.getStatus()).isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL);
- assertHalRemove(currentUser, removeUser);
+ assertUserRemovalResultStatus(result, UserRemovalResult.STATUS_SUCCESSFUL);
+ assertHalRemove(currentUser, removeUser, /* evenWhenDisallowed= */ true);
}
@Test
@@ -986,14 +981,13 @@
UserInfo removeUser = mAdminUser;
mockGetCallingUserHandle(currentUser.id);
mockExistingUsersAndCurrentUser(mExistingUsers, currentUser);
- when(mMockedUserManager.removeUserOrSetEphemeral(removeUser.id)).thenReturn(
+ mockRemoveUserNoCallback(removeUser, /* evenWhenDisallowed= */ true,
UserManager.REMOVE_RESULT_SET_EPHEMERAL);
UserRemovalResult result = mCarUserService.removeUser(removeUser.id,
HAS_CALLER_RESTRICTIONS);
- assertThat(result.getStatus())
- .isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL);
+ assertUserRemovalResultStatus(result, UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL);
assertNoHalUserRemoval();
}
@@ -2211,10 +2205,33 @@
}
private void mockRemoveUser(@NonNull UserInfo user) {
- mockUmRemoveUserOrSetEphemeral(mMockedUserManager, user,
+ mockRemoveUser(user, UserManager.REMOVE_RESULT_REMOVED);
+ }
+
+ private void mockRemoveUser(@NonNull UserInfo user, @RemoveResult int result) {
+ mockRemoveUser(user, /* evenWhenDisallowed= */ false, result);
+ }
+
+ private void mockRemoveUser(@NonNull UserInfo user, boolean evenWhenDisallowed) {
+ mockRemoveUser(user, evenWhenDisallowed, UserManager.REMOVE_RESULT_REMOVED);
+ }
+
+ private void mockRemoveUser(@NonNull UserInfo user, boolean evenWhenDisallowed,
+ @RemoveResult int result) {
+ mockUmRemoveUserOrSetEphemeral(mMockedUserManager, user, evenWhenDisallowed, result,
(u) -> mCarUserService.onUserRemoved(u));
}
+ private void mockRemoveUserNoCallback(@NonNull UserInfo user, @RemoveResult int result) {
+ mockRemoveUserNoCallback(user, /* evenWhenDisallowed= */ false, result);
+ }
+
+ private void mockRemoveUserNoCallback(@NonNull UserInfo user, boolean evenWhenDisallowed,
+ @RemoveResult int result) {
+ mockUmRemoveUserOrSetEphemeral(mMockedUserManager, user, evenWhenDisallowed, result,
+ /* listener= */ null);
+ }
+
private void mockHalGetInitialInfo(@UserIdInt int currentUserId,
@NonNull InitialUserInfoResponse response) {
UsersInfo usersInfo = newUsersInfo(currentUserId);
@@ -2456,7 +2473,7 @@
}
private void verifyNoUserRemoved() {
- verify(mMockedUserManager, never()).removeUserOrSetEphemeral(anyInt());
+ verify(mMockedUserManager, never()).removeUserOrSetEphemeral(anyInt(), anyBoolean());
verify(mMockedUserManager, never()).removeUser(anyInt());
}
@@ -2582,7 +2599,12 @@
}
private void assertHalRemove(@NonNull UserInfo currentUser, @NonNull UserInfo removeUser) {
- verify(mMockedUserManager).removeUserOrSetEphemeral(removeUser.id);
+ assertHalRemove(currentUser, removeUser, /* evenWhenDisallowed= */ false);
+ }
+
+ private void assertHalRemove(@NonNull UserInfo currentUser, @NonNull UserInfo removeUser,
+ boolean evenWhenDisallowed) {
+ verify(mMockedUserManager).removeUserOrSetEphemeral(removeUser.id, evenWhenDisallowed);
ArgumentCaptor<RemoveUserRequest> requestCaptor =
ArgumentCaptor.forClass(RemoveUserRequest.class);
verify(mUserHal).removeUser(requestCaptor.capture());
@@ -2592,6 +2614,16 @@
assertThat(request.usersInfo.currentUser.userId).isEqualTo(currentUser.id);
}
+ private void assertUserRemovalResultStatus(UserRemovalResult result,
+ @UserRemovalResult.Status int expectedStatus) {
+ int actualStatus = result.getStatus();
+ if (actualStatus != expectedStatus) {
+ fail(String.format("wrong UserRemovalResult: expected %s, got %s",
+ UserRemovalResult.statusToString(expectedStatus),
+ UserRemovalResult.statusToString(actualStatus)));
+ }
+ }
+
@NonNull
private static SwitchUserRequest isSwitchUserRequest(int requestId,
@UserIdInt int currentUserId, @UserIdInt int targetUserId) {