1 /*
2  * Copyright (C) 2023 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.bouncer.data.factory
18 
19 import android.annotation.IntDef
20 import com.android.keyguard.KeyguardSecurityModel
21 import com.android.keyguard.KeyguardSecurityModel.SecurityMode
22 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT
23 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEFAULT
24 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN
25 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_FACE_LOCKED_OUT
26 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_FINGERPRINT_LOCKED_OUT
27 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_FACE_INPUT
28 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT
29 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT
30 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE
31 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT
32 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE
33 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT
34 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART
35 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE
36 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT
37 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED
38 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST
39 import com.android.systemui.R.string.bouncer_face_not_recognized
40 import com.android.systemui.R.string.keyguard_enter_password
41 import com.android.systemui.R.string.keyguard_enter_pattern
42 import com.android.systemui.R.string.keyguard_enter_pin
43 import com.android.systemui.R.string.kg_bio_too_many_attempts_password
44 import com.android.systemui.R.string.kg_bio_too_many_attempts_pattern
45 import com.android.systemui.R.string.kg_bio_too_many_attempts_pin
46 import com.android.systemui.R.string.kg_bio_try_again_or_password
47 import com.android.systemui.R.string.kg_bio_try_again_or_pattern
48 import com.android.systemui.R.string.kg_bio_try_again_or_pin
49 import com.android.systemui.R.string.kg_face_locked_out
50 import com.android.systemui.R.string.kg_fp_locked_out
51 import com.android.systemui.R.string.kg_fp_not_recognized
52 import com.android.systemui.R.string.kg_primary_auth_locked_out_password
53 import com.android.systemui.R.string.kg_primary_auth_locked_out_pattern
54 import com.android.systemui.R.string.kg_primary_auth_locked_out_pin
55 import com.android.systemui.R.string.kg_prompt_after_dpm_lock
56 import com.android.systemui.R.string.kg_prompt_after_update_password
57 import com.android.systemui.R.string.kg_prompt_after_update_pattern
58 import com.android.systemui.R.string.kg_prompt_after_update_pin
59 import com.android.systemui.R.string.kg_prompt_after_user_lockdown_password
60 import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pattern
61 import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pin
62 import com.android.systemui.R.string.kg_prompt_auth_timeout
63 import com.android.systemui.R.string.kg_prompt_password_auth_timeout
64 import com.android.systemui.R.string.kg_prompt_pattern_auth_timeout
65 import com.android.systemui.R.string.kg_prompt_pin_auth_timeout
66 import com.android.systemui.R.string.kg_prompt_reason_restart_password
67 import com.android.systemui.R.string.kg_prompt_reason_restart_pattern
68 import com.android.systemui.R.string.kg_prompt_reason_restart_pin
69 import com.android.systemui.R.string.kg_prompt_unattended_update
70 import com.android.systemui.R.string.kg_too_many_failed_attempts_countdown
71 import com.android.systemui.R.string.kg_trust_agent_disabled
72 import com.android.systemui.R.string.kg_unlock_with_password_or_fp
73 import com.android.systemui.R.string.kg_unlock_with_pattern_or_fp
74 import com.android.systemui.R.string.kg_unlock_with_pin_or_fp
75 import com.android.systemui.R.string.kg_wrong_input_try_fp_suggestion
76 import com.android.systemui.R.string.kg_wrong_password_try_again
77 import com.android.systemui.R.string.kg_wrong_pattern_try_again
78 import com.android.systemui.R.string.kg_wrong_pin_try_again
79 import com.android.systemui.bouncer.shared.model.BouncerMessageModel
80 import com.android.systemui.bouncer.shared.model.Message
81 import com.android.systemui.dagger.SysUISingleton
82 import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
83 import javax.inject.Inject
84 
85 @SysUISingleton
86 class BouncerMessageFactory
87 @Inject
88 constructor(
89     private val biometricSettingsRepository: BiometricSettingsRepository,
90     private val securityModel: KeyguardSecurityModel,
91 ) {
92 
93     fun createFromPromptReason(
94         @BouncerPromptReason reason: Int,
95         userId: Int,
96         secondaryMsgOverride: String? = null
97     ): BouncerMessageModel? {
98         val pair =
99             getBouncerMessage(
100                 reason,
101                 securityModel.getSecurityMode(userId),
102                 biometricSettingsRepository.isFingerprintAuthCurrentlyAllowed.value
103             )
104         return pair?.let {
105             BouncerMessageModel(
106                 message = Message(messageResId = pair.first, animate = false),
107                 secondaryMessage =
108                     secondaryMsgOverride?.let {
109                         Message(message = secondaryMsgOverride, animate = false)
110                     }
111                         ?: Message(messageResId = pair.second, animate = false)
112             )
113         }
114     }
115 
116     /**
117      * Helper method that provides the relevant bouncer message that should be shown for different
118      * scenarios indicated by [reason]. [securityMode] & [fpAuthIsAllowed] parameters are used to
119      * provide a more specific message.
120      */
121     private fun getBouncerMessage(
122         @BouncerPromptReason reason: Int,
123         securityMode: SecurityMode,
124         fpAuthIsAllowed: Boolean = false
125     ): Pair<Int, Int>? {
126         return when (reason) {
127             // Primary auth locked out
128             PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT -> primaryAuthLockedOut(securityMode)
129             // Primary auth required reasons
130             PROMPT_REASON_RESTART -> authRequiredAfterReboot(securityMode)
131             PROMPT_REASON_TIMEOUT -> authRequiredAfterPrimaryAuthTimeout(securityMode)
132             PROMPT_REASON_DEVICE_ADMIN -> authRequiredAfterAdminLockdown(securityMode)
133             PROMPT_REASON_USER_REQUEST -> authRequiredAfterUserLockdown(securityMode)
134             PROMPT_REASON_PREPARE_FOR_UPDATE -> authRequiredForUnattendedUpdate(securityMode)
135             PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE -> authRequiredForMainlineUpdate(securityMode)
136             PROMPT_REASON_FINGERPRINT_LOCKED_OUT -> fingerprintUnlockUnavailable(securityMode)
137             PROMPT_REASON_AFTER_LOCKOUT -> biometricLockout(securityMode)
138             // Non strong auth not available reasons
139             PROMPT_REASON_FACE_LOCKED_OUT ->
140                 if (fpAuthIsAllowed) faceLockedOutButFingerprintAvailable(securityMode)
141                 else faceLockedOut(securityMode)
142             PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT ->
143                 if (fpAuthIsAllowed) nonStrongAuthTimeoutWithFingerprintAllowed(securityMode)
144                 else nonStrongAuthTimeout(securityMode)
145             PROMPT_REASON_TRUSTAGENT_EXPIRED ->
146                 if (fpAuthIsAllowed) trustAgentDisabledWithFingerprintAllowed(securityMode)
147                 else trustAgentDisabled(securityMode)
148             // Auth incorrect input reasons.
149             PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT ->
150                 if (fpAuthIsAllowed) incorrectSecurityInputWithFingerprint(securityMode)
151                 else incorrectSecurityInput(securityMode)
152             PROMPT_REASON_INCORRECT_FACE_INPUT ->
153                 if (fpAuthIsAllowed) incorrectFaceInputWithFingerprintAllowed(securityMode)
154                 else incorrectFaceInput(securityMode)
155             PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT -> incorrectFingerprintInput(securityMode)
156             // Default message
157             PROMPT_REASON_DEFAULT ->
158                 if (fpAuthIsAllowed) defaultMessageWithFingerprint(securityMode)
159                 else defaultMessage(securityMode)
160             else -> null
161         }
162     }
163 
164     fun emptyMessage(): BouncerMessageModel =
165         BouncerMessageModel(Message(message = ""), Message(message = ""))
166 }
167 
168 @Retention(AnnotationRetention.SOURCE)
169 @IntDef(
170     PROMPT_REASON_TIMEOUT,
171     PROMPT_REASON_DEVICE_ADMIN,
172     PROMPT_REASON_USER_REQUEST,
173     PROMPT_REASON_AFTER_LOCKOUT,
174     PROMPT_REASON_PREPARE_FOR_UPDATE,
175     PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT,
176     PROMPT_REASON_TRUSTAGENT_EXPIRED,
177     PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
178     PROMPT_REASON_INCORRECT_FACE_INPUT,
179     PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT,
180     PROMPT_REASON_FACE_LOCKED_OUT,
181     PROMPT_REASON_FINGERPRINT_LOCKED_OUT,
182     PROMPT_REASON_DEFAULT,
183     PROMPT_REASON_NONE,
184     PROMPT_REASON_RESTART,
185     PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT,
186     PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE,
187 )
188 annotation class BouncerPromptReason
189 
190 private fun defaultMessage(securityMode: SecurityMode): Pair<Int, Int> {
191     return when (securityMode) {
192         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
193         SecurityMode.Password -> Pair(keyguard_enter_password, 0)
194         SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
195         else -> Pair(0, 0)
196     }
197 }
198 
199 private fun defaultMessageWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> {
200     return when (securityMode) {
201         SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, 0)
202         SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, 0)
203         SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, 0)
204         else -> Pair(0, 0)
205     }
206 }
207 
208 private fun incorrectSecurityInput(securityMode: SecurityMode): Pair<Int, Int> {
209     return when (securityMode) {
210         SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, 0)
211         SecurityMode.Password -> Pair(kg_wrong_password_try_again, 0)
212         SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, 0)
213         else -> Pair(0, 0)
214     }
215 }
216 
217 private fun incorrectSecurityInputWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> {
218     return when (securityMode) {
219         SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, kg_wrong_input_try_fp_suggestion)
220         SecurityMode.Password -> Pair(kg_wrong_password_try_again, kg_wrong_input_try_fp_suggestion)
221         SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, kg_wrong_input_try_fp_suggestion)
222         else -> Pair(0, 0)
223     }
224 }
225 
226 private fun incorrectFingerprintInput(securityMode: SecurityMode): Pair<Int, Int> {
227     return when (securityMode) {
228         SecurityMode.Pattern -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pattern)
229         SecurityMode.Password -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_password)
230         SecurityMode.PIN -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pin)
231         else -> Pair(0, 0)
232     }
233 }
234 
235 private fun incorrectFaceInput(securityMode: SecurityMode): Pair<Int, Int> {
236     return when (securityMode) {
237         SecurityMode.Pattern -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pattern)
238         SecurityMode.Password -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_password)
239         SecurityMode.PIN -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pin)
240         else -> Pair(0, 0)
241     }
242 }
243 
244 private fun incorrectFaceInputWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
245     return when (securityMode) {
246         SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, bouncer_face_not_recognized)
247         SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, bouncer_face_not_recognized)
248         SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, bouncer_face_not_recognized)
249         else -> Pair(0, 0)
250     }
251 }
252 
253 private fun biometricLockout(securityMode: SecurityMode): Pair<Int, Int> {
254     return when (securityMode) {
255         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_bio_too_many_attempts_pattern)
256         SecurityMode.Password -> Pair(keyguard_enter_password, kg_bio_too_many_attempts_password)
257         SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_bio_too_many_attempts_pin)
258         else -> Pair(0, 0)
259     }
260 }
261 
262 private fun authRequiredAfterReboot(securityMode: SecurityMode): Pair<Int, Int> {
263     return when (securityMode) {
264         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_reason_restart_pattern)
265         SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_reason_restart_password)
266         SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin)
267         else -> Pair(0, 0)
268     }
269 }
270 
271 private fun authRequiredAfterAdminLockdown(securityMode: SecurityMode): Pair<Int, Int> {
272     return when (securityMode) {
273         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_dpm_lock)
274         SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_after_dpm_lock)
275         SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock)
276         else -> Pair(0, 0)
277     }
278 }
279 
280 private fun authRequiredAfterUserLockdown(securityMode: SecurityMode): Pair<Int, Int> {
281     return when (securityMode) {
282         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_user_lockdown_pattern)
283         SecurityMode.Password ->
284             Pair(keyguard_enter_password, kg_prompt_after_user_lockdown_password)
285         SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin)
286         else -> Pair(0, 0)
287     }
288 }
289 
290 private fun authRequiredForUnattendedUpdate(securityMode: SecurityMode): Pair<Int, Int> {
291     return when (securityMode) {
292         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_unattended_update)
293         SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_unattended_update)
294         SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_unattended_update)
295         else -> Pair(0, 0)
296     }
297 }
298 
299 private fun authRequiredForMainlineUpdate(securityMode: SecurityMode): Pair<Int, Int> {
300     return when (securityMode) {
301         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_update_pattern)
302         SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_after_update_password)
303         SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_update_pin)
304         else -> Pair(0, 0)
305     }
306 }
307 
308 private fun authRequiredAfterPrimaryAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> {
309     return when (securityMode) {
310         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_pattern_auth_timeout)
311         SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_password_auth_timeout)
312         SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout)
313         else -> Pair(0, 0)
314     }
315 }
316 
317 private fun nonStrongAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> {
318     return when (securityMode) {
319         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_auth_timeout)
320         SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_auth_timeout)
321         SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_auth_timeout)
322         else -> Pair(0, 0)
323     }
324 }
325 
326 private fun nonStrongAuthTimeoutWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
327     return when (securityMode) {
328         SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_prompt_auth_timeout)
329         SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_prompt_auth_timeout)
330         SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_prompt_auth_timeout)
331         else -> Pair(0, 0)
332     }
333 }
334 
335 private fun faceLockedOut(securityMode: SecurityMode): Pair<Int, Int> {
336     return when (securityMode) {
337         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_face_locked_out)
338         SecurityMode.Password -> Pair(keyguard_enter_password, kg_face_locked_out)
339         SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_face_locked_out)
340         else -> Pair(0, 0)
341     }
342 }
343 
344 private fun faceLockedOutButFingerprintAvailable(securityMode: SecurityMode): Pair<Int, Int> {
345     return when (securityMode) {
346         SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_face_locked_out)
347         SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_face_locked_out)
348         SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_face_locked_out)
349         else -> Pair(0, 0)
350     }
351 }
352 
353 private fun fingerprintUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> {
354     return when (securityMode) {
355         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_fp_locked_out)
356         SecurityMode.Password -> Pair(keyguard_enter_password, kg_fp_locked_out)
357         SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_fp_locked_out)
358         else -> Pair(0, 0)
359     }
360 }
361 
362 private fun trustAgentDisabled(securityMode: SecurityMode): Pair<Int, Int> {
363     return when (securityMode) {
364         SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_trust_agent_disabled)
365         SecurityMode.Password -> Pair(keyguard_enter_password, kg_trust_agent_disabled)
366         SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_trust_agent_disabled)
367         else -> Pair(0, 0)
368     }
369 }
370 
371 private fun trustAgentDisabledWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
372     return when (securityMode) {
373         SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_trust_agent_disabled)
374         SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_trust_agent_disabled)
375         SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_trust_agent_disabled)
376         else -> Pair(0, 0)
377     }
378 }
379 
380 private fun primaryAuthLockedOut(securityMode: SecurityMode): Pair<Int, Int> {
381     return when (securityMode) {
382         SecurityMode.Pattern ->
383             Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pattern)
384         SecurityMode.Password ->
385             Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_password)
386         SecurityMode.PIN ->
387             Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pin)
388         else -> Pair(0, 0)
389     }
390 }
391