9

I am working on a device admin app (has been signed by the manufacturer). I am using it to install other apps using the below adb shell command for android 9 :-

cat /sdcard/Download/myfolder/newapp.apk | pm install -S 1528293

and I am just passing it like this:-

String command = "cat /sdcard/Download/myfolder/newapp.apk | pm install -S 1528293"
Runtime.getRuntime().exec(command);

But I get the error "cat unknown option S ".

The same command works perfectly fine when I run it from adb shell. Don't know what I am doing wrong and could use some help.

EDIT 1:- I tried running the command like below:-

String[] commandInstall = {
                "/system/bin/sh",
                "-c",
                "cat /sdcard/Download/myfolder/newapp.apk | pm install -S 1528293"
        };
Process process = Runtime.getRuntime().exec(commandInstall);

But now I get the error:-

ava.lang.SecurityException: Reverse mode only supported from shell
    at com.android.server.pm.PackageInstallerSession.doWriteInternal(PackageInstallerSession.java:679)
    at com.android.server.pm.PackageInstallerSession.write(PackageInstallerSession.java:612)
    at android.content.pm.PackageInstaller$Session.write(PackageInstaller.java:852)
    at com.android.server.pm.PackageManagerShellCommand.doWriteSplit(PackageManagerShellCommand.java:2447)
    at com.android.server.pm.PackageManagerShellCommand.runInstall(PackageManagerShellCommand.java:915)
    at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:158)
    at android.os.ShellCommand.exec(ShellCommand.java:103)
    at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:21330)
    at android.os.Binder.shellCommand(Binder.java:634)
    at android.os.Binder.onTransact(Binder.java:532)
    at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:2821)
    at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:3856)
    at android.os.Binder.execTransact(Binder.java:731)

Edit 2:- Prior to android 9, I could just do the below for installing apps:-

Runtime.getRuntime().exec("pm install -r app.apk");

2 Answers 2

6

Looking at the source code of PackageInstallerSession I found that it was changed to :-

switch (Binder.getCallingUid()) {
    case android.os.Process.SHELL_UID:
    case android.os.Process.ROOT_UID:
        break;
    default:
        throw new SecurityException("Reverse mode only supported from shell");
    }

Source So even if it is a system app, the shell command for install might not work. From the commit messages it seems, this was done to let PackageInstaller do this job.

However it seems this again got changed to at some point, but probably is not included in android 9:-

    switch (Binder.getCallingUid()) {
                case android.os.Process.SHELL_UID:
                case android.os.Process.ROOT_UID:
                case android.os.Process.SYSTEM_UID:
                    break;
                default:
                    throw new SecurityException(
                            "Reverse mode only supported from shell or system");
            }

Source

So if the app is a system app , then the best way would be to use PackageInstaller.

Sign up to request clarification or add additional context in comments.

1 Comment

Exactly, check my slimier attempt to clear android browser data, through adb shell work fine, but when do it pragmatically even its system app or in rooted devices. these cmd are not allowed, stackoverflow.com/questions/10934304/…
1

from PackageInstallerSession.java:

switch (Binder.getCallingUid()) {
                    case android.os.Process.SHELL_UID:
                    case android.os.Process.ROOT_UID:
                    case android.os.Process.SYSTEM_UID:
                        break;
                    default:
                        throw new SecurityException(
                                "Reverse mode only supported from shell or system");
                }

If your app is under system/app maybe you have to put it in system/priv-app. Hope the origin of the exception helps you somehow.

1 Comment

I did see this and the calling uid and system uid should be the same . Moreover the error message says:- reverse mode only supported from shell. So maybe something changed in android p.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.