接上一篇《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日写,先发出来。
历史上的今天
暂无评论...
随机推荐
Android初始化第三方app权限
前言定制项目时要跟第三方应用合作,随着Android权限的收紧,需要APP主动申请需要的权限并让用户选择,但车机项目提醒权限申请这个弹框比较不友好,因此被客户要正文我只是Android系统应用测试开机时启动一个服务,添加需要申请权限的包名。不一定有效,个人笔记,只供参考AskP...
[摘]Android判断顶部Activity的包名等
前言本文摘抄,具体来源看末尾连接,记录于此。好记性不如烂笔头。小结在实际中,发现使用[获取顶层Activity]的第一个方式存在问题,偶尔获取的顶层activity是错误的。正文判断当前是不是桌面 public static boolean isHome(Context con...
重写TextView的setText出现异常问题
前言TextView重写setText(CharSequence text, BufferType type) 时出现如下异常日志(截取部分日志):java.lang.NullPointerException: Attempt to invoke interface method 'int j...
茅盾:白杨礼赞
白杨树实在是不平凡的,我赞美白杨树!当汽车在望不到边际的高原上奔驰,扑入你的视野的,是黄绿错综的一条大毡子;黄的,那是土,未开垦的处女土,几十万年前由伟大的自然力所堆积成功的黄土高原的外壳;绿的呢,是人类劳力战胜自然的成果,是麦田,和风吹送,翻起了一轮一轮的绿波——,这时你会真心佩服昔人所造的两个...
常见的文件头或文件尾十六进制表示
前言最近在加载图片时,由于需要对不同图片使用不同的加载方式,因此需要通过判断图片的类型进行条用不同的接口。因此摘抄于此,以便查阅。正文下面的文件头或文件尾都是用十六进制表示的。JPEG (jpg)文件头:FFD8FF文件尾:FFD9PNG (png)文件头:89504E47文件尾...
新井一二三:图书馆的恋人
我14岁那年,为了准备翌年的高中入学考试,除了上课以外,很多时间都在图书馆里温习。尤其放了暑假,每天一大早就到图书馆门口排队,以便获得里头较安静的座位。有个男同学叫T,每天也一定来图书馆。有时候,我早晨起得晚,差一点就没赶上9点钟图书馆开门的时间。每逢此时T都帮我占个座位。我们邻座学习到中午,一起...