I am running all the below commands from two locations: 1) from aosp root folder 2) from where the cuttlefish android emulator is installed.
upgautam@amd:/opt/aosp$ source build/envsetup.sh
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined$ HOME=$PWD ./bin/launch_cvd
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb devices
List of devices attached
0.0.0.0:6520 device
We built a dummy system app, and tried to test its superpower, such as ls /sys folder.
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Note: Declaraing the same system permission for normal app doesn't grant the permission as permission declaration is different to permission granting.
Android system ensures if those system permission are declared and those are the system app then they are granted those permission. To test this, I modified my dummy app as follows,
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.DummySystemApplication"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.DummySystemApplication">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
And, my activtiy as,
package com.example.dummysystemapplication
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.dummysystemapplication.ui.theme.dummysystemapplicationTheme
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.OutputStreamWriter
import kotlin.concurrent.thread
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
disableSELinux()
executeRootCommand()
setContent {
dummysystemapplicationTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Uddha P. Gautam",
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
private fun disableSELinux() {
thread {
try {
// Start the root shell with /system/xbin/su 0
val command = "/system/xbin/su 0"
val process = Runtime.getRuntime().exec(command)
// Send setenforce 0 command to the root shell
val outputStream = process.outputStream
val writer = BufferedWriter(OutputStreamWriter(outputStream))
writer.write("setenforce 0\n")
writer.flush()
// Capture the output of the command
val output = process.inputStream.bufferedReader().use(BufferedReader::readText)
process.waitFor()
runOnUiThread {
Toast.makeText(this, "SELinux disabled:\n$output", Toast.LENGTH_SHORT).show()
}
} catch (e: Exception) {
e.printStackTrace()
runOnUiThread {
Toast.makeText(this, "Error disabling SELinux", Toast.LENGTH_SHORT).show()
}
}
}
}
// Function to execute root commands
private fun executeRootCommand() {
thread {
try {
// Start the root shell
val command = "/system/xbin/su 0"
val process = Runtime.getRuntime().exec(command)
// Send the "ls /sys" command to the root shell
val outputStream = process.outputStream
val writer = BufferedWriter(OutputStreamWriter(outputStream))
writer.write("ls /sys\n")
writer.flush()
// Capture the output of the command
val output = process.inputStream.bufferedReader().use(BufferedReader::readText)
process.waitFor()
runOnUiThread {
Toast.makeText(this, "Root Command Output:\n$output", Toast.LENGTH_LONG).show()
}
} catch (e: Exception) {
e.printStackTrace()
runOnUiThread {
Toast.makeText(this, "Can't run root command", Toast.LENGTH_SHORT).show()
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
dummysystemapplicationTheme {
Greeting("Uddhav P. Gautam")
}
}
Build the apk and push. But this time, I also installed magisk app and from there patched the boot.img, I pulled that patched boot.img to host and then stopped and started cuttlefish emulator with new patched boot.img.
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb push ~/Desktop/DummyApp/app-debug.apk /system/priv-app/dummy_app/app-debug.apk
adb: error: failed to copy '/home/upgautam/Desktop/DummyApp/app-debug.apk' to '/system/priv-app/dummy_app/app-debug.apk': remote secure_mkdirs() failed: Read-only file system
/home/upgautam/Desktop/DummyApp/app-debug.apk: 1 file pushed, 0 skipped. 674.3 MB/s (8670593 bytes in 0.012s)
To fix this read-only error,
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb reboot
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb root
restarting adbd as root
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb shell
vsoc_x86_64:/ # whoami
root
vsoc_x86_64:/ # setenforce 0
vsoc_x86_64:/ # disable-verity
AVB verification is disabled, disabling verity state may have no effect
enabling overlayfs
Reboot the device for new settings to take effect
vsoc_x86_64:/ # reboot
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb root
adb: unable to connect for root: no devices/emulators found
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb root
restarting adbd as root
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb shell
vsoc_x86_64:/ # mount -o rw,remount /system
vsoc_x86_64:/ # mkdir /system/priv-app/dummy_app/
vsoc_x86_64:/ # exit
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb push ~/Desktop/DummyApp/app-debug.apk /system/priv-app/dummy_app/app-debug.apk
/home/upgautam/Desktop/DummyApp/app-debug.apk: 1 file pushed, 0 skipped. 21.7 MB/s (8670593 bytes in 0.380s)
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb reboot
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb root
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb shell
vsoc_x86_64:/ # am start com.example.dummysystemapplication/.MainActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.dummysystemapplication/.MainActivity }
Still the issue exists. I can't make it work. I can't test its superpower, although it is a system app. I tried cuttlefish emulator with original boot.img, the same issue.
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb push ~/Desktop/DummyApp/app-debug.apk /system/priv-app/dummy_app/app-debug.apk
/home/upgautam/Desktop/DummyApp/app-debug.apk: 1 file pushed, 0 skipped. 22.6 MB/s (8670593 bytes in 0.366s)
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb root
adbd is already running as root
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb shell
vsoc_x86_64:/ # chmod 644 /system/priv-app/dummy_app/app-debug.apk
vsoc_x86_64:/ # chown root:system /system/priv-app/dummy_app/app-debug.apk
vsoc_x86_64:/ # reboot //when it restarts the apk will be installed as system app
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb root
restarting adbd as root
upgautam@amd:/opt/cuttlefish/cuttlefish-run/combined/bin$ ./adb shell
vsoc_x86_64:/ # setenforce 0
vsoc_x86_64:/ # am start com.example.dummysystemapplication/.MainActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.dummysystemapplication/.MainActivity }
#Still I get Error.