Files
Lawnchair/src/com/android/launcher3/util/ApplicationInfoWrapper.kt
T
Sunny Goyal 28d6bbd6b4 Moving various application into related methods to a separate class
> This avoids duplicate RPCs when trying to get multiple properties
  from AppInfo
> This would be used in a followup cl when AppInfo is added to caching
  logic in IconCache

Bug: 366237794
Test: atest ApplicationInfoWrapperTest
Flag: EXEMPT refactor
Change-Id: I55b964d4f8cfa1ff1770e310ac278719495e285d
2024-09-23 22:09:24 -07:00

116 lines
4.1 KiB
Kotlin

/*
* Copyright (C) 2024 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.launcher3.util
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.ApplicationInfo.FLAG_EXTERNAL_STORAGE
import android.content.pm.ApplicationInfo.FLAG_INSTALLED
import android.content.pm.ApplicationInfo.FLAG_SUSPENDED
import android.content.pm.ApplicationInfo.FLAG_SYSTEM
import android.content.pm.LauncherApps
import android.content.pm.PackageManager
import android.content.pm.PackageManager.NameNotFoundException
import android.os.UserHandle
import com.android.launcher3.Flags.enableSupportForArchiving
import com.android.launcher3.Utilities.ATLEAST_V
import kotlin.LazyThreadSafetyMode.NONE
/**
* A set of utility methods around ApplicationInfo with support for fetching the actual info lazily
*/
class ApplicationInfoWrapper private constructor(provider: () -> ApplicationInfo?) {
constructor(appInfo: ApplicationInfo?) : this({ appInfo })
constructor(
ctx: Context,
pkg: String,
user: UserHandle,
) : this({
try {
ctx.getSystemService(LauncherApps::class.java)
?.getApplicationInfo(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, user)
?.let { ai ->
// its enabled and (either installed or archived)
if (
ai.enabled &&
(ai.flags.and(FLAG_INSTALLED) != 0 ||
(ATLEAST_V && enableSupportForArchiving() && ai.isArchived))
) {
ai
} else {
null
}
}
} catch (e: NameNotFoundException) {
null
}
})
constructor(
ctx: Context,
intent: Intent,
) : this(
provider@{
try {
val pm = ctx.packageManager
val packageName: String =
intent.component?.packageName
?: intent.getPackage()
?: return@provider pm.resolveActivity(
intent,
PackageManager.MATCH_DEFAULT_ONLY,
)
?.activityInfo
?.applicationInfo
pm.getApplicationInfo(packageName, 0)
} catch (e: NameNotFoundException) {
null
}
}
)
private val appInfo: ApplicationInfo? by lazy(NONE, provider)
private fun hasFlag(flag: Int) = appInfo?.let { it.flags.and(flag) != 0 } ?: false
/**
* Returns true if the app can possibly be on the SDCard. This is just a workaround and doesn't
* guarantee that the app is on SD card.
*/
fun isOnSdCard() = hasFlag(FLAG_EXTERNAL_STORAGE)
/** Returns whether the target app is installed for a given user */
fun isInstalled() = hasFlag(FLAG_INSTALLED)
/**
* Returns whether the target app is suspended for a given user as per
* [android.app.admin.DevicePolicyManager.isPackageSuspended].
*/
fun isSuspended() = hasFlag(FLAG_INSTALLED) && hasFlag(FLAG_SUSPENDED)
/** Returns whether the target app is archived for a given user */
fun isArchived() = ATLEAST_V && enableSupportForArchiving() && appInfo?.isArchived ?: false
/** Returns whether the target app is a system app */
fun isSystem() = hasFlag(FLAG_SYSTEM)
fun getInfo(): ApplicationInfo? = appInfo
}