Loading core/java/com/android/internal/util/ConcurrentUtils.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.internal.util; import android.os.Process; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; /** * Utility methods for common functionality using java.util.concurrent package * * @hide */ public class ConcurrentUtils { private ConcurrentUtils() { } /** * Creates a thread pool using * {@link java.util.concurrent.Executors#newFixedThreadPool(int, ThreadFactory)} * * @param nThreads the number of threads in the pool * @param poolName base name of the threads in the pool * @param linuxThreadPriority a Linux priority level. see {@link Process#setThreadPriority(int)} * @return the newly created thread pool */ public static ExecutorService newFixedThreadPool(int nThreads, String poolName, int linuxThreadPriority) { return Executors.newFixedThreadPool(nThreads, new ThreadFactory() { private final AtomicInteger threadNum = new AtomicInteger(0); @Override public Thread newThread(final Runnable r) { return new Thread(poolName + threadNum.incrementAndGet()) { @Override public void run() { Process.setThreadPriority(linuxThreadPriority); r.run(); } }; } }); } /** * Waits if necessary for the computation to complete, and then retrieves its result. * <p>If {@code InterruptedException} occurs, this method will interrupt the current thread * and throw {@code IllegalStateException}</p> * * @param future future to wait for result * @param description short description of the operation * @return the computed result * @throws IllegalStateException if interrupted during wait * @throws RuntimeException if an error occurs while waiting for {@link Future#get()} * @see Future#get() */ public static <T> T waitForFutureNoInterrupt(Future<T> future, String description) { try { return future.get(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IllegalStateException(description + " interrupted"); } catch (ExecutionException e) { throw new RuntimeException(description + " failed", e); } } } services/core/java/com/android/server/PersistentDataBlockService.java +2 −2 Original line number Diff line number Diff line Loading @@ -116,12 +116,12 @@ public class PersistentDataBlockService extends SystemService { @Override public void onStart() { // Do init on a separate thread, will join in PHASE_ACTIVITY_MANAGER_READY FgThread.getHandler().post(() -> { SystemServerInitThreadPool.get().submit(() -> { enforceChecksumValidity(); formatIfOemUnlockEnabled(); publishBinderService(Context.PERSISTENT_DATA_BLOCK_SERVICE, mService); mInitDoneSignal.countDown(); }); }, TAG + ".onStart"); } @Override Loading services/core/java/com/android/server/SystemServerInitThreadPool.java 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server; import android.os.Build; import android.os.Process; import android.util.Slog; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.Preconditions; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; 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. * * @hide */ 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 SystemServerInitThreadPool sInstance; private ExecutorService mService = ConcurrentUtils.newFixedThreadPool(2, "system-server-init-thread", Process.THREAD_PRIORITY_FOREGROUND); public static synchronized SystemServerInitThreadPool get() { if (sInstance == null) { sInstance = new SystemServerInitThreadPool(); } Preconditions.checkState(sInstance.mService != null, "Cannot get " + TAG + " - it has been shut down"); return sInstance; } public Future<?> submit(Runnable runnable, String description) { if (IS_DEBUGGABLE) { return mService.submit(() -> { Slog.d(TAG, "Started executing " + description); try { runnable.run(); } catch (RuntimeException e) { Slog.e(TAG, "Failure in " + description + ": " + e, e); throw e; } Slog.d(TAG, "Finished executing " + description); }); } return mService.submit(runnable); } static synchronized void shutdown() { if (sInstance != null && sInstance.mService != null) { sInstance.mService.shutdown(); boolean terminated; try { terminated = sInstance.mService.awaitTermination(SHUTDOWN_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IllegalStateException(TAG + " init interrupted"); } List<Runnable> unstartedRunnables = sInstance.mService.shutdownNow(); if (!terminated) { throw new IllegalStateException("Cannot shutdown. Unstarted tasks " + unstartedRunnables); } sInstance.mService = null; // Make mService eligible for GC Slog.d(TAG, "Shutdown successful"); } } } services/core/java/com/android/server/UiModeManagerService.java +6 −4 Original line number Diff line number Diff line Loading @@ -208,11 +208,13 @@ final class UiModeManagerService extends SystemService { Settings.Secure.UI_NIGHT_MODE, defaultNightMode); // Update the initial, static configurations. synchronized (this) { SystemServerInitThreadPool.get().submit(() -> { synchronized (mLock) { updateConfigurationLocked(); sendConfigurationLocked(); } }, TAG + ".onStart"); publishBinderService(Context.UI_MODE_SERVICE, mService); } Loading services/core/java/com/android/server/fingerprint/FingerprintService.java +2 −2 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.server.FgThread; import com.android.server.SystemServerInitThreadPool; import com.android.server.SystemService; import org.json.JSONArray; Loading Loading @@ -1077,7 +1077,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe @Override public void onStart() { publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper()); FgThread.getHandler().post(() -> getFingerprintDaemon()); SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart"); listenForUserSwitches(); } Loading Loading
core/java/com/android/internal/util/ConcurrentUtils.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.internal.util; import android.os.Process; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; /** * Utility methods for common functionality using java.util.concurrent package * * @hide */ public class ConcurrentUtils { private ConcurrentUtils() { } /** * Creates a thread pool using * {@link java.util.concurrent.Executors#newFixedThreadPool(int, ThreadFactory)} * * @param nThreads the number of threads in the pool * @param poolName base name of the threads in the pool * @param linuxThreadPriority a Linux priority level. see {@link Process#setThreadPriority(int)} * @return the newly created thread pool */ public static ExecutorService newFixedThreadPool(int nThreads, String poolName, int linuxThreadPriority) { return Executors.newFixedThreadPool(nThreads, new ThreadFactory() { private final AtomicInteger threadNum = new AtomicInteger(0); @Override public Thread newThread(final Runnable r) { return new Thread(poolName + threadNum.incrementAndGet()) { @Override public void run() { Process.setThreadPriority(linuxThreadPriority); r.run(); } }; } }); } /** * Waits if necessary for the computation to complete, and then retrieves its result. * <p>If {@code InterruptedException} occurs, this method will interrupt the current thread * and throw {@code IllegalStateException}</p> * * @param future future to wait for result * @param description short description of the operation * @return the computed result * @throws IllegalStateException if interrupted during wait * @throws RuntimeException if an error occurs while waiting for {@link Future#get()} * @see Future#get() */ public static <T> T waitForFutureNoInterrupt(Future<T> future, String description) { try { return future.get(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IllegalStateException(description + " interrupted"); } catch (ExecutionException e) { throw new RuntimeException(description + " failed", e); } } }
services/core/java/com/android/server/PersistentDataBlockService.java +2 −2 Original line number Diff line number Diff line Loading @@ -116,12 +116,12 @@ public class PersistentDataBlockService extends SystemService { @Override public void onStart() { // Do init on a separate thread, will join in PHASE_ACTIVITY_MANAGER_READY FgThread.getHandler().post(() -> { SystemServerInitThreadPool.get().submit(() -> { enforceChecksumValidity(); formatIfOemUnlockEnabled(); publishBinderService(Context.PERSISTENT_DATA_BLOCK_SERVICE, mService); mInitDoneSignal.countDown(); }); }, TAG + ".onStart"); } @Override Loading
services/core/java/com/android/server/SystemServerInitThreadPool.java 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server; import android.os.Build; import android.os.Process; import android.util.Slog; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.Preconditions; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; 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. * * @hide */ 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 SystemServerInitThreadPool sInstance; private ExecutorService mService = ConcurrentUtils.newFixedThreadPool(2, "system-server-init-thread", Process.THREAD_PRIORITY_FOREGROUND); public static synchronized SystemServerInitThreadPool get() { if (sInstance == null) { sInstance = new SystemServerInitThreadPool(); } Preconditions.checkState(sInstance.mService != null, "Cannot get " + TAG + " - it has been shut down"); return sInstance; } public Future<?> submit(Runnable runnable, String description) { if (IS_DEBUGGABLE) { return mService.submit(() -> { Slog.d(TAG, "Started executing " + description); try { runnable.run(); } catch (RuntimeException e) { Slog.e(TAG, "Failure in " + description + ": " + e, e); throw e; } Slog.d(TAG, "Finished executing " + description); }); } return mService.submit(runnable); } static synchronized void shutdown() { if (sInstance != null && sInstance.mService != null) { sInstance.mService.shutdown(); boolean terminated; try { terminated = sInstance.mService.awaitTermination(SHUTDOWN_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IllegalStateException(TAG + " init interrupted"); } List<Runnable> unstartedRunnables = sInstance.mService.shutdownNow(); if (!terminated) { throw new IllegalStateException("Cannot shutdown. Unstarted tasks " + unstartedRunnables); } sInstance.mService = null; // Make mService eligible for GC Slog.d(TAG, "Shutdown successful"); } } }
services/core/java/com/android/server/UiModeManagerService.java +6 −4 Original line number Diff line number Diff line Loading @@ -208,11 +208,13 @@ final class UiModeManagerService extends SystemService { Settings.Secure.UI_NIGHT_MODE, defaultNightMode); // Update the initial, static configurations. synchronized (this) { SystemServerInitThreadPool.get().submit(() -> { synchronized (mLock) { updateConfigurationLocked(); sendConfigurationLocked(); } }, TAG + ".onStart"); publishBinderService(Context.UI_MODE_SERVICE, mService); } Loading
services/core/java/com/android/server/fingerprint/FingerprintService.java +2 −2 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.server.FgThread; import com.android.server.SystemServerInitThreadPool; import com.android.server.SystemService; import org.json.JSONArray; Loading Loading @@ -1077,7 +1077,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe @Override public void onStart() { publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper()); FgThread.getHandler().post(() -> getFingerprintDaemon()); SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart"); listenForUserSwitches(); } Loading