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