Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Power off Android device with system signed application

Tags:

android

I am developing an Android application and we need to power off the device under certain circumstances.

I have read in many places that you need a rooted phone in order to do so. Then, you can issue the "reboot" command by using Java's API:

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

I have actually tried this in a Cyanogenmod 10 device (Samsung Galaxy S3), and it works. However, we do not want a rooted device in order to power it off, since the end user will then be able to do unintended things which are not allowed by our company.

On the other hand, our application is signed by the manufacturer's certificate, in this case Cyanogen's. I have read that by signing your application with the manufacturer's certificate, you should be able to issue privileged commands (as if root). However, even if I install my app as a system app signed with the manufacturer's certificate, the above code does not work:

  • If I leave the "su" part of the command, the "Superuser Request" screen is displayed, but that's something we are trying to avoid.

  • If I remove the "su" part (just leaving "reboot -p"), the command is silently ignored.

As a result, we are not being able to poweroff our device with our system app, which is signed with the manifacturer's certificate. So my question is, how am I supposed to do that?

EDITED

And, by the way, just in case someone is not sure about it: the application is properly signed and installed as a system application, because we can actually access some restricted APIs, such as PowerManager.goToSleep()

like image 624
Knuckles the Echidna Avatar asked Jun 19 '13 11:06

Knuckles the Echidna


2 Answers

If you want the device to reboot (power off and on), then try PowerManager.reboot()

PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
powerManager.reboot(null);

android.os.PowerManager:

/**
 * Reboot the device.  Will not return if the reboot is successful.
 * <p>
 * Requires the {@link android.Manifest.permission#REBOOT} permission.
 * </p>
 *
 * @param reason code to pass to the kernel (e.g., "recovery") to
 *               request special boot modes, or null.
 */
public void reboot(String reason) {
    try {
        mService.reboot(false, reason, true);
    } catch (RemoteException e) {
    }
}

UPDATE

If you want the device to completely turn off, use PowerManagerService.shutdown():

IPowerManager powerManager = IPowerManager.Stub.asInterface(
        ServiceManager.getService(Context.POWER_SERVICE));
try {
    powerManager.shutdown(false, false);
} catch (RemoteException e) {
}

com.android.server.power.PowerManagerService:

/**
 * Shuts down the device.
 *
 * @param confirm If true, shows a shutdown confirmation dialog.
 * @param wait If true, this call waits for the shutdown to complete and does not return.
 */
@Override // Binder call
public void shutdown(boolean confirm, boolean wait) {
    mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);

    final long ident = Binder.clearCallingIdentity();
    try {
        shutdownOrRebootInternal(true, confirm, null, wait);
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}
like image 52
ozbek Avatar answered Nov 15 '22 20:11

ozbek


This was working fine for me:

startActivity(new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN"));

you need this permission ( depends on being system-app ):

 <uses-permission android:name="android.permission.SHUTDOWN"/>

source: https://github.com/sas101/shutdown-android-app/wiki

like image 32
ligi Avatar answered Nov 15 '22 21:11

ligi