Android 中 startService()啟動service的過程分析
通過分析點選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的過程的了.