文章目录
Android 插件化系列文章目录
一、插件包 Activity 启动原理
二、分析主线程中创建 Activity 实例源码
1、LaunchActivityItem
2、ActivityThread
三、使用 Hook 技术在主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件
1、反射获取 ActivityThread 类
2、反射获取 ActivityThread 单例对象
3、反射获取 mH 字段
4、反射获取 mH 对象
5、反射获取 Handler 中的 mCallback 字段
6、通过反射替换 Handler 中的 mCallback 成员
7、完整代码示例
四、用于替换 ActivityThread 中 mH 中的 mCallback 静态代理类
1、获取 ClientTransaction 类
2、验证 msg.obj 类型是否合法
3、反射获取 mActivityCallbacks 字段
4、反射获取 mActivityCallbacks 成员对象
5、使用插件 Activity 对应的 Intent 替换 LaunchActivityItem 类中的 mIntent 字段
6、完整代码示例
五、Hook Activity 启动流程涉及的完整代码
一、插件包 Activity 启动原理
使用动态代理 , 替换 android.app.ActivityManager 中的 private static final Singleton IActivityManagerSingleton 成员的 mInstance 成员 ;
注意 : 该操作一定要在 AMS 启动之前将原来的 Intent 替换掉 , 使用占坑的 Activity 替换插件包中的 Activity , 之后 AMS 执行完毕 , 执行到主线程 实例化 Activity 对象之前 , 还要替换回去 ;
插件包组件启动方式 : 使用 Intent 启动插件包时 , 一般都使用隐式启动 ; 调用 Intent 的 setComponent , 通过包名和类名创建 Component , 这样操作 , 即使没有获得 Activity 引用 , 也不会报错
该插件包中的 Activity 没有在 “宿主” 应用中注册 , 因此启动报错 ;
AMS 会干掉没有注册过的 Activity , 这里先 在启动 AMS 之前 , 设置一个已经 注册过的 占坑 Activity ( StubActivity ) 执行启动流程 , 在主线程生成 Activity 实例对象时 , 还需要恢复插件包中的 Activity
二、分析主线程中创建 Activity 实例源码
1、LaunchActivityItem
ActivityManagerService 执行 Activity 启动 , 执行了一系列的操作后 , 需要在主线程中进行实例化 , 这些操作暂时不管 , 与 Hook 无关 , 直接开始分析 主线程中的 Activity 实例化操作 ;
Activity 实例化的起点 , 从 LaunchActivityItem 源码开始分析 ;
LaunchActivityItem 类 , 继承了 ClientTransactionItem 类 ;
该类中重写了 execute 方法 , 其中调用了 client.handleLaunchActivity 方法 , 就是调用的 ActivityThread 的 handleLaunchActivity 方法 ;
public class LaunchActivityItem extends ClientTransactionItem { @Override public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState, mPendingResults, mPendingNewIntents, mIsForward, mProfilerInfo, client); client.handleLaunchActivity(r, pendingActions, null /* customIntent */); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } }
源码路径 : /frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java
2、ActivityThread
ActivityThread 中的 handleLaunchActivity 方法中调用了 performLaunchActivity ,
在 performLaunchActivity 方法中 , 进行了 Activity 的实例化操作 ;
activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent);
在 class H extends Handler 类中 , 处理 EXECUTE_TRANSACTION 信号时 , 启动了 LaunchActivityItem 的 execute 方法 , 进而调用 ActivityThread 中的 handleLaunchActivity 方法 , 创建 Activity 实例对象 ;
这里劫持该 Handler , 将插件包 Activity 替换到原来的 Activity 中 ;
ActivityThread 的相关源码 :
public final class ActivityThread extends ClientTransactionHandler { final H mH = new H(); /** Reference to singleton {@link ActivityThread} */ private static volatile ActivityThread sCurrentActivityThread; class H extends Handler { public static final int EXECUTE_TRANSACTION = 159; public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { case EXECUTE_TRANSACTION: final ClientTransaction transaction = (ClientTransaction) msg.obj; mTransactionExecutor.execute(transaction); if (isSystem()) { // Client transactions inside system process are recycled on the client side // instead of ClientLifecycleManager to avoid being cleared before this // message is handled. transaction.recycle(); } // TODO(lifecycler): Recycle locally scheduled transactions. break; } } } /** * Extended implementation of activity launch. Used when server requests a launch or relaunch. */ @Override public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); mSomeActivitiesChanged = true; if (r.profilerInfo != null) { mProfiler.setProfiler(r.profilerInfo); mProfiler.startProfiling(); } // Make sure we are running with the most recent config. handleConfigurationChanged(null, null); if (localLOGV) Slog.v( TAG, "Handling launch of " + r); // Initialize before creating the activity if (!ThreadedRenderer.sRendererDisabled) { GraphicsEnvironment.earlyInitEGL(); } WindowManagerGlobal.initialize(); final Activity a = performLaunchActivity(r, customIntent); if (a != null) { r.createdConfig = new Configuration(mConfiguration); reportSizeConfigurations(r); if (!r.activity.mFinished && pendingActions != null) { pendingActions.setOldState(r.state); pendingActions.setRestoreInstanceState(true); pendingActions.setCallOnPostCreate(true); } } else { // If there was an error, for any reason, tell the activity manager to stop us. try { ActivityManager.getService() .finishActivity(r.token, Activity.RESULT_CANCELED, null, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } return a; } /** Core implementation of activity launch. */ private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ActivityInfo aInfo = r.activityInfo; if (r.packageInfo == null) { r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE); } ComponentName component = r.intent.getComponent(); if (component == null) { component = r.intent.resolveActivity( mInitialApplication.getPackageManager()); r.intent.setComponent(component); } if (r.activityInfo.targetActivity != null) { component = new ComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity); } ContextImpl appContext = createBaseContextForActivity(r); Activity activity = null; try { java.lang.ClassLoader cl = appContext.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(); if (r.state != null) { r.state.setClassLoader(cl); } } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to instantiate activity " + component + ": " + e.toString(), e); } } try { Application app = r.packageInfo.makeApplication(false, mInstrumentation); if (localLOGV) Slog.v(TAG, "Performing launch of " + r); if (localLOGV) Slog.v( TAG, r + ": app=" + app + ", appName=" + app.getPackageName() + ", pkg=" + r.packageInfo.getPackageName() + ", comp=" + r.intent.getComponent().toShortString() + ", dir=" + r.packageInfo.getAppDir()); if (activity != null) { CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); if (r.overrideConfig != null) { config.updateFrom(r.overrideConfig); } if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " + r.activityInfo.name + " with config " + config); Window window = null; if (r.mPendingRemoveWindow != null && r.mPreserveWindow) { window = r.mPendingRemoveWindow; r.mPendingRemoveWindow = null; r.mPendingRemoveWindowManager = null; } appContext.setOuterContext(activity); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback); if (customIntent != null) { activity.mIntent = customIntent; } r.lastNonConfigurationInstances = null; checkAndBlockForNetworkAccess(); activity.mStartedActivity = false; int theme = r.activityInfo.getThemeResource(); if (theme != 0) { activity.setTheme(theme); } activity.mCalled = false; if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } if (!activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()"); } r.activity = activity; } r.setState(ON_CREATE); mActivities.put(r.token, r); } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to start activity " + component + ": " + e.toString(), e); } } return activity; } }
源码路径 : /frameworks/base/core/java/android/app/ActivityThread.java