編輯:關於Android編程
Linux內核啟動之後就到Android Init進程,進而啟動Android相關的服務和應用。
啟動的過程如下圖所示:
下面將從Android4.0源碼中,和網絡達人對此的總結中,對此過程加以學習了解和總結,
以下學習過程中代碼片段中均有省略不完整,請參照源碼。
一 Init進程的啟動
init進程,它是一個由內核啟動的用戶級進程。內核自行啟動(已經被載入內存,開始運行,
並已初始化所有的設備驅動程序和數據結構等)之後,就通過啟動一個用戶級程序init的方式,完成引導進程。init始終是第一個進程。
啟動過程就是代碼init.c中main函數執行過程:system\core\init\init.c
在函數中執行了:文件夾建立,掛載,rc文件解析,屬性設置,啟動服務,執行動作,socket監聽……
下面看兩個重要的過程:rc文件解析和服務啟動。
1 rc文件解析
.rc文件是Android使用的初始化腳本文件 (System/Core/Init/readme.txt中有描述:
four broad classes of statements which are Actions, Commands, Services, and Options.)
其中Command 就是系統支持的一系列命令,如:export,hostname,mkdir,mount,等等,其中一部分是 linux 命令,
還有一些是 android 添加的,如:class_start: 啟動服務,class_stop:關閉服務,等等。
其中Options是針對 Service 的選項的。
系統初始化要觸發的動作和要啟動的服務及其各自屬性都在rc腳本文件中定義。 具體看一下啟動腳本:\system\core\rootdir\init.rc
在解析rc腳本文件時,將相應的類型放入各自的List中:
\system\core\init\Init_parser.c :init_parse_config_file( )存入到
action_queue、 action_list、 service_list中,解析過程可以看一下parse_config函數,類似狀態機形式挺有意思。
這其中包含了服務:adbd、servicemanager、vold、ril-daemon、debuggerd、surfaceflinger、zygote、media……
2 服務啟動
文件解析完成之後將service放入到service_list中。
文件解析完成之後將service放入到service_list中。
\system\core\init\builtins.c
Service的啟動是在do_class_start函數中完成:
int do_class_start(int nargs, char **args) { service_for_each_class(args[1], service_start_if_not_disabled); return 0; }
遍歷所有名稱為classname,狀態不為SVC_DISABLED的Service啟動
void service_for_each_class(const char *classname,
void (*func)(struct service *svc)) { …… } static void service_start_if_not_disabled(struct service *svc) { if (!(svc->flags & SVC_DISABLED)) { service_start(svc, NULL); } }do_class_start對應的命令:
KEYWORD(class_start, COMMAND, 1, do_class_start)
init.rc文件中搜索class_start:class_start main 、class_start core、……
main、core即為do_class_start參數classname
init.rc文件中Service class名稱都是main:
service drm /system/bin/drmserver
class main
service surfaceflinger /system/bin/surfaceflinger
class main
於是就能夠通過main名稱遍歷到所有的Service,將其啟動。
do_class_start調用:
init.rc中
on boot //action
class_start core //執行command 對應 do_class_start
class_start main
Init進程main函數中:system/core/init/init.c中:
int main(){
//掛在文件
//解析配置文件:init.rc……
//初始化化action queue
…… for(;;){ execute_one_command(); restart_processes(); for (i = 0; i 循環調用service_start,將狀態SVC_RESTARTING啟動, 將啟動後的service狀態設置為SVC_RUNNING。
pid=fork();
execve();
在消息循環中:Init進程執行了Android的Command,啟動了Android的NativeService,監聽Service的變化需求,Signal處理。
Init進程是作為屬性服務(Property service),維護這些NativeService。
二 ServiceManager啟動
在.rc腳本文件中zygote的描述:
service servicemanager /system/bin/servicemanager class core user system group system critical onrestart restart zygote onrestart restart media onrestart restart surfaceflinger onrestart restart drm
ServiceManager用來管理系統中所有的binder service,不管是本地的c++實現的還是java語言實現的都需要
這個進程來統一管理,最主要的管理就是,注冊添加服務,獲取服務。所有的Service使用前都必須先在servicemanager中進行注冊。
do_find_service( )
do_add_service( )
svcmgr_handler( )
代碼位置:frameworks\base\cmds\servicemanager\Service_manager.c
三 Zygote進程的啟動
Zygote這個進程是非常重要的一個進程,Zygote進程的建立是真正的Android運行空間,初始化建立的Service都是Navtive service.
(1) 在.rc腳本文件中zygote的描述:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 666 onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd 參數:--zygote --start-system-server代碼位置:frameworks/base/cmds/app_process/app_main.cpp
上面的參數在這裡就會用上,決定是否要啟動和啟動那些進程。
int main( ){AppRuntime runtime; if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", startSystemServer ? "start-system-server" : ""); } } class AppRuntime : public AndroidRuntime{};
(2) 接著到了AndroidRuntime類中:
frameworks\base\core\jni\AndroidRuntime.cpp
void start(const char* className, const char* options){ // start the virtual machine Java在虛擬機中運行的 JNIEnv* env; if (startVm(&mJavaVM, &env) != 0) { return; } //向剛剛新建的虛擬機注冊JNI本地接口 if (startReg(env) GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V"); // jni調用 java方法,調用到ZygoteInit類的main函數 jclass startClass = env->FindClass(className); env->CallStaticVoidMethod(startClass, startMeth, strArray); }
到了ZygoteInit.java中的靜態main函數中,從C++ ——》JAVA
(3)ZygoteInit
真正Zygote進程:
frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
public static void main(String argv[]) { //Registers a server socket for zygote command connections registerZygoteSocket(); //Loads and initializes commonly used classes and //used resources that can be shared across processes preload(); // Do an initial gc to clean up after startup gc(); if (argv[1].equals("start-system-server")) { startSystemServer(); } /** * Runs the zygote process's select loop. Accepts new connections as * they happen, and reads commands from connections one spawn-request's * worth at a time. */ runSelectLoopMode(); //loop中 /** * Close and clean up zygote sockets. Called on shutdown and on the * child's exit path. */ closeServerSocket(); }Zygote就建立好了,利用Socket通訊,接收請求,Fork應用程序進程,進入Zygote進程服務框架中。
四 SystemServer啟動
(1)在Zygote進程進入循環之前,調用了startSystemServer( );
private static boolean startSystemServer(){ /* Request to fork the system server process 孵化新的進程 */ ZygoteConnection.Arguments parsedArgs = null; pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); /* For child process 對新的子進程設置 */ if (pid == 0) { handleSystemServerProcess(parsedArgs); } } void handleSystemServerProcess(parsedArgs){ closeServerSocket(); //"system_server" Process.setArgV0(parsedArgs.niceName); //Pass the remaining arguments to SystemServer. RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs); /* should never reach here */ }
(2)RuntimeInit中:
frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
//The main function called when started through the zygote process. void zygoteInit(int targetSdkVersion, String[] argv){ applicationInit(targetSdkVersion, argv); } void applicationInit(int targetSdkVersion, String[] argv){ // Remaining arguments are passed to the start class's static main invokeStaticMain(args.startClass, args.startArgs); } void invokeStaticMain(String className, String[] argv){ Class> cl; cl = Class.forName(className); //獲取SystemServer的main方法,拋出MethodAndArgsCaller異常 Method m; m = cl.getMethod("main", new Class[] { String[].class }); int modifiers = m.getModifiers(); throw new ZygoteInit.MethodAndArgsCaller(m, argv); }
(3)從startSystemServer開始執行並沒有去調用SystemServer的任何方法,
只是通過反射獲取了main方法,付給了MethodAndArgsCaller,並拋出了MethodAndArgsCaller異常。
此異常是在哪裡處理的呢?
回到startSystemServer( )函數的調用處:
在ZygoteInit的main函數中:
public static void main(String argv[]) { try { …… if (argv[1].equals("start-system-server")) { startSystemServer(); //這裡如果拋出異常,跳過下面流程 } runSelectLoopMode(); //loop中 …… } catch (MethodAndArgsCaller caller) { caller.run(); //處理的異常 } }
如果startSystemServer拋出了異常,跳過執行ZygoteInit進程的循環,這是怎麼回事呢?
在startSystemServer中異常是由handleSystemServerProcess拋出,而
pid = Zygote.forkSystemServer( )
/* For child process 僅對新的子進程設置 */
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
// Zygote.forkSystemServer根據參數fork 出一個子進程,若成功調用,則返回兩次:
一次返回的是 zygote 進程的 pid ,值大於0;一次返回的是子進程 pid,值等於0否則,出錯返回-1;
caller.run();
MethodAndArgsCaller run函數:調用前面所提到的
//SystemServer main方法
m = cl.getMethod("main", new Class[] { String[].class });
啟動了進程SystemServer。
(4)SystemServer的執行 init1( )
//frameworks\base\services\java\com\android\server\SystemServer.java
public static void main(String[] args) {
System.loadLibrary("android_servers"); /* * This method is called from Zygote to initialize the system. * This will cause the native services (SurfaceFlinger, AudioFlinger, etc..) * to be started. After that it will call back * up into init2() to start the Android services. */ init1(args); //native 完了回調init2( ) } //init1: frameworks/base/services/jni/com_android_server_SystemServer.cpp:: android_server_SystemServer_init1( ) 中調用:system_init extern "C" status_t system_init() { sp proc(ProcessState::self()); sp sm = defaultServiceManager(); //啟動SurfaceFlinger 和傳感器 property_get("system_init.startsurfaceflinger", propBuf, "1"); SurfaceFlinger::instantiate(); property_get("system_init.startsensorservice", propBuf, "1"); SensorService::instantiate(); // And now start the Android runtime. We have to do this bit // of nastiness because the Android runtime initialization requires // some of the core system services to already be started. // All other servers should just start the Android runtime at // the beginning of their processes's main(), before calling // the init function. AndroidRuntime* runtime = AndroidRuntime::getRuntime(); //回調 com.android.server.SystemServer init2 方法 JNIEnv* env = runtime->getJNIEnv(); jclass clazz = env->FindClass("com/android/server/SystemServer"); jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V"); env->CallStaticVoidMethod(clazz, methodId); //啟動線程池 做為binder 服務 ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); return NO_ERROR; }
ProcessState:
每個進程在使用binder 機制通信時,均需要維護一個ProcessState 實例來描述當前進程在binder 通信時的binder 狀態。
ProcessState 有如下2 個主要功能:
1. 創建一個thread, 該線程負責與內核中的binder 模塊進行通信,稱該線程為Pool thread ;
2. 為指定的handle 創建一個BpBinder 對象,並管理該進程中所有的BpBinder 對象。
Pool thread:
在Binder IPC 中,所有進程均會啟動一個thread 來負責與BD 來直接通信,也就是不停的讀寫BD ,
這個線程的實現主體是一個IPCThreadState 對象,下面會介紹這個類型。
下面是Pool thread 的啟動方式:
ProcessState::self()->startThreadPool();
IPCThreadState :
IPCThreadState 也是以單例模式設計的。由於每個進程只維護了一個ProcessState 實例,同時ProcessState 只啟動一個Pool thread ,
也就是說每一個進程只會啟動一個Pool thread ,因此每個進程則只需要一個IPCThreadState 即可。
Pool thread 的實際內容則為:
IPCThreadState::self()->joinThreadPool();
(5)SystemServer的執行 init2( )
public static final void init2() { //建立線程來處理 Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); } //看看線程ServerThread裡面都做了什麼事情? public void run() { addBootEvent(new String("Android:SysServerInit_START")); Looper.prepare(); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); //初始化服務,創建各種服務實例,如:電源、網絡、Wifi、藍牙,USB等, //初始化完成以後加入到 ServiceManager中, //事我們用 Context.getSystemService (String name) 才獲取到相應的服務 PowerManagerService power = null; NetworkManagementService networkManagement = null; WifiP2pService wifiP2p = null; WindowManagerService wm = null; BluetoothService bluetooth = null; UsbService usb = null; NotificationManagerService notification = null; StatusBarManagerService statusBar = null; …… power = new PowerManagerService(); ServiceManager.addService(Context.POWER_SERVICE, power); …… // ActivityManagerService作為ApplicationFramework最重要的服務 ActivityManagerService.setSystemProcess(); ActivityManagerService.installSystemProviders(); ActivityManagerService.self().setWindowManager(wm); // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state // where third party code can really run (but before it has actually // started launching the initial applications), for us to complete our // initialization. //系統服務初始化准備就緒,通知各個模塊 ActivityManagerService.self().systemReady(new Runnable() { public void run() { startSystemUi(contextF); batteryF.systemReady(); networkManagementF.systemReady(); usbF.systemReady(); …… // It is now okay to let the various system services start their // third party code... appWidgetF.systemReady(safeMode); wallpaperF.systemReady(); } }); // //BOOTPROF addBootEvent(new String("Android:SysServerInit_END")); Looper.loop(); }
到這裡系統ApplicationFramework層的XxxServiceManager准備就緒,可以開始跑上層應用了,我們的第一個上層應用HomeLauncher。
HomeActivity又是如何啟動的呢?
Activity的啟動必然和ActivityManagerService有關,我們需要去看看
ActivityManagerService.systemReady( )中都干了些什麼。
五 Home界面啟動
public void systemReady(final Runnable goingCallback) { …… //ready callback if (goingCallback != null) goingCallback.run(); synchronized (this) { // Start up initial activity. // ActivityStack mMainStack; mMainStack.resumeTopActivityLocked(null); } …… } final boolean resumeTopActivityLocked(ActivityRecord prev) { // Find the first activity that is not finishing. ActivityRecord next = topRunningActivityLocked(null); if (next == null) { // There are no more activities! Let's just start up the // Launcher... if (mMainStack) { //ActivityManagerService mService; return mService.startHomeActivityLocked(); } } …… }
然後就啟動了Home界面,完成了整個Android啟動流程。
整個過程如下:(摘自網絡)
微信轉賬輸入框規則(可能不全)1、小數點後兩位2、起始輸入小數點,顯示0.3、刪除到第一個位置是小數點的時候,第一個位置為0 ,避免出現小數點在第一個位置的情況修改這個朋
ViewAndroid所有的控件都是View或者View的子類,它其實表示的就是屏幕上的一塊矩形區域,用一個Rect來表示,left,top表示View相對於它的pare
在Android實現沒有標題欄的方法有兩種:在代碼中添加requestWindowFeature(Window.FEATURE_NO_TITLE); 在清單文件Andro
1、概述開發Android的同學都知道sdk已經為我們提供了一個SQLiteOpenHelper類來創建和管理SQLite數據庫,通過寫一個子類去繼承它,就可以方便的創建