• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.settings.supervision
17 
18 import android.app.Activity
19 import android.app.supervision.SupervisionManager
20 import android.content.Context
21 import android.content.Intent
22 import androidx.preference.Preference
23 import com.android.settings.R
24 import com.android.settingslib.datastore.KeyValueStore
25 import com.android.settingslib.datastore.NoOpKeyedObservable
26 import com.android.settingslib.metadata.MainSwitchPreference
27 import com.android.settingslib.metadata.PreferenceLifecycleContext
28 import com.android.settingslib.metadata.PreferenceLifecycleProvider
29 import com.android.settingslib.metadata.PreferenceMetadata
30 import com.android.settingslib.metadata.PreferenceSummaryProvider
31 import com.android.settingslib.metadata.ReadWritePermit
32 import com.android.settingslib.metadata.SensitivityLevel
33 import com.android.settingslib.preference.MainSwitchPreferenceBinding
34 import com.android.settingslib.preference.forEachRecursively
35 
36 /** Main toggle to enable or disable device supervision. */
37 class SupervisionMainSwitchPreference(context: Context) :
38     MainSwitchPreference(KEY, R.string.device_supervision_switch_title),
39     PreferenceSummaryProvider,
40     MainSwitchPreferenceBinding,
41     Preference.OnPreferenceChangeListener,
42     PreferenceLifecycleProvider {
43 
44     private val supervisionMainSwitchStorage = SupervisionMainSwitchStorage(context)
45     private lateinit var lifeCycleContext: PreferenceLifecycleContext
46 
47     // TODO(b/383568136): Make presence of summary conditional on whether PIN
48     // has been set up before or not.
getSummarynull49     override fun getSummary(context: Context): CharSequence? =
50         context.getString(R.string.device_supervision_switch_no_pin_summary)
51 
52     override fun storage(context: Context): KeyValueStore = supervisionMainSwitchStorage
53 
54     override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) =
55         ReadWritePermit.DISALLOW
56 
57     override fun getWritePermit(context: Context, callingPid: Int, callingUid: Int) =
58         ReadWritePermit.DISALLOW
59 
60     override val sensitivityLevel: Int
61         get() = SensitivityLevel.HIGH_SENSITIVITY
62 
63     override fun onCreate(context: PreferenceLifecycleContext) {
64         lifeCycleContext = context
65     }
66 
onResumenull67     override fun onResume(context: PreferenceLifecycleContext) {
68         updateDependentPreferencesEnabledState(
69             context.findPreference<Preference>(KEY),
70             supervisionMainSwitchStorage.getBoolean(KEY)!!,
71         )
72     }
73 
onActivityResultnull74     override fun onActivityResult(
75         context: PreferenceLifecycleContext,
76         requestCode: Int,
77         resultCode: Int,
78         data: Intent?,
79     ): Boolean {
80         if (resultCode == Activity.RESULT_OK) {
81             val mainSwitchPreference =
82                 context.requirePreference<com.android.settingslib.widget.MainSwitchPreference>(KEY)
83             val newValue = !supervisionMainSwitchStorage.getBoolean(KEY)!!
84             mainSwitchPreference.setChecked(newValue)
85             updateDependentPreferencesEnabledState(mainSwitchPreference, newValue)
86             context.notifyPreferenceChange(SupervisionPinManagementScreen.KEY)
87         }
88 
89         return true
90     }
91 
bindnull92     override fun bind(preference: Preference, metadata: PreferenceMetadata) {
93         super.bind(preference, metadata)
94         preference.onPreferenceChangeListener = this
95     }
96 
onPreferenceChangenull97     override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
98         if (newValue !is Boolean) return true
99 
100         val intent = Intent(lifeCycleContext, ConfirmSupervisionCredentialsActivity::class.java)
101         lifeCycleContext.startActivityForResult(
102             intent,
103             REQUEST_CODE_CONFIRM_SUPERVISION_CREDENTIALS,
104             null,
105         )
106         return false
107     }
108 
updateDependentPreferencesEnabledStatenull109     private fun updateDependentPreferencesEnabledState(
110         preference: Preference?,
111         isChecked: Boolean,
112     ) {
113         preference?.parent?.forEachRecursively {
114             if (it.parent?.key == SupervisionDashboardScreen.SUPERVISION_DYNAMIC_GROUP_1) {
115                 it.isEnabled = isChecked
116             }
117         }
118     }
119 
120     @Suppress("UNCHECKED_CAST")
121     private class SupervisionMainSwitchStorage(private val context: Context) :
122         NoOpKeyedObservable<String>(), KeyValueStore {
containsnull123         override fun contains(key: String) = key == KEY
124 
125         override fun <T : Any> getValue(key: String, valueType: Class<T>) =
126             (context.getSystemService(SupervisionManager::class.java)?.isSupervisionEnabled() ==
127                 true)
128                 as T
129 
130         override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
131             if (key == KEY && value is Boolean) {
132                 val supervisionManager = context.getSystemService(SupervisionManager::class.java)
133                 supervisionManager?.setSupervisionEnabled(value)
134             }
135         }
136     }
137 
138     companion object {
139         const val KEY = "device_supervision_switch"
140         const val REQUEST_CODE_CONFIRM_SUPERVISION_CREDENTIALS = 0
141     }
142 }
143