Android中system server程序啟動流程原始碼解析 系統服務啟動
system server
前言
在平時的開發中或多或少會了解過ActivityManagerService,WindowManagerService,PowerManagerService等服務,那你有想過這些服務如何產生的嗎,它們執行在哪呢?我們是如何獲取到這些服務的呢?要想了解這些就要看System Server程序了
本篇部落格原始碼基於API24
System Server
System Server程序和Zygote程序可以說是Android世界中的兩大最重要的程序,離開其中之一基本上系統就玩完了(這裡還有一個Media Server程序,是由init程序fork而來,負責啟動和管理整個C++ framework,包含AudioFlinger,Camera Service等服務);System Server負責啟動和管理整個framework,基本上在Framework中的大多數服務都是在system server程序中以一個執行緒的方式存在的;System Server程序的程序名是system_server,大家可以通過adb shell ps檢視當前手機存在的程序資訊,可以看到這幾條
USER PID PPID VSIZE RSS WCHAN PC NAME root 1 0 9048 1012 ffffffff 00000000 S /init root 349 1 2118552 17464 ffffffff 00000000 S zygote64 root 350 1 1526172 16800 ffffffff 00000000 S zygote system 793 349 2792784 109876 ffffffff 00000000 S system_server
fork SystemServer
System Server程序是由Zygote程序fork出來的,至於如何被Zygote程序fork出來的以及Zygote程序的資訊可以參考下面部落格
Android系統啟動流程概述 init程序啟動 zygote程序啟動 system server程序啟動
zygote程序fork成功後,會反射呼叫SystemServer.main()方法,至此進入system server程序的工作空間
SystemServer.main()
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
try {
//若當前時間小於1970年1月1日,那就設定為1970年1月1日
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
//設定系統的語言環境
if (!SystemProperties.get("persist.sys.language").isEmpty()) {
final String languageTag = Locale.getDefault().toLanguageTag();
SystemProperties.set("persist.sys.locale", languageTag);
SystemProperties.set("persist.sys.language", "");
SystemProperties.set("persist.sys.country", "");
SystemProperties.set("persist.sys.localevar", "");
}
//變更虛擬機器的庫檔案,對於Android 6.0預設採用的是libart.so
SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
//清除vm記憶體增長上限,由於啟動過程需要較多的虛擬機器記憶體空間
VMRuntime.getRuntime().clearGrowthLimit();
//設定記憶體的可能有效使用率為0.8
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
// 針對部分裝置依賴於執行時就產生指紋資訊,因此需要在開機完成前已經定義
Build.ensureFingerprintProperty();
//訪問環境變數前,需要明確地指定使用者
Environment.setUserRequired(true);
// Within the system server, any incoming Bundles should be defused
// to avoid throwing BadParcelableException.
BaseBundle.setShouldDefuse(true);
//確保當前系統程序的binder呼叫,總是執行在前臺優先順序(foreground priority)
BinderInternal.disableBackgroundScheduling(true);
// 增加system_server中的binder執行緒數
BinderInternal.setMaxThreads(sMaxBinderThreads);
// 建立主執行緒looper 在當前執行緒執行
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper();
//初始化android_servers庫
System.loadLibrary("android_servers");
//檢測上次關機過程是否失敗
performPendingShutdown();
//初始化系統上下文
//初始化系統上下文物件mSystemContext,並設定預設的主題,mSystemContext實際上是一個ContextImpl物件。
//呼叫ActivityThread.systemMain()的時候,會呼叫ActivityThread.attach(true),而在attach()裡面,則建立了Application物件,並呼叫了Application.onCreate()。
createSystemContext();
//建立系統服務管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
//啟動各種系統服務
try {
//引導服務
startBootstrapServices();
//核心服務
startCoreServices();
//其它服務
startOtherServices();
} catch (Throwable ex) {
throw ex;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
//開啟訊息迴圈
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
這個main方法做了很多事情:設定系統時間,設定語言環境,設定虛擬機器記憶體,設定binder執行緒數,初始化Loop,載入執行庫等
除了這些操作外,接下來繼續往下看main方法後半段
SystemServer.createSystemContext
private Context mSystemContext;
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
}
沒想到啊,原來System Server中也有Context物件,這個方法就是初始化system context;可能有人不太理解Context到底是個什麼玩意
Context英文原意是上下文的意思,在平時開發中涉及到的四大元件及資源操作基本上都離不開Context物件;你可以想象它是一團神祕的漂浮的物質,在一個生活場景中,不管你在哪,在幹什麼,你都可以通過這團神祕物質獲取到一些屬於這個場景的隱性資訊
比如你在吃一條魚這個場景,你能知道的就是這條魚多大,多好吃,但是假如你有Context這個上下文資訊,你就能獲取到更多資訊,比如魚的重量,魚的種類,魚的年齡等,用程式碼表示就是Context.getFishType(),你就知道這條魚的種類了
這就是上下文的意思,某一個場景下一些隱藏的資訊
其實Context家族很複雜,Context本身是一個抽象類,而ContextImpl,ContextWrapper,Activity,Service,Application等都是它的直接或間接子類
接下來我們看下方法後續呼叫
public static ActivityThread systemMain() {
// 低記憶體裝置上的系統程序無法使用硬體加速繪圖,因為這會給程序增加太多開銷
if (!ActivityManager.isHighEndGfx()) {
ThreadedRenderer.disable(true);
} else {
ThreadedRenderer.enableForegroundTrimming();
}
ActivityThread thread = new ActivityThread();
thread.attach(true);
return thread;
}
public ContextImpl getSystemContext() {
synchronized (this) {
if (mSystemContext == null) {
mSystemContext = ContextImpl.createSystemContext(this);
}
return mSystemContext;
}
}
其中 thread.attach(true)這句話經過一系列呼叫後會建立很多物件,比如ActivityThread,Instrumentation, ContextImpl,LoadedApk,Application等
具體執行過程可檢視博主部落格
從Activity載入原始碼深入理解ActivityThrad的工作邏輯
執行完後System Server後續就能用到這些物件了
SystemServiceManager
繼續往下看
//建立系統服務管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
這裡是例項化SystemServiceManager物件,這個類主要是用來對System server中的一些系統服務的建立,啟動和其它的一些生命週期事件進行管理
SystemServiceManager維護了一個集合
private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
SystemServer啟動的很多服務都儲存在這個集合裡
啟動服務三連
//啟動各種系統服務
try {
//引導服務
startBootstrapServices();
//核心服務
startCoreServices();
//其它服務
startOtherServices();
} catch (Throwable ex) {
throw ex;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
main方法最後會執行這三個重要的啟動服務方法,先看第一個
SystemServer.startBootstrapServices
這個方法將會啟動一些引導服務
private PowerManagerService mPowerManagerService;
private ActivityManagerService mActivityManagerService;
private WebViewUpdateService mWebViewUpdateService;
private DisplayManagerService mDisplayManagerService;
private PackageManagerService mPackageManagerService;
private PackageManager mPackageManager;
/**
* 啟動一些系統執行必須的關鍵服務,這些服務具有複雜的相互依賴性,所以就在這裡全部初始化
*/
private void startBootstrapServices() {
// 阻塞等待installd完成啟動,與其建立socket通道
// 以便它有機會使用適當的許可權建立關鍵目錄,例如/ data / user
// 在初始化其他服務之前,我們需要完成此操作
Installer installer = mSystemServiceManager.startService(Installer.class);
// 啟動ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
// PowerManagerService需要儘早啟動,因為其他服務需要它。 本機守護程式可能正在監視它是否已註冊
// 因為它要立即準備好處理傳入進來的binder呼叫(包括能夠驗證這些呼叫的許可權)
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// 現在電源管理器已經啟動,讓ActivityManagerService初始化電源管理功能
mActivityManagerService.initPowerManagement();
// 啟動服務LightsService 管理LED並顯示背光
mSystemServiceManager.startService(LightsService.class);
// 啟動服務DisplayManagerService
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
// 在初始化package manager之前,需要預設的顯示
mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
// 如果我們正在加密裝置,則只執行“核心”應用程式.
String cryptState = SystemProperties.get("vold.decrypt");
if (ENCRYPTING_STATE.equals(cryptState)) {
//加密程式正在執行
mOnlyCore = true;
} else if (ENCRYPTED_STATE.equals(cryptState)) {
//已經被加密了
mOnlyCore = true;
}
// 啟動PackageManagerService
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
// 沒有加密的話進行odex優化
if (!mOnlyCore) {
boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",false);
if (!disableOtaDexopt) {
traceBeginAndSlog("StartOtaDexOptService");
try {
OtaDexoptService.main(mSystemContext, mPackageManagerService);
} catch (Throwable e) {
reportWtf("starting OtaDexOptService", e);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
}
//啟動服務UserManagerService,新建目錄/data/user/
mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
//初始化屬性快取用來快取包資源.
AttributeCache.init(mSystemContext);
// 為系統程序設定Application例項並開始使用
mActivityManagerService.setSystemProcess();
// 啟動感測器服務
// 感測器服務需要訪問包管理器服務,app ops服務和許可權服務,因此我們在它們之後啟動它
startSensorService();
}
//這是native方法
private static native void startSensorService();
可以看到這裡啟動了很多系統關鍵性服務,而且都是通過SystemServiceManager例項去操作
SystemServiceManager.startService
/**
* 建立並啟動 system service. 且這些服務必須是SystemService子類
*
* @param serviceClass A Java class that implements the SystemService interface.
* @return The service instance, never null.
* @throws RuntimeException if the service fails to start.
*/
@SuppressWarnings("unchecked")
public <T extends SystemService> T startService(Class<T> serviceClass) {
try {
final String name = serviceClass.getName();
// 建立 service.
if (!SystemService.class.isAssignableFrom(serviceClass)) {
throw new RuntimeException("Failed to create " + name
+ ": service must extend " + SystemService.class.getName());
}
final T service;
try {
Constructor<T> constructor = serviceClass.getConstructor(Context.class);
service = constructor.newInstance(mContext);
} catch (InstantiationException ex) {
throw new RuntimeException("Failed to create service " + name
+ ": service could not be instantiated", ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException("Failed to create service " + name
+ ": service must have a public constructor with a Context argument", ex);
} catch (NoSuchMethodException ex) {
throw new RuntimeException("Failed to create service " + name
+ ": service must have a public constructor with a Context argument", ex);
} catch (InvocationTargetException ex) {
throw new RuntimeException("Failed to create service " + name
+ ": service constructor threw an exception", ex);
}
// 新增到list集合
mServices.add(service);
try {
//啟動
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + name
+ ": onStart threw an exception", ex);
}
return service;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
這裡都是通過反射構造出這些服務的例項,然後呼叫它們的onStart方法啟動,以Installer服務為例看一下
Installer.onStart
public final class Installer extends SystemService {
private final InstallerConnection mInstaller;
public Installer(Context context) {
super(context);
mInstaller = new InstallerConnection();
}
@Override
public void onStart() {
//等待installd準備完畢
mInstaller.waitForConnection();
}
}
public class InstallerConnection {
public void waitForConnection() {
for (;;) {
try {
execute("ping");
return;
} catch (InstallerException ignored) {
}
//還沒準備好,休息一秒繼續嘗試
SystemClock.sleep(1000);
}
}
}
其實就是不斷的通過ping命令連線Zygote程序(SystemServer和Zygote程序通過socket方式通訊,其他程序通過Binder方式通訊),成功連線之後才會開始啟動其他服務
SystemServer.startCoreServices
接下來看第二個啟動方法
/**
* 啟動一些與引導服務沒有複雜依賴的基本服務
*/
private void startCoreServices() {
// 啟動BatteryService 跟蹤電池電量
mSystemServiceManager.startService(BatteryService.class);
// 啟動UsageStatsService 跟蹤應用程式使用統計資訊
mSystemServiceManager.startService(UsageStatsService.class);
mActivityManagerService.setUsageStatsManager(
LocalServices.getService(UsageStatsManagerInternal.class));
// 啟動WebViewUpdateService 跟蹤可更新的WebView是否處於就緒狀態並監視更新安裝。
mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
}
SystemServer.startOtherServices
這個方法著實有點長,將近一千行,不過做的事情不復雜,主要是啟動服務;這裡就不一一列舉了
private void startOtherServices() {
final Context context = mSystemContext;
//這裡會啟動一堆雜七雜八的服務
VibratorService vibrator = null;
IMountService mountService = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
NetworkScoreService networkScore = null;
NsdService serviceDiscovery= null;
WindowManagerService wm = null;
SerialService serial = null;
NetworkTimeUpdateService networkTimeUpdater = null;
CommonTimeManagementService commonTimeMgmtService = null;
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
ConsumerIrService consumerIr = null;
MmsServiceBroker mmsService = null;
HardwarePropertiesManagerService hardwarePropertiesService = null;
//讀取配置資訊
boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false);
boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false);
boolean disableLocation = SystemProperties.getBoolean("config.disable_location", false);
boolean disableSystemUI = SystemProperties.getBoolean("config.disable_systemui", false);
boolean disableNonCoreServices = SystemProperties.getBoolean("config.disable_noncore", false);
boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false);
boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime", false);
boolean disableRtt = SystemProperties.getBoolean("config.disable_rtt", false);
boolean disableMediaProjection = SystemProperties.getBoolean("config.disable_mediaproj",
false);
boolean disableSerial = SystemProperties.getBoolean("config.disable_serial", false);
boolean disableSearchManager = SystemProperties.getBoolean("config.disable_searchmanager",
false);
boolean disableTrustManager = SystemProperties.getBoolean("config.disable_trustmanager",
false);
boolean disableTextServices = SystemProperties.getBoolean("config.disable_textservices", false);
boolean disableSamplingProfiler = SystemProperties.getBoolean("config.disable_samplingprof",
false);
boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");
try {
SystemConfig.getInstance();
ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
mSystemServiceManager.startService(TelecomLoaderService.class);
telephonyRegistry = new TelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);
......
} catch (RuntimeException e) {
Slog.e("System", "************ Failure starting core service", e);
}
StatusBarManagerService statusBar = null;
INotificationManager notification = null;
LocationManagerService location = null;
CountryDetectorService countryDetector = null;
ILockSettings lockSettings = null;
AssetAtlasService atlas = null;
MediaRouterService mediaRouter = null;
......
ActivityManagerNative.getDefault().showBootMessage(...); //顯示啟動介面
try {
vibrator.systemReady();
} catch (Throwable e) {
reportWtf("making Vibrator Service ready", e);
}
mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
try {
wm.systemReady();
} catch (Throwable e) {
reportWtf("making Window Manager Service ready", e);
}
......
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
......
try {
startSystemUi(context);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
mSystemServiceManager.startBootPhase(
SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
......
}
});
}
這裡會啟動大量的服務,到這裡系統服務基本上啟動完成,system_server程序隨後進入Looper.loop()狀態,隨時等待訊息到來
總結
- SystemServer程序啟動後會設定系統時間,設定語言環境,設定虛擬機器記憶體,設定binder執行緒數,初始化Loop,載入執行庫等
- 接下來建立Context物件,SystemServiceManager物件
- 最後啟動三類服務:引導服務,核心服務,其它服務;其中引導服務有7個,核心服務有三個,其他服務有70+
- 進行訊息迴圈,隨時處理接收到的事件