1 /*
2  * Copyright (C) 2022 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.v34
18 
19 import android.app.Application
20 import android.content.pm.InstallSourceInfo
21 import android.content.pm.PackageManager
22 import android.os.Process
23 import android.os.UserHandle
24 import android.util.Log
25 import com.android.permissioncontroller.PermissionControllerApplication
26 import com.android.permissioncontroller.permission.data.DataRepositoryForPackage
27 import com.android.permissioncontroller.permission.data.PackageBroadcastReceiver
28 import com.android.permissioncontroller.permission.data.SmartAsyncMediatorLiveData
29 import com.android.permissioncontroller.permission.model.livedatatypes.v34.LightInstallSourceInfo
30 import com.android.permissioncontroller.permission.model.livedatatypes.v34.LightInstallSourceInfo.Companion.INSTALL_SOURCE_UNAVAILABLE
31 import kotlinx.coroutines.Job
32 
33 /**
34  * [LightInstallSourceInfo] [LiveData] for the specified package
35  *
36  * @param app current Application
37  * @param packageName name of the package to get InstallSourceInfo for
38  * @param user The user of the package
39  */
40 class LightInstallSourceInfoLiveData
41 private constructor(
42     private val app: Application,
43     private val packageName: String,
44     private val user: UserHandle
45 ) :
46     SmartAsyncMediatorLiveData<LightInstallSourceInfo>(),
47     PackageBroadcastReceiver.PackageBroadcastListener {
48 
onActivenull49     override fun onActive() {
50         super.onActive()
51         PackageBroadcastReceiver.addChangeCallback(packageName, this)
52     }
53 
onInactivenull54     override fun onInactive() {
55         super.onInactive()
56         PackageBroadcastReceiver.removeChangeCallback(packageName, this)
57     }
58 
59     /**
60      * Callback from the PackageBroadcastReceiver
61      *
62      * @param packageName the name of the package which was updated.
63      */
onPackageUpdatenull64     override fun onPackageUpdate(packageName: String) {
65         update()
66     }
67 
loadDataAndPostValuenull68     override suspend fun loadDataAndPostValue(job: Job) {
69         if (job.isCancelled) {
70             return
71         }
72 
73         val lightInstallSourceInfo: LightInstallSourceInfo =
74             try {
75                 val installSourceInfo = getInstallSourceInfo(packageName)
76                 LightInstallSourceInfo(
77                     installSourceInfo.packageSource,
78                     installSourceInfo.initiatingPackageName
79                 )
80             } catch (e: PackageManager.NameNotFoundException) {
81                 Log.w(LOG_TAG, "InstallSourceInfo for $packageName not found")
82                 invalidateSingle(packageName to user)
83                 INSTALL_SOURCE_UNAVAILABLE
84             }
85         postValue(lightInstallSourceInfo)
86     }
87 
88     /** Returns the [InstallSourceInfo] for the given package. */
89     @Throws(PackageManager.NameNotFoundException::class)
getInstallSourceInfonull90     private fun getInstallSourceInfo(packageName: String): InstallSourceInfo {
91         val userContext =
92             if (user == Process.myUserHandle()) {
93                 app
94             } else {
95                 app.createContextAsUser(user, /* flags= */ 0)
96             }
97         return userContext.packageManager.getInstallSourceInfo(packageName)
98     }
99 
100     companion object :
101         DataRepositoryForPackage<Pair<String, UserHandle>, LightInstallSourceInfoLiveData>() {
102         private val LOG_TAG = LightInstallSourceInfoLiveData::class.java.simpleName
103 
newValuenull104         override fun newValue(key: Pair<String, UserHandle>): LightInstallSourceInfoLiveData {
105             return LightInstallSourceInfoLiveData(
106                 PermissionControllerApplication.get(),
107                 key.first,
108                 key.second
109             )
110         }
111     }
112 }
113