VirtualApp框架--- Application启动过程
来源:互联网 发布:java音乐网站系统 编辑:程序博客网 时间:2024/05/18 00:52
一、VA 的Application为VApp,定义在io.virtualapp包中。VA重写了attachBaseContext()方法,在程序启动时会首先运行该方法,然后再调用VA的oncreate()方法。
二、VApp的attachBaseContext方法会去调用VirtualCore.getCore().startup(base)方法。
2.1. VirtualCore类定义在com.lody.virtual.client.core包中,getCore方法则是获取VirtualCore类的一个静态对象。接着调用该静态对象的startup方法。startup方法的部分源码如下
this.context = context; mainThread = ActivityThread.currentActivityThread(); hostBindData = ActivityThreadCompat.getBoundApplication(mainThread); unHookPackageManager = context.getPackageManager(); hostPkgInfo = unHookPackageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_PROVIDERS); ProviderInfo[] hostProviders = hostPkgInfo.providers; if (hostProviders != null) { for (ProviderInfo info : hostProviders) { hostProviderAuths.add(info.authority);
在上面代码中得出,首先获取当前的线程,然后获取这个线程的boundApplication对象,即AppBindData对象,在该对象中保存该线程的一些属性信息。然后调用context的getPackageManager方法获取了一个包管理器,然后通过传入当前包名获取当前的包信息,再然后就可以获取存储在报信息中的provider信息,最后将所有provider的authority属性保存到hostProviderAuths中。
2.2 接下来代码如下:
// Host包名 pkgName = context.getPackageName(); // 主进程名 mainProcessName = context.getApplicationInfo().processName; // 当前进程名 processName = mainThread.getProcessName(); if (processName.equals(mainProcessName)) { processType = ProcessType.Main; } else if (processName.endsWith(Constants.SERVER_PROCESS_NAME)) { processType = ProcessType.Server; } else if (LocalProcessManager.isAppProcess(processName)) { processType = ProcessType.VAppClient; } else { processType = ProcessType.CHILD; } PatchManager patchManager = PatchManager.getInstance(); patchManager.injectAll(); patchManager.checkEnv(); RuntimeEnv.init(); PatchManager.fixContext(context); isStartUp = true;
在上面的代码中首先获取当前包名,主进程名,当前进程名,然后判断当前进程的进程类型。进程类型分为四种,分别是服务端进程,插件客户端进程,主进程和子进程。前两张判断比较简单,直接比较当前进程名与主进程名是否相同可以判断是否为主进程;检查当前进程的名字是否以’:x’结尾可以判断是否为服务端进程。检查是否为插件客户端进程则需要调用LocalProcessManager类的isAppProcess方法。
2.3 接下来分析一下这个方法,这个方法的源码如下:
public static boolean isAppProcess(String processName) { try { return getService().isAppProcess(processName); } catch (RemoteException e) { return RuntimeEnv.crash(e); } }
从上面代码可以看到它首先调用了getService方法,这个方法会返回一个IProcessManager对象,然后调用该对象的isAppProcess方法进行判断。
2.4 接下来看一下getService方法的源码
private static IProcessManager service; private static IProcessManager getService() { if (service == null) { synchronized (LocalProcessManager.class) { if (service == null) { IBinder binder = ServiceManagerNative.getService(ServiceManagerNative.PROCESS_MANAGER); service = IProcessManager.Stub.asInterface(binder); } } } if (service == null) { throw new RuntimeException("Unable to attach ProcessManager"); } return service; }
在getService方法中,调用了ServiceManagerNative类的getService方法获取了一个IBinder对象,然后将远程对象的代理传给了service,然后进行了返回。
2.5 接下来看一下ServiceManagerNative类的getService方法,其源码如下:
public static IBinder getService(String name) { if (VirtualCore.getCore().isServiceProcess()) { return ServiceCache.getService(name); } IServiceFetcher fetcher = getServiceFetcher(); if (fetcher != null) { try { return fetcher.getService(name); } catch (RemoteException e) { e.printStackTrace(); } } VLog.e(TAG, "GetService(%s) return null.", name); return null; }
首先调用VirtualCore类中的isServiceProcess方法判断当前进程是否为服务进程,如果是的话直接返回保存在ServiceCache类中的service。从上文分析来看,如果当前进程是服务进程就会直接返回了,不会有2.3步骤的分析了,因此此处不是服务进程,进入下面分析。通过调用getServiceFetcher方法获取一个IServiceFetcher对象,然后调用返回该对象的getService方法。
2.6 接着看一下getServiceFetcher方法的源码:
public static IServiceFetcher getServiceFetcher() { Context context = VirtualCore.getCore().getContext(); Bundle response = new ProviderCaller.Builder(context, SERVICE_CP_AUTH).methodName("@").call(); if (response != null) { IBinder binder = BundleCompat.getBinder(response, ExtraConstants.EXTRA_BINDER); linkBinderDied(binder); return IServiceFetcher.Stub.asInterface(binder); } return null; }
首先获取了VirtualCore中的context对象,然后构建了一个ProviderCaller的一个内部类Builder对象,然后依次调用了methodName方法和call方法,最后返回了一个Bundle对象。
2.7 首先看一下内部类Builder的源码:
public static final class Builder { private Context context; private Bundle bundle = new Bundle(); private String methodName; private String auth; private String arg; public Builder(Context context, String auth) { this.context = context; this.auth = auth; } public Builder methodName(String name) { this.methodName = name; return this; } public Builder arg(String arg) { this.arg = arg; return this; } public Builder addArg(String key, Object value) { if (value != null) { if (value instanceof IBinder) { if (Build.VERSION.SDK_INT >= 18) { bundle.putBinder(key, (IBinder) value); } else { //noinspection deprecation bundle.putIBinder(key, (IBinder) value); } } else if (value instanceof Boolean) { bundle.putBoolean(key, (Boolean) value); } else if (value instanceof Integer) { bundle.putInt(key, (Integer) value); } else if (value instanceof String) { bundle.putString(key, (String) value); } else if (value instanceof Serializable) { bundle.putSerializable(key, (Serializable) value); } else if (value instanceof Bundle) { bundle.putBundle(key, (Bundle) value); } else if (value instanceof Parcelable) { bundle.putParcelable(key, (Parcelable) value); } else { throw new IllegalArgumentException("Unknown type " + value.getClass() + " in Bundle."); } } return this; }
从上面代码可以看出,其methodName方法只是将名字”@”传给了它的methodName属性,而call方法则是调用了其外部类 ProviderCaller的call方法。
2.8 ProviderCaller的call方法源码如下:
public static Bundle call(String auth, Context context, String methodName, String arg, Bundle bundle) { Uri uri = Uri.parse("content://" + auth); ContentResolver contentResolver = context.getContentResolver(); return contentResolver.call(uri, methodName, arg, bundle); }
可以看到,在该方法中最后实际工作是调用了ContentResolver类的call方法,该方法是Android系统源码中定义的方法,它可以执行在ContentProvider中暴露出来的方法,所有最后实际工作还是在provider中进行的,该流程暂时分析到这里。
2.9 接着进行2.2步的分析
PatchManager patchManager = PatchManager.getInstance(); patchManager.injectAll(); patchManager.checkEnv(); RuntimeEnv.init(); PatchManager.fixContext(context); isStartUp = true;
从上面代码可以看出,首先创建了一个PatchManager类的实例,然后分别调用了改对象的injectAll方法和checkEnv方法。
2.10 首先分析PatchManager对象的injectAll方法,其源码如下:
public void injectAll() throws Throwable { if (PatchManagerHolder.sInit) { throw new IllegalStateException("PatchManager Has been initialized."); } injectInternal(); PatchManagerHolder.sInit = true; }
该方法中会去调用injectInternal方法,injectInternal方法源码如下:
private void injectInternal() throws Throwable { addPatch(new ActivityManagerPatch()); addPatch(new PackageManagerPatch()); if (VirtualCore.getCore().isVAppProcess()) { // ## Fuck the MIUI Security if (MIUISecurityManagerPatch.needInject()) { addPatch(new MIUISecurityManagerPatch()); } // ## End addPatch(HCallbackHook.getDefault()); addPatch(AppInstrumentation.getDefault()); addPatch(new NotificationManagerPatch()); addPatch(new LocationManagerPatch()); addPatch(new WindowManagerPatch()); addPatch(new ClipBoardPatch()); addPatch(new MountServicePatch()); addPatch(new BackupManagerPatch()); addPatch(new TelephonyPatch()); addPatch(new PhoneSubInfoPatch()); addPatch(new PowerManagerPatch()); addPatch(new TelephonyRegistryPatch()); addPatch(new AppWidgetManagerPatch()); addPatch(new AccountManagerPatch()); addPatch(new DropBoxManagerPatch()); addPatch(new AudioManagerPatch()); addPatch(new SearchManagerPatch()); if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR2) { addPatch(new VibratorPatch()); addPatch(new WifiManagerPatch()); } if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR1) { addPatch(new UserManagerPatch()); } if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR1) { addPatch(new DisplayManagerPatch()); } if (Build.VERSION.SDK_INT >= L) { addPatch(new InputMethodManagerPatch()); addPatch(new MmsPatch()); addPatch(new SessionManagerPatch()); addPatch(new JobPatch()); addPatch(new RestrictionPatch()); addPatch(new CameraPatch()); } if (Build.VERSION.SDK_INT >= KITKAT) { addPatch(new AppOpsManagerPatch()); addPatch(new MediaRouterServicePatch()); } if (Build.VERSION.SDK_INT >= LOLLIPOP_MR1) { addPatch(new GraphicsStatsPatch()); } } }
在上面代码可以看出,它调用了addPatch方法将许多xxxPatch类添加了进去。addPatch源码如下:
private void addPatch(Injectable injectable) { injectableMap.put(injectable.getClass(), injectable); }
从上面代码可以看出,addPatch方法就是讲许多的Injectable对象存放了起来,其中injectableMap的定义如下:
private Map<Class<?>, Injectable> injectableMap = new HashMap<Class<?>, Injectable>(12);
因此,addPatch方法就是将Injectable对象存放到了了injectableMap这个Map表中。以ActivityManagerPatch()为例看一下这些xxxPatch对象。
2.11 ActivityManagerPatch类的源码如下:
@Patch({Hook_StartActivities.class, Hook_StartActivity.class, Hook_StartActivityAsCaller.class, Hook_StartActivityAsUser.class, Hook_GetIntentSender.class, Hook_RegisterReceiver.class, Hook_GetContentProvider.class, Hook_GetContentProviderExternal.class, Hook_GetActivityClassForToken.class, Hook_GetTasks.class, Hook_GetRunningAppProcesses.class, Hook_StartService.class, Hook_StopService.class, Hook_StopServiceToken.class, Hook_BindService.class, Hook_UnbindService.class, Hook_PeekService.class, Hook_ServiceDoneExecuting.class, Hook_UnbindFinished.class, Hook_PublishService.class, Hook_HandleIncomingUser.class, Hook_SetServiceForeground.class, Hook_BroadcastIntent.class, Hook_GetCallingPackage.class, Hook_GrantUriPermissionFromOwner.class, Hook_CheckGrantUriPermission.class, Hook_GetPersistedUriPermissions.class, Hook_KillApplicationProcess.class, Hook_ForceStopPackage.class, Hook_AddPackageDependency.class, Hook_UpdateDeviceOwner.class, Hook_CrashApplication.class, Hook_GetPackageForToken.class, Hook_SetPackageAskScreenCompat.class, Hook_GetPackageAskScreenCompat.class, Hook_SetAppLockedVerifying.class, Hook_CheckPermission.class, Hook_PublishContentProviders.class, Hook_GetCurrentUser.class, Hook_UnstableProviderDied.class, Hook_GetCallingActivity.class,}) public class ActivityManagerPatch extends PatchObject<IActivityManager, HookObject<IActivityManager>> { public static IActivityManager getAMN() { return ActivityManagerNative.getDefault(); } @Override protected HookObject<IActivityManager> initHookObject() { return new HookObject<IActivityManager>(getAMN()); } @Override public void inject() throws Throwable { Field f_gDefault = ActivityManagerNative.class.getDeclaredField("gDefault"); if (!f_gDefault.isAccessible()) { f_gDefault.setAccessible(true); } if (f_gDefault.getType() == IActivityManager.class) { f_gDefault.set(null, getHookObject().getProxyObject()); } else if (f_gDefault.getType() == Singleton.class) { Singleton gDefault = (Singleton) f_gDefault.get(null); Field f_mInstance = Singleton.class.getDeclaredField("mInstance"); if (!f_mInstance.isAccessible()) { f_mInstance.setAccessible(true); } f_mInstance.set(gDefault, getHookObject().getProxyObject()); } else { // 不会经过这里 throw new UnsupportedOperationException("Singleton is not visible in AMN."); } HookBinder<IActivityManager> hookAMBinder = new HookBinder<IActivityManager>() { @Override protected IBinder queryBaseBinder() { return ServiceManager.getService(Context.ACTIVITY_SERVICE); } @Override protected IActivityManager createInterface(IBinder baseBinder) { return getHookObject().getProxyObject(); } }; hookAMBinder.injectService(Context.ACTIVITY_SERVICE); } @Override public boolean isEnvBad() { return getAMN() != getHookObject().getProxyObject(); } }
从上面代码可以看出,ActivityManagerPatch这个类大概是用来替换获取AMS的代理对象gDefault的。暂且看到这里,再回到流程2.9中去.
2.12 接下来要执行的就是patchManager.checkEnv()方法,下面看一下checkEnv的源码
public void checkEnv() throws Throwable { for (Injectable injectable : injectableMap.values()) { if (injectable.isEnvBad()) { injectable.inject(); } } }
可以看到,在这个方法中是通过便利injectableMap中的injectable对象,然后执行了每个对象的inject方法。从2.10可以看出,其实这个injectable对象就是前面提到的xxxPatch类的对象。还是以ActivityManagerPatch类为例,首先执行它的isEnvBad方法。
2.13 ActivityManagerPatch类的isEnvBad方法源码如下:
@Override public boolean isEnvBad() { return getAMN() != getHookObject().getProxyObject(); }
这个函数的返回值取决于getAMN方法和getHookObject().getProxyObject()方法的返回值,分别来看一下它们的作用。
2.14 getAMN方法的源码如下
public static IActivityManager getAMN() { return ActivityManagerNative.getDefault(); }
可以看到,这个方法其实返回的就是AMS的代理对象gDefault,再看一下后者的源码。
2.15 getHookObject方法的源码如下
public H getHookObject() { return hookObject; }
这个方法是ActivityManagerPatch的父类PatchObject中的方法,这里的H就是HookObject类,这里返回的就是一个HookObject类对象。由于PatchObject类是ActivityManagerPatch类的父类,所以在2.10步添加一个新的ActivityManagerPatch类对象是也会同步创建一个PatchObject类对象,看一下PatchObject类对象的源码。
2.16 首先看一下PatchObject类的无参构造方法源码
public PatchObject() { this.hookObject = initHookObject(); applyHooks(); afterHookApply(hookObject); }
2.17 initHookObject方法的源码如下
@Override protected HookObject<IActivityManager> initHookObject() { return new HookObject<IActivityManager>(getAMN());
这个方法在PatchObject类中是一个抽象方法,具体实现是在ActivityManagerPatch中,可以看到其返回一个使用AMS的代理gDefault作为参数的HookObject类对象。继续看一下HookObject类的源码。
2.18 HookObject类的构造方法如下
public HookObject(T baseObject, Class<?>... proxyInterfaces) { this(baseObject == null ? null : baseObject.getClass().getClassLoader(), baseObject, proxyInterfaces); } public HookObject(ClassLoader cl, T baseObject, Class<?>... proxyInterfaces) { this.mBaseObject = baseObject; if (mBaseObject != null) { if (proxyInterfaces == null) { proxyInterfaces = baseObject.getClass().getInterfaces(); } mProxyObject = (T) Proxy.newProxyInstance(cl, proxyInterfaces, new HookHandler()); } } public HookObject(T baseObject) { this(baseObject, (Class<?>[]) null); }
可以看到,一共有三个构造方法,但最终会调用到第二个构造方法,在第二个构造方法中,mBaseObject对象就是我们传入的gDefault对象。同时在构造方法末尾创建了一个代理对象mProxyObject。继续2.16步的流程。
2.19 接下来要执行applyHooks()方法,这个方法的源码如下
protected void applyHooks() { if (hookObject == null) { return; } Class<? extends PatchObject> clazz = getClass(); Patch patch = clazz.getAnnotation(Patch.class); int version = Build.VERSION.SDK_INT; if (patch != null) { Class<? extends Hook>[] hookTypes = patch.value(); for (Class<? extends Hook> hookType : hookTypes) { ApiLimit apiLimit = hookType.getAnnotation(ApiLimit.class); boolean needToAddHook = true; if (apiLimit != null) { int apiStart = apiLimit.start(); int apiEnd = apiLimit.end(); boolean highThanStart = apiStart == -1 || version > apiStart; boolean lowThanEnd = apiEnd == -1 || version < apiEnd; if (!highThanStart || !lowThanEnd) { needToAddHook = false; } } if (needToAddHook) { addHook(hookType); } } } }
在上面的步骤中我们已经创建了HookObject对象,所以hookObject对象不为null,接着调用getClass方法获取当前类的类型,即ActivityManagerPatch类,然后获取该类的Patch类型的注解。在2.11步的代码中可以看出,ActivityManagerPatch类注解了patch类型,因此此处的patch不为null。首先是遍历patch注解的所有成员,以Hook_StartActivities类为例,此时hookType为Hook_StartActivities类,然后获取这个类的ApiLimit.class类型的注解。在Hook_StartActivities类中没有看到ApiLimit.class类型的注解,因此apiLImit为null,而needToAddHook因此还是为true,因此需要执行addHook方法。
2.20 addHook方法的源码如下
private void addHook(Class<? extends Hook> hookType) { try { Constructor<?> constructor = hookType.getDeclaredConstructors()[0]; if (!constructor.isAccessible()) { constructor.setAccessible(true); } Hook hook; if (constructor.getParameterTypes().length == 0) { hook = (Hook) constructor.newInstance(); } else { hook = (Hook) constructor.newInstance(this); } hookObject.addHook(hook); } catch (Throwable e) { throw new RuntimeException("Unable to instance Hook : " + hookType + " : " + e.getMessage()); } }
可以看出,在该方法中,主要工作就是创建了一个Hook类型的对象,并将它添加到了hookObject对象中。接下来分析hookObject对象的addHook方法。
2.21 HookObject类的addHook方法源码如下所示
@Override public void addHook(Hook hook) { if (hook != null && !TextUtils.isEmpty(hook.getName())) { if (internalHookMapping.containsKey(hook.getName())) { VLog.w(TAG, "Hook(%s) from class(%s) have been added, can't add again.", hook.getName(), hook.getClass().getName()); } internalHookMapping.put(hook.getName(), hook); } }
首先,Hook_StartActivities类继承了Hook类,这里传进来的就是一个Hook_StartActivities类对象,很容易判断应该直接执行internalHookMapping.put(hook.getName(), hook)这行代码。internalHookMapping是一个Map对象,存放了需要hook的类,此处将Hook_StartActivities类存放了进去。再回到主流程2.16中。
2.22 接下来要执行afterHookApply(hookObject)代码,它是一个空方法,暂时未执行。
2.23 回到流程2.13中,此时调用getProxyObject()方法,它返回的是2.18步中创建的代理对象mProxyObject。因此isEnvBad方法的返回值为true,再回到2.12中,此时就会执行injectable.inject()
2.24 以ActivityManagerPatch类为例,它的inject源码如下
@Override public void inject() throws Throwable { Field f_gDefault = ActivityManagerNative.class.getDeclaredField("gDefault"); if (!f_gDefault.isAccessible()) { f_gDefault.setAccessible(true); } if (f_gDefault.getType() == IActivityManager.class) { f_gDefault.set(null, getHookObject().getProxyObject()); } else if (f_gDefault.getType() == Singleton.class) { Singleton gDefault = (Singleton) f_gDefault.get(null); Field f_mInstance = Singleton.class.getDeclaredField("mInstance"); if (!f_mInstance.isAccessible()) { f_mInstance.setAccessible(true); } f_mInstance.set(gDefault, getHookObject().getProxyObject()); } else { // 不会经过这里 throw new UnsupportedOperationException("Singleton is not visible in AMN."); }
从上面代码可以看出,这个函数就是将AMS的代理对象gDefault给替换掉,替换成2.18步创建的代理对象mProxyObject。
2.25 回到流程2.9,此时patchManager.checkEnv()执行完毕,接下来执行RuntimeEnv.init(),init方法的源码如下所示
public static void init() { sUIHandler = new Handler(Looper.getMainLooper()); }
可以看出,它只是创建了一个以MainLooper为参数的Handler对象。接下来回到流程2.9,接着执行PatchManager.fixContext(context)。
2.26 fixContext方法的源码如下
public static void fixContext(Context context) { while (context instanceof ContextWrapper) { context = ((ContextWrapper) context).getBaseContext(); } try { Reflect.on(context).set("mPackageManager", null); context.getPackageManager(); } catch (Throwable e) { // Ignore } }
首先,获取了父类ContextWrapper的mBase对象,mBase是一个contextImpl对象,实现了context的功能,,然后将mBase覆盖原有context。接着调用Reflect类的on方法。
2.27 on方法的源码如下所示
public static Reflect on(Object object) { return new Reflect(object); }
在on方法中,直接以传入的context为参数构建了一个新的Reflect对象,接下来调用这个新的Reflect对象的set方法。
2.28 Reflect类的set方法源码如下所示
public Reflect set(String name, Object value) throws ReflectException { try { Field field = field0(name); field.setAccessible(true); field.set(object, unwrap(value)); return this; } catch (Exception e) { throw new ReflectException(e); } }
首先调用field0方法。
2.29 field0方法的源码如下所示
private Field field0(String name) throws ReflectException { Class<?> type = type(); // 先尝试取得公有字段 try { return type.getField(name); } // 此时尝试非公有字段 catch (NoSuchFieldException e) { do { try { return accessible(type.getDeclaredField(name)); } catch (NoSuchFieldException ignore) { } type = type.getSuperclass(); } while (type != null); throw new ReflectException(e); } }
首先通过调用type方法获取上面在创建Reflect对象时所传入的context对象的类类型,然后获取该类的字段mPackageManager。回到2.28中,接下来将context对象的mPackageManager字段置空。回到流程2.26中,接下来调用context.getPackageManager()。
2.30 contextImpl类的getPackageManager方法源码如下
@Override public PackageManager getPackageManager() { if (mPackageManager != null) { return mPackageManager; } IPackageManager pm = ActivityThread.getPackageManager(); if (pm != null) { return (mPackageManager = new ApplicationPackageManager(this, pm)); } return null; }
由于在2.28步中将context对象的mPackageManager字段置空,所以此时会创建一个新的PackageManager类对象,并将其赋给mPackageManager字段。回到2.9,将isStartUp字段置为true,表明已经启动。至此,VirtualCore.getCore().startup(base)执行完毕。
三、在VApp的onCreate方法中注册进程管理器,管理进程变化。
3.1 VApp的onCreate方法源码如下所示
@Override public void onCreate() { gDefault = this; super.onCreate(); if (VirtualCore.getCore().isMainProcess()) { Once.initialise(this); LocalProcessManager.registerProcessObserver(new IProcessObserver.Stub() { @Override public void onProcessCreated(String pkg, String processName) throws RemoteException { VLog.d("VProcess", "Process created: %s -> %s.", pkg, processName); } @Override public void onProcessDied(String pkg, String processName) throws RemoteException { VLog.d("VProcess", "Process died: %s -> %s.", pkg, processName); } }); } }
首先,将当前类对象传给gDefault,然后调用VirtualCore类的isMainProcess方法判断当前类是否为主进程,如果是的话再进行进一步处理。先调用Once类进行初始化,然后调用LocalProcessManager类的registerProcessObserver方法,
3.2 registerProcessObserver方法的源码如下所示
public static void registerProcessObserver(IProcessObserver observer) { try { getService().registerProcessObserver(observer); } catch (RemoteException e) { e.printStackTrace(); } }
首先调用getService方法获取一个service对象,然后进一步调用了这个service对象的registerProcessObserver方法。
3.3 首先看一下gerService方法的源码
private static IProcessManager service; private static IProcessManager getService() { if (service == null) { synchronized (LocalProcessManager.class) { if (service == null) { IBinder binder = ServiceManagerNative.getService(ServiceManagerNative.PROCESS_MANAGER); service = IProcessManager.Stub.asInterface(binder); } } } if (service == null) { throw new RuntimeException("Unable to attach ProcessManager"); } return service; }
可以看到方法最后是调用了ServiceManagerNative的getService方法获取了一个binder对象,然后将此binder对象包装后传给service。可以看到,此处代码与2.4处相同,执行到最后会调用contentResolver的call方法来获取Bundle对象,然后从该Bundle对象中取出保存在对象里面的Binder对象。
至此,VA的Application启动过程就分析完成。
- VirtualApp框架--- Application启动过程
- VirtualApp原理解析(4)--双开应用启动过程
- Application启动过程初探
- 对 VirtualApp hook过程的理解
- Android 启动过程框架
- JBoss Application Server的启动过程
- 基于StoryBoard的Application的启动过程
- org.tinygroup.application-应用启动框架
- org.tinygroup.application-应用启动框架
- Asterisk内核框架(2)--启动过程
- Mina 框架源码解析-NioSocketAcceptor启动过程
- android 基础框架和启动过程
- laravel框架的启动过程分析
- Android应用框架之应用启动过程
- Delta3d框架学习--程序启动过程详解
- Android 双开沙箱 VirtualApp 源码分析(三)App 启动
- Android 双开沙箱 VirtualApp 源码分析(四)启动插件 Service
- spring 启动过程 各个application context 的创建过程(重要)
- 进阶项目8.3-学生成绩系统
- C# 静态类和静态函数
- BZOJ4444 SCOI2015国旗计划 根据性质优化贪心
- 窗口和消息
- 初识Akka之Router
- VirtualApp框架--- Application启动过程
- es6-特性整理
- java-基础-类与继承
- Android 4.2 API 变更
- C#控制台 foreach处理二维数组
- 告诉你Hadoop是什么
- 多线程之线程安全初探
- SDUT3335数据结构实验之栈八:栈的基本操作(栈)
- 守护进程