在源码树下搜寻某个包(.apk, .so, ...)的源码路径的命令(以libmedia为例):
find . -iname Android.mk -exec grep -i -H "LOCAL_MODULE.*=.*libmedia" {} \;
--------------------------------------------------------
init启动zygote:
Android中,java程序是通过app_process启动的。在/init.rc里面,有如下代码:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
其中,app_process的命令行格式如下:
app_process [java-options] cmd-dir start-class-name [options]
因此,上述init.rc里命令的各个参数的对应关系为:
-Xzygote: java-options,这些参数会传给dalvik;它们必须以-开头,一旦遇到不是以-开头的或者--,代表java-options结束;
/system/bin:cmd-dir,也就是当前目录,用作文件操作的父路径;
start-class-name: 上述命令中为空;
--zygote --start-system-server: 选项。
根据app_process的main()函数(在frameworks/base/cmds/app_process/app_main.cpp里面):app_process有两种启动方式:
1) 第一种就是init.rc里面的这种方式。这种方式下先调用set_process_name("zygote")通过系统调用prctl(PR_SET_NAME,...)将进程名称改为zygote(见system/core/libcutils/process_name.c),然后将会以zygote模式启动com.android.internal.os.ZygoteInit;具体分析见下。
2) 另外一种是以非zygote模式启动,实际运行的是类com.android.internal.os.RuntimeInit(见frameworks/base/core/jni/AndroidRuntime.cpp中的方法AndroidRuntime::start()),并调用它的main() 方法。main()的最后会执行native的finishInit()方法,该方法会调用app_process的onStarted()方法(见frameworks/base/core/jni/AndroidRuntime.cpp文件),在onStarted()里面将会调用app_init(mClassName, mArgC, mArgV),进而调用java类的main函数(文件frameworks/base/core/jni/AndroidRuntime.cpp:callMain(className, argc, argv))。
无论那种方式,类的启动都是通过frameworks/base/core/jni/AndroidRuntime.cpp:start(const char* className, const bool startSystemServer)来完成的,其中有startVm(&mJavaVM, &env)启动虚拟机,startReg(env)来向虚拟机注册所有native方法 。
--------------------------------------------------------
进程zygote分析:
根据/init.rc,进程zygote(以root运行)是在进程servicemanager(以system身份运行)之后启动的。因为zygote是其它dalvik进程的父进程,它须以root身份运行以便完成向其它身份的切换。zygote在ZYGOTE_SOCKET(即/dev/socket/zygote)上接收发给它的命令,并启动相应进程(即Android应用)。
zygote是一个含有main()的java程序,对应的文件为frameworks/base/core/java/com/android/internal/os/ZygoteInit.java。但它会用到文件libcore/dalvik/src/main/java/dalvik/system/Zygote.java中的以下jni支持函数:
native public static int forkSystemServer(int uid, int gid,
int[] gids, int debugFlags, int[][] rlimits,
long permittedCapabilities, long effectiveCapabilities);
ZygoteInit.java的main()首先设置最小可用堆大小为5M,然后注册ZYGOTE_SOCKET以便接受外来请求,随后执行preloadClasses()来加载基础java类(这样在运行其它应用时就可共享之),最后进入循环等待。代码片断如下:
public static void main(String argv[]) {
VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024); // 最小堆大小为5M
registerZygoteSocket(); // Zygote类的私有静态函数!
preloadClasses(); // Zygote类的私有静态函数!
preloadResources();
gc();
// If requested, start system server directly from Zygote
if (argv[1].equals("true")) {
startSystemServer(); // Zygote类的私有静态函数!
}
if (ZYGOTE_FORK_MODE) {
runForkMode(); // Zygote类的私有静态函数!
} else {
runSelectLoopMode(); // Zygote类的私有静态函数!
}
closeServerSocket();
...
}
其中,preloadClasses()生成一个VMRuntime实例(runtime),然后根据文件PRELOADED_CLASSES(即frameworks/base/preloaded-classes文件)的内容列表加载各个类,并可根据属性"ro.amlogic.no.preloadclass"加载根据设备定制的某些类。在源码的frameworks/base/Android.mk文件中有如下行:
LOCAL_JAVA_RESOURCES_FILES += $(LOCAL_PATH)/preloaded-classes
这个预加载类列表文件中包含了AccountManager, ActivityManager*, LocalActivityManager, AppWidgetManager, PackageManager, SensorManager, LocationManager, AudioManager, WifiManager, PreferenceManager, TelephonyManager, WindowManager, InputMehodManager, IntentService, BluetoothService等基本类。
注意,在开始加载这些类时zygote把自己的身份调整为普通用户(uid=9999),加载完后再恢复到ROOT身份。此后zygote始终以root身份运行。
值得注意的是随后的startSystemServer()函数调用(仍是root身份运行)。这是Android请求Zygote运行的第一个dalvik程序,其启动参数也是代码中写死了的。
system_server(文件frameworks/base/services/java/com/android/server/SystemServer.java)也是一个含main()的java程序,该进程由startSystemServer()函数启动,相关的部分代码如下:
private static boolean startSystemServer() { // in file ZygoteInit.java
String args[] = {
"--setuid=1000", //SYSTEM_UID
"--setgid=1000", //SYSTEM_UID
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
// 参见文件system/core/include/private/android_filesystem_config.h:
// 1001=AID_RADIO, 1002=AID_BLUETOOTH, 1003=AID_GRAPHICS, 1004=AID_INPUT,
// 1005=AID_AUDIO, 1006=AID_CAMERA, 1007=AID_LOG, 1009=AID_MOUNT, 1010=AID_WIFI,
// (1012=AID_INSTALL, 1015=AID_SDCARD_RW)
// 3001=AID_NET_BT_ADMIN, 3002=AID_NET_BT, 3003=AID_INET
"--capabilities=130104352,130104352",
// effective = 130104352 = 00000111-11000001-00111100-00100000:
// {TTY_CONFIG, TIME_RESOURCE, NICE,
// BOOT, MODULE, RAW,
// ADMIN, BROADCAST, SERVICE,
// KILL}
"--runtime-init",
"--nice-name=system_server", // 哦,这可不是/system/bin/system_server执行文件哟!
"com.android.server.SystemServer", // 要启动的java程序
};
...
ZygoteConnection.Arguments parsedArgs = new ZygoteConnection.Arguments(args);
int pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, debugFlags, null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
}
分析以上参数的代码见frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java$Arguments.parseArgs()。
这里android利用linux的附加组(supplementary group)机制[系统调用getgroups(int size, gid_t list[])]来实现权限的共享:由上看出,system_server具有RADIO/BT/WIFI/LOG/INET等进程的权限。
startSystemServer()函数通过handleSystemServerProcess()函数调用invokeStaticMain(startClass, startArgs)来启动进程system_server(对应文件为frameworks/base/services/java/com/android/server/SystemServer.java)。
SystemServer.java首先做简单的准备工作,然后加载c库libandroid_servers.so (见frameworks/base/services/jni/Android.mk),并执行其中的init1()函数(见文件frameworks/base/services/jni/com_android_server_SystemServer.cpp):
android_server_SystemServer_init1() -------- com_android_server_SystemServer.cpp
-> system_init() -------- frameworks/base/cmds/system_server/library/system_init.cpp
system_init()在初始化SurfaceFlinger, SensorService, simu:AudioFlinger, simu:MediaPlayerService, simu:CameraService,simu:AudioPolicyService等,并随后通过AndroidRunTime调用com_android_server_SystemServer.cpp中的init2()函数。
system_init() -> runtime->callStatic("com/android/server/SystemServer", "init2"); 其实init1和init2是两个阶段:
init1(): 启动SurfaceFlinger、虚拟机上的特殊处理、调用init2、开启线程池并等其结束(即永不退出);
init2(): 添加各个service。
------------------------
注:system_init()只是为simulator初始化Audiolinger、MediaPlayerService、CameraService、AudioPolicyService等服务,而对于真实设备,则是用一个独立可执行文件来初始化这些service的。在/init.rc文件中有:
service media /system/bin/mediaserver
user media
而mediaserver是这样生成的:
文件frameworks/base/media/mediaserver/Android.mk :
LOCAL_SRC_FILES:= main_mediaserver.cpp
LOCAL_MODULE:= mediaserver
include $(BUILD_EXECUTABLE)
文件frameworks/base/media/mediaserver/main_mediaserver.cpp中有:
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
可见,有关多媒体的服务是一起管理的,其中Camera服务是在文件frameworks/base/services/camera/libcameraservice/CameraService.cpp中定义的。
--------------------------------------------------------
下面以WiFi为例看一下各个service的启动:
在frameworks/base/services/java/com/android/server/SystemServer.java中,它定义的init2()通过一个ServerThread()来启动各项服务。ServerThread是一个线程,它会在run()中通过ServiceManager.addService("serv_name", new serv_instance)来启动并注册各个服务,其中就含有CONNECTIVITY_SERVICE,即"connectivity"。这里的addService()实际上是由 frameworks/base/core/java/android/os/ServiceManager.java又通过JNI接口
frameworks/base/cmds/runtime/ServiceManager.cpp中实现的。
ConnectivityService的构造函数(实际是在一个线程中执行的)会构造WifiService,并向ServiceManager注册。Android中的connectivity是按网络类型分级的(通过分析frameworks/base/core/res/res/values/config.xml的networkAttributes节,此顺序由高到低为MMS,SUPL,DUN,WIFI,MOBILE, 故wifi打开时,mobile会关闭;而wifi关闭时,mobile会重新打开,不过在sdk2.2后可以同时打开这两种连接),默认的网络连接为WIFI。ConnectivityService利用循环同时生成对wifi和mobile的tracker。WifiService注册后,应用程序就可使用getSystemService(WIFI_SERVICE)获得一个WifiManager对象来管理wifi设备了。
其它service的启动和使用与Wifi类似,只不过简繁不同。
system_server的ServerThread会在所有service启动后,使用xxx.systemReady()通知各个服务(特别是ActivityManagerService,Widget, wallpaper, 和imm),系统已经就绪。
值得注意的是,HomeScreen(或Laucher)就是在ActivityManagerService.systemReady()通知的过程中建立的。下面是ActivityManagerService.systemReady()的调用顺序:
systemReady()-> // Line
resumeTopActivityLocked() -> //Line2597
startHomeActivityLocked(); -> //如果是第一个则启动HomeActivity // Line 2609
startActivityLocked(null,intent(CATEGORY_HOME|NEW_TASK),...); // Line2505
<EOF>