Android 官方并没有提供可运行在树莓派3上的Android系统,而只提供了AndroidThings系统,并且还只是preview的版本。想在树莓派上运行Android 8.1系统,就需要自己动手修改。

幸好官方提供了AndroidThings preview 6的系统,这使得让树莓派3运行Android 8.1系统难度大大降低。

准备工作

1. 官方提供的AndroidThing preview 6的镜像

2. Ubuntu 14.04系统,用于编译Android系统

3. Android 8.1源代码,这里使用的版本为android-8.1.0_r2, 源代码可以从(https://lug.ustc.edu.cn/wiki/mirrors/help/aosp)下载

提取文件

这里我需要从AndroidThings preview 6中提取整个分区及system分区中的部份文件

用如下命令将镜像文件进行拆分:

#! /bin/bash

mkdir -v SPLIT

sgdisk -p iot_rpi3.img | tail -n +10 | while read line

do

ARRAY=(${line})

start=${ARRAY[1]}

end=${ARRAY[2]}

name=${ARRAY[6]}

echo "=> START: ${start}, END: ${end}, NAME: ${name}"

dd if=iot_rpi3.img of=SPLIT/${name}.img skip=${start} bs=512 count=$((${end} - ${start} + 1))

done

我们只需要保留如下分区文件:

boot_a.img oem_a.img rpiboot.img system_a.img vendor_a.img

从system_a.img中提取如下文件:

.

+-- fstab.rpi3

+-- init.rpi3.rc

+-- system

| +-- bin

| | `-- surfaceflinger

| `-- lib

| +-- android.frameworks.displayservice@1.0.so

| +-- android.frameworks.vr.composer@1.0.so

| +-- android.hardware.boot@1.0.so

| +-- android.hardware.configstore@1.0.so

| +-- android.hardware.configstore-utils.so

| +-- android.hardware.graphics.allocator@2.0.so

| +-- android.hardware.graphics.bufferqueue@1.0.so

| +-- android.hardware.graphics.common@1.0.so

| +-- android.hardware.graphics.composer@2.1.so

| +-- android.hardware.graphics.mapper@2.0.so

| +-- android.hardware.media@1.0.so

| +-- android.hardware.power@1.0.so

| +-- android.hardware.usb@1.0.so

| +-- android.hardware.wifi@1.0.so

| +-- android.hardware.wifi@1.1.so

| +-- android.hardware.wifi.supplicant@1.0.so

| +-- android.hidl.token@1.0.so

| +-- android.hidl.token@1.0-utils.so

| +-- hw

| | +-- android.hidl.memory@1.0-impl.so

| | +-- audio.a2dp.default.so

| | +-- audio.primary.rpi3.so

| | +-- bluetooth.default.so

| | +-- bootctrl.bcb.so

| | +-- bootctrl.default.so -> bootctrl.bcb.so

| | +-- camera.v4l2.so

| | +-- gps.iot.so

| | +-- gralloc.rpi3.so

| | +-- keystore.default.so

| | +-- lights.rpi3.so

| | +-- memtrack.dummy.so

| | +-- peripheral_io.rpi3.so

| | `-- sensors.iot.so

| `-- libsurfaceflinger.so

`-- ueventd.rpi3.rc

从源代码开始编译Android系统

android-8.1.0_r2的代码从这里下载:https://lug.ustc.edu.cn/wiki/mirrors/help/aosp

文件结构如下:

O-8.1.0_r2-rpi3b/

`-- device

`-- brobwind

`-- rpi3

+-- AndroidProducts.mk

+-- BoardConfig.mk

+-- init.mini-emulator.rc

+-- mini_emulator_common.mk

+-- overlay

| `-- frameworks

| `-- base

| `-- core

| `-- res

| `-- res

| `-- values

| `-- config.xml

+-- root

| +-- fstab.rpi3

| +-- init.rpi3.rc

| +-- system

| | +-- bin

| | | `-- surfaceflinger

| | `-- lib

| | +-- android.frameworks.displayservice@1.0.so

| | +-- android.frameworks.vr.composer@1.0.so

| | +-- android.hardware.boot@1.0.so

| | +-- android.hardware.configstore@1.0.so

| | +-- android.hardware.configstore-utils.so

| | +-- android.hardware.graphics.allocator@2.0.so

| | +-- android.hardware.graphics.bufferqueue@1.0.so

| | +-- android.hardware.graphics.common@1.0.so

| | +-- android.hardware.graphics.composer@2.1.so

| | +-- android.hardware.graphics.mapper@2.0.so

| | +-- android.hardware.media@1.0.so

| | +-- android.hardware.power@1.0.so

| | +-- android.hardware.usb@1.0.so

| | +-- android.hardware.wifi@1.0.so

| | +-- android.hardware.wifi@1.1.so

| | +-- android.hardware.wifi.supplicant@1.0.so

| | +-- android.hidl.token@1.0.so

| | +-- android.hidl.token@1.0-utils.so

| | +-- hw

| | | +-- android.hidl.memory@1.0-impl.so

| | | +-- audio.a2dp.default.so

| | | +-- audio.primary.rpi3.so

| | | +-- bluetooth.default.so

| | | +-- bootctrl.bcb.so

| | | +-- bootctrl.default.so -> bootctrl.bcb.so

| | | +-- camera.v4l2.so

| | | +-- gps.iot.so

| | | +-- gralloc.rpi3.so

| | | +-- keystore.default.so

| | | +-- lights.rpi3.so

| | | +-- memtrack.dummy.so

| | | +-- peripheral_io.rpi3.so

| | | `-- sensors.iot.so

| | `-- libsurfaceflinger.so

| `-- ueventd.rpi3.rc

+-- rpi3.mk

+-- system.prop

+-- vendor.img

`-- vendorsetup.sh

编译完成之后,我们只需要最终生成的system img.

创建开机磁盘镜像

将上一步骤生成的system image替换掉SPLIT目录下的system_a.img, 然后执行如下脚本生成我们所需的磁盘镜像:

#! /bin/bash

#Disk iot_rpi3.img: 8912896 sectors, 4.2 GiB

#Logical sector size: 512 bytes

#Disk identifier (GUID): B4E0B8F7-2781-4463-B8F6-C5E9739823BC

#Partition table holds up to 128 entries

#First usable sector is 34, last usable sector is 8912862

#Partitions will be aligned on 8-sector boundaries

#Total free space is 13 sectors (6.5 KiB)

#

#Number Start (sector) End (sector) Size Code Name

# 1 40 131111 64.0 MiB FFFF rpiboot

# 2 131112 133159 1024.0 KiB FFFF uboot_a

# 3 133160 135207 1024.0 KiB FFFF uboot_b

# 4 135208 200743 32.0 MiB FFFF boot_a

# 5 200744 266279 32.0 MiB FFFF boot_b

# 6 266280 1314855 512.0 MiB FFFF system_a

# 7 1314856 2363431 512.0 MiB FFFF system_b

# 8 2363432 2363559 64.0 KiB FFFF vbmeta_a

# 9 2363560 2363687 64.0 KiB FFFF vbmeta_b

# 10 2363688 2365735 1024.0 KiB FFFF misc

# 11 2365736 2496807 64.0 MiB FFFF vendor_a

# 12 2496808 2627879 64.0 MiB FFFF vendor_b

# 13 2627880 4086055 712.0 MiB FFFF oem_a

# 14 4086056 5544231 712.0 MiB FFFF oem_b

# 15 5544232 5552423 4.0 MiB FFFF oem_bootloader_a

# 16 5552424 5560615 4.0 MiB FFFF oem_bootloader_b

# 17 5560616 5626151 32.0 MiB FFFF factory

# 18 5626152 5658919 16.0 MiB FFFF factory_bootloader

# 19 5658920 8912847 1.6 GiB FFFF userdata

# 20 8912848 8912855 4.0 KiB FFFF gapps

#SGDISK=/data/O-8.1.0_r2-rpi3b/out/host/linux-x86/bin/sgdisk

SGDISK=sgdisk

GDISK=gdisk

DD=dd

source=iot_rpi3.img

target=iot.img

DINFO="`${SGDISK} --print ${source}`"

sectors=`echo "${DINFO}" | head -n 1 | sed 's/.*:[[:space:]]*\([[:digit:]]\+\).*/\1/g'`

sector_size=`echo "${DINFO}" | head -n 2 | tail -n 1 | sed 's/.*:[[:space:]]*\([[:digit:]]\+\).*/\1/g'`

if [ ! -f ${target} ] ; then

dd if=/dev/zero of=${target} bs=${sector_size} count=${sectors}

fi

echo " => Clear partition table ..."

${SGDISK} --clear ${target}

echo " => Install GPT partition table ..."

${SGDISK} --set-alignment=1 $(echo "${DINFO}" | tail -n +10 | while read line

do

ARRAY=(${line})

num=${ARRAY[0]}

start=${ARRAY[1]}

end=${ARRAY[2]}

label=${ARRAY[6]}

uuid=`${SGDISK} --info ${num} ${source} | head -n 1 | sed 's/.*: \([0-9A-Z-]\+\).*/\1/g'`

echo "--new=${num}:${start}:${end} --typecode=${num}:${uuid} --change-name=${num}:${label}"

done) ${target}

echo " => Install hybrid MBR partitoin table ..."

${GDISK} << EOF ${target}

r

h

1

N

06

N

N

w

Y

EOF

echo " => Install images ...."

echo "${DINFO}" | tail -n +10 | while read line

do

ARRAY=(${line})

start=${ARRAY[1]}

end=${ARRAY[2]}

label=${ARRAY[6]}

if [ -f SPLIT/${label}.img ] ; then

echo " => Install: ${label} images ..."

${DD} if=SPLIT/${label}.img of=${target} conv=notrunc bs=${sector_size} count=$((${end} - ${start} + 1)) seek=${start}

fi

done

最终会在当前目录下生成iot.img文件。

写入磁盘镜像文件

将iot.img文件写入到TF卡中,可通过dd命令

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐