4

I want to use this code in order to reboot my RPI3 running Android Things:

public static void Reboot()
{
    try {
        Process proc = Runtime.getRuntime().exec(new String[]{"su", "-c", "reboot"});
        proc.waitFor();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

I get the following error:

java.io.IOException: Cannot run program "su": error=13, Permission denied

I add to the manifest all the permission

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.SET_TIME_ZONE"/>
<uses-permission android:name="android.permission.SHUTDOWN"/>

Am I missing something?

Onik
  • 19,396
  • 14
  • 68
  • 91
Daniele
  • 668
  • 2
  • 10
  • 25
  • 2
    not the android permission mater, but the linux `su` command permission. make sure you process(user) have the permission to execute su – Jiang YD May 23 '17 at 08:29
  • How can I check if I can execute "su"? – Daniele May 23 '17 at 08:40
  • that is a basic linux problem, can not say much here. please learn how to execute command in linux bash, and check binary executable. – Jiang YD May 23 '17 at 09:11

4 Answers4

7

/system/bin/reboot binary in DP 4, so as in all the previous dev previews, has world-executable permission, i.e. the following yields

adb shell ls -l /system/bin | grep reboot
-rwxr-xr-x 1 root shell   ... reboot

That said, it is yet possible to execute the binary for any user (a.k.a app process in Android) without a need to grab su. Just execute in Java for

rebooting

Runtime.getRuntime().exec("reboot");

or for powering off

Runtime.getRuntime().exec("reboot -p");

No permission's needed in AndroidManifest.xml to run the binary successfully.

Caution: in case of security model changes in newer OS versions this approach may not work.

Onik
  • 19,396
  • 14
  • 68
  • 91
  • 1
    `Runtime.getRuntime().exec("reboot");` works at the first time. Thank you. As mentioned in the comment at @Devunwired I need only to execute AVRdude with su – Daniele May 24 '17 at 07:38
  • _"'su' command are not accessible in any case?"_ You could try `adb root`, then `adb remount` (to prevent `/system/ not in /proc/mounts`), then `adb shell chmod 777 /system/xbin/su` (777 is just an example, you might pick a more restricted mode), **but you know that making `su` world-executable is a huge security hole, right?** :) – Onik May 26 '17 at 20:45
7

You can now do a reboot using:

https://developer.android.com/things/reference/com/google/android/things/devicemanagement/DeviceManager.html

Example

 public class SomeActivity extends Activity {

     void doReboot() {
         DeviceManager.getInstance().reboot();
     }

     void doFactoryReset() {
         boolean wipeExternalCard = true;
         DeviceManager.getInstance().factoryReset(wipeExternalCard);
     }
  }

You need the com.google.android.things.permission.REBOOT permission

Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
Blundell
  • 75,855
  • 30
  • 208
  • 233
3

Access to system-protected features (such as those provided by the PowerManager.reboot() API) will be available to apps running on Android Things in a future developer preview release. You cannot (and should not) attempt to run your app process as the root user via su.

As a side note, the developer images for Android Things are built as userdebug, which means you can access root from the shell by simply rebooting the ADB daemon with the adb root command before you attempt to access the shell. This gives you any root access you may need during development without compromising the device security and allowing app processes to run as root.

devunwired
  • 62,780
  • 12
  • 127
  • 139
  • Thank you for your answer! So I will wait for the future release! "su" command are not accessible in any case? e.g. if I need to run AVRDude (to upload an arduino firmware... ) how can I do that without "su"? – Daniele May 23 '17 at 17:17
  • 1
    The recommended method would be to implement the protocol directly using the Peripheral I/O APIs, rather than calling out to an external executable that requires elevated permissions. This is a difficult thing for us to secure. – devunwired May 23 '17 at 20:23
  • 1
    Thank you for the explanation! At the end the method suggested by @Onik is able to reboot the RPI3. Now I need to find a way to execute AVRdude :D – Daniele May 24 '17 at 07:36
0

You need a root access.

public static void runCmd(String cmd) {
    DataOutputStream os;
    try {
        Process process = Runtime.getRuntime().exec("su");
        os = new DataOutputStream(process.getOutputStream());
        os.writeBytes(cmd + "\n");
        os.writeBytes("exit\n");
        os.flush();
        os.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Then you can run any commands that require root access like this: runCmd("reboot");

Andrej Jurkin
  • 2,216
  • 10
  • 19