Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c07102a authored by Martin Wallgren's avatar Martin Wallgren Committed by Steve Kondik
Browse files

Parallel shutdown

Decrease shutdown time by doing some shutdown tasks in parallel.

There are two threads executing during the shut down: the ShutdownThread
and a separate thread for the radio shutdown. However, the execution is
done in serial, as the ShutdownThread immediately joins on the radio
thread.

This commit will move the shutdown of the radio to the beginning of
shutdown and execute it in parallel to the shutdown of the rest of the
system.

The flow of the two threads during shutdown is now:

Radio Thread
  * Start shutdown of the radio
  * Wait for radio off or time out
  * Notify that the radio is done
ShutdownThread
  * Broadcast ACTION_SHUTDOWN as a parallel broadcast. (The receivers
    will get as much time to handle onReceive as it takes execute the
    rest of the tasks in the shut down flow. If they are not done in
    that time, we don't care.)
  * Shutdown ActivityManager
  * Shutdown MountService
  * Wait for MountService and radio to notify done
  * Vibrate
  * Low level shutdown

Change-Id: Ifdd8a9c75337fd9d00148a0d2b9917e10fa60634
parent b54a0af9
Loading
Loading
Loading
Loading
+14 −40
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@

package com.android.server.power;

import java.util.concurrent.atomic.AtomicBoolean;

import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -86,6 +88,8 @@ public final class ShutdownThread extends Thread {
    
    private final Object mActionDoneSync = new Object();
    private boolean mActionDone;
    private AtomicBoolean mModemDone = new AtomicBoolean(false);
    private AtomicBoolean mMountServiceDone = new AtomicBoolean(false);
    private Context mContext;
    private PowerManager mPowerManager;
    private PowerManager.WakeLock mCpuWakeLock;
@@ -342,7 +346,7 @@ public final class ShutdownThread extends Thread {

    void actionDone() {
        synchronized (mActionDoneSync) {
            mActionDone = true;
            mActionDone = mMountServiceDone.get() && mModemDone.get();
            mActionDoneSync.notifyAll();
        }
    }
@@ -352,13 +356,6 @@ public final class ShutdownThread extends Thread {
     * Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
     */
    public void run() {
        BroadcastReceiver br = new BroadcastReceiver() {
            @Override public void onReceive(Context context, Intent intent) {
                // We don't allow apps to cancel this, so ignore the result.
                actionDone();
            }
        };

        /*
         * Write a system property in case the system_server reboots before we
         * get to the actual hardware restart. If that happens, we'll retry at
@@ -376,31 +373,14 @@ public final class ShutdownThread extends Thread {
        if (mRebootSafeMode) {
            SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
        }

        // Shutdown radios.
        shutdownRadios(MAX_RADIO_WAIT_TIME);
        Log.i(TAG, "Sending shutdown broadcast...");

        // First send the high-level shut down broadcast.
        mActionDone = false;
        Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        mContext.sendOrderedBroadcastAsUser(intent,
                UserHandle.ALL, null, br, mHandler, 0, null, null);
        
        final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
        synchronized (mActionDoneSync) {
            while (!mActionDone) {
                long delay = endTime - SystemClock.elapsedRealtime();
                if (delay <= 0) {
                    Log.w(TAG, "Shutdown broadcast timed out");
                    break;
                }
                try {
                    mActionDoneSync.wait(delay);
                } catch (InterruptedException e) {
                }
            }
        }

        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
        Log.i(TAG, "Shutting down activity manager...");

        final IActivityManager am =
@@ -412,13 +392,11 @@ public final class ShutdownThread extends Thread {
            }
        }

        // Shutdown radios.
        shutdownRadios(MAX_RADIO_WAIT_TIME);

        // Shutdown MountService to ensure media is in a safe state
        IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
            public void onShutDownComplete(int statusCode) throws RemoteException {
                Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown");
                mMountServiceDone.set(true);
                actionDone();
            }
        };
@@ -426,7 +404,6 @@ public final class ShutdownThread extends Thread {
        Log.i(TAG, "Shutting down MountService");

        // Set initial variables and time out time.
        mActionDone = false;
        final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;
        synchronized (mActionDoneSync) {
            try {
@@ -582,17 +559,14 @@ public final class ShutdownThread extends Thread {
                    }
                    SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
                }
            }
        };

        t.start();
        try {
            t.join(timeout);
        } catch (InterruptedException ex) {
        }
                if (!done[0]) {
                    Log.w(TAG, "Timed out waiting for NFC, Radio and Bluetooth shutdown.");
                }
                mModemDone.set(true);
                actionDone();
            }
        };
        t.start();
    }

    /**