1 package com.android.permissioncontroller.safetycenter.ui.model
2 
3 import android.content.Context
4 import android.os.Build.VERSION_CODES.TIRAMISU
5 import android.safetycenter.SafetyCenterData
6 import android.safetycenter.SafetyCenterStatus
7 import android.safetycenter.SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK
8 import android.safetycenter.SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN
9 import android.util.Log
10 import androidx.annotation.RequiresApi
11 import com.android.permissioncontroller.R
12 
13 /** UI model representation of a Status Card. */
14 @RequiresApi(TIRAMISU)
15 data class StatusUiData(
16     private val status: SafetyCenterStatus,
17     @get:JvmName("hasIssues") val hasIssues: Boolean = false,
18     @get:JvmName("hasPendingActions") val hasPendingActions: Boolean = false
19 ) {
20 
21     constructor(
22         safetyCenterData: SafetyCenterData
23     ) : this(safetyCenterData.status, hasIssues = safetyCenterData.issues.size > 0)
24 
25     // For convenience use in Java.
copyForPendingActionsnull26     fun copyForPendingActions(hasPendingActions: Boolean) =
27         copy(hasPendingActions = hasPendingActions)
28 
29     companion object {
30         private val TAG: String = StatusUiData::class.java.simpleName
31         fun getStatusImageResId(severityLevel: Int) =
32             when (severityLevel) {
33                 OVERALL_SEVERITY_LEVEL_UNKNOWN,
34                 OVERALL_SEVERITY_LEVEL_OK -> R.drawable.safety_status_info
35                 SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_RECOMMENDATION ->
36                     R.drawable.safety_status_recommendation
37                 SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING ->
38                     R.drawable.safety_status_warn
39                 else -> {
40                     Log.w(TAG, "Unexpected OverallSeverityLevel: $severityLevel")
41                     R.drawable.safety_status_info
42                 }
43             }
44     }
45 
46     val title: CharSequence by status::title
47     val originalSummary: CharSequence by status::summary
48     val severityLevel: Int by status::severityLevel
49 
50     val statusImageResId: Int
51         get() = getStatusImageResId(severityLevel)
52 
getSummarynull53     fun getSummary(context: Context): CharSequence {
54         return if (hasPendingActions) {
55             // Use a different string for the special quick-settings-only hasPendingActions state.
56             context.getString(R.string.safety_center_qs_status_summary)
57         } else {
58             originalSummary
59         }
60     }
61 
getContentDescriptionnull62     fun getContentDescription(context: Context): CharSequence {
63         return context.getString(
64             R.string.safety_status_preference_title_and_summary_content_description,
65             title,
66             getSummary(context)
67         )
68     }
69 
70     val isRefreshInProgress: Boolean
71         get() =
72             when (status.refreshStatus) {
73                 SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS,
74                 SafetyCenterStatus.REFRESH_STATUS_DATA_FETCH_IN_PROGRESS -> true
75                 else -> false
76             }
77 
shouldShowRescanButtonnull78     fun shouldShowRescanButton(): Boolean {
79         return !hasIssues &&
80             !hasPendingActions &&
81             when (severityLevel) {
82                 OVERALL_SEVERITY_LEVEL_OK,
83                 OVERALL_SEVERITY_LEVEL_UNKNOWN -> true
84                 else -> false
85             }
86     }
87 
88     enum class ButtonToShow {
89         RESCAN,
90         REVIEW_SETTINGS
91     }
92     val buttonToShow: ButtonToShow?
93         get() =
94             when {
95                 hasIssues -> null
96                 hasPendingActions -> ButtonToShow.REVIEW_SETTINGS
97                 severityLevel == OVERALL_SEVERITY_LEVEL_OK ||
98                     severityLevel == OVERALL_SEVERITY_LEVEL_UNKNOWN -> ButtonToShow.RESCAN
99                 else -> null
100             }
101 }
102