blob: 63584d9e43e5df7440dc7f8b3e720d828a6104d0 [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;
Makoto Onukie8edbcf2018-03-02 16:49:29 -080042 private long mRuntimeStartElapsedTime;
43 private long mRuntimeStartUptime;
Adam Lesinski182f73f2013-12-05 16:48:06 -080044
45 // Services that should receive lifecycle events.
46 private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
47
48 private int mCurrentPhase = -1;
49
Fyodor Kupolov1d87e402017-01-10 18:34:10 -080050 SystemServiceManager(Context context) {
Adam Lesinski182f73f2013-12-05 16:48:06 -080051 mContext = context;
52 }
53
Jeff Brown6f357d32014-01-15 20:40:55 -080054 /**
Adam Lesinski2cb6c602014-02-14 17:19:56 -080055 * Starts a service by class name.
Jeff Brown6f357d32014-01-15 20:40:55 -080056 *
Adam Lesinski2cb6c602014-02-14 17:19:56 -080057 * @return The service instance.
Jeff Brown6f357d32014-01-15 20:40:55 -080058 */
59 @SuppressWarnings("unchecked")
Jeff Brown2c43c332014-06-12 22:38:59 -070060 public SystemService startService(String className) {
61 final Class<SystemService> serviceClass;
62 try {
63 serviceClass = (Class<SystemService>)Class.forName(className);
64 } catch (ClassNotFoundException ex) {
65 Slog.i(TAG, "Starting " + className);
66 throw new RuntimeException("Failed to create service " + className
67 + ": service class not found, usually indicates that the caller should "
68 + "have called PackageManager.hasSystemFeature() to check whether the "
69 + "feature is available on this device before trying to start the "
70 + "services that implement it", ex);
71 }
72 return startService(serviceClass);
Amith Yamasani91588252013-11-22 08:25:26 -080073 }
74
Adam Lesinski182f73f2013-12-05 16:48:06 -080075 /**
76 * Creates and starts a system service. The class must be a subclass of
77 * {@link com.android.server.SystemService}.
78 *
79 * @param serviceClass A Java class that implements the SystemService interface.
Jeff Brown6f357d32014-01-15 20:40:55 -080080 * @return The service instance, never null.
Adam Lesinski182f73f2013-12-05 16:48:06 -080081 * @throws RuntimeException if the service fails to start.
82 */
Jeff Brown6f357d32014-01-15 20:40:55 -080083 @SuppressWarnings("unchecked")
84 public <T extends SystemService> T startService(Class<T> serviceClass) {
Adam Lesinski182f73f2013-12-05 16:48:06 -080085 try {
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +090086 final String name = serviceClass.getName();
87 Slog.i(TAG, "Starting " + name);
88 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);
Adam Lesinski182f73f2013-12-05 16:48:06 -080089
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +090090 // Create the service.
91 if (!SystemService.class.isAssignableFrom(serviceClass)) {
92 throw new RuntimeException("Failed to create " + name
93 + ": service must extend " + SystemService.class.getName());
94 }
95 final T service;
96 try {
97 Constructor<T> constructor = serviceClass.getConstructor(Context.class);
98 service = constructor.newInstance(mContext);
99 } catch (InstantiationException ex) {
100 throw new RuntimeException("Failed to create service " + name
101 + ": service could not be instantiated", ex);
102 } catch (IllegalAccessException ex) {
103 throw new RuntimeException("Failed to create service " + name
104 + ": service must have a public constructor with a Context argument", ex);
105 } catch (NoSuchMethodException ex) {
106 throw new RuntimeException("Failed to create service " + name
107 + ": service must have a public constructor with a Context argument", ex);
108 } catch (InvocationTargetException ex) {
109 throw new RuntimeException("Failed to create service " + name
110 + ": service constructor threw an exception", ex);
111 }
Adam Lesinski182f73f2013-12-05 16:48:06 -0800112
MÃ¥rten Kongstad2e0d0f32016-06-02 09:35:31 +0200113 startService(service);
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900114 return service;
115 } finally {
116 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800117 }
118 }
119
MÃ¥rten Kongstad2e0d0f32016-06-02 09:35:31 +0200120 public void startService(@NonNull final SystemService service) {
121 // Register it.
122 mServices.add(service);
123 // Start it.
Wei Wangc3a76d02017-07-14 11:39:30 -0700124 long time = SystemClock.elapsedRealtime();
MÃ¥rten Kongstad2e0d0f32016-06-02 09:35:31 +0200125 try {
126 service.onStart();
127 } catch (RuntimeException ex) {
128 throw new RuntimeException("Failed to start service " + service.getClass().getName()
129 + ": onStart threw an exception", ex);
130 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700131 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
MÃ¥rten Kongstad2e0d0f32016-06-02 09:35:31 +0200132 }
133
Adam Lesinski182f73f2013-12-05 16:48:06 -0800134 /**
135 * Starts the specified boot phase for all system services that have been started up to
136 * this point.
137 *
138 * @param phase The boot phase to start.
139 */
140 public void startBootPhase(final int phase) {
141 if (phase <= mCurrentPhase) {
142 throw new IllegalArgumentException("Next phase must be larger than previous");
143 }
144 mCurrentPhase = phase;
145
146 Slog.i(TAG, "Starting phase " + mCurrentPhase);
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900147 try {
148 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "OnBootPhase " + phase);
149 final int serviceLen = mServices.size();
150 for (int i = 0; i < serviceLen; i++) {
151 final SystemService service = mServices.get(i);
Wei Wangc3a76d02017-07-14 11:39:30 -0700152 long time = SystemClock.elapsedRealtime();
Philip Cuadra4345c0d2016-08-17 18:02:24 -0700153 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, service.getClass().getName());
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900154 try {
155 service.onBootPhase(mCurrentPhase);
156 } catch (Exception ex) {
157 throw new RuntimeException("Failed to boot service "
158 + service.getClass().getName()
159 + ": onBootPhase threw an exception during phase "
160 + mCurrentPhase, ex);
161 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700162 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onBootPhase");
Philip Cuadra4345c0d2016-08-17 18:02:24 -0700163 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800164 }
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900165 } finally {
166 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800167 }
168 }
169
Keun-young Park4136d2d2017-05-08 14:51:59 -0700170 /**
171 * @return true if system has completed the boot; false otherwise.
172 */
173 public boolean isBootCompleted() {
174 return mCurrentPhase >= SystemService.PHASE_BOOT_COMPLETED;
175 }
176
Dianne Hackborn91097de2014-04-04 18:02:06 -0700177 public void startUser(final int userHandle) {
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700178 Slog.i(TAG, "Calling onStartUser u" + userHandle);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700179 final int serviceLen = mServices.size();
180 for (int i = 0; i < serviceLen; i++) {
181 final SystemService service = mServices.get(i);
Philip Cuadraca3329c2016-06-24 12:02:06 -0700182 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onStartUser "
183 + service.getClass().getName());
Wei Wangc3a76d02017-07-14 11:39:30 -0700184 long time = SystemClock.elapsedRealtime();
Dianne Hackborn91097de2014-04-04 18:02:06 -0700185 try {
186 service.onStartUser(userHandle);
187 } catch (Exception ex) {
188 Slog.wtf(TAG, "Failure reporting start of user " + userHandle
189 + " to service " + service.getClass().getName(), ex);
190 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700191 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStartUser ");
Philip Cuadraca3329c2016-06-24 12:02:06 -0700192 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700193 }
194 }
195
Jeff Sharkeybedbaa92015-12-02 16:42:25 -0700196 public void unlockUser(final int userHandle) {
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700197 Slog.i(TAG, "Calling onUnlockUser u" + userHandle);
Jeff Sharkeybedbaa92015-12-02 16:42:25 -0700198 final int serviceLen = mServices.size();
199 for (int i = 0; i < serviceLen; i++) {
200 final SystemService service = mServices.get(i);
Philip Cuadraca3329c2016-06-24 12:02:06 -0700201 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onUnlockUser "
202 + service.getClass().getName());
Wei Wangc3a76d02017-07-14 11:39:30 -0700203 long time = SystemClock.elapsedRealtime();
Jeff Sharkeybedbaa92015-12-02 16:42:25 -0700204 try {
205 service.onUnlockUser(userHandle);
206 } catch (Exception ex) {
207 Slog.wtf(TAG, "Failure reporting unlock of user " + userHandle
208 + " to service " + service.getClass().getName(), ex);
209 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700210 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onUnlockUser ");
Philip Cuadraca3329c2016-06-24 12:02:06 -0700211 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Jeff Sharkeybedbaa92015-12-02 16:42:25 -0700212 }
213 }
214
Dianne Hackborn91097de2014-04-04 18:02:06 -0700215 public void switchUser(final int userHandle) {
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700216 Slog.i(TAG, "Calling switchUser u" + userHandle);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700217 final int serviceLen = mServices.size();
218 for (int i = 0; i < serviceLen; i++) {
219 final SystemService service = mServices.get(i);
Philip Cuadraca3329c2016-06-24 12:02:06 -0700220 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onSwitchUser "
221 + service.getClass().getName());
Wei Wangc3a76d02017-07-14 11:39:30 -0700222 long time = SystemClock.elapsedRealtime();
Dianne Hackborn91097de2014-04-04 18:02:06 -0700223 try {
224 service.onSwitchUser(userHandle);
225 } catch (Exception ex) {
226 Slog.wtf(TAG, "Failure reporting switch of user " + userHandle
227 + " to service " + service.getClass().getName(), ex);
228 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700229 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onSwitchUser");
Philip Cuadraca3329c2016-06-24 12:02:06 -0700230 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700231 }
232 }
233
234 public void stopUser(final int userHandle) {
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700235 Slog.i(TAG, "Calling onStopUser u" + userHandle);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700236 final int serviceLen = mServices.size();
237 for (int i = 0; i < serviceLen; i++) {
238 final SystemService service = mServices.get(i);
Philip Cuadraca3329c2016-06-24 12:02:06 -0700239 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onStopUser "
240 + service.getClass().getName());
Wei Wangc3a76d02017-07-14 11:39:30 -0700241 long time = SystemClock.elapsedRealtime();
Dianne Hackborn91097de2014-04-04 18:02:06 -0700242 try {
243 service.onStopUser(userHandle);
244 } catch (Exception ex) {
245 Slog.wtf(TAG, "Failure reporting stop of user " + userHandle
246 + " to service " + service.getClass().getName(), ex);
247 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700248 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStopUser");
Philip Cuadraca3329c2016-06-24 12:02:06 -0700249 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700250 }
251 }
252
253 public void cleanupUser(final int userHandle) {
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700254 Slog.i(TAG, "Calling onCleanupUser u" + userHandle);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700255 final int serviceLen = mServices.size();
256 for (int i = 0; i < serviceLen; i++) {
257 final SystemService service = mServices.get(i);
Philip Cuadraca3329c2016-06-24 12:02:06 -0700258 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onCleanupUser "
259 + service.getClass().getName());
Wei Wangc3a76d02017-07-14 11:39:30 -0700260 long time = SystemClock.elapsedRealtime();
Dianne Hackborn91097de2014-04-04 18:02:06 -0700261 try {
262 service.onCleanupUser(userHandle);
263 } catch (Exception ex) {
264 Slog.wtf(TAG, "Failure reporting cleanup of user " + userHandle
265 + " to service " + service.getClass().getName(), ex);
266 }
Wei Wangc3a76d02017-07-14 11:39:30 -0700267 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onCleanupUser");
Philip Cuadraca3329c2016-06-24 12:02:06 -0700268 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Dianne Hackborn91097de2014-04-04 18:02:06 -0700269 }
270 }
271
Amith Yamasani91588252013-11-22 08:25:26 -0800272 /** Sets the safe mode flag for services to query. */
Fyodor Kupolov1d87e402017-01-10 18:34:10 -0800273 void setSafeMode(boolean safeMode) {
Amith Yamasani91588252013-11-22 08:25:26 -0800274 mSafeMode = safeMode;
275 }
276
277 /**
278 * Returns whether we are booting into safe mode.
279 * @return safe mode flag
280 */
281 public boolean isSafeMode() {
282 return mSafeMode;
283 }
284
Adam Lesinski182f73f2013-12-05 16:48:06 -0800285 /**
Fyodor Kupolov1d87e402017-01-10 18:34:10 -0800286 * @return true if runtime was restarted, false if it's normal boot
287 */
288 public boolean isRuntimeRestarted() {
289 return mRuntimeRestarted;
290 }
291
Makoto Onukie8edbcf2018-03-02 16:49:29 -0800292 /**
293 * @return Time when SystemServer was started, in elapsed realtime.
294 */
295 public long getRuntimeStartElapsedTime() {
296 return mRuntimeStartElapsedTime;
297 }
298
299 /**
300 * @return Time when SystemServer was started, in uptime.
301 */
302 public long getRuntimeStartUptime() {
303 return mRuntimeStartUptime;
304 }
305
306 void setStartInfo(boolean runtimeRestarted,
307 long runtimeStartElapsedTime, long runtimeStartUptime) {
Fyodor Kupolov1d87e402017-01-10 18:34:10 -0800308 mRuntimeRestarted = runtimeRestarted;
Makoto Onukie8edbcf2018-03-02 16:49:29 -0800309 mRuntimeStartElapsedTime = runtimeStartElapsedTime;
310 mRuntimeStartUptime = runtimeStartUptime;
Fyodor Kupolov1d87e402017-01-10 18:34:10 -0800311 }
312
Fyodor Kupolov701a85f2017-04-25 12:52:08 -0700313 private void warnIfTooLong(long duration, SystemService service, String operation) {
314 if (duration > SERVICE_CALL_WARN_TIME_MS) {
315 Slog.w(TAG, "Service " + service.getClass().getName() + " took " + duration + " ms in "
316 + operation);
317 }
318 }
Fyodor Kupolov1d87e402017-01-10 18:34:10 -0800319
320 /**
Adam Lesinski182f73f2013-12-05 16:48:06 -0800321 * Outputs the state of this manager to the System log.
322 */
323 public void dump() {
324 StringBuilder builder = new StringBuilder();
325 builder.append("Current phase: ").append(mCurrentPhase).append("\n");
326 builder.append("Services:\n");
327 final int startedLen = mServices.size();
328 for (int i = 0; i < startedLen; i++) {
329 final SystemService service = mServices.get(i);
330 builder.append("\t")
331 .append(service.getClass().getSimpleName())
332 .append("\n");
333 }
334
335 Slog.e(TAG, builder.toString());
336 }
Adam Lesinski182f73f2013-12-05 16:48:06 -0800337}