SystemServiceManager.java revision 9158825f9c41869689d6b1786d7c7aa8bdd524ce
1/* 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 private boolean mSafeMode; 33 34 // Services that should receive lifecycle events. 35 private final ArrayList<SystemService> mServices = new ArrayList<SystemService>(); 36 37 private int mCurrentPhase = -1; 38 39 public SystemServiceManager(Context context) { 40 mContext = context; 41 } 42 43 public void startService(String className) { 44 try { 45 startService(Class.forName(className)); 46 } catch (ClassNotFoundException cnfe) { 47 Slog.i(TAG, className + " not available, ignoring."); 48 } 49 } 50 51 /** 52 * Creates and starts a system service. The class must be a subclass of 53 * {@link com.android.server.SystemService}. 54 * 55 * @param serviceClass A Java class that implements the SystemService interface. 56 * @throws RuntimeException if the service fails to start. 57 */ 58 public void startService(Class<?> serviceClass) { 59 final SystemService serviceInstance = createInstance(serviceClass); 60 try { 61 Slog.i(TAG, "Creating " + serviceClass.getSimpleName()); 62 serviceInstance.init(mContext, this); 63 } catch (Throwable e) { 64 throw new RuntimeException("Failed to create service " + serviceClass.getName(), e); 65 } 66 67 mServices.add(serviceInstance); 68 69 try { 70 Slog.i(TAG, "Starting " + serviceClass.getSimpleName()); 71 serviceInstance.onStart(); 72 } catch (Throwable e) { 73 throw new RuntimeException("Failed to start service " + serviceClass.getName(), e); 74 } 75 } 76 77 /** 78 * Starts the specified boot phase for all system services that have been started up to 79 * this point. 80 * 81 * @param phase The boot phase to start. 82 */ 83 public void startBootPhase(final int phase) { 84 if (phase <= mCurrentPhase) { 85 throw new IllegalArgumentException("Next phase must be larger than previous"); 86 } 87 mCurrentPhase = phase; 88 89 Slog.i(TAG, "Starting phase " + mCurrentPhase); 90 91 final int serviceLen = mServices.size(); 92 for (int i = 0; i < serviceLen; i++) { 93 final SystemService service = mServices.get(i); 94 try { 95 service.onBootPhase(mCurrentPhase); 96 } catch (Throwable e) { 97 reportWtf("Service " + service.getClass().getName() + 98 " threw an Exception processing boot phase " + mCurrentPhase, e); 99 } 100 } 101 } 102 103 /** Sets the safe mode flag for services to query. */ 104 public void setSafeMode(boolean safeMode) { 105 mSafeMode = safeMode; 106 } 107 108 /** 109 * Returns whether we are booting into safe mode. 110 * @return safe mode flag 111 */ 112 public boolean isSafeMode() { 113 return mSafeMode; 114 } 115 116 /** 117 * Outputs the state of this manager to the System log. 118 */ 119 public void dump() { 120 StringBuilder builder = new StringBuilder(); 121 builder.append("Current phase: ").append(mCurrentPhase).append("\n"); 122 builder.append("Services:\n"); 123 final int startedLen = mServices.size(); 124 for (int i = 0; i < startedLen; i++) { 125 final SystemService service = mServices.get(i); 126 builder.append("\t") 127 .append(service.getClass().getSimpleName()) 128 .append("\n"); 129 } 130 131 Slog.e(TAG, builder.toString()); 132 } 133 134 private SystemService createInstance(Class<?> clazz) { 135 // Make sure it's a type we expect 136 if (!SystemService.class.isAssignableFrom(clazz)) { 137 reportWtf("Class " + clazz.getName() + " does not extend " + 138 SystemService.class.getName()); 139 } 140 141 try { 142 return (SystemService) clazz.newInstance(); 143 } catch (InstantiationException e) { 144 reportWtf("Class " + clazz.getName() + " is abstract", e); 145 } catch (IllegalAccessException e) { 146 reportWtf("Class " + clazz.getName() + 147 " must have a public no-arg constructor", e); 148 } 149 return null; 150 } 151 152 private static void reportWtf(String message) { 153 reportWtf(message, null); 154 } 155 156 private static void reportWtf(String message, Throwable e) { 157 Slog.i(TAG, "******************************"); 158 Log.wtf(TAG, message, e); 159 160 // Make sure we die 161 throw new RuntimeException(message, e); 162 } 163} 164