blob: 3078193280730a70dda08f962fe085c14b3fea53 [file] [log] [blame]
/*
* 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.Application
import android.content.pm.PackageManager
import android.util.Log
import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.permission.model.livedatatypes.LightPermInfo
import com.android.permissioncontroller.permission.utils.Utils.OS_PKG
import com.android.permissioncontroller.permission.utils.Utils.isRuntimePlatformPermission
import kotlinx.coroutines.Job
/**
* LiveData for a LightPermInfo.
*
* @param app current Application
* @param permissionName name of the permission this LiveData will watch for mode changes for
*/
class LightPermInfoLiveData private constructor(
private val app: Application,
private val permissionName: String
) : SmartAsyncMediatorLiveData<LightPermInfo>(),
PackageBroadcastReceiver.PackageBroadcastListener {
private val LOG_TAG = LightPermInfoLiveData::class.java.simpleName
/** Is this liveData currently listing for changes */
private var isListeningForChanges = false
/**
* Callback from the PackageBroadcastReceiver.
*
* <p>Package updates might change permission properties
*/
override fun onPackageUpdate(ignored: String) {
updateAsync()
}
override fun updateAsync() {
// No need to update if the value can never change
if (value != null && isImmutable()) {
return
}
super.updateAsync()
}
override suspend fun loadDataAndPostValue(job: Job) {
if (job.isCancelled) {
return
}
val newValue = try {
LightPermInfo(app.packageManager.getPermissionInfo(permissionName, 0))
} catch (e: PackageManager.NameNotFoundException) {
Log.w(LOG_TAG, "Permission \"$permissionName\" not found")
invalidateSingle(permissionName)
null
}
if (isImmutable()) {
stopListeningForChanges()
}
postValue(newValue)
}
/**
* @return if the permission state can never change
*/
private fun isImmutable(): Boolean {
// The os package never changes
value?.let {
if (it.packageName == OS_PKG) {
return true
}
}
// Platform permissions never change
return isRuntimePlatformPermission(permissionName)
}
/**
* Start listing for changes to this permission if needed
*/
private fun startListeningForChanges() {
if (!isListeningForChanges && !isImmutable()) {
isListeningForChanges = true
PackageBroadcastReceiver.addAllCallback(this)
}
}
/**
* Stop listing for changes to this permission
*/
private fun stopListeningForChanges() {
if (isListeningForChanges) {
PackageBroadcastReceiver.removeAllCallback(this)
isListeningForChanges = false
}
}
override fun onActive() {
super.onActive()
startListeningForChanges()
updateAsync()
}
override fun onInactive() {
super.onInactive()
stopListeningForChanges()
}
/**
* Repository for LightPermInfoLiveData
*
* <p>Key value is a string permission name, value is its corresponding LiveData.
*/
companion object : DataRepositoryForPackage<String, LightPermInfoLiveData>() {
override fun newValue(key: String): LightPermInfoLiveData {
return LightPermInfoLiveData(PermissionControllerApplication.get(), key)
}
}
}