• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2020 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.data
18 
19 import android.app.AppOpsManager.permissionToOp
20 import android.app.Application
21 import com.android.permissioncontroller.PermissionControllerApplication
22 import com.android.permissioncontroller.permission.utils.Utils.getPlatformPermissionNamesOfGroup
23 import kotlin.collections.set
24 
25 /**
26  * LiveData that loads the last usage of permission group for every package/attributionTag-pair.
27  *
28  * <p>This relies on app-ops data, hence this only works for platform defined permission groups.
29  *
30  * <p>For app-ops with duration the end of the access is considered.
31  *
32  * <p>Returns map perm-group-name -> {@link OpUsageLiveData.OpAccess}
33  *
34  * @param app The current application
35  * @param permGroupsNames The names of the permission groups we wish to search for
36  * @param usageDurationMs how much ago can an access have happened to be considered
37  */
38 class PermGroupUsageLiveData(
39     private val app: Application,
40     private val permGroupsNames: List<String>,
41     private val usageDurationMs: Long
42 ) : SmartUpdateMediatorLiveData<Map<String, List<OpAccess>>>() {
43     /** Perm group name -> OpUsageLiveData */
44     private val permGroupUsages = permGroupsNames.map { permGroup ->
45         val appops = getPlatformPermissionNamesOfGroup(permGroup).mapNotNull { permName ->
46             permissionToOp(permName)
47         }
48 
49         permGroup to OpUsageLiveData[appops, usageDurationMs]
50     }.toMap()
51 
52     init {
53         for (usage in permGroupUsages.values) {
54             addSource(usage) {
55                 update()
56             }
57         }
58     }
59 
60     override fun onUpdate() {
61         if (permGroupUsages.values.any { !it.isInitialized }) {
62             return
63         }
64 
65         if (permGroupUsages.values.any { it.value == null }) {
66             value = null
67             return
68         }
69 
70         // Only keep the last access for a permission group
71         value = permGroupUsages.map { (permGroupName, usageLiveData) ->
72             // (packageName, attributionTag) -> access
73             val lastAccess = mutableMapOf<Pair<String, String?>, OpAccess>()
74             for (access in usageLiveData.value!!.values.flatten()) {
75                 val key = access.packageName to access.attributionTag
76                 if (access.isRunning ||
77                         lastAccess[key]?.lastAccessTime ?: 0 < access.lastAccessTime) {
78                     lastAccess[key] = access
79                 }
80             }
81 
82             permGroupName to lastAccess.values.toList()
83         }.toMap()
84     }
85 
86     companion object : DataRepository<Pair<List<String>, Long>, PermGroupUsageLiveData>() {
87         override fun newValue(key: Pair<List<String>, Long>): PermGroupUsageLiveData {
88             return PermGroupUsageLiveData(PermissionControllerApplication.get(), key.first,
89                     key.second)
90         }
91     }
92 }
93