diff --git a/res/drawable/ic_pin_outline.xml b/res/drawable/ic_pin_outline.xml
new file mode 100644
index 00000000000..d7e5f71ebcd
--- /dev/null
+++ b/res/drawable/ic_pin_outline.xml
@@ -0,0 +1,25 @@
+
+
+
+
diff --git a/src/com/android/settings/supervision/SupervisionHelper.kt b/src/com/android/settings/supervision/SupervisionHelper.kt
new file mode 100644
index 00000000000..8b9b325cb7c
--- /dev/null
+++ b/src/com/android/settings/supervision/SupervisionHelper.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.supervision
+
+import android.app.KeyguardManager
+import android.content.Context
+import android.os.UserHandle
+import android.os.UserManager
+import android.os.UserManager.USER_TYPE_PROFILE_SUPERVISING
+import androidx.annotation.VisibleForTesting
+
+/** Convenience methods for interacting with the supervising user profile. */
+open class SupervisionHelper private constructor(context: Context) {
+ private val mUserManager = context.getSystemService(UserManager::class.java)
+ private val mKeyguardManager = context.getSystemService(KeyguardManager::class.java)
+
+ fun getSupervisingUserHandle(): UserHandle? {
+ for (user in (mUserManager?.users ?: emptyList())) {
+ if (user.userType.equals(USER_TYPE_PROFILE_SUPERVISING)) {
+ return user.userHandle
+ }
+ }
+ return null
+ }
+
+ fun isSupervisingCredentialSet(): Boolean {
+ val supervisingUserId = getSupervisingUserHandle()?.identifier ?: return false
+ return mKeyguardManager?.isDeviceSecure(supervisingUserId) ?: false
+ }
+
+ companion object {
+ @Volatile @VisibleForTesting var sInstance: SupervisionHelper? = null
+
+ fun getInstance(context: Context): SupervisionHelper {
+ return sInstance
+ ?: synchronized(this) {
+ sInstance ?: SupervisionHelper(context).also { sInstance = it }
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/supervision/SupervisionMainSwitchPreference.kt b/src/com/android/settings/supervision/SupervisionMainSwitchPreference.kt
index 88afc55147c..57591f9aee5 100644
--- a/src/com/android/settings/supervision/SupervisionMainSwitchPreference.kt
+++ b/src/com/android/settings/supervision/SupervisionMainSwitchPreference.kt
@@ -83,6 +83,7 @@ class SupervisionMainSwitchPreference(context: Context) :
val newValue = !supervisionMainSwitchStorage.getBoolean(KEY)!!
mainSwitchPreference.setChecked(newValue)
updateDependentPreferencesEnabledState(mainSwitchPreference, newValue)
+ context.notifyPreferenceChange(SupervisionPinManagementScreen.KEY)
}
return true
@@ -110,10 +111,7 @@ class SupervisionMainSwitchPreference(context: Context) :
isChecked: Boolean,
) {
preference?.parent?.forEachRecursively {
- if (
- it.parent?.key == SupervisionDashboardScreen.SUPERVISION_DYNAMIC_GROUP_1 ||
- it.key == SupervisionPinManagementScreen.KEY
- ) {
+ if (it.parent?.key == SupervisionDashboardScreen.SUPERVISION_DYNAMIC_GROUP_1) {
it.isEnabled = isChecked
}
}
diff --git a/src/com/android/settings/supervision/SupervisionPinManagementScreen.kt b/src/com/android/settings/supervision/SupervisionPinManagementScreen.kt
index 6d9874a69b7..f3cb2e3c782 100644
--- a/src/com/android/settings/supervision/SupervisionPinManagementScreen.kt
+++ b/src/com/android/settings/supervision/SupervisionPinManagementScreen.kt
@@ -17,16 +17,20 @@ package com.android.settings.supervision
import android.content.Context
import com.android.settings.R
+import com.android.settingslib.metadata.PreferenceAvailabilityProvider
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 {
+class SupervisionPinManagementScreen : PreferenceScreenCreator, PreferenceAvailabilityProvider {
override val key: String
get() = KEY
+ override fun isAvailable(context: Context) =
+ SupervisionHelper.getInstance(context).isSupervisingCredentialSet()
+
override val title: Int
get() = R.string.supervision_pin_management_preference_title
@@ -36,7 +40,7 @@ class SupervisionPinManagementScreen : PreferenceScreenCreator {
// TODO(b/391994031): dynamically update the icon according to PIN status.
override val icon: Int
- get() = R.drawable.ic_pin
+ get() = R.drawable.ic_pin_outline
override fun fragmentClass() = SupervisionPinManagementFragment::class.java
diff --git a/tests/robotests/src/com/android/settings/supervision/SupervisionDashboardScreenTest.kt b/tests/robotests/src/com/android/settings/supervision/SupervisionDashboardScreenTest.kt
index bf579d9fd89..c112b934c0d 100644
--- a/tests/robotests/src/com/android/settings/supervision/SupervisionDashboardScreenTest.kt
+++ b/tests/robotests/src/com/android/settings/supervision/SupervisionDashboardScreenTest.kt
@@ -65,7 +65,7 @@ class SupervisionDashboardScreenTest {
val mainSwitchPreference =
fragment.findPreference(SupervisionMainSwitchPreference.KEY)!!
val childPreference =
- fragment.findPreference(SupervisionPinManagementScreen.KEY)!!
+ fragment.findPreference(SupervisionWebContentFiltersScreen.KEY)!!
assertThat(childPreference.isEnabled).isFalse()
@@ -89,7 +89,7 @@ class SupervisionDashboardScreenTest {
val mainSwitchPreference =
fragment.findPreference(SupervisionMainSwitchPreference.KEY)!!
val childPreference =
- fragment.findPreference(SupervisionPinManagementScreen.KEY)!!
+ fragment.findPreference(SupervisionWebContentFiltersScreen.KEY)!!
assertThat(childPreference.isEnabled).isFalse()
diff --git a/tests/robotests/src/com/android/settings/supervision/SupervisionPinManagementScreenTest.kt b/tests/robotests/src/com/android/settings/supervision/SupervisionPinManagementScreenTest.kt
index 90719fba908..294f0ec0cf6 100644
--- a/tests/robotests/src/com/android/settings/supervision/SupervisionPinManagementScreenTest.kt
+++ b/tests/robotests/src/com/android/settings/supervision/SupervisionPinManagementScreenTest.kt
@@ -15,25 +15,73 @@
*/
package com.android.settings.supervision
+import android.app.KeyguardManager
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 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.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class SupervisionPinManagementScreenTest {
- private val context: Context = ApplicationProvider.getApplicationContext()
+ private val mockKeyguardManager = mock()
+ private val mockUserManager = mock()
+
+ private val context: Context =
+ object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
+ override fun getSystemService(name: String): Any? =
+ when (name) {
+ Context.KEYGUARD_SERVICE -> mockKeyguardManager
+ Context.USER_SERVICE -> mockUserManager
+ else -> super.getSystemService(name)
+ }
+ }
private val supervisionPinManagementScreen = SupervisionPinManagementScreen()
+ @Before
+ fun setup() {
+ SupervisionHelper.sInstance = null
+ }
+
@Test
fun key() {
assertThat(supervisionPinManagementScreen.key).isEqualTo(SupervisionPinManagementScreen.KEY)
}
+ @Test
+ fun isAvailable() {
+ whenever(mockUserManager.users).thenReturn(listOf(SUPERVISING_USER_INFO))
+ whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(true)
+
+ assertThat(supervisionPinManagementScreen.isAvailable(context)).isTrue()
+ }
+
+ @Test
+ fun isAvailable_noSupervisingUser_returnsFalse() {
+ whenever(mockUserManager.users).thenReturn(emptyList())
+ whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(true)
+
+ assertThat(supervisionPinManagementScreen.isAvailable(context)).isFalse()
+ }
+
+ @Test
+ fun isAvailable_noSupervisingCredential_returnsFalse() {
+ whenever(mockUserManager.users).thenReturn(listOf(SUPERVISING_USER_INFO))
+ whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(false)
+
+ assertThat(supervisionPinManagementScreen.isAvailable(context)).isFalse()
+ }
+
@Test
fun getTitle() {
assertThat(supervisionPinManagementScreen.title)
@@ -45,4 +93,16 @@ class SupervisionPinManagementScreenTest {
assertThat(supervisionPinManagementScreen.summary)
.isEqualTo(R.string.supervision_pin_management_preference_summary_add)
}
+
+ private companion object {
+ const val SUPERVISING_USER_ID = 5
+ val SUPERVISING_USER_INFO =
+ UserInfo(
+ SUPERVISING_USER_ID,
+ /* name */ "supervising",
+ /* iconPath */ "",
+ /* flags */ 0,
+ USER_TYPE_PROFILE_SUPERVISING,
+ )
+ }
}