当前位置: 首页 > news >正文

Android 12 源码分析 —— 应用层 一(SystemUI准备篇)

Android 12 源码分析 —— 应用层一(SystemUI准备篇)

在接下来的时间中,将会使用Pixel 3(blueline)作为研究对象,选用AOSP的android-12.0.0_r34分支作源代码。

先从android的应用层进行探析,然后慢慢深入android的framework,接着进入android的hal层,最后以android的linux内核结束,期间可能会穿插一些其他文章如android的art虚拟机分析等。

本文是整个系列的第一篇,但是在此之前,请务必阅读以下的文章,他们将在以后的源码分析中时不时出场

  1. android 如何分析应用的内存(二)——xdd,gdb命令行(http://t.csdn.cn/RENbG)
  2. android 如何分析应用的内存(三)——LLDB命令行(http://t.csdn.cn/Vpw8e)
  3. android 如何分析应用的内存(四)——Visual studio code的LLDB(http://t.csdn.cn/8ZM8A)
  4. android 如何分析应用的内存(十四)——jdb命令行(http://t.csdn.cn/99r2G)
  5. android 如何分析应用的内存(十五)——Visual Studio Code 调试Android应用(http://t.csdn.cn/dWeF5)

上面列出的文章,是关于如何使用gdb,lldb,jdb进行android源码级别的调试。它在没有IDE的情况下非常有用。

本文作为应用层的开篇之作,选取SystemUI作为研究对象。

为什么选取SystemUI?

在Android的应用层有很多应用可以进行源码分析,如Launcher,Camera,Gallery,Bluetooth,SIM,telephony,Settings等等应用,综合考虑到SystemUI可能是定制比较多的一个模块,因此,对其进行仔细的分析。

本文的首要目标是——搭建分析SystemUI的环境——如何使用Android Studio进行AOSP的开发和调试

注意:在使用Android studio时,对pc的性能有一定的要求,如果pc性能确实不够,可以参考前面列出的5篇文章,使用VS code进行替代。在前面5篇文章中,未提及如何搭建java工程,只提及了如何调试。读者可参考其他关于:Extension Pack for Java插件的使用。搭配前面的5篇调试文章,也可以进行AOSP的开发。

如何使用Android Studio进行AOSP的开发和调试

要使用Android Studio进行SystemUI的编辑工作,需要进行如下的配置:

  1. 使用AOSP源码中aidegen工具,构建依赖模块
  2. 使用AOSP源码中的JDK
  3. 使用AOSP源码中的SDK
  4. 如何让AndroidManifest.xml和各种资源xml能相互引用
  5. 如何修改静态代码分析工具lint,以解决IDE中各种标红的错误(实际非错误)
  6. 如何使用Android studio单步调试SystemUI

接下来我们依次解决上面的步骤。

使用aidegen工具,构建依赖模块

在aosp源码中,加载完编译环境之后,即运行下面的命令之后:

. build/envsetup.sh
lunch

aidegen即可使用。

接下来使用aidegen工具,产生能在as中打开SystemUI的工程配置文件。如下:

aidegen SystemUI -i s -p /media/wanbiao/disk1t/root/IDE/android-studio/bin
# SystemUI:表示要生成工程文件的模块
# -i s:表示生成的工程文件对应的IDE为Android studio。
#        j=IntelliJ s=Android Studio e=Eclipse c=CLion v=VS Code
# -p <路径>:表示对应的IDE的安装路径,在生成工程文件完成之后,会自动打开IDE
# 其他常见选项如下:
# -n:表示不用打开IDE
# -s:表示跳过编译各种依赖,如果以前运行过make等命令,可以添加-s
# -e:表示排除一些目录,这个非常有用,尤其是大型模块
# -d:源码引用的模块的深度
# -r:重置所有的aidegen保存的配置
# -v:显示debug级别的log
# -a:生成整个Android 源码树的工程文件
# -l:用指定的语言打开IDE,j=java,c=c/c++,r=Rust
# -h:打开帮助

成功运行之后,会得到如下的图片
在这里插入图片描述

在frameworks/base/package/SystemUI目录下,会出现一下几个文件:

  1. .idea文件夹,Android studio使用的工程文件夹,里面可以配置有多少个模块,从上图可以看到,有三个模块分别为:R,SystemUI,dependencies
  2. SystemUI.iml:配置SystemUI模块的配置文件
  3. dependencies.iml:配置dependencies模块的配置文件

接下来我们将要对上面的模块进行JDK和SDK的配置。这样as才能正确地在java类之间跳转。

使用AOSP源码中的JDK

可以使用which javac命令,查看具体的jdk路径如下:
在这里插入图片描述

然后打开Android studio,将这个jdk加入配置中,

  1. File->Project Structure
  2. 按照下图进行配置
    在这里插入图片描述

在这里插入图片描述

如上图,我们选择了aosp目录中的jdk,并将这个jdk配置命名为:aosp-jdk11

接下来配置sdk

使用AOSP源码中的SDK

在android-12.0.0_r34分支中,默认并不会编译SDK,因此,运行下面的命令进行源码的编译。

. build/envsetup.sh
lunch
make sdk -j8

在Android的编译过程中,可能会报错,例如:module can not be located。又或者xxx文件不存在。

解决办法:只需要找到对应的报错文件,然后打开查看对应的module是否存在,如果不存在,就修改成正确的路径。当然也可简单粗暴的注释掉报错行,前提是:能够确定该行不会影响SDK的功能。

编译成功之后,将会在如下路径中出现:

./out/host/本机平台/sdk/aosp_blueline/android-sdk_eng.wanbiao_linux-x86

然后按照如下所示,添加SDK。

在这里插入图片描述

在这里插入图片描述

注意:在上图中,要保证SDK内部使用的JDK为我们前面配置的JDK即,aosp-jdk11.同时build target请确保为Android API 31.

将SDK和JDK与SystemUI项目相关联

上面两个步骤只是添加了对应的SDK配置和JDK配置,但是还未与SystemUI相关联起来,参照如下步骤,进行关联

在这里插入图片描述

接下来将项目下的各个模块,也配置好SDK,如下图
在这里插入图片描述

在点击完,apply之后,会出现一段时间的indexing…请等待片刻。

至此,as已经具备,编辑和跳转java代码的功能。在进行xml资源配置之前,我们需要先解决几个问题
如下:

  1. 如何正确跳转到源码中,而不是跳转到SDK中
  2. 源码中的重复文件该怎么操作

如何正确跳转到源码中

在上面的配置中,如果我们跳转源码,将会首先跳转到SDK中。为了能够成功跳转到我们的源码中而不是SDK中
可以有如下两种办法:

  1. 修改依赖的优先级
  2. 去掉sdk中的android.jar

两种办法都需要修改,project structure.我们用如下的图片来讲解两种办法
第一种办法:
在这里插入图片描述

第一种办法通常需要经常修改,因为as经常会将sdk移动到高优先级

第二种办法:
在这里插入图片描述

经过上面的配置,就可以正确的跳转到源码中的位置了

如何处理重复文件

我们处理重复文件,通过将其文件夹标记为exclude 目录即可,如下图
在这里插入图片描述
上图将Stub模块下的重复的SystemProperties.java排除在了source file之外。

注意:添加exclude 文件夹,除了上面的右键以外,还可通过对应的.iml文件添加如下的格式:

<content url="file://$MODULE_DIR$/../../../../system/tools/sysprop/stub"><sourceFolder url="file://$MODULE_DIR$/../../../../system/tools/sysprop/stub" isTestSource="false" /><excludeFolder url="file://$MODULE_DIR$/../../../../system/tools/sysprop/stub/android/os" />
</content>

再次注意:除了上面两种方法,还可以通过打开project structure进行修改,如下图

在这里插入图片描述

配置Android

上面的处理,只能进行java代码之间的跳转和配置,我们还需要进行AndroidManifest.xml和资源文件的处理。进行如下配置。

  1. 添加Android
    在这里插入图片描述

  2. 选择清单文件和资源文件夹。其中清单文件和资源文件夹是必须
    在这里插入图片描述

注意:在Android中,一次只能添加一个资源文件夹,如果有多个资源文件夹需要编辑,可以修改此处的配置。例如,我想在res-product中编辑资源的时候,IDE能给我正确的提示,那么可以将此处的Resource directory改为对应的文件夹。

至此,IDE中已经基本可以使用Android的资源了。但是在使用之前,依然还需要处理两个问题:

  1. 引用系统资源时,跳转到源码而不是sdk
  2. 处理IDE中报错,但是是正确的使用

如何调整到系统资源

在我的例子中,为了能够正确的关联到系统资源,我将编译出来的sdk中的资源文件夹,删掉,然后通过链接文件夹指向framworks/base/core/res/res目录。使用ln命令即可,不再赘述

处理xml中的非法使用

在AndroidManifest.xml中,如果使用了系统权限如:

<uses-permission android:name="android.permission.BIND_CONTROLS" />

再如,使用了不属于应用的useid

android:sharedUserId="android.uid.systemui"

这些会在IDE中,用红线标识其错误,

再如资源文件夹中使用

@*android:integer/config_mediumAnimTime

访问非public的资源,也会报错

这些都属于静态代码检查工具的功能,我们将对其进行一些修改。

针对上述错误,可做如下修改:
方法一:

  1. 打开AndroidManifest.xml文件之后,右键单击
  2. 选中Analyze->Configure Current File Analysis
  3. 最后选择Syntax

上面的步骤,是告诉IDE,对于当前这个文件,只做语法检查,不做其他检查

方法二:
上面仅仅是非常粗暴的关掉了提示。同样还可以通过File->Settings->Editor->Inspections 在打开的面板中,进行精细的条件。这个涉及到inspect功能的详细解读,不在此赘述。

方法三:
除了通过图形界面操作以外,还可以在当前目录下的lint.xml文件中进行配置。
lint.xml支持的选项,可以通过如下命令得到:

./prebuilts/devtools/tools/lint --list

至此,你可以畅快的在Android Studio中进行,java代码以及xml代码中的编辑工作了。

当然,你也可以对IDE编辑器上面的报错,视而不见,这对于我们的编辑工作并没有什么实质性影响。

在Android studio中调试

关于Android studio怎么调试Android 应用,此处不再介绍,请参考:
android 如何分析应用的内存(五)——Android studio的LLDB:http://t.csdn.cn/jSurw和android 如何分析应用的内存(十五)——Visual Studio Code 调试Android应用:http://t.csdn.cn/wHOgd

本文只介绍,如何能让SystemUI能够正确的调试起来。

事实上,在进行SystemUI的调试中,你将会发现local变量无法debug的场景。为了解决这个问题。需要处理如下几个步骤:

  1. 确定编译的时候,添加了javac -g选项
  2. 关掉AOSP中的优化配置

确定编译出来的class文件包含调试信息

在android 如何分析应用的内存(十四)——jdb命令行http://t.csdn.cn/GtbBH文章中,讲解了使用javap进行查看的命令。

接下来我们直接查看SystemUIApplication.class是否含有调试信息。
在这里插入图片描述

如果没有上面的输出,则尝试如下修改:

1. Android.mk中增加:LOCAL_JAVACFLAGS += -g
2. Android.bp中增加:javacflags:["-g"]

然后重新编译。并再次确定,如果依然没有调试信息。可以尝试切换成userdebug版本

关掉AOSP中的模块优化

在AOSP生成apk的环节中,有一个优化环节,这个优化环节包括资源的压缩,无用代码的剥离,混淆代码等。为了不破坏调试信息,我们需要关闭优化。如下:

1. Android.mk中添加:LOCAL_PROGUARD_ENABLED := false
2. Android.bp中添加:optimize:[enabled:false]

完成上述步骤之后,可关闭优化功能,且能够在单步调试中进行本地变量的查看

开始调试代码

为了能让SystemUI启动的时候就等待调试器的加入,我们运行下面的命令:

adb shell am set-debug-app -w com.android.systemui

上面代码的详细解释,可参考:android 如何分析应用的内存(十五)——Visual Studio Code 调试Android应用http://t.csdn.cn/JPBjC一文中的开始测试小节

调试结果

单步调试结果如下图

在这里插入图片描述

在上面的图中,可以一步一步单步下去,完成整个执行流程的熟悉。

本篇是我们分析SystemUI的基础环节,必不可少的环节,因为能够单步运行,减轻了许多分析源码的工作。说句人话就是少加班了。

至此,Android studio如何进行SystemUI的源码编辑和调试,介绍完毕。

从下一篇文章开始,我们将正式进入SystemUI的源码中,查看让人魂牵梦绕的SystemUI是怎样被写出来的。

另外,题外话,如果自己的PC性能还可以,可以使用一些AI工具,进行辅助编程,比如笔者正在使用tabnine插件,再比如使用variable extractor将对象翻译成json格式,然后使用工具,进行图形化查看,如前面文章中提及的Debug Visualizer工具

相关文章:

Android 12 源码分析 —— 应用层 一(SystemUI准备篇)

Android 12 源码分析 —— 应用层一&#xff08;SystemUI准备篇&#xff09; 在接下来的时间中&#xff0c;将会使用Pixel 3(blueline)作为研究对象&#xff0c;选用AOSP的android-12.0.0_r34分支作源代码。 先从android的应用层进行探析&#xff0c;然后慢慢深入android的fr…...

记录 MySQL 如何开启已有的定时任务

1.首先&#xff0c;确保你已经在MySQL的配置文件my.ini中启用了事件调度器。在[mysqld]部分添加event_schedulerON&#xff0c;然后保存文件并重启MySQL服务。这将启用MySQL的事件调度器功能。 但如果是线上业务不能停也可以在该数据库中输入 -- 开启事件计划程序 SET GLOBAL …...

三种生成树(STP,RSTP,MSTP)的基本配置(自我理解)

目录 一、为什么要使用生成树&#xff08;STP)&#xff1a; 二、由于设备冗余而导致的问题&#xff1a; 广播风暴&#xff1a; 三、802.1D生成树基本配置 四、802.1D生成树实验 实验拓扑&#xff1a; 实验配置&#xff1a; 配置完成后&#xff0c;在SW8上观察现象&…...

FRP内网穿透,配置本地电脑作为服务器

FRP内网穿透&#xff0c;配置本地电脑作为服务器 下载FRP服务端客户端 参考链接&#xff1a; https://www.it235.com/实用工具/内网穿透/pierce.html https://www.cnblogs.com/007sx/p/17469301.html 由于没有公网ip&#xff0c;所以尝试内网穿透将本地电脑作为服务器&#xff…...

Linux基础指令

本文已收录至《Linux知识与编程》专栏&#xff01; 作者&#xff1a;ARMCSKGT 演示环境&#xff1a;CentOS 7 目录 前言 正文 查看当前用户whoami 查看当前目录路径pwd 清理屏幕clear 查看目录下文件指令ls 进入目录指令cd 以树状结构显示目录文件tree 创建普通文件指…...

基于GRU门控循环网络的时间序列预测matlab仿真,对比LSTM网络

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 LSTM: GRU 2.算法运行软件版本 matlab2022a 3.部分核心程序 %构建GRU网络模型 layers [ ...sequenceInputLayer(N_feature)gruLayer(N_hidden)f…...

windows上ffmpeg如何录制双屏幕中的一个屏幕上的视频

首先&#xff0c;如何在window上安装ffmpeg自己查找scoop安装ffmpeg. 如题&#xff1a; 如果你有两个屏幕&#xff0c;如何让ffmpeg来录制其中的一个屏幕的视频呢。 很简单&#xff0c;首先你要查看另外一个屏幕的分辨率&#xff1a; 第一步&#xff1a;进入系统中 第二步&am…...

使用Python搭建服务器公网展示本地电脑文件

文章目录 1.前言2.本地http服务器搭建2.1.Python的安装和设置2.2.Python服务器设置和测试 3.cpolar的安装和注册3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 Python作为热度比较高的编程语言&#xff0c;其语法简单且语句清晰&#xff0c;而且python有…...

Java IO流(五)Netty实战[TCP|Http|心跳检测|Websocket]

Netty入门代码示例(基于TCP服务) Server端 package com.bierce.io.netty.simple; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGro…...

C#基础进阶

C#基础进阶 泛型 http://www.runoob.com/csharp/csharp-generic.html 匿名函数 http://www.runoob.com/csharp/csharp-anonymous-methods.html 扩展方法 https://blog.csdn.net/u011127019/article/details/54728886 https://docs.microsoft.com/zh-cn/dotnet/csharp/pr…...

Java:ArrayList集合、LinkedList(链表)集合的底层原理及应用场景

ArrayList集合的底层原理及应用场景 LinkedList&#xff08;链表&#xff09;集合的底层原理及应用场景 单向链表 增加数据 删除数据 双向链表 LinkedList的应用场景之一:可以用来设计队列 入队 出队 LinkedList的应用场景之一:可以用来设计栈 压栈&#xff08;push),addFirst…...

【Python】json文件的读取

文章目录 1. json简介2.json的使用规范3.json文件的书写4.json文件的读取 1. json简介 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;常用于将结构化数据进行传输和存储。它基于JavaScript语法&#xff0c;但可以被多种编程…...

专用杂凑函数的消息鉴别码算法学习记录

声明 本文是学习github5.com 网站的报告而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 范围 GB/T 15852的本部分规定了三种采用专用杂凑函数的消息鉴别码算法。这些消息鉴别码算法可用作数据完整性检验&#xff0c;检验数据是否被非授权地改变。同样…...

Golang使用消息队列(RabbitMQ)

最近在使用Golang做了一个网盘项目&#xff08;类似百度网盘&#xff09;&#xff0c;这个网盘项目有一个功能描述如下&#xff1a;用户会删除一个文件到垃圾回收站&#xff0c;回收站的文件有一个时间期限&#xff0c;比如24h&#xff0c;24h后数据库中记录和oss中文件会被删除…...

Apache Spark远程代码执行漏洞(CVE-2023-32007)漏洞复现

漏洞描述 Apache Spark是美国阿帕奇&#xff08;Apache&#xff09;基金会的一款支持非循环数据流和内存计算的大规模数据处理引擎。 Apache Spark 3.4.0之前版本存在命令注入漏洞&#xff0c;该漏洞源于如果ACL启用后&#xff0c;HttpSecurityFilter中的代码路径可以允许通过…...

春秋云镜 :CVE-2020-21650(MyuCMS后台rce)

一、题目 靶标介绍&#xff1a; MyuCMS开源内容管理系统,采用ThinkPHP开发而成的社区商城聚合&#xff0c;插件&#xff0c;模板&#xff0c;轻便快捷容易扩展 其2.2版本中admin.php/config/add方法存在任意命令执行漏洞. 进入题目&#xff1a; exp&#xff1a; url/index.p…...

测试框架pytest教程(7)实现 xunit 风格的setup

pytest支持setup和teardown&#xff0c;对于使用unittest和nose框架的用户来说对这些很熟悉&#xff0c;但是在pytest可以使用功能更强大的fixture来实现固定装置。 模块级别 如果单个模块中有多个测试函数和测试类&#xff0c;您可以选择实现以下固定方法&#xff0c;这些方…...

用队列实现栈

目录 题目题目要求示例 解答方法一、实现思路时间复杂度和空间复杂度代码 方法二、实现思路时间复杂度和空间复杂度代码 方法三、实现思路时间复杂度和空间复杂度代码 总结 题目 用队列实现栈 题目要求 题目链接 示例 解答 方法一、 使用两个队列来实现栈。 实现思路 题…...

Anolis 8.6 下 Redis 7.2.0 集群搭建和配置

Redis 7.2.0 搭建和集群配置 一.Redis 下载与单机部署1.Redis 下载2.虚拟机配置3.Redis 单机源码安装和测试4.Java 单机连接测试1.Pom 依赖2.配置文件3.启动类4.配置类5.单元测试6.测试结果 二.Redis 集群部署1.主从1.从节点配置2.Java 测试 2.哨兵1.哨兵节点配置2.复制一个哨兵…...

综合能源系统(8)——综合能源系统支撑技术

综合能源系统关键技术与典型案例  何泽家&#xff0c;李德智主编 1、大数据技术 1.1、大数据技术概述 大数据是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合&#xff0c;是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...