赞
踩
在Activity中使用bindService绑定Service时,会调用ContextWrapper的bindService方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/content/ContextWrapper.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
这个方法的mBase就是一个ContextImpl类型的对象。所以这里调用了ContextImpl类的bindService方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ContextImpl.java @Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser()); } 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); } else { throw new RuntimeException("Not supported in system context"); } validateServiceIntent(service); try { // ... // 关键代码 int res = ActivityManager.getService().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier()); // ... } // ... }
在bindServiceCommon方法中,先调用LoadedApk类型的变量mPackageInfo.getServiceDispatcher方法,获取一个IServiceConnection类型的对象sd,下面看看LoadedApk类中的这个方法的具体实现:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags) { synchronized (mServices) { LoadedApk.ServiceDispatcher sd = null; ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); if (map != null) { if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c); sd = map.get(c); } if (sd == null) { // 关键代码 sd = new ServiceDispatcher(c, context, handler, flags); if (map == null) { map = new ArrayMap<>(); mServices.put(context, map); } map.put(c, sd); } else { sd.validate(context, handler); } // 关键代码 return sd.getIServiceConnection(); } } ServiceDispatcher(ServiceConnection conn, Context context, Handler activityThread, int flags) { // 关键代码 mIServiceConnection = new InnerConnection(this); // ... } private static class InnerConnection extends IServiceConnection.Stub { // ... }
从LoadedApk类的getServiceDispatcher方法内部的逻辑主要是创建其内部类ServiceDispatcher对象,在ServiceDispatcher对象的创建过程中,又创建了ServiceDispatcher的静态内部类InnerConnection的实例。InnerConnection其实是继承IServiceConnection.Stub,所以它是一个Binder。在getServiceDispatcher方法的最后一行,通过sd.getIServiceConnection();返回的就是InnerConnection这类的实例。继续看ContextImpl类的bindServiceCommon方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ContextImpl.java 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); } else { throw new RuntimeException("Not supported in system context"); } validateServiceIntent(service); try { // ... // 关键代码 int res = ActivityManager.getService().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier()); // ... } // ... }
这个方法内部,通过ActivityManager.getService()获取到system_servier进程中的ActivityManagerService(后面简称AMS)在app进程中的代理对象,然后调用代理对象的bindService方法,并将前面获取的InnerConnection这个Binder对象作为参数传入,
这个过程就是进程间通信,下面看看AMS中的bindService方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("bindService"); // Refuse possible leaked file descriptors if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } // ... synchronized(this) { //关键代码 return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, callingPackage, userId); } }
这个方法内调用了mServices对象的bindServiceLocked方法,mServices是ActiveSerivces类型的,下面看看ActiveServices类的bindServiceLocked方法的具体实现:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String callingPackage, final int userId) throws TransactionTooLargeException { //... try { // ... if ((flags&Context.BIND_AUTO_CREATE) != 0) { //关键代码 if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) { return 0; } } // ... if (s.app != null && b.intent.received) { try { //关键代码 c.conn.connected(s.name, b.intent.binder, false); } // ... } // ... } // ... return 1; } private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { // ... if (!isolated) { app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); // 如果要启动的Service所在 进程已经创建,并且进程的ActivityThread也不为null,则直接启动Service if (app != null && app.thread != null) { try { app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats); realStartServiceLocked(r, app, execInFg); return null; } // ... } } // ... //要启动的Service所在的进程还未创建 if (app == null && !permissionsReviewRequired) { // 关键代码 if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, hostingType, r.name, false, isolated, false)) == null) { String msg = "Unable to launch app " + r.appInfo.packageName + "/" + r.appInfo.uid + " for service " + r.intent.getIntent() + ": process is bad"; bringDownServiceLocked(r); return msg; } // ... } //... return null; }
bindServiceLocked这个方法内部,会调用bringUpServiceLocked方法,bringUpServiceLocked内部会根据要绑定的Service所在的进程是否创建,如果进程创建了并且ActivityThread也不为null,则直接走绑定Service流程,否则,要先创建Service所在的进程,然后在走绑定Service的流程。为了分析过程尽量全面,我们就按照Service是在一个新的进程中这种情况分析,下面看mAm.startProcessLocked()这个方法,这里的mAm就是AMS,在AMS中,通过调用几次startProcessLocked()的重载方法后,调用到startProcess方法,接着调用了Process类的start方法,接着调用了ZygoteProcess类的start方法,Process类的start方法调用是system_server进程和ZygoteProcess进程进行进程间通信,他们是通过socket方式进行进程间通信的。ZygoteProcess内部,通过调用start方法,接着调用startViaZygote方法,最终调用zygoteSendArgsAndGetResult方法,完成Servcie所在的进程的创建工作,这样Servcie所在的进程就创建了,执行ActivityThread的main方法,在main方法中,主要完成了主线程的Looper的创建,并创建ActivityThread对象,并调用其attach方法,如果sMainHandler对象为null,则给这个对象赋值,并调用Looper.loop()方法进行消息的抽取。ActivityThread的attach方法中,在次获取system_server进程在app进程的代理对象,然后调用这个代理对象attachApplication方法,这个方法中,将ApplicationThread对象作为参数传入,这样system_servier进程就可以获取到app进程的ApplicationThread这个binder对象在system_server进程中的代理对象。方便后续system_server进程(客户端)向app进程(服务端)发起进程间通信。AMS的attachApplication方法内部又调用了attachApplicationLocked方法,
这个方法内部通过调用ApplicationThread这个对象的bindApplication方法,这个时候是进程间通信(system_server作为客户端,app进程作为服务端),ApplicationThread的bindApplication方法内部,调用了sendMessage(H.Execute_Bind)方法,接着又执行了handleBindApplication方法,handleBindApplication方法内部主要做了三件事:
1.创建Instrumentation对象
2.调用LoadedApk的makeApplication方法,创建Application对象
3.调用Instrumentation的callApplicationOnCreate方法,完成Application的OnCreate方法的执行。
到这里,AMS的attachApplicationLocked方法中的ApplicationThread的bindApplication方法执行过程分析完毕,这个过程的具体分析,可以看Android 9.0 点击桌面应用图标,启动Activity的过程分析
接着继续看AMS的attachApplicationLocked方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java @GuardedBy("this") private final boolean attachApplicationLocked(IApplicationThread thread, int pid, int callingUid, long startSeq) { // ... try { // ... if (app.isolatedEntryPoint != null) { thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs); } else if (app.instr != null) { thread.bindApplication(processName, appInfo, providers, app.instr.mClass, profilerInfo, app.instr.mArguments, app.instr.mWatcher, app.instr.mUiAutomationConnection, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, isAutofillCompatEnabled); } else { // 关键代码 thread.bindApplication(processName, appInfo, providers, null, profilerInfo, null, null, null, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, isAutofillCompatEnabled); } // ... } // ... // Find any services that should be running in this process... if (!badApp) { try { //关键代码 didSomething |= mServices.attachApplicationLocked(app, processName); checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked"); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown starting services in " + app, e); badApp = true; } } // ... return true; }
上面已经分析了thread.bindApplication方法,下面继续看mServices.attachApplicationLocked方法,mServices是ActivieServices类型的,所以代码执行到ActivieServices类的attachApplicationLocked方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java boolean attachApplicationLocked(ProcessRecord proc, String processName) throws RemoteException { boolean didSomething = false; if (mPendingServices.size() > 0) { ServiceRecord sr = null; try { for (int i=0; i<mPendingServices.size(); i++) { sr = mPendingServices.get(i); // ... // 关键代码 realStartServiceLocked(sr, proc, sr.createdFromFg); didSomething = true; // ... } } // ... } // ... return didSomething; } private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { // ... boolean created = false; try { // ... // 关键代码 app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); // ... } // ... // 关键代码 requestServiceBindingsLocked(r, execInFg); updateServiceClientActivitiesLocked(app, null, true); // ... } private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException { //在前面的分析中,Service所在的进程已经创建,并且ActivityThread也创建了,所以这里的判断不成立 if (r.app == null || r.app.thread == null) { return false; } if ((!i.requested || rebind) && i.apps.size() > 0) { try { // ... r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState); // ... } // ... } return true; }
attachApplicationLocked方法内部会r.app.thread.scheduleCreateService方法,r表示ServcieRecord对象,可以理解为是Servcie, r.app其实就是ProcessRecord类型的对象,可以理解为Process,r.app.thread是一个IApplicationThread类型的对象。
所以r.app.thread.scheduleBindService最终会执行到ApplicationThread的scheduleCreateService方法,这里其实是进程间通信。下面看看这个方法的具体实现
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) { updateProcessState(processState, false); // ... // 关键代码 sendMessage(H.CREATE_SERVICE, s); } public void handleMessage(Message msg) { 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; } private void handleCreateService(CreateServiceData data) { unscheduleGcIdler(); LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { // 关键代码 java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent); } // ... try { // 关键代码 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); Application app = packageInfo.makeApplication(false, mInstrumentation); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); service.onCreate(); mServices.put(data.token, service); // ... } // ... }
handleCreateService方法内部做了如下事情:
1.通过类加载的方式创建Service实例对象
2.调用LoadedApk类的makeApplication方法,返回一个Application对象
3.调用servcie的attach方法,这个方法内部主要是调用了attachBaseContext方法,将servcie与ContextImpl对象关联
4.调用Servcie的onCreate方法
至此,Servcie被创建,并且OnCreate方法也得到执行。
下面继续看ActiveServices类的realStartServiceLocked方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { // ... boolean created = false; try { // ... // 关键代码 app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); // ... } // ... // 关键代码 requestServiceBindingsLocked(r, execInFg); updateServiceClientActivitiesLocked(app, null, true); // ... } private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg) throws TransactionTooLargeException { for (int i=r.bindings.size()-1; i>=0; i--) { IntentBindRecord ibr = r.bindings.valueAt(i); //关键代码 if (!requestServiceBindingLocked(r, ibr, execInFg, false)) { break; } } } private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException { //在前面的分析中,Service所在的进程已经创建,并且ActivityThread也创建了,所以这里的判断不成立 if (r.app == null || r.app.thread == null) { return false; } if ((!i.requested || rebind) && i.apps.size() > 0) { try { // ... r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState); // ... } // ... } return true; }
这方法内部继续调用到requestServiceBindingLocked的重载方法,这个重载方法内部,
调用r.app.thread,这个对象的scheduleBindService方法,r.app.thread是一个IApplicationThread类型的对象。所以r.app.thread.scheduleBindService最终会执行到ApplicationThread的scheduleBindService方法,这里其实是进程间通信。下面看看这个方法的具体实现
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) { updateProcessState(processState, false); // ... // 关键代码 sendMessage(H.BIND_SERVICE, s); } public void handleMessage(Message msg) { case BIND_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind"); handleBindService((BindServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; } private void handleBindService(BindServiceData data) { Service s = mServices.get(data.token); if (s != null) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); try { if (!data.rebind) { // 关键代码 IBinder binder = s.onBind(data.intent); // 关键代码 ActivityManager.getService().publishService( data.token, data.intent, binder); } else { s.onRebind(data.intent); ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } // ... } // ... } // ... } }
scheduleBindService方法最终调用到了handleBindService方法,最终调用了s.onBind()方法,这里的s就是Service,所以,至此Service的onBind方法执行。
接着调用了AMS的publishService方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public void publishService(IBinder token, Intent intent, IBinder service) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { if (!(token instanceof ServiceRecord)) { throw new IllegalArgumentException("Invalid service token"); } // 关键代码 mServices.publishServiceLocked((ServiceRecord)token, intent, service); } }
这个方法中mServices是ActiveServices类型的,下面看看ActiveServices类的publishServiceLocked方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { final long origId = Binder.clearCallingIdentity(); try { if (r != null) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord b = r.bindings.get(filter); if (b != null && !b.received) { b.binder = service; b.requested = true; b.received = true; for (int conni=r.connections.size()-1; conni>=0; conni--) { ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni); for (int i=0; i<clist.size(); i++) { ConnectionRecord c = clist.get(i); if (!filter.equals(c.binding.intent.intent)) { continue; } try { // 关键代码 c.conn.connected(r.name, service, false); } // ... } } } serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false); } } finally { Binder.restoreCallingIdentity(origId); } }
这个方法内部c.conn.connected(r.name, service, false);其中c.conn是LoadedApk类的静态内部类ServiceDispatcher的静态内部类InnerConnection类型对象,而InnerConnection 是继承 IServiceConnection.Stub,所以,c.conn其实就是app进程的InnerConnection这个binder对象在system_server进程中的代理,此时,system_server进程作为客户端,通过这个代理对象向app进程(作为服务端)发起进程间通信,这样,InnerConnection的onConnected方法就得到执行,下面看看InnerConnection的connected的具体实现
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java public final class LoadedApk { static final class ServiceDispatcher { private static class InnerConnection extends IServiceConnection.Stub { final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; InnerConnection(LoadedApk.ServiceDispatcher sd) { mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); } public void connected(ComponentName name, IBinder service, boolean dead) throws RemoteException { LoadedApk.ServiceDispatcher sd = mDispatcher.get(); if (sd != null) { // 关键代码 sd.connected(name, service, dead); } } public void connected(ComponentName name, IBinder service, boolean dead) { if (mActivityThread != null) { // 关键代码 mActivityThread.post(new RunConnection(name, service, 0, dead)); } else { doConnected(name, service, dead); } } } }
InnerConnection的connected这个方法内部会调用ServiceDispatcher类的connected方法,
ServiceDispatcher类的connected方法又会调用
mActivityThread.post(new RunConnection(name, service, 0, dead));
这里mActivityThread其实就是个handler,下面看看这个RunConnection类,它是LoadedApk的静态内部类ServiceDispatcher的一个内部类
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java private final class RunConnection implements Runnable { RunConnection(ComponentName name, IBinder service, int command, boolean dead) { mName = name; mService = service; mCommand = command; mDead = dead; } public void run() { if (mCommand == 0) { // 关键代码 doConnected(mName, mService, mDead); } else if (mCommand == 1) { doDeath(mName, mService); } } final ComponentName mName; final IBinder mService; final int mCommand; final boolean mDead; } public void doConnected(ComponentName name, IBinder service, boolean dead) { ServiceDispatcher.ConnectionInfo old; ServiceDispatcher.ConnectionInfo info; synchronized (this) { if (mForgotten) { return; } old = mActiveConnections.get(name); if (old != null && old.binder == service) { return; } if (service != null) { // A new service is being connected... set it all up. info = new ConnectionInfo(); info.binder = service; info.deathMonitor = new DeathMonitor(name, service); try { service.linkToDeath(info.deathMonitor, 0); mActiveConnections.put(name, info); } catch (RemoteException e) { // This service was dead before we got it... just // don't do anything with it. mActiveConnections.remove(name); return; } } else { // The named service is being disconnected... clean up. mActiveConnections.remove(name); } if (old != null) { old.binder.unlinkToDeath(old.deathMonitor, 0); } } // If there was an old service, it is now disconnected. if (old != null) { mConnection.onServiceDisconnected(name); } if (dead) { mConnection.onBindingDied(name); } if (service != null) { // 关键代码 mConnection.onServiceConnected(name, service); } else { // The binding machinery worked, but the remote returned null from onBind(). mConnection.onNullBinding(name); } }
run方法中,有调用了doConnected方法,doConnected方法中,mConnection.onServiceConnected方法,这里的mConnection就是我们bindServcie方法中传入的ServiceConnection类型的变量,所以至此,onServiceConnected方法得到回调。
以上便是bindService的整个过程分析
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。