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

Commit 38d00662 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Minor improvements on SystemServerInitThreadPool:"

parents e58b8dd2 29f1ae91
Loading
Loading
Loading
Loading
+67 −18
Original line number Diff line number Diff line
@@ -16,10 +16,12 @@

package com.android.server;

import android.annotation.NonNull;
import android.os.Build;
import android.os.Process;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.Preconditions;
import com.android.server.am.ActivityManagerService;
@@ -32,9 +34,11 @@ import java.util.concurrent.TimeUnit;

/**
 * Thread pool used during initialization of system server.
 *
 * <p>System services can {@link #submit(Runnable)} tasks for execution during boot.
 * The pool will be shut down after {@link SystemService#PHASE_BOOT_COMPLETED}.
 * New tasks <em>should not</em> be submitted afterwards.
 *
 * <p>New tasks <em>should not</em> be submitted afterwards.
 *
 * @hide
 */
@@ -42,26 +46,46 @@ public class SystemServerInitThreadPool {
    private static final String TAG = SystemServerInitThreadPool.class.getSimpleName();
    private static final int SHUTDOWN_TIMEOUT_MILLIS = 20000;
    private static final boolean IS_DEBUGGABLE = Build.IS_DEBUGGABLE;
    private static final Object LOCK = new Object();

    @GuardedBy("LOCK")
    private static SystemServerInitThreadPool sInstance;

    private ExecutorService mService = ConcurrentUtils.newFixedThreadPool(
            Runtime.getRuntime().availableProcessors(),
            "system-server-init-thread", Process.THREAD_PRIORITY_FOREGROUND);
    private final ExecutorService mService;

    private List<String> mPendingTasks = new ArrayList<>();
    @GuardedBy("mPendingTasks")
    private final List<String> mPendingTasks = new ArrayList<>();

    public static synchronized SystemServerInitThreadPool get() {
        if (sInstance == null) {
            sInstance = new SystemServerInitThreadPool();
    @GuardedBy("mPendingTasks")
    private boolean mShutDown;

    private SystemServerInitThreadPool() {
        final int size = Runtime.getRuntime().availableProcessors();
        Slog.i(TAG, "Creating instance with " + size + " threads");
        mService = ConcurrentUtils.newFixedThreadPool(size,
                "system-server-init-thread", Process.THREAD_PRIORITY_FOREGROUND);
    }
        Preconditions.checkState(sInstance.mService != null, "Cannot get " + TAG

    /**
     * Gets the singleton.
     *
     * @throws IllegalStateException if it hasn't been started or has been shut down already.
     */
    public static SystemServerInitThreadPool get() {
        synchronized (LOCK) {
            Preconditions.checkState(sInstance != null, "Cannot get " + TAG
                    + " - it has been shut down");
            return sInstance;
        }
    }

    public Future<?> submit(Runnable runnable, String description) {
    /**
     * Submits a task for execution.
     */
    public @NonNull Future<?> submit(@NonNull Runnable runnable, @NonNull String description) {
        Preconditions.checkNotNull(description, "description cannot be null");
        synchronized (mPendingTasks) {
            Preconditions.checkState(!mShutDown, TAG + " already shut down");
            mPendingTasks.add(description);
        }
        return mService.submit(() -> {
@@ -83,10 +107,36 @@ public class SystemServerInitThreadPool {
        });
    }

    static synchronized void shutdown() {
        if (sInstance != null && sInstance.mService != null) {
    /**
     * Starts it.
     *
     * <p>Note:</p> should only be called by {@link SystemServer}.
     *
     * @throws IllegalStateException if it has been started already without being shut down yet.
     */
    static void start() {
        synchronized (LOCK) {
            Preconditions.checkState(sInstance == null, TAG + " already started");
            sInstance = new SystemServerInitThreadPool();
        }
    }

    /**
     * Shuts it down.
     *
     * <p>Note:</p> should only be called by {@link SystemServer}.
     */
    static void shutdown() {
        synchronized (LOCK) {
            if (sInstance == null) {
                Slog.wtf(TAG, "Already shutdown", new Exception());
                return;
            }
            synchronized (sInstance.mPendingTasks) {
                sInstance.mShutDown = true;
            }
            sInstance.mService.shutdown();
            boolean terminated;
            final boolean terminated;
            try {
                terminated = sInstance.mService.awaitTermination(SHUTDOWN_TIMEOUT_MILLIS,
                        TimeUnit.MILLISECONDS);
@@ -100,7 +150,7 @@ public class SystemServerInitThreadPool {
                // in the thread pool.
                dumpStackTraces();
            }
            List<Runnable> unstartedRunnables = sInstance.mService.shutdownNow();
            final List<Runnable> unstartedRunnables = sInstance.mService.shutdownNow();
            if (!terminated) {
                final List<String> copy = new ArrayList<>();
                synchronized (sInstance.mPendingTasks) {
@@ -109,8 +159,7 @@ public class SystemServerInitThreadPool {
                throw new IllegalStateException("Cannot shutdown. Unstarted tasks "
                        + unstartedRunnables + " Unfinished tasks " + copy);
            }
            sInstance.mService = null; // Make mService eligible for GC
            sInstance.mPendingTasks = null;
            sInstance = null; // Make eligible for GC
            Slog.d(TAG, "Shutdown successful");
        }
    }
+1 −1
Original line number Diff line number Diff line
@@ -501,7 +501,7 @@ public final class SystemServer {
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // Prepare the thread pool for init tasks that can be parallelized
            SystemServerInitThreadPool.get();
            SystemServerInitThreadPool.start();
        } finally {
            t.traceEnd();  // InitBeforeStartServices
        }