Reputation: 137
I have following code, which is used for auto update of app, which is installed like system app on rooted device. It starts from copyToPrivateApps with already downloaded new apk file. It is attached to IO thread from corutine scope
fun copyToPrivateApps(context: Context, apkPath: String?) {
sudoForCommandAndResult("mount -o rw,remount /system")
sudoForCommandAndResult("mkdir $systemFolder")
sudoForCommandAndResult("cat $apkPath > $systemApkPath")
sudoForCommandAndResult("cp -R ${sudoForResult("find ./data/app -name ${context.packageName}*").drop(1) + "/lib"} $systemFolder")
sudoForCommandAndResult("chmod -R 755 $systemFolder")
sudoForCommandAndResult("chmod 644 $systemFngFolder")
sudoForCommandAndResult("chmod 644 $systemSilFolder")
sudoForCommandAndResult("chmod 644 $systemApkPath")
sudoForCommandAndResult("mount -o ro,remount /system")}
fun sudoForCommandAndResult(string: String): String {
var res = ""
var outputStream: DataOutputStream? = null
var response : InputStream? = null
var error : InputStream? = null
try {
val su = Runtime.getRuntime().exec("su")
outputStream = DataOutputStream(su.outputStream)
response = su.inputStream
error = su.errorStream
outputStream.writeBytes(string + "\n")
outputStream.flush()
outputStream.writeBytes("exit\n")
outputStream.flush()
try {
su.waitFor()
} catch (e: Throwable) {
e.printStackTrace()
}
val responseString = readFully(response!!).replace("su:main", "").trim()
val errorString = readFully(error!!).replace("su:main", "").trim()
res = logTimeFormat.format(Date()) + string + if(responseString.isNotBlank()) "\n" + logTimeFormat.format(Date()) + responseString else ""
res += if(errorString.isNotBlank()) "\n" + logTimeFormat.format(Date()) + errorString else ""
} catch (e: Throwable) {
res += logTimeFormat.format(Date()) + e.message?.trim()
e.printStackTrace()
} finally {
Closer.closeSilently(outputStream, response)
}
return res}
fun sudoForResult(string: String): String {
var res = ""
var outputStream: DataOutputStream? = null
var response : InputStream? = null
var error : InputStream? = null
try {
val su = Runtime.getRuntime().exec("su")
outputStream = DataOutputStream(su.outputStream)
response = su.inputStream
error = su.errorStream
outputStream.writeBytes(string + "\n")
outputStream.flush()
outputStream.writeBytes("exit\n")
outputStream.flush()
try {
su.waitFor()
} catch (e: Throwable) {
e.printStackTrace()
}
val responseString = readFully(response!!).replace("su:main", "").trim()
val errorString = readFully(error!!).replace("su:main", "").trim()
res = listOf(responseString, errorString).joinToString(separator = " ")
} catch (e: Throwable) {
res += e.message?.trim()
e.printStackTrace()
} finally {
Closer.closeSilently(outputStream, response)
}
return res.trim()}
It fails inside sudoForResult(), on val su = Runtime.getRuntime().exec("su") when trying to execute "cp" command with following error: A/libc: Fatal signal 4 (SIGILL), code 1, fault addr 0x7f6190fa24 in tid 6974 (DefaultDispatch)
and some strange warning
W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m -j3 --instruction-set-variant=generic --instruction-set-features=default --dex-file=/system/priv-app/appName/appName.apk --oat-file=/data/dalvik-cache/arm64/system@priv-app@[email protected]@classes.dex) because non-0 exit status
Sometimes it crash even earlier on "cat" command with similar error
EDIT: This was working before with smaller update apk file, now it is almost 3x bigger.
Upvotes: 0
Views: 196
Reputation: 46
try this:
sudoForCommandAndResult("chmod +x $systemFolder")
sudoForCommandAndResult("chmod +x $systemApkPath")
//change cat command with dd if
sudoForCommandAndResult("dd if=$apkPath of=$systemApkPath")
Upvotes: 0