android 13 WMS/AMS系统开发-SplashScreen的添加与移除分析

Android 12系统源码_SystemUI(九)WindowInsetsController源码解析 通过Android12系统源码,解析WindowInsetsController源码调用流程。 阅读详情
AI摘要

文章详细介绍了如何在Android13中添加和分析SplashScreen的流程,包括通过日志追踪、代码定位、堆栈打印等方法,重点探讨了从WindowManager服务到ActivityTaskManager服务的调用链路。

android 13 WMS/AMS系统开发-SplashScreen的添加与移除分析

更多内容qqun:422901085 https://ke.qq.com/course/5992266#term_id=106217431
(代码基于android-13.0.0_r6)
在系统开发过程中大家要学会怎么来学习追踪代码,这一点是非常关键的,因为在庞大系统代码中,如果什么都进行正向分析,那么很有可能因为代码过于庞大,进入分支过多而导致丢失方向,失去了主要线路,陷入一种丢了西瓜捡到芝麻情况,这情况其实经常在分析系统源码时候常见,但是这其实对我们学习主流程来说是非常不利的,因为我们往往对代码执行的主流线路都还没有摸清,没有办法对流程有一个比较好的理解,而容易被执行某个小点,小部分卡住。故经常建议大家采用如下几个方法进行:
1、首先可以尝试看需要分析流程中是否本身有相关日志开启或可以通过代码,Proto方式来开启日志,或者自己加入log,然后通过日志来大概定位流程执行
2、在第一部分已经知道了大概流程,但是还不清楚具体的过程等,这个时候就建议可以通过寻找到我们过程目标方法,就相当于以目标为参考点,然后目标方法中加入堆栈打印,或之as的debug调试,通过具体堆栈然后反向来分析流程。

下面我们就以上面的方法来试试今天的需要分析的SplashScreen

首先直观认识什么是SplashScreen,大家看如下图:
在这里插入图片描述

简单说就是因为首次Activity启动需要时间,一般几百ms,但是如果这个期间什么都不显示,那么给用户感觉可能有一点卡,为了更好用户体验,那么就需要点击时候立即显示,显示东西就是如上图界面,一个app图标的页面,知道app绘制完成才消失,然后显示正常的页面
在这里插入图片描述

好了功能知道了,我们下面就来分析吧。
分析方法步骤:
1、获取一下启动引导页面SplashScreen界面的window名字,看看是否可以从它进行入手,设置中开发者选项把动画调慢10倍,点击启动图库,同时adb shell dumpsys window windows看看对应数据:
我们挑出如下发现他就是对应的window名字

  Window #9 Window{ed8162c u0 Splash Screen com.android.gallery3d}:
    WindowStateAnimator{52bfa62 Splash Screen com.android.gallery3d}:
      mSurface=Surface(name=Splash Screen com.android.gallery3d)/@0x3cfa7f3
  imeLayeringTarget in display# 0 Window{ed8162c u0 Splash Screen com.android.gallery3d}

知道window名字后我们开启去代码搜索谁创建的?

test@test:~/aosp/frameworks/base$ grep "Splash Screen" ./ -rn
./core/java/android/window/SplashScreenView.java:638:     * Get the view containing the Splash Screen icon and its background.
./libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java:311:        params.setTitle("Splash Screen " + activityInfo.packageName);
./libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java:45:    // Starting Windows (Splash Screen)

从结果可以看出,明显是./libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java:311:
这里我们既可以去看一下StartingSurfaceDrawer代码,然后从它的代码开始入手分析

2、知道代码对应地方,可以尝试用日志打印堆栈方法来定位系统调用流程
代码中可以简单看出是addStartingWindow中的调用的,即只要关心addStartingWindow

 public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
        mSplashScreenExecutor.execute(() -> {
            //省略
            if (isSplashScreenType(suggestionType)) {
                mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken,
              //省略
        });
    }

通过堆栈发现addStartingWindow如下,而且知道资格进程运行在systemui进程(log中有进程好既可以判断):

addStartingWindow:124, StartingWindowController (com.android.wm.shell.startingsurface)
addStartingWindow:392, ShellTaskOrganizer (com.android.wm.shell)
lambda$addStartingWindow$0$android-window-TaskOrganizer$1:286, TaskOrganizer$1 (android.window)
run:-1, TaskOrganizer$1$$ExternalSyntheticLambda5 (android.window)
handleCallback:942, Handler (android.os)
dispatchMessage:99, Handler (android.os)
loopOnce:201, Looper (android.os)
loop:288, Looper (android.os)
main:7898, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
run:548, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main:936, ZygoteInit (com.android.internal.os)

可以看出其实是TaskOrganizer类中进行调用

 private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() {
        @Override
        public void addStartingWindow(StartingWindowInfo windowInfo,
                IBinder appToken) {
            mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(windowInfo, appToken));
        }
        //省略

这里其实就是一个跨进程调用,调用方法是addStartingWindow,那么就可以去framework下搜索:
排除一些Test就如下几个地方

test@test:~/aosp/frameworks/base$ grep "\.addStartingWindow(" ./ -rn
./services/core/java/com/android/server/wm/StartingSurfaceController.java:85:            if (task != null && mService.mAtmService.mTaskOrganizerController.addStartingWindow(
./services/core/java/com/android/server/wm/StartingSurfaceController.java:169:                mService.mAtmService.mTaskOrganizerController.addStartingWindow(task,
./services/core/java/com/android/server/wm/TaskOrganizerController.java:510:            lastOrganizer.addStartingWindow(info, activity.token);

明显看出其实最后都是调用了TaskOrganizerController的addStartingWindow方法:

  boolean addStartingWindow(Task task, ActivityRecord activity, int launchTheme,
            TaskSnapshot taskSnapshot) {
       //ignore
        try {
            lastOrganizer.addStartingWindow(info, activity.token);
        } catch (RemoteException e) {
            Slog.e(TAG, "Exception sending onTaskStart callback", e);
            return false;
        }
        return true;
    }

又可以在这里进行堆栈打印追踪:

addStartingWindow:510, TaskOrganizerController (com.android.server.wm)
createSplashScreenStartingSurface:85, StartingSurfaceController (com.android.server.wm)
createStartingSurface:36, SplashScreenStartingData (com.android.server.wm)
run:2418, ActivityRecord$AddStartingWindow (com.android.server.wm)
scheduleAddStartingWindow:2391, ActivityRecord (com.android.server.wm)
addStartingWindow:2370, ActivityRecord (com.android.server.wm)
showStartingWindow:6978, ActivityRecord (com.android.server.wm)
showStartingWindow:6938, ActivityRecord (com.android.server.wm)
showStartingWindow:197, StartingSurfaceController (com.android.server.wm)
startActivityLocked:5150, Task (com.android.server.wm)
startActivityInner:1905, ActivityStarter (com.android.server.wm)
startActivityUnchecked:1661, ActivityStarter (com.android.server.wm)
executeRequest:1216, ActivityStarter (com.android.server.wm)
execute:702, ActivityStarter (com.android.server.wm)
startActivityAsUser:1240, ActivityTaskManagerService (com.android.server.wm)
startActivityAsUser:1203, ActivityTaskManagerService (com.android.server.wm)
startActivity:1178, ActivityTaskManagerService (com.android.server.wm)
onTransact:893, IActivityTaskManager$Stub (android.app)
onTransact:5183, ActivityTaskManagerService (com.android.server.wm)
execTransactInternal:1280, Binder (android.os)
execTransact:1244, Binder (android.os)

在这里插入图片描述

在这里插入图片描述

Android 12之启动画面Splash Screens(二) -- framework原理 本篇介绍Splash Screens的framework层原理。 阅读详情

相关推荐

Android 12.0 禁用系统app首次启动动画SplashScreen功能分析

在12.0的系统开发中,由于系统增加了新特性,在app首次启动的时候,添加了启动引导动画SplashScreen功能,所以会默认显示 app图标作为一张动画来过度,解决首次启动卡顿问题,接下来分析下看是怎么样添加的,然后禁用就可以了

安卓兼职framework和app工程师的博客 4214

适配splashscreen步骤以及启动卡住不动(白屏)的坑

适配splashscreen,在splashscreen显示弹窗,解释setOnExitAnimationListener不执行的问题

喻志强的博客 1万+

Coze+剪映小助手实战:5分钟搞定视频草稿创建工作流(附常见错误排查)

本文详细介绍了如何利用Coze平台与剪映小助手,通过create_draft接口快速搭建自动化视频草稿创建工作流。文章从核心价值、零基础搭建步骤、运行验证到深度错误排查,手把手教你5分钟内实现视频项目参数预设的标准化与自动化,显著提升短视频创作与团队协作效率。

oil88的博客 549

splash screen

public class Splashscreen extends Activity{ private Thread splashThread; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layou

zexu82 博客 477

Ubuntu 22.04 “软件与更新”装了NVIDIA驱动,WiFi等设备不见了

在Win10装了Ubuntu22.04的双系统,台式机里面有NVIDIA 3080Ti的独立显卡,Ubuntu默认使用的nouveau驱动,需要更换成NVIDIA相应的驱动,在软件和更新里面一键安装了NVIDIA-driver-535-server之后,发现wifi、蓝牙等设备消失了。这个问题的根源据说跟这个nouveau驱动有关,希望linux社区可以解决这个问题。命令安装后 sudo reboot就可以重新看到WiFi以及蓝牙等设备图标了。然后用U盘拷贝到不能上网的Ubuntu22.04系统上,利用。

me_ysd的博客 5855

ESP8266连接阿里云(STM32)

一、概述 之前通过串口调试助手+ESP8266已经连接上阿里云了 ESP8266连接阿里云(串口调试助手) 这次我们使用STM32+ESP8266来接入阿里云,其实本质上就是STM32和ESP8266进行串口通信,相当于使用STM32代替之前使用的串口调试助手来发送AT指令。只是发送的字符串数据可能有些细节需要注意一下。 二、保存连接的AT指令 定义几个字符串数据保存需要发送的AT指令 //注意: //末尾记得加\r\n //字符...

xyx0610的博客 4万+

关闭 Android SplashScreen(闪屏)

如果你想自定义SplashScreen 可以继承R.style.Theme_SplashScreen 或者 R.style.Theme_SplashScreen_IconBackground.参考。SplashScreen在Android 12上是强制的,如果你什么都不做,你的App在Android 12上就会自动拥有SplashScreen界面。其实也没什么他主要作用是为了在App启动初始化的时候避免让用户在一个空白界面等待过长时间,一定程度上提升用户体验。

qq_50675668的博客 9883

Openclaw Onboarding向导全攻略——如何配置你的第一个AI助手

很多新手在成功运行 `openclaw --version` 后,面对黑底白字的终端就陷入了迷茫:“安装好了,然后呢?” 本篇我们就彻底解决这个问题,带你完整走完 `openclaw onboard` 交互式初始化配置向导的每一步,从“安装完成”到“真正能用”,只差这一个向导的距离。 本文为2026年3月最新版,适配OpenClaw v2026.2.x 稳定版,所有步骤均经过实测验证,可直接落地。

夏日清风 1917

android 常考 面试题 详解

android 常考 面试题 详解

maoning20080808的专栏 483

【QNX+Android虚拟化方案】01 - 芯片介绍

【QNX+Android虚拟化方案】01 - 芯片介绍

|~~~热爱生活、努力学习的小伙汁~~~| 2946

AXI总线详解完结篇

经过几个月的整理和发文,AXI总线详解系列正式迎来最终篇,内容基本涵盖了上一篇文章的全部内容。 所有文章的链接如下: 1、 AXI总线详解 2、AXI总线详解-总线和接口以及协议 3、AXI协议中的通道结构 4、AXI总线详解-AXI4读写操作时序及AXI4猝发地址及选择 5、AXI4交换机制 6、ZYNQ中DMA与AXI4总线-DMA简介 7、AXI总线详解-不同类型的DMA 8、AXI总线详解-DMA内部寄存器的读写方式 9、AXI总线详解-几种应用DMA的场合 10、Altera Scatter-G.

OpenFPGA的博客 5493

Android U WMShell动画调用堆栈

简单介绍WMshell动画调用的堆栈

yimelancholy的博客 2226

汽车IVI中控开发入门及进阶(三十八):手机投屏HiCar开发

为了兼容这部分手机,车机端在向手机端发送USB控制命令字的同时,需要启动mDNS Server,广播车机端IP地址和HiCar SDK侦听的Server Socket端口(IP地址和端口在HiCar SDK初始化USB driver时,告知车机),在检测到手机断开USB连接时关闭mDNS Server。厂商在集成HiCar SDK开发HMI应用时,不可避免会使用到智能座舱的敏感权限,例如位置权限、摄像头权限、麦克风权限等,SDK初始化时,厂商HMI应用需要设置必要的车机参数供SDK使用。

码农17年的博客 1075

WMSHELL 架构说明

在Android12之后,系统的ui 处理不断的外放到应用上,自己不再参与ui方面的显示,比如转场动效,decorview, startwindow;而whshell是运行于systemui 下的一个独立的部分。wmshell下存放了所有task的大小,负责多窗交互,悬浮窗管理等。是一个重要的窗口管理中心。我们做多窗开发要熟练掌握wmshell的具体架构及交互方式,这样才能够进行具体的需求实现。

qq_40194645的博客 2714

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

千里马带你学framework:android 13 WM_SHELL_STARTING_WINDOW相关记录笔记

这里是为啥阿,因为高版本StartingWindow已经移殖到了Systemui进程,让Systemui来负责窗口创建相关,所以自然就wms端处理不了,要跨进程让systemui处理。这里注意,明显用wm开启时候,和正常wm相关的打印输出也是不一样的,明显显示是No IProtoLogGroup named WM_SHELL_STARTING_WINDOW。这个时候logcat -s WindowManager是没有这个shell相关打印,必须要。才可以打印出相关的Proto日志。

liaosongmao1的专栏 793

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

APP启动优化与黑白屏

通过APP冷启动的流程,可以看到1、2、3步骤都是系统进行的操作,很难进行优化;而4、5两步,分别执行Application的onCreate和Activity的onCreate、onStart,应尽量避免耗时操作。

NIIIICO的博客 1668

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

WMShell (WindowManager Shell)

wmshell

sinat_38816956的博客 1260

Android U 多任务启动分屏——SystemUI流程

前文说到通过接口跨进程调用到了SystemUI进程,我们继续分析分屏在systemui中的实现,这些实现都是在WMShell中实现的。

yimelancholy的博客 2929

冷启动的流程

该线程通过异步调用桌面的AIDL::java::IRemoteTransition::startAnimation::server.该线程会唤醒桌面UI线程执行远程动画.对端 AIDL::java::IWindowSession::remove::server ,移除Startingwindow 会执行一个窗口移除动画。桌面远程动画的最后一帧会唤醒桌面UIThreadHelper线程,该线程唤醒SystemUI子线程,唤醒systemui中的wmshell.main线程。1.桌面远程动画的触发。

alone_egg的博客 633

辉哥的分屏学习笔记

安卓T 分屏

qq_30215785的博客 2121

Android 项目 报错 XX 解决

1、ActivityManager: Warning: Activity not started, its current task has been brought to the front出现这个提示的解决办法,退出模拟器中运行的程序,再次运行即可解决!清理一下2、emulator: ERROR: the user data image is used by another emulator.

liu_jun_y的专栏 795

创建Android启动界面

每个Android应用启动之后都会出现一个Splash启动界面,显示产品的LOGO、公司的LOGO或者开发者信息。如果应用程序启动时间比较长,那么启动界面就是一个很好的东西,可以让用户耐心等待这段枯燥的时间。 制作Splash界面突出产品LOGO,产品名称,产品主要特色;注明产品的版本信息;注明公司信息或者开发者信息;背景图片,亦可以用背景颜色代替; 除了等待还能做点什么大多数的Splas...

weixin_33995481的博客 173

安卓:Splash screens——官方解决启动白屏的方法之一

安卓启动app会出现白屏现象,官方提供了Splash screens这个解决白屏问题的方法之一,最近学完顺便记录下笔记。本篇文章只是Splash screens的基础使用,虽然在练手项目用起来看着还不错,但是接下来可能会接着修改这篇文章,因为手头没有合适的icon,所以这是随便找的图片,而且也没试过添加动画来优化Splash screens。

薪火_的博客 4780
上一篇: android 12/13 分屏设置Task的Bounds区域-系统车机开发必学
下一篇: android 13 WMS/AMS系统开发-窗口层级相关DisplayArea,WindowContainer
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值