OK. As explained above, the system has started zygote from the init process --> started SystemServer --> ??? So what should we start now?
According to the previous analysis, the basic native and java World environments have been established, so there is still a HOME page display? The visualization system is about to begin.
In Zygote, there is a function:
Main @ frameworks \ base \ core \ java \ com \ android \ internal \ OS \ ZygoteInit. java
Here, the runSelectLoopMode () function is used to process customer connections and customer requests.
Private static void runSelectLoopMode (){
While (true ){
// Use select for multi-channel I/O listening
Index = selectReadable (fdArray );
// If a client is connected, accept is added to the ArrayList.
If (index = 0 ){
ZygoteConnection newPeer = acceptCommandPeer ();
Peers. add (newPeer );
Fds. add (newPeer. getFileDesciptor ());
} Else {
// Otherwise, it is handed over to the runOnce () function of ZygoteConnection.
Done = peers. get (index). runOnce ();
}
}
...
}
-->
The ZygoteConnection class is used for client connection. The specific runOnce () function is as follows:
RunOnce @ frameworks \ base \ core \ java \ com \ android \ internal \ OS \ ZygoteConnection. java
Boolean runOnce () throws ZygoteInit. MethodAndArgsCaller {
Args = readArgumentList ();
// Create a process using forkAndSpecialize based on the parameters specified by the client
Pid = Zygote. forkAndSpecialize (parsedArgs. uid,
ParsedArgs. gid,
ParsedArgs. gids,
ParsedArgs. debugFlags, rlimits );
// Process child and parent processes based on the pid Value
If (pid = 0 ){
// In child
HandleChildProc (parsedArgs, descriptors, newStderr );
// Shocould never happen
Return true;
} Else {/* pid! = 0 */
// In parent... pid of <0 means failure
Return handleParentProc (pid, descriptors, parsedArgs );
}
...
}
Summary: The client uses Zygote to request zygote to create a new process on behalf of ZygoteConnection. After the process is successfully created, the client processes the child process and the parent process separately.
After the application is installed, you also need a HOME application to display them on the desktop. The default is the Launcher2 application. Here we will introduce the Launcher2 startup process, there are six major processes to start:
The following describes how to process ActivityManagerService in SystemServer. java:
1. ActivityManagerService. main (factoryTest );
An ActivityManagerService instance is created internally through the AThread thread object, and the instance is saved to its member variable mService. Then, the ActivityManagerService instance is saved to the static member variable mSelf of the ActivityManagerService class:
ActivityManagerService m = new ActivityManagerService ();
MService = m;
MSelf = mService;
2. ActivityManagerService. setSystemProcess ();
All information of the application in the system is stored in PackageManagerService. the required application information can be extracted from here.
ApplicationInfo info =
MSelf. mContext. getPackageManager (). getApplicationInfo (
"Android", STOCK_PM_FLAGS );
MSystemThread. installSystemApplicationInfo (info );
3. In the second half of the run () function, there are many xxx. systemReady (); here we will notify each service that the system is ready.
The following code snippet:
// 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) ActivityManagerNative. getDefault ())
. SystemReady ()
-->
SystemReady @ frameworks \ base \ services \ java \ com \ android \ server \ am \ ActivityManagerSe
Rvice. java
Public void systemReady (final Runnable goingCallback ){
...
ResumeTopActivityLocked (null); // start the Home application here
...
}
-->
Private final boolean resumeTopActivityLocked (HistoryRecord prev ){
// Find the first activity that is not finishing.
HistoryRecord next = topRunningActivityLocked (null );
If (next = null ){
// There are no more activities! Let's just start up
// Launcher...
Return startHomeActivityLocked ();
}
...
}
TopRunningActivityLocked is used to return the Activity at the top of the current system Activity stack. If it is null, topRunningActivityLocked () is called ()
4. Start the HOME Application
Private boolean startHomeActivityLocked (){
...
If (mFactoryTest! = SystemServer. FACTORY_TEST_LOW_LEVEL ){
Intent. addCategory (Intent. CATEGORY_HOME );
}
ActivityInfo aInfo =
Intent. resolveActivityInfo (mContext. getPackageManager (), STOCK_PM_FLAGS );
ProcessRecord app = getProcessRecordLocked (aInfo. processName, aInfo. applicationInfo. uid );
If (app = null | app. instrumentationClass = null ){
StartActivityLocked (null, intent, null, null, 0, aInfo,
Null, null, 0, 0, 0, false, false );
}
}
Here, an Intent of the CATEGORY_HOME type is created, and the resolveActivityInfo function is used to query PackageManagerService to check whether the CATEGORY type is HOME. Here, the Activity com. android. launcher2.Launcher is returned. Start the Activity for the first time with startActivityLocked.
View packages \ apps \ Launcher2 \ AndroidManifest. xml:
<Intent-filter>
<Action android: name = "android. intent. action. MAIN"/>
<Category android: name = "android. intent. category. HOME"/>
<Category android: name = "android. intent. category. DEFAULT"/>
<Category android: name = "android. intent. category. MONKEY"/>
</Intent-filter>
5. Start the Activity com. android. launcher2.Launcher.
First, let's start by executing the onCreate function and briefly look at the approximate relationship between code calls:
OnCreate --> mModel. startLoader (this, true); -->
Call LauncherModel. java
Public void startLoader (Context context, boolean isLaunching)
The application is not directly loaded, but is processed by LoaderThread by sending messages.
MLoaderThread = new LoaderThread (context, oldThread, isLaunching );
MLoaderThread. start ();
-->
Public void run (){
WaitForOtherThread ();
...
If (loadWorkspaceFirst ){
If (DEBUG_LOADERS) Log. d (TAG, "step 1: loading workspace ");
LoadAndBindWorkspace ();
} Else {
If (DEBUG_LOADERS) Log. d (TAG, "step 1: special: loading all apps ");
LoadAndBindAllApps ();
}
...
// Second step
If (loadWorkspaceFirst ){
If (DEBUG_LOADERS) Log. d (TAG, "step 2: loading all apps ");
LoadAndBindAllApps ();
} Else {
If (DEBUG_LOADERS) Log. d (TAG, "step 2: special: loading workspace ");
LoadAndBindWorkspace ();
}
...
}
Call loadAndBindAllApps to perform the following operations: www.2cto.com.
Private void loadAndBindAllApps (){
Loadall1_bybatch ();
}
Private void loadall1_bybatch (){
// Construct an Intent of the CATEGORY_LAUNCHER type
Final Intent mainIntent = new Intent (Intent. ACTION_MAIN, null); mainIntent. addCategory (Intent. CATEGORY_LAUNCHER );
// Use queryIntentActivities to set all types to Intent. ACTION_MAIN and
// Intent. CATEGORY_LAUNCHER Activity
Final PackageManager packageManager = mContext. getPackageManager ();
Apps = packageManager. queryIntentActivities (mainIntent, 0 );
// Save it to the mallmedialist Application List
For (int j = 0; I <N & j <batchSize; j ++ ){
// This builds the icon bitmaps.
MAllAppsList. add (new ApplicationInfo (apps. get (I), mIconCache ));
I ++;
}
// Use Callbacks
Final Callbacks callbacks = tryGetCallbacks (oldCallbacks );
MHandler. post (...){
Callbacks. bindAllApplications (added );
}
}
-->
/**
* Add the icons for all apps.
*
* Implementation of the method from LauncherModel. Callbacks.
*/
Public void bindAllApplications (ArrayList <ApplicationInfo> apps ){
MAllAppsGrid. setApps (apps );
}
6. allbench 2D. java continues to load applications.
Public void setApps (ArrayList <ApplicationInfo> list ){
MAllAppsList. clear ();
AddApps (list );
}
Public void addApps (ArrayList <ApplicationInfo> list ){
Final int N = list. size ();
For (int I = 0; I <N; I ++ ){
Final ApplicationInfo item = list. get (I );
Int index = Collections. binarySearch (mallelizlist, item,
LauncherModel. APP_NAME_COMPARATOR );
If (index <0 ){
Index =-(index + 1 );
}
MAllAppsList. add (index, item );
}
MAppsAdapter. notifyDataSetChanged ();
}
Here an ApplicationInfo instance is created, that is, each application icon is displayed on the desktop, and you can click to start these applications.
When you click the MENU button on the rightmost side, the following function is used:
/**
* Launches the intent referred by the clicked shortcut.
*
* @ Param v The view representing the clicked shortcut.
*/
Public void onClick (View v ){
ShowAllApps (true );
}
-->
Void showAllApps (boolean animated ){
MAllAppsGrid. zoom (1.0f, animated );
(View) mAllAppsGrid). setFocusable (true );
(View) mall1_grid). requestFocus ();
// TODO: fade these two too
MDeleteZone. setVisibility (View. GONE );
}
All applications in the system are displayed. When you click a specific icon:
All1_2d. java @ all1_2d. java
Public void onItemClick (AdapterView parent, View v,
Int position, long id ){
ApplicationInfo app = (ApplicationInfo) parent. getItemAtPosition (position );
MLauncher. startActivitySafely (app. intent, app );
}
Call startActivitySafely to start the corresponding application.
Summary:
There are too many things involved in this section. Here we just briefly go through the Code. There are still many concepts that need to be understood, but at least know the basic process steps.
Finally, we end the android system startup framework with a picture:
From andyhuabing's column