【Android 启动过程】Activity 启动源码分析 ( ActivityThread 流程分析 一 )

2023-03-29 17:17:54 浏览数 (1)

文章目录

  • 一、ActivityThread 主函数启动
  • 二、ActivityThread 绑定 ApplicationThread
  • 三、AMS attachApplication -> attachApplicationLocked 绑定 ApplicationThread
  • 四、ApplicationThread.bindApplication 绑定 ApplicationThread
  • 五、ActivityThread.H 处理 BIND_APPLICATION 消息
  • 六、ActivityThread.handleBindApplication 处理绑定问题
  • 七、LoadedApk.makeApplication 创建 Application 对象
  • 八、Instrumentation.newApplication 创建 Application 对象
  • 九、AppComponentFactory.instantiateApplicationCompat 创建 Application 对象

一、ActivityThread 主函数启动


ActivityThread 是应用的主线程 , 从 main 函数开始执行 ;

Looper.prepareMainLooper() 将主线程设置为 Looper 线程 , 开启 Looper , 用于配合 H 处理消息 ;

thread.attach(false, startSeq) 绑定 ActivityThread ;

在方法最后 Looper.loop(); 开始无限循环 , 处理 Handler 消息 ;

代码语言:javascript复制
/**
 * 管理应用程序进程中主线程的执行、调度和执行活动、广播以及活动管理器请求的其他操作。
 *
 * {@hide}
 */
public final class ActivityThread extends ClientTransactionHandler {
    public static void main(String[] args) {

		// 将主线程设置为 Looper 线程 , 开启 Looper , 用于配合 H 处理消息 
        Looper.prepareMainLooper();

		// 创建 ActivityThread 实例对象 
        ActivityThread thread = new ActivityThread();
        // 绑定
        thread.attach(false, startSeq);
	
		// 开始无限循环 , 处理 Handler 消息 
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
}

完整代码参考 /frameworks/base/core/java/android/app/ActivityThread.java

二、ActivityThread 绑定 ApplicationThread


ActivityThread 中的 void attach(boolean system, long startSeq) 方法 , 主要是通过 Binder 机制获取 AMS , 并调用 AMS 的 attachApplication 方法 , 为 ActivityThread 绑定 ApplicationThread ;

代码语言:javascript复制
/**
 * 管理应用程序进程中主线程的执行、调度和执行活动、广播以及活动管理器请求的其他操作。
 *
 * {@hide}
 */
public final class ActivityThread extends ClientTransactionHandler {

    private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            // 通过 Binder 机制获取 AMS 
            final IActivityManager mgr = ActivityManager.getService();
            try {
            	// 调用 AMS 的 attachApplication 方法 , 为 ActivityThread 绑定 ApplicationThread 
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

}

完整代码参考 /frameworks/base/core/java/android/app/ActivityThread.java

三、AMS attachApplication -> attachApplicationLocked 绑定 ApplicationThread


在 AMS 中的 attachApplication 方法中 , 调用了 attachApplicationLocked 方法 ,

attachApplicationLocked 方法中 , 有调用了 ActivityThread 的 bindApplication 方法 , 为 ActivityThread 绑定了 ApplicationThread ;

代码语言:javascript复制
public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }


	// 为 ApplicationThread 绑定 Application 主方法
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        try {
            checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
            mStackSupervisor.mActivityMetricsLogger.notifyBindApplication(app);
			// 在此处为 ActivityThread 绑定 Application , 此时又回到 ActivityThread
            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);
            } 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);
            }
        } catch (Exception e) {
        }

        return true;
    }

}

ActivityManagerService 完整源码参考 : frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

四、ApplicationThread.bindApplication 绑定 ApplicationThread


再次回到 ActivityThread 内部类 ApplicationThread 中 , 调用 ApplicationThread 类的 bindApplication 方法 , 即可为 ActivityThread 绑定 ApplicationThread , 在所有数据就位后 , 发送了一个 H.BIND_APPLICATION 消息 ;

代码语言:javascript复制
/**
 * 管理应用程序进程中主线程的执行、调度和执行活动、广播以及活动管理器请求的其他操作。
 *
 * {@hide}
 */
public final class ActivityThread extends ClientTransactionHandler {
    private class ApplicationThread extends IApplicationThread.Stub {
		// 为 ActivityThread 绑定 Application 
        public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                String buildSerial, boolean autofillCompatibilityEnabled) {

            // 此处在所有数据就位后 , 发送了一个 H.BIND_APPLICATION 消息
            sendMessage(H.BIND_APPLICATION, data);
        }
	}
}

完整代码参考 /frameworks/base/core/java/android/app/ActivityThread.java

五、ActivityThread.H 处理 BIND_APPLICATION 消息


ActivityThread.ApplicationThread.bindApplication 中 , 发送了一条 BIND_APPLICATION 消息 ,

110

;

ActivityThread.H 中的 handleMessage 方法中 , 处理

110

事件的分支中, 调用了 handleBindApplication 方法 , 处理绑定 ApplicationThread 相关逻辑 ;

代码语言:javascript复制
/**
 * 管理应用程序进程中主线程的执行、调度和执行活动、广播以及活动管理器请求的其他操作。
 *
 * {@hide}
 */
public final class ActivityThread extends ClientTransactionHandler {
    class H extends Handler {
        public static final int BIND_APPLICATION        = 110;

        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: "   codeToString(msg.what));
            switch (msg.what) {
                case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    // 处理绑定 Application 相关逻辑
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
            }
            Object obj = msg.obj;
            if (obj instanceof SomeArgs) {
                ((SomeArgs) obj).recycle();
            }
        }
    }
}

完整代码参考 /frameworks/base/core/java/android/app/ActivityThread.java

六、ActivityThread.handleBindApplication 处理绑定问题


ActivityThread.handleBindApplication 方法中 , 通过调用 data.info.makeApplication(data.restrictedBackupMode, null) 方法 , 创建 Application 实例对象 ;

data.infoLoadedApk 类型 ;

代码语言:javascript复制
/**
 * 管理应用程序进程中主线程的执行、调度和执行活动、广播以及活动管理器请求的其他操作。
 *
 * {@hide}
 */
public final class ActivityThread extends ClientTransactionHandler {
    private void handleBindApplication(AppBindData data) {
        // 将UI线程注册为运行时的敏感线程。
        VMRuntime.registerSensitiveThread();
        if (data.trackAllocation) {
            DdmVmInternal.enableRecentAllocations(true);
        }

        // 记录进程开始时间
        Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());

        // 允许在应用程序和提供程序安装期间访问磁盘。
        // 这可能会阻止处理有序的广播,但稍后的处理可能最终会执行相同的磁盘访问。
        Application app;
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
        try {
            // 如果要启动应用程序进行完全备份或恢复,请使用基本应用程序类在受限环境中启动。
            app = data.info.makeApplication(data.restrictedBackupMode, null);

            // Propagate autofill compat state
            app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);

            mInitialApplication = app;
        } 
    }
}

完整代码参考 /frameworks/base/core/java/android/app/ActivityThread.java

七、LoadedApk.makeApplication 创建 Application 对象


调用 LoadedApkmakeApplication 方法 , 创建 Application 实例 , 在该方法中通过调用 InstrumentationnewApplication 方法 , 创建 Application 实例对象

代码语言:javascript复制
/**
 * 本地状态维护了当前加载的.apk. 
 * Local state maintained about a currently loaded .apk.
 * @hide
 */
public final class LoadedApk {

	// 创建 Application 实例对象 
    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        // 如果当前存在 Application , 直接返回 
        if (mApplication != null) {
            return mApplication;
        }

        try {
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            // 通过调用 Instrumentation 的 newApplication 方法 , 创建 Application 实例对象
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;

        return app;
    }
}

完整代码参考 /frameworks/base/core/java/android/app/LoadedApk.java ;

八、Instrumentation.newApplication 创建 Application 对象


LoadedApkmakeApplication 方法 中 , 调用了 InstrumentationnewApplication 方法创建 Application 实例对象 ;

代码语言:javascript复制
/**
 * 用于实现应用程序检测代码的基类。
 * 当在启用检测的情况下运行时,该类将在任何应用程序代码之前为您实例化,
 * 从而允许您监视系统与应用程序之间的所有交互。
 * 通过AndroidManifest.xml的&amp;lt;仪器仪表&amp;gt;标签。
 */
public class Instrumentation {

    /**
     * 执行进程{@link Application}对象的实例化。默认实现提供正常的系统行为。
     *
     * @param cl 用来实例化对象的类加载器。
     * @param className 实现应用程序对象的类的名称。
     * @param context 用于初始化应用程序的上下文
     *
     * @return 新实例化的应用程序对象。
     */
    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }
	
}

完整代码参考 /frameworks/base/core/java/android/app/Instrumentation.java ;

九、AppComponentFactory.instantiateApplicationCompat 创建 Application 对象


InstrumentationnewApplication 方法中 , 调用了 AppComponentFactoryinstantiateApplicationCompat 方法 , 创建 Application , (Application) cl.loadClass(className).getDeclaredConstructor().newInstance(); , 此处通过反射创建 Application 实例对象 ;

代码语言:javascript复制
/**
 * 使用androidx库的{@link android.app.AppComponentFactory}版本。
 *
 * 注意:这只适用于API 28 ,不支持AppComponentFactory功能。
 */
@RequiresApi(28)
public class AppComponentFactory extends android.app.AppComponentFactory {

   /**
    * 允许应用程序重写应用程序对象的创建。这可以用于对这些类执行依赖项注入或类装入器更改等操作。
    * <p>
    * 此方法仅用于提供用于实例化的挂钩。它不提供对应用程序对象的早期访问。
    * 返回的对象尚未初始化为上下文,不应用于与其他android API交互。
    *
    * @param cl        用于实例化的默认类加载器。
    * @param className 要实例化的类。
    */
    public @NonNull Application instantiateApplicationCompat(@NonNull ClassLoader cl,
            @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        try {
            return (Application) cl.loadClass(className).getDeclaredConstructor().newInstance();
        } catch (InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException("Couldn't call constructor", e);
        }
    }

}

完整代码参考 /frameworks/support/compat/src/main/java/androidx/core/app/AppComponentFactory.java ;

0 人点赞