目录
前言
如果你和我一样刚刚接触安卓不久,又恰巧学过其他编程,那么你多半会有个和我一样的疑问缠绕心头:Android 程序的入口到底在哪里?
我们知道,Android开发采用的编程语言是 Java 或 Kotlin,由于目前使用的是 Java ,这里仅说 Java。以往我们写 Java程序都会有一个入口函数main;而我们之前写的 Demo,程序都是从 Activity 的 onCreate( ) 方法中开始执行,那么它就我们Anroid APP程序的入口吗 ?
答案是 否定的。
我们都知道我们 Android 应用程序是运行在 Android系统 之上的,即先有 Android系统,才能运行我们的 app。
下面我们先看了解下 Android 的整体框架及 Android 系统的启动流程:
Android 框架
Android系统启动流程
装载机层
- Boot Rom:当手机处于关机状态时,长按开机键开机,会引导芯片开始从固化在 ROM 里的代码开始执行,然后加载引导程序到RAM
- Boot Loader:启动 Android 系统之前的引导程序,主要是检查 RAM,初始化参数等
内核层
Kernel层指的就是 Android 的 Linux内核层,其启动流程如下:
- 启动 swapper进程(PID = 0),这是系统初始化过程内核创建的第一个进程,用于初始化进程管理,内存管理,加载Display,Camera,Binder等驱动相关工作
- 启动 kthreadd 进程(PID = 2),它会创建内核工作 线程 kworkder,软中断 线程ksoftirqd、thermal 等内核守护进程。
kthreadd 是所有内核进程的鼻祖。
原生API层
这里 Native层 主要包括 init进程(PID = 1) 孵化的用户空间的守护进程,HAL 层以及开机动画等。
- init 进程会孵化出 ueventd,logd,healthd,installd,adbd,lmkd 等用户守护进程;
- init 进度即将启动 ServiceManager(Binder 服务管家),bootanim(开机动画)等重要服务。
- init 进程孵化出 Zygote进程,Zygote进程是 Android 系统第一个 Java 进程(虚拟机进程)。
Init 是所有用户空间进程的鼻祖。
Zygote进程是所有 Java 进程的父进程。
框架层(Framework)
Zygote 进程,是由 init 进程通过解析 init.rc 文件后 fork( ) 生成的,它主要包括以下内
- 加载 ZygoteInit 类,注册 Zygote Socket 服务端套接字
- 加载虚拟机
- 提前加载类 preloadClasses
- 提前加载资源 preloadResouces
System Server 进程,是由 Zygote 进程 fork( ) 而来
- System Server 是Zygote 孵化的第一个进程。
- System Server 负责启动和管理整个 Java framework,包含 ActivityManager,WindowManager,PackageManager,PowerManager 等服务。
Media Server 进程,是由 init 进程 fork( ) 而来
负责启动和管理整个 C++ framework,包含 AudioFlinger,Camera Service 等服务。
应用层
- Zygote 孵化进程第的一个 App进程 为 Launcher进程,也就是我们的桌面进程。
- Zygote进程 也会创建 Browser,Phone,Email等应用进程。也就是说所有的应用都是进程由 Zygote 进程 fork() 生成的。而且上层的进程全部由下层的进程进行管理,包括但不限于界面的注册,跳转,消息的传递。
Android应用程序打开流程
重要声明
本次Android源码阅读的版本是 2014-09-06- 索引:棒棒糖 - 5.0.0_r2
为什么不看最新的源码呢,因为资料少..目前还真啃不动
主界面 Launcher 其实也是一个 Activity,它存在击 icon 的事件OnClick()
// 代码节选:
// Launcher.java --- 2428
/**
* Launches the intent referred by the clicked shortcut.
*
* @param v The view representing the clicked shortcut.
*/
public void onClick(View v) {
// Make sure that rogue clicks don't get through while allapps is launching, or after the
// view has detached (it's possible for this to happen if the view is removed mid touch).
if (v.getWindowToken() == null) {
return;
}
if (!mWorkspace.isFinishedSwitchingState()) {
return;
}
if (v instanceof Workspace) {
if (mWorkspace.isInOverviewMode()) {
mWorkspace.exitOverviewMode(true);
}
return;
}
if (v instanceof CellLayout) {
if (mWorkspace.isInOverviewMode()) {
mWorkspace.exitOverviewMode(mWorkspace.indexOfChild(v), true);
}
}
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
onClickAppShortcut(v);
} else if (tag instanceof FolderInfo) {
if (v instanceof FolderIcon) {
onClickFolderIcon(v);
}
} else if (v == mAllAppsButton) {
onClickAllAppsButton(v);
} else if (tag instanceof AppInfo) {
startAppShortcutOrInfoActivity(v);
} else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v);
}
}
}
OnClick 事件会调用 startAppShortcutOrInfoActivity ()
// 代码节选:
// Launcher.java --- 2629
private void startAppShortcutOrInfoActivity(View v) {
Object tag = v.getTag();
final ShortcutInfo shortcut;
final Intent intent;
if (tag instanceof ShortcutInfo) {
shortcut = (ShortcutInfo) tag;
intent = shortcut.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()));
} else if (tag instanceof AppInfo) {
shortcut = null;
intent = ((AppInfo) tag).intent;
} else {
throw new IllegalArgumentException("Input must be a Shortcut or AppInfo");
}
boolean success = startActivitySafely(v, intent, tag);
mStats.recordLaunch(intent, shortcut);
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
}
}
这里调用了 startActivitySafely() 并通过 Binder IPC 机制 调用 ActivityManagerService.java 中的 startActivity (Intent)
// 代码节选:
// ActivityManagerService.java --- 3589
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
ActivityManagerService 会执行如下操作:
- 通过 PackageManager 的 resolveIntent () 收集这个 intent 对象的指向信息,并将指向信息被存储在一个 intent 对象中。
// 代码节选: // ActivityManagerService.java --- 3341 ResolveInfo info = AppGlobals.getPackageManager().resolveIntent( intent, intent.resolveTypeIfNeeded(mContext.getContentResolver()), flags, userId);
- 通过 grantUriPermissionLocked () 方法来验证用户是否有足够的权限去调用该 intent 对象指向的 Activity.
// 代码节选: // ActivityManagerService.java --- 7538 // grantUriPermissionLocked () 在 7388 处 /** * @param uri This uri must NOT contain an embedded userId. * @param userId The userId in which the uri is to be resolved. */ @Override public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri, final int modeFlags, int userId) { enforceNotIsolatedCaller("grantUriPermission"); GrantUri grantUri = new GrantUri(userId, uri, false); synchronized(this) { final ProcessRecord r = getRecordForAppLocked(caller); if (r == null) { throw new SecurityException("Unable to find app for caller " + caller + " when granting permission to uri " + grantUri); } if (targetPkg == null) { throw new IllegalArgumentException("null target"); } if (grantUri == null) { throw new IllegalArgumentException("null uri"); } Preconditions.checkFlagsArgument(modeFlags, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); grantUriPermissionLocked(r.uid, targetPkg, grantUri, modeFlags, null, UserHandle.getUserId(r.uid)); } }
- 如果有权限,ActivityManagerService 会检查并在新的 task 中启动目标 activity。
这时需要先检查这个进程的 ProcessRecord 是否存在了。(ProcessRecord 是用于描述进程的数据结构对象)
如果 ProcessRecord 是 null, ActivityManagerService 会创建新的进程来实例化目标 activity.
为了启动 App 并使其 Activity 进入 resumed 状态,需要先使当前运行的 Activity(也就是 Launcher) 进入 Paused 状态
ActivityManagerService 最终调用 overridePendingTransition( ) 执行(未严格验证)
// 代码摘取:
// ActivityManagerService .java ---- 4700
@Override
public void overridePendingTransition(IBinder token, String packageName,
int enterAnim, int exitAnim) {
synchronized(this) {
ActivityRecord self = ActivityRecord.isInStackLocked(token);
if (self == null) {
return;
}
final long origId = Binder.clearCallingIdentity();
if (self.state == ActivityState.RESUMED
|| self.state == ActivityState.PAUSING) {
mWindowManager.overridePendingAppTransition(packageName,
enterAnim, exitAnim, null);
}
Binder.restoreCallingIdentity(origId);
}
}
之后又通过 Binder 通信 调用到 ApplicationThread 的 schedulePauseActivity( )向本地的消息循环中加入一个 H.PAUSE_ACTIVITY 的消息。
// 代码摘取:
// ApplicationThread.java ---- 565
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) {
sendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
(userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
configChanges);
}
之后会通过 Handler 的子类 - H 发送消息,处理消息的逻辑在 ActivityThread.java 的 handleMessage( ) 中
// 代码摘取:
// ActivityThread.java ---- 1269
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
(msg.arg1&2) != 0);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
//...
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}
最终会调用 Activity 的 performPause () 方法
// 代码摘取:
// Activity.java ---- 6040
final void performPause() {
mDoReportFullyDrawn = false;
mFragments.dispatchPause();
mCalled = false;
onPause();
mResumed = false;
if (!mCalled && getApplicationInfo().targetSdkVersion
>= android.os.Build.VERSION_CODES.GINGERBREAD) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onPause()");
}
mResumed = false;
}
终于出现一个比较熟悉的身影了 onPause( )
之后在 handlePauseActivity ( ) 中调用 ActivityManagerNative.getDefault().activityPaused(token);
// 代码摘取:
// Activitythread.java ---- 3149
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
performPauseActivity(token, finished, r.isPreHoneycomb());
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
// Tell the activity manager we have paused.
if (!dontReport) {
try {
ActivityManagerNative.getDefault().activityPaused(token);
} catch (RemoteException ex) {
}
}
mSomeActivitiesChanged = true;
}
}
通过 Binder 机制调用 ActivityManagerService 中的 activityPaused ( ) 方法,如下:
// 代码摘录:
//ActivityManagerService.java ---- 6435
@Override
public final void activityPaused(IBinder token) {
final long origId = Binder.clearCallingIdentity();
synchronized(this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
stack.activityPausedLocked(token, false);
}
}
Binder.restoreCallingIdentity(origId);
}
最终调用到 startProcessLocked ( )
该方法用以创建新的进程,通过 socket 通道传递参数给 Zygote 进程。Zygote 孵化自身,并调用 ZygoteInit.main () 方法来实例化 ActivityThread 对象并最终返回新进程的 pid。具体过程如下:
// 代码摘录:
// ActivityManagerService.java ---- 2947
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
接着会调用startProcessLocked ( )的重载方法:
// 代码摘录:
//ActivityManagerService.java ---- 3189
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
//...
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
checkTime(startTime, "startProcess: asking zygote to start proc");
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
checkTime(startTime, "startProcess: returned from zygote!");
//...
}
Process.start ( ) 实际上是调用 Zygote 来 fork( ) 一个新的进程,并且在最后会调用 ActivityThread 的 main () 方法。ActivityManagerService 所在的进程和 Zygote 所在的进程通过 Socket 通信,ZygoteInit 中循环侦听 Socket 连接:
// 代码摘录
// ZygoteInit.java ---- 733
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*
* @throws MethodAndArgsCaller in a child process when a main() should
* be executed.
*/
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) {
int index;
/*
* Call gc() before we block in select().
* It's work that has to be done anyway, and it's better
* to avoid making every child do it. It will also
* madvise() any free memory as a side-effect.
*
* Don't call it every time, because walking the entire
* heap is a lot of overhead to free a few hundred bytes.
*/
if (loopCount <= 0) {
gc();
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
}
try {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDescriptor());
} else {
boolean done;
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
可发现:
一旦建立 ZygoteConnection 即调用 runOnce( )
//代码摘录:
//ZygoteConnection.java ---- 142
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
//...
checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
//...
try {
if (pid == 0) {
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// should never get here, the child is expected to either
// throw ZygoteInit.MethodAndArgsCaller or exec().
return true;
} else {
// in parent...pid of < 0 means failure
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
//...
}
我们来看看 forkAndSpecialize ( )
//代码摘录:
//Zygote.java ---- 87
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir) {
long startTime = SystemClock.elapsedRealtime();
VM_HOOKS.preFork();
checkTime(startTime, "Zygote.preFork");
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
instructionSet, appDataDir);
checkTime(startTime, "Zygote.nativeForkAndSpecialize");
VM_HOOKS.postForkCommon();
checkTime(startTime, "Zygote.postForkCommon");
return pid;
}
最终会去 fork( ) 进程,在子进程 (即 App 进程) 中执行 handleChildProc ( ) 方法
//代码摘录:
//ZygoteConnection.java ---- 855
/**
* Handles post-fork setup of child proc, closing sockets as appropriate,
* reopen stdio as appropriate, and ultimately throwing MethodAndArgsCaller
* if successful or returning if failed.
*
* @param parsedArgs non-null; zygote args
* @param descriptors null-ok; new file descriptors for stdio if available.
* @param pipeFd null-ok; pipe for communication back to Zygote.
* @param newStderr null-ok; stream to use for stderr until stdio
* is reopened.
*
* @throws ZygoteInit.MethodAndArgsCaller on success to
* trampoline to code that invokes static main.
*/
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
/**
* By the time we get here, the native code has closed the two actual Zygote
* socket connections, and substituted /dev/null in their place. The LocalSocket
* objects still need to be closed properly.
*/
closeSocket();
ZygoteInit.closeServerSocket();
if (descriptors != null) {
try {
ZygoteInit.reopenStdio(descriptors[0],
descriptors[1], descriptors[2]);
for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
newStderr = System.err;
} catch (IOException ex) {
Log.e(TAG, "Error reopening stdio", ex);
}
}
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.runtimeInit) {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
pipeFd, parsedArgs.remainingArgs);
} else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
} else {
String className;
try {
className = parsedArgs.remainingArgs[0];
} catch (ArrayIndexOutOfBoundsException ex) {
logAndPrintError(newStderr,
"Missing required class name argument", null);
return;
}
String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1];
System.arraycopy(parsedArgs.remainingArgs, 1,
mainArgs, 0, mainArgs.length);
if (parsedArgs.invokeWith != null) {
WrapperInit.execStandalone(parsedArgs.invokeWith,
parsedArgs.classpath, className, mainArgs);
} else {
ClassLoader cloader;
if (parsedArgs.classpath != null) {
cloader = new PathClassLoader(parsedArgs.classpath,
ClassLoader.getSystemClassLoader());
} else {
cloader = ClassLoader.getSystemClassLoader();
}
try {
ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
} catch (RuntimeException ex) {
logAndPrintError(newStderr, "Error starting.", ex);
}
}
}
}
注意到后面调用了 ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
本处即调用 ActivityThread 的 main () 方法
//代码摘录:
//ActivityThread.java ---- 5184
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
//初始化当前UserID
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
// Make sure TrustedCertificateStore looks in the right place for CA certificates
//设置当前用户CA证书的保存位置
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
//设置进程名
Process.setArgV0("<pre-initialized>");
//为主进程创建Looper
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
//发出创建ActivityThread的消息
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
//主线程进入无限循环状态,等待接收消息
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
从这里开始,准备主线程的消息队列,并为 App 创建并配置一个 ActivityThread, 再通过 thread.attach ( ) 将 ActivityThead, ApplicationThread 与 ActivityManagerService 关联起来。
ActivityThread 随后依次调用 Looper.prepareLoop () 和 Looper.loop () 来开启消息循环
ActivityManagerService 通过 Binder 通知 ActivityThread 进行 App 中主线程的调度工作。
ActivityThread main( )逻辑如下:
大佬原图,可点击查看大图(ps:转自 3分钟看懂 Activity 启动流程)
参考鸣谢
Android 应用的真正入口是哪里?Seasoninthesun - 回答(强烈推荐)
Android系统架构开篇(强烈推荐)
3 分钟看懂 Activity 启动流程(强烈推荐)
Android 应用程序进程启动过程(强烈推荐)
资源下载
链接 提取码: b2cg