主目录见:Android高级进阶知识(这是总目录索引)
框架地址:VirtualApk
在线源码查看:AndroidXRef
关于滴滴插件化框架VirtualApk我们已经讲了有几篇了:
1)插件化框架VirtualApk之初始化
2)插件化框架VirtualApk之插件加载
3)插件化框架VirtualApk之Activity启动
这篇我们紧接着前面开始讲,我们知道启动服务有两种方式startService和bindService两种方式,我们前面已经讲过startService的流程分析和bindService方式的从framework分析AIDL生成文件,而且我们知道,Service
的生命周期是我们可以手动控制的,我们可以不像Activity
生命周期的控制一样交给系统管理,我们可以更简单地控制Service
的生命周期。
我们看到Service的生命周期是比较简单的,而且图中已经说明了startService的时候,会调用onCreate(),onSstartCommand()方法,然后停止服务的时候我们可以调用stopService()或者stopSelf()方法;如果是bindService的时候,则会调用onCreate(),onBind()方法返回binder对象,然后会回调ServiceConnection
对象,解除绑定的时候可以调用unBindService()来回调onUnbind()方法。和上一篇一样,我们这里就贴一下startService的启动过程概图:
我们看到和Activity启动不一样的是,这里并不是通过
Instrumentation
来进行管理创建过程的,而是直接通过
ActivityManagerProxy
和
AMS
通讯进行创建的。
一.Service管理过程分析
插件化框架VirtualApk在Service的管理上采用了一种称为代理分发的方式。首先会在AndroidManifest.xml
中注册两种代理Service
,这样要启动插件Service
的时候,我们都会启动这个代理Srevice
,然后在onStartCommand()
方法中进行分发执行插件的onStartCommand()
方法。所以我们先来看看这两个代理Service的注册情况:
我们看到这里注册了两个代理服务,一个是在主进程中的,一个是在非主进程中的,根据插件服务在的进程进行分别地启动。而且在前面的初始化我们已经看到,一个是hook 了Instrumentation
类还有一个是hook了IActivityManager
,我们来看看:
private void hookSystemServices() {
try {
Singleton defaultSingleton = (Singleton) ReflectUtil.getField(ActivityManagerNative.class, null, "gDefault");
IActivityManager activityManagerProxy = ActivityManagerProxy.newInstance(this, defaultSingleton.get());
// Hook IActivityManager from ActivityManagerNative
ReflectUtil.setField(defaultSingleton.getClass().getSuperclass(), defaultSingleton, "mInstance", activityManagerProxy);
if (defaultSingleton.get() == activityManagerProxy) {
this.mActivityManager = activityManagerProxy;
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void hookAMSForO() {
try {
Singleton defaultSingleton = (Singleton) ReflectUtil.getField(ActivityManager.class, null, "IActivityManagerSingleton");
IActivityManager activityManagerProxy = ActivityManagerProxy.newInstance(this, defaultSingleton.get());
ReflectUtil.setField(defaultSingleton.getClass().getSuperclass(), defaultSingleton, "mInstance", activityManagerProxy);
} catch (Exception e) {
e.printStackTrace();
}
}
我们看到根据不同android版本分别采用了不同的方式,但是最终都是通过动态代理的方式将ActivityManagerProxy
代理成我们自己的ActivityManagerProxy
对象。这样在调用AMS的时候,我们会走到自己的ActivityManagerProxy
对象的invoke()
方法来。我们来看看invoke()
方法:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("startService".equals(method.getName())) {
try {
return startService(proxy, method, args);
} catch (Throwable e) {
Log.e(TAG, "Start service error", e);
}
} else if ("stopService".equals(method.getName())) {
try {
return stopService(proxy, method, args);
} catch (Throwable e) {
Log.e(TAG, "Stop Service error", e);
}
} else if ("stopServiceToken".equals(method.getName())) {
try {
return stopServiceToken(proxy, method, args);
} catch (Throwable e) {
Log.e(TAG, "Stop service token error", e);
}
} else if ("bindService".equals(method.getName())) {
try {
return bindService(proxy, method, args);
} catch (Throwable e) {
e.printStackTrace();
}
} else if ("unbindService".equals(method.getName())) {
try {
return unbindService(proxy, method, args);
} catch (Throwable e) {
e.printStackTrace();
}
} else if ("getIntentSender".equals(method.getName())) {
try {
getIntentSender(method, args);
} catch (Exception e) {
e.printStackTrace();
}
} else if ("overridePendingTransition".equals(method.getName())){
try {
overridePendingTransition(method, args);
} catch (Exception e){
e.printStackTrace();
}
}
try {
// sometimes system binder has problems.
return method.invoke(this.mActivityManager, args);
} catch (Throwable th) {
Throwable c = th.getCause();
if (c != null && c instanceof DeadObjectException) {
// retry connect to system binder
IBinder ams = ServiceManager.getService(Context.ACTIVITY_SERVICE);
if (ams != null) {
IActivityManager am = ActivityManagerNative.asInterface(ams);
mActivityManager = am;
}
}
Throwable cause = th;
do {
if (cause instanceof RemoteException) {
throw cause;
}
} while ((cause = cause.getCause()) != null);
throw c != null ? c : th;
}
}
这个方法很简单,我们看到关于Service的所有操作都被拦截了,我们这里一个一个方法来讲,首先我们看看startService()
方法。
1.startService
private Object startService(Object proxy, Method method, Object[] args) throws Throwable {
IApplicationThread appThread = (IApplicationThread) args[0];
Intent target = (Intent) args[1];
ResolveInfo resolveInfo = this.mPluginManager.resolveService(target, 0);
if (null == resolveInfo || null == resolveInfo.serviceInfo) {
// is host service
return method.invoke(this.mActivityManager, args);
}
return startDelegateServiceForTarget(target, resolveInfo.serviceInfo, null, RemoteService.EXTRA_COMMAND_START_SERVICE);
}
我们看到这里的resolveService()
方法跟Activity启动管理里面的resolveActivity()
方法类似,是根据intent的信息然后查找出来匹配的Service
的ResolveInfo
信息来,然后判断ResolveInfo
如果为空则说明是宿主程序中的服务,否则会调用startDelegateServiceForTarget()
方法进行处理:
private ComponentName startDelegateServiceForTarget(Intent target, ServiceInfo serviceInfo, Bundle extras, int command) {
Intent wrapperIntent = wrapperTargetIntent(target, serviceInfo, extras, command);
return mPluginManager.getHostContext().startService(wrapperIntent);
}
我们看到这里会先调用wrapperTargetIntent()
进行将要启动插件的服务替换成前面提前注册好的服务,然后启动。我们看看这里的替换代码:
private Intent wrapperTargetIntent(Intent target, ServiceInfo serviceInfo, Bundle extras, int command) {
// fill in service with ComponentName
target.setComponent(new ComponentName(serviceInfo.packageName, serviceInfo.name));
String pluginLocation = mPluginManager.getLoadedPlugin(target.getComponent()).getLocation();
// start delegate service to run plugin service inside
boolean local = PluginUtil.isLocalService(serviceInfo);
Class extends Service> delegate = local ? LocalService.class : RemoteService.class;
Intent intent = new Intent();
intent.setClass(mPluginManager.getHostContext(), delegate);
intent.putExtra(RemoteService.EXTRA_TARGET, target);
intent.putExtra(RemoteService.EXTRA_COMMAND, command);
intent.putExtra(RemoteService.EXTRA_PLUGIN_LOCATION, pluginLocation);
if (extras != null) {
intent.putExtras(extras);
}
return intent;
}
我们看到这里的首先设置intent的Component为插件中服务的Component,然后获取插件的位置,而且判断是不是要启动的插件服务是在独立的进程中,接着就设置intent的class等等一些信息。最后将提前注册好的Service启动。到这里我们的LocalService
和RemoteService
就已经启动了,这里的RemoteService
是继承LocalService
的,多了一步创建Application的操作。我们看前面的Service的生命周期可以知道,启动Service的过程中,会回调onStartCommand()
方法,所以我们在这里面做相应的操作即可,首先我们来看启动服务的回调:
case EXTRA_COMMAND_START_SERVICE: {
ActivityThread mainThread = (ActivityThread)ReflectUtil.getActivityThread(getBaseContext());
IApplicationThread appThread = mainThread.getApplicationThread();
Service service;
if (this.mPluginManager.getComponentsHandler().isServiceAvailable(component)) {
service = this.mPluginManager.getComponentsHandler().getService(component);
} else {
try {
service = (Service) plugin.getClassLoader().loadClass(component.getClassName()).newInstance();
Application app = plugin.getApplication();
IBinder token = appThread.asBinder();
Method attach = service.getClass().getMethod("attach", Context.class, ActivityThread.class, String.class, IBinder.class, Application.class, Object.class);
IActivityManager am = mPluginManager.getActivityManager();
attach.invoke(service, plugin.getPluginContext(), mainThread, component.getClassName(), token, app, am);
service.onCreate();
this.mPluginManager.getComponentsHandler().rememberService(component, service);
} catch (Throwable t) {
return START_STICKY;
}
}
service.onStartCommand(target, 0, this.mPluginManager.getComponentsHandler().getServiceCounter(service).getAndIncrement());
break;
}
这个方法就是启动Service的方法,首先会调用isServiceAvailable()
方法判断服务是否已经创建好缓存在mServices中了,如果有则不用重新创建直接获取到Service然后调用它的onStartCommand
方法,否则就重新反射创建Service,调用attach()
方法,然后手动调用Service的onCreate()
方法,并将创建好的Service添加到缓存中。如果这块代码有点不懂的话那么可以认真看framework层的代码。
2.stopService
case EXTRA_COMMAND_STOP_SERVICE: {
Service service = this.mPluginManager.getComponentsHandler().forgetService(component);
if (null != service) {
try {
service.onDestroy();
} catch (Exception e) {
Log.e(TAG, "Unable to stop service " + service + ": " + e.toString());
}
} else {
Log.i(TAG, component + " not found");
}
break;
}
我们看到停止服务比较简单,即时移除缓存中的Service,然后执行他的onDestroy()
方法即可。
3.bindService
private Object bindService(Object proxy, Method method, Object[] args) throws Throwable {
Intent target = (Intent) args[2];
ResolveInfo resolveInfo = this.mPluginManager.resolveService(target, 0);
if (null == resolveInfo || null == resolveInfo.serviceInfo) {
// is host service
return method.invoke(this.mActivityManager, args);
}
Bundle bundle = new Bundle();
PluginUtil.putBinder(bundle, "sc", (IBinder) args[4]);
startDelegateServiceForTarget(target, resolveInfo.serviceInfo, bundle, RemoteService.EXTRA_COMMAND_BIND_SERVICE);
mPluginManager.getComponentsHandler().remberIServiceConnection((IBinder) args[4], target);
return 1;
}
我们看到绑定服务这里将IBinder存入了一个Bundle
中,这个IBinder
就是我们前面分析源码时候提及的IServiceConnection
类,然后通过startDelegateServiceForTarget()
启动代理的Service,同样地,最终会来到LocalService
的onStartCommand()
方法中。
case EXTRA_COMMAND_BIND_SERVICE: {
ActivityThread mainThread = (ActivityThread)ReflectUtil.getActivityThread(getBaseContext());
IApplicationThread appThread = mainThread.getApplicationThread();
Service service = null;
if (this.mPluginManager.getComponentsHandler().isServiceAvailable(component)) {
service = this.mPluginManager.getComponentsHandler().getService(component);
} else {
try {
service = (Service) plugin.getClassLoader().loadClass(component.getClassName()).newInstance();
Application app = plugin.getApplication();
IBinder token = appThread.asBinder();
Method attach = service.getClass().getMethod("attach", Context.class, ActivityThread.class, String.class, IBinder.class, Application.class, Object.class);
IActivityManager am = mPluginManager.getActivityManager();
attach.invoke(service, plugin.getPluginContext(), mainThread, component.getClassName(), token, app, am);
service.onCreate();
this.mPluginManager.getComponentsHandler().rememberService(component, service);
} catch (Throwable t) {
t.printStackTrace();
}
}
try {
IBinder binder = service.onBind(target);
IBinder serviceConnection = PluginUtil.getBinder(intent.getExtras(), "sc");
IServiceConnection iServiceConnection = IServiceConnection.Stub.asInterface(serviceConnection);
if (Build.VERSION.SDK_INT >= 26) {
ReflectUtil.invokeNoException(IServiceConnection.class, iServiceConnection, "connected",
new Class[]{ComponentName.class, IBinder.class, boolean.class},
new Object[]{component, binder, false});
} else {
iServiceConnection.connected(component, binder);
}
} catch (Exception e) {
e.printStackTrace();
}
break;
}
这里的代码也并不复杂,主要做了几件事,首先也是判断缓存中有没有创建好的Service,如果没有则创建调用他的attach()
方法和onCreate()
方法,这里还有一个不同的地方是调用Service的onBind()
方法,然后会调ServiceConnection
的connected()
方法。
4.unbindService
case EXTRA_COMMAND_UNBIND_SERVICE: {
Service service = this.mPluginManager.getComponentsHandler().forgetService(component);
if (null != service) {
try {
service.onUnbind(target);
service.onDestroy();
} catch (Exception e) {
Log.e(TAG, "Unable to unbind service " + service + ": " + e.toString());
}
} else {
Log.i(TAG, component + " not found");
}
break;
}
这个跟stopService
差不多,就是多了一个在onDestroy
前面调用了onUnbind()
方法,这样的话,Service的整个启动,停止,绑定,解绑等都已经完成了。
还有在invoke()
方法里面有一个stopServiceToken
方法,这个方法的调用主要是在IntentService
中的stopSelf()
方法中会调用到,最终会调用mActivityManager.stopServiceToken
方法,同样的中转到STOP操作即可.
总结:到这里Service的管理我们也已经讲完了,整理来说代码逻辑不难,细节倒是非常多的,如果想要更深入了解,建议还是要认真看一下FrameWork的源码,希望大家能有所收获。