xiongzhu 1 tahun lalu
induk
melakukan
06f305eb41

+ 7 - 0
app/src/main/java/com/example/modifier/model/AdbResult.kt

@@ -0,0 +1,7 @@
+package com.example.modifier.model
+
+data class AdbResult(
+    val output: String = "",
+    val error: String = "",
+    val exitCode: Int = -1
+)

+ 5 - 21
app/src/main/java/com/example/modifier/service/ModifierService.kt

@@ -24,7 +24,7 @@ import android.widget.FrameLayout
 import androidx.annotation.MenuRes
 import androidx.appcompat.widget.PopupMenu
 import androidx.core.content.ContextCompat
-import com.draco.ladb.utils.ADB
+import com.example.modifier.utils.ADB
 import com.example.modifier.BuildConfig
 import com.example.modifier.R
 import com.example.modifier.TraverseResult
@@ -82,7 +82,6 @@ class ModifierService : AccessibilityService() {
     private val screenController by lazy { ScreenController(this, screenInspector) }
     private val spoofedSimInfoRepo = SpoofedSimInfoRepo.instance
     private val backupRepository by lazy { BackupRepository(this, backupItemDao) }
-    private val adb by lazy { ADB.getInstance(applicationContext) }
     private lateinit var socketClient: SocketClient
     lateinit var taskRunner: TaskRunner
     private lateinit var uiContext: Context
@@ -384,25 +383,10 @@ class ModifierService : AccessibilityService() {
             CoroutineScope(Dispatchers.IO).launch {
                 when (item.itemId) {
                     R.id.adb -> {
-                        if (adb.connect()) {
-                            Log.i(TAG, "adb connected")
-                            adb.adb(
-                                listOf(
-                                    "shell",
-                                    "am",
-                                    "start",
-                                    "com.google.android.apps.messaging"
-                                )
-                            )
-                            delay(2000)
-                            adb.adb(
-                                listOf(
-                                    "shell",
-                                    "am",
-                                    "force-stop",
-                                    "com.google.android.apps.messaging"
-                                )
-                            )
+                        if (ADB.connect()) {
+                            Log.i(TAG, "adb connected, testing")
+                            ADB.adbShell("echo hello", "ls /sdcard")
+                            Log.i(TAG, "adb test pass")
                         } else {
                             Log.i(TAG, "adb not connected")
                         }

+ 1 - 1
app/src/main/java/com/example/modifier/service/ScreenController.kt

@@ -8,7 +8,6 @@ import android.graphics.Rect
 import android.provider.Settings
 import android.util.Log
 import android.view.accessibility.AccessibilityNodeInfo
-import com.draco.ladb.utils.ADB
 import com.example.modifier.TraverseResult
 import com.example.modifier.constants.CMD_BACK
 import com.example.modifier.constants.CMD_RCS_SETTINGS_ACTIVITY
@@ -167,6 +166,7 @@ class ScreenController(val context: AccessibilityService, private val inspector:
 
         delay(1000)
         context.rootInActiveWindow.findFirstByIdAndText("android:id/title","IP address & Port")
+        return true
     }
 
     fun tapNode(node: AccessibilityNodeInfo) {

+ 121 - 90
app/src/main/java/com/example/modifier/utils/ADB.kt

@@ -1,113 +1,144 @@
-package com.draco.ladb.utils
+package com.example.modifier.utils
 
-import android.annotation.SuppressLint
-import android.content.Context
-import android.provider.Settings
 import android.util.Log
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
+import com.example.modifier.model.AdbResult
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
-import java.util.concurrent.TimeUnit
 
-class ADB(private val context: Context) {
+class ADB {
     companion object {
         const val TAG = "ADB"
-        const val MAX_OUTPUT_BUFFER_SIZE = 1024 * 16
-        const val OUTPUT_BUFFER_DELAY_MS = 100L
-
-        @SuppressLint("StaticFieldLeak")
-        @Volatile
-        private var instance: ADB? = null
-        fun getInstance(context: Context): ADB = instance ?: synchronized(this) {
-            instance ?: ADB(context).also { instance = it }
-        }
-    }
-
-
-    private val adbPath = "${context.applicationInfo.nativeLibraryDir}/libadb.so"
-    private val scriptPath = "${context.getExternalFilesDir(null)}/script.sh"
-
-    /**
-     * Is the shell ready to handle commands?
-     */
-    private val _started = MutableLiveData(false)
-    val started: LiveData<Boolean> = _started
-
-    private var tryingToPair = false
-
-    /**
-     * Is the shell closed for any reason?
-     */
-    private val _closed = MutableLiveData(false)
-    val closed: LiveData<Boolean> = _closed
-
-
-    private fun isWirelessDebuggingEnabled() =
-        Settings.Global.getInt(context.contentResolver, "adb_wifi_enabled", 0) == 1
-
-    private fun isUSBDebuggingEnabled() =
-        Settings.Global.getInt(context.contentResolver, Settings.Global.ADB_ENABLED, 0) == 1
-
-
-    suspend fun connect(): Boolean {
-//        adb(listOf("connect", "localhost:5555"))
-        delay(5000)
-
-        adb(listOf("devices"))
-
-        val shell2 = adb(listOf("shell", "ls"))
-        return shell2.exitValue() == 0
-    }
-
-    /**
-     * Send a raw ADB command
-     */
-    suspend fun adb(command: List<String>): Process {
-        val commandList = command.toMutableList().also {
-            it.add(0, adbPath)
+        private val adbPath by lazy { "${getContext().applicationInfo.nativeLibraryDir}/libadb.so" }
+        private val homeDir by lazy { getContext().filesDir }
+        private val cacheDir by lazy { getContext().cacheDir }
+
+        suspend fun connect(): Boolean {
+            return run ls@{
+                repeat(1000) {
+                    adb("connect", "localhost:5555")
+                    delay(5000)
+                    adb("devices")
+                    if (adb("shell", "echo", "hello").exitCode == 0) {
+                        return@ls true
+                    }
+                    delay(3000)
+                }
+                return@ls false
+            }
         }
-        return shell(commandList)
-    }
 
-    /**
-     * Send a raw shell command
-     */
-    private suspend fun shell(command: List<String>): Process {
-        val process = withContext(Dispatchers.IO) {
-            ProcessBuilder(command)
-                .directory(context.filesDir)
-                .apply {
-                    redirectErrorStream(true)
-                    environment().apply {
-                        put("HOME", context.filesDir.path)
-                        put("TMPDIR", context.cacheDir.path)
+        /**
+         * Send a raw ADB command
+         */
+        suspend fun adb(vararg command: String): AdbResult {
+            runCatching {
+                val fullCommand = command.toMutableList().also {
+                    it.add(0, adbPath)
+                    if (command.firstOrNull() == "shell") {
+                        it.add(1, "-s")
+                        it.add(2, "localhost:5555")
                     }
                 }
-                .start()
-        }
-        coroutineScope {
-            launch {
-                process.inputStream.bufferedReader().useLines { line ->
-                    line.forEach {
-                        Log.i(TAG, "ADB out: $it")
+                Log.i(TAG, "ADB command: ${fullCommand.joinToString(" ")}".replace(adbPath, "adb"))
+                var output = ""
+                var error = ""
+                val process = withContext(Dispatchers.IO) {
+                    ProcessBuilder(fullCommand)
+                        .directory(homeDir)
+                        .apply {
+//                    redirectErrorStream(true)
+                            environment().apply {
+                                put("HOME", homeDir.path)
+                                put("TMPDIR", cacheDir.path)
+                            }
+                        }
+                        .start()
+                }
+                coroutineScope {
+                    launch {
+                        process.inputStream.bufferedReader().useLines { line ->
+                            line.forEach {
+                                output += it + "\n"
+                                Log.i(TAG, "ADB out: $it")
+                            }
+                        }
                     }
+                    launch {
+                        process.errorStream.bufferedReader().useLines { line ->
+                            line.forEach {
+                                error += it + "\n"
+                                Log.e(TAG, "ADB err: $it")
+                            }
+                        }
+                    }
+                }
+                withContext(Dispatchers.IO) {
+                    process.waitFor()
                 }
+                return AdbResult(exitCode = process.exitValue())
+            }.onFailure {
+                Log.wtf(TAG, "Error running ADB command: ${it.message}", it)
             }
-            launch {
-                process.errorStream.bufferedReader().useLines { line ->
-                    line.forEach {
-                        Log.e(TAG, "ADB err: $it")
+            return AdbResult()
+        }
+
+        /**
+         * Send a raw ADB command
+         */
+        suspend fun adbShell(vararg commands: String): AdbResult {
+            Log.i(TAG, "ADB command: ${commands.joinToString("\n")}")
+            runCatching {
+                var output = ""
+                var error = ""
+                val process = withContext(Dispatchers.IO) {
+                    ProcessBuilder(listOf(adbPath, "-s", "localhost:5555", "shell"))
+                        .directory(homeDir)
+                        .apply {
+//                    redirectErrorStream(true)
+                            environment().apply {
+                                put("HOME", homeDir.path)
+                                put("TMPDIR", cacheDir.path)
+                            }
+                        }
+                        .start()
+                }
+                process.outputStream.bufferedWriter().use { writer ->
+                    commands.forEach { command ->
+                        writer.write(command)
+                        writer.newLine()
+                        writer.flush()
+                    }
+                }
+                coroutineScope {
+                    launch {
+                        process.inputStream.bufferedReader().useLines { line ->
+                            line.forEach {
+                                output += it + "\n"
+                                Log.i(TAG, "ADB out: $it")
+                            }
+                        }
+                    }
+                    launch {
+                        process.errorStream.bufferedReader().useLines { line ->
+                            line.forEach {
+                                error += it + "\n"
+                                Log.e(TAG, "ADB err: $it")
+                            }
+                        }
                     }
                 }
+                withContext(Dispatchers.IO) {
+                    process.waitFor()
+                }
+                Log.i(TAG, "ADB exit code: ${process.exitValue()}")
+                return AdbResult(output = output, error = error, exitCode = process.exitValue())
+            }.onFailure {
+                Log.wtf(TAG, "Error running ADB command: ${it.message}", it)
             }
+            return AdbResult()
         }
-        withContext(Dispatchers.IO) {
-            process.waitFor()
-        }
-        return process
     }
 }

+ 1 - 0
app/src/main/java/com/example/modifier/utils/System.kt

@@ -43,6 +43,7 @@ import kotlin.system.exitProcess
 
 
 const val systemTag = "$baseTag/System"
+const val ROOTED_PHONE = false
 val uniqueId: String
     @SuppressLint("HardwareIds")
     get() {