Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package com.android.permissioncontroller.permission.data |
| 18 | |
| 19 | import android.app.AppOpsManager |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 20 | import android.app.AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED |
| 21 | import android.app.Application |
| 22 | import android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT |
| 23 | import android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE |
| 24 | import android.os.UserHandle |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 25 | import com.android.permissioncontroller.PermissionControllerApplication |
| 26 | import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData.Companion.NON_RUNTIME_NORMAL_PERMS |
Kevin Han | 5f99f69 | 2021-03-08 18:28:06 -0800 | [diff] [blame] | 27 | import com.android.permissioncontroller.permission.model.livedatatypes.HibernationSettingState |
Kevin Han | 91e447c | 2021-02-04 20:24:08 -0800 | [diff] [blame] | 28 | import com.android.permissioncontroller.hibernation.ExemptServicesLiveData |
Kevin Han | 03ea65e | 2021-03-02 12:35:10 -0800 | [diff] [blame] | 29 | import com.android.permissioncontroller.hibernation.HibernationEnabledLiveData |
Kevin Han | e75de21 | 2021-02-04 22:40:49 -0800 | [diff] [blame] | 30 | import com.android.permissioncontroller.hibernation.isHibernationJobEnabled |
Kevin Han | 8ba3b0e | 2021-02-08 21:08:13 -0800 | [diff] [blame] | 31 | import com.android.permissioncontroller.hibernation.isPackageHibernationExemptByUser |
Kevin Han | e75de21 | 2021-02-04 22:40:49 -0800 | [diff] [blame] | 32 | import com.android.permissioncontroller.hibernation.isPackageHibernationExemptBySystem |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 33 | import kotlinx.coroutines.Job |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 34 | |
| 35 | /** |
Kevin Han | 5f99f69 | 2021-03-08 18:28:06 -0800 | [diff] [blame] | 36 | * A LiveData which tracks the hibernation/auto-revoke state for one user package. |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 37 | * |
| 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 Han | 5f99f69 | 2021-03-08 18:28:06 -0800 | [diff] [blame] | 42 | class HibernationSettingStateLiveData private constructor( |
Eugene Susla | 7fc8cd5 | 2020-04-02 18:07:00 -0700 | [diff] [blame] | 43 | private val app: Application, |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 44 | private val packageName: String, |
| 45 | private val user: UserHandle |
Kevin Han | 5f99f69 | 2021-03-08 18:28:06 -0800 | [diff] [blame] | 46 | ) : SmartAsyncMediatorLiveData<HibernationSettingState>(), AppOpsManager.OnOpChangedListener { |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 47 | |
| 48 | private val packagePermsLiveData = |
| 49 | PackagePermissionsLiveData[packageName, user] |
| 50 | private val packageLiveData = LightPackageInfoLiveData[packageName, user] |
| 51 | private val permStateLiveDatas = mutableMapOf<String, PermStateLiveData>() |
Nate Myren | 0b7d023 | 2020-06-02 12:00:24 -0700 | [diff] [blame] | 52 | private val exemptServicesLiveData = ExemptServicesLiveData[user] |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 53 | private val appOpsManager = app.getSystemService(AppOpsManager::class.java)!! |
| 54 | |
| 55 | init { |
| 56 | addSource(packagePermsLiveData) { |
Colin Cross | e877ec7 | 2020-08-27 04:12:26 +0000 | [diff] [blame] | 57 | update() |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 58 | } |
| 59 | addSource(packageLiveData) { |
Colin Cross | e877ec7 | 2020-08-27 04:12:26 +0000 | [diff] [blame] | 60 | update() |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 61 | } |
Nate Myren | 0b7d023 | 2020-06-02 12:00:24 -0700 | [diff] [blame] | 62 | addSource(exemptServicesLiveData) { |
Colin Cross | e877ec7 | 2020-08-27 04:12:26 +0000 | [diff] [blame] | 63 | update() |
Nate Myren | 0b7d023 | 2020-06-02 12:00:24 -0700 | [diff] [blame] | 64 | } |
Kevin Han | 03ea65e | 2021-03-02 12:35:10 -0800 | [diff] [blame] | 65 | addSource(HibernationEnabledLiveData) { |
| 66 | update() |
| 67 | } |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | override suspend fun loadDataAndPostValue(job: Job) { |
Nate Myren | 0b7d023 | 2020-06-02 12:00:24 -0700 | [diff] [blame] | 71 | if (!packageLiveData.isInitialized || !packagePermsLiveData.isInitialized || |
| 72 | !exemptServicesLiveData.isInitialized) { |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 73 | return |
| 74 | } |
| 75 | |
| 76 | val groups = packagePermsLiveData.value?.keys?.filter { it != NON_RUNTIME_NORMAL_PERMS } |
Nate Myren | 0b7d023 | 2020-06-02 12:00:24 -0700 | [diff] [blame] | 77 | |
| 78 | if (packageLiveData.value?.uid == null || groups == null) { |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 79 | postValue(null) |
| 80 | return |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 81 | } |
| 82 | |
Nate Myren | 60421a8 | 2020-05-19 17:12:08 -0700 | [diff] [blame] | 83 | val getLiveData = { groupName: String -> PermStateLiveData[packageName, groupName, user] } |
| 84 | setSourcesToDifference(groups, permStateLiveDatas, getLiveData) |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 85 | |
| 86 | if (!permStateLiveDatas.all { it.value.isInitialized }) { |
| 87 | return |
| 88 | } |
| 89 | |
Kevin Han | 5f99f69 | 2021-03-08 18:28:06 -0800 | [diff] [blame] | 90 | val canHibernate = !isPackageHibernationExemptByUser(app, packageLiveData.value!!) |
Eugene Susla | d4d2c24 | 2020-06-02 13:15:40 -0700 | [diff] [blame] | 91 | val revocableGroups = mutableListOf<String>() |
Kevin Han | e75de21 | 2021-02-04 22:40:49 -0800 | [diff] [blame] | 92 | if (!isPackageHibernationExemptBySystem(packageLiveData.value!!, user)) { |
Eugene Susla | d4d2c24 | 2020-06-02 13:15:40 -0700 | [diff] [blame] | 93 | 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 Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 101 | } |
| 102 | } |
| 103 | |
Zhen Zhang | 3fc6735 | 2021-06-24 15:25:44 -0700 | [diff] [blame] | 104 | postValue(HibernationSettingState(isHibernationJobEnabled(), canHibernate, revocableGroups)) |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 105 | } |
| 106 | |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 107 | override fun onOpChanged(op: String?, packageName: String?) { |
| 108 | if (op == OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED && packageName == packageName) { |
Colin Cross | e877ec7 | 2020-08-27 04:12:26 +0000 | [diff] [blame] | 109 | update() |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 110 | } |
| 111 | } |
| 112 | |
| 113 | override fun onActive() { |
| 114 | super.onActive() |
| 115 | appOpsManager.startWatchingMode(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageName, this) |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 116 | } |
| 117 | |
| 118 | override fun onInactive() { |
| 119 | super.onInactive() |
| 120 | appOpsManager.stopWatchingMode(this) |
| 121 | } |
| 122 | /** |
Kevin Han | 5f99f69 | 2021-03-08 18:28:06 -0800 | [diff] [blame] | 123 | * Repository for HibernationSettingStateLiveDatas. |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 124 | * <p> Key value is a pair of string package name and UserHandle, value is its corresponding |
| 125 | * LiveData. |
| 126 | */ |
Nate Myren | 2b64bd3 | 2020-03-24 11:38:14 -0700 | [diff] [blame] | 127 | companion object : DataRepositoryForPackage<Pair<String, UserHandle>, |
Kevin Han | 5f99f69 | 2021-03-08 18:28:06 -0800 | [diff] [blame] | 128 | HibernationSettingStateLiveData>() { |
| 129 | override fun newValue(key: Pair<String, UserHandle>): HibernationSettingStateLiveData { |
| 130 | return HibernationSettingStateLiveData(PermissionControllerApplication.get(), |
Nate Myren | 33e4225 | 2020-02-07 12:30:47 -0800 | [diff] [blame] | 131 | key.first, key.second) |
| 132 | } |
| 133 | } |
| 134 | } |