/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.permissioncontroller.permission.data import android.app.AppOpsManager.permissionToOp import android.app.Application import com.android.permissioncontroller.PermissionControllerApplication import com.android.permissioncontroller.permission.utils.Utils.getPlatformPermissionNamesOfGroup import kotlin.collections.set /** * LiveData that loads the last usage of permission group for every package/attributionTag-pair. * *

This relies on app-ops data, hence this only works for platform defined permission groups. * *

For app-ops with duration the end of the access is considered. * *

Returns map perm-group-name -> {@link OpUsageLiveData.OpAccess} * * @param app The current application * @param permGroupsNames The names of the permission groups we wish to search for * @param usageDurationMs how much ago can an access have happened to be considered */ class PermGroupUsageLiveData( private val app: Application, private val permGroupsNames: List, private val usageDurationMs: Long ) : SmartUpdateMediatorLiveData>>() { /** Perm group name -> OpUsageLiveData */ private val permGroupUsages = permGroupsNames.map { permGroup -> val appops = getPlatformPermissionNamesOfGroup(permGroup).mapNotNull { permName -> permissionToOp(permName) } permGroup to OpUsageLiveData[appops, usageDurationMs] }.toMap() init { for (usage in permGroupUsages.values) { addSource(usage) { update() } } } override fun onUpdate() { if (permGroupUsages.values.any { !it.isInitialized }) { return } if (permGroupUsages.values.any { it.value == null }) { value = null return } // Only keep the last access for a permission group value = permGroupUsages.map { (permGroupName, usageLiveData) -> // (packageName, attributionTag) -> access val lastAccess = mutableMapOf, OpAccess>() for (access in usageLiveData.value!!.values.flatten()) { val key = access.packageName to access.attributionTag if (access.isRunning || lastAccess[key]?.lastAccessTime ?: 0 < access.lastAccessTime) { lastAccess[key] = access } } permGroupName to lastAccess.values.toList() }.toMap() } companion object : DataRepository, Long>, PermGroupUsageLiveData>() { override fun newValue(key: Pair, Long>): PermGroupUsageLiveData { return PermGroupUsageLiveData(PermissionControllerApplication.get(), key.first, key.second) } } }