1 /*
2  * Copyright (C) 2021 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.apphibernation.AppHibernationManager
20 import android.content.Context.APP_HIBERNATION_SERVICE
21 import android.os.UserHandle
22 import android.util.Log
23 import com.android.permissioncontroller.DumpableLog
24 import com.android.permissioncontroller.PermissionControllerApplication
25 import com.android.permissioncontroller.permission.utils.Utils.getUserContext
26 import kotlinx.coroutines.Job
27 
28 /**
29  * Tracks which packages have been hibernated.
30  */
31 object HibernatedPackagesLiveData
32     : SmartAsyncMediatorLiveData<Set<Pair<String, UserHandle>>>() {
33     private val LOG_TAG = HibernatedPackagesLiveData::class.java.simpleName
34 
35     init {
36         addSource(AllPackageInfosLiveData) {
37             update()
38         }
39     }
40 
41     override suspend fun loadDataAndPostValue(job: Job) {
42         if (job.isCancelled) {
43             return
44         }
45         if (!AllPackageInfosLiveData.isInitialized) {
46             return
47         }
48         val allPackages = AllPackageInfosLiveData.value!!
49         val hibernatingPackages = mutableSetOf<Pair<String, UserHandle>>()
50         for ((user, pkgs) in allPackages) {
51             val userContext = getUserContext(PermissionControllerApplication.get(), user)
52             val hibernationManager =
53                 userContext.getSystemService(APP_HIBERNATION_SERVICE) as AppHibernationManager
54             for (pkg in pkgs) {
55                 try {
56                     if (hibernationManager.isHibernatingForUser(pkg.packageName)) {
57                         hibernatingPackages.add(pkg.packageName to user)
58                     }
59                 } catch (e: Exception) {
60                     DumpableLog.e(LOG_TAG,
61                         "Failed to get hibernation state of package: ${pkg.packageName}")
62                 }
63             }
64         }
65 
66         Log.i(LOG_TAG, "postValue: $hibernatingPackages")
67 
68         postValue(hibernatingPackages)
69     }
70 }
71 
72 private val hibernatedOrRevokedPackagesLiveData = object
73     : SmartUpdateMediatorLiveData<Set<Pair<String, UserHandle>>>() {
74 
75     init {
76         addSource(AutoRevokedPackagesLiveData) {
77             update()
78         }
79         addSource(HibernatedPackagesLiveData) {
80             update()
81         }
82     }
83 
84     override fun onUpdate() {
85         if (!AutoRevokedPackagesLiveData.isInitialized ||
86             !HibernatedPackagesLiveData.isInitialized) {
87             return
88         }
89         value = AutoRevokedPackagesLiveData.value!!.keys + HibernatedPackagesLiveData.value!!
90     }
91 }
92 val unusedHibernatedOrRevokedPackagesLiveData =
93     UnusedPackagesLiveData(hibernatedOrRevokedPackagesLiveData)