Loading res/values/strings.xml +4 −2 Original line number Diff line number Diff line Loading @@ -14452,8 +14452,10 @@ Data usage charges may apply.</string> <string name="keywords_supervision_settings">supervision, parental supervision, parental controls</string> <!-- Title for supervision PIN management settings entry [CHAR LIMIT=60] --> <string name="supervision_pin_management_preference_title">Manage PIN</string> <!-- Description for supervision PIN management settings entry, in the case of adding a PIN [CHAR LIMIT=NONE] --> <string name="supervision_pin_management_preference_summary_add">Add a PIN recovery method</string> <!-- Description for supervision PIN management settings entry, in the case of adding a PIN recovery method[CHAR LIMIT=NONE] --> <string name="supervision_pin_management_preference_summary_add">Add PIN recovery</string> <!-- Description for supervision PIN management settings entry, in the case of verifying the PIN recovery method[CHAR LIMIT=NONE] --> <string name="supervision_pin_management_preference_summary_verify_recovery">Verify PIN recovery</string> <!-- Title for supervision change PIN setting entry [CHAR LIMIT=60] --> <string name="supervision_change_pin_preference_title">Change PIN</string> <!-- Title for supervision forgot PIN setting entry [CHAR LIMIT=60] --> src/com/android/settings/supervision/SupervisionAddRecoveryPreference.kt +1 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ class SupervisionAddRecoveryPreference : if (resultCode == Activity.RESULT_OK) { context.notifyPreferenceChange(KEY) context.notifyPreferenceChange(SupervisionUpdateRecoveryEmailPreference.KEY) context.notifyPreferenceChange(SupervisionPinManagementScreen.KEY) } return true } Loading src/com/android/settings/supervision/SupervisionPinManagementScreen.kt +44 −7 Original line number Diff line number Diff line Loading @@ -15,16 +15,24 @@ */ package com.android.settings.supervision import android.app.supervision.SupervisionManager import android.app.supervision.flags.Flags import android.content.Context import com.android.settings.R import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.PreferenceIconProvider import com.android.settingslib.metadata.PreferenceSummaryProvider import com.android.settingslib.metadata.ProvidePreferenceScreen import com.android.settingslib.metadata.preferenceHierarchy import com.android.settingslib.preference.PreferenceScreenCreator /** Pin Management landing page (Settings > Supervision > Manage Pin). */ @ProvidePreferenceScreen(SupervisionPinManagementScreen.KEY) class SupervisionPinManagementScreen : PreferenceScreenCreator, PreferenceAvailabilityProvider { class SupervisionPinManagementScreen : PreferenceScreenCreator, PreferenceAvailabilityProvider, PreferenceSummaryProvider, PreferenceIconProvider { override val key: String get() = KEY Loading @@ -34,13 +42,42 @@ class SupervisionPinManagementScreen : PreferenceScreenCreator, PreferenceAvaila override val title: Int get() = R.string.supervision_pin_management_preference_title // TODO(b/391994031): dynamically update the summary according to PIN status. override val summary: Int get() = R.string.supervision_pin_management_preference_summary_add override fun getSummary(context: Context): CharSequence? { if (!Flags.enableSupervisionPinRecoveryScreen()) { return null } val recoveryInfo = context.getSystemService(SupervisionManager::class.java)?.supervisionRecoveryInfo return when { recoveryInfo == null || (recoveryInfo.email.isNullOrEmpty() && recoveryInfo.id.isNullOrEmpty()) -> { context.getString(R.string.supervision_pin_management_preference_summary_add) } recoveryInfo.id.isNullOrEmpty() -> { context.getString( R.string.supervision_pin_management_preference_summary_verify_recovery ) } else -> null } } // TODO(b/391994031): dynamically update the icon according to PIN status. override val icon: Int get() = R.drawable.ic_pin_outline // TODO(b/409837094): get icon with dynamic color. override fun getIcon(context: Context): Int { if (Flags.enableSupervisionPinRecoveryScreen()) { val recoveryInfo = context.getSystemService(SupervisionManager::class.java)?.supervisionRecoveryInfo if ( recoveryInfo == null || recoveryInfo.email.isNullOrEmpty() || recoveryInfo.id.isNullOrEmpty() ) { // if recovery is not fully setup. return R.drawable.exclamation_icon } } return R.drawable.ic_pin_outline } override fun fragmentClass() = SupervisionPinManagementFragment::class.java Loading tests/robotests/src/com/android/settings/supervision/SupervisionPinManagementScreenTest.kt +76 −3 Original line number Diff line number Diff line Loading @@ -16,16 +16,23 @@ package com.android.settings.supervision import android.app.KeyguardManager import android.app.supervision.SupervisionManager import android.app.supervision.SupervisionRecoveryInfo import android.app.supervision.flags.Flags import android.content.Context import android.content.ContextWrapper import android.content.pm.UserInfo import android.os.UserManager import android.os.UserManager.USER_TYPE_PROFILE_SUPERVISING import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.SetFlagsRule import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.R import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.mock Loading @@ -35,6 +42,9 @@ import org.mockito.kotlin.whenever class SupervisionPinManagementScreenTest { private val mockKeyguardManager = mock<KeyguardManager>() private val mockUserManager = mock<UserManager>() private val mockSupervisionManager = mock<SupervisionManager>() @get:Rule val setFlagsRule = SetFlagsRule() private val context: Context = object : ContextWrapper(ApplicationProvider.getApplicationContext()) { Loading @@ -42,6 +52,7 @@ class SupervisionPinManagementScreenTest { when (name) { Context.KEYGUARD_SERVICE -> mockKeyguardManager Context.USER_SERVICE -> mockUserManager Context.SUPERVISION_SERVICE -> mockSupervisionManager else -> super.getSystemService(name) } } Loading Loading @@ -89,9 +100,71 @@ class SupervisionPinManagementScreenTest { } @Test fun getSummary_addPin() { assertThat(supervisionPinManagementScreen.summary) .isEqualTo(R.string.supervision_pin_management_preference_summary_add) @EnableFlags(Flags.FLAG_ENABLE_SUPERVISION_PIN_RECOVERY_SCREEN) fun getDescription_recoveryInfoMissing_addPinRecovery() { whenever(mockSupervisionManager.supervisionRecoveryInfo).thenReturn(null) assertThat(supervisionPinManagementScreen.getSummary(context)) .isEqualTo( context.getString(R.string.supervision_pin_management_preference_summary_add) ) assertThat(supervisionPinManagementScreen.getIcon(context)) .isEqualTo(R.drawable.exclamation_icon) } @Test @EnableFlags(Flags.FLAG_ENABLE_SUPERVISION_PIN_RECOVERY_SCREEN) fun getDescription_recoveryInfoEmpty_addPinRecovery() { whenever(mockSupervisionManager.supervisionRecoveryInfo) .thenReturn(SupervisionRecoveryInfo()) assertThat(supervisionPinManagementScreen.getSummary(context)) .isEqualTo( context.getString(R.string.supervision_pin_management_preference_summary_add) ) assertThat(supervisionPinManagementScreen.getIcon(context)) .isEqualTo(R.drawable.exclamation_icon) } @Test @EnableFlags(Flags.FLAG_ENABLE_SUPERVISION_PIN_RECOVERY_SCREEN) fun getDescription_recoveryIdMissing_verifyPinRecovery() { val recoveryInfo = SupervisionRecoveryInfo().apply { email = "email" } whenever(mockSupervisionManager.supervisionRecoveryInfo).thenReturn(recoveryInfo) assertThat(supervisionPinManagementScreen.getSummary(context)) .isEqualTo( context.getString( R.string.supervision_pin_management_preference_summary_verify_recovery ) ) assertThat(supervisionPinManagementScreen.getIcon(context)) .isEqualTo(R.drawable.exclamation_icon) } @Test @DisableFlags(Flags.FLAG_ENABLE_SUPERVISION_PIN_RECOVERY_SCREEN) fun getDescription_recoveryFlagDisabled_noSummary() { whenever(mockSupervisionManager.supervisionRecoveryInfo).thenReturn(null) assertThat(supervisionPinManagementScreen.getSummary(context)).isNull() assertThat(supervisionPinManagementScreen.getIcon(context)) .isEqualTo(R.drawable.ic_pin_outline) } @Test @EnableFlags(Flags.FLAG_ENABLE_SUPERVISION_PIN_RECOVERY_SCREEN) fun getDescription_recoverySetup_noSummary() { val recoveryInfo = SupervisionRecoveryInfo().apply { email = "email" id = "id" } whenever(mockSupervisionManager.supervisionRecoveryInfo).thenReturn(recoveryInfo) assertThat(supervisionPinManagementScreen.getSummary(context)).isNull() assertThat(supervisionPinManagementScreen.getIcon(context)) .isEqualTo(R.drawable.ic_pin_outline) } private companion object { Loading Loading
res/values/strings.xml +4 −2 Original line number Diff line number Diff line Loading @@ -14452,8 +14452,10 @@ Data usage charges may apply.</string> <string name="keywords_supervision_settings">supervision, parental supervision, parental controls</string> <!-- Title for supervision PIN management settings entry [CHAR LIMIT=60] --> <string name="supervision_pin_management_preference_title">Manage PIN</string> <!-- Description for supervision PIN management settings entry, in the case of adding a PIN [CHAR LIMIT=NONE] --> <string name="supervision_pin_management_preference_summary_add">Add a PIN recovery method</string> <!-- Description for supervision PIN management settings entry, in the case of adding a PIN recovery method[CHAR LIMIT=NONE] --> <string name="supervision_pin_management_preference_summary_add">Add PIN recovery</string> <!-- Description for supervision PIN management settings entry, in the case of verifying the PIN recovery method[CHAR LIMIT=NONE] --> <string name="supervision_pin_management_preference_summary_verify_recovery">Verify PIN recovery</string> <!-- Title for supervision change PIN setting entry [CHAR LIMIT=60] --> <string name="supervision_change_pin_preference_title">Change PIN</string> <!-- Title for supervision forgot PIN setting entry [CHAR LIMIT=60] -->
src/com/android/settings/supervision/SupervisionAddRecoveryPreference.kt +1 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ class SupervisionAddRecoveryPreference : if (resultCode == Activity.RESULT_OK) { context.notifyPreferenceChange(KEY) context.notifyPreferenceChange(SupervisionUpdateRecoveryEmailPreference.KEY) context.notifyPreferenceChange(SupervisionPinManagementScreen.KEY) } return true } Loading
src/com/android/settings/supervision/SupervisionPinManagementScreen.kt +44 −7 Original line number Diff line number Diff line Loading @@ -15,16 +15,24 @@ */ package com.android.settings.supervision import android.app.supervision.SupervisionManager import android.app.supervision.flags.Flags import android.content.Context import com.android.settings.R import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.PreferenceIconProvider import com.android.settingslib.metadata.PreferenceSummaryProvider import com.android.settingslib.metadata.ProvidePreferenceScreen import com.android.settingslib.metadata.preferenceHierarchy import com.android.settingslib.preference.PreferenceScreenCreator /** Pin Management landing page (Settings > Supervision > Manage Pin). */ @ProvidePreferenceScreen(SupervisionPinManagementScreen.KEY) class SupervisionPinManagementScreen : PreferenceScreenCreator, PreferenceAvailabilityProvider { class SupervisionPinManagementScreen : PreferenceScreenCreator, PreferenceAvailabilityProvider, PreferenceSummaryProvider, PreferenceIconProvider { override val key: String get() = KEY Loading @@ -34,13 +42,42 @@ class SupervisionPinManagementScreen : PreferenceScreenCreator, PreferenceAvaila override val title: Int get() = R.string.supervision_pin_management_preference_title // TODO(b/391994031): dynamically update the summary according to PIN status. override val summary: Int get() = R.string.supervision_pin_management_preference_summary_add override fun getSummary(context: Context): CharSequence? { if (!Flags.enableSupervisionPinRecoveryScreen()) { return null } val recoveryInfo = context.getSystemService(SupervisionManager::class.java)?.supervisionRecoveryInfo return when { recoveryInfo == null || (recoveryInfo.email.isNullOrEmpty() && recoveryInfo.id.isNullOrEmpty()) -> { context.getString(R.string.supervision_pin_management_preference_summary_add) } recoveryInfo.id.isNullOrEmpty() -> { context.getString( R.string.supervision_pin_management_preference_summary_verify_recovery ) } else -> null } } // TODO(b/391994031): dynamically update the icon according to PIN status. override val icon: Int get() = R.drawable.ic_pin_outline // TODO(b/409837094): get icon with dynamic color. override fun getIcon(context: Context): Int { if (Flags.enableSupervisionPinRecoveryScreen()) { val recoveryInfo = context.getSystemService(SupervisionManager::class.java)?.supervisionRecoveryInfo if ( recoveryInfo == null || recoveryInfo.email.isNullOrEmpty() || recoveryInfo.id.isNullOrEmpty() ) { // if recovery is not fully setup. return R.drawable.exclamation_icon } } return R.drawable.ic_pin_outline } override fun fragmentClass() = SupervisionPinManagementFragment::class.java Loading
tests/robotests/src/com/android/settings/supervision/SupervisionPinManagementScreenTest.kt +76 −3 Original line number Diff line number Diff line Loading @@ -16,16 +16,23 @@ package com.android.settings.supervision import android.app.KeyguardManager import android.app.supervision.SupervisionManager import android.app.supervision.SupervisionRecoveryInfo import android.app.supervision.flags.Flags import android.content.Context import android.content.ContextWrapper import android.content.pm.UserInfo import android.os.UserManager import android.os.UserManager.USER_TYPE_PROFILE_SUPERVISING import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.SetFlagsRule import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.R import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.mock Loading @@ -35,6 +42,9 @@ import org.mockito.kotlin.whenever class SupervisionPinManagementScreenTest { private val mockKeyguardManager = mock<KeyguardManager>() private val mockUserManager = mock<UserManager>() private val mockSupervisionManager = mock<SupervisionManager>() @get:Rule val setFlagsRule = SetFlagsRule() private val context: Context = object : ContextWrapper(ApplicationProvider.getApplicationContext()) { Loading @@ -42,6 +52,7 @@ class SupervisionPinManagementScreenTest { when (name) { Context.KEYGUARD_SERVICE -> mockKeyguardManager Context.USER_SERVICE -> mockUserManager Context.SUPERVISION_SERVICE -> mockSupervisionManager else -> super.getSystemService(name) } } Loading Loading @@ -89,9 +100,71 @@ class SupervisionPinManagementScreenTest { } @Test fun getSummary_addPin() { assertThat(supervisionPinManagementScreen.summary) .isEqualTo(R.string.supervision_pin_management_preference_summary_add) @EnableFlags(Flags.FLAG_ENABLE_SUPERVISION_PIN_RECOVERY_SCREEN) fun getDescription_recoveryInfoMissing_addPinRecovery() { whenever(mockSupervisionManager.supervisionRecoveryInfo).thenReturn(null) assertThat(supervisionPinManagementScreen.getSummary(context)) .isEqualTo( context.getString(R.string.supervision_pin_management_preference_summary_add) ) assertThat(supervisionPinManagementScreen.getIcon(context)) .isEqualTo(R.drawable.exclamation_icon) } @Test @EnableFlags(Flags.FLAG_ENABLE_SUPERVISION_PIN_RECOVERY_SCREEN) fun getDescription_recoveryInfoEmpty_addPinRecovery() { whenever(mockSupervisionManager.supervisionRecoveryInfo) .thenReturn(SupervisionRecoveryInfo()) assertThat(supervisionPinManagementScreen.getSummary(context)) .isEqualTo( context.getString(R.string.supervision_pin_management_preference_summary_add) ) assertThat(supervisionPinManagementScreen.getIcon(context)) .isEqualTo(R.drawable.exclamation_icon) } @Test @EnableFlags(Flags.FLAG_ENABLE_SUPERVISION_PIN_RECOVERY_SCREEN) fun getDescription_recoveryIdMissing_verifyPinRecovery() { val recoveryInfo = SupervisionRecoveryInfo().apply { email = "email" } whenever(mockSupervisionManager.supervisionRecoveryInfo).thenReturn(recoveryInfo) assertThat(supervisionPinManagementScreen.getSummary(context)) .isEqualTo( context.getString( R.string.supervision_pin_management_preference_summary_verify_recovery ) ) assertThat(supervisionPinManagementScreen.getIcon(context)) .isEqualTo(R.drawable.exclamation_icon) } @Test @DisableFlags(Flags.FLAG_ENABLE_SUPERVISION_PIN_RECOVERY_SCREEN) fun getDescription_recoveryFlagDisabled_noSummary() { whenever(mockSupervisionManager.supervisionRecoveryInfo).thenReturn(null) assertThat(supervisionPinManagementScreen.getSummary(context)).isNull() assertThat(supervisionPinManagementScreen.getIcon(context)) .isEqualTo(R.drawable.ic_pin_outline) } @Test @EnableFlags(Flags.FLAG_ENABLE_SUPERVISION_PIN_RECOVERY_SCREEN) fun getDescription_recoverySetup_noSummary() { val recoveryInfo = SupervisionRecoveryInfo().apply { email = "email" id = "id" } whenever(mockSupervisionManager.supervisionRecoveryInfo).thenReturn(recoveryInfo) assertThat(supervisionPinManagementScreen.getSummary(context)).isNull() assertThat(supervisionPinManagementScreen.getIcon(context)) .isEqualTo(R.drawable.ic_pin_outline) } private companion object { Loading