Configuration Change派发到App进程

news2024/11/19 10:42:51

整体时序

在这里插入图片描述
在这里插入图片描述

// DisplayContent.java
boolean updateDisplayOverrideConfigurationLocked(Configuration values,
        ActivityRecord starting, boolean deferResume,
        ActivityTaskManagerService.UpdateConfigurationResult result) {

    int changes = 0;
    boolean kept = true;

    mAtmService.deferWindowLayout();
    try {
        if (values != null) {
            if (mDisplayId == DEFAULT_DISPLAY) {
                // 先触发进程相关的Configuration变化
                changes = mAtmService.updateGlobalConfigurationLocked(values,
                        false /* initLocale */, false /* persistent */,
                        UserHandle.USER_NULL /* userId */);
            } else {
                changes = performDisplayOverrideConfigUpdate(values);
            }
        }

        if (!deferResume) {
            // 再触发Activity相关的Configuration的变化
            kept = mAtmService.ensureConfigAndVisibilityAfterUpdate(starting, changes);
        }
    } finally {
        mAtmService.continueWindowLayout();
    }
    .....
}

进程级别ConfigurationChangeItem

主要是更新app进程的Resource中的Configuration并触发Application/Service/Provider等的onConfigurationChanged回调。

System server

// ATMS.java
int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
        boolean persistent, int userId) {

    ......
    Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig);
   ......
    SparseArray<WindowProcessController> pidMap = mProcessMap.getPidMap();
    for (int i = pidMap.size() - 1; i >= 0; i--) {
        final int pid = pidMap.keyAt(i);
        final WindowProcessController app = pidMap.get(pid);
        ProtoLog.v(WM_DEBUG_CONFIGURATION, "Update process config of %s to new "
                + "config %s", app.mName, mTempConfig);
        app.onConfigurationChanged(mTempConfig);
    }
    ......
}

在这里插入图片描述

// WindowProcessController.java
private void scheduleConfigurationChange(IApplicationThread thread, Configuration config) {
    ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName,
            config);
    ......
    mHasCachedConfiguration = false;
    try {
        mAtm.getLifecycleManager().scheduleTransaction(thread,
                ConfigurationChangeItem.obtain(config, mLastTopActivityDeviceId));
    } catch (Exception e) {
        Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change: " + mOwner, e);
    }
}

App

// ConfigurationController.java
void handleConfigurationChanged(@Nullable Configuration config,
        @Nullable CompatibilityInfo compat) {
   ......
    synchronized (mResourcesManager) {
        ......
        // 先更新Resource中的Configuration的值
        mResourcesManager.applyConfigurationToResources(config, compat);
        ......
    }
    final ArrayList<ComponentCallbacks2> callbacks =
            mActivityThread.collectComponentCallbacks(false /* includeUiContexts */);

    freeTextLayoutCachesIfNeeded(configDiff);

    if (callbacks != null) {
        final int size = callbacks.size();
        for (int i = 0; i < size; i++) {
            ComponentCallbacks2 cb = callbacks.get(i);
            if (!equivalent) {
                // 再触发Application/Service/Provider等的回调
                performConfigurationChanged(cb, config);
            }
        }
    }
}

在这里插入图片描述

Activity级别

处理的两种方式

针对Activity级别的处理,relaunch当前Activity或触发当前Actiivty回调onConfigurationChanged方法,只会发生其一。

  • app在AndroidManifest.xml中配置对应的configChanges,则触发Activity回调onConfigurationChanged方法
  • 否则直接执行relaunch操作
ActivityRelaunchItem

如果app未在AndroidManifest.xml中配置对应的configChanges,则当configuration更改时会触发当前top页面的relaunch,对应的event log如下:

10-10 16:12:05.951  3972  8346 I configuration_changed: 512
10-10 16:12:06.021  3972  8346 I wm_relaunch_resume_activity: [0,237413577,21,com.miui.gallery/.activity.MapActivity,200]
10-10 16:12:06.022  3972  8346 I wm_relaunch_activity: [0,218943334,21,com.miui.gallery/.activity.HomePageActivity,200]
// top resume的页面重建后仍然停留在onResume的状态
10-10 16:12:06.244 20930 20930 I wm_on_top_resumed_lost_called: [237413577,com.miui.gallery.activity.MapActivity,pausing]
10-10 16:12:06.284 20930 20930 I wm_on_paused_called: [0,237413577,com.miui.gallery.activity.MapActivity,performPause,39]
10-10 16:12:06.294 20930 20930 I wm_on_stop_called: [0,237413577,com.miui.gallery.activity.MapActivity,handleRelaunchActivity,2]
10-10 16:12:06.328 20930 20930 I wm_on_destroy_called: [0,237413577,com.miui.gallery.activity.MapActivity,performDestroy,32]
10-10 16:12:06.461 20930 20930 I wm_on_create_called: [0,237413577,com.miui.gallery.activity.MapActivity,performCreate,29]
10-10 16:12:06.599 20930 20930 I wm_on_start_called: [0,237413577,com.miui.gallery.activity.MapActivity,handleStartActivity,135]
10-10 16:12:06.603 20930 20930 I wm_on_resume_called: [0,237413577,com.miui.gallery.activity.MapActivity,RESUME_ACTIVITY,2]
10-10 16:12:06.603 20930 20930 I wm_on_top_resumed_gained_called: [237413577,com.miui.gallery.activity.MapActivity,topWhenResuming]

// 可见但是pause的页面重建后最终状态仍然是onPause
10-10 16:12:06.625 20930 20930 I wm_on_stop_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,handleRelaunchActivity,6]
10-10 16:12:06.649 20930 20930 I wm_on_destroy_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performDestroy,13]
10-10 16:12:06.701 20930 20930 I wm_on_create_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performCreate,34]
10-10 16:12:06.903 20930 20930 I wm_on_start_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,handleStartActivity,199]
10-10 16:12:06.910 20930 20930 I wm_on_resume_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,LIFECYCLER_RESUME_ACTIVITY,5]
10-10 16:12:06.926 20930 20930 I wm_on_paused_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performPause,1]

传送一个ClientTransaction到app进程:

  • 如果应该resume:ActivityRelaunchItem(处理Activity重建) & ResumeActivityItem (处理最终生命周期)
  • 否则:ActivityRelaunchItem & PauseActivityItem
void relaunchActivityLocked(boolean preserveWindow) {
    ......
    if (andResume) {
        EventLogTags.writeWmRelaunchResumeActivity(mUserId, System.identityHashCode(this),
                task.mTaskId, shortComponentName, Integer.toHexString(configChangeFlags));
    } else {
        EventLogTags.writeWmRelaunchActivity(mUserId, System.identityHashCode(this),
                task.mTaskId, shortComponentName, Integer.toHexString(configChangeFlags));
    }

    startFreezingScreenLocked(0);

    try {
       ......
        final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
                pendingNewIntents, configChangeFlags,
                new MergedConfiguration(getProcessGlobalConfiguration(),
                        getMergedOverrideConfiguration()),
                preserveWindow);
        final ActivityLifecycleItem lifecycleItem;
        if (andResume) {
            lifecycleItem = ResumeActivityItem.obtain(isTransitionForward(),
                    shouldSendCompatFakeFocus());
        } else {
            lifecycleItem = PauseActivityItem.obtain();
        }
        final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), token);
        transaction.addCallback(callbackItem);
        transaction.setLifecycleStateRequest(lifecycleItem);
        mAtmService.getLifecycleManager().scheduleTransaction(transaction);
    } catch (RemoteException e) {
        ProtoLog.i(WM_DEBUG_STATES, "Relaunch failed %s", e);
    }
   ......
}

然后根据ResumeActivityItem和PauseActivityItem执行相应的生命周期,一般top Activity执行onResume,底下的执行onPause。
在这里插入图片描述

ActivityConfigurationChangeItem

如果没有在功能清单文件配置对应的configChanges,则会触发app当前的Activity执行onConfigurationChanged方法,主要是post一个ActivityConfigurationChangeItem到app进程(区分于进程级别的ConfigurationChangeItem)。
在这里插入图片描述

更新top Activity的Configuration

10-10 16:12:05.951  3972  8346 I configuration_changed: 512
10-10 16:12:06.021  3972  8346 I wm_relaunch_resume_activity: [0,237413577,21,com.miui.gallery/.activity.MapActivity,200]
// top resume的页面重建后仍然停留在onResume的状态
10-10 16:12:06.244 20930 20930 I wm_on_top_resumed_lost_called: [237413577,com.miui.gallery.activity.MapActivity,pausing]
10-10 16:12:06.284 20930 20930 I wm_on_paused_called: [0,237413577,com.miui.gallery.activity.MapActivity,performPause,39]
10-10 16:12:06.294 20930 20930 I wm_on_stop_called: [0,237413577,com.miui.gallery.activity.MapActivity,handleRelaunchActivity,2]
10-10 16:12:06.328 20930 20930 I wm_on_destroy_called: [0,237413577,com.miui.gallery.activity.MapActivity,performDestroy,32]
10-10 16:12:06.461 20930 20930 I wm_on_create_called: [0,237413577,com.miui.gallery.activity.MapActivity,performCreate,29]
10-10 16:12:06.599 20930 20930 I wm_on_start_called: [0,237413577,com.miui.gallery.activity.MapActivity,handleStartActivity,135]
10-10 16:12:06.603 20930 20930 I wm_on_resume_called: [0,237413577,com.miui.gallery.activity.MapActivity,RESUME_ACTIVITY,2]
10-10 16:12:06.603 20930 20930 I wm_on_top_resumed_gained_called: [237413577,com.miui.gallery.activity.MapActivity,topWhenResuming]
// ATMS.java
/** Applies latest configuration and/or visibility updates if needed. */
boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
    boolean kept = true;
    final Task mainRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
    // mainRootTask is null during startup.
    if (mainRootTask != null) {
        if (changes != 0 && starting == null) {
            // If the configuration changed, and the caller is not already
            // in the process of starting an activity, then find the top
            // activity to check if its configuration needs to change.
            starting = mainRootTask.topRunningActivity();
        }

        if (starting != null) {
            // 更新top running页面的configuration
            kept = starting.ensureActivityConfiguration(changes,
                    false /* preserveWindow */);
            // And we need to make sure at this point that all other activities
            // are made visible with the correct configuration.
            // 更新其它可见的Activity的configuration
            mRootWindowContainer.ensureActivitiesVisible(starting, changes,
                    !PRESERVE_WINDOWS);
        }
    }

    return kept;
}

在这里插入图片描述

更新其它可见的Activity的Configuration

// EnsureActivitiesVisibleHelper.java
private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
        final boolean resumeTopActivity) {
    .....
    final boolean reallyVisible = r.shouldBeVisibleUnchecked();
    ......
    // 如果可见且不是top
    if (reallyVisible) {
       .....
        // First: if this is not the current activity being started, make
        // sure it matches the current configuration.
        if (r != mStarting && mNotifyClients) {
            r.ensureActivityConfiguration(0 /* globalChanges */, mPreserveWindows,
              true /* ignoreVisibility */);
        }
10-10 16:12:05.951  3972  8346 I configuration_changed: 512
10-10 16:12:06.022  3972  8346 I wm_relaunch_activity: [0,218943334,21,com.miui.gallery/.activity.HomePageActivity,200]
// 可见但是pause的页面重建后最终状态仍然是onPause
10-10 16:12:06.625 20930 20930 I wm_on_stop_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,handleRelaunchActivity,6]
10-10 16:12:06.649 20930 20930 I wm_on_destroy_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performDestroy,13]
10-10 16:12:06.701 20930 20930 I wm_on_create_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performCreate,34]
10-10 16:12:06.903 20930 20930 I wm_on_start_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,handleStartActivity,199]
10-10 16:12:06.910 20930 20930 I wm_on_resume_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,LIFECYCLER_RESUME_ACTIVITY,5]
10-10 16:12:06.926 20930 20930 I wm_on_paused_called: [0,218943334,com.miui.gallery.activity.HomePageActivity,performPause,1]

在这里插入图片描述

更新其它不可见Activity的Configuration

其它Activity会在下次resume的时候再触发relaunch,跟上面两个不在同一线程以及同一时间执行,如果想查找relaunch的具体原因,需要向前时间查找对应的configuration_changed的log,具体参考https://blog.csdn.net/xiaoyantan/article/details/126292133

10-11 10:58:57.071  3998 11823 I wm_set_resumed_activity: [0,com.miui.gallery/.activity.HomePageActivity,resumeTopActivity - onActivityStateChanged]
10-11 10:58:57.074  3998 11823 I wm_relaunch_resume_activity: [0,197612339,22,com.miui.gallery/.activity.HomePageActivity,200]

在这里插入图片描述

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

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

相关文章

VUEX全网最详细讲解之一

目录 一.Vuex简介 二.vuex的存值取值 测试结果 三.vuex异步请求 测试结果 ​编辑 ​编辑 一.Vuex简介 Vuex 是一个用于 Vue.js 应用程序的状态管理模式和库。它以集中式存储管理应用的所有组件的状态&#xff0c;并提供可预测的状态变化。Vuex 主要解决了多个组件之间共享…

Springboot——集成jodconverter做文档转换

文章目录 前言jodconverter 简介下载安装 libreoffice代码演示1、创建springboot项目工程并引入依赖2、配置3、准备一个docx模板4、编写测试代码 运行后的样式linux 环境下安装 libreoffice 前言 公司项目开发中&#xff0c;早期使用docx4j进行word转pdf&#xff0c;出现了很多…

嵌入式养成计划-39----C++静态成员--继承--多继承

九十一、静态成员 静态成员变量是属于类的变量&#xff0c;而不是属于类的对象的。它们在类的所有实例中是共享的。它们具有类范围的生命周期&#xff0c;因此与全局变量有一些相似之处。 在数据成员前static ----->静态数据成员 在成员函数前static ------>静态成员函…

接口自动化测试 —— 工具、请求与响应

1.工具介绍 postman &#xff1a;很主流的API测试工具&#xff0c;也是工作里面使用最广泛的研发工具。 JMeter&#xff1a; ApiPost&#xff1a; 2.安装postman&#xff1a; 安装好直接打开&#xff0c;不用注册。 二、通信模式&#xff1a; 1、同步通信&#xff1a; …

【走方格的方案数】

目录 一、题目描述二、算法原理三、代码实现 一、题目描述 二、算法原理 三、代码实现 #include <iostream> using namespace std; int func(int m,int n) {if(m1||n1){return mn;}return func(m-1,n)func(m,n-1); } int main() {int m, n;while (cin >>m >>…

word行距怎么设置?专业排版,让文档更具吸引力!

Microsoft Word是最常用的文字处理工具之一&#xff0c;广泛用于学术写作、商务沟通和文档编辑。掌握Word的基本功能是高效使用它的关键。本文将介绍word行距怎么设置的3种方法&#xff0c;以确保您的文档格式清晰、易读&#xff0c;让您的文档更具吸引力&#xff01; 方法1&am…

C++ 命名空间-----namespace(超详细解析,小白必看系列)

目录 一、前言 &#x1f34e;什么是C 二、关键字 三、命名空间&#xff08;重点&#xff09; &#x1f350;C语言--命名冲突 &#x1f349;C--命名空间的定义 &#x1f353;C--命名空间的使用 四、C输入&输出 五、共勉 一、前言 既博主学过C语言后又一新的语言&a…

动手学强化学习第2章多臂老虎机

2.1简介 多臂老虎机问题可以被看作简化版的强化学习问题。但是其只有动作和奖励没有状态信息&#xff0c;算是简化版的强化学习问题。 2.2问题介绍 2.2.1问题定义 在多臂老虎机(MAB)问题中&#xff0c;有一个有K根拉杆的老虎机&#xff0c;拉动每一根拉杆都对应一个关于奖励…

简单使用 Hugo 博客

之前用过 hugo&#xff0c;本次来分享一波&#xff0c;确实简单好用&#xff0c;可以持续使用&#xff0c;尤其是喜欢 GO语言的同学 hugo Hugo是一个用 Go语言 编写的静态网站生成器&#xff0c;可以快速地生成高效、安全和易于管理的静态网站。Hugo具有速度快、可定制性强、…

Linux引导故障排除:从问题到解决方案的详细指南

1 BIOS初始化 通电->对硬件检测->初始化硬件时钟 2 磁盘引导及其修复 2.1 磁盘引导故障 磁盘主引导记录&#xff08;MBR&#xff09;是在0磁道1扇区位置&#xff0c;446字节。 MBR作用&#xff1a;记录grub2引导文件的位置 2.2 修复 步骤&#xff1a;1、光盘进…

Javascript笔记:Web页面中的事件处理

1 任务队列 2事件处理&#xff1a;⼀个只有宏任务的示例 3 Web⻚⾯中的事件处理 3.1 定时器与事件处理&#xff1a;一个实例 4 Web⻚⾯中的事件处理 5 事件在DOM中的传播 5.1 两个阶段

C++ (Chapter 1)

C (一) 1.C的命名空间 先来看一个C语言的例子: 下面这段代码是可以正常运行的. #include<stdio.h> int rand 0; int main() {printf("%d \n", rand);return 0; }但是,包含了一个头文件之后,甚至无法通过编译. #include<stdio.h> #include<stdli…

尘封已久的功能!iPhone 15带来了一项早该使用的电池功能

了解如何在iPhone 15上检查电池周期&#xff0c;在设备使用寿命的某个阶段将非常有用。只要简单地看一眼完成的循环次数&#xff0c;你就可以确定你的电池有多健康&#xff0c;以及你是否需要很快更换它。 这是iPhone在过去一直缺失的东西。iPhone上有检查电池周期的数据&…

Altium Designer实用系列(三)----部分问题解决办法(连完所有的线之后还存在飞线,isolated copper...)

一、常见问题解决 1.1 连完所有的线之后还存在飞线 出现此问题可以尝试把该PCB先关闭&#xff0c;然后关闭Altium Designer软件。之后再打开Altium Designer&#xff0c;之后再进行DRC电气检查&#xff0c;可解决该问题。 1.2 isolated copper:split plane(xxx)on … 该问题…

计算机毕业设计选什么题目好?springboot智慧养老中心管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

C++入门篇1

文章目录 C入门篇11、命名空间1.1、命名空间定义1.2、命名空间的使用 2、输入&输出3、缺省参数3.1、缺省参数概念3.2、缺省参数分类 C入门篇1 1、命名空间 1.1、命名空间定义 命名空间是什么&#xff1f;是一种将相关功能和数据封装在一起的方式&#xff0c;以避免名称冲…

nginx如何安装 以及nginx的配置文件

Nginx 网站服务 是一个高性能 轻量级web服务软件&#xff0c; 高新能&#xff1a;对http并发连接的处理能很高&#xff0c;单台处理器可支持30000-50000个并发请求&#xff0c;&#xff08;一般设置在20000个左右&#xff09; 轻量级&#xff1a;nginx软件很小&#xff0c;安装…

c语言:通讯录管理系统(动态分配内存版)

前言&#xff1a;在大多数高校内&#xff0c;都是通过设计一个通讯录管理系统来作为c语言课程设计&#xff0c;通过一个具体的系统设计将我们学习过的结构体和函数等知识糅合起来&#xff0c;可以很好的锻炼学生的编程思维&#xff0c;本文旨在为通讯录管理系统的设计提供思路和…

GPU 基础知识整理

萌新&#xff1a; 在接触一款硬件时我会&#xff1a;基础硬件结构&#xff0c;线程结构&#xff0c;内存布局&#xff0c;数据吞吐量&#xff0c;等方面进行学习 首先GPU的特点: 并行性能&#xff1a;GPU 是专门设计用于并行计算的硬件&#xff0c;通常具有大量的处理单元&am…

Vue中的监视属性

一、监视属性的使用 &#xff08;一&#xff09;配置watch进行监视 当我们想要监视一个属性改变的时候就可以使用监视属性监视其变化并进行操作。 语法格式如下&#xff1a; watch:{ 监视属性名称 : { // 监视属性的配置项 } } 1. handler函数 当监视的属性发生变化时就调…