1 /*
<lambda>null2 * 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.permissioncontroller.permission.ui.wear
18
19 import android.os.Build
20 import androidx.annotation.RequiresApi
21 import androidx.compose.foundation.layout.fillMaxWidth
22 import androidx.compose.runtime.Composable
23 import androidx.compose.runtime.getValue
24 import androidx.compose.runtime.livedata.observeAsState
25 import androidx.compose.runtime.mutableStateOf
26 import androidx.compose.runtime.remember
27 import androidx.compose.runtime.setValue
28 import androidx.compose.ui.Modifier
29 import androidx.compose.ui.platform.LocalContext
30 import androidx.compose.ui.res.stringResource
31 import com.android.permissioncontroller.R
32 import com.android.permissioncontroller.permission.ui.handheld.v31.PermissionUsageControlPreference
33 import com.android.permissioncontroller.permission.ui.viewmodel.v31.PermissionUsageViewModel
34 import com.android.permissioncontroller.permission.ui.viewmodel.v31.PermissionUsagesUiState
35 import com.android.permissioncontroller.permission.ui.wear.elements.Chip
36 import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
37 import com.android.permissioncontroller.permission.ui.wear.model.WearPermissionUsageViewModel
38 import com.android.permissioncontroller.permission.utils.Utils
39 import java.text.Collator
40
41 @RequiresApi(Build.VERSION_CODES.S)
42 @Composable
43 fun WearPermissionUsageScreen(
44 sessionId: Long,
45 viewModel: PermissionUsageViewModel,
46 wearViewModel: WearPermissionUsageViewModel
47 ) {
48 val context = LocalContext.current
49 val permissionUsagesUiData = wearViewModel.permissionUsagesUiStateLiveData.observeAsState(null)
50 val showSystem = wearViewModel.showSystemAppsLiveData.observeAsState(false)
51 val show7Days = wearViewModel.show7DaysLiveData.observeAsState(false)
52 var isLoading by remember { mutableStateOf(true) }
53 val isDataLoaded = permissionUsagesUiData.value is PermissionUsagesUiState.Success
54 val hasSystemApps: Boolean =
55 if (isDataLoaded) {
56 val uiState = permissionUsagesUiData.value as PermissionUsagesUiState.Success
57 uiState.shouldShowSystemToggle
58 } else {
59 false
60 }
61 val onShowSystemClick: (Boolean) -> Unit = { show ->
62 run {
63 wearViewModel.updatePermissionUsagesUiStateLiveData(viewModel.updateShowSystem(show))
64 wearViewModel.showSystemAppsLiveData.value = viewModel.getShowSystemApps()
65 }
66 }
67
68 val permissionGroupWithUsageCounts: Map<String, Int> =
69 if (isDataLoaded) {
70 val uiState = permissionUsagesUiData.value as PermissionUsagesUiState.Success
71 uiState.permissionGroupUsageCount
72 } else {
73 emptyMap()
74 }
75 val permissionGroupWithUsageCountsEntries: List<Map.Entry<String, Int>> =
76 ArrayList<Map.Entry<String, Int>>(permissionGroupWithUsageCounts.entries)
77
78 val collator = Collator.getInstance(context.resources.configuration.locales.get(0))
79 val permissionGroupPreferences =
80 permissionGroupWithUsageCountsEntries
81 // Removing Health Connect from the list of permissions to fix b/331260850
82 .filterNot { Utils.isHealthPermissionGroup(it.key) }
83 .map {
84 PermissionUsageControlPreference(
85 context,
86 it.key,
87 it.value,
88 showSystem.value,
89 sessionId,
90 show7Days.value
91 )
92 }
93 .sortedWith { o1, o2 ->
94 var result = collator.compare(o1.title.toString(), o2.title.toString())
95 if (result == 0) {
96 result = o1.title.toString().compareTo(o2.title.toString())
97 }
98 result
99 }
100 .toList()
101
102 WearPermissionUsageContent(
103 isLoading,
104 hasSystemApps,
105 showSystem.value,
106 onShowSystemClick,
107 permissionGroupPreferences
108 )
109
110 if (isLoading && isDataLoaded) {
111 isLoading = false
112 }
113 }
114
115 @Composable
WearPermissionUsageContentnull116 internal fun WearPermissionUsageContent(
117 isLoading: Boolean,
118 hasSystemApps: Boolean,
119 showSystem: Boolean,
120 onShowSystemClick: (Boolean) -> Unit,
121 permissionGroupPreferences: List<PermissionUsageControlPreference>
122 ) {
123 ScrollableScreen(
124 title = stringResource(R.string.permission_usage_title),
125 isLoading = isLoading
126 ) {
127 if (permissionGroupPreferences.isEmpty()) {
128 item { Chip(label = stringResource(R.string.no_permissions), onClick = {}) }
129 } else {
130 for (preference in permissionGroupPreferences) {
131 item {
132 Chip(
133 label = preference.title.toString(),
134 labelMaxLines = Int.MAX_VALUE,
135 secondaryLabel = preference.summary.toString(),
136 secondaryLabelMaxLines = Int.MAX_VALUE,
137 icon = preference.icon,
138 enabled = preference.isEnabled,
139 onClick = { preference.performClick() }
140 )
141 }
142 }
143 if (hasSystemApps) {
144 item {
145 Chip(
146 label =
147 if (showSystem) {
148 stringResource(R.string.menu_hide_system)
149 } else {
150 stringResource(R.string.menu_show_system)
151 },
152 labelMaxLines = Int.MAX_VALUE,
153 onClick = { onShowSystemClick(!showSystem) },
154 modifier = Modifier.fillMaxWidth(),
155 )
156 }
157 }
158 }
159 }
160 }
161