Cleanup AppProcessInfo

This commit is contained in:
topjohnwu 2021-11-04 05:36:29 -07:00 committed by John Wu
parent 627ec91687
commit 6723d20616
3 changed files with 36 additions and 27 deletions

View File

@ -10,6 +10,7 @@ import android.graphics.drawable.Drawable
import android.os.Build.VERSION.SDK_INT import android.os.Build.VERSION.SDK_INT
import com.topjohnwu.magisk.core.utils.currentLocale import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.ktx.getLabel import com.topjohnwu.magisk.ktx.getLabel
import java.util.*
class CmdlineListItem(line: String) { class CmdlineListItem(line: String) {
val packageName: String val packageName: String
@ -25,31 +26,39 @@ class CmdlineListItem(line: String) {
const val ISOLATED_MAGIC = "isolated" const val ISOLATED_MAGIC = "isolated"
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
class AppProcessInfo(val applicationInfo: ApplicationInfo, pm: PackageManager, class AppProcessInfo(
denyList: List<CmdlineListItem>) : Comparable<AppProcessInfo> { info: ApplicationInfo,
pm: PackageManager,
denyList: List<CmdlineListItem>
) : ApplicationInfo(info), Comparable<AppProcessInfo> {
private val denyList = denyList.filter { private val denyList = denyList.filter {
it.packageName == applicationInfo.packageName || it.packageName == ISOLATED_MAGIC it.packageName == packageName || it.packageName == ISOLATED_MAGIC
} }
val label = applicationInfo.getLabel(pm)
val iconImage: Drawable = applicationInfo.loadIcon(pm) val label = getLabel(pm)
val iconImage: Drawable = loadIcon(pm)
val processes = fetchProcesses(pm) val processes = fetchProcesses(pm)
override fun compareTo(other: AppProcessInfo) = comparator.compare(this, other) override fun compareTo(other: AppProcessInfo) = comparator.compare(this, other)
private fun createProcess(name: String, pkg: String = applicationInfo.packageName) = private fun createProcess(name: String, pkg: String = packageName) =
ProcessInfo(name, pkg, denyList.any { it.process == name && it.packageName == pkg }) ProcessInfo(name, pkg, denyList.any { it.process == name && it.packageName == pkg })
private fun ComponentInfo.getProcName(): String = processName private fun ComponentInfo.getProcName(): String = processName
?: applicationInfo.processName ?: applicationInfo.processName
?: applicationInfo.packageName ?: applicationInfo.packageName
private fun Array<out ComponentInfo>.processes() = map { createProcess(it.getProcName()) } private val ServiceInfo.isIsolated get() = (flags and ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
private val ServiceInfo.useAppZygote get() = (flags and ServiceInfo.FLAG_USE_APP_ZYGOTE) != 0
private fun Array<ServiceInfo>.processes() = map { private fun Array<out ComponentInfo>?.toProcessList() =
if ((it.flags and ServiceInfo.FLAG_ISOLATED_PROCESS) != 0) { this?.map { createProcess(it.getProcName()) }.orEmpty()
if ((it.flags and ServiceInfo.FLAG_USE_APP_ZYGOTE) != 0) {
val proc = applicationInfo.processName ?: applicationInfo.packageName private fun Array<ServiceInfo>?.toProcessList() = this?.map {
if (it.isIsolated) {
if (it.useAppZygote) {
val proc = processName ?: packageName
createProcess("${proc}_zygote") createProcess("${proc}_zygote")
} else { } else {
val proc = if (SDK_INT >= 29) "${it.getProcName()}:${it.name}" else it.getProcName() val proc = if (SDK_INT >= 29) "${it.getProcName()}:${it.name}" else it.getProcName()
@ -58,30 +67,30 @@ class AppProcessInfo(val applicationInfo: ApplicationInfo, pm: PackageManager,
} else { } else {
createProcess(it.getProcName()) createProcess(it.getProcName())
} }
} }.orEmpty()
private fun fetchProcesses(pm: PackageManager): List<ProcessInfo> { private fun fetchProcesses(pm: PackageManager): Collection<ProcessInfo> {
val flag = MATCH_DISABLED_COMPONENTS or MATCH_UNINSTALLED_PACKAGES or val flag = MATCH_DISABLED_COMPONENTS or MATCH_UNINSTALLED_PACKAGES or
GET_ACTIVITIES or GET_SERVICES or GET_RECEIVERS or GET_PROVIDERS GET_ACTIVITIES or GET_SERVICES or GET_RECEIVERS or GET_PROVIDERS
val packageInfo = try { val packageInfo = try {
pm.getPackageInfo(applicationInfo.packageName, flag) pm.getPackageInfo(packageName, flag)
} catch (e: Exception) { } catch (e: Exception) {
// Exceed binder data transfer limit, local parsing package // Exceed binder data transfer limit, parse the package locally
pm.getPackageArchiveInfo(applicationInfo.sourceDir, flag) ?: return emptyList() pm.getPackageArchiveInfo(sourceDir, flag) ?: return emptyList()
} }
val list = LinkedHashSet<ProcessInfo>() val processSet = TreeSet<ProcessInfo>(compareBy{ it.name })
list += packageInfo.activities?.processes().orEmpty() processSet += packageInfo.activities.toProcessList()
list += packageInfo.services?.processes().orEmpty() processSet += packageInfo.services.toProcessList()
list += packageInfo.receivers?.processes().orEmpty() processSet += packageInfo.receivers.toProcessList()
list += packageInfo.providers?.processes().orEmpty() processSet += packageInfo.providers.toProcessList()
return list.sortedBy { it.name } return processSet
} }
companion object { companion object {
private val comparator = compareBy<AppProcessInfo>( private val comparator = compareBy<AppProcessInfo>(
{ it.label.lowercase(currentLocale) }, { it.label.lowercase(currentLocale) },
{ it.applicationInfo.packageName } { it.packageName }
) )
} }
} }

View File

@ -81,13 +81,13 @@ class DenyListViewModel : BaseViewModel(), Queryable {
fun isSystemApp(flag: Int) = flag and ApplicationInfo.FLAG_SYSTEM != 0 fun isSystemApp(flag: Int) = flag and ApplicationInfo.FLAG_SYSTEM != 0
items.filter { items.filter {
fun filterSystem() = isShowSystem || !isSystemApp(it.info.applicationInfo.flags) fun filterSystem() = isShowSystem || !isSystemApp(it.info.flags)
fun filterOS() = (isShowSystem && isShowOS) || isApp(it.info.applicationInfo.uid) fun filterOS() = (isShowSystem && isShowOS) || isApp(it.info.uid)
fun filterQuery(): Boolean { fun filterQuery(): Boolean {
fun inName() = it.info.label.contains(query, true) fun inName() = it.info.label.contains(query, true)
fun inPackage() = it.info.applicationInfo.packageName.contains(query, true) fun inPackage() = it.info.packageName.contains(query, true)
fun inProcesses() = it.processes.any { p -> p.process.name.contains(query, true) } fun inProcesses() = it.processes.any { p -> p.process.name.contains(query, true) }
return inName() || inPackage() || inProcesses() return inName() || inPackage() || inProcesses()
} }

View File

@ -70,7 +70,7 @@
android:id="@+id/hide_package" android:id="@+id/hide_package"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{item.info.applicationInfo.packageName}" android:text="@{item.info.packageName}"
android:textAppearance="@style/AppearanceFoundation.Caption.Variant" android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/hide_name" app:layout_constraintEnd_toEndOf="@+id/hide_name"