Android8.1源码讲解之ActivityThread启动Activity

本文深入探讨Android8.1的ActivityThread启动Activity的细节,从ActivityThread的main方法开始,讲解AMS的attachApplication过程,包括StackSupervisor的attachApplicationLocked和realStartActivityLocked步骤,再到ApplicationThread如何通过scheduleLaunchActivity、Handler消息处理,直至handleLaunchActivity和performLaunchActivity,完成Activity的启动。文章最后对整个流程进行了总结,并预告了后续可能涉及的深入话题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在上一篇文章有说ActivityThread启动的过程,最后讲解到ActivityThread的main函数启动。这篇文章接上篇文章讲解main方法中怎么启动Activity的,方便日后讲解有关Activity中的事件处理机制。

一、ActivityThread中main方法

public static void main(String[] args) {
    SamplingProfilerIntegration.start();

    // CloseGuard defaults to true and can be quite spammy.  We
    // disable it here, but selectively enable it later (via
    // StrictMode) on debug builds, but using DropBox, not logs.
    CloseGuard.setEnabled(false);

    Environment.initForCurrentUser();

    // Set the reporter for event logging in libcore
    EventLogger.setReporter(new EventLoggingReporter());

    Process.setArgV0("<pre-initialized>");

    //准备主线程中的Loop启动
    Looper.prepareMainLooper();
    //创建ActivityThread实例
    ActivityThread thread = new ActivityThread();
    //ActivityThread内容绑定
    thread.attach(false);

    if (sMainThreadHandler == null) {
 
 //获取主线程中的Handler
        sMainThreadHandler = thread.getHandler();
    }

    AsyncTask.init();

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    //启动主线中的Handler消息机制的loop
    Looper.loop();

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

这里完成了ActivityThread的实例的创建,然后进行绑定操作。在这里还完成了主线程也就是UI中的looper的启动,以便日后使用Handler消息机制。接下来要看一下ActivityThread的绑定Application的过程,接下来看一下ActivityThread中的attach方法。

//在这里是启动的ActivityThread不是系统,在main方法中已经看到传递过来的是false
private void attach(boolean system) {
    sThreadLocal.set(this);
    mSystemThread = system;
    if (!system) {
        ViewRootImpl.addFirstDrawHandler(new Runnable() {
            public void run() {
                ensureJitEnabled();
            }
        });
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                UserHandle.myUserId());
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        //获取远程AMS的代理对象
        IActivityManager mgr = ActivityManagerNative.getDefault();
        //调用AMS中attachApplication方法,mAppThread在类加载的时候已经进行了初始化
        //在以后Activity的start、stop、resume以及显示都是mAppThread进行的
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            // Ignore
        }
    } else {
        // Don't set application object here -- if the system crashes,
        // we can't display an alert, we just want to die die die.
        android.ddm.DdmHandleAppName.setAppName("system_process",
                UserHandle.myUserId());
        try {
            mInstrumentation = new Instrumentation();
            ContextImpl context = new ContextImpl();
            context.init(getSystemContext().mPackageInfo, null, this);
            Application app = Instrumentation.newApplication(Application.class, context);
            mAllApplications.add(app);
            mInitialApplication = app;
            app.onCreate();
        } catch (Exception e) {
            throw new RuntimeException(
                    "Unable to instantiate Application():" + e.toString(), e);
        }
    }

    // add dropbox logging to libcore
    DropBox.setReporter(new DropBoxReporter());

    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
        public void onConfigurationChanged(Configuration newConfig) {
            synchronized (mPackages) {
                // We need to apply this change to the resources
                // immediately, because upon returning the view
                // hierarchy will be informed about it.
                if (applyConfigurationToResourcesLocked(newConfig, null)) {
                    // This actually changed the resources!  Tell
                    // everyone about it.
                    if (mPendingConfiguration == null ||
                            mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                        mPendingConfiguration = newConfig;

                        queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
                    }
                }
            }
        }
        public void onLowMemory() {
        }
        public void onTrimMemory(int level) {
        }
    });
}
在这里获取到远程AMS的代理对象,然后调用AMS方法进行Application的绑定工作。在这里有说到mAppThread这个成员变量,是ApplicationThreadNative的实例,在以后的操作Activity的操作都是在ApplicationThreadNative中进行的,这里不在详说。接下来就又回到了AMS中。

二、AMS中attachApplication

1、AMS的attachApplication

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

private final boolean attachApplicationLocked(IApplicationThread thread,
                                              int pid) {

    // Find the application record that is being attached...  either via
    // the pid if we are running in multiple processes, or just pull the
    // next app record if we are emulating process with anonymous threads.
    ProcessRecord app;
    long startTime = SystemClock.uptimeMillis();
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            //由pid获取进程记录
            app = mPidsSelfLocked.get(pid);
        }
    } else {
        app = null;
    }

    if (app == null) {
 
 //如果不存在则做相应处理
        Slog.w(TAG, "No pending application record for pid " + pid
                + " (IApplicationThread " + thread + "); dropping process");
        EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
        if (pid > 0 && pid != MY_PID) {
            killProcessQuiet(pid);
            //TODO: killProcessGroup(app.info.uid, pid);
        } else {
            try {
                thread.scheduleExit();
            } catch (Exception e) {
                // Ignore exceptions.
            }
        }
        return false;
    }

    // If this application record is still attached to a previous
    // process, clean it up now.
    //如果当前进程记录已经和其他应用进程绑定了这里进行删除操作
    if (app.thread != null) {
        handleAppDiedLocked(app, true, true);
    }

    // Tell the process all about itself.

    if (DEBUG_ALL) Slog.v(
            TAG, "Binding process pid " + pid + " to record " + app);

    final String processName = app.processName;
    try {
        AppDeathRecipient adr = new AppDeathRecipient(
                app, pid, thread);
        thread.asBinder().linkToDeath(adr, 0);
        app.deathRecipient = adr;
    } catch (RemoteException e) {
        app.resetPackageList(mProcessStats);
        startProcessLocked(app, "link fail", processName);
        return false;
    }

    EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName)
<think>好的,我需要回答用户关于Android中HostingRecord的问题,特别是它记录的内容以及如何通过它确定当前应用是由哪个应用拉起的。首先,我需要确认HostingRecord的基本定义和作用。根据用户提供的引用,可能涉及到ActivityServiceConnectionsHolder、AppBindRecord、ConnectionRecord等类,这些可能与HostingRecord有关联,但引用中没有直接提到HostingRecord,可能需要依赖其他知识。 HostingRecord在Android系统中通常用于记录组件(如Activity、Service)的宿主信息,包括启动来源的应用。例如,当一个应用启动另一个应用的Activity或Service时,系统需要跟踪这种关系,以便进行权限管理和进程间通信。 接下来,我需要确定HostingRecord具体包含哪些字段。根据常见的Android源码结构,HostingRecord可能包含以下信息:宿主应用的包名、用户ID、进程信息、启动意图(Intent)等。这些信息帮助系统管理组件之间的依赖关系。 然后,如何通过HostingRecord确定当前应用是被哪个应用拉起的?可能需要通过获取当前组件(如Service或Activity)的HostingRecord,并从中提取发起者的包名或进程信息。例如,在启动Service时,AMS(ActivityManagerService)可能会记录发起者的HostingRecord,从而允许当前应用查询自己的启动来源。 用户提到的引用[3]中提到AMS中appServicesRestrictedInBackgroundLocked方法根据包名返回启动模式,这可能与HostingRecord的使用场景相关。当系统检查是否允许后台启动服务时,可能需要参考HostingRecord中的信息来判断发起者是否有权限。 需要注意的是,HostingRecord的具体实现可能因Android版本而异。例如,在Android 8.1中,持久性应用(android:persistent="true")可能有不同的处理方式,如引用[3]所述,系统可能允许它们拉起第三方服务,此时HostingRecord中的信息会被特别处理。 总结:HostingRecord记录宿主应用的详细信息,包括包名、UID等,开发者可以通过调试或反射机制获取这些信息,进而确定当前应用的启动来源。但需要注意的是,直接访问这些内部类可能需要系统权限或特定API,普通应用可能无法直接获取。</think>Android系统中的`HostingRecord`主要用于记录**组件宿主关系**和**跨进程调用来源**,尤其在Activity或Service启动时追踪发起方信息。以下是其核心内容与确定应用拉起关系的方法: --- ### **HostingRecord记录的关键信息** 1. **宿主标识** - 发起方应用包名(`callingPackage`)、用户ID(`callingUid`)及进程ID(`callingPid`),用于标识请求来源[^3]。 2. **组件类型** - 记录当前组件是`Activity`、`Service`还是其他类型(如`ContentProvider`)。 3. **启动参数** - 包含启动意图(`Intent`)、标志位(`flags`)等上下文信息,例如隐式启动或显式启动的差异[^1]。 --- ### **如何通过HostingRecord确定当前应用的拉起方** 1. **AMS中的关联逻辑** - 在`ActivityManagerService`(AMS)中,当通过`startActivity()`或`bindService()`跨进程启动组件时,会创建`HostingRecord`并关联到目标进程的`ProcessRecord`,其中保存调用方包名和UID[^2]。 - **关键代码逻辑示例**: ```java // 伪代码:AMS处理Service启动时记录HostingRecord HostingRecord hr = new HostingRecord(callingPackage, callingUid, "Service"); ProcessRecord targetApp = getProcessForService(hr); targetApp.addHostingRecord(hr); // 将记录绑定到目标进程 ``` 2. **调试信息获取** - 通过`dumpsys activity processes`命令可查看进程的HostingRecord信息,例如: ``` HostingRecord{com.example.launcher (uid=10234): Service} ``` 表示当前服务由包名`com.example.launcher`的应用拉起。 3. **反射获取(需系统权限)** - 在系统级应用中,可通过反射访问`ActivityThread`或`ProcessRecord`内部的`HostingRecord`字段: ```java // 示例:获取当前进程的HostingRecord列表 Object activityThread = ActivityThread.currentActivityThread(); ProcessRecord pr = activityThread.getProcessRecord(); List<HostingRecord> records = pr.getHostingRecords(); // 实际字段名可能不同 ``` --- ### **注意事项** - **权限限制**:普通应用无法直接读取`HostingRecord`,需系统签名或`adb`调试权限。 - **版本差异**:在Android 8.1及更高版本中,后台启动限制(如`APP_START_MODE_NORMAL`)可能影响HostingRecord的生成逻辑[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值