首页
关于
友链
其它
统计
壁纸
更多
留言
Search
1
cgroup--(4)cgroup v1和cgroup v2的详细介绍
6,730 阅读
2
修改Linux Kernel defconfig的标准方法
6,581 阅读
3
Android系统之VINTF(1)manifests&compatibility matrices
6,167 阅读
4
使用git生成patch和应用patch
3,720 阅读
5
c语言的__attribute__
3,204 阅读
默认分类
文章收集
学习总结
算法
环境配置
知识点
入门系列
vim
shell
Git
Make
Android
Linux
Linux命令
内存管理
Linux驱动
Language
C++
C
Rust
工具
软件工具
Bug
COMPANY
登录
Search
标签搜索
Rust
shell
Linux
c
uboot
Vim
vintf
Linux驱动
Android
device_tree
git
DEBUG
arm64
链表
数据结构
IDR
内核
ELF
gcc
ARM
adtxl
累计撰写
381
篇文章
累计收到
17
条评论
首页
栏目
默认分类
文章收集
学习总结
算法
环境配置
知识点
入门系列
vim
shell
Git
Make
Android
Linux
Linux命令
内存管理
Linux驱动
Language
C++
C
Rust
工具
软件工具
Bug
COMPANY
页面
关于
友链
其它
统计
壁纸
留言
搜索到
381
篇与
的结果
2021-03-08
C++标准库--IO库
暂无简介
2021年03月08日
683 阅读
0 评论
0 点赞
2021-03-08
CPP基础--类
暂无简介
2021年03月08日
683 阅读
0 评论
0 点赞
2021-03-08
CPP基础--表达式
暂无简介
2021年03月08日
664 阅读
0 评论
0 点赞
2021-03-08
CPP基础--函数
暂无简介
2021年03月08日
622 阅读
0 评论
0 点赞
2021-03-08
CPP基础--语句之范围for语句
范围for语句C++11标准引入了一种更简单的for语句,这种语句可以遍历容器或其他序列的所有元素。范围for语句的语法形式是:for (declaration : expression) statementexpression表示的必须是一个序列,比如用花括号括起来的初始值列表、数组或者vector等类型的对象,这些类型的共同特点是拥有能返回迭代器的begin和end成员。declaration定义一个变量,序列中的每个元素都得能转换成该变量的类型。确保类型相容最简单的办法是使用auto类型说明符。如果需要对序列中的元素执行写操作,循环变量必须声明成引用类型。每次迭代都会重新定义循环控制变量,并将其初始化成序列中的下一个值,之后才会执行statement。所有元素都处理完毕后循环终止。
2021年03月08日
637 阅读
0 评论
0 点赞
2021-03-08
CPP基础--标准库类型vector
标准库类型vector标准库类型vector表示对象的集合,其中所有对象的类型都相同。集合中每个对象都有一个与之对应的索引,索引用于访问对象。因为vector"容纳着"其他对象,所以也常被乘做容器(container)。vector是模板而非类型,由vector生成的类型必须包含vector中元素的类型,例如vector<int>vector能容纳绝大多数类型的对象作为其元素,但是因为引用不是对象,所以不存在包含引用的vector。1. 定义和初始化vector对象和任何一种类类型一样,vector模板控制着定义和初始化向量的方法。列表初始化vector对象用花括号括起来的0个或多个初始元素值被赋给vector对象:vector<string> articles = {"a", "an", "the"};创建指定数量的元素还可以用vector对象容纳的元素数量和所有元素的统一初始值来初始化vector对象:vector<int> ivec(10, -1); vector<string> svec(10, "hi");值初始化通常情况下,可以只提供给vector对象容纳的元素数量而不用略去初始值。此时库会创建一个值初始化的(value-initialized)元素初值,并把它赋给容器中的所有元素。这个初值由vector对象中元素的类型决定。vector<int> ivec(10); // 10个元素,每个都初始化为0 vector<string> svec(10); // 10个元素,每个都是空string对象对这种初始化的方式有两个特殊限制:其一,有些类要求必须明确地提供初始值,如果vector对象中元素的类型不支持默认初始化,我们就必须提供初始的元素值。对这种类型的对象来说,只提供元素的数量而不设定初始值无法完成初始化工作。列表初始值还是元素数量在某些情况下,初始化的真实含义依赖于传递初始值时用的是花括号还是圆括号。vector<int> v1(10); // 10个元素,每个值都是0 vector<int> v2{10}; // 1个元素,值为10 vector<int> v3(10, 1); // 10个元素,每个值都是1 vector<int> v4{10, 1}; // 2个元素,值分别是10和1如果用的是圆括号,可以说提供的值是用来构造(construct)vector对象的。如果用的是花括号,可以表述成我们想列表初始化该vector对象。另一方面,如果初始化时用了花括号的形式但是提供的值又不能用来列表初始化,就要考虑用这样的值来构造vector对象了。vector<string> v5{"hi"}; vector<string> v6("hi"); // error:不能使用字符串字面值构建vector对象 vector<string> v7{10}; // v7有10个默认初始化的元素 vector<string> v8{10, "hi"}; // v8有10个值为"hi"的元素2. 向vector对象添加元素经常使用vector的情况是并不清楚实际所需的元素个数,元素的值也经常无法确定。还有些时候即使元素的初值已知,但如果这些值总量较大而各不相同,那么在创建vector对象的时候执行初始化操作也会显得过于繁琐。我们可以利用vector成员函数push_back()向其中添加元素vector<int> v1; for (int i = 0; i < 100; i++) { v1.push_back(i); }向vector对象添加元素蕴含的编程假定必须要确保缩写的循环正确无误,特别是在循环有可能改变vector对象容量的时候如果循环体内部包含有向vector对象添加元素的语句,则不能使用范围for循环。范围for语句体内不应改变其所遍历序列的大小。3. 其它vector操作除了push_back之外,vector还提供了几种其他操作,大多数都和string的相关操作类似计算vector内对象的索引使用下标运算符能获取到指定对象的元素。和string一样,vector对象的下标也是从0开始计起,下标的类型是相应的size_type类型。只要vector对象不是一个常量,就能向下标运算符返回的元素赋值。不能使用下标形式添加元素vector对象(以及string对象)的下标运算符可用于访问已存在的元素,而不能用于添加元素。关于下标必须明确的一点是:只能对确知已存在的元素执行下标操作。
2021年03月08日
752 阅读
0 评论
0 点赞
2021-03-08
CPP基础--变量和基本类型之const限定符
const限定符因为const对象一旦创建后其值不能更改,因此创建时就必须初始化在不改变const对象的操作中还有一种是初始化,如果利用一个对象去初始化另外一个对象,则它们是不是const都无关紧要:int i = 42; const ci = i; // correct int j = ci; // correct尽管ci是整型常量,但无论如何ci中的值还是一个整型数。ci的常量特征仅仅在执行改变ci的操作时才会发挥作用。当用ci去初始化j时,根本无须在意ci是不是一个常量。拷贝一个对象的值并不会改变它,一旦拷贝完成,新的对象就和原来的对象没有关系了。默认状态下,const对象仅在文件内有效当多个文件中出现了同名的const变量时,其实等同于在不同文件中分别定义了独立的变量。某些时候有这样一种const变量,它的初始值不是一个常量表达式,但又确实有必要在文件间共享。这种情况下,我们不希望编译器为每个文件分别生成独立的变量。相反,我们想让这类const对象像其他(非常量)对象一样工作,也就是说,只在一个文件中定义const,而在多个文件中声明并使用它解决办法是,对于const变量不管是声明还是定义都添加extern关键字,这样只需定义一次就可以了;// file_1.cc定义并初始化了一个常量,该常量能被其他文件访问 extern const int bufSize = fcn(); // file_1.h头文件 extern const int bufSize; // 与file_1.cc中定义的bufSize是同一个file_1.h头文件中的声明也由extern做了限定,其作用是指明bufSize并非本文件所独有,它的定义将在别处出现。如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字1. const的引用可以把引用绑定到const对象上,就像绑定到其它对象上一样,我们称之为对常用的引用(reference to const)。与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象:const int ci = 1024; const int &r1 = ci; // correct,引用及其对应的对象都是常量 r1 = 42; // 错误,r1是对常量的引用 int &r2 = ci; // 错误,试图让一个非常量引用指向一个常量对象。假设该初始化合法,则可以通过r2来改变它引用对象的值,这显然是不正确的。初始化和对const的引用引用的类型必须与其所引用的对象的类型一致,但是有两个例外。第一种例外情况就是在初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可,尤其,允许为一个常量引用绑定非常量的对象、字面值,甚至是个一般表达式:int i = 42; const int &r1 = i; // 允许将const int&绑定到一个普通的int对象上 const int &r2 = 42; // 正确: r1是一个常量引用 const int &r3 = r1 * 2; // 正确; // r3是一个常量引用 int &r4 = r1 * 2; // 错误:r4是一个普通的非常量引用可以这样做的原因如下,double dval = 3.14; const int &ri = dval;编译器把上述代码变成了如下形式const int temp = dval; // 由双精度浮点数生成一个临时的整型常量 const int &ri = temp; // 由ri绑定这个临时量如果ri不是常量,就允许对ri赋值,这样就会改变ri所引用对象的值。注意,此时绑定的对象是一个临时量而非dval。程序员既然让ri引用dval,就肯定想通过ri改变dval的值,否则干什么要给ri赋值呢?如此看来,既然大家都不会想着把引用绑定到临时量上,C++语言也就把这种行为归为非法。对const的引用可能引用一个并非const的对象int i = 42; int &r1 = i; // 引用ri绑定对象i const int &r2 = i; // r2也绑定对象i,但是不允许通过r2修改i的值 r1 = 0; // r1并非常量,i的值修改为0 r2 = 0; // 错误:r2是一个常量引用不允许通过r2修改i的值2. 指针和const指向常量的指针(pointer to const)不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针:const double pi = 3.14; double *ptr = π // error const double *cptr = π // correct *cptr = 42; // errorconst指针常量指针(const pointer),将指针本身定为常量。常量指针必须初始化,而且一旦初始化完成,则它的值(也就是存放在指针中的那个地址)就不能再改变了。int errnumb= 0; int *const curErr = &errNumb; // curErr将一直指向errNumb const double pi = 3.14159; const double *const pip = π // pip是一个指向常量对象的常量指针3. 顶层const用名词顶层const(top-level const)表示指针本身是个常量用名词底层const(low-level const)表示指针所指的对象是一个常量4.constexpr和常量表达式常量表达式(const expression)是指值不会改变并且在编译过程就能得到计算结果的表达式。以下均不是常量表达式;int staff_size = 27; const int sz = get_size();constexpr变量在一个复杂系统中,很难(几乎不能)分辨一个初始值到底是不是一个常量表达式。C++11标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化。一般来说,如果你认定变量是一个常量表达式,那就把它声明称constexpr类型。字面值类型常量表达式的值需要在编译时就得到计算,因此对声明constexpr时用到的类型必须有所限制。因为这些类型一般比较简单,值也显而易见、容易得到,就把它们称为"字面值类型"(literal type)到目前为止,算术类型、引用和指针都属于字面值类型。自定义类Sales_item、IO库、string类型则不属于字面值类型,也就不能被定义成constexpr。指针和constexpr必须明确一点,在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关:const int *p = nullptr; // p是一个指向整型常量的指针 constexpr int *q = nullptr; // q是一个指向整数的常量指针
2021年03月08日
688 阅读
0 评论
0 点赞
2021-03-03
[转载]android 8.1 安全机制 — SEAndroid & SELinux
版权声明:本文为CSDN博主「岁月斑驳7」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_19923217/article/details/81240027
2021年03月03日
1,363 阅读
0 评论
0 点赞
2021-03-02
Android系统之VINTF(1)manifests&compatibility matrices
暂无简介
2021年03月02日
6,167 阅读
0 评论
0 点赞
2021-03-01
添加新设备类型-Android编译系统(4)
1.理解构建层构建层次结构包括与设备的物理结构对应的抽象层。下表中介绍了这些层。每一层都与上一层存在一对多的关系。例如,一个架构(ARCH)可以有多个主板(Board/device),一个主板可以有多个产品(Product)。您可以将指定层中的某个元素定义为同一层中某个元素的特化元素,这样可以免去复制操作并简化维护工作。LayerExampleDescriptionProductmyProduct, myProduct_eu, myProduct_eu_fr, j2, sdkThe product layer defines the feature specification of a shipping product such as the modules to build, locales supported, and configuration for various locales. In other words, this is the name of the overall product. Product-specific variables are defined in product definition makefiles. A product can inherit from other product definitions, which simplifies maintenance. A common method is to create a base product that contains features that apply to all products, then create product variants based on that base product. For example, two products that differ only by their radios (CDMA versus GSM) can inherit from the same base product that doesn't define a radio.Board/devicemarlin, blueline, coralThe board/device layer represents the physical layer of plastic on the device (that is, the industrial design of the device). This layer also represents the bare schematics of a product. These include the peripherals on the board and their configuration. The names used are merely codes for different board/device configurations.Archarm, x86, arm64, x86_64The architecture layer describes the processor configuration and application binary interface (ABI) running on the board.2.使用build variants在针对特定产品进行构建时,如果能在最终发布 build 的基础上有细微的变化,会非常有用。在模块定义中,模块可以通过 LOCAL_MODULE_TAGS 指定标记,这些标记可以是以下一个或多个值:optional(默认值)、debug 和 eng。如果某个模块没有通过 LOCAL_MODULE_TAGS 指定标记,则其标记默认设置为 optional。仅当 PRODUCT_PACKAGES 的产品配置需要可选模块时,系统才会安装可选模块。下面是当前定义的构建变体(build variants)。VariantDescriptionengThis is the default flavor. - Installs modules tagged with eng or debug.- Installs modules according to the product definition files, in addition to tagged modules.- ro.secure=0- ro.debuggable=1- ro.kernel.android.checkjni=1- adb is enabled by default.userThe variant intended to be the final release bits.- Installs modules tagged with user.- Installs modules according to the product definition files, in addition to tagged modules.- ro.secure=1- ro.debuggable=0- adb is disabled by default.userdebugThe same as user, with these exceptions:- Also installs modules tagged with debug.- ro.debuggable=1- adb is enabled by default.aosp为build系统提供三种Product配置,文档里叫做build variants,分别是:eng : 对应到工程版。编译打包所有模块。表示adbd处于ROOT状态,所有调试开关打开userdebug : 对应到用户调试版。打开调试开关,但并没有放开ROOT权限user : 对应到用户版。关闭调试开关,关闭ROOT权限。最终发布到用户手上的版本,通常都是user版。2.1 userdebug的准则在测试中运行 userdebug build 有助于设备开发者了解开发中版本的性能和功耗。为了让 user build 和 userdebug build 保持一致,并在用于调试的 build 中获得可靠的指标,设备开发者应遵循以下准则:userdebug 定义为已启用 root 权限的 user build,但以下情况除外:仅由用户视需要运行且仅用于 userdebug build 的应用仅在空闲维护(连接充电器/充满电)期间执行的操作,例如,使用 dex2oatd 而不是 dex2oat 来进行后台编译不要添加根据构建类型默认启用/停用的功能。建议开发者不要使用任何影响电池续航时间的日志记录形式(例如调试日志记录或堆转储)。在 userdebug build 中默认启用的任何调试功能都应明确定义,并告知处理相关项目的所有开发者。您应该只在限定的时间内启用调试功能,直到您尝试调试的问题得到解决。3. Customizing the build with resource overlays(利用资源叠加层自定义build)Android 构建系统会在构建时使用资源叠加层来自定义产品。资源叠加层用于指定在默认文件之上应用的资源文件。如需使用资源叠加层,请修改项目构建文件,将 PRODUCT_PACKAGE_OVERLAYS 设为相对于顶级目录的路径。当构建系统搜索资源时,该路径会变为影子根目录,系统除了在当前根目录中进行搜索外,还会一并在该路径中进行搜索。最常自定义的设置包含在 frameworks/base/core/res/res/values/config.xml 文件中。如需在此文件上设置资源叠加层,请使用以下某个命令将叠加层目录添加到项目构建文件:PRODUCT_PACKAGE_OVERLAYS := device/device-implementer/device-name/overlay例如:或PRODUCT_PACKAGE_OVERLAYS := vendor/vendor-name/overlay然后,将一个叠加层文件添加到该目录下,例如:vendor/foobar/overlay/frameworks/base/core/res/res/config.xml在叠加层 config.xml 文件中找到的所有字符串或字符串数组都会替换在原始文件中找到的对应字符串或字符串数组。4. 构建产品您可以通过多种不同的方式来组织设备的源文件。下面简要说明了 Pixel 实现的一种组织方式。为 Pixel 实现名为 marlin 的主设备配置。根据此设备配置,为产品创建产品定义 Makefile,用于声明关于设备的产品特定信息,例如名称和型号。您可以查看 device/google/marlin 目录,了解所有相关配置的具体设置方式。4.1 编写产品Makefile以下步骤介绍了如何采用与设置 Pixel 产品线类似的方式设置产品 Makefile:为您的产品创建一个 device/<company-name>/<device-name> 目录。例如,device/google/marlin。此目录将包含您设备的源代码以及构建这些代码所需的 Makefile。创建一个 device.mk Makefile,用来声明设备所需的文件和模块。有关示例,请查看 device/google/marlin/device-marlin.mk。创建一个产品定义 Makefile,以便基于设备创建具体产品。以下示例 Makefile 来自于 device/google/marlin/aosp_marlin.mk。请注意,该产品会通过 Makefile 沿用 device/google/marlin/device-marlin.mk 和 vendor/google/marlin/device-vendor-marlin.mk 文件中的设置,同时还会声明产品特定信息,例如名称、品牌和型号。# Inherit from the common Open Source product configuration $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk) PRODUCT_NAME := aosp_marlin PRODUCT_DEVICE := marlin PRODUCT_BRAND := Android PRODUCT_MODEL := AOSP on msm8996 PRODUCT_MANUFACTURER := Google PRODUCT_RESTRICT_VENDOR_FILES := true PRODUCT_COPY_FILES += device/google/marlin/fstab.common:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.marlin $(call inherit-product, device/google/marlin/device-marlin.mk) $(call inherit-product-if-exists, vendor/google_devices/marlin/device-vendor-marlin.mk) PRODUCT_PACKAGES += \ Launcher3QuickStep \ WallpaperPicker如需了解可添加到 Makefile 的其他产品特定变量,请参阅设置产品定义变量(4.2小节)。创建一个指向产品的 Makefile文件AndroidProducts.mk。在此示例中,仅需要产品定义 Makefile。以下示例来自于 device/google/marlin/AndroidProducts.mk(该文件同时包含 marlin (Pixel) 和 sailfish (Pixel XL),它们共享大部分配置):PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/aosp_marlin.mk \ $(LOCAL_DIR)/aosp_sailfish.mk COMMON_LUNCH_CHOICES := \ aosp_marlin-userdebug \ aosp_sailfish-userdebug创建一个包含主板特定配置的Makefile文件BoardConfig.mk 。如需查看示例,请查看 device/google/marlin/BoardConfig.mk。创建一个 vendorsetup.sh 文件,以便将您的产品(“午餐套餐”)与构建变体(使用短划线将两者分隔开)一起添加到 build 中。例如:add_lunch_combo <product-name>-userdebug这一步显得多余了,谷歌已经不建议这样了这时,您就可以基于同一设备创建更多产品变体了。4.2 设置产品定义变量产品特定变量在产品的 Makefile 中进行定义。下表显示了在产品定义文件中维护的部分变量。变量说明示例PRODUCT_AAPT_CONFIGaapt configurations to use when creating packages. PRODUCT_BRANDThe brand (for example, carrier) the software is customized for, if any. PRODUCT_CHARACTERISTICSaapt characteristics to allow adding variant-specific resources to a package.tablet, nosdcardPRODUCT_COPY_FILESList of words like source_path:destination_path. The file at the source path should be copied to the destination path when building this product. The rules for the copy steps are defined in config/makefile. PRODUCT_DEVICEName of the industrial design. This is also the board name, and the build system uses it to locate BoardConfig.mk.tunaPRODUCT_LOCALESA space-separated list of two-letter language code, two-letter country code pairs that describe several settings for the user, such as the UI language and time, date, and currency formatting. The first locale listed in PRODUCT_LOCALES is used as the product's default locale.en_GB, de_DE, es_ES, fr_CAPRODUCT_MANUFACTURERName of the manufacturer.acmePRODUCT_MODELEnd-user-visible name for the end product. PRODUCT_NAMEEnd-user-visible name for the overall product. Appears in the Settings > About screen. PRODUCT_OTA_PUBLIC_KEYSList of over-the-air (OTA) public keys for the product. PRODUCT_PACKAGESList of the APKs and modules to install.Calendar contactsPRODUCT_PACKAGE_OVERLAYSIndicates whether to use default resources or add any product specific overlays.vendor/acme/overlayPRODUCT_SYSTEM_PROPERTIESList of the system property assignments in the format "key=value" for the system partition. System properties for other partitions can be set via PRODUCT_<PARTITION>_PROPERTIES as in PRODUCT_VENDOR_PROPERTIES for the vendor partition. Supported partition names: SYSTEM, VENDOR, ODM, SYSTEM_EXT, and PRODUCT. 4.3 设置ADB_VENDOR_KEYS以通过USB进行连接借助 ADB_VENDOR_KEYS 环境变量,设备制造商无需手动授权,即可通过 adb 访问可调试的 build(userdebug build 和 eng build,但不能访问 user build)。通常,adb 会为每台客户端计算机生成一个唯一的 RSA 身份验证密钥,并将其发送到所有已连接的设备。这就是 adb 授权对话框中显示的 RSA 密钥。或者,您也可以将已知密钥构建到系统映像中,并将其分享给相应的 adb 客户端。这对于操作系统开发来说很有用,对测试来说尤其有用,因为此做法无需与 adb 授权对话框手动进行交互。如需创建供应商密钥,应安排一个人(通常为发布管理员)执行以下操作:使用 adb keygen 生成密钥对。对于 Google 设备,Google 会为每个新操作系统版本生成一个新密钥对。将密钥对签入源代码树中的某个位置。例如,Google 会将其存储在 vendor/google/security/adb/ 中。设置构建变体 PRODUCT_ADB_KEYS,使其指向您的密钥目录。为此,Google 会在密钥目录中添加一个 Android.mk 文件,其内容为 PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub,以帮助确保我们记得为每个操作系统版本生成新的密钥对。以下是 Google 在该目录(我们将各版本的已签入密钥对存储在此处)中使用的 Makefile:PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub ifeq ($(wildcard $(PRODUCT_ADB_KEYS)),) $(warning ========================) $(warning The adb key for this release) $(warning ) $(warning $(PRODUCT_ADB_KEYS)) $(warning ) $(warning does not exist. Most likely PLATFORM_VERSION in build/core/version_defaults.mk) $(warning has changed and a new adb key needs to be generated.) $(warning ) $(warning Please run the following commands to create a new key:) $(warning ) $(warning make -j8 adb) $(warning LOGNAME=android-eng HOSTNAME=google.com adb keygen $(patsubst %.pub,%,$(PRODUCT_ADB_KEYS))) $(warning ) $(warning and upload/review/submit the changes) $(warning ========================) $(error done) endif如需使用这些供应商密钥,工程师只需将 ADB_VENDOR_KEYS 环境变量设为指向存储相应密钥对的目录。这会告知 adb 先尝试这些规范密钥,然后回退到需要手动授权的已生成主机密钥。当 adb 无法连接到未获授权的设备时,系统会显示错误消息,提示您设置 ADB_VENDOR_KEYS(如果尚未设置)。参考:Android系统之添加ProductAdding a New Device
2021年03月01日
1,178 阅读
0 评论
0 点赞
1
...
31
32
33
...
39