接上一篇《Android 6.0 启动startService()源码分析(1)》,依旧分析startService()启动过程。由于篇幅过长,分开记录,便于阅读。
10.4 ActivityManagerProxy.attachApplication
在上一篇中的代码中
【获取的又是ActivityManagerProxy对象】
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread); 【 10.4 ActivityManagerProxy.attachApplication 】但最终还是跑到了ActivityManagerService中attachApplication中
} catch (RemoteException ex) {
// Ignore
}
根据上一篇分析
ActivityManagerNative.getDefault()获取的就是ActivityManagerProxy对象(过程可以看上一篇中的分析,此处省略)
我们看ActivityManagerProxy.attachApplication()
public void attachApplication(IApplicationThread app) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(app.asBinder());
【mRemote 就是Binder 此处发送ATTACH_APPLICATION_TRANSACTION出去,然后在ActivityManagerNative的onTransact】
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
经过mRemote.transac后,ATTACH_APPLICATION_TRANSACTION有传送到ActivityManagerNative的onTransact()中
ActivityManagerNative.onTransact()
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
......
case ATTACH_APPLICATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IApplicationThread app = ApplicationThreadNative.asInterface(
data.readStrongBinder());
if (app != null) {
【这里最终调用的是 10.5 ActivityManagerService.attachApplication() 】
attachApplication(app);
}
reply.writeNoException();
return true;
}
.....
}
10.5 ActivityManagerService.attachApplication()
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
【10.6 ActivityManagerService.attachApplicationLocked】
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
10.6 ActivityManagerService.attachApplicationLocked
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
if (app == null) {
Slog.w(TAG, "No pending application record for pid " + pid
+ " (IApplicationThread " + thread + "); dropping process");
EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
if (pid > 0 && pid != MY_PID) {
Process.killProcessQuiet(pid);
//TODO: killProcessGroup(app.info.uid, pid);
} else {
try {
thread.scheduleExit();
} catch (Exception e) {
// Ignore exceptions.
}
}
return false;
}
// If this application record is still attached to a previous
// process, clean it up now.
if (app.thread != null) {
handleAppDiedLocked(app, true, true);
}
......
// Find any services that should be running in this process...
if (!badApp) {
try {
【10.7 mServices.attachApplicationLocked 】
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
......
return true;
}
10.7 ActiveServices.attachApplicationLocked
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
boolean didSomething = false;
// Collect any services that are waiting for this process to come up.
if (mPendingServices.size() > 0) {
ServiceRecord sr = null;
try {
for (int i=0; i<mPendingServices.size(); i++) {
sr = mPendingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mPendingServices.remove(i);
i--;
【添加包名】
proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
mAm.mProcessStats);
【10.8 ActiveServices.realStartServiceLocked() 】
realStartServiceLocked(sr, proc, sr.createdFromFg);
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting service "
+ sr.shortName, e);
throw e;
}
}
// Also, if there are any services that are waiting to restart and
// would run in this process, now is a good time to start them. It would
// be weird to bring up the process but arbitrarily not let the services
// run at this point just because their restart time hasn't come up.
if (mRestartingServices.size() > 0) {
ServiceRecord sr = null;
for (int i=0; i<mRestartingServices.size(); i++) {
sr = mRestartingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mAm.mHandler.removeCallbacks(sr.restarter);
mAm.mHandler.post(sr.restarter);
}
}
return didSomething;
}
10.8 ActiveServices.realStartServiceLocked()
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
if (DEBUG_MU)
Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
+ ", ProcessRecord.uid = " + app.uid);
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
final boolean newService = app.services.add(r);
【10.9 ActiveServices.bumpServiceExecutingLocked 发送SERVICE_TIMEOUT_MSG用来判断是否ANR】
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
mAm.updateOomAdjLocked();
【这是服务的首次启动流程,先执行scheduleCreateService,其实到了本地端就是实例化服务类,然后调用了其onCreate方法 】
boolean created = false;
try {
if (LOG_SERVICE_START_STOP) {
String nameTerm;
int lastPeriod = r.shortName.lastIndexOf('.');
nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
EventLogTags.writeAmCreateService(
r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
}
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
【执行onCreate()方法 10.10 ActivityThread.scheduleCreateService】
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
} finally {
if (!created) {
// Keep the executeNesting count accurate.
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
// Cleanup.
if (newService) {
app.services.remove(r);
r.app = null;
}
// Retry.
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
// If the service is in the started state, and there are no
// pending arguments, then fake up one so its onStartCommand() will
// be called.
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null));
}
【11. 0 服务进入onStartCommand()】
sendServiceArgsLocked(r, execInFg, true);
if (r.delayed) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
if (r.delayedStop) {
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Applying delayed stop (from start): " + r);
stopServiceLocked(r);
}
}
}
10.9 ActiveServices.bumpServiceExecutingLocked 发送SERVICE_TIMEOUT_MSG用来判断是否ANR
没写完,由于最近忙,没有大块时间,后续补上,不好意思
2018月6月11日写,先发出来。
历史上的今天
暂无评论...
随机推荐
Ubuntu16安装openjdk-7
Ubuntu16.04 安装openjdk-7-jdksudo apt-get install openjdk-7-jre 或者sudo apt-get install openjdk-7-jdkUbuntu16.04的安装源已经默认没有openjdk7了,所以要自己手动添加仓库,如下:...
startActivity之进程启动
前言今天简单的记录一下App进程的启动过程。继之前startActivity的分析(《startActivity源码分析1》和《startActivity源码分析2》)中的进程启动是一带而过的,聪明的你会发现,进程启动的大部分跟《Zygote的启动之二ZygoteInit》重合了。正文回到...
Launcher根据包名启动应用
前言很多项目中Launcher是有可能自定义的,毕竟Android原生的Launcher比较庞大,有时候需要的需求很简单,自己重新写Launcher也比较容易维护。为啥要根据包名启动,因为一个应用可能存在多个Activity,当按Home键退出后,再次从Launcher界面点击需要回到之前展示...
萧红:饿
“列巴圈”挂在过道别人的门上,过道好象还没有天明,可是电灯已经熄了。夜间遗留下来睡朦朦的气息充塞在过道,茶房气喘着,抹着地板。我不愿醒得太早,可是已经醒了,同时再不能睡去。厕所房的电灯仍开着,和夜间一般昏黄,好象黎明还没有到来,可是“列巴圈”已经挂上别人家的门了!有的牛奶瓶也规规矩矩地等在别的房间...
Git tag 简单使用
前言打标签像其他版本控制系统(VCS)一样,Git可以给仓库历史中的某一个提交打上标签,以示重要。比较有代表性的是人们会使用这个功能来标记发布结点( v1.0 、 v2.0 等等)。在项目中,为了区分SOP的版本代码,常要求打标签。正文下面简单的介绍一下TAG的使用.列出标签git...
[摘]常见音视频格式
前言本文内容(音视频格式介绍)来源网络,这里我只是整合一下。好记性不如烂笔头正文常见的音频编码格式MP3全称是MPEG Audio Layer3。MP3是利用MPEG Audio Layer 3的技术,将音乐以1:10甚至1:12 的压缩率,压缩成容量较小的file。mp3能够在音质...