Android TV shutdown/restart logic simplified by pressing Power key for a long time, say goodbye to long wait

Posted by driver on Sat, 18 May 2019 02:04:32 +0200

The reason for writing this article: the project encountered problems, in an apk interface long press the power button to choose shutdown or restart, apk will appear restart phenomenon. After carefully studying the relevant source code of shutdown/restart, some logic was modified to solve the problem. Let's use a blog to record the pit we stepped on.

The starting point of this article is the logic of shutdown/restart in the framework layer. We focus on two classes: Phone Windows Manager. Java ShutdownThread. java. Specific code calls are not explained here. If you are interested, please refer to the source code by yourself. The general process is as follows:
Receive power Long Press Event - > power Long Press () > Pop-up Dialog Box - > Select Shutdown/Restart Options - > Execute Shutdown/Restart

After reading the source code, it is found that the shutdown process is mainly implemented in HutdownThread. java. The emphasis is on the following methods:

1.shutdown method

    /**
     * Request a clean shutdown, waiting for subsystems to clean up their
     * state etc.  Must be called from a Looper thread in which its UI
     * is shown.
     *
     * @param context Context used to display the shutdown progress dialog.
     * @param reason code to pass to android_reboot() (e.g. "userrequested"), or null.
     * @param confirm true if user confirmation is needed before shutting down.
     */
    public static void shutdown(final Context context, String reason, boolean confirm) {
        mReboot = false;
        mRebootSafeMode = false;
        mReason = reason;
        shutdownInner(context, confirm);
    }

2.reboot method

    /**
     * Request a clean shutdown, waiting for subsystems to clean up their
     * state etc.  Must be called from a Looper thread in which its UI
     * is shown.
     *
     * @param context Context used to display the shutdown progress dialog.
     * @param reason code to pass to the kernel (e.g. "recovery"), or null.
     * @param confirm true if user confirmation is needed before shutting down.
     */
    public static void reboot(final Context context, String reason, boolean confirm) {
        mReboot = true;
        mRebootSafeMode = false;
        mRebootHasProgressBar = false;
        mReason = reason;
        shutdownInner(context, confirm);
    }

3.rebootOrShutdown method

    /**
     * Do not call this directly. Use {@link #reboot(Context, String, boolean)}
     * or {@link #shutdown(Context, boolean)} instead.
     *
     * @param context Context used to vibrate or null without vibration
     * @param reboot true to reboot or false to shutdown
     * @param reason reason for reboot/shutdown
     */
    public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
        if (reboot) {
            Log.i(TAG, "Rebooting, reason: " + reason);
            PowerManagerService.lowLevelReboot(reason);
            Log.e(TAG, "Reboot failed, will attempt shutdown instead");
            reason = null;
        } else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
            // vibrate before shutting down
            Vibrator vibrator = new SystemVibrator(context);
            try {
                vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
            } catch (Exception e) {
                // Failure to vibrate shouldn't interrupt shutdown.  Just log it.
                Log.w(TAG, "Failed to vibrate during shutdown.", e);
            }

            // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
            try {
                Thread.sleep(SHUTDOWN_VIBRATE_MS);
            } catch (InterruptedException unused) {
            }
        }

        // Shutdown power
        Log.i(TAG, "Performing low-level shutdown...");
        PowerManagerService.lowLevelShutdown(reason);
    }

Shut down/restart some of the main tasks:
Send off broadcasting
Close AMS
Close PMS
Close MountService
Power Manager Service calls the kernel to shut down/restart

Early warning - knock on the blackboard, the point is coming!!!!

When shutting down MountService, if a process is still operating on the SD card (e.g. logging), Baidu knows that the process of occupying the SD card is usually stubborn, then the problem arises. This process may be restarted immediately after killing. The number of restarts may be 1, 2, 3, 4 times, so there is a vicious circle: kill-restart-kill-restart. . What you see is a blinding blindness. Unexpectedly, shutting down the machine is so bad, even if it wastes time, but also flash, simply can not bear!

The question is confirmed, and then how to fix. Shut down here, the upper level has so many operations, encounter stubborn process is not good, how complete? Simple rough point, try to skip some operations, directly into rebootOrShutdown call the bottom, the top can not kill, the bottom directly seconds kill? Do as you say, open the ShutdownThread.java source code, block what display boxes, broadcast, close the service logic, compile firmware and verify.

Result: Direct second killing shortened the time.

Direct patch:

--- a/frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
@@ -251,7 +251,7 @@ public final class ShutdownThread extends Thread {
             }
             sIsStarted = true;
         }
-
+/*forlan modified to reboot and shutdown more quickly start
         // Throw up a system dialog to indicate the device is rebooting / shutting down.
         ProgressDialog pd = new ProgressDialog(context);

@@ -342,7 +342,7 @@ public final class ShutdownThread extends Thread {
                 sInstance.mScreenWakeLock = null;
             }
         }
-
+forlan modified to reboot and shutdown more quickly end*/
         // start the thread that initiates shutdown
         sInstance.mHandler = new Handler() {
         };
@@ -387,7 +387,7 @@ public final class ShutdownThread extends Thread {
         }

         Log.i(TAG, "Sending shutdown broadcast...");
-
+/*forlan modified to reboot and shutdown more quickly start
         // First send the high-level shut down broadcast.
         mActionDone = false;
         Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
@@ -499,7 +499,7 @@ public final class ShutdownThread extends Thread {
             // done yet, trigger it now.
             uncrypt();
         }
-
+forlan modified to reboot and shutdown more quickly end*/
         rebootOrShutdown(mContext, mReboot, mReason);
     }

Topics: Java Android Windows