• 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.Manifest
20 import android.content.Intent
21 import android.os.Build
22 import android.os.Bundle
23 import android.os.UserHandle
24 import android.view.LayoutInflater
25 import android.view.View
26 import android.view.ViewGroup
27 import androidx.annotation.RequiresApi
28 import androidx.compose.ui.platform.ComposeView
29 import androidx.fragment.app.Fragment
30 import androidx.lifecycle.ViewModelProvider
31 import com.android.modules.utils.build.SdkLevel
32 import com.android.permissioncontroller.Constants
33 import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage
34 import com.android.permissioncontroller.permission.model.v31.PermissionUsages
35 import com.android.permissioncontroller.permission.model.v31.PermissionUsages.PermissionsUsagesChangeCallback
36 import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModel
37 import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModelFactory
38 import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModel
39 import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModelFactory
40 import com.android.permissioncontroller.permission.ui.wear.model.WearLocationProviderInterceptDialogViewModel
41 import com.android.permissioncontroller.permission.ui.wear.model.WearLocationProviderInterceptDialogViewModelFactory
42 
43 /**
44  * This is a condensed version of
45  * [com.android.permissioncontroller.permission.ui.handheld.PermissionAppsFragment], tailored for
46  * Wear.
47  *
48  * Show and manage apps which request a single permission group.
49  *
50  * <p>Shows a list of apps which request at least on permission of this group.
51  */
52 class WearPermissionAppsFragment : Fragment(), PermissionsUsagesChangeCallback {
53     private val LOG_TAG = "PermissionAppsFragment"
54 
55     private lateinit var permissionUsages: PermissionUsages
56     private lateinit var wearViewModel: WearAppPermissionUsagesViewModel
57 
58     // Suppress warning of the deprecated class [android.app.LoaderManager] since other form factors
59     // are using the class to load PermissionUsages.
60     @Suppress("DEPRECATION")
61     override fun onCreateView(
62         inflater: LayoutInflater,
63         container: ViewGroup?,
64         savedInstanceState: Bundle?
65     ): View? {
66         val permGroupName =
67             arguments?.getString(Intent.EXTRA_PERMISSION_GROUP_NAME)
68                 ?: arguments?.getString(Intent.EXTRA_PERMISSION_NAME)
69                 ?: throw RuntimeException("Permission group name must not be null.")
70         val sessionId: Long =
71             arguments?.getLong(Constants.EXTRA_SESSION_ID) ?: Constants.INVALID_SESSION_ID
72         val isStorageAndLessThanT =
73             !SdkLevel.isAtLeastT() && permGroupName == Manifest.permission_group.STORAGE
74 
75         val activity = requireActivity()
76         val factory =
77             PermissionAppsViewModelFactory(activity.getApplication(), permGroupName, this, Bundle())
78         val viewModel = ViewModelProvider(this, factory).get(PermissionAppsViewModel::class.java)
79         wearViewModel =
80             ViewModelProvider(this, WearAppPermissionUsagesViewModelFactory())
81                 .get(WearAppPermissionUsagesViewModel::class.java)
82 
83         val locationProviderDialogViewModel =
84             ViewModelProvider(
85                 owner = this,
86                 factory = WearLocationProviderInterceptDialogViewModelFactory()
87             )[WearLocationProviderInterceptDialogViewModel::class.java]
88 
89         val onAppClick: (String, UserHandle, String) -> Unit = { packageName, user, category ->
90             run {
91                 viewModel.navigateToAppPermission(
92                     this,
93                     packageName,
94                     user,
95                     WearAppPermissionFragment.createArgs(
96                         packageName,
97                         null,
98                         permGroupName,
99                         user,
100                         this::class.java.name,
101                         sessionId,
102                         category
103                     )
104                 )
105             }
106         }
107 
108         val onShowSystemClick: (Boolean) -> Unit = { showSystem ->
109             run { viewModel.updateShowSystem(showSystem) }
110         }
111 
112         val logPermissionAppsFragmentCreated:
113             (String, UserHandle, Long, Boolean, Boolean, Boolean) -> Unit =
114             { packageName, user, viewId, isAllowed, isAllowedForeground, isDenied ->
115                 run {
116                     viewModel.logPermissionAppsFragmentCreated(
117                         packageName,
118                         user,
119                         viewId,
120                         isAllowed,
121                         isAllowedForeground,
122                         isDenied,
123                         sessionId,
124                         activity.application,
125                         permGroupName,
126                         LOG_TAG
127                     )
128                 }
129             }
130 
131         // If the build type is below S, the app ops for permission usage can't be found. Thus, we
132         // shouldn't load permission usages, for them.
133         if (SdkLevel.isAtLeastS()) {
134             permissionUsages = PermissionUsages(requireContext())
135 
136             val filterTimeBeginMillis: Long = viewModel.getFilterTimeBeginMillis()
137             permissionUsages.load(
138                 null,
139                 null,
140                 filterTimeBeginMillis,
141                 Long.MAX_VALUE,
142                 PermissionUsages.USAGE_FLAG_LAST,
143                 requireActivity().loaderManager,
144                 false,
145                 false,
146                 this,
147                 false
148             )
149         }
150 
151         return ComposeView(requireContext()).apply {
152             setContent {
153                 WearPermissionAppsScreen(
154                     WearPermissionAppsHelper(
155                         activity.application,
156                         this@WearPermissionAppsFragment.requireContext(),
157                         permGroupName,
158                         viewModel,
159                         wearViewModel,
160                         locationProviderDialogViewModel,
161                         isStorageAndLessThanT,
162                         onAppClick,
163                         onShowSystemClick,
164                         logPermissionAppsFragmentCreated
165                     )
166                 )
167             }
168         }
169     }
170 
171     @RequiresApi(Build.VERSION_CODES.S)
172     override fun onPermissionUsagesChanged() {
173         if (permissionUsages.usages.isEmpty()) {
174             return
175         }
176         if (context == null) {
177             // Async result has come in after our context is gone.
178             return
179         }
180         wearViewModel.appPermissionUsages.value =
181             ArrayList<AppPermissionUsage>(permissionUsages.usages)
182     }
183 }
184