• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 
17 package com.android.systemui.statusbar.policy
18 
19 import android.content.Context
20 import android.content.pm.UserInfo
21 import android.database.ContentObserver
22 import android.net.Uri
23 import android.os.Handler
24 import android.os.HandlerExecutor
25 import android.os.UserHandle
26 import android.provider.Settings
27 import android.util.ArraySet
28 import android.util.SparseBooleanArray
29 import androidx.annotation.GuardedBy
30 import androidx.annotation.WorkerThread
31 import com.android.systemui.Dumpable
32 import com.android.systemui.dagger.SysUISingleton
33 import com.android.systemui.dagger.qualifiers.Background
34 import com.android.systemui.dagger.qualifiers.Main
35 import com.android.systemui.dump.DumpManager
36 import com.android.systemui.settings.UserTracker
37 import com.android.systemui.util.settings.GlobalSettings
38 import com.android.systemui.util.settings.SecureSettings
39 import java.io.PrintWriter
40 import java.util.concurrent.Executor
41 import java.util.concurrent.atomic.AtomicBoolean
42 import javax.inject.Inject
43 
44 @SysUISingleton
45 open class DeviceProvisionedControllerImpl @Inject constructor(
46     private val secureSettings: SecureSettings,
47     private val globalSettings: GlobalSettings,
48     private val userTracker: UserTracker,
49     private val dumpManager: DumpManager,
50     @Background private val backgroundHandler: Handler,
51     @Main private val mainExecutor: Executor
52 ) : DeviceProvisionedController,
53     DeviceProvisionedController.DeviceProvisionedListener,
54     Dumpable {
55 
56     companion object {
57         private const val ALL_USERS = -1
58         private const val NO_USERS = -2
59         protected const val TAG = "DeviceProvisionedControllerImpl"
60     }
61 
62     private val deviceProvisionedUri = globalSettings.getUriFor(Settings.Global.DEVICE_PROVISIONED)
63     private val frpActiveUri = secureSettings.getUriFor(Settings.Secure.SECURE_FRP_MODE)
64     private val userSetupUri = secureSettings.getUriFor(Settings.Secure.USER_SETUP_COMPLETE)
65 
66     private val deviceProvisioned = AtomicBoolean(false)
67     private val frpActive = AtomicBoolean(false)
68     @GuardedBy("lock")
69     private val userSetupComplete = SparseBooleanArray()
70     @GuardedBy("lock")
71     private val listeners = ArraySet<DeviceProvisionedController.DeviceProvisionedListener>()
72 
73     private val lock = Any()
74 
75     private val backgroundExecutor = HandlerExecutor(backgroundHandler)
76 
77     private val initted = AtomicBoolean(false)
78 
79     private val _currentUser: Int
80         get() = userTracker.userId
81 
getCurrentUsernull82     override fun getCurrentUser(): Int {
83         return _currentUser
84     }
85 
86     private val observer = object : ContentObserver(backgroundHandler) {
onChangenull87         override fun onChange(
88             selfChange: Boolean,
89             uris: MutableCollection<Uri>,
90             flags: Int,
91             userId: Int
92         ) {
93             val updateDeviceProvisioned = deviceProvisionedUri in uris
94             val updateFrp = frpActiveUri in uris
95             val updateUser = if (userSetupUri in uris) userId else NO_USERS
96             updateValues(updateDeviceProvisioned, updateFrp, updateUser)
97             if (updateDeviceProvisioned) {
98                 onDeviceProvisionedChanged()
99             }
100             if (updateFrp) {
101                 onFrpActiveChanged()
102             }
103             if (updateUser != NO_USERS) {
104                 onUserSetupChanged()
105             }
106         }
107     }
108 
109     private val userChangedCallback = object : UserTracker.Callback {
110         @WorkerThread
onUserChangednull111         override fun onUserChanged(newUser: Int, userContext: Context) {
112             updateValues(updateDeviceProvisioned = false, updateFrp = false, updateUser = newUser)
113             onUserSwitched()
114         }
115 
onProfilesChangednull116         override fun onProfilesChanged(profiles: List<UserInfo>) {}
117     }
118 
119     init {
120         userSetupComplete.put(currentUser, false)
121     }
122 
123     /**
124      * Call to initialize values and register observers
125      */
initnull126     open fun init() {
127         if (!initted.compareAndSet(false, true)) {
128             return
129         }
130         dumpManager.registerDumpable(this)
131         updateValues()
132         userTracker.addCallback(userChangedCallback, backgroundExecutor)
133         globalSettings.registerContentObserver(deviceProvisionedUri, observer)
134         globalSettings.registerContentObserver(frpActiveUri, observer)
135         secureSettings.registerContentObserverForUser(userSetupUri, observer, UserHandle.USER_ALL)
136     }
137 
138     @WorkerThread
updateValuesnull139     private fun updateValues(
140         updateDeviceProvisioned: Boolean = true,
141         updateFrp: Boolean = true,
142         updateUser: Int = ALL_USERS
143     ) {
144         if (updateDeviceProvisioned) {
145             deviceProvisioned
146                     .set(globalSettings.getInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0)
147         }
148         if (updateFrp) {
149             frpActive.set(globalSettings.getInt(Settings.Secure.SECURE_FRP_MODE, 0) != 0)
150         }
151         synchronized(lock) {
152             if (updateUser == ALL_USERS) {
153                 val n = userSetupComplete.size()
154                 for (i in 0 until n) {
155                     val user = userSetupComplete.keyAt(i)
156                     val value = secureSettings
157                             .getIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0, user) != 0
158                     userSetupComplete.put(user, value)
159                 }
160             } else if (updateUser != NO_USERS) {
161                 val value = secureSettings
162                         .getIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0, updateUser) != 0
163                 userSetupComplete.put(updateUser, value)
164             }
165         }
166     }
167 
168     /**
169      * Adds a listener.
170      *
171      * The listener will not be called when this happens.
172      */
addCallbacknull173     override fun addCallback(listener: DeviceProvisionedController.DeviceProvisionedListener) {
174         synchronized(lock) {
175             listeners.add(listener)
176         }
177     }
178 
removeCallbacknull179     override fun removeCallback(listener: DeviceProvisionedController.DeviceProvisionedListener) {
180         synchronized(lock) {
181             listeners.remove(listener)
182         }
183     }
184 
isDeviceProvisionednull185     override fun isDeviceProvisioned(): Boolean {
186         return deviceProvisioned.get()
187     }
188 
isFrpActivenull189     override fun isFrpActive(): Boolean {
190         return frpActive.get()
191     }
192 
isUserSetupnull193     override fun isUserSetup(user: Int): Boolean {
194         val index = synchronized(lock) {
195             userSetupComplete.indexOfKey(user)
196         }
197         return if (index < 0) {
198             val value = secureSettings
199                     .getIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0, user) != 0
200             synchronized(lock) {
201                 userSetupComplete.put(user, value)
202             }
203             value
204         } else {
205             synchronized(lock) {
206                 userSetupComplete.get(user, false)
207             }
208         }
209     }
210 
isCurrentUserSetupnull211     override fun isCurrentUserSetup(): Boolean {
212         return isUserSetup(currentUser)
213     }
214 
onDeviceProvisionedChangednull215     override fun onDeviceProvisionedChanged() {
216         dispatchChange(
217             DeviceProvisionedController.DeviceProvisionedListener::onDeviceProvisionedChanged
218         )
219     }
220 
onFrpActiveChangednull221     override fun onFrpActiveChanged() {
222         dispatchChange(
223             DeviceProvisionedController.DeviceProvisionedListener::onFrpActiveChanged
224         )
225     }
226 
onUserSetupChangednull227     override fun onUserSetupChanged() {
228         dispatchChange(DeviceProvisionedController.DeviceProvisionedListener::onUserSetupChanged)
229     }
230 
onUserSwitchednull231     override fun onUserSwitched() {
232         dispatchChange(DeviceProvisionedController.DeviceProvisionedListener::onUserSwitched)
233     }
234 
dispatchChangenull235     protected fun dispatchChange(
236         callback: DeviceProvisionedController.DeviceProvisionedListener.() -> Unit
237     ) {
238         val listenersCopy = synchronized(lock) {
239             ArrayList(listeners)
240         }
241         mainExecutor.execute {
242             listenersCopy.forEach(callback)
243         }
244     }
245 
dumpnull246     override fun dump(pw: PrintWriter, args: Array<out String>) {
247         pw.println("Device provisioned: ${deviceProvisioned.get()}")
248         pw.println("Factory Reset Protection active: ${frpActive.get()}")
249         synchronized(lock) {
250             pw.println("User setup complete: $userSetupComplete")
251             pw.println("Listeners: $listeners")
252         }
253     }
254 }