Android应用程序的载体是APK文件,它是一个组件和资源的容器。APK文件和我们常见的执行文件还是有区别的:每个执行文件都是运行在一个进程中,但是APK可能运行在一个进程中,也可能和其他APK运行在一个进程中。Android的设计理念中弱化进程的存在,而是以组件的概念代替。
但是Android毕竟是建立在Linux,基础的环境还是由进程组成。
一、应用进程的组成
Android应用的核心类是ActivityThread类,mActivityies,mServices、mProviderMap3个变量的类型都是ArrayMap,保存有了应用中所有的Activity、Service、ContentProvider。没有BroadcastReceiver,应用广播的生命周期比较短,属于调用一次运行一次的类型。
mInitialApplication变量是一个Application对象,应用中Application对象只有一个。如果每个应用从Application类派生了自己的类,mInitialApplication对象将是应用中自定义的实例对象。
ApplicationThread类型的变量mAppThread是一个Binder实体对象,AMS通过它来调用应用的接口。
mPackages和mResourcePackages保存的是应用apk包的信息。这里有两个变量的原因是appliction属性中,有hascode属性。如果不包含代码,只有资源文件的保存在mResourcePackages相反保存在mPackages。
1.1 ApplicationThread
ApplicationThread是ActivityThread的一个嵌套类。它不是一个Thread,是一个Binder的服务类。AMS及时通过Binder调用ApplicationThread里面的接口。
ApplicationThread继承ApplicationThreadNative,而ApplicationThreadNative又是继承Binder。对应的客户端的Binder是IApplicationThread,是在AMS中。
比如说在ApplicationThread中调用scheduleResumeActivity,最后会发送一个消息。
-
public final void scheduleResumeActivity(IBinder token, int processState,
-
boolean isForward, Bundle resumeArgs) {
-
updateProcessState(processState,
false);
-
sendMessage(H.RESUME_ACTIVITY, token, isForward ?
1 :
0);
-
}
最终消息处理会去调用handleResumeActivity函数。
-
case RESUME_ACTIVITY:
-
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"activityResume");
-
handleResumeActivity((IBinder) msg.obj,
true, msg.arg1 !=
0,
true);
-
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
break;
知道这流程后,我们就知道AMS调用schedule。。。函数,最总都睡调到handle。。。函数。
1.2 Context
Context的字母意义是上下文环境。应用上层代码都是通过Context类提供的接口来操作Android的4大组件和资源的。
Context的实现类是ContextWrapper类,它其中有一个成员mBase,是ContextImpl类,这是一个典型的代理模式,好多功能都在ContextImpl实现。
而且为了方便,Service、Application、Activity都是ContextWrapper的子类。
二、AMS服务
AMS是AndroidFramework的核心,管理着四大组件。
AMS是Binder服务,但是不是通过AIDL自动生成的。AMS从ActivityManagerNative类派生,这个类实现了IActivityManager的接口。然后还有一个内部类ActivityManagerProxy,这个是应用ActivityManager调用过来的。相当于AMS的客户端Binder
一般ActivityManager中都是通过下面的方法,来获取AMS的Binder客户端
ActivityManagerNative.getDefault()
-
private
static
final Singleton<IActivityManager> gDefault =
new Singleton<IActivityManager>() {
-
protected IActivityManager create() {
-
IBinder b = ServiceManager.getService(
"activity");
-
if (
false) {
-
Log.v(
"ActivityManager",
"default service binder = " + b);
-
}
-
IActivityManager am = asInterface(b);
-
if (
false) {
-
Log.v(
"ActivityManager",
"default service = " + am);
-
}
-
return am;
-
}
-
};
2.1 AMS的初始化
AMS运行在SystemServer进程中:
mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
AMS的构造函数就是初始化一些成员变量,然后建一个消息处理handler等,这边就不分析了。
SystemServer中创建了AMS后,调用了其setSystemProcess
-
public void setSystemProcess() {
-
try {
-
ServiceManager.addService(Context.ACTIVITY_SERVICE,
this,
true);
//注册一些Service
-
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
-
ServiceManager.addService(
"meminfo",
new MemBinder(
this));
-
ServiceManager.addService(
"gfxinfo",
new GraphicsBinder(
this));
-
ServiceManager.addService(
"dbinfo",
new DbBinder(
this));
-
if (MONITOR_CPU_USAGE) {
-
ServiceManager.addService(
"cpuinfo",
new CpuBinder(
this));
-
}
-
ServiceManager.addService(
"permission",
new PermissionController(
this));
-
-
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
-
"android", STOCK_PM_FLAGS);
-
mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
-
-
synchronized (
this) {
-
ProcessRecord app = newProcessRecordLocked(info, info.processName,
false,
0);
//将SystemServer进程加入管理
-
app.persistent =
true;
-
app.pid = MY_PID;
-
app.maxAdj = ProcessList.SYSTEM_ADJ;
-
app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
-
mProcessNames.put(app.processName, app.uid, app);
-
synchronized (mPidsSelfLocked) {
-
mPidsSelfLocked.put(app.pid, app);
-
}
-
updateLruProcessLocked(app,
false,
null);
//这两个方法比较关键后续会详细介绍
-
updateOomAdjLocked();
-
}
-
}
catch (PackageManager.NameNotFoundException e) {
-
throw
new RuntimeException(
-
"Unable to find android system package", e);
-
}
-
}
在这个函数中,将一些Service注册到ServiceManager,并且最后把SystemServer加入到process的管理中。
2.2 systemReady方法
SystemServer启动完所有服务后,将调用AMS的systemReady方法。systemReady方法比较长,我们就挑一些重点说。
-
ArrayList<ProcessRecord> procsToKill =
null;
-
synchronized(mPidsSelfLocked) {
-
for (
int i=mPidsSelfLocked.size()-
1; i>=
0; i--) {
-
ProcessRecord proc = mPidsSelfLocked.valueAt(i);
-
if (!isAllowedWhileBooting(proc.info)){
//检查进程是否有persistent标志
-
if (procsToKill ==
null) {
-
procsToKill =
new ArrayList<ProcessRecord>();
-
}
-
procsToKill.add(proc);
-
}
-
}
-
}
-
-
synchronized(
this) {
-
if (procsToKill !=
null) {
-
for (
int i=procsToKill.size()-
1; i>=
0; i--) {
-
ProcessRecord proc = procsToKill.get(i);
-
Slog.i(TAG,
"Removing system update proc: " + proc);
-
removeProcessLocked(proc,
true,
false,
"system update done");
-
}
-
}
-
-
// Now that we have cleaned up any update processes, we
-
// are ready to start launching real processes and know that
-
// we won't trample on them any more.
-
mProcessesReady =
true;
-
}
这段代码作用是找到已经启动的应用进程,然后杀掉它们。目的是为了在启动HOME前准备一个干净的环境。但是有一种进程不用退出,isAllowWhileBooting方法会判断进程是否带有FLAG_PERSISTENT标记,如果有就不用退出了。因为有这个标记还要启动它们的,这里就留下不清理了。
-
synchronized (
this) {
-
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
//不在测试模式
-
try {
-
List apps = AppGlobals.getPackageManager().
-
getPersistentApplications(STOCK_PM_FLAGS);
//检查系统中带有FLAG_PERSISTENT标志的应用
-
if (apps !=
null) {
-
int N = apps.size();
-
int i;
-
for (i=
0; i<N; i++) {
-
ApplicationInfo info
-
= (ApplicationInfo)apps.get(i);
-
if (info !=
null &&
-
!info.packageName.equals(
"android")) {
-
addAppLocked(info,
false,
null
/* ABI override */);
//启动应用
-
}
-
}
-
}
-
}
catch (RemoteException ex) {
-
// pm is in same process, this will never happen.
-
}
-
}
-
-
// Start up initial activity.
-
mBooting =
true;
-
startHomeActivityLocked(mCurrentUserId,
"systemReady");
//启动HOME应用
-
............
-
}
-
}
这段代码主要启动带有FLAG_PERSISTENT标志的应用,然后启动HOME应用,启动后会发出ACTION_BOOT_COMPLETED广播。
从systemReady方法可以知道:
1.系统应用如果响应ACTION_PRE_BOOT_COMPLETED,可以在升级后得到通知。
2.如果系统应用希望在HOME应用启动前启动,可以加入FLAG_PERSISTENT标志。接受Intent的ACTION_BOOT_COMPLETED的应用只能在HOME启动后启动。
2.3 Process管理
虽然Android的应用开发中,不再强调进程的概念。但是在AMS中,还必须管理和调度进程。AMS对进程的管理,主要在两个方面:
一、动态地调整进程在mLruProcess列表中的位置。
二、调整进程的oom_adj值。
这两项调整和系统进行自动内存回收有关,当内存不足时,系统会关闭一些进程来释放内存。系统就是根据oom_adj值来杀进程。值越大越可能被杀。
下面我们看下如何启动进程
在上面一节中,把带有FLAG_PERSISTENT标志的应用放进addAppLocked就可以启动应用,我们来看下这个函数:
-
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
-
String abiOverride) {
-
ProcessRecord app;
-
if (!isolated) {
//该值为true,表示要启动一个新的进程
-
app = getProcessRecordLocked(info.processName, info.uid,
true);
-
}
else {
-
app =
null;
-
}
-
-
if (app ==
null) {
-
app = newProcessRecordLocked(info,
null, isolated,
0);
//创建一个ProcessRecord对象
-
mProcessNames.put(info.processName, app.uid, app);
-
if (isolated) {
-
mIsolatedProcesses.put(app.uid, app);
-
}
-
updateLruProcessLocked(app,
false,
null);
-
updateOomAdjLocked();
-
}
-
-
// This package really, really can not be stopped.
-
try {
-
AppGlobals.getPackageManager().setPackageStoppedState(
-
info.packageName,
false, UserHandle.getUserId(app.uid));
-
}
catch (RemoteException e) {
-
}
catch (IllegalArgumentException e) {
-
Slog.w(TAG,
"Failed trying to unstop package "
-
+ info.packageName +
": " + e);
-
}
-
-
if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
-
== (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
-
app.persistent =
true;
-
app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
-
}
-
if (app.thread ==
null && mPersistentStartingProcesses.indexOf(app) <
0) {
-
mPersistentStartingProcesses.add(app);
-
startProcessLocked(app,
"added application", app.processName, abiOverride,
//启动进程
-
null
/* entryPoint */,
null
/* entryPointArgs */);
-
}
-
-
return app;
-
}
这个方法会根据isolated来决定是否要启动一个进程,getProcessRecordLocked方法会在当前运行的进程列表中查找进程。updateLruProcessLocked和updateOomAdjLocked方法后面介绍。下面再来看看startProcessLocked方法:
-
private final void startProcessLocked(ProcessRecord app, String hostingType,
-
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
-
.......
-
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!");
-
.......
-
synchronized (mPidsSelfLocked) {
-
this.mPidsSelfLocked.put(startResult.pid, app);
-
if (isActivityProcess) {
-
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
-
msg.obj = app;
-
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
-
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
-
}
-
}
最后会调用Process.start方法启动一个进程,启动进程后,会发送一个PROC_START_TIMEOUT_MSG消息,这个消息用来防止进程启动超时。如果超时弹出ANR对话框。
2.4 调整进程中的位置
AMS中代码经常调用updateLruProcessLocked来调整进程在mLruProcess列表的位置。在这个列表中,最近活动过得进程总是位于最高位置,同时拥有Activity的进程位置总是高于只有Service的进程位置。
2.5 调整进程的oom_adj值
AMS中调整oom_adj值的函数是updateOomAdjLocked,下面选了一段代码:
-
for (
int i=N-
1; i>=
0; i--) {
//从后面遍历mLruProcesses列表
-
ProcessRecord app = mLruProcesses.get(i);
-
if (!app.killedByAm && app.thread !=
null) {
-
app.procStateChanged =
false;
-
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP,
true, now);
-
-
// If we haven't yet assigned the final cached adj
-
// to the process, do that now.
-
if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
-
switch (app.curProcState) {
-
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
-
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
-
// This process is a cached process holding activities...
-
// assign it the next cached value for that type, and then
-
// step that cached level.
-
app.curRawAdj = curCachedAdj;
-
app.curAdj = app.modifyRawOomAdj(curCachedAdj);
-
if (DEBUG_LRU &&
false) Slog.d(TAG,
"Assigning activity LRU #" + i
-
+
" adj: " + app.curAdj +
" (curCachedAdj=" + curCachedAdj
-
+
")");
-
if (curCachedAdj != nextCachedAdj) {
-
stepCached++;
-
if (stepCached >= cachedFactor) {
-
stepCached =
0;
-
curCachedAdj = nextCachedAdj;
-
nextCachedAdj +=
2;
//mLruProcesses列表越前面adj的值越大
-
if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
-
nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
-
}
-
}
-
}
-
break;
从上面的代码看出mLruProcesses列表越前面adj的值越大,也就越有可能被kill掉。