Loading src/com/android/settings/supervision/ConfirmSupervisionCredentialsActivity.kt +10 −3 Original line number Diff line number Diff line Loading @@ -122,9 +122,11 @@ class ConfirmSupervisionCredentialsActivity : FragmentActivity() { getResultLauncher.launch(setupIntent) return } val authController = SupervisionAuthController.getInstance(this) if (!authController.isSessionActive(taskId)) { val forceConfirmation = intent.getBooleanExtra(EXTRA_FORCE_CONFIRMATION, false) if ( forceConfirmation || !SupervisionAuthController.getInstance(this).isSessionActive(taskId) ) { val activityManager = getSystemService(ActivityManager::class.java) if (!activityManager.startProfile(supervisingUser)) { errorHandler("Unable to start supervising user, cannot verify credentials.") Loading Loading @@ -213,4 +215,9 @@ class ConfirmSupervisionCredentialsActivity : FragmentActivity() { setResult(RESULT_CANCELED) finish() } companion object { // If true, force confirmation of supervision credentials, regardless of active auth session @VisibleForTesting const val EXTRA_FORCE_CONFIRMATION = "force_confirmation" } } tests/robotests/src/com/android/settings/supervision/ConfirmSupervisionCredentialsActivityTest.kt +48 −16 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.app.supervision.SupervisionManager import android.app.supervision.SupervisionRecoveryInfo import android.app.supervision.SupervisionRecoveryInfo.STATE_PENDING import android.content.Context import android.content.Intent import android.content.pm.UserInfo import android.hardware.biometrics.BiometricManager import android.hardware.biometrics.PromptContentViewWithMoreOptionsButton Loading @@ -34,6 +35,7 @@ import android.os.UserManager.USER_TYPE_PROFILE_SUPERVISING import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.R import com.android.settings.supervision.ConfirmSupervisionCredentialsActivity.Companion.EXTRA_FORCE_CONFIRMATION import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test Loading Loading @@ -76,22 +78,7 @@ class ConfirmSupervisionCredentialsActivityTest { @Before fun setUp() { ShadowRoleManager.reset() // Note, we have to use ActivityController (instead of ActivityScenario) in order to access // the activity before it is created, so we can set up various mocked responses before they // are referenced in onCreate. mActivityController = Robolectric.buildActivity(ConfirmSupervisionCredentialsActivity::class.java) mActivity = mActivityController.get() shadowActivity = shadowOf(mActivity) shadowActivity.setCallingPackage(callingPackage) shadowKeyguardManager = shadowOf(mActivity.getSystemService(KeyguardManager::class.java)) Shadow.extract<ShadowContextImpl>(mActivity.baseContext).apply { setSystemService(Context.ACTIVITY_SERVICE, mockActivityManager) setSystemService(Context.SUPERVISION_SERVICE, mockSupervisionManager) setSystemService(Context.USER_SERVICE, mockUserManager) } setUpActivity(forceConfirm = false) SupervisionAuthController.sInstance = null } Loading Loading @@ -153,6 +140,25 @@ class ConfirmSupervisionCredentialsActivityTest { assertThat(shadowActivity.resultCode).isEqualTo(Activity.RESULT_OK) } @Test fun onCreate_authSessionActive_forceConfirmation_doesNotFinish() { ShadowRoleManager.addRoleHolder(ROLE_SYSTEM_SUPERVISION, callingPackage, currentUser) mockUserManager.stub { on { users } doReturn listOf(SUPERVISING_USER_INFO) } mockActivityManager.stub { on { startProfile(any()) } doReturn true } shadowKeyguardManager.setIsDeviceSecure(SUPERVISING_USER_ID, true) SupervisionAuthController.getInstance(context).startSession(mActivity.taskId) setUpActivity(forceConfirm = true) mActivityController.setup() assertThat(mActivity.isFinishing).isFalse() // Ensure that the supervising profile is started val userCaptor = argumentCaptor<UserHandle>() verify(mockActivityManager).startProfile(userCaptor.capture()) assert(userCaptor.lastValue.identifier == SUPERVISING_USER_ID) } @Test @Config(sdk = [Build.VERSION_CODES.BAKLAVA]) fun onCreate_callerIsSystemUid_doesNotFinish() { Loading Loading @@ -212,6 +218,7 @@ class ConfirmSupervisionCredentialsActivityTest { .isInstanceOf(PromptContentViewWithMoreOptionsButton::class.java) } @Test fun getBiometricPrompt_recoveryInfoEmpty_noMoreOptionsButton() { whenever(mockSupervisionManager.supervisionRecoveryInfo).thenReturn(null) Loading @@ -225,6 +232,7 @@ class ConfirmSupervisionCredentialsActivityTest { assertThat(biometricPrompt.contentView).isNull() } @Test fun onAuthenticationSucceeded_startsAuthSession_returnsResultOK() { mockUserManager.stub { on { users } doReturn listOf(SUPERVISING_USER_INFO) } shadowKeyguardManager.setIsDeviceSecure(SUPERVISING_USER_ID, true) Loading @@ -236,6 +244,30 @@ class ConfirmSupervisionCredentialsActivityTest { assertThat(shadowActivity.resultCode).isEqualTo(Activity.RESULT_OK) } private fun setUpActivity(forceConfirm: Boolean) { // Note, we have to use ActivityController (instead of ActivityScenario) in order to access // the activity before it is created, so we can set up various mocked responses before they // are referenced in onCreate. if (forceConfirm) { val intent = Intent().putExtra(EXTRA_FORCE_CONFIRMATION, true) mActivityController = Robolectric.buildActivity(ConfirmSupervisionCredentialsActivity::class.java, intent) } else { mActivityController = Robolectric.buildActivity(ConfirmSupervisionCredentialsActivity::class.java) } mActivity = mActivityController.get() shadowActivity = shadowOf(mActivity) shadowActivity.setCallingPackage(callingPackage) shadowKeyguardManager = shadowOf(mActivity.getSystemService(KeyguardManager::class.java)) Shadow.extract<ShadowContextImpl>(mActivity.baseContext).apply { setSystemService(Context.ACTIVITY_SERVICE, mockActivityManager) setSystemService(Context.SUPERVISION_SERVICE, mockSupervisionManager) setSystemService(Context.USER_SERVICE, mockUserManager) } } private companion object { const val SUPERVISING_USER_ID = 5 val SUPERVISING_USER_INFO = Loading Loading
src/com/android/settings/supervision/ConfirmSupervisionCredentialsActivity.kt +10 −3 Original line number Diff line number Diff line Loading @@ -122,9 +122,11 @@ class ConfirmSupervisionCredentialsActivity : FragmentActivity() { getResultLauncher.launch(setupIntent) return } val authController = SupervisionAuthController.getInstance(this) if (!authController.isSessionActive(taskId)) { val forceConfirmation = intent.getBooleanExtra(EXTRA_FORCE_CONFIRMATION, false) if ( forceConfirmation || !SupervisionAuthController.getInstance(this).isSessionActive(taskId) ) { val activityManager = getSystemService(ActivityManager::class.java) if (!activityManager.startProfile(supervisingUser)) { errorHandler("Unable to start supervising user, cannot verify credentials.") Loading Loading @@ -213,4 +215,9 @@ class ConfirmSupervisionCredentialsActivity : FragmentActivity() { setResult(RESULT_CANCELED) finish() } companion object { // If true, force confirmation of supervision credentials, regardless of active auth session @VisibleForTesting const val EXTRA_FORCE_CONFIRMATION = "force_confirmation" } }
tests/robotests/src/com/android/settings/supervision/ConfirmSupervisionCredentialsActivityTest.kt +48 −16 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.app.supervision.SupervisionManager import android.app.supervision.SupervisionRecoveryInfo import android.app.supervision.SupervisionRecoveryInfo.STATE_PENDING import android.content.Context import android.content.Intent import android.content.pm.UserInfo import android.hardware.biometrics.BiometricManager import android.hardware.biometrics.PromptContentViewWithMoreOptionsButton Loading @@ -34,6 +35,7 @@ import android.os.UserManager.USER_TYPE_PROFILE_SUPERVISING import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.R import com.android.settings.supervision.ConfirmSupervisionCredentialsActivity.Companion.EXTRA_FORCE_CONFIRMATION import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test Loading Loading @@ -76,22 +78,7 @@ class ConfirmSupervisionCredentialsActivityTest { @Before fun setUp() { ShadowRoleManager.reset() // Note, we have to use ActivityController (instead of ActivityScenario) in order to access // the activity before it is created, so we can set up various mocked responses before they // are referenced in onCreate. mActivityController = Robolectric.buildActivity(ConfirmSupervisionCredentialsActivity::class.java) mActivity = mActivityController.get() shadowActivity = shadowOf(mActivity) shadowActivity.setCallingPackage(callingPackage) shadowKeyguardManager = shadowOf(mActivity.getSystemService(KeyguardManager::class.java)) Shadow.extract<ShadowContextImpl>(mActivity.baseContext).apply { setSystemService(Context.ACTIVITY_SERVICE, mockActivityManager) setSystemService(Context.SUPERVISION_SERVICE, mockSupervisionManager) setSystemService(Context.USER_SERVICE, mockUserManager) } setUpActivity(forceConfirm = false) SupervisionAuthController.sInstance = null } Loading Loading @@ -153,6 +140,25 @@ class ConfirmSupervisionCredentialsActivityTest { assertThat(shadowActivity.resultCode).isEqualTo(Activity.RESULT_OK) } @Test fun onCreate_authSessionActive_forceConfirmation_doesNotFinish() { ShadowRoleManager.addRoleHolder(ROLE_SYSTEM_SUPERVISION, callingPackage, currentUser) mockUserManager.stub { on { users } doReturn listOf(SUPERVISING_USER_INFO) } mockActivityManager.stub { on { startProfile(any()) } doReturn true } shadowKeyguardManager.setIsDeviceSecure(SUPERVISING_USER_ID, true) SupervisionAuthController.getInstance(context).startSession(mActivity.taskId) setUpActivity(forceConfirm = true) mActivityController.setup() assertThat(mActivity.isFinishing).isFalse() // Ensure that the supervising profile is started val userCaptor = argumentCaptor<UserHandle>() verify(mockActivityManager).startProfile(userCaptor.capture()) assert(userCaptor.lastValue.identifier == SUPERVISING_USER_ID) } @Test @Config(sdk = [Build.VERSION_CODES.BAKLAVA]) fun onCreate_callerIsSystemUid_doesNotFinish() { Loading Loading @@ -212,6 +218,7 @@ class ConfirmSupervisionCredentialsActivityTest { .isInstanceOf(PromptContentViewWithMoreOptionsButton::class.java) } @Test fun getBiometricPrompt_recoveryInfoEmpty_noMoreOptionsButton() { whenever(mockSupervisionManager.supervisionRecoveryInfo).thenReturn(null) Loading @@ -225,6 +232,7 @@ class ConfirmSupervisionCredentialsActivityTest { assertThat(biometricPrompt.contentView).isNull() } @Test fun onAuthenticationSucceeded_startsAuthSession_returnsResultOK() { mockUserManager.stub { on { users } doReturn listOf(SUPERVISING_USER_INFO) } shadowKeyguardManager.setIsDeviceSecure(SUPERVISING_USER_ID, true) Loading @@ -236,6 +244,30 @@ class ConfirmSupervisionCredentialsActivityTest { assertThat(shadowActivity.resultCode).isEqualTo(Activity.RESULT_OK) } private fun setUpActivity(forceConfirm: Boolean) { // Note, we have to use ActivityController (instead of ActivityScenario) in order to access // the activity before it is created, so we can set up various mocked responses before they // are referenced in onCreate. if (forceConfirm) { val intent = Intent().putExtra(EXTRA_FORCE_CONFIRMATION, true) mActivityController = Robolectric.buildActivity(ConfirmSupervisionCredentialsActivity::class.java, intent) } else { mActivityController = Robolectric.buildActivity(ConfirmSupervisionCredentialsActivity::class.java) } mActivity = mActivityController.get() shadowActivity = shadowOf(mActivity) shadowActivity.setCallingPackage(callingPackage) shadowKeyguardManager = shadowOf(mActivity.getSystemService(KeyguardManager::class.java)) Shadow.extract<ShadowContextImpl>(mActivity.baseContext).apply { setSystemService(Context.ACTIVITY_SERVICE, mockActivityManager) setSystemService(Context.SUPERVISION_SERVICE, mockSupervisionManager) setSystemService(Context.USER_SERVICE, mockUserManager) } } private companion object { const val SUPERVISING_USER_ID = 5 val SUPERVISING_USER_INFO = Loading