Android-Framework学习笔记(八)Service的启动-绑定过程,附赠复习资料

Configuration overrideConfiguration) {
if (packageInfo == null) throw new IllegalArgumentException(“packageInfo”);
return new ContextImpl(null, mainThread, packageInfo, activityToken, null, 0,
null, overrideConfiguration, displayId);
}

注释1处的上下文对象appContext 的具体类型就是ContextImpl 。Activity的attach方法中将ContextImpl赋值给ContextWrapper的成员变量mBase中,因此,mBase具体指向就是ContextImpl 。
具体是不是这样呢?看看Activity的attach方法:

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

Activity#attach()

final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window) {
attachBaseContext(context); //1

}

Activity继承ContextThemeWrapper,ContextThemeWrapper继承ContextWrapper,因此注释1执行的是ContextWrapper类attachBaseContext方法。

ContextWrapper#attachBaseContext()

protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException(“Base context already set”);
}
mBase = base;
}

果不其然,因此,ContextWrapper中的mBase具体指向就是ContextImpl 。

继续来看mBase.startService方法,就是ContextImpl的startService方法。

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

ContextImpl#startService()

@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}

ContextImpl#startServiceCommon()

private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
//1
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), getOpPackageName(), user.getIdentifier());

return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

注释1有没有很熟悉?在Framework学习(七)AMS家族一文说过AMS中Binder机制。注释1其实最终调用的是AMS的startService方法。

AMS到ActivityThread的调用

接着来查看AMS的startService方法。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

ActivityManagerService#startService()

@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId)
throws TransactionTooLargeException {

synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, callingPackage, userId); //1
Binder.restoreCallingIdentity(origId);
return res;
}
}

注释1处调用mServices的startServiceLocked方法,mServices的类型是ActiveServices。

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

ActiveServices#startServiceLocked()

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, String callingPackage, final int userId)
throws TransactionTooLargeException {

return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}

ActiveServices#startServiceInnerLocked()

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {


String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);

return r.name;
}

ActiveServices#bringUpServiceLocked()

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {

final String procName = r.processName;//1
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);//2
if (DEBUG_MU) Slog.v(TAG_MU, “bringUpServiceLocked: appInfo.uid=” + r.appInfo.uid

  • " app=" + app);
    if (app != null && app.thread != null) {//3
    try {
    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode,
    mAm.mProcessStats);
    realStartServiceLocked(r, app, execInFg);//4
    return null;
    } catch (TransactionTooLargeException e) {
    throw e;
    } catch (RemoteException e) {
    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
    }
    }
    } else {
    app = r.isolatedProc;
    }
    if (app == null && !permissionsReviewRequired) {//5
    if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
    “service”, r.name, false, isolated, false)) == null) {//6

    }
    if (isolated) {
    r.isolatedProc = app;
    }
    }

    }

和应用程序启动流程基本一致。
注释1处得到ServiceRecord的processName的值赋值给procName ,其中ServiceRecord用来描述Service的android:process属性。
注释2处将procName和Service的uid传入到AMS的getProcessRecordLocked方法中,来查询是否存在一个与Service对应的ProcessRecord类型的对象app,ProcessRecord主要用来记录运行的应用程序进程的信息。
注释5处判断Service对应的app为null则说明用来运行Service的应用程序进程不存在,则调用注释 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》开源 6处的AMS的startProcessLocked方法来创建对应的应用程序进程,具体创建过程参考Framework学习(六)应用程序进程启动过程。
注释3处表示Service的应用程序进程已经存在,则执行注释4的realStartServiceLocked方法。

ActiveServices#realStartServiceLocked()

private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {

try {

//1
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {

}

}

注释1调用了app.thread的scheduleCreateService方法。其中app.thread是IApplicationThread类型的,它的实现是ActivityThread的内部类ApplicationThread,其中ApplicationThread继承了ApplicationThreadNative,而ApplicationThreadNative继承了Binder并实现了IApplicationThread接口。

ActivityThread启动Service
frameworks/base/core/java/android/app/ActivityThread.java

ApplicationThread#scheduleCreateService()

public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData(); //1
s.token = token;
s.info = info;
s.compatInfo = compatInfo;

sendMessage(H.CREATE_SERVICE, s); //2
}

注释1将要启动的信息封装成CreateServiceData对象。
注释2将CreateServiceData对象通过sendMessage方法向H发送CREATE_SERVICE消息。

ApplicationThread#sendMessage()

private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)

  • ": " + arg1 + " / " + obj);
    Message msg = Message.obtain();
    msg.what = what;
    msg.obj = obj;
    msg.arg1 = arg1;
    msg.arg2 = arg2;
    if (async) {
    msg.setAsynchronous(true);
    }
    mH.sendMessage(msg);
    }

这里mH指的是H,它是ActivityThread的内部类并继承Handler。

ActivityThread.H

private class H e Android开源项目《ali1024.coding.net/public/P7/Android/git》 xtends Handler {
public static final int CREATE_SERVICE = 114;

public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;

}

ActivityThread#handleCreateService()

private void handleCreateService(CreateServiceData data) {

LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo); //1
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader(); //2
service = (Service) cl.loadClass(data.info.name).newInstance(); //3
} catch (Exception e) {

}

try {
ContextImpl context = ContextImpl.createAppContext(this, packageInfo); //4
context.setOuterContext(service);

Application app = packageInfo.makeApplication(false, mInstrumentation); //5
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault()); //6
service.onCreate(); //7
mServices.put(data.token, service); //8

}
}

注释1处获取要启动Service的应用程序的LoadedApk,LoadedApk是一个APK文件的描述类。
注释2处通过调用LoadedApk的getClassLoader方法来获取类加载器。
注释3处根据CreateServiceData对象中存储的Service信息,通过反射创建service实例。
注释4处创建Service的上下文环境ContextImpl对象。
注释5处获取当前应用的Application对象,该对象的唯一作用就是作为参数传递到Service里,然后在Service类中可以获得调用getApplication方法来获取Application对象。
注释6处调用Service的attach方法初始化Service,将ContextImpl对象注册到对应的Service中,之后在Service类中就可以使用Context的所有功能了。
注释7处调用Service的onCreate方法,这样Service就启动了。
注释8处将启动的Service加入到ActivityThread的成员变量mServices中,其中mServices是ArrayMap类型。

最后看看Service的启动时序图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Q3XJ4xt-1650618481218)(//upload-images.jianshu.io/upload_images/19956127-27206b815743150e.png?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)]

Service的绑定过程

Service的绑定过程和Service的启动过程很多内容有重复,这里简单跟一下流程。

ContextImpl请求AMS

frameworks/base/core/java/android/content/ContextWrapper.java

ContextWrapper#bindService()

@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}

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

ContextImpl#bindService()

@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}

ContextImpl#bindServiceCommon()

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException(“connection is null”);
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);//1
} else {
throw new RuntimeException(“Not supported in system context”);
}
validateServiceIntent(service);
try {

//2
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());

} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

注释1处调用了LoadedApk类型的对象mPackageInfo的getServiceDispatcher方法,它的主要作用是将ServiceConnection封装为IServiceConnection类型的对象sd,从IServiceConnection的名字我们就能得知它实现了Binder机制,这样Service的绑定就支持了跨进程通信。
注释2处我们又看见了熟悉的代码,最终会调用AMS的bindService方法。

AMS到ActivityThread的调用
接着来查看AMS的bindService方法。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

ActivityManagerService#bindService()

最后

在此为大家准备了四节优质的Android高级进阶视频:

架构师项目实战——全球首批Android开发者对Android架构的见解

附相关架构及资料

image.png

往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
rameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

ActivityManagerService#bindService()

最后

在此为大家准备了四节优质的Android高级进阶视频:

架构师项目实战——全球首批Android开发者对Android架构的见解

附相关架构及资料

[外链图片转存中…(img-mxyKAdkJ-1650618481220)]

往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值