前言
我们都知道ActivityThread这个类是app程序的入口,本文为了证明这一点,因Launcher亦是一个Activity,且我们之前也对Launcher启动流程做过一定的分析,SO,本文以它为支点,展开对于ActivityThread的学习。
本文的目的只分析到main方法的调用处,而main方法中是如何进行初始化的将另开一篇,另外,有错误请直接指出。
代码分析
frameworks\base\services\java\com\android\server\am\ActivityStack.java#startActivityLocked()
注意这里调用的是11个参数的startActivityLocked方法。
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType,
Uri[] grantedUriPermissions,
int grantedMode, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, boolean onlyIfNeeded,
boolean componentSpecified) {
......
return startActivityUncheckedLocked(r, sourceRecord,
grantedUriPermissions, grantedMode, onlyIfNeeded, true);
}
frameworks\base\services\java\com\android\server\am\ActivityStack.java#startActivityUncheckedLocked()
这个函数尾部注释6处调用了3个参数的startActivityLocked方法。
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, Uri[] grantedUriPermissions,
int grantedMode, boolean onlyIfNeeded, boolean doResume) {
......
if (r.packageName != null) {//逻辑1
// If the activity being launched is the same as the one currently
// at the top, then we need to check if it should only be launched
// once.
ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);//注释1
if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity)) {
if (top.app != null && top.app.thread != null) {
if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
// For paranoia, make sure we have correctly
// resumed the top activity.
if (doResume) {
resumeTopActivityLocked(null);//注释2
}
if (onlyIfNeeded) {
// We don't need to start a new activity, and
// the client said not to do anything if that
// is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
top.deliverNewIntentLocked(callingUid, r.intent);//注释3
return START_DELIVERED_TO_TOP;
}
}
}
}
} else {
if (r.resultTo != null) {
sendActivityResultLocked(-1,
r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);//注释4
}
return START_CLASS_NOT_FOUND;
}
boolean newTask = false;
// Should this be considered a new task?
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
// todo: should do better management of integers.
......
} else if (sourceRecord != null) {
if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
// In this case, we are adding the activity to an existing
// task, but the caller has asked to clear that task if the
// activity is already running.
......
} else if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
// In this case, we are launching an activity in our own task
// that may already be running somewhere in the history, and
// we want to shuffle it to the front of the stack if so.
......
}
// An existing activity is starting this new activity, so we want
// to keep the new one in the same task as the one that is starting
// it.
......
} else {
// This not being started from an existing activity, and not part
// of a new task... just put it in the top task, though these days
// this case should never happen.
......
}
......
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
intent, r.getUriPermissionsLocked());
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
}
logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);//注释5
startActivityLocked(r, newTask, doResume);//注释6
return START_SUCCESS;
}
frameworks\base\services\java\com\android\server\am\ActivityStack.java#startActivityLocked()
注意这里调用的是3个参数的startActivityLocked方法。并在注释1处调到了resumeTopActivityLocked方法。
private final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume) {
......
if (!newTask) {
// If starting in an existing task, find where that is...
......
for (int i = NH-1; i >= 0; i--) {
ActivityRecord p = (ActivityRecord)mHistory.get(i);
if (p.finishing) {
continue;
}
if (p.task == r.task) {
// Here it is! Now, if this is not yet visible to the
// user, then just add it without starting; it will
// get started when the user navigates back to it.
......
break;
}
if (p.fullscreen) {
startIt = false;
}
}
}
// Place a new activity at top of stack, so it is next to interact
// with the user.
......
// If we are not placing the new activity frontmost, we do not want
// to deliver the onUserLeaving callback to the actual frontmost
// activity
......
// Slot the activity into the history stack and proceed
......
if (NH > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
// not currently running.
......
if (newTask) {
// Even though this activity is starting fresh, we still need
// to reset it to make sure we apply affinities to move any
// existing activities from other tasks in to it.
// If the caller has requested that the target task be
// reset, then do so.
......
}
if (SHOW_APP_STARTING_PREVIEW && doShow) {
// Figure out if we are transitioning from another activity that is
// "has the same starting icon" as the next one. This allows the
// window manager to keep the previous window it had previously
// created, if it still had one.
ActivityRecord prev = mResumedActivity;
if (prev != null) {
// We don't want to reuse the previous starting preview if:
// (1) The current activity is in a different task.
......
// (2) The current activity is already displayed.
......
}
mService.mWindowManager.setAppStartingWindow(
r, r.packageName, r.theme, r.nonLocalizedLabel,
r.labelRes, r.icon, prev, showStartingIcon);
}
} else {
// If this is the first activity, don't do any fancy animations,
// because there is nothing for it to animate on top of.
mService.mWindowManager.addAppToken(addPos, r, r.task.taskId,
r.info.screenOrientation, r.fullscreen);
}
if (VALIDATE_TOKENS) {
mService.mWindowManager.validateAppTokens(mHistory);
}
if (doResume) {
resumeTopActivityLocked(null);//注释1
}
}
frameworks\base\services\java\com\android\server\am\ActivityStack.java#resumeTopActivityLocked()
final boolean resumeTopActivityLocked(ActivityRecord prev) {
// Find the first activity that is not finishing.
......
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
......
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
if (mMainStack) {
return mService.startHomeActivityLocked();
}
}
......
if (next.app != null && next.app.thread != null) {
......
} else {
// Whoops, need to restart this activity!
// resume一个新的activity(还未跟进程关联的Activity),
// 进程可能还没起来。调用startSpecificActivityLocked(),
// 在这个函数中会寻找目标进程,如果目标进程存在,
// 那么就直接调用realStartActivityLocked(),
// 如果目标进程不存在那么就先startProcess;
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
mService.mWindowManager.setAppStartingWindow(
next, next.packageName, next.theme,
next.nonLocalizedLabel,
next.labelRes, next.icon, null, true);
}
if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
}
startSpecificActivityLocked(next, true, true);
}
return true;
}
重点关注方法尾部,它去掉用了startSpecificActivityLocked方法。
frameworks\base\services\java\com\android\server\am\ActivityStack.java#startSpecificActivityLocked
在这个函数中会寻找目标进程,如果目标进程存在,那么就直接调用realStartActivityLocked(),如果目标进程不存在那么就先startProcess。
private final void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
// 寻找进程操作
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid);
if (r.launchTime == 0) {
r.launchTime = SystemClock.uptimeMillis();
if (mInitialStartTime == 0) {
mInitialStartTime = r.launchTime;
}
} else if (mInitialStartTime == 0) {
mInitialStartTime = SystemClock.uptimeMillis();
}
if (app != null && app.thread != null) {
try {
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
//如果目标进程不存在那么就先startProcess,Ams的方法
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false);
}
frameworks\base\services\java\com\android\server\am\ActivityManagerService.java#startProcessLocked(7参)
注意它调用的是7个参数的startProcessLocked方法,然后内部又调用了3个参数的startProcessLocked方法。
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
ProcessRecord app = getProcessRecordLocked(processName, info.uid);
// We don't have to do anything more if:
// (1) There is an existing application record; and
// (2) The caller doesn't think it is dead, OR there is no thread
// object attached to it so we know it couldn't have crashed; and
// (3) There is a pid assigned to it, so it is either starting or
// already running.
......
startProcessLocked(app, hostingType, hostingNameStr);
return (app.pid != 0) ? app : null;
}
frameworks\base\services\java\com\android\server\am\ActivityManagerService.java#startProcessLocked(3参)
在注释1处调用了Process.start方法,并传入了参数”android.app.ActivityThread”,那么我们进入Process.start方法瞧瞧。
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
......
try {
......
int pid = Process.start("android.app.ActivityThread",
mSimpleProcessManagement ? app.processName : null, uid, uid,
gids, debugFlags, null);//注释1
BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
synchronized (bs) {
if (bs.isOnBattery()) {
app.batteryStats.incStartsLocked();
}
}
......
StringBuilder buf = mStringBuilder;
buf.setLength(0);
buf.append("Start proc ");
buf.append(app.processName);
buf.append(" for ");
buf.append(hostingType);
if (hostingNameStr != null) {
buf.append(" ");
buf.append(hostingNameStr);
}
buf.append(": pid=");
buf.append(pid);
buf.append(" uid=");
buf.append(uid);
buf.append(" gids={");
if (gids != null) {
for (int gi=0; gi<gids.length; gi++) {
if (gi != 0) buf.append(", ");
buf.append(gids[gi]);
}
}
buf.append("}");
Slog.i(TAG, buf.toString());
if (pid == 0 || pid == MY_PID) {
// Processes are being emulated with threads.
app.pid = MY_PID;
app.removed = false;
mStartingProcesses.add(app);
} else if (pid > 0) {
app.pid = pid;
app.removed = false;
synchronized (mPidsSelfLocked) {
this.mPidsSelfLocked.put(pid, app);
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
}
} else {
app.pid = 0;
RuntimeException e = new RuntimeException(
"Failure starting process " + app.processName
+ ": returned pid=" + pid);
Slog.e(TAG, e.getMessage(), e);
}
} catch (RuntimeException e) {
// XXX do better error recovery.
app.pid = 0;
Slog.e(TAG, "Failure starting process " + app.processName, e);
}
}
frameworks\base\core\java\android\os\Process.java#start()
注释1处直接去调用了invokeMain方法。
/**
* Start a new process.
*
* <p>If processes are enabled, a new process is created and the
* static main() function of a <var>processClass</var> is executed there.
* The process will continue running after this function returns.
*
* <p>If processes are not enabled, a new thread in the caller's
* process is created and main() of <var>processClass</var> called there.
*
* <p>The niceName parameter, if not an empty string, is a custom name to
* give to the process instead of using processClass. This allows you to
* make easily identifyable processes even if you are using the same base
* <var>processClass</var> to start them.
*
* @param processClass The class to use as the process's main entry
* point.
* @param niceName A more readable name to use for the process.
* @param uid The user-id under which the process will run.
* @param gid The group-id under which the process will run.
* @param gids Additional group-ids associated with the process.
* @param enableDebugger True if debugging should be enabled for this process.
* @param zygoteArgs Additional arguments to supply to the zygote process.
*
* @return int If > 0 the pid of the new process; if 0 the process is
* being emulated by a thread
* @throws RuntimeException on fatal start failure
*
* {@hide}
*/
public static final int start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags,
String[] zygoteArgs){
if (supportsProcesses()) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
} else {
// Running in single-process mode
Runnable runnable = new Runnable() {
public void run() {
//注释1:这里的processClass时机上就是ActivityThread方法
Process.invokeStaticMain(processClass);
}
};
// Thread constructors must not be called with null names (see spec).
if (niceName != null) {
new Thread(runnable, niceName).start();
} else {
new Thread(runnable).start();
}
return 0;
}
}
frameworks\base\core\java\android\os\Process.java#invokeStaticMain()
至此ActivityThread的main方法被执行了。
private static void invokeStaticMain(String className) {
Class cl;
Object args[] = new Object[1];
args[0] = new String[0]; //this is argv
try {
cl = Class.forName(className);
cl.getMethod("main", new Class[] { String[].class })
.invoke(null, args);
} catch (Exception ex) {
// can be: ClassNotFoundException,
// NoSuchMethodException, SecurityException,
// IllegalAccessException, IllegalArgumentException
// InvocationTargetException
// or uncaught exception from main()
Log.e(LOG_TAG, "Exception invoking static main on "
+ className, ex);
throw new RuntimeException(ex);
}
}
总结
当Zygote启动时,会分裂出system_server并进行不断地ipc轮询,system_server会创建AMS等服务。当你在桌面点击一个app图标时,并且这个app在内存中是无实例的。ams会通知system_server,由system_server通知Zygote去fork出子进程并执行ActivityThread的main方法。main方法的调用是在子进程的主线程中。