-
Notifications
You must be signed in to change notification settings - Fork 69
AndroidApplicationStartup
As usual a few hints from Diane are most welcome…
http://osdir.com/ml/android-platform/2010-10/msg00199.html
Just follow the code from ContextImpl.startActivity() -> ActivityMangerService.startActivity;
in ActivityManagerService there is a bunch of work to maintain the activity stack and keep
the top activity in the stack resumed as described by the activity lifecycle documentation in
the SDK. This is done by performing calls on IApplicationThread, which is implemented by
ActivityThread to receive commands from the activity manager and execute them.
ActivityManagerNative is not really interesting. It is just the marshalling side of the
IPC interface with the activity manager.
I would strongly recommend when exploring the code to load it up in to Eclipse.
Being able to use Command-G (to find implementations of a symbol) and Shift-Command-G
(to find references to a symbol) make it a lot easier to follow calls.
Android applications
Questions to answer:
- How is an activity started?
- How is an service started?
- How are content provider started?
At high level the story goes as follow: An activity is started from an other activity. The activity that is calling
uses it’s context to get hold of the activity system service and then requests an activity to be started.
At that point the ActivityManagerService (the class implementing the “activity” service) will perform the necessary
actions for the activity to be started. It can either spawn a new process or request an existing process to add
that activity to it’s stack.
High level overview of an activity creation
High level overview of an activity creation
Lower level overview of an activity creation
Lower level overview of an activity creation
Relevant classes:
Overview of the classes involved in Activity creation
android.content.Context
android.app.ContextImpl
android.app.Instrumentation
android.app.ActivityManager
android.app.ActivityManagerNative
android.app.ActivityManagerProxy (Remote implementation of the IActivityManager).
android.app.ActivityThread → This manages the execution of the main thread in an application process
android.app.LocalActivityManager
android.app.LoadedApk
com.android.server.am.ActivityManagerService → The process actually launching packages and services
android.app.ActivityThread (is the class calling onCreate, onBind etc on a started activity)
android.os.Process
things to figure out:
android.app.ActivityThread
-> IContentProvider installProvider
c = context.createPackageContext
ClassLoader cl = c.getClassLoader()
localProvider = cl.loadClass(info.name).newInstance();
android.app.ApplicationThread → the glue beteen the “activity manager” and application threads. My understanding
is that every process that is spawned will connect to the Activity manager stack.
android.app.ContextImpl extends Context
-> startActivity(Intent intent)
get app main thread get Instrumentation execStartActivity(context , app thread , nu,, null, intent ,-1);
android.app.Instrumentation
-> execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode)
ActivityManagerNative.getDefault() -> this executes a ServiceManager.getService("activity") + cast to IActivityManager (e.g. as binder object)
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
null, 0, token, target != null ? target.mEmbeddedID : null,
requestCode, false, false);
android.app.ContextImpl extends Context
-> Context createPackageContext(String packageName, int flags)
-> LoadedApk pi = mMainThread.getPackageInfo(packageName, flags)
ContextImpl c = new ContextImpl();
c.init(pi, null, mMainThread, mResources);
com.android.server.am.ActivityManagerService extends android.app.ActivityManagerNative
-> startProcessLocked
Process.start("android.app.ActivityThread",
mSimpleProcessManagement ? app.processName : null, uid, uid,
gids, debugFlags, null);
android.os.Process
-> start(Sting classname)
if (supports processes)
-> startViaZygote(classname)
openZygoteSocketIfNeeded
Services: activity class com.android.server.am.ActivityManagerService (is instansiated in the SystemServer context = ActivityManagerService.main(factoryTest)
Activity:caller Context —> ActivityManager
P0 zygote
| (0)
| Launches (fork)
\|/
P1 system server
* ActivityManagerNative
| \-(1) Create process record----------(4)-> Find ActivityRecord
| /|\ \--> (5) mMainStack.realStartActivityLocked
| (2) | \->(6) app.thread.scheduleLaunchActivity
| Starts (socket to zygote) | (IApplicationThread.attachApplication)
\|/ |
P1 ActivityThread---(3)----------------/
We know that the zygote is stated to load many libraries and after that will wait fork itself
into different java virtual machines running as separate processes. From Java side the code called is in the Process class
and it will communicate via a socket to zygote.
Debugging zygote to find out what is happening
select () at bionic/libc/arch-arm/syscalls/select.S:17
17 ldmfd sp!, {r4, r5, r6, r7}
(gdb)
(gdb) bt
#0 select () at bionic/libc/arch-arm/syscalls/select.S:17
#1 0xad35c7c4 in com_android_internal_os_ZygoteInit_selectReadable
(env=0xabe0, clazz=<value optimized out>, fds=0x4050a398) at
frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp:297
#2 0xaca11e78 in dvmPlatformInvoke () at dalvik/vm/arch/arm/CallEABI.S:243
#3 0xaca436da in dvmCallJNIMethod_general (args=0x431ecf48, pResult=0xbe816870,
method=0x4325ee44, self=0xce48) at dalvik/vm/Jni.c:1729
#4 0xaca3c1cc in dvmCheckCallJNIMethod_general (args=0x431ecf48,
pResult=0x4422b983, method=0xad35c70d, self=0xbe816870) at dalvik/vm/CheckJni.c:136
#5 0xaca17078 in dalvik_mterp () at dalvik/vm/mterp/out/InterpAsm-armv7-a.S:10017
#6 0xaca1c118 in dvmMterpStd (self=<value optimized out>, glue=0xbe816868) at
dalvik/vm/mterp/Mterp.c:105
#7 0xaca1b004 in dvmInterpret (self=0xce48, method=0x4325ec70, pResult=<value optimized
out>) at dalvik/vm/interp/Interp.c:1345
#8 0xaca59c16 in dvmCallMethodV (self=0xce48, method=0x4325ec70, obj=0x0,
fromJni=true, pResult=0xbe816b20, args=...) at dalvik/vm/interp/Stack.c:529
#9 0xaca4612e in CallStaticVoidMethodV (env=<value optimized out>,
jclazz=<value optimized out>, methodID=0x4325ec70, args=...) at dalvik/vm/Jni.c:2943
#10 0xaca38f20 in Check_CallStaticVoidMethodV (env=0xabe0, clazz=0x400397b0,
methodID=0x4325ec70, args=...) at dalvik/vm/CheckJni.c:1937
#11 0xad3307fc in _JNIEnv::CallStaticVoidMethod (this=0xaca823e4, clazz=<value optimized out>,
methodID=0xaf90c2c2) at dalvik/libnativehelper/include/nativehelper/jni.h:793
#12 0xad3316aa in android::AndroidRuntime::start (this=<value optimized out>, className=0x8dde
"com.android.internal.os.ZygoteInit", startSystemServer=<value optimized out>)
at frameworks/base/core/jni/AndroidRuntime.cpp:974
#13 0x00008ccc in main (argc=<value optimized out>, argv=<value optimized out>)
at frameworks/base/cmds/app_process/app_main.cpp:159
Break zygote on “fork” and start a new application:
(gdb) bt
#0 fork () at bionic/libc/bionic/fork.c:43
#1 0xaca60360 in forkAndSpecializeCommon (args=<value optimized out>, isSystemServer=<value optimized out>) at dalvik/vm/native/dalvik_system_Zygote.c:397
#2 0xaca6058a in Dalvik_dalvik_system_Zygote_forkAndSpecialize (args=0xaca8a004, pResult=0xbe816870) at dalvik/vm/native/dalvik_system_Zygote.c:482
#3 0xaca17078 in dalvik_mterp () at dalvik/vm/mterp/out/InterpAsm-armv7-a.S:10017
#4 0xaca1c118 in dvmMterpStd (self=<value optimized out>, glue=0xbe816868) at dalvik/vm/mterp/Mterp.c:105
#5 0xaca1b004 in dvmInterpret (self=0xce48, method=0x4325ec70, pResult=<value optimized out>) at dalvik/vm/interp/Interp.c:1345
#6 0xaca59c16 in dvmCallMethodV (self=0xce48, method=0x4325ec70, obj=0x0, fromJni=true, pResult=0xbe816b20, args=...) at dalvik/vm/interp/Stack.c:529
#7 0xaca4612e in CallStaticVoidMethodV (env=<value optimized out>, jclazz=<value optimized out>, methodID=0x4325ec70, args=...) at dalvik/vm/Jni.c:2943
#8 0xaca38f20 in Check_CallStaticVoidMethodV (env=0xabe0, clazz=0x400397b0, methodID=0x4325ec70, args=...) at dalvik/vm/CheckJni.c:1937
#9 0xad3307fc in _JNIEnv::CallStaticVoidMethod (this=0xaca823e4, clazz=<value optimized out>, methodID=0xaf90c2c2) at dalvik/libnativehelper/include/nativehelper/jni.h:793
#10 0xad3316aa in android::AndroidRuntime::start (this=<value optimized out>, className=0x8dde "com.android.internal.os.ZygoteInit", startSystemServer=<value optimized out>) at frameworks/base/core/jni/AndroidRuntime.cpp:974
#11 0x00008ccc in main (argc=<value optimized out>, argv=<value optimized out>) at frameworks/base/cmds/app_process/app_main.cpp:159
The java side of a process started by zygote side of thing can be viewed using ddms. We see that after forking an ActivityThread.main is call and this will probably connect back to the ActivityStack using the “attach” method of the activty thread.( attachApplication on IActivityManager )
<1> main@830002557320, prio=5, in group 'main', status: 'RUNNING'
at android.os.MessageQueue.nativePollOnce(MessageQueue.java:-1)
at android.os.MessageQueue.next(MessageQueue.java:119)
at android.os.Looper.loop(Looper.java:117)
at android.app.ActivityThread.main(ActivityThread.java:3683)
at java.lang.reflect.Method.invokeNative(Method.java:-1)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(NativeStart.java:-1)