Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ParcelableArray in getAllProcess #21

Merged
merged 4 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ android {

dependencies {
//Ui
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.core:core-ktx:1.10.0'
implementation 'androidx.fragment:fragment-ktx:1.5.5'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.0'
Expand Down
99 changes: 41 additions & 58 deletions app/src/main/java/com/dumper/android/dumper/process/Process.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,83 +12,66 @@ import java.io.File

object Process {

fun getAllProcess(ctx: Context, isRoot: Boolean): ArrayList<ProcessData> {
val finalAppsBundle = ArrayList<ProcessData>()
if (isRoot) {
val activityManager = ctx.getSystemService(ACTIVITY_SERVICE) as ActivityManager
fun getAllProcess(ctx: Context, isRoot: Boolean) =
if (isRoot)
getAllProcessRoot(ctx)
else
getAllProcessNoRoot()

activityManager.runningAppProcesses.forEach {
try {
val apps = ctx.packageManager.getApplicationInfoCompact(
it.processName.substringBefore(":"), 0
)
if (!apps.isInvalid() && apps.packageName != BuildConfig.APPLICATION_ID) {
val data = ProcessData(
it.processName,
ctx.packageManager.getApplicationLabel(apps).toString()
)
finalAppsBundle.add(data)

private fun getAllProcessRoot(ctx: Context): List<ProcessData> {
val activityManager = ctx.getSystemService(ACTIVITY_SERVICE) as ActivityManager
return activityManager.runningAppProcesses
.mapNotNull {
runCatching {
val pkgManager = ctx.packageManager
val app = pkgManager.getApplicationInfoCompact(it.processName, 0)
if (!app.isInvalid() && app.packageName != BuildConfig.APPLICATION_ID) {
val appLabel = pkgManager.getApplicationLabel(app).toString()
ProcessData(it.processName, appLabel)
} else {
null
}
} catch (_: Exception) {
}
}.getOrNull()
}
} else {
val proc = File("/proc")
if (!proc.exists())
return finalAppsBundle

val dPID = proc.listFiles()
if (dPID.isNullOrEmpty())
return finalAppsBundle

for (line in dPID) {
if (!line.name.isDigitsOnly())
continue;
}

val comm = File("${line.path}/comm")
val cmdline = File("${line.path}/cmdline")
private fun getAllProcessNoRoot(): List<ProcessData> {
return File("/proc")
.listFiles().orEmpty()
.filter { it.name.isDigitsOnly() }
.mapNotNull {
val comm = File("${it.path}/comm")
val cmdline = File("${it.path}/cmdline")
if (!comm.exists() || !cmdline.exists())
continue;
return@mapNotNull null

val processName = comm.readText(Charsets.UTF_8).removeNullChar()
val processPkg = cmdline.readText(Charsets.UTF_8).removeNullChar()

if (processPkg != "sh" && !processPkg.contains(BuildConfig.APPLICATION_ID)) {
val data = ProcessData(processPkg, processName)
finalAppsBundle.add(data)
ProcessData(processPkg, processName)
} else {
null
}
}
}
return finalAppsBundle
}

/**
* Get the PID
* @return pid of process or null if process id is not found
*/
fun getProcessID(pkg: String): Int? {
val proc = File("/proc")
if (!proc.exists())
return null

val dPID = proc.listFiles()
if (dPID.isNullOrEmpty())
return null

dPID.find {
if (it.name.isDigitsOnly()) {
return File("/proc")
.listFiles().orEmpty()
.filter { it.name.isDigitsOnly() }
.find {
val cmdline = File("${it.path}/cmdline")
if (cmdline.exists()) {
val textCmd = cmdline.readText(Charsets.UTF_8)
if (textCmd.contains(pkg)) {
return@find true
}
}
}
return@find false
}?.let {
return it.name.toInt()
}
return null
if (!cmdline.exists())
return@find false

val textCmd = cmdline.readText(Charsets.UTF_8)
return@find textCmd.contains(pkg)
}?.name?.toIntOrNull()
}
}
5 changes: 3 additions & 2 deletions app/src/main/java/com/dumper/android/messager/MSGReceiver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package com.dumper.android.messager

import android.os.Handler
import android.os.Message
import androidx.core.os.BundleCompat
import com.dumper.android.core.MainActivity
import com.dumper.android.core.RootServices
import com.dumper.android.dumper.process.ProcessData
import com.dumper.android.utils.getParcelableArrayListCompact

class MSGReceiver(private val activity: MainActivity) : Handler.Callback {

Expand All @@ -14,7 +14,8 @@ class MSGReceiver(private val activity: MainActivity) : Handler.Callback {

when (message.what) {
RootServices.MSG_GET_PROCESS_LIST -> {
message.data.getParcelableArrayListCompact<ProcessData>(RootServices.LIST_ALL_PROCESS)
BundleCompat.getParcelableArray(message.data, RootServices.LIST_ALL_PROCESS, ProcessData::class.java)
?.filterIsInstance<ProcessData>()
?.let {
activity.memory.showProcess(activity, it)
}
Expand Down
31 changes: 18 additions & 13 deletions app/src/main/java/com/dumper/android/ui/memory/MemoryViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.dumper.android.ui.memory

import android.content.Context
import android.widget.Toast
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.dumper.android.dumper.process.ProcessData
Expand All @@ -14,25 +15,29 @@ class MemoryViewModel : ViewModel() {
val isFixELF = MutableLiveData<Boolean>()
val isDumpMetadata = MutableLiveData<Boolean>()


fun showProcess(ctx: Context, list: ArrayList<ProcessData>) {
list.sortBy { it.appName }

val appNames = list.map { processData ->
val processName = processData.processName
if (processName.contains(":"))
"${processData.appName} (${processName.substringAfter(":")})"
else
processData.appName
fun showProcess(ctx: Context, list: List<ProcessData>) {
if (list.isEmpty()) {
Toast.makeText(ctx, "No process found", Toast.LENGTH_SHORT).show()
return
}

val appNames = list.sortedBy { it.processName }
val appsTitle = appNames
.map { processData ->
val processName = processData.processName
if (processName.contains(":"))
"${processData.appName} (${processName.substringAfter(":")})"
else
processData.appName
}.toTypedArray()

MaterialAlertDialogBuilder(ctx)
.setTitle("Select process")
.setSingleChoiceItems(appNames.toTypedArray(), -1) { dialog, which ->
selectedApps.value = list[which].processName
.setSingleChoiceItems(appsTitle, -1
) { dialog, idx ->
selectedApps.value = appNames[idx].processName
dialog.dismiss()
}
.show()
}

}
12 changes: 2 additions & 10 deletions app/src/main/java/com/dumper/android/utils/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,8 @@ fun Long.toHex(): String {
}

@Suppress("DEPRECATION")
inline fun <reified T : Parcelable> Bundle.getParcelableArrayListCompact(key: String): ArrayList<T>? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getParcelableArrayList(key, T::class.java)
} else {
getParcelableArrayList(key)
}
}

@Suppress("DEPRECATION")
fun PackageManager.getApplicationInfoCompact(packageName: String, flags: Int): ApplicationInfo {
fun PackageManager.getApplicationInfoCompact(processName: String, flags: Int): ApplicationInfo {
val packageName = processName.substringBefore(":")
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getApplicationInfo(packageName, PackageManager.ApplicationInfoFlags.of(flags.toLong()))
} else {
Expand Down