您的位置:首页 > 移动开发 > Android开发

Android 中 startService()启动service的过程分析

2016-06-13 19:19 901 查看
通过分析点击android桌面app图标启动应用程序的过程这篇文章,我们了解启动activity的过程,再来分析启动android的另一个组件service的过程就比较容易了.因为流程差不多.

现在假设应用程序有一个activity和一个service,然后在activity中通过startService()启动service,清单文件中service的process属性没有设置.也就是activity和service在一个进程中.

startService()这个方法是Activty的父类ContextWrapper中的.

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

public ComponentName startService(Intent service) {
return mBase.startService(service);
}
这里mBase变量是ContextImpl类型,是在创建activity的时候,new 一个ContextImpl对象,赋值给activity的.

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

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
.....
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);//创建contextImpl
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
.....
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);//传进去

.....
return activity;
}


好了继续:

第一步:frameworks/base/core/java/android/app/ContextImpl.java

public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceAsUser(service, mUser);
}

@Override
public ComponentName startServiceAsUser(Intent service, UserHandle user) {
try {
service.setAllowFds(false);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
....
return cn;
} catch (RemoteException e) {
return null;
}
}


这里通过Binder通信,调用到ActivityManagerService的启动service方法.

mMainThread.getApplicationThread()是ApplicationThread类型的mAppThread对象,ApplicationThread其实是Binder类型.是用来和ActivityManagerService进程间通信的,它是在ActivityThread类中创建的.

service.resolveTypeIfNeeded(getContentResolver())获取这个intent的MIME类型,这里假设没有设置MIME类型
即AndroidManifest.xml没有设置Service的MIME类型,所以这里返回null.

第二步:

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

public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeInt(userId);
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
ComponentName res = ComponentName.readFromParcel(reply);
data.recycle();
reply.recycle();
return res;
}


通过Binder驱动

case START_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
int userId = data.readInt();
ComponentName cn = startService(app, service, resolvedType, userId);
reply.writeNoException();
ComponentName.writeToParcel(cn, reply);
return true;
}


上面就调用到了ActivityManagerService中.

第三步:startService().

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

public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, int userId) {
.....
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
checkValidCaller(callingUid, userId);
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}


第四步:startServiceLocked().

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

ComponentName startServiceLocked(IApplicationThread caller,
Intent service, String resolvedType,
int callingPid, int callingUid, int userId) {
....
if (caller != null) {
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
.....
}
}

ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
callingPid, callingUid, userId, true);
if (res == null) {
...
}
if (res.record == null) {
...
}
ServiceRecord r = res.record;
......
String error = bringUpServiceLocked(r, service.getFlags(), false);
....
return r.name;
}
函数首先通过retrieveServiceLocked来解析service这个Intent,就是解析我们在AndroidManifest.xml定义的Service标签的intent-filter相关内容,然后将解析结果放在res.record中.

第五步:bringUpServiceLocked().ActiveServices.java中

private final String bringUpServiceLocked(ServiceRecord r,
int intentFlags, boolean whileRestarting) {
....
if (r.app != null && r.app.thread != null) {
...
}
.....
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
ProcessRecord app;

if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);//这里获取不为空,因为该service所在的进程已经启动起来了
....
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName);
realStartServiceLocked(r, app);
return null;
} catch (RemoteException e) {
...
}
.....
}
} else {
...
}

....
return null;
}
这里service所在的进程已经启动起来了,所以接下来直接在这个进程中启动service.

第六步:realStartServiceLocked().ActiveServices.java中

private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app) throws RemoteException {
...
try {
....
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));//去创建service
r.postNotification();
created = true;
} finally {
...
}
.....
sendServiceArgsLocked(r, true);
}
首先看scheduleCreateService方法,

第七步:scheduleCreateService().

frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中,这里又是Binder进程间通信了.

public final void scheduleCreateService(IBinder token, ServiceInfo info,
CompatibilityInfo compatInfo) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
info.writeToParcel(data, 0);
compatInfo.writeToParcel(data, 0);
mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}


经过Binder驱动

case SCHEDULE_CREATE_SERVICE_TRANSACTION: {
data.enforceInterface(IApplicationThread.descriptor);
IBinder token = data.readStrongBinder();
ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data);
CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
scheduleCreateService(token, info, compatInfo);
return true;
}


这样就调用到了应用程序中了

第八步:scheduleCreateService().

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

public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo) {
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;

queueOrSendMessage(H.CREATE_SERVICE, s);
}


第九步:queueOrSendMessage().

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

private void queueOrSendMessage(int what, Object obj) {
queueOrSendMessage(what, obj, 0, 0);
}
private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
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;
mH.sendMessage(msg);
}
}


第十步:handleCreateService().

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

case CREATE_SERVICE:
...
handleCreateService((CreateServiceData)msg.obj);
...
break;
private void handleCreateService(CreateServiceData data) {
...
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();//创建一个service实例
} catch (Exception e) {
...
}

try {
...
ContextImpl context = new ContextImpl();
context.init(packageInfo, null, this);

Application app = packageInfo.makeApplication(false, mInstrumentation);
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
service.onCreate();//回调service的onCreat()方法
mServices.put(data.token, service);
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, 0, 0, 0);
} catch (RemoteException e) {
// nothing to do.
}
} catch (Exception e) {
...
}
}


service.onCreate()这个方法最终会回调service的oncreate()方法,这个大家应该熟悉.这里service就创建起来了

接下来回到第六步,另外一个方法sendServiceArgsLocked();
第十一步:sendServiceArgsLocked().

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

private final void sendServiceArgsLocked(ServiceRecord r,
boolean oomAdjusted) {
.....
r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
....
}


这里通过Binder通信到应用程序中去了,

这里我就省略中间的几步了,和第七步类似.
第十二步:sendServiceArgsLocked().

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

public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
int flags ,Intent args) {
ServiceArgsData s = new ServiceArgsData();
s.token = token;
s.taskRemoved = taskRemoved;
s.startId = startId;
s.flags = flags;
s.args = args;

queueOrSendMessage(H.SERVICE_ARGS, s);
}


这里省略中间消息发送的几个步骤,和第九步类似.

第十三步:handleServiceArgs().

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

private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
...
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
.....
}
s.onStartCommand()这个方法会先回调service的onStart()方法,这样onStart()和onStartCommand()就被相继调用了,这两个回调大家应该也熟悉吧.

这就是启动service的过程的了.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  startService