OS puts emphases on how to provide interfaces to user's APPs

for using hardware device

in the convenient and efficient way.

Everything has its own logic of running and must be done step by step,no shortcut. 

Take a look at Android OS Framework

Now, how to make the above OS run and every component of OS work to provide the service for user APP. Take a look at the process of startup as following picture

Step1: Startup from power on, Linux start up

  • System boot:bootloader  @bootable/bootloader/*
    • Comera+Power--->fastboot,
    • Home+Power--->load recovery.img
    • Power--->load boot.img
  • bootloader loads linux kernel
  • linux kernel initialize: @kernel/*

Step2: Android startup

  • kernel loads init-process: @ system/core/init/*
  • read config file: @system/rootdir/init.rc to start android service and start other commands and service(adbd for adb service, vold for SD mount)
  • Start native service, and other services such as ServiceManager,Zygote,media service.
  • Init read init process to start ril-daemon, media, bootsound, bootanim, servicemanager......
 init:@System/Core/Init
Init.c: parse_config_file(Init.rc) @parse_config_file(Init.marvel.rc)
解析脚本文件:Init.rc和Init.xxxx.rc(硬件平台相关)
Init.rc是Android自己规定的初始化脚本(Android Init Language, System/Core/Init/readme.txt)
该脚本包含四个类型的声明: Actions, Commands, Services, Options.
1.2 服务启动机制,我们来看看Init是这样解析.rc文件开启服务的。
()打开.rc文件,解析文件内容 @system/core/init/init.c
将service信息放置到service_list中。@system/core/init/parser.c
()restart_service() @system/core/init/init.c
service_start
execve(…).建立service进程。 export PATH /sbin:/system/sbin:/system/bin
export LD_LIBRARY_PATH /system/lib
mkdir /dev
mkdir /proc
mkdir /sys
mount tmpfs tmpfs /dev
mkdir /dev/pts
mkdir /dev/socket
mount devpts devpts /dev/pts
mount proc proc /proc
mount sysfs sysfs /sys
write /proc/cpu/alignment
ifup lo
hostname localhost
domainname localhost
mount yaffs2 mtd@system /system
mount yaffs2 mtd@userdata /data
import /system/etc/init.conf
class_start default
service adbd /sbin/adbd
user adb
group adb
service usbd /system/bin/usbd -r
user usbd
group usbd
socket usbd
service zygote /system/bin/app_process -Xzygote /system/bin --zygote
socket zygote
service runtime /system/bin/runtime
user system
group system
on device-added-/dev/compass
start akmd
on device-removed-/dev/compass
stop akmd
service akmd /sbin/akmd
disabled
user akmd
group akmd
Zygote // @system\core\rootdir\init.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media

Step3: Zygote Startup

  • In init.rc: service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
 /**
* Main entry of app process.
*
* Starts the interpreted runtime, then starts up the application.
*
*/ #define LOG_TAG "appproc" #include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <cutils/process_name.h>
#include <cutils/memory.h>
#include <android_runtime/AndroidRuntime.h> #include <stdio.h>
#include <unistd.h> namespace android { void app_usage()
{
fprintf(stderr,
"Usage: app_process [java-options] cmd-dir start-class-name [options]\n");
} class AppRuntime : public AndroidRuntime
{
public:
AppRuntime()
: mParentDir(NULL)
, mClassName(NULL)
, mClass(NULL)
, mArgC(0)
, mArgV(NULL)
{
} #if 0
// this appears to be unused
const char* getParentDir() const
{
return mParentDir;
}
#endif const char* getClassName() const
{
return mClassName;
} virtual void onVmCreated(JNIEnv* env)
{
if (mClassName == NULL) {
return; // Zygote. Nothing to do here.
} /**
* This is a little awkward because the JNI FindClass call uses the
* class loader associated with the native method we're executing in.
* If called in onStarted (from RuntimeInit.finishInit because we're
* launching "am", for example), FindClass would see that we're calling
* from a boot class' native method, and so wouldn't look for the class
* we're trying to look up in CLASSPATH. Unfortunately it needs to,
* because the "am" classes are not boot classes.
*
* The easiest fix is to call FindClass here, early on before we start
* executing boot class Java code and thereby deny ourselves access to
* non-boot classes.
*/
char* slashClassName = toSlashClassName(mClassName);
mClass = env->FindClass(slashClassName);
if (mClass == NULL) {
LOGE("ERROR: could not find class '%s'\n", mClassName);
}
free(slashClassName); mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
} virtual void onStarted()
{
sp<ProcessState> proc = ProcessState::self();
LOGV("App process: starting thread pool.\n");
proc->startThreadPool(); AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgC, mArgV); IPCThreadState::self()->stopProcess();
} virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
LOGV("App process: starting thread pool.\n");
proc->startThreadPool();
} virtual void onExit(int code)
{
if (mClassName == NULL) {
// if zygote
IPCThreadState::self()->stopProcess();
} AndroidRuntime::onExit(code);
} const char* mParentDir;
const char* mClassName;
jclass mClass;
int mArgC;
const char* const* mArgV;
}; } using namespace android; /**
* sets argv0 to as much of newArgv0 as will fit
*/
static void setArgv0(const char *argv0, const char *newArgv0)
{
strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
} int main(int argc, const char* const argv[])
{
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv; mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--; AppRuntime runtime;
const char* argv0 = argv[0]; // Process command line arguments
// ignore argv[0]
argc--;
argv++; // Everything up to '--' or first non '-' arg goes to the vm int i = runtime.addVmArguments(argc, argv); // Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
const char* parentDir = NULL;
const char* niceName = NULL;
const char* className = NULL;
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg;
} else if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = "zygote";
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12;
} else {
className = arg;
break;
}
} if (niceName && *niceName) {
setArgv0(argv0, niceName);
set_process_name(niceName);
} runtime.mParentDir = parentDir; if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
runtime.start("com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}

app_main

 // @system\core\rootdir\init.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
  • Zygote start up from main(…) of app_process   //@frameworks/base/cmds/app_main.cpp。
  • Create Java Runtime:  runtime.start("com.android.internal.os.ZygoteInit.java", startSystemServer); //@AndroidRuntime.cpp
  • Make Zygote run:com.android.internal.os.ZygoteInit:main()  //@com.android.internal.os.ZygoteInit
  • registerZygoteSocket();
  • startSystemServer();com.android.internal.os.ZygoteInit:startSystemServer() //@com.android.internal.os.ZygoteInit.
  • Now the Zygote service framework is built, and accept the requet from ActivityManagerService via Socket to fork APP.
  • Zygote.forkSystemServer(@dalvik.system.Zygote.java) is mapped to the process of linux with pid.
 public static void main(String argv[])
{
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());
preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
gc();
// If requested, start system server directly from Zygote
if (argv.length != 2) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
if (argv[1].equals("start-system-server")) {
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
if (ZYGOTE_FORK_MODE) {
runForkMode();
} else {
runSelectLoopMode();
}
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
 private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException
{
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid; try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
}
catch (IllegalArgumentException ex)
{
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
return true;
}
 //@dalvik.system.Zygote.java
public static int forkSystemServer(int uid, int gid, int[] gids,int debugFlags, int[][] rlimits,long permittedCapabilities, long effectiveCapabilities)
{
preFork();
//call native method to fork a process of system server which is mappged to linux process
int pid = nativeForkSystemServer(uid, gid, gids, debugFlags, rlimits,
permittedCapabilities,
effectiveCapabilities);
postFork();
return pid;
}

Step3:SystemServer Startup

  • Zygote fork a process of SystemServer: forkSystemServer() //@dalvik.system.Zygote.java
  • Zygote.nativeForkSystemServer() //@dalvik/vm/native/dalvik_system_Zygote.c
  • SystemServer is created and running.
  • com.android.server.SystemServer:init1(): The native method start all system native service.
  • com.android.server.SystemServer:init2(): Create a ServerThread to add just created native service by init1() to service list and finally loop.

com.android.server.SystemServer:main()//@com.android.server.SystemServer.java

 public static void main(String[] args)
{
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
// If a device's clock is before 1970 (before 0), a lot of
// APIs crash dealing with negative numbers, notably
// java.io.File#setLastModified, so instead we fake it and
// hope that time from cell towers or NTP fixes it
// shortly.
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
timer = new Timer();
timer.schedule(new TimerTask()
{
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server", null);
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}
// Mmmmmm... more memory!
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
System.loadLibrary("android_servers");//load android_servers.so
init1(args);
}
/***
* 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.
*/
native public static void init1(String[] args); public static final void init2() {
Slog.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
 //@com.android.server.SystemService
class ServerThread extends Thread
{
......
@Override
public void run()
{
...............................
Looper.prepare();
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
BinderInternal.disableBackgroundScheduling(true);
android.os.Process.setCanSelfBackground(false);
// Check whether we failed to shut down last time we tried.
{
....................
}
String factoryTestStr = SystemProperties.get("ro.factorytest");
int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
: Integer.parseInt(factoryTestStr);
.......//declare all native service object.
// Critical services...add all service into list of service manager
try {
Slog.i(TAG, "Entropy Service");
ServiceManager.addService("entropy", new EntropyService());
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
context = ActivityManagerService.main(factoryTest);
ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
AttributeCache.init(context);
........................
alarm = new AlarmManagerService(context);
ServiceManager.addService(Context.ALARM_SERVICE, alarm);
Watchdog.getInstance().init(context, battery, power, alarm,ActivityManagerService.self());
Slog.i(TAG, "Window Manager");
wm = WindowManagerService.main(context, power,factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,!firstBoot);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ActivityManagerService.self().setWindowManager(wm);
....................... } catch (RuntimeException e) {
}
.............................
// Bring up services needed for UI.
if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL)
{
try {
Slog.i(TAG, "Input Method Service");
imm = new InputMethodManagerService(context);
ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);
} catch (Throwable e) {
reportWtf("starting Input Manager Service", e);
}
.......................
} try {
wm.displayReady();
} catch (Throwable e) {
reportWtf("making display ready", e);
} try {
pm.performBootDexOpt();
} catch (Throwable e) {
reportWtf("performing boot dexopt", e);
} try {
ActivityManagerNative.getDefault().showBootMessage(context.getResources().getText(
com.android.internal.R.string.android_upgrading_starting_apps),
false);
} catch (RemoteException e) {
}
if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
try {
Slog.i(TAG, "Device Policy");
devicePolicy = new DevicePolicyManagerService(context);
ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy);
} catch (Throwable e) {
reportWtf("starting DevicePolicyService", e);
}
....................
try {
Slog.i(TAG, "Wi-Fi Service");
wifi = new WifiService(context);
ServiceManager.addService(Context.WIFI_SERVICE, wifi);
} catch (Throwable e) {
reportWtf("starting Wi-Fi Service", e);
}
....................
try {
Slog.i(TAG, "NetworkTimeUpdateService");
networkTimeUpdater = new NetworkTimeUpdateService(context);
} catch (Throwable e) {
reportWtf("starting NetworkTimeUpdate service", e);
}
}
// Before things start rolling, be sure we have decided whether
// we are in safe mode.
final boolean safeMode = wm.detectSafeMode();
if (safeMode) {
ActivityManagerService.self().enterSafeMode();
// Post the safe mode state in the Zygote class
Zygote.systemInSafeMode = true;
// Disable the JIT for the system_server process
VMRuntime.getRuntime().disableJitCompilation();
} else {
// Enable the JIT for the system_server process
VMRuntime.getRuntime().startJitCompilation();
}
// It is now time to start up the app processes...
if (devicePolicy != null) {
try {
devicePolicy.systemReady();
} catch (Throwable e) {
reportWtf("making Device Policy Service ready", e);
}
}
if (notification != null) {
try {
notification.systemReady();
} catch (Throwable e) {
reportWtf("making Notification Service ready", e);
}
}
try {
wm.systemReady();
} catch (Throwable e) {
reportWtf("making Window Manager Service ready", e);
}
if (safeMode) {
ActivityManagerService.self().showSafeModeOverlay();
}
// Update the configuration for this context by hand, because we're going
// to start using it before the config change done in wm.systemReady() will
// propagate to it.
..................................
power.systemReady();
try {
pm.systemReady();
} catch (Throwable e) {
reportWtf("making Package Manager Service ready", e);
} // These are needed to propagate to the runnable below.
final Context contextF = context;
final BatteryService batteryF = battery;
.........................
// 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() {
Slog.i(TAG, "Making services ready");
startSystemUi(contextF);
try {
if (batteryF != null) batteryF.systemReady();
} catch (Throwable e) {
reportWtf("making Battery Service ready", e);
}
.....................
try {
if (textServiceManagerServiceF != null) textServiceManagerServiceF.systemReady();
} catch (Throwable e) {
reportWtf("making Text Services Manager Service ready", e);
}
}
}); // For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i(TAG, "Enabled StrictMode for system server main thread.");
}
Looper.loop();
Slog.d(TAG, "System ServerThread is exiting!");
}
static final void startSystemUi(Context context) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
Slog.d(TAG, "Starting service: " + intent);
context.startService(intent);
}
}

Step4:Home luncher Startup

http://blog.csdn.net/maxleng/article/details/5508372

http://wenku.baidu.com/view/fc7729375a8102d276a22f13.html

http://wenku.baidu.com/view/42ebf459be23482fb4da4c33.html

http://www.cnblogs.com/linucos/archive/2012/05/22/2513760.html

Android's Process & Thread

Android OS Startup的更多相关文章

  1. android.os.NetworkOnMainThreadException异常

    在android4.0以前,访问网络的代码可以写在UI主线程,但是在android4.0以上就不能在ui主线程中访问网络了,会出现android.os.NetworkOnMainThreadExcep ...

  2. Xamarin Android.Views.WindowManagerBadTokenException: Unable to add window -- token android.os.BinderProxy

    Android.Views.WindowManagerBadTokenException: Unable to add window -- token android.os.BinderProxy@ ...

  3. Android.os.NetworkOnMainThreadException

    出现Android.os.NetworkOnMainThreadException错误提示的原因原因:不允许在主线程中进行网络访问解决办法:将网络访问的操作单独放到一个线程中

  4. android aidl 进程间通信需要注意的地方(android.os.TransactionTooLargeException)

    转自:http://blog.sina.com.cn/s/blog_4e1e357d0102wau9.html 1.bus工程实现通过service实现aidl实体类 2.actor工程通过发起bin ...

  5. android-解决 Android N 上 报错:android.os.FileUriExposedException

    解决 Android N 上 安装Apk时报错:android.os.FileUriExposedException: file:///storage/emulated/0/Download/appN ...

  6. Android内核开发:系统启动速度优化-Android OS启动优化(转)

    Android系统的启动优化主要分为三大部分: (1) Bootloader优化 (2) Linux Kernel的剪裁与优化 (3) Android OS部分的剪裁与优化 本文重点关注Android ...

  7. android.os.BadParcelableException: ClassNotFoundException when unmarshalling:解决办法

    例如在用AlarmManager的时候 AlarmManager alarmMgr = (AlarmManager) mContext .getSystemService(Context.ALARM_ ...

  8. 主线程中一定不能放耗时操作,必须要开子线程,比如下载文件,不然会不让你拿到输入流--报错显示android.os.NetworkOnMainThreadException

    1.必须要开子线程来操作耗时操作,android.os.NetworkOnMainThreadException new Thread(new Runnable() { @Override publi ...

  9. android.os.NetworkOnMainThreadException解决

    很早就知道Android4.0以后,要把耗时的网络操作放在多线程中,处理方法有: 1) setContentView(R.layout.activity_main)下面加上如下代码 if (andro ...

随机推荐

  1. OpenCV&Qt学习之四——OpenCV 实现人脸检测与相关知识整理

    开发配置 OpenCV的例程中已经带有了人脸检测的例程,位置在:OpenCV\samples\facedetect.cpp文件,OpenCV的安装与这个例子的测试可以参考我之前的博文Linux 下编译 ...

  2. es6-01

    ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer ManufacturersAssociation)通过ECMA-262标准化的脚本程 ...

  3. 小聊outline和border

    border与outline: border属性: border-width.border-style.border-color 其中border-style可以为none或hidden outlin ...

  4. H - 逆序数(树状数组)

    在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 如2 4 3 1中,2 1,4 3,4 1,3 1是逆序 ...

  5. AD域账号验证

    public partial class _Default : Page { [DllImport("advapi32.dll")] private static extern b ...

  6. Modbus协议学习笔记

    之前也有写过基于 Modbus 通讯协议的控制远程监控程序,但是由于当时时间赶.人手少(软硬件前后台都是在下一人

  7. Nuxt 2.3.X 配置babel

    1. 在package.json中修改运行脚本 添加--exec babel-node 添加之后的效果为:(修改了8/10行) { "name": "nuxt-learn ...

  8. 30段有用的javascript代码

    1. 如何区分IE及非IE浏览器 if(!+[1,]){ console.log("这是IE浏览器"): } else{ console.log("这不是IE浏览器&qu ...

  9. bcc-tools安装

    1           一. 安装cmake cmake是一种跨平台的编译工具,安装过程如下: 下载源码包:https://cmake.org/files/v3.8/cmake-3.8.0.tar.g ...

  10. Mongodb installation & userguide

    1.Mongodb Installation in Ubuntu (1) Download from: https://www.mongodb.org/downloads File: mongodb- ...