Waydorid是从anbox演进的新的容器安卓的一种方案,我们的客户想要运行安卓程序,这里描述如何使用waydroid来兼容安卓10的系统
git clone https://github.com/waydroid/libglibutil.git git clone https://github.com/waydroid/libgbinder.git git clone https://github.com/waydroid/gbinder-python git clone https://github.com/waydroid/waydroid.git
apt build-dep . debuild -us -uc
这里 gbinder-python没用changlog,所有需要额外处理一下
dch --create --package "gbinder-python" --newversion "1.0.0~git20210909-1" foo bar dh_make --createorig -p "gbinder-python_1.0.0~git20210909"
因为waydroid依赖容器,所以需要安装lxc
apt install lxc dpkg -i bridge-utils_1.6-2kylin1_arm64.deb liblxc1_1%3a4.0.2-0kylin1_arm64.deb liblxc-common_1%3a4.0.2-0kylin1_arm64.deb lxc_1%3a4.0.2-0kylin1_all.deb lxc-utils_1%3a4.0.2-0kylin1_arm64.deb
然后安装编译出来的包
dpkg -i libgbinder_1.1.25_arm64.deb libgbinder-tools_1.1.25_arm64.deb libglibutil_1.0.66_arm64.deb python3-gbinder_1.1_arm64.deb waydroid_1.3.0_all.deb
安卓系统需要binder和ashmem,如果系统安装了linux-module包,可以直接加载,如下
modprobe ashmem_linux modprobe binder_linux
如果linux是可编译的,可以修改config增加如下
CONFIG_ASHMEM=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y CONFIG_ANDROID_BINDERFS=y
CONFIG_BRIDGE / "802.1d Ethernet Bridging" ('Networking support -> Networking options -> 802.1d Ethernet Bridging') CONFIG_VETH / "Veth pair device" CONFIG_MACVLAN / "Macvlan" CONFIG_VLAN_8021Q / "Vlan" CONFIG_NETFILTER CONFIG_NF_NAT CONFIG_NF_TABLES CONFIG_NFT_NAT CONFIG_NETFILTER_XT_TARGET_CHECKSUM CONFIG_IP_NF_TARGET_MASQUERADE CONFIG_NF_CONNTRACK CONFIG_NETFILTER_XTABLES CONFIG_IP_NF_IPTABLES CONFIG_IP_NF_FILTER CONFIG_IP_NF_MANGLE
如下是kmre启动过程中需要的iptable_nat模块添加的宏:
CONFIG_PACKET=y CONFIG_NETFILTER=y CONFIG_IP_NF_CONNTRACK=y CONFIG_IP_NF_FTP=y CONFIG_IP_NF_IRC=y CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_NAT=y CONFIG_IP_NF_MATCH_STATE=y CONFIG_IP_NF_TARGET_LOG=y CONFIG_IP_NF_MATCH_LIMIT=y CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_NETFILTER_ADVANCED=y CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_NAMESPACES / "Namespaces" ('General Setup -> Namespaces support') CONFIG_UTS_NS / "Utsname namespace" ('General Setup -> Namespaces Support / UTS namespace') CONFIG_IPC_NS / "Ipc namespace" ('General Setup -> Namespaces Support / IPC namesapce') CONFIG_USER_NS / "User namespace" ('General Setup -> Namespaces Support / User namespace (EXPERIMENTAL)') CONFIG_PID_NS / "Pid namespace" ('General Setup -> Namespaces Support / PID Namespaces') CONFIG_NET_NS / "Network namespace" ('General Setup -> Namespaces Support -> Network namespace')
CONFIG_CGROUP_SCHED / "Cgroup sched" ('General Setup -> Control Group support -> Group CPU scheduler') CONFIG_FAIR_GROUP_SCHED / "Group scheduling for SCHED_OTHER" ('General Setup -> Control Group support -> Group CPU scheduler -> Group scheduling for SCHED_OTHER') CONFIG_BLK_CGROUP / "Block IO controller" ('General Setup -> Control Group support -> Block IO controller') CONFIG_CFQ_GROUP_IOSCHED / "CFQ Group Scheduling support" ('Enable the block layer -> IO Schedulers -> CFQ I/O scheduler -> CFQ Group Scheduling support') CONFIG_CGROUP_CPUACCT / "Cgroup cpu account" ('General Setup -> Control Group support -> Simple CPU accounting cgroup subsystem') CONFIG_MEMCG_SWAP / Memory Resource Controller Swap Extension
内核配置可以按照如下脚本检测docker启动必须的脚本:check-config.sh;使用命令如下:
./check-config.sh rockchip_linux_defconfig
配置如下
General setup ---> [*] Control Group support ---> [*] Freezer cgroup subsystem [*] Device controller for cgroups [*] Cpuset support [*] Include legacy /proc/<pid>/cpuset file [*] Simple CPU accounting cgroup subsystem [*] Resource counters [*] Memory Resource Controller for Control Groups [*] Memory Resource Controller Swap Extension [*] Memory Resource Controller Swap Extension enabled by default [*] Enable perf_event per-cpu per-container group (cgroup) monitoring [*] Group CPU scheduler ---> [*] Group scheduling for SCHED_OTHER [*] Group scheduling for SCHED_RR/FIFO <*> Block IO controller -*- Namespaces support [*] UTS namespace [*] IPC namespace [*] User namespace (EXPERIMENTAL) [*] PID Namespaces [*] Network namespace [*] Configure standard kernel features (expert users) [*] Networking support ---> Networking options ---> <M> 802.1d Ethernet Bridging <M> 802.1Q VLAN Support Device Drivers ---> [*] Network device support ---> <M> MAC-VLAN support (EXPERIMENTAL) <M> Virtual ethernet pair device Character devices ---> -*- Unix98 PTY support [*] Support multiple instances of devpts
在cmdline,也就是chosen的bootarge下追加 psi=1,可以降低oom的风险
默认需要下载system.img和vendor.img
如果已存在上述文件,可以直接使用
mkdir -p /usr/share/waydroid-extra/images mv system.img vendor.img /usr/share/waydroid-extra/images/ waydroid init
如果没有system vendor,则会自动下载
下载地址为:https://sourceforge.net/projects/waydroid/files/images/
使用之前,建议重启一下容器服务,如下:
systemctl restart waydroid-container.service
重启之后,在机器环境下直接启动安卓UI如下
waydroid show-full-ui
安卓容器可以获取/设置属性,通过如下命令
waydroid prop get ro.hardware.egl waydroid prop set ro.hardware.egl=swiftshader
waydroid app install *.apk waydroid app launch com.android.calculator2
waydroid logcat
waydroid shell
ro.hardware.gralloc和ro.hardware.egl是选择显卡驱动的。
如果没有选择,默认走gbm和mesa。如果为了兼容,可以走
ro.hardware.gralloc=default ro.hardware.egl=swiftshader
当然不同机器按照实际情况走即可
waydroid是基于wayland后端,如果要在X11平台启动,则需要启动一个wayland后端,这里可以是weston
然后在weston里面启动waydroid ui即可
飞腾E2000默认可以通过wic格式安装,wic格式按照的方式如下。
Win32DiskImager 可以烧录img格式文件。主要步骤如下
a 选择wic文件
b 选择需要刻录的设备
c 点击写入
将U盘插入机器,通过dd命令直接更新,如下:
sudo dd if=Kylin-embedded_vkylin_arm64-xxxx-rc1.wic of=/dev/sda status=progress
注意这里/dev/sda为U盘识别的块,而不是U盘识别的分区.如果插入U盘是sdb。则这里填写/dev/sdb 以此类推
在启动过程中一直按着空格或者enter键,如果是uboot启动就会进入uboot模式
E2000默认的串口波特率为115200,根据实际板子情况接入TTL串口,通过串口功能确保能够正常读写
开机一直按下ctrl+c,直到进入uboot shell,如下所示
在 uboot shell中输入 usb start 能够开启USB功能,此时uboot阶段即可正常识别U盘设备,命令如下:
E2000#usb start starting USB... Bus usb3@31a00000: Register 2000110 NbrPorts 2 Starting the controller USB XHCI 1.10 Bus usb3@31a20000: Register 2000110 NbrPorts 2 Starting the controller USB XHCI 1.10 scanning bus usb3@31a00000 for devices... 5 USB Device(s) found scanning bus usb3@31a20000 for devices... 1 USB Device(s) found scanning usb for storage devices... 1 Storage Device(s) found
这里如看到”scanning usb for storage devices... 1 Storage Device(s) found“ 字样,则代表U盘已经识别,如看不到,则检查硬件或uboot驱动
通过ls 命令可以查看盘符内文件系统内容,如下
ls usb 0:1 / 为查看USB设备第一个盘符的文件内容 ls usb 0:2 / 为查看USB设备第二个盘符的文件内容 E2000#ls usb 0:1 / EFI/ System Volume Information/ 0 file(s), 2 dir(s) E2000#ls usb 0:2 / <DIR> 4096 . <DIR> 4096 .. <DIR> 16384 lost+found <SYM> 7 bin <SYM> 8 sbin <SYM> 7 lib 0 .exectl <DIR> 4096 var <DIR> 4096 usr <DIR> 4096 boot <DIR> 4096 dev <DIR> 4096 etc <DIR> 4096 home <DIR> 4096 proc <DIR> 4096 root <DIR> 4096 run <DIR> 4096 sys <DIR> 4096 tmp <DIR> 4096 mnt <DIR> 4096 srv <DIR> 4096 opt <DIR> 4096 media <DIR> 4096 download
setenv bootargs 'console=ttyAMA1,115200 earlycon=pl011,0x2800d000 root=/dev/sda2 rw rootwait security=none';
在Uboot shell中敲入如上命令即可修改开机挂载root分区的具体位置
这里上述参数仅修改root=,用于指定内核挂载操作系统的真实根文件系统位置(root=/dev/sda2),这里通过u盘挂载,则默认可知rootfs位置为/dev/sda2
如不更新内核,在此步骤上,可以直接运行boot命令启动系统。这样能够达到在使用原内核直接启动/dev/sda2的系统的目的。
boot # 该命令使用原来内核启动系统
如果不使用kylin内核,则直接跳转到《三:U盘系统内操作》
ext4load usb 0:2 $kernel_addr boot/uImage-5.4.18-63-generic;
上述参数,可以更换uboot启动过程中的内核加载uimage的实际文件。这里实际内核文件为uImage-5.4.18-63-generic,存放于usb设备的第二个分区的/boot目录。
注意:内核uImage需适配硬件,否则有概率启动失败
ext4load usb 0:2 $ft_fdt_addr /boot/dtb-5.4.18-63-generic/device-tree/phytium/e2000d-demo-board.dtb
上述参数,可以更换uboot启动过程中加载设备树dtb的实际文件,这里实际设备树文件为e2000d-demo-board.dtb,存放于usb设备的第二个分区的/boot/dtb-5.4.18-63-generic/device-tree/phytium/目录
注意:内核设备树需适配硬件,否则有概率启动失败
bootm $kernel_addr -:- $ft_fdt_addr
上述参数可以直接将内核启动,通过如上方法,E2000可以正常启动为U盘(sda2)内的系统镜像
saveenv
上述命令可以保存uboot中的环境变量,后续每次启动将自动启动,无需重复配置.
当一切就绪后,可使用此保存当前环境变量,U盘启动无需保存,因其仅启动一次,如设置nvme/sata/mmc启动则可保存,以免重复配置
在上述方式通过U盘进入系统之后,进入终端,可以发现系统是通过sda2挂载的。现在需要将其正式的更新到固定磁盘上。
root@kylinos:~# mount /dev/sda2 on / type ext4 (rw,relatime)
通过上述命令可以发现,现在已经进入U盘系统中,需要在U盘系统中将系统更新到emmc中,主要如下:
tar xzvf Kylin-embedded_vkylin_arm64-xxxx-rc1.wic.tar.gz
# 目的盘为nvme sudo dd if=Kylin-embedded_vkylin_arm64-xxxx-rc1.wic of=/dev/nvme0n1 status=progress # 目的盘为sata sudo dd if=Kylin-embedded_vkylin_arm64-xxxx-rc1.wic of=/dev/sda status=progress
需要注意的是,这里的of=指定的是真实存在的物理设备,例如/dev/nvme0n1为机器的nvme盘,具体安装情况视当前硬件情况决定
如果不想dd wic文件,可以直接将U盘的根分区内容直接对拷到目的硬盘。例如
cp -raf /run/media/usb_storage/* /rum/media/nvme0np2/
这里/run/media/usb_storage/ 是U盘的根分区挂载,可以通过 mount /dev/sda2 /run/media/usb_storage/挂载
这里/rum/media/nvme0np2/
通过上述操作,实际已经安装好系统,现在仅需要进入uboot中,保存自己需要启动的环境变量。从而做到每次开机自动加载即可。
setenv bootargs 'console=ttyAMA1,115200 earlycon=pl011,0x2800d000 root=/dev/sda2 rw rootwait security=none'; setenv load_kernel 'ext4load scsi 0:3 $kernel_addr boot/uImage-5.4.18-63.52-e2000-rc15-generic'; setenv load_fdt 'ext4load scsi 0:3 $ft_fdt_addr boot/dtb/e2000d-demo-board.dtb'; saveenv
setenv bootargs 'console=ttyAMA1,115200 earlycon=pl011,0x2800d000 root=/dev/sda3 rw rootwait security=none'; setenv load_kernel 'ext4load usb 0:3 $kernel_addr boot/uImage-5.4.18-63.52-e2000-rc15-generic'; setenv load_fdt 'ext4load usb 0:3 $ft_fdt_addr boot/dtb/e2000d-demo-board.dtb'; saveenv
setenv bootargs 'console=ttyAMA1,115200 earlycon=pl011,0x2800d000 root=/dev/nvme0n1p3 rw rootwait security=none'; setenv load_kernel 'ext4load nvme 0:3 $kernel_addr boot/uImage-5.4.18-63.52-e2000-rc15-generic'; setenv load_fdt 'ext4load nvme 0:3 $ft_fdt_addr boot/dtb/e2000d-demo-board.dtb'; saveenv
printenv可以打印变量,确定自己设置的和打印的是否一致即可。接下来就能正常启动新的系统了。
第一次登录需要手动运行resize-assistant。用于扩大rootfs分区
默认密码 kylin qwer1234
设置启动一共就三步,分别为,设置内核地址,设置设备树地址,设置启动命令,保存配置。通常仅修改加载内核和设备树的地址。 现在示例想系统更新到mmc盘符,主要操作如下: 打印uboot的所有配置:printenv,setenv args "contents"可以配置具体的环境变量,最后saveenv保存环境变量最后重启即可生效
如下是我们配置的usb启动的整个例子可以参考:
E2000#printenv arch=arm baudrate=115200 board=e2000 board_name=e2000 boot_os=bootm $kernel_addr -:- $ft_fdt_addr bootargs=console=ttyAMA1,115200 earlycon=pl011,0x2800d000 \\\ root=/dev/mmcblk0p1 rw rootwait security=none bootcmd=usb start; run load_kernel; run load_fdt; run boot_os bootdelay=2 cpu=armv8 distro_bootcmd=run load_kernel; run load_initrd; run load_fdt; run boot_os eth0addr=00:11:22:33:44:55 eth1addr=10:22:33:44:55:66 eth2addr=10:11:22:33:44:55 eth3addr=00:22:33:44:55:66 ethaddr=00:11:22:33:44:55 fdtcontroladdr=f9c3f7f0 fileaddr=90100000 filesize=17d0240 ft_fdt_addr=0x90000000 ft_fdt_name=boot/dtb/e2000.dtb gatewayip=202.197.67.1 initrd_addr=0x95000000 ipaddr=202.197.67.2 kernel_addr=0x90100000 load_fdt=ext4load usb 0:2 0x90000000 boot/e2000d-demo-board.dtb load_initrd=ext4load usb 0:2 0x95000000 initrd.img-5.4.18-65-generic load_kernel=ext4load usb 0:2 0x90100000 boot/uImage-kylin loadaddr=0x90000000 netdev=eth0 netmask=255.255.255.0 serverip=202.197.67.3 stderr=uart@2800d000 stdin=uart@2800d000 stdout=uart@2800d000 vendor=phytium Environment size: 1047/4092 bytes
备注:
bootargs=console=ttyAMA1,115200 earlycon=pl011,0x2800d000 \\\ root=/dev/mmcblk0p1 rw rootwait security=none
/dev/mmcblk0p1为系统分区,可以从内核串口log中可以看到,如果找不到rootfs可以查看此处
load_fdt=ext4load usb 0:2 0x90000000 boot/e2000d-demo-board.dtb load_kernel=ext4load usb 0:2 0x90100000 boot/uImage-kylin
e2000d-demon-board.dtb和uImage两个文件我们可以手动复制到u盘中的/boot/目录下,根据cpu的不同e2000d,e2000q,e2000s可以选择不同的dtb文件
setenv load_kernel 'ext4load usb 0:2 $kernel_addr boot/uImage-5.4.18-63-generic'; setenv load_fdt 'ext4load usb 0:2 $ft_fdt_addr boot/e2000d-demo-board.dtb'; setenv bootcmd 'usb start; run load_kernel; run load_fdt; run boot_os' setenv boot_os 'bootm $kernel_addr -:- $ft_fdt_addr' saveenv
这里设置了内核地址为U盘的 boot/uImage-5.4.18-63-generic,设备树地址为 U盘的 boot/e2000d-demo-board.dtb,启动命令为 bootm ft_fdt_addr
dd if=Kylin-embedded_vkylin_arm64_rc1_20230419.wic of=/dev/mmcblk0 status=progress
setenv load_kernel 'ext4load mmc 0:2 $kernel_addr boot/uImage-5.4.18-63-generic'; setenv load_fdt 'ext4load mmc 0:2 $ft_fdt_addr boot/e2000d-demo-board.dtb'; setenv bootcmd 'usb start; run load_kernel; run load_fdt; run boot_os' setenv boot_os 'bootm $kernel_addr -:- $ft_fdt_addr' saveenv
通过上述设置,下次启动则可以正常加载新的系统。
通常e2000的机器,设备树默认使用机器本身的,内核使用麒麟和客户自身的均可以,系统必须指定为麒麟系统即可完成正常安装
有客户需要在不接任何显示器的前提下能够正常启动图形服务器。但是linux drm框架下,drm是建立在connector上。所以需要内核打开虚拟显示屏,这样能够将图形启动在虚拟显示器上,下面介绍主要操作方法
配置文件打开
CONFIG_ROCKCHIP_VCONN=y
这个配置依赖于
HAS_IOMEN[=y]
与
DRM_ROCKCHIP[=y]
一般都是打开的
virtual_con { compatible = "rockchip,virtual-connector"; };
static int rockchip_virtual_connector_probe(struct platform_device *pdev) { return component_add(&pdev->dev, &rockchip_virtual_connector_ops); }
因为rk的drm驱动走的component框架,这里只需要为其添加组件即可
static const struct component_ops rockchip_virtual_connector_ops = { .bind = rockchip_virtual_connector_bind, .unbind = rockchip_virtual_connector_unbind, };
drm驱动会逐个绑定drm的connector,然后根据具体的connector紧张逐个绑定encoder
rockchip_virtual_connector_register(vconn); list_for_each_entry_safe(vconn_dev, n, &vconn->list_head, list) { drm_simple_encoder_init(vconn->drm_dev, encoder, vconn_dev→encoder_type); drm_connector_init(vconn->drm_dev, connector, &rockchip_virtual_connector_funcs, vconn_dev→output_type); drm_connector_attach_encoder(connector, encoder);
在绑定的时候会注册connector,然后根据之前创建的设备逐个绑定connector和decoder
root@kylin:~# xrandr Screen 0: minimum 320 x 200, current 1024 x 768, maximum 16384 x 16384 Virtual-1 connected primary 1024x768+0+0 (normal left inverted right x axis y axis) 0mm x 0mm 1024x768 60.00*+ 4096x2160 60.00 59.94 2560x1600 59.99 59.97 1920x1440 60.00 1856x1392 60.00 1792x1344 60.00 2048x1152 60.00 1920x1200 59.88 59.95 1920x1080 60.00 1600x1200 60.00 1680x1050 59.95 59.88 1400x1050 59.98 59.95 1600x900 60.00 1280x1024 60.02 1440x900 59.89 59.90 1280x960 60.00 1366x768 59.79 60.00 1360x768 60.02 1280x800 59.81 59.91 1280x768 59.87 59.99 1280x720 60.00 800x600 60.32 56.25 848x480 60.00 640x480 59.94
至此,即使机器没有任何的实际connector,也可以虚拟一个假的connector,也就是虚拟显示屏来执行图形APP的运行
为了丰富版本的调试功能,这里提供了web ssh来支持浏览器打开ssh。只需要四步即可完成,只要实施步骤如下
apt install shellinabox
根据自身机器环境配置网络即可
为了更加安全,这里使用9999端口,如下
sed -i 's/SHELLINABOX_PORT=4200/SHELLINABOX_PORT=9999/g' /etc/default/shellinabox
systemctl restart shellinabox
netstat -ntp | grep shellinabox
如果一切正常,则看到出现9999端口的shellinaboxd
项目中有客户需要将设备当作纯U盘来使用,已知Linux的gadget本身就支持U盘设备,这里描述一下如何将Linux系统作为U盘使用。
对于usb gadget功能,需要打开内核默认设置,主要配置如下:
CONFIG_USB_F_MASS_STORAGE=y CONFIG_USB_LIBCOMPOSITE=y CONFIG_USB_CONFIGFS_MASS_STORAGE=y CONFIG_USB_MASS_STORAGE=m
将CONFIG_USB_MASS_STORAGE作为ko的原因是需要加载时传参,如果希望固化,则可以将传参写到cmdline中。
对于U盘功能,则需要单独划一块分区给U盘使用,这里可以是单独的分区,也可以是一个img文件。
如果是单独的分区,则如下:
mkfs.vfat /dev/mmc0blk1p5 insmod g_mass_stroage.ko file=/dev/mmc0blk1p5 removable=1
如果需要系统内也能看到文件修改,这里增加一个fstab即可。如下
/dev/mmc0blk1p5 /data1 vfat defaults,user,rw,codepage=936,iocharset=utf8 0 0
如果是单独的文件,则如下:
dd if=/dev/zero of=/media/usb_stroage.img bs=512 count=2097152 # (1G大小) mkfs.vfat /media/usb_stroage.img
这里可以利用fstab的挂载
/media/usb_stroage.img /data1 vfat defaults,user,rw,codepage=936,iocharset=utf8 0 0
然后加载驱动
insmod g_mass_stroage.ko file=/dev/loop0 removable=1
如果不确定loop0是否为自己的img,可以指定挂载如下
losetup /dev/loop0 /media/usb_stroage.img
使用就非常简单了,将otg的功能的USB接上电脑,电脑会按照U盘的方式弹出一个已经格式化好的文件。此时正常使用U盘即可。