[Android Software/Hacking General [Developers Only]] llrraa2010:
WindowManagerService

Part III: understanding android in scenes

chapter 7 start of Activity

7.2　start of root Activity

In Android, the app consists of Activity, so the start of app is actually the start of default Activity in the app. Here we will discuss how the app starts.

The start of MainActivity is shown in the figure below:

We will discuss every step in details in the following:

Step 1. Launcher.startActivitySafely

In Android, the app is started by Launcher. In fact, Launcher is also one app. When one app is installed, there will be on corresponding icon on the Launcher screen. When the icon is clicked, Launcher will start the app.

The source of Launcher is in folder packages/apps/Launcher2, and the source to start other apps is in file src/com/android/launcher2/Launcher.java

/**
* Default launcher application.
*/
public final class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {

......

/**
* Launches the intent referred by the clicked shortcut.
*
* [MENTION=955119]param[/MENTION] v The view representing the clicked shortcut.
*/
public void onClick(View v) {
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// Open shortcut
final Intent intent = ((ShortcutInfo) tag).intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(new Rect(pos[0], pos[1],
pos[0] + v.getWidth(), pos[1] + v.getHeight()));
startActivitySafely(intent, tag);
} else if (tag instanceof FolderInfo) {
......
} else if (v == mHandleView) {
......
}
}

void startActivitySafely(Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
......
} catch (SecurityException e) {
......
}
}

......

}

We already know that the default Activity of one app is MainActivity, and it's configed in AndroidManifest.xml:

<activity android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

So, in the intent, action = "android.intent.action.Main", category="android.intent.category.LAUNCHER" and cmp="shy.luo.activity/.MainActivity". This means the Activity to start is shy.luo.activity.MainActivity.

Intent.FLAG_ACTIVITY_NEW_TASK means it's going to start the Activity in a new Task. Task is different from Process. It's a group of Activity, managed in stack, last in first out. In fact, Task is very complicated. If you are interested in it, please visit http://developer.android.com/guide/topics/manifest/activity-element.html for more details. Here, we just need to know the MainActivity is going to start in a new Task, and that's enough.

Step 2. Activity.startActivity

In step 1, we see that Launcher is derived from Activity, and class Activity implements function startActivity, so, here function Activity.startActivity is called. The source is in file frameworks/base/core/java/android/app/Activity.java:

public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks {

......

@Override
public void startActivity(Intent intent) {
startActivityForResult(intent, -1);
}

......

}

This function is very simple, just calls startActivityForResult. The second argument -1 means no returned result is needed after the Activity ends.

Step 3. Activity.startActivityForResult

The source is also in file frameworks/base/core/java/android/app/Activity.java

public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks {

......

public void startActivityForResult(Intent intent, int requestCode) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode);
......
} else {
......
}

......

}

Minstrumentation is the data member of class Activity. Its type is Intrumentation, whose source is in file frameworks/base/core/java/android/app/Instrumentation.java. Intrumentation is used to monitor all of the interaction the system has with the application.

Here, mMainThread is also the data member of class Activity. Its type is ActivityThread, and it represents the main thread of the app. We get data member ApplicationThread by mMainThread.getApplicationThread. It's a Binder, and ActivityManagerService uses it for IPC with

ActivityThread. Here mMainThread is the main thread of Launcher.

Here mToken is also the data member of class Activity. It's a remote interface of Binder.

Step 4. Instrumentation.execStartActivity	12

Step 5. ActivityManagerProxy.startActivity	13

Step 6. ActivityManagerService.startActivity	14

Step 7.*ActivityStack.startActivityMayWait	15

Step 8. ActivityStack.startActivityLocked	18

Step 9. ActivityStack.startActivityUncheckedLocked	20

Step 10. Activity.resumeTopActivityLocked	24

Step 11. ActivityStack.startPausingLocked	25

Step 12.*ApplicationThreadProxy.schedulePauseActivity	27

Step 13. ApplicationThread.schedulePauseActivity	27

Step 14. ActivityThread.queueOrSendMessage	28

Step 15. H.handleMessage	29

Step 16.*ActivityThread.handlePauseActivity	30

Step 17. ActivityManagerProxy.activityPaused	31

Step 18.*ActivityManagerService.activityPaused	32

Step 20.*ActivityStack.completePauseLocked	33

Step 21.*ActivityStack.resumeTopActivityLokced	34

Step 22. ActivityStack.startSpecificActivityLocked	36

Step 23.*ActivityManagerService.startProcessLocked	37

Step 24. ActivityThread.main	39

Step 25.*ActivityManagerProxy.attachApplication	41

Step 26.*ActivityManagerService.attachApplication	41

Step 27.*ActivityManagerService.attachApplicationLocked	42

Step 28. ActivityStack.realStartActivityLocked	44

Step 29.*ApplicationThreadProxy.scheduleLaunchActivity	46

Step 30.*ApplicationThread.scheduleLaunchActivity	47

Step 31.*ActivityThread.queueOrSendMessage	48

Step 32. H.handleMessage	49

Step 33.*ActivityThread.handleLaunchActivity	50

Step 34.*ActivityThread.performLaunchActivity	51

Step 35. MainActivity.onCreate	54

chapter 20 WindowManagerService

20.1 window size calculation

At any time, there's only one active Activity window in android. But, for WindowManagerService, it doesn't mean it only needs to manage one Activity window. For example, during the transition of two apps, two Activity windows are both visible. Even when there's only one Activity window is visible, WindowManagerService still has to manage multiple windows at the same time, since visible Activity window might have Wallpaper Winodw or Sub Window, and possibly Status Bar and Input Method Window would show up, as shown in the diagram below:

20.2 window management

As you know, in Android, Activity is managed as stack by ActivityManagerService. Similar to Activity, Window is also managed as stack by WindowManagerService. The higher Windows in the stack is above those lower windows. Here we will discuss how WindowManagerService manages windows as stack.

From chapter 7, we know that for each Activity there's one ActivityRecord in ActivityManagerService. Also, for each ActivityRecord there's one AppWindowToken in WindowManagerService.

In addition to that, for each inputmethodwindow there's one binder in InputMethodManagerService, and correspondingly one WindowToken in WindowManagerService.

Similar to inputmethodwindow, for each Wallpaperwindow there's one binder in WallpaperManagerService, and correspondingly one WindowToken in WindowManagerService.

In WindowManagerService, Windows(WindowState) are organized as groups, and windows in the same groups have the same token( AppWindowToken and WindowToken ). For example, one Activity window can have a Starting Window, and several child windows, then all these windows are in the same group, and use the AppWindowToken of the Activity window as token.

The above relationship is shown in the figure below:

In the above figure, Activity Stack is created by ActivityManagerService, Token List and Window Stack are created by WindowManagerService, Binder for IM is created by InputMethodManagerService for a InputMethodWindow, and Binder for WP is created by WallpaperManagerService for a WallpaperWindow.

Relationship of objects in the above figure is shown as below:

1. ActivityRecord-J corresponds to AppWindowToken-J, which identifies a group of windows: {WindowState- A,*WindowState-B,*WindowState-B-1}. WindowState-B-1 is the child window of WindowState-B.

2. ActivityRecord-K corresponds to AppWindowToken-K, which identifies a group of windows: {WindowState-C, WindowState-C-1, WindowState-D, WindowState-D-1}. WindowState-C-1 is the child window of WindowState-C, and WindowState-D-1 is the child window of WindowState-D.

20.3 Input Method Window management

In Android, inputmethod window is a kind of special window, and it's always on top of the window who knows it. So once WindowManagerService knows the focused window needs inputmethod, it will adjust the position of inputmethod window in the window stack, and make it on top of the focused window, so that the user can input character by inputmethod window. We will discuss how WindowManagerService manages inputmethod window in details here.

In android, except for Inputmethod Window, there's another kind of window called Input Method Dialog, which is always on top of Input Method Window. The relationship between Activity window, Input Method Window and Input Method Dialog is shown as the figure below:

20.4 Wallpaper Window management

In Android, Wallpaper Window, just like the Input Method Window, is also a special kind of window, and they both love to stay with a normal Activity Window. Input Method Window is on the top, Wallpaper Window is at the bottom, and Activity Window is in the middle. We already know how Input Method Window is on top of Activity Window, and here we will discuss how Wallpaper Window stays at the bottom of Activity Window.

If one Activity Window needs to show the wallpaper, it must fulfill the following two conditions:

1. the background is Translucent. For example, its android:theme property in file AndroidManifest.xml must be set to Theme.Translucent

<activity android:name=".WallpaperActivity"
android:theme="@android:style/Theme.Translucent">
......
</activity>