1e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov/* 2e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * Copyright (C) 2016 The Android Open Source Project 3e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * 4e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * Licensed under the Apache License, Version 2.0 (the "License"); 5e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * you may not use this file except in compliance with the License. 6e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * You may obtain a copy of the License at 7e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * 8e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * http://www.apache.org/licenses/LICENSE-2.0 9e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * 10e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * Unless required by applicable law or agreed to in writing, software 11e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * distributed under the License is distributed on an "AS IS" BASIS, 12e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * See the License for the specific language governing permissions and 14e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * limitations under the License 15e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov */ 16e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov 17e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovpackage com.android.server; 18e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov 19e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport android.os.Build; 20e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport android.os.Process; 21e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport android.util.Slog; 22e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov 23e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport com.android.internal.util.ConcurrentUtils; 24e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport com.android.internal.util.Preconditions; 25e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov 26e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport java.util.List; 27e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport java.util.concurrent.Callable; 28e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport java.util.concurrent.ExecutorService; 29e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport java.util.concurrent.Future; 30e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport java.util.concurrent.TimeUnit; 31e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov 32e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov/** 33e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * Thread pool used during initialization of system server. 34e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * <p>System services can {@link #submit(Runnable)} tasks for execution during boot. 35e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * The pool will be shut down after {@link SystemService#PHASE_BOOT_COMPLETED}. 36e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * New tasks <em>should not</em> be submitted afterwards. 37e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * 38e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov * @hide 39e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov */ 40e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovpublic class SystemServerInitThreadPool { 41e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov private static final String TAG = SystemServerInitThreadPool.class.getSimpleName(); 42e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov private static final int SHUTDOWN_TIMEOUT_MILLIS = 20000; 43e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov private static final boolean IS_DEBUGGABLE = Build.IS_DEBUGGABLE; 44e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov 45e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov private static SystemServerInitThreadPool sInstance; 46e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov 47b76e0fdf1ef2767e2d4f0ced2886756ff9556b19Fyodor Kupolov private ExecutorService mService = ConcurrentUtils.newFixedThreadPool(4, 48e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov "system-server-init-thread", Process.THREAD_PRIORITY_FOREGROUND); 49e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov 50e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov public static synchronized SystemServerInitThreadPool get() { 51e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov if (sInstance == null) { 52e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov sInstance = new SystemServerInitThreadPool(); 53e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov } 54e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov Preconditions.checkState(sInstance.mService != null, "Cannot get " + TAG 55e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov + " - it has been shut down"); 56e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov return sInstance; 57e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov } 58e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov 59e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov public Future<?> submit(Runnable runnable, String description) { 60e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov if (IS_DEBUGGABLE) { 61e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov return mService.submit(() -> { 62e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov Slog.d(TAG, "Started executing " + description); 63e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov try { 64e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov runnable.run(); 65e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov } catch (RuntimeException e) { 66e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov Slog.e(TAG, "Failure in " + description + ": " + e, e); 67e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov throw e; 68e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov } 69e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov Slog.d(TAG, "Finished executing " + description); 70e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov }); 71e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov } 72e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov return mService.submit(runnable); 73e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov } 74e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov 75e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov static synchronized void shutdown() { 76e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov if (sInstance != null && sInstance.mService != null) { 77e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov sInstance.mService.shutdown(); 78e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov boolean terminated; 79e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov try { 80e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov terminated = sInstance.mService.awaitTermination(SHUTDOWN_TIMEOUT_MILLIS, 81e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov TimeUnit.MILLISECONDS); 82e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov } catch (InterruptedException e) { 83e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov Thread.currentThread().interrupt(); 84e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov throw new IllegalStateException(TAG + " init interrupted"); 85e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov } 86e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov List<Runnable> unstartedRunnables = sInstance.mService.shutdownNow(); 87e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov if (!terminated) { 88e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov throw new IllegalStateException("Cannot shutdown. Unstarted tasks " 89e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov + unstartedRunnables); 90e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov } 91e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov sInstance.mService = null; // Make mService eligible for GC 92e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov Slog.d(TAG, "Shutdown successful"); 93e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov } 94e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov } 95e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov 96e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov} 97