blob: 581914db4bfabe545daba8a7dbec27cbc74e18dc [file] [log] [blame]
Adam Lesinski182f73f2013-12-05 16:48:06 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
MÃ¥rten Kongstad2e0d0f32016-06-02 09:35:31 +020019import android.annotation.NonNull;
Adam Lesinski182f73f2013-12-05 16:48:06 -080020import android.content.Context;
Wei Wangc3a76d02017-07-14 11:39:30 -070021import android.os.SystemClock;
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +090022import android.os.Trace;
Adam Lesinski182f73f2013-12-05 16:48:06 -080023import android.util.Slog;
24
Jeff Brownb880d882014-02-10 19:47:07 -080025import java.lang.reflect.Constructor;
26import java.lang.reflect.InvocationTargetException;
Adam Lesinski182f73f2013-12-05 16:48:06 -080027import java.util.ArrayList;
28
29/**
Adam Lesinskib102b2c2013-12-20 11:46:14 -080030 * Manages creating, starting, and other lifecycle events of
Jeff Brownb880d882014-02-10 19:47:07 -080031 * {@link com.android.server.SystemService system services}.
Adam Lesinskib102b2c2013-12-20 11:46:14 -080032 *
33 * {@hide}
Adam Lesinski182f73f2013-12-05 16:48:06 -080034 */
35public class SystemServiceManager {
36 private static final String TAG = "SystemServiceManager";
Fyodor Kupolov701a85f2017-04-25 12:52:08 -070037 private static final int SERVICE_CALL_WARN_TIME_MS = 50;
Adam Lesinski182f73f2013-12-05 16:48:06 -080038
39 private final Context mContext;
Amith Yamasani91588252013-11-22 08:25:26 -080040 private boolean mSafeMode;
Fyodor Kupolov1d87e402017-01-10 18:34:10 -080041 private boolean mRuntimeRestarted;
Adam Lesinski182f73f2013-12-05 16:48:06 -080042
43 // Services that should receive lifecycle events.
44 private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
45
46 private int mCurrentPhase = -1;
47
Fyodor Kupolov1d87e402017-01-10 18:34:10 -080048 SystemServiceManager(Context context) {
Adam Lesinski182f73f2013-12-05 16:48:06 -080049 mContext = context;
50 }
51
Jeff Brown6f357d32014-01-15 20:40:55 -080052 /**
Adam Lesinski2cb6c602014-02-14 17:19:56 -080053 * Starts a service by class name.
Jeff Brown6f357d32014-01-15 20:40:55 -080054 *
Adam Lesinski2cb6c602014-02-14 17:19:56 -080055 * @return The service instance.
Jeff Brown6f357d32014-01-15 20:40:55 -080056 */
57 @SuppressWarnings("unchecked")
Jeff Brown2c43c332014-06-12 22:38:59 -070058 public SystemService startService(String className) {
59 final Class<SystemService> serviceClass;
60 try {
61 serviceClass = (Class<SystemService>)Class.forName(className);
62 } catch (ClassNotFoundException ex) {
63 Slog.i(TAG, "Starting " + className);
64 throw new RuntimeException("Failed to create service " + className
65 + ": service class not found, usually indicates that the caller should "
66 + "have called PackageManager.hasSystemFeature() to check whether the "
67 + "feature is available on this device before trying to start the "
68 + "services that implement it", ex);
69 }
70 return startService(serviceClass);
Amith Yamasani91588252013-11-22 08:25:26 -080071 }
72
Adam Lesinski182f73f2013-12-05 16:48:06 -080073 /**
74 * Creates and starts a system service. The class must be a subclass of
75 * {@link com.android.server.SystemService}.
76 *
77 * @param serviceClass A Java class that implements the SystemService interface.
Jeff Brown6f357d32014-01-15 20:40:55 -080078 * @return The service instance, never null.
Adam Lesinski182f73f2013-12-05 16:48:06 -080079 * @throws RuntimeException if the service fails to start.
80 */
Jeff Brown6f357d32014-01-15 20:40:55 -080081 @SuppressWarnings("unchecked")
82 public <T extends SystemService> T startService(Class<T> serviceClass) {
Adam Lesinski182f73f2013-12-05 16:48:06 -080083 try {
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +090084 final String name = serviceClass.getName();
85 Slog.i(TAG, "Starting " + name);
86 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);
Adam Lesinski182f73f2013-12-05 16:48:06 -080087
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +090088 // Create the service.
89 if (!SystemService.class.isAssignableFrom(serviceClass)) {
90 throw new RuntimeException("Failed to create " + name
91 + ": service must extend " + SystemService.class.getName());
92 }
93 final T service;
94 try {
95 Constructor<T> constructor = serviceClass.getConstructor(Context.class);
96 service = constructor.newInstance(mContext);
97 } catch (InstantiationException ex) {
98 throw new RuntimeException("Failed to create service " + name
99 + ": service could not be instantiated", ex);
100 } catch (IllegalAccessException ex) {
101 throw new RuntimeException("Failed to create service " + name
102 + ": service must have a public constructor with a Context argument", ex);
103 } catch (NoSuchMethodException ex) {
104 throw new RuntimeException("Failed to create service " + name
105 + ": service must have a public constructor with a Context argument", ex);
106 } catch (InvocationTargetException ex) {
107 throw new RuntimeException("Failed to create service " + name
108 + ": service constructor threw an exception", ex);
109 }
Adam Lesinski182f73f2013-12-05 16:48:06 -0800110
MÃ¥rten Kongstad2e0d0f32016-06-02 09:35:31 +0200111 startService(service);
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900112 return service;
113 } finally {
114 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800115 }
116 }
117
MÃ¥rten Kongstad2e0d0f32016-06-02 09:35:31 +0200118 public void startService(@NonNull final SystemService service) {
119 // Register it.
120 mServices.add(service);
121 // Start it.
Wei Wangc3a76d02017-07-14 11:39:30 -0700122 long time = SystemClock.elapsedRealtime();
MÃ¥rten Kongstad2e0d0f32016-06-02 09:35:31 +0200123 try {
124 service.onStart();
125 } catch (RuntimeException ex) {
126 throw new RuntimeException("Failed to start service " + service.getClass().getName()
127 + ": onStart threw an exception", ex);
128 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700129 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
MÃ¥rten Kongstad2e0d0f32016-06-02 09:35:31 +0200130 }
131
Adam Lesinski182f73f2013-12-05 16:48:06 -0800132 /**
133 * Starts the specified boot phase for all system services that have been started up to
134 * this point.
135 *
136 * @param phase The boot phase to start.
137 */
138 public void startBootPhase(final int phase) {
139 if (phase <= mCurrentPhase) {
140 throw new IllegalArgumentException("Next phase must be larger than previous");
141 }
142 mCurrentPhase = phase;
143
144 Slog.i(TAG, "Starting phase " + mCurrentPhase);
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900145 try {
146 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "OnBootPhase " + phase);
147 final int serviceLen = mServices.size();
148 for (int i = 0; i < serviceLen; i++) {
149 final SystemService service = mServices.get(i);
Wei Wangc3a76d02017-07-14 11:39:30 -0700150 long time = SystemClock.elapsedRealtime();
Philip Cuadra4345c0d2016-08-17 18:02:24 -0700151 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, service.getClass().getName());
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900152 try {
153 service.onBootPhase(mCurrentPhase);
154 } catch (Exception ex) {
155 throw new RuntimeException("Failed to boot service "
156 + service.getClass().getName()
157 + ": onBootPhase threw an exception during phase "
158 + mCurrentPhase, ex);
159 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700160 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onBootPhase");
Philip Cuadra4345c0d2016-08-17 18:02:24 -0700161 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800162 }
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900163 } finally {
164 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800165 }
166 }
167
Keun-young Park4136d2d2017-05-08 14:51:59 -0700168 /**
169 * @return true if system has completed the boot; false otherwise.
170 */
171 public boolean isBootCompleted() {
172 return mCurrentPhase >= SystemService.PHASE_BOOT_COMPLETED;
173 }
174
Dianne Hackborn91097de2014-04-04 18:02:06 -0700175 public void startUser(final int userHandle) {
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700176 Slog.i(TAG, "Calling onStartUser u" + userHandle);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700177 final int serviceLen = mServices.size();
178 for (int i = 0; i < serviceLen; i++) {
179 final SystemService service = mServices.get(i);
Philip Cuadraca3329c2016-06-24 12:02:06 -0700180 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onStartUser "
181 + service.getClass().getName());
Wei Wangc3a76d02017-07-14 11:39:30 -0700182 long time = SystemClock.elapsedRealtime();
Dianne Hackborn91097de2014-04-04 18:02:06 -0700183 try {
184 service.onStartUser(userHandle);
185 } catch (Exception ex) {
186 Slog.wtf(TAG, "Failure reporting start of user " + userHandle
187 + " to service " + service.getClass().getName(), ex);
188 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700189 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStartUser ");
Philip Cuadraca3329c2016-06-24 12:02:06 -0700190 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700191 }
192 }
193
Jeff Sharkeybedbaa92015-12-02 16:42:25 -0700194 public void unlockUser(final int userHandle) {
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700195 Slog.i(TAG, "Calling onUnlockUser u" + userHandle);
Jeff Sharkeybedbaa92015-12-02 16:42:25 -0700196 final int serviceLen = mServices.size();
197 for (int i = 0; i < serviceLen; i++) {
198 final SystemService service = mServices.get(i);
Philip Cuadraca3329c2016-06-24 12:02:06 -0700199 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onUnlockUser "
200 + service.getClass().getName());
Wei Wangc3a76d02017-07-14 11:39:30 -0700201 long time = SystemClock.elapsedRealtime();
Jeff Sharkeybedbaa92015-12-02 16:42:25 -0700202 try {
203 service.onUnlockUser(userHandle);
204 } catch (Exception ex) {
205 Slog.wtf(TAG, "Failure reporting unlock of user " + userHandle
206 + " to service " + service.getClass().getName(), ex);
207 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700208 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onUnlockUser ");
Philip Cuadraca3329c2016-06-24 12:02:06 -0700209 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Jeff Sharkeybedbaa92015-12-02 16:42:25 -0700210 }
211 }
212
Dianne Hackborn91097de2014-04-04 18:02:06 -0700213 public void switchUser(final int userHandle) {
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700214 Slog.i(TAG, "Calling switchUser u" + userHandle);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700215 final int serviceLen = mServices.size();
216 for (int i = 0; i < serviceLen; i++) {
217 final SystemService service = mServices.get(i);
Philip Cuadraca3329c2016-06-24 12:02:06 -0700218 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onSwitchUser "
219 + service.getClass().getName());
Wei Wangc3a76d02017-07-14 11:39:30 -0700220 long time = SystemClock.elapsedRealtime();
Dianne Hackborn91097de2014-04-04 18:02:06 -0700221 try {
222 service.onSwitchUser(userHandle);
223 } catch (Exception ex) {
224 Slog.wtf(TAG, "Failure reporting switch of user " + userHandle
225 + " to service " + service.getClass().getName(), ex);
226 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700227 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onSwitchUser");
Philip Cuadraca3329c2016-06-24 12:02:06 -0700228 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700229 }
230 }
231
232 public void stopUser(final int userHandle) {
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700233 Slog.i(TAG, "Calling onStopUser u" + userHandle);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700234 final int serviceLen = mServices.size();
235 for (int i = 0; i < serviceLen; i++) {
236 final SystemService service = mServices.get(i);
Philip Cuadraca3329c2016-06-24 12:02:06 -0700237 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onStopUser "
238 + service.getClass().getName());
Wei Wangc3a76d02017-07-14 11:39:30 -0700239 long time = SystemClock.elapsedRealtime();
Dianne Hackborn91097de2014-04-04 18:02:06 -0700240 try {
241 service.onStopUser(userHandle);
242 } catch (Exception ex) {
243 Slog.wtf(TAG, "Failure reporting stop of user " + userHandle
244 + " to service " + service.getClass().getName(), ex);
245 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700246 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStopUser");
Philip Cuadraca3329c2016-06-24 12:02:06 -0700247 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700248 }
249 }
250
251 public void cleanupUser(final int userHandle) {
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700252 Slog.i(TAG, "Calling onCleanupUser u" + userHandle);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700253 final int serviceLen = mServices.size();
254 for (int i = 0; i < serviceLen; i++) {
255 final SystemService service = mServices.get(i);
Philip Cuadraca3329c2016-06-24 12:02:06 -0700256 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onCleanupUser "
257 + service.getClass().getName());
Wei Wangc3a76d02017-07-14 11:39:30 -0700258 long time = SystemClock.elapsedRealtime();
Dianne Hackborn91097de2014-04-04 18:02:06 -0700259 try {
260 service.onCleanupUser(userHandle);
261 } catch (Exception ex) {
262 Slog.wtf(TAG, "Failure reporting cleanup of user " + userHandle
263 + " to service " + service.getClass().getName(), ex);
264 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700265 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onCleanupUser");
Philip Cuadraca3329c2016-06-24 12:02:06 -0700266 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700267 }
268 }
269
Amith Yamasani91588252013-11-22 08:25:26 -0800270 /** Sets the safe mode flag for services to query. */
Fyodor Kupolov1d87e402017-01-10 18:34:10 -0800271 void setSafeMode(boolean safeMode) {
Amith Yamasani91588252013-11-22 08:25:26 -0800272 mSafeMode = safeMode;
273 }
274
275 /**
276 * Returns whether we are booting into safe mode.
277 * @return safe mode flag
278 */
279 public boolean isSafeMode() {
280 return mSafeMode;
281 }
282
Adam Lesinski182f73f2013-12-05 16:48:06 -0800283 /**
Fyodor Kupolov1d87e402017-01-10 18:34:10 -0800284 * @return true if runtime was restarted, false if it's normal boot
285 */
286 public boolean isRuntimeRestarted() {
287 return mRuntimeRestarted;
288 }
289
290 void setRuntimeRestarted(boolean runtimeRestarted) {
291 mRuntimeRestarted = runtimeRestarted;
292 }
293
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700294 private void warnIfTooLong(long duration, SystemService service, String operation) {
295 if (duration > SERVICE_CALL_WARN_TIME_MS) {
296 Slog.w(TAG, "Service " + service.getClass().getName() + " took " + duration + " ms in "
297 + operation);
298 }
299 }
Fyodor Kupolov1d87e402017-01-10 18:34:10 -0800300
301 /**
Adam Lesinski182f73f2013-12-05 16:48:06 -0800302 * Outputs the state of this manager to the System log.
303 */
304 public void dump() {
305 StringBuilder builder = new StringBuilder();
306 builder.append("Current phase: ").append(mCurrentPhase).append("\n");
307 builder.append("Services:\n");
308 final int startedLen = mServices.size();
309 for (int i = 0; i < startedLen; i++) {
310 final SystemService service = mServices.get(i);
311 builder.append("\t")
312 .append(service.getClass().getSimpleName())
313 .append("\n");
314 }
315
316 Slog.e(TAG, builder.toString());
317 }
Adam Lesinski182f73f2013-12-05 16:48:06 -0800318}