注册

Android知识点之Service(三)

(3)、异进程服务启动绑定流程

(1)和(2)可以知道,无论是启动服务还是绑定服务,最终是通过SystemServer进程中的ActiveServices对象的bringUpServiceLocked方法来执行,bringUpServiceLocked方法是进程判断与启动新进程的入口,当在应用的AndroidManifest.xml文件中Service设置为新进程执行,那么就会在bringUpServiceLocked方法中启动一个新的进程


a、SystemServer进程与Zygote进程通信流程

android应用层次的进程都是通过Zygote进程去卵化启动的,Service进程也是一样
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java


private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
····
//启动一个新的进程
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {
·····
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
····
return null;
}
复制代码

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java


final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
//mProcessList是一个ProcessList对象
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
keepIfLarge, null /* ABI override */, null /* entryPoint */,
null /* entryPointArgs */, null /* crashHandler */);
}
复制代码

frameworks/base/services/core/java/com/android/server/am/ProcessList.java


boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
boolean mountExtStorageFull, String abiOverride) {
····
//新进程启动的入口类,即是android.app.ActivityThread类的main方法
final String entryPoint = "android.app.ActivityThread";
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
instructionSet, invokeWith, startTime);
····
}

boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
····
final Process.ProcessStartResult startResult = startProcess(hostingRecord,
entryPoint, app,
uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
requiredAbi, instructionSet, invokeWith, startTime);
····
}


private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
int mountExternal, String seInfo, String requiredAbi, String instructionSet,
String invokeWith, long startTime) {
····
//SystemServer进程与Zygote进程通信是通过LocalSocket和LocalServerSocket进行通信,并非是Binder
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
····
return startResult;
····
}
复制代码

SystemServer进程与Zygote进程通信是通过LocalSocket和LocalServerSocket进行通信,并非是Binder,最终Zygote进程启动好新进程则会调用android.app.ActivityThread类的main方法,此时新进程启动完成


b、Zygote进程与新启动进程通信流程

新进程启动完会调用android.app.ActivityThread类的main方法
frameworks/base/core/java/android/app/ActivityThread.java


public static void main(String[] args) {
····
Looper.prepareMainLooper();
····
//创建一个ActivityThread,同时创建一个ApplicationThread的binder对象,用于跨进程通讯
ActivityThread thread = new ActivityThread();
//启动一个Application
thread.attach(false, startSeq);
····
Looper.loop();
····
}

private void attach(boolean system, long startSeq) {
····
final IActivityManager mgr = ActivityManager.getService();
try {
//跨进程调用AMS的attachApplication方法
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
····
}
复制代码

c、新启动进程与SystemServer进程(AMS)通信流程

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java


public final void attachApplication(IApplicationThread thread, long startSeq) {
····
synchronized (this) {
····
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
····
}
}

private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
·····
if (!badApp) {
try {
//启动服务,mServices为ActiveServices对象
didSomething |= mServices.attachApplicationLocked(app, processName);
·····
} catch (Exception e) {
·····
}
}
·····
return true;
}
复制代码

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java


boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
····
//此时进程已经启动,启动服务
realStartServiceLocked(sr, proc, sr.createdFromFg);
····
return didSomething;
}
复制代码

realStartServiceLocked方法的执行源码流程,可以参考(1)和(2),realStartServiceLocked方法中主要是启动ANR超时任务监测,以及是启动服务还是绑定服务的生命周期调用分配,这样两种不同形式的服务独自执行各自的生命周期


(4)、服务启动超时(ANR)监测处理流程流程


Service生命周期的执行,最终通过ActiveServices对象的realStartServiceLocked方法去调配,此时也是加入了超时任务监测(ANR)


a、启动Server超时任务

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java


private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
····
//启动超时定时ANR任务
bumpServiceExecutingLocked(r, execInFg, "create");
//接下来就是启动Server一系列操作,或者计算在Server中的onCreate()生命周期方法是否有耗时操作
····
try {
····
//进入应用进程启动,移除超时定时ANR任务操作也在此处
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.getReportedProcState());
····
//完成启动
created = true;
} catch (DeadObjectException e) {
····
}
···
}

private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
····
//开启超时任务
scheduleServiceTimeoutLocked(r.app);
···
}

void scheduleServiceTimeoutLocked(ProcessRecord proc) {
····
//通过Handler发送一个定时任务,当时间到没有移除这个任务,则认为是超时
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc;
mAm.mHandler.sendMessageDelayed(msg,
proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
}
复制代码

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java


final class MainHandler extends Handler {
····
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
····
//当Server超时的时候,回调到此处,准备弹ANR窗口
case SERVICE_TIMEOUT_MSG: {
mServices.serviceTimeout((ProcessRecord)msg.obj);
} break;
···
//当内容提供者超时,回调到此处,准备弹ANR窗口
case CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG: {
ProcessRecord app = (ProcessRecord)msg.obj;
synchronized (ActivityManagerService.this) {
processContentProviderPublishTimedOutLocked(app);
}
} break;
····
}
}
}
复制代码

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java


//前台server超时时间
static final int SERVICE_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
//后台server超时时间
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;

void serviceTimeout(ProcessRecord proc) {
String anrMessage = null;
synchronized(mAm) {
····
if (timeout != null && mAm.mProcessList.mLruProcesses.contains(proc)) {
····
//超时后来到此处anrMessage赋值
anrMessage = "executing service " + timeout.shortInstanceName;
} else {
//初始化定时,设定超时时间
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc;
mAm.mHandler.sendMessageAtTime(msg, proc.execServicesFg
? (nextTime+SERVICE_TIMEOUT) : (nextTime + SERVICE_BACKGROUND_TIMEOUT));
}
}
//当时间达到了server超时时间,则进入此处
if (anrMessage != null) {
//最终通过此处处理ANR
mAm.mAnrHelper.appNotResponding(proc, anrMessage);
}
}
复制代码

frameworks/base/services/core/java/com/android/server/am/AnrHelper.java


class AnrHelper {
private static class AnrRecord {
····
final ProcessRecord mApp;
····
void appNotResponding(boolean onlyDumpSelf) {
//通过一系列操作最终调用ProcessRecord对象的appNotResponding方法
mApp.appNotResponding(mActivityShortComponentName, mAppInfo,
mParentShortComponentName, mParentProcess, mAboveSystem, mAnnotation,
onlyDumpSelf);
}
}
}
复制代码

frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java


void appNotResponding(String activityShortComponentName, ApplicationInfo aInfo,
String parentShortComponentName, WindowProcessController parentProcess,
boolean aboveSystem, String annotation, boolean onlyDumpSelf) {
····
synchronized (mService) {
····
//mService对应的是ActivityManagerService对象
if (mService.mUiHandler != null) {
// Bring up the infamous App Not Responding dialog
Message msg = Message.obtain();
msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
msg.obj = new AppNotRespondingDialog.Data(this, aInfo, aboveSystem);
//向UiHandler发送一条数据
mService.mUiHandler.sendMessage(msg);
}
}
}
复制代码

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java


final class UiHandler extends Handler {
···
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
····
case SHOW_NOT_RESPONDING_UI_MSG: {
//同Handler机制回调到此处弹起ANR窗口
mAppErrors.handleShowAnrUi(msg);
ensureBootCompleted();
} break;
·····
}
}
}
复制代码

b、移除Server超时任务

frameworks/base/core/java/android/app/ActivityThread.java


public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
//向主线程发送一条消息
sendMessage(H.CREATE_SERVICE, s);
}

class H extends Handler {
public void handleMessage(Message msg) {
····
switch (msg.what) {
····
case CREATE_SERVICE:
····
//主线程处理Server启动
handleCreateService((CreateServiceData) msg.obj);
····
break;
····
}
}
}

private void handleCreateService(CreateServiceData data) {
····
try {
····
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//调用Server生命周期方法
service.onCreate();
···
try {
//调用AMS的serviceDoneExecuting方法移除Server超时监测任务
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
····
}
}
复制代码

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java


public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
synchronized(this) {
//mServices对应的是ActiveServices对象,移除超时任务
mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
}
}
复制代码

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java


void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
····
if (r != null) {
····
//移除超时任务
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
····
}
···
}

private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
boolean finishing) {
····
if (r.executeNesting <= 0) {
if (r.app != null) {
···
if (r.app.executingServices.size() == 0) {
····
//向MainHandler移除SERVICE_TIMEOUT_MSG的超时任务
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
}
····
}
····
}
}
复制代码


作者:小狼人爱吃萝卜
链接:https://juejin.cn/post/7008699606372450341
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册