blob: 18686875adadc1b1d227d946ecd65019d71d6ff7 [file] [log] [blame]
Nate Myren33e42252020-02-07 12:30:47 -08001/*
2 * 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
17package com.android.permissioncontroller.permission.data
18
19import android.app.AppOpsManager
Nate Myren33e42252020-02-07 12:30:47 -080020import android.app.AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED
21import android.app.Application
22import android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
23import android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE
24import android.os.UserHandle
Nate Myren33e42252020-02-07 12:30:47 -080025import com.android.permissioncontroller.PermissionControllerApplication
26import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData.Companion.NON_RUNTIME_NORMAL_PERMS
Kevin Han5f99f692021-03-08 18:28:06 -080027import com.android.permissioncontroller.permission.model.livedatatypes.HibernationSettingState
Kevin Han91e447c2021-02-04 20:24:08 -080028import com.android.permissioncontroller.hibernation.ExemptServicesLiveData
Kevin Han03ea65e2021-03-02 12:35:10 -080029import com.android.permissioncontroller.hibernation.HibernationEnabledLiveData
Kevin Hane75de212021-02-04 22:40:49 -080030import com.android.permissioncontroller.hibernation.isHibernationJobEnabled
Kevin Han8ba3b0e2021-02-08 21:08:13 -080031import com.android.permissioncontroller.hibernation.isPackageHibernationExemptByUser
Kevin Hane75de212021-02-04 22:40:49 -080032import com.android.permissioncontroller.hibernation.isPackageHibernationExemptBySystem
Nate Myren33e42252020-02-07 12:30:47 -080033import kotlinx.coroutines.Job
Nate Myren33e42252020-02-07 12:30:47 -080034
35/**
Kevin Han5f99f692021-03-08 18:28:06 -080036 * A LiveData which tracks the hibernation/auto-revoke state for one user package.
Nate Myren33e42252020-02-07 12:30:47 -080037 *
38 * @param app The current application
39 * @param packageName The package name whose state we want
40 * @param user The user for whom we want the package
41 */
Kevin Han5f99f692021-03-08 18:28:06 -080042class HibernationSettingStateLiveData private constructor(
Eugene Susla7fc8cd52020-04-02 18:07:00 -070043 private val app: Application,
Nate Myren33e42252020-02-07 12:30:47 -080044 private val packageName: String,
45 private val user: UserHandle
Kevin Han5f99f692021-03-08 18:28:06 -080046) : SmartAsyncMediatorLiveData<HibernationSettingState>(), AppOpsManager.OnOpChangedListener {
Nate Myren33e42252020-02-07 12:30:47 -080047
48 private val packagePermsLiveData =
49 PackagePermissionsLiveData[packageName, user]
50 private val packageLiveData = LightPackageInfoLiveData[packageName, user]
51 private val permStateLiveDatas = mutableMapOf<String, PermStateLiveData>()
Nate Myren0b7d0232020-06-02 12:00:24 -070052 private val exemptServicesLiveData = ExemptServicesLiveData[user]
Nate Myren33e42252020-02-07 12:30:47 -080053 private val appOpsManager = app.getSystemService(AppOpsManager::class.java)!!
54
55 init {
56 addSource(packagePermsLiveData) {
Colin Crosse877ec72020-08-27 04:12:26 +000057 update()
Nate Myren33e42252020-02-07 12:30:47 -080058 }
59 addSource(packageLiveData) {
Colin Crosse877ec72020-08-27 04:12:26 +000060 update()
Nate Myren33e42252020-02-07 12:30:47 -080061 }
Nate Myren0b7d0232020-06-02 12:00:24 -070062 addSource(exemptServicesLiveData) {
Colin Crosse877ec72020-08-27 04:12:26 +000063 update()
Nate Myren0b7d0232020-06-02 12:00:24 -070064 }
Kevin Han03ea65e2021-03-02 12:35:10 -080065 addSource(HibernationEnabledLiveData) {
66 update()
67 }
Nate Myren33e42252020-02-07 12:30:47 -080068 }
69
70 override suspend fun loadDataAndPostValue(job: Job) {
Nate Myren0b7d0232020-06-02 12:00:24 -070071 if (!packageLiveData.isInitialized || !packagePermsLiveData.isInitialized ||
72 !exemptServicesLiveData.isInitialized) {
Nate Myren33e42252020-02-07 12:30:47 -080073 return
74 }
75
76 val groups = packagePermsLiveData.value?.keys?.filter { it != NON_RUNTIME_NORMAL_PERMS }
Nate Myren0b7d0232020-06-02 12:00:24 -070077
78 if (packageLiveData.value?.uid == null || groups == null) {
Nate Myren33e42252020-02-07 12:30:47 -080079 postValue(null)
80 return
Nate Myren33e42252020-02-07 12:30:47 -080081 }
82
Nate Myren60421a82020-05-19 17:12:08 -070083 val getLiveData = { groupName: String -> PermStateLiveData[packageName, groupName, user] }
84 setSourcesToDifference(groups, permStateLiveDatas, getLiveData)
Nate Myren33e42252020-02-07 12:30:47 -080085
86 if (!permStateLiveDatas.all { it.value.isInitialized }) {
87 return
88 }
89
Kevin Han5f99f692021-03-08 18:28:06 -080090 val canHibernate = !isPackageHibernationExemptByUser(app, packageLiveData.value!!)
Eugene Suslad4d2c242020-06-02 13:15:40 -070091 val revocableGroups = mutableListOf<String>()
Kevin Hane75de212021-02-04 22:40:49 -080092 if (!isPackageHibernationExemptBySystem(packageLiveData.value!!, user)) {
Eugene Suslad4d2c242020-06-02 13:15:40 -070093 permStateLiveDatas.forEach { (groupName, liveData) ->
94 val default = liveData.value?.any { (_, permState) ->
95 permState.permFlags and (FLAG_PERMISSION_GRANTED_BY_DEFAULT or
96 FLAG_PERMISSION_GRANTED_BY_ROLE) != 0
97 } ?: false
98 if (!default) {
99 revocableGroups.add(groupName)
100 }
Nate Myren33e42252020-02-07 12:30:47 -0800101 }
102 }
103
Zhen Zhang3fc67352021-06-24 15:25:44 -0700104 postValue(HibernationSettingState(isHibernationJobEnabled(), canHibernate, revocableGroups))
Nate Myren33e42252020-02-07 12:30:47 -0800105 }
106
Nate Myren33e42252020-02-07 12:30:47 -0800107 override fun onOpChanged(op: String?, packageName: String?) {
108 if (op == OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED && packageName == packageName) {
Colin Crosse877ec72020-08-27 04:12:26 +0000109 update()
Nate Myren33e42252020-02-07 12:30:47 -0800110 }
111 }
112
113 override fun onActive() {
114 super.onActive()
115 appOpsManager.startWatchingMode(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageName, this)
Nate Myren33e42252020-02-07 12:30:47 -0800116 }
117
118 override fun onInactive() {
119 super.onInactive()
120 appOpsManager.stopWatchingMode(this)
121 }
122 /**
Kevin Han5f99f692021-03-08 18:28:06 -0800123 * Repository for HibernationSettingStateLiveDatas.
Nate Myren33e42252020-02-07 12:30:47 -0800124 * <p> Key value is a pair of string package name and UserHandle, value is its corresponding
125 * LiveData.
126 */
Nate Myren2b64bd32020-03-24 11:38:14 -0700127 companion object : DataRepositoryForPackage<Pair<String, UserHandle>,
Kevin Han5f99f692021-03-08 18:28:06 -0800128 HibernationSettingStateLiveData>() {
129 override fun newValue(key: Pair<String, UserHandle>): HibernationSettingStateLiveData {
130 return HibernationSettingStateLiveData(PermissionControllerApplication.get(),
Nate Myren33e42252020-02-07 12:30:47 -0800131 key.first, key.second)
132 }
133 }
134}