App启动——Application的创建

news2024/10/2 8:23:42

Application的创建

一个 app 启动时候创建一个 Application 对象。这个对象的创建时间在 frameworks 中调用创建的,创建流程可见下图,涉及的几个主要的类调用。

Application创建流程

一、主线程运行入口

​ APP进程起来后,主线程运行入库 ActivityThread.main() 方法。

    ```java
    // ActivityThread.java
    
    @UnsupportedAppUsage
    final ApplicationThread mAppThread = new ApplicationThread();
    
    public static void main(String[] args) {
    	// ...
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
        // ...
    }
    
    @UnsupportedAppUsage
    private void attach(boolean system, long startSeq) {
        // ...
    
        if (!system) {
            // ...
    
            final IActivityManager mgr = ActivityManager.getService(); //获取 IActivityManager 对象。
            try {
                mgr.attachApplication(mAppThread, startSeq); // Binder 调用 AMS 的 attachApplicaion() 方法。
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
    		// ...
        }
    
        // ...
    }
    ```

运行启动是一般的app,并非 system app,因此进入到 if 分支。

二、ActivityManagerService 方法执行

从app主线程执行,进而跨进程调用到 ActivityManagerServiceattachApplication(IApplicationThread thread, long startSeq) 方法。

// ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    if (thread == null) {
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}

@GuardedBy("this")
private void attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
	// ......  这里的一个比较重要的数据是 appInfo:ApplicationInfo
    // if 分支内,表明运行的时候隔离状态的app,这样的app不能访问系统资源,服务及其他app进程。
    if (app.getIsolatedEntryPoint() != null) {
        // This is an isolated process which should just call an entry point instead of
        // being bound to an application.
        thread.runIsolatedEntryPoint(
                app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
    } else if (instr2 != null) {
        thread.bindApplication(processName, appInfo,
                app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                providerList,
                instr2.mClass,
                profilerInfo, instr2.mArguments,
                instr2.mWatcher,
                instr2.mUiAutomationConnection, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.getCompat(), getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions,
                app.getDisabledCompatChanges(), serializedSystemFontMap,
                app.getStartElapsedTime(), app.getStartUptime());
    } else {
        thread.bindApplication(processName, appInfo,
                app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                providerList, null, profilerInfo, null, null, null, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.getCompat(), getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions,
                app.getDisabledCompatChanges(), serializedSystemFontMap,
                app.getStartElapsedTime(), app.getStartUptime());
    }
	// ......
}

在内部调用到 attachApplicationLocked() 方法,在方法内部,会执行到 bindApplication() 方法,除非运行的app是一个独立APP,即不访问系统任何资源。这个方法里还有一个重要的数据变量是 appInfo 表示了应用的信息,会在调用 bindApplication() 方法时传递给 ApplicationThread 对象方法。

三、ApplicationThread.bindApplication()

// ActivityThread.java

private class ApplicationThread extends IApplicationThread.Stub {
    @Override
    public final void bindApplication(String processName, ApplicationInfo appInfo,
            String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,
            ProviderInfoList providerList, 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, AutofillOptions autofillOptions,
            ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges,
            SharedMemory serializedSystemFontMap,
            long startRequestedElapsedTime, long startRequestedUptime) {
        // ......
        
            AppBindData data = new AppBindData();
            // 构建 AppBindData 数据结构。
            updateCompatOverrideScale(compatInfo);
            CompatibilityInfo.applyOverrideScaleIfNeeded(config);
            sendMessage(H.BIND_APPLICATION, data);  // 发送消息。
    }
}

ActivityManagerService 中进行执行后,获取必要的信息,然后执行回到 ApplicationThread 的 app 进程 bindApplication() 方法中,并构建 AppBindData 数据对象,最终发送消息 H.BIND_APPLICATION 进入消息队列等待执行。

四、handleBindApplication(AppBindData data)

通过消息机制执行到 handleMessage(Message msg),依据消息 whatBIND_APPLICATION 执行方法 handleBindApplication(AppBindData data)

// ActivityThread.java

@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
	// ...
    // 获取 LoadedApk 类型对象 
    data.info = getPackageInfo(data.appInfo, mCompatibilityInfo, null /* baseLoader */,  
    							false /* securityViolation */, true /* includeCode */,
    							false /* registerPackage */, isSdkSandbox);
    
    // ...
    // 获取 ActivityManagerService 的 Binder 句柄
    final IActivityManager mgr = ActivityManager.getService();   
    // 创建 Context 上下文对象
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);    
    
    // ...
    Application app;
    // ...
        try {
			// 通过 LoadedApk 对象创建 Application 对象,内部具体实现细节,并且调用到了 Application.attach(Coext)。
		    // 在 attach(Context) 方法内调用从 ContextWrapper 继承而来的 attachBaseContext(Context),设置 mBaseContext 的实例变量。 
            app = data.info.makeApplicationInner(data.restrictedBackupMode, null);
            // ...
        } finally {
            // ...
        }
		// ...
        try {
            mgr.finishAttachApplication(mStartSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
}

执行 handleBindApplication() 方法传入参数 AppBindData ,在最终创建 Application 前,data.info 被赋值 。接着调用到 LoadedApk.makeApplicationInner(boolean forceDefaultAppClass, Instrumentation instrumentation)

// LoadedApk.java

public Application makeApplicationInner(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    return makeApplicationInner(forceDefaultAppClass, instrumentation,
            /* allowDuplicateInstances= */ false);
}

private Application makeApplicationInner(boolean forceDefaultAppClass,
        Instrumentation instrumentation, boolean allowDuplicateInstances) {
    if (mApplication != null) {
        return mApplication;
    }

	// ...
    Application app = null;

    final String myProcessName = Process.myProcessName();
    String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess(
            myProcessName);
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    try {
        final java.lang.ClassLoader cl = getClassLoader();
		// ...
        // 创建方式与 ActivityThread 中 handleBindApplication 创建方式一致。
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); 
 		// ...
        // 创建 Application
        app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
		// ...
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;
	// ...
    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app); // 调用了 Application 的声明周期方法 onCreate
        } catch (Exception e) {
           // ...
        }
    }
    return app;
}

最终调用的 Application 对象是在 Instrumentation 中创建。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1180307.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker DeskTop的安装(Windows版本)

目录 一、官网下载Docker安装包 二、安装Docker DeskTop 2.1 双击 Docker Installer.exe 以运行安装程序 2.2 安装操作 2.3 关于更改Docker安装位置 2.3.1 自定义安装路径(不推荐) 2.3.2 移动 Docker 镜像存储位置 三、启动Docker DeskTop 一、官…

GaussDB SQL基础语法-变量常量

目录 一、前言 二、GaussDB数据库中的常量和变量的基本概述及语法定义 1、变量定义 2、常量定义 3、其他(%TYPE、%ROWTYPE属性) 三、在GaussDB数据库中如何使用变量&常量(示例) 示例一,定义常量&变量&a…

有什么软件可以管控员工的电脑桌面

信息化的快速发展,员工在工作中使用电脑的情况越来越普遍。然而,员工在使用电脑时可能会出现工作效率低下、滥用公司资源等问题,因此对员工电脑进行监测和管理显得尤为重要。 1、域之盾软件 它是一款功能强大的电脑监控软件,可以…

(二)Spring源码解析:默认标签解析

一、概述 还记得我们在上一讲末尾提到的关于默认标签解析和自定义标签解析吧。本讲就来针对默认标签解析进行讲解。为了便于衔接上一讲的内容,我们将源码部分粘贴出来: 从上图中的源码中,我们可以看出默认标签的解析是在parseDefaultElement…

Unit2_1:动态规划DP

文章目录 一、介绍二、0-1背包问题问题描述分析伪代码时间复杂度 三、钢条切割问题问题描述分析伪代码过程 四、矩阵链乘法背景性质分析案例伪代码 一、介绍 动态规划类似于分治法,它们都将一个问题划分为更小的子问题 最优子结构:问题的最优解包含子问题的最优解。DP适用的原…

一种单总线串口通信的调试方法

单总线的优点: 节省IO口,发送时可以将单片机的RXD设置为普通IO进行软件模拟发送,发送完设置为串口接收。避免通信干扰,由于是通过IO口对三极管/MOS管进行拉高拉低,外部信号不易对IO口进行干扰,EMI&#xf…

代码随想录算法训练营第四十六天 | LeetCode 139. 单词拆分、多重背包、背包总结

代码随想录算法训练营第四十六天 | LeetCode 139. 单词拆分、多重背包、背包总结 文章链接:单词拆分 多重背包 背包总结 视频链接:单词拆分 1. LeetCode 139. 单词拆分 1.1 思路 本题的那些单词就是物品,字符串就是背包,问用这些…

大数据学习之一文学会Spark【Spark知识点总结】

文章目录 什么是SparkSpark的特点Spark vs HadoopSparkHadoopSpark集群安装部署Spark集群安装部署StandaloneON YARN Spark的工作原理什么是RDDRDD的特点Spark架构相关进程Spark架构原理 Spark实战:单词统计Scala代码开发java代码开发任务提交 Transformation与Acti…

echarts 类目轴设置xAxis.interval不起效果

情景:在xAxis.typecategory;设置xAxis.interval不起效果; 解决方案:通过设置xAxis.axisLabel.interval属性

【H616_语言小美_控制安卓刷抖音项目 orangePi zero2 (已开源) 】.md uptada:23/11/07

文章目录 H616_语言小美_控制安卓刷抖音项目小美效果展示H616 ubuntu系统 安装adb智能公元 SU-03T 离线语音模组 固件制作配合串口实现 小美_控制安卓刷抖音 H616_语言小美_控制安卓刷抖音项目 注意:orangePi zero2 H616 安装系统为ubuntu 小美效果展示 语言小美 …

企业级私有化部署数字办公工具集合,解决企业全方位需求,快收藏

随着信息技术的日新月异,企业对IT建设的依赖程度越来越高。为了满足这一需求,软开企服凭借积累了多年的项目经验,推出了一款名为JVS的私有化部署企业信息化底座。JVS涵盖了多个产品领域,如协同办公、低代码开发、数据分析、风控决…

KaiOS APN配置文件apn.json调试验证方法(无需项目全编)

1、KaiOS 的应用就类似web应用,结合文件夹路径webapp字面意思理解。 2、KaiOS APN配置文件源代码在apn.json, (1)apn.json可以自定义路径,通过配置脚本实现拷贝APN在编译时动态选择路径在机器中生效。 (…

linux复习笔记03(小滴课堂)

find命令: d查找目录: 按照文件权限查找: 600全部权限: -user根据所属主: 上面的例子是找出文件并打印有多少行。 我们也可以把我们查询到的结果复制到其它文件位置中去: 复制成功。 -mtime根据修改时间…

DOCTYPE是什么,有何作用、 使用方式、渲染模式、严格模式和怪异模式的区别?

前言 持续学习总结输出中,今天分享的是DOCTYPE是什么,有何作用、 使用方式、渲染模式、严格模式和怪异模式的区别。 DOCTYPE是什么,有何作用? DOCTYPE是HTML5的文档声明,通过它可以告诉浏览器,使用那个H…

MySQL的高阶语句

数据库的权限一般很小,工作中使用最多的场景就是查 排序、分组、子查询、视图、多表连接查询(左连接、右连接、内连接) create TABLE info ( id int(4) primary key, NAME varchar(5) not null, score decimal(5,2), address varchar(20)…

Django实战项目-学习任务系统-发送短信通知

接着上期代码内容,继续完善优化系统功能。 本次增加发送短信通知功能,学习任务系统发布的任务,为了更加及时通知到学生用户,再原有发送邮件通知基础上,再加上手机短信通知功能。 第一步:开通短信通知服务…

JSP通用材料收集归档系统eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 JSP 通用材料收集归档系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发,数据库为Mysql5.0&#xff0c…

计算机服务器中了eking勒索病毒怎么办,勒索病毒解密,文件数据恢复

随着科技的不断发展,网络技术也得到了不断更新,极大地方便了人们的生产与生活,但随之而来的网络安全威胁也不断增加,近期,网络上的eking勒索病毒开始流行,它是phobos勒索家族中的一种病毒,具有较…

红黑树的性质和实现

红黑树 由于AVL树为了保持平衡需要经常旋转,开销是很大的。因此,红黑树比起AVL树放宽了平衡的限制。 概念 红黑树,在每个节点上增加一个存储位表示节点的颜色,可以是RED或BLACK。 通过对任何一条从根到叶子的路径上各个结点着…

EGpKa

利用数据增强的可解释图神经网络预测碳氢化合物的 pKa,原文 Explainable Graph Neural Networks with Data Augmentation for Predicting pKa of C–H Acids,代码在 DATA AND SOFTWARE AVAILABILITY。模型框架如下: