在 Android 10 中,根文件系统已不再包含在 ramdisk.img 中,而是合并到了 system.img(即在创建 system.img 时始终将 BOARD_BUILD_SYSTEM_ROOT_IMAGE 视为已设置)。搭载 Android 10 的设备:

  • 使用 system-as-root 分区布局(由编译流程自动执行,且不可选择更改这种行为)。
  • 必须使用 ramdisk,这对于 dm-linear 而言是必需的。
  • 必须将 BOARD_BUILD_SYSTEM_ROOT_IMAGE 设为 false。此设置仅用于区分使用 ramdisk 的设备和没有使用 ramdisk 的设备(这类设备直接装载 system.img)。

system-as-root 配置的含义在 Android 9 和 Android 10 之间有所不同。在 Android 9 system-as-root 配置中,BOARD_BUILD_SYSTEM_ROOT_IMAGE 设为 true,这会强制编译将根文件系统合并到 system.img 中,然后将 system.img 作为根文件系统 (rootfs) 进行装载。此配置对于搭载 Android 9 的设备是强制性的,但对于升级到 Android 9 及搭载较低 Android 版本的设备是可选的。在 Android 10 system-as-root 配置中,编译始终将 $TARGET_SYSTEM_OUT$TARGET_ROOT_OUT 合并到 system.img 中;此配置是搭载 Android 10 的所有设备的默认行为。

Android 10 进行了进一步更改来支持动态分区,这是一种可以通过无线下载 (OTA) 更新来创建、销毁分区或调整分区大小的用户空间分区系统。作为此更改的一部分,Linux 内核无法再在搭载 Android 10 的设备上装载逻辑系统分区,因此该操作由第一阶段的 init 处理。

以下部分介绍了系统专用 OTA 的 system-as-root 要求,提供了有关将设备更新为使用 system-as-root 的指导(包括分区布局更改以及 dm-verity 内核要求),并详细介绍了 Android 10 中对 ramdisk 的更改。

关于系统专用 OTA

系统专用 OTA 需要 system-as-root 分区布局,可以让 Android 版本在不更改其他分区的情况下更新 system.img。搭载 Android 10 的所有设备都必须使用 system-as-root 分区布局来启用系统专用 OTA。

  • A/B 设备(将 system 分区作为 rootfs 进行装载)已经使用 system-as-root,不需要进行更改即可支持系统 OTA。
  • 非 A/B 设备(在 /system 装载 system 分区)必须更新为使用 system-as-root 分区布局才可支持系统 OTA。

如需详细了解 A/B 设备和非 A/B 设备,请参阅 A/B(无缝)系统更新。

更新为 system-as-root

要将非 A/B 设备更新为使用 system-as-root,您必须更新 boot.imgsystem.img 的分区架构、设置 dm-verity,并移除特定于设备的根文件夹中的任何启动依赖项。

更新分区

不同于将 /boot 改为 recovery 分区的 A/B 设备,非 A/B 设备必须保留单独的 /recovery 分区,因为它们没有后备插槽分区(例如从 boot_aboot_b)。如果在非 A/B 设备上移除 /recovery 并使其与 A/B 架构类似,那么在 /boot 分区更新失败时,恢复模式可能无法正常工作。因此,在非 A/B 设备上,必须/recovery 分区与 /boot 分区分开,这意味着将继续延迟更新恢复映像(即和搭载 Android 9 之前版本的设备一样)。

下表列出了非 A/B 设备在使用 Android 9 前后的映像分区差异。

映像 ramdisk(Android 9 之前) system-as-root(Android 9 之后)
boot.img 包含内核和 ramdisk.img

ramdisk.img-/- init.rc- init- etc -> /system/etc- system/ (mount point)- vendor/ (mount point)- odm/ (mount point)...
仅包含正常启动内核。
recovery.img 包含恢复内核和恢复 ramdisk.img
system.img 包含以下内容:

system.img-/- bin/- etc- vendor -> /vendor- ...
包含原始 system.imgramdisk.img 的合并内容:

system.img-/- init.rc- init- etc -> /system/etc- system/- bin/- etc/- vendor -> /vendor- ...- vendor/ (mount point)- odm/ (mount point)...

分区本身不会更改;ramdisk 和 system-as-root 都使用以下分区架构:

  • /boot
  • /system
  • /recovery
  • /vendor 等

设置 dm-verity

在 system-as-root 中,内核必须使用 dm-verity 在 /(装载点)下装载 system.img。AOSP 支持 system.img 的下列 dm-verity 实现。

vboot 1.0

对于 vboot 1.0,内核必须在 /system 上解析 Android 专用元数据,然后转换为 dm-verity 参数以设置 dm-verity(需要这些内核补丁程序)。下面的示例显示了内核命令行中 system-as-root 的 dm-verity 相关设置:

ro root=/dev/dm-0 rootwait skip_initramfs init=/init
dm="system none ro,0 1 android-verity /dev/sda34"
veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f

vboot 2.0

对于 vboot 2.0 (AVB),引导加载程序必须先整合 external/avb/libavb,然后 external/avb/libavb 会解析 /system 的哈希树描述符,再将解析结果转换为 dm-verity 参数,最后通过内核命令行将这些参数传递给内核。(/system 的哈希树描述符可能位于 /vbmeta/system 本身上)。

vboot 2.0 需要以下内核补丁程序:

  • https://android-review.googlesource.com/#/c/kernel/common/+/158491/
  • 内核 4.4 补丁程序、内核 4.9 补丁程序等

注意:您也可以在 external/avb/contrib/linux/ 查找 AVB 专用内核补丁程序文件。

下面的示例显示了内核命令行中 system-as-root 的 dm-verity 相关设置:

ro root=/dev/dm-0 rootwait  skip_initramfs init=/initdm="1 vroot none ro 1,0 5159992 verity 1
PARTUUID=00000016-0000-0000-0000-000000000000
PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999
sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2
8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption
ignore_zero_blocks use_fec_from_device
PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks
650080 fec_start 650080"

使用特定于设备的根文件夹

使用 system-as-root 时,在设备上刷写常规系统映像 (GSI) 之后(以及在运行供应商测试套件测试之前),任何通过 BOARD_ROOT_EXTRA_FOLDERS 添加的特定于设备的根文件夹都会消失,因为整个根目录内容已被 system-as-root GSI 取代。如果对特定于设备的根文件夹有依赖性(例如将此类文件夹用作装载点),则移除这些文件夹可能会导致设备无法启动。

为避免此问题,请勿使用 BOARD_ROOT_EXTRA_FOLDERS 来添加特定于设备的根文件夹。如果需要指定特定于设备的装载点,请使用 /mnt/vendor/<mount point>(已添加到这些更改列表中)。这些特定于供应商的装载点可在 fstab 设备树(适用于第一阶段的装载)和 /vendor/etc/fstab.{ro.hardware} 文件中直接指定,而无需进行额外设置(因为 fs_mgr 将在 /mnt/vendor/* 下自动创建它们)。

Ramdisk

在 Android 10 中,第一阶段 ramdisk 包含第一阶段 init 二进制文件(按照 fstab 条目的指定执行早期装载)和供应商 fstab 文件。(与在 Android 9 中一样,system.img 包含 $TARGET_ROOT_OUT 的内容。)

  • 对于具有 boot-ramdisk 的设备(非 A/B),第一阶段 init 是位于 /init 的静态可执行文件。这些设备将 system.img 作为 /system 进行装载,然后执行切换根操作将装载从 /system 移动到 /。装载完成后,ramdisk 的内容将会释放。
  • 对于将恢复用作 ramdisk 的设备,第一阶段 init 位于恢复 ramdisk 中的 /init。这些设备首先将根切换到 /first_stage_ramdisk,以便从环境中移除恢复组件,然后执行与具有 boot-ramdisk 的设备一样的操作(即,将 system.img 作为 /system 进行装载,切换根以将该装载移动到 /,然后在装载完成后释放 ramdisk 内容)。如果内核命令行中存在 androidboot.force_normal_boot=1,则设备会正常启动(启动到 Android)而不是启动到恢复模式。

在第一阶段 init 完成后,它会使用 selinux_setup 参数执行 /system/bin/init,以便编译 SELinux 并将其加载到系统中。最后,init 会使用 second_stage 参数再次执行 /system/bin/init。此时,init 的主要阶段将会运行,并使用 init.rc 脚本继续执行启动过程。

注意:Android 10 将 ramdisk 内容替换为第一阶段 init 可执行文件,后者与以前的 ramdisk 启动系统的方式不兼容。

分区布局(非 A/B 设备)

下面的部分详细介绍了非 A/B 设备在使用 Android 10 前后的分区布局差异。

boot.img

Ramdisk
(Android 8.x 及更低版本)
System as root
(Android 9)
Ramdisk
(Android 10)
包含内核和 ramdisk.img

ramdisk.img-/- init.rc- init- etc -> /system/etc- system/ (mount point)- vendor/ (mount point)- odm/ (mount point)...
仅包含正常启动内核。 包含内核和 ramdisk.img

ramdisk.img-/- init- vendor fstab files- system/ (mount point)- vendor/ (mount point)- odm/ (mount point)...

recovery.img

Ramdisk
(Android 8.x 及更低版本)
System as root
(Android 9)
Ramdisk
(Android 10)
包含恢复内核和恢复 ramdisk.img

system.img

Ramdisk
(Android 8.x 及更低版本)
System as root
(Android 9)
Ramdisk
(Android 10)
包含 system.img

system.img-/- bin/- etc- vendor -> /vendor- ...
包含 $TARGET_SYSTEM_OUT$TARGET_ROOT_OUT 的合并内容。

system.img-/- init.rc- init- etc -> /system/etc- system/- bin/- etc/- vendor -> /vendor- ...- vendor/ (mount point)- odm/ (mount point)...
包含 $TARGET_SYSTEM_OUT$TARGET_ROOT_OUT 的合并内容。

system.img-/- init.rc- init -> /system/bin/init- etc -> /system/etc- system/- bin/- etc/- vendor -> /vendor- ...- vendor/ (mount point)- odm/ (mount point)...

分区布局(A/B 设备)

下面的部分详细介绍了 A/B 设备在使用 Android 10 前后的分区布局差异。

boot.img

System as root
(Android 9)
Ramdisk
(Android 10)
包含正常启动内核和 recovery-ramdisk (BOARD_USES_RECOVERY_AS_BOOT := true)。

Recovery-ramdisk 仅用于启动到恢复模式。

包含正常启动内核和 recovery-ramdisk (BOARD_USES_RECOVERY_AS_BOOT := true)。

Recovery-ramdisk 用于启动到恢复模式和 Android。

ramdisk.img-/- init -> /system/bin/init- first_stage_ramdisk- vendor fstab files- etc -> /system/etc- system/ (mount point)- vendor/ (mount point)- odm/ (mount point)...

system.img

System as root
(Android 9)
Ramdisk
(Android 10)
包含 $TARGET_SYSTEM_OUT$TARGET_ROOT_OUT 的合并内容。

system.img-/- init.rc- init -> /system/bin/init- etc -> /system/etc- system/- bin/- etc/- vendor -> /vendor- ...- vendor/ (mount point)- odm/ (mount point)...

提前装载分区

支持 Treble 的设备必须启用第一阶段装载,以确保 init 可以加载分布在 systemvendor 分区的安全增强型 (SELinux) 政策 Fragment。此访问权限还可实现在内核启动后尽快加载内核模块。

如需执行提前装载,Android 必须有权访问模块所在的文件系统。Android 8.0 及更高版本支持在 init 的第一阶段(即初始化 SElinux 之前)装载 /system/vendor/odm

AOSP 提前装载更改摘要:

  • 提前装载 v1 和 v2
  • 杂项分区查找移除
  • 提前装载支持
  • 使用 VBoot 2.0 (AVB) 完成提前装载

Fstab 条目

在 Android 9 及更低版本中,设备可以使用设备树叠加层 (DTO) 为提前装载的分区指定 fstab 条目。在 Android 10 及更高版本中,设备必须使用第一阶段 ramdisk 中的 fstab 文件为提前装载的分区指定 fstab 条目。Android 10 引入了以下可在 fstab 文件中使用的 fs_mgr 标记:

  • first_stage_mount 表明将由第一阶段 init 装载分区。
  • logical 表明这是一个动态分区。
  • avb=vbmeta-partition-name 可指定 vbmeta 分区。第一阶段 init 可初始化该分区,然后再装载其他分区。如果该条目的 vbmeta 分区已由上一行中的其他 fstab 条目指定,可以省略此标记的参数。

以下示例展示了将 systemvendorproduct 分区设置为逻辑(动态)分区的 fstab 条目。

#<dev>  <mnt_point> <type>  <mnt_flags options> <fs_mgr_flags>
system   /system     ext4    ro,barrier=1     wait,slotselect,avb=vbmeta_system,logical,first_stage_mount
vendor   /vendor     ext4    ro,barrier=1     wait,slotselect,avb=vbmeta,logical,first_stage_mount
product  /product    ext4    ro,barrier=1     wait,slotselect,avb,logical,first_stage_mount

在上述示例中,供应商使用 fs_mgr 标记 avb=vbmeta 指定了 vbmeta 分区,但 product 省略了 vbmeta 参数,因为供应商已将 vbmeta 添加到了分区列表。

搭载 Android 10 及更高版本的设备必须将 fstab 文件放在 ramdisk 和 vendor 分区中。

Ramdisk

ramdisk通过直面意思就大概能理解意思,ram disk虚拟内存盘,将ram模拟成硬盘来使用的文件系统。对于传统的磁盘文件系统来说,这样做的好处是可以极大提高文件访问速度;但由于是ram,所以在掉电后,这部分内容不能保存。ramdisk文件系统是在系统上电后直接从磁盘一次性加载到内存,在整个运行期间都不会有写回操作,所以,任何修改都掉电后丢失。如下图所示:

fstab 文件在 ramdisk 中的位置取决于设备如何使用 ramdisk。

具有启动 ramdisk 的设备必须将 fstab 文件放在启动 ramdisk 根目录中。如果设备同时具有启动 ramdisk 和恢复 ramdisk,就无需对恢复 ramdisk 进行任何更改。示例:

PRODUCT_COPY_FILES +=  device/google/<product-name>/fstab.hardware:$(TARGET_COPY_OUT_RAMDISK)/fstab.$(PRODUCT_PLATFORM)

将恢复用作 ramdisk 的设备必须使用内核命令行参数 androidboot.force_normal_boot=1 来决定是启动到 Android 还是继续启动到恢复模式。在这些设备中,第一阶段 init 在装载提前装载分区之前将根操作切换到了 /first_stage_ramdisk,因此设备必须将 fstab 文件放在 $(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk 中。示例:

PRODUCT_COPY_FILES +=  device/google/<product-name>/fstab.hardware:$(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM)

Vendor

所有设备都必须将 fstab 文件的副本放到 /vendor/etc 中。这是因为第一阶段 init 在完成分区提前装载之后释放了 ramdisk,并执行了切换根操作,以将位于 /system 的装载移动到了 /。因此,后续任何需要访问 fstab 文件的操作都必须使用 /vendor/etc 中的副本。示例:

PRODUCT_COPY_FILES +=  device/google/<product-name>/fstab.hardware:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.$(PRODUCT_PLATFORM)

提前装载分区,VBoot 1.0

使用 VBoot 1.0 提前装载分区的要求包括:

  1. 设备节点路径必须在 fstab 和设备树条目中使用其 by-name 符号链接。例如,确保对分区进行命名且设备节点为 /dev/block/…./by-name/{system,vendor,odm},而不是使用 /dev/block/mmcblk0pX 指定分区。
  2. 在产品的设备配置中(即 device/oem/project/device.mk 中)为 PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITIONCUSTOM_IMAGE_VERITY_BLOCK_DEVICE 指定的路径必须与 fstab/设备树条目中相应块设备节点指定的 by-name 相匹配。示例:
  1. PRODUCT_SYSTEM_VERITY_PARTITION := /dev/block/…./by-name/system
    PRODUCT_VENDOR_VERITY_PARTITION := /dev/block/…./by-name/vendor
    CUSTOM_IMAGE_VERITY_BLOCK_DEVICE := /dev/block/…./by-name/odm
    
  2. 通过设备树叠加层提供的条目不得在 fstab 文件 Fragment 中出现重复。例如,指定某个条目以在设备树中装载 /vendor 时,fstab 文件不得重复该条目。
  3. 不得提前装载需要 verifyatboot 的分区(此操作不受支持)。
  4. 必须在 kernel_cmdline 中使用 androidboot.veritymode 选项指定验证分区的真实模式/状态(现有要求)。

提前装载设备树,VBoot 1.0

在 Android 8.x 及更高版本中,init 会解析设备树并创建 fstab 条目,以在其第一阶段提前装载分区。fstab 条目采用以下形式:

src mnt_point type mnt_flags fs_mgr_flags

定义设备树属性以模拟该格式:

  • fstab 条目必须在设备树中的 /firmware/android/fstab 下,且必须将兼容字符串设置为 android,fstab
  • /firmware/android/fstab 下的每个节点都被视为单个提前装载 fstab 条目。节点必须定义以下属性:
    • dev 必须指向表示 by-name 分区的设备节点
    • type 必须是文件系统类型(如在 fstab 文件中一样)
    • mnt_flags 必须是装载标记的逗号分隔列表(如在 fstab 文件中一样)
    • fsmgr_flags 必须是 Android fs_mgr flags 列表(如在 fstab 文件中一样)
  • A/B 分区必须具有 slotselect fs_mgr 选项。
  • 已启用 dm-verity 的分区必须具有 verify fs_mgr 选项。

示例:N6P 上的 /system 和 /vendor

下面的示例显示的是在 Nexus 6P 上为 systemvendor 分区提前装载设备树:

/ {firmware {android {compatible = "android,firmware";fstab {compatible = "android,fstab";system {compatible = "android,system";dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/system";type = "ext4";mnt_flags = "ro,barrier=1,inode_readahead_blks=8";fsmgr_flags = "wait,verify";};vendor {compatible = "android,vendor";dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor";type = "ext4";mnt_flags = "ro,barrier=1,inode_readahead_blks=8";fsmgr_flags = "wait";};};};};
};

示例:Pixel 上的 /vendor

下面的示例显示的是在 Pixel 上为 /vendor 提前装载设备树(请务必为 A/B 分区添加 slotselect):

/ {firmware {android {compatible = "android,firmware";fstab {compatible = "android,fstab";vendor {compatible = "android,vendor";dev = "/dev/block/platform/soc/624000.ufshc/by-name/vendor";type = "ext4";mnt_flags = "ro,barrier=1,discard";fsmgr_flags = "wait,slotselect,verify";};};};};
};

提前装载分区,VBoot 2.0

VBoot 2.0 是 Android 启动时验证 (AVB)。使用 VBoot 2.0 提前装载分区的要求如下:

  1. 设备节点路径必须在 fstab 和设备树条目中使用其 by-name 符号链接。例如,确保对分区进行命名且设备节点为 /dev/block/…./by-name/{system,vendor,odm},而不是使用 /dev/block/mmcblk0pX 指定分区。
  2. VBoot 1.0 所用的构建系统变量(如 PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITIONCUSTOM_IMAGE_VERITY_BLOCK_DEVICE)对 VBoot 2.0 而言并不是必需的。您应定义 VBoot 2.0 中引入的构建变量(包括 BOARD_AVB_ENABLE := true);如需查看完整配置,请参阅适用于 AVB 的构建系统集成。
  3. 通过设备树叠加层提供的条目不得在 fstab 文件 Fragment 中出现重复。例如,如果您指定某个条目以在设备树中装载 /vendorfstab 文件不得重复该条目。
  4. VBoot 2.0 不支持 verifyatboot,无论是否启用了提前装载。
  5. 必须在 kernel_cmdline 中使用 androidboot.veritymode 选项指定验证分区的真实模式/状态(现有要求)。确保包含以下 AVB 修复程序:
    • https://android-review.googlesource.com/#/q/topic:libavb-api-rev-for-verity-modes+(status:open+OR+status:merged)
    • https://android-review.googlesource.com/#/c/394215/

提前装载设备树,VBoot 2.0

VBoot 2.0 设备树中的配置与 VBoot 1.0 中的大致相同,但还有以下几项不同之处:

  • fsmgr_flagverify 变为 avb
  • 包含 AVB 元数据的所有分区都必须位于设备树的 VBMeta 条目中,即使相应的分区并非提前装载的分区(如 /boot)也是如此。

示例:N5X 上的 /system 和 /vendor

下面的示例显示的是在 Nexus 5X 上为 systemvendor 分区提前装载设备树。注意:

  • /system 使用 AVB 进行装载,且 /vendor 的装载不需要进行完整性验证。
  • 由于 Nexus 5X 没有 /vbmeta 分区,因此顶层 vbmeta 位于 /boot 分区的末端(如需了解详情,请参阅 AOSP 变更列表)。
  • / {firmware {android {compatible = "android,firmware";vbmeta {compatible = "android,vbmeta";parts = "boot,system,vendor";};fstab {compatible = "android,fstab";system {compatible = "android,system";dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/system";type = "ext4";mnt_flags = "ro,barrier=1,inode_readahead_blks=8";fsmgr_flags = "wait,avb";};vendor {compatible = "android,vendor";dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor";type = "ext4";mnt_flags = "ro,barrier=1,inode_readahead_blks=8";fsmgr_flags = "wait";};};};};
    };
    

示例:Pixel 上的 /vendor

下面的示例显示的是在 Pixel 上提前装载 /vendor。注意:

  • 很多分区都是在 vbmeta 条目中指定的,因为这些分区受 AVB 保护。
  • 请务必包含所有 AVB 分区,即使仅提前装载了 /vendor 也是如此。
  • 请务必为 A/B 分区添加 slotselect
/ {vbmeta {compatible = "android,vbmeta";parts = "vbmeta,boot,system,vendor,dtbo";};firmware {android {compatible = "android,firmware";fstab {compatible = "android,fstab";vendor {compatible = "android,vendor";dev = "/dev/block/platform/soc/624000.ufshc/by-name/vendor";type = "ext4";mnt_flags = "ro,barrier=1,discard";fsmgr_flags = "wait,slotselect,avb";};};};};
};

Android 分区布局详解相关推荐

  1. Android五大布局详解

    http://www.open-open.com/lib/view/open1390095269414.html Android 的五大布局分别是LinearLayout(线性布局).FrameLay ...

  2. qt布局嵌套_QDockWidget嵌套布局详解-实现Visual Studio布局

    概述 许多工程软件,如Qt Creator,VS,matlab等,都是使用dock布局窗口,这样用户可以自定义界面,自由组合窗口. Qt的嵌套布局由QDockWidget完成,用Qt Creator拖 ...

  3. Android开发重点难点1:RelativeLayout(相对布局)详解

    前言 啦啦啦~博主又推出了一个新的系列啦~ 之前的Android开发系列主要以完成实验的过程为主,经常会综合许多知识来写,所以难免会有知识点的交杂,给人一种混乱的感觉. 所以博主推出"重点难 ...

  4. android中帧布局效果,布局之FrameLayout(帧布局)详解

    New UI-布局之FrameLayout(帧布局)详解 --转载请注明出处:coder-pig,欢迎转载,请勿用于商业用途!本节引言:FrameLayout(帧布局)可以说是六大布局中最为简单的一 ...

  5. Android事件流程详解

    Android事件流程详解 网络上有不少博客讲述了android的事件分发机制和处理流程机制,但是看过千遍,总还是觉得有些迷迷糊糊,因此特地抽出一天事件来亲测下,向像我一样的广大入门程序员详细讲述an ...

  6. android屏幕适配详解

    android屏幕适配详解 官方地址:http://developer.android.com/guide/practices/screens_support.html 一.关于布局适配建议 1.不要 ...

  7. Android 动画框架详解,第 1 部分

    2019独角兽企业重金招聘Python工程师标准>>> Android 平台提供了一套完整的动画框架,使得开发者可以用它来开发各种动画效果,本文将向读者阐述 Android 的动画框 ...

  8. Android开发 GradientDrawable详解

    Android开发 GradientDrawable详解 前言 GradientDrawable类似与Xml布局里的shape,常用在一些自己封装的对话框控件的背景或者其他View中,优势是不需要你在 ...

  9. Android AIDL使用详解

    一.概述 AIDL 意思即 Android Interface Definition Language,翻译过来就是Android接口定义语言,是用于定义服务器和客户端通信接口的一种描述语言,可以拿来 ...

  10. android开发照相机啊,Android照相机开发详解(一)

    Android相机开发详解(一) Android相机开发详解(一) 请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的 ...

最新文章

  1. psfaddtable - 添加一个Unicode字符表到控制台字体中
  2. mysql非安装_mysql 非安装版的配置
  3. Java 并发基础——线程安全性
  4. 开发模式遵循的规则_研究每个软件开发人员应遵循的10条规则
  5. “3D几何与视觉技术”全球在线研讨会第八期~识别3D中的物体和场景
  6. 【声学基础】概述——传播
  7. 大数据之-Hadoop之HDFS的API操作_文件上传---大数据之hadoop工作笔记0056
  8. 深入浅出ExtJS 第六章 布局
  9. 5319. 删除回文子序列
  10. 计算机硬件课题,计算机硬件技术基础免试课题.pptx
  11. Vue.js05:vue内联样式
  12. 假如时光倒流我会这么学java
  13. html 京东购物车样式,购物车css样式效果
  14. 整理一些除了Google Adsense以外比较适合英文站的国外广告联盟
  15. 冷门节日借势营销策略分析
  16. python进程间通信之管道通信
  17. 多伦多大学好吗_多伦多大学留学好不好
  18. 汉语编程的时代会到来吗?
  19. js原生获取html的高度,如何通过js获取Html元素的实际宽度高度
  20. 飞利浦 V808 android

热门文章

  1. 蚂蚁分类信息使用心得
  2. 接口测试用例设计实践(含详细实例)
  3. RedHat7安装QQ
  4. Windows7系统下OpenCV2.4.4+PCL1.6.0+SSBA3.0+VS2010 IDE32环境下编译和安装以实现Sfm和PCL点云数据可视化...
  5. 在r中弄方差分析表_使用R语言进行单因素方差分析
  6. 虚拟化识别共享USB加密狗|银行U盾等解决方案
  7. 【一文搞懂】【WIN32】(_beginthread、_beginthreadex)和CreateThread
  8. 拼多多Java面试题、笔试题(含答案)
  9. html鼠标经过改变样式,css如何实现鼠标经过样式改变
  10. LLC谐振参数计算实例,mathcad格式,列出完整计算公式,软件自动计算并绘出增益曲线,方便修改设计参数