blob: 648975a9b7caba72620ae6c8b2e4d6700b04d312 [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
19import android.content.Context;
20import android.util.Log;
21import android.util.Slog;
22
23import java.util.ArrayList;
24
25/**
26 * Manages creating, starting, and other lifecycle events of system services.
27 */
28public class SystemServiceManager {
29 private static final String TAG = "SystemServiceManager";
30
31 private final Context mContext;
32
33 // Services that should receive lifecycle events.
34 private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
35
36 private int mCurrentPhase = -1;
37
38 public SystemServiceManager(Context context) {
39 mContext = context;
40 }
41
42 /**
43 * Creates and starts a system service. The class must be a subclass of
44 * {@link com.android.server.SystemService}.
45 *
46 * @param serviceClass A Java class that implements the SystemService interface.
47 * @throws RuntimeException if the service fails to start.
48 */
49 public void startService(Class<?> serviceClass) {
50 final SystemService serviceInstance = createInstance(serviceClass);
51 try {
52 Slog.i(TAG, "Creating " + serviceClass.getSimpleName());
53 serviceInstance.init(mContext, this);
54 } catch (Throwable e) {
55 throw new RuntimeException("Failed to create service " + serviceClass.getName(), e);
56 }
57
58 mServices.add(serviceInstance);
59
60 try {
61 Slog.i(TAG, "Starting " + serviceClass.getSimpleName());
62 serviceInstance.onStart();
63 } catch (Throwable e) {
64 throw new RuntimeException("Failed to start service " + serviceClass.getName(), e);
65 }
66 }
67
68 /**
69 * Starts the specified boot phase for all system services that have been started up to
70 * this point.
71 *
72 * @param phase The boot phase to start.
73 */
74 public void startBootPhase(final int phase) {
75 if (phase <= mCurrentPhase) {
76 throw new IllegalArgumentException("Next phase must be larger than previous");
77 }
78 mCurrentPhase = phase;
79
80 Slog.i(TAG, "Starting phase " + mCurrentPhase);
81
82 final int serviceLen = mServices.size();
83 for (int i = 0; i < serviceLen; i++) {
84 final SystemService service = mServices.get(i);
85 try {
86 service.onBootPhase(mCurrentPhase);
87 } catch (Throwable e) {
88 reportWtf("Service " + service.getClass().getName() +
89 " threw an Exception processing boot phase " + mCurrentPhase, e);
90 }
91 }
92 }
93
94 /**
95 * Outputs the state of this manager to the System log.
96 */
97 public void dump() {
98 StringBuilder builder = new StringBuilder();
99 builder.append("Current phase: ").append(mCurrentPhase).append("\n");
100 builder.append("Services:\n");
101 final int startedLen = mServices.size();
102 for (int i = 0; i < startedLen; i++) {
103 final SystemService service = mServices.get(i);
104 builder.append("\t")
105 .append(service.getClass().getSimpleName())
106 .append("\n");
107 }
108
109 Slog.e(TAG, builder.toString());
110 }
111
112 private SystemService createInstance(Class<?> clazz) {
113 // Make sure it's a type we expect
114 if (!SystemService.class.isAssignableFrom(clazz)) {
115 reportWtf("Class " + clazz.getName() + " does not extend " +
116 SystemService.class.getName());
117 }
118
119 try {
120 return (SystemService) clazz.newInstance();
121 } catch (InstantiationException e) {
122 reportWtf("Class " + clazz.getName() + " is abstract", e);
123 } catch (IllegalAccessException e) {
124 reportWtf("Class " + clazz.getName() +
125 " must have a public no-arg constructor", e);
126 }
127 return null;
128 }
129
130 private static void reportWtf(String message) {
131 reportWtf(message, null);
132 }
133
134 private static void reportWtf(String message, Throwable e) {
135 Slog.i(TAG, "******************************");
136 Log.wtf(TAG, message, e);
137
138 // Make sure we die
139 throw new RuntimeException(message, e);
140 }
141}