Nov 30, 2021
Technology目的
在Ubuntu 18.04.6
上配置pulseaudio的 system-wide
daemon模式,以使得pulseaudio
为所有用户可用。
步骤
确保pulseaudio
被安装(默认应该是被安装的), 撰写一个systemd
服务条目,重新定义其启动方式(做完以下步骤后需要重新启动机器), 需注意需要手动执行usermod
一行为所有用户添加到组里:
# vi /etc/systemd/system/pulseaudio.service
[Unit]
Description=PulseAudio Daemon
[Install]
WantedBy=multi-user.target
[Service]
Type=simple
PrivateTmp=true
ExecStart=/usr/bin/pulseaudio --system --realtime --disallow-exit --no-cpu-limit
# vi /usr/share/dbus-1/system.d/pulseaudio.conf
<?xml version="1.0"?> <!--*-nxml-*-->
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy group="pulse">
<allow own="org.pulseaudio.Server"/>
</policy>
<policy context="default">
<allow send_destination="org.pulseaudio.Server"/>
<allow receive_sender="org.pulseaudio.Server"/>
</policy>
</busconfig>
# groupadd --system pulse
# groupadd --system pulse-access
# useradd --system -g pulse -G audio -d /var/run/pulse -m pulse
# usermod -G video,pulse-access root
# usermod -G video,pulse-access test
# usermod -G video,pulse-access seat1
# usermod -G video,pulse-access seat2
# echo "default-server = /var/run/pulse/native" >> /etc/pulse/client.conf
# echo "autospawn = no" >> /etc/pulse/client.conf
# systemctl daemon-reload
# systemctl enable pulseaudio
# reboot
重启后,以ssh登陆到各用户下,在命令行下播放音频,如用mplayer 1.mp3
等操作,应该可以看到音频被正确解码,但是此时无声音,应该使用以下命令unmute音道.
开启所有音道:
# pactl set-sink-mute @DEFAULT_SINK@ false
Nov 15, 2021
Technology目的
这里记录开启转码支持所需要更改的文件列表
build/target/board/generic_x86_64/BoardConfig.mk
, 在文件的尾部添加关于ABI架构支持的列表:
# Native Bridge ABI List
NB_ABI_LIST_32_BIT := armeabi-v7a armeabi
NB_ABI_LIST_64_BIT := arm64-v8a
TARGET_CPU_ABI_LIST_64_BIT ?= $(TARGET_CPU_ABI) $(TARGET_CPU_ABI2)
TARGET_CPU_ABI_LIST_32_BIT ?= $(TARGET_2ND_CPU_ABI) $(TARGET_2ND_CPU_ABI2)
TARGET_CPU_ABI_LIST := \
$(TARGET_CPU_ABI_LIST_64_BIT) \
$(TARGET_CPU_ABI_LIST_32_BIT) \
$(NB_ABI_LIST_64_BIT) \
$(NB_ABI_LIST_32_BIT)
TARGET_CPU_ABI_LIST_32_BIT += $(NB_ABI_LIST_32_BIT)
TARGET_CPU_ABI_LIST_64_BIT += $(NB_ABI_LIST_64_BIT)
build/target/board/generic_x86_64/device.mk
, 文件结尾处添加关于nativebridge
的编译(这里关于属性的配置似乎无法生效,所以后面会在libart.mk中配置属性):
# Added houdini
$(call inherit-product-if-exists, vendor/google/chromeos-x86/target/houdini.mk)
$(call inherit-product-if-exists, vendor/google/chromeos-x86/target/native_bridge_arm_on_x86.mk)
PRODUCT_SYSTEM_DEFAULT_PROPERTIES += persist.sys.nativebridge=1
# Get native bridge settings
$(call inherit-product-if-exists,device/generic/common/nativebridge/nativebridge.mk)
# NativeBridge
PRODUCT_PACKAGES += libhoudini houdini
PRODUCT_PROPERTY_OVERRIDES += ro.dalvik.vm.isa.arm=x86 ro.enable.native.bridge.exec=1
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.dalvik.vm.isa.arm=x86 ro.enable.native.bridge.exec=1
PRODUCT_PACKAGES += houdini64
PRODUCT_PROPERTY_OVERRIDES += ro.dalvik.vm.isa.arm64=x86_64 ro.enable.native.bridge.exec64=1
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.dalvik.vm.isa.arm64=x86_64 ro.enable.native.bridge.exec64=1
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.dalvik.vm.native.bridge=libhoudini.so
build/target/product/AndroidProducts.mk
中加入关于编译时lunch
的选项:
COMMON_LUNCH_CHOICES := \
.......
sdk_phone_x86_64-userdebug \
build/target/product/runtime_libart.mk
中注释掉ro.dalvik.vm.native.bridge=0
的默认设置,加入关于ro.dalvik.vm.isa.arm
及其他几个参数配置
#PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
# ro.dalvik.vm.native.bridge=0
PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
ro.dalvik.vm.isa.arm=x86 \
ro.enable.native.bridge.exec=1 \
ro.dalvik.vm.isa.arm64=x86_64 \
ro.enable.native.bridge.exec64=1 \
build/target/product/sdk_phone_x86.mk
及build/target/product/sdk_phone_x86_64.mk
中添加所需要拷贝的静态库的定义:
#PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
# PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST := \
#
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST := \
system/bin/houdini \
system/bin/houdini64 \
system/etc/binfmt_misc/arm64_dyn \
.......
device/generic/x86_64/BoardConfig.mk
中添加以下规则:
PRC_COMPATIBILITY_PACKAGE := true
BUILD_ARM_FOR_X86 := true
-include vendor/google/chromeos-x86/board/native_bridge_arm_on_x86.mk
device/generic/x86_64/mini_x86_64.mk
中添加关于nativebridge
的编译:
$(call inherit-product-if-exists,device/generic/common/nativebridge/nativebridge.mk)
frameworks/base/core/java/com/android/internal/content/NativeLibraryHelper.java
区别:
7,88d86
< final String pkgName;
< final String apkDir;
99,110d96
< public static String getApkDirFromCodePath(String codePath) {
< if (codePath == null ||
< codePath.startsWith("/system/") ||
< codePath.startsWith("/system_ext/") ||
< codePath.startsWith("/product/") ||
< codePath.startsWith("/vendor/") ||
< codePath.startsWith("/oem/")) {
< return null;
< }
< return codePath;
< }
<
113c99
< lite.debuggable, lite.packageName, getApkDirFromCodePath(lite.codePath));
---
> lite.debuggable);
117c103
< boolean extractNativeLibs, boolean debuggable, String pkgName, String apkdir) throws IOException {
---
> boolean extractNativeLibs, boolean debuggable) throws IOException {
134c120
< return new Handle(apkPaths, apkHandles, multiArch, extractNativeLibs, debuggable, pkgName, apkdir);
---
> return new Handle(apkPaths, apkHandles, multiArch, extractNativeLibs, debuggable);
146c132
< lite.extractNativeLibs, lite.debuggable, lite.packageName, getApkDirFromCodePath(lite.codePath));
---
> lite.extractNativeLibs, lite.debuggable);
150c136
< boolean extractNativeLibs, boolean debuggable, String pkgName, String apkdir) {
---
> boolean extractNativeLibs, boolean debuggable) {
156,157d141
< this.pkgName = pkgName;
< this.apkDir = apkdir;
232,234c216
< final int res = nativeFindSupportedAbiReplace(apkHandle, supportedAbis,
< handle.debuggable, handle.pkgName, handle.apkDir);
<
---
> final int res = nativeFindSupportedAbi(apkHandle, supportedAbis, handle.debuggable);
256,257c238,239
< private native static int nativeFindSupportedAbiReplace(long handle, String[] supportedAbis,
< boolean debuggable, String pkgName, String apkdir);
---
> private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis,
> boolean debuggable);
frameworks/base/core/jni/Android.bp
中添加编译规则:
15d14
< "-D_PRC_COMPATIBILITY_PACKAGE_",
71d69
< "abipicker/ABIPicker.cpp",
frameworks/base/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
中添加:
42,45d41
< #ifdef _PRC_COMPATIBILITY_PACKAGE_
< #include "abipicker/ABIPicker.h"
< #endif
<
60,64d55
< #ifdef _PRC_COMPATIBILITY_PACKAGE_
< #define X86ABI "x86"
< #define X8664ABI "x86_64"
< #endif
<
517,524c508,509
< com_android_internal_content_NativeLibraryHelper_findSupportedAbi_replace(
< JNIEnv *env,
< jclass clazz,
< jlong apkHandle,
< jobjectArray javaCpuAbisToSearch,
< jboolean debuggable,
< jstring apkPkgName,
< jstring apkDir)
---
> com_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, jclass clazz,
> jlong apkHandle, jobjectArray javaCpuAbisToSearch, jboolean debuggable)
526,612c511
< #ifdef _PRC_COMPATIBILITY_PACKAGE_
<
< int abiType = findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable);
< if (apkDir == NULL) {
< return (jint)abiType;
< }
<
< char abiFlag[256] = {'\0'};
< ScopedUtfChars apkdir(env, apkDir);
< size_t apkdir_size = apkdir.size();
< const int numAbis = env->GetArrayLength(javaCpuAbisToSearch);
< Vector<ScopedUtfChars*> supportedAbis;
<
< assert(apkdir_size < 256 - 15);
< if (strlcpy(abiFlag, apkdir.c_str(), 256) != apkdir.size()) {
< return (jint)abiType;
< }
<
< int abiIndex = 0;
< abiFlag[apkdir_size] = '/';
< abiFlag[apkdir_size + 1] = '.';
< for (abiIndex = 0; abiIndex < numAbis; abiIndex++) {
< ScopedUtfChars* abiName = new ScopedUtfChars(env,
< (jstring)env->GetObjectArrayElement(javaCpuAbisToSearch, abiIndex));
< supportedAbis.push_back(abiName);
< if (abiName == NULL || abiName->c_str() == NULL || abiName->size() <= 0) {
< break;
< }
< if ((strlcpy(abiFlag + apkdir_size + 2, abiName->c_str(), 256 - apkdir_size - 2)
< == abiName->size()) && (access(abiFlag, F_OK) == 0)) {
< abiType = abiIndex;
< break;
< }
< }
<
< if (abiIndex < numAbis) {
< for (int j = 0; j < abiIndex; ++j) {
< if (supportedAbis[j] != NULL) {
< delete supportedAbis[j];
< }
< }
< return (jint)abiType;
< }
<
< do {
< if (abiType < 0 || abiType >= numAbis) {
< break;
< }
<
< if (0 != strcmp(supportedAbis[abiType]->c_str(), X86ABI) &&
< 0 != strcmp(supportedAbis[abiType]->c_str(), X8664ABI)) {
< break;
< }
<
< ScopedUtfChars name(env, apkPkgName);
< if (NULL == name.c_str()) {
< break;
< }
<
< if (isInOEMWhiteList(name.c_str())) {
< break;
< }
<
< ABIPicker picker(name.c_str(),supportedAbis);
< if (!picker.buildNativeLibList((void*)apkHandle)) {
< break;
< }
<
< abiType = picker.pickupRightABI(abiType);
< if (abiType >= 0 && abiType < numAbis &&
< (strlcpy(abiFlag + apkdir_size + 2, supportedAbis[abiType]->c_str(),
< 256 - apkdir_size - 2) == supportedAbis[abiType]->size())) {
< int flagFp = creat(abiFlag, 0644);
< if (flagFp != -1) {
< close(flagFp);
< }
< }
<
< } while(0);
<
< for (int i = 0; i < numAbis; ++i) {
< delete supportedAbis[i];
< }
< return (jint)abiType;
< #else
< return (jint)findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable);
< #endif
---
> return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable);
703,705c602,604
< {"nativeFindSupportedAbiReplace",
< "(J[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)I",
< (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi_replace},
---
> {"nativeFindSupportedAbi",
> "(J[Ljava/lang/String;Z)I",
> (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi},
frameworks/base/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
添加:
139,141c139
< pkg.isDebuggable(),
< pkg.getPackageName(),
< NativeLibraryHelper.Handle.getApkDirFromCodePath(pkg.getCodePath())
---
> pkg.isDebuggable()
system/linkerconfig/contents/namespace/systemdefault.cc
添加关于空间权限:
build/system/linkerconfig/contents/namespace/systemdefault.cc origin/system/linkerconfig/contents/namespace/systemdefault.cc
67,70d66
< "/system/lib/arm",
< "/system/lib/arm/nb",
< "/system/lib64/arm64",
< "/system/lib64/arm64/nb",
20220225 added:
需加入abipicker的支持:
scp -r ./frameworks/base/core/jni/abipicker/ remote_folder
上传/vendor
目录下的相关内容:
scp -r vendor/google/ root@192.168.xx.xxx:/root/Code/redroid_11/vendor/
如果是redroid
的编译,而对应需要修改redroid文件的定义:
# vim device/redroid/redroid_x86_64/device.mk
PRODUCT_PACKAGES += \
vulkan.intel \
# Added houdini
$(call inherit-product-if-exists, vendor/google/chromeos-x86/target/houdini.mk)
$(call inherit-product-if-exists, vendor/google/chromeos-x86/target/native_bridge_arm_on_x86.mk)
PRODUCT_SYSTEM_DEFAULT_PROPERTIES += persist.sys.nativebridge=1
# Get native bridge settings
$(call inherit-product-if-exists,device/generic/common/nativebridge/nativebridge.mk)
# NativeBridge
PRODUCT_PACKAGES += libhoudini houdini
PRODUCT_PROPERTY_OVERRIDES += ro.dalvik.vm.isa.arm=x86 ro.enable.native.bridge.exec=1
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.dalvik.vm.isa.arm=x86 ro.enable.native.bridge.exec=1
PRODUCT_PACKAGES += houdini64
PRODUCT_PROPERTY_OVERRIDES += ro.dalvik.vm.isa.arm64=x86_64 ro.enable.native.bridge.exec64=1
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.dalvik.vm.isa.arm64=x86_64 ro.enable.native.bridge.exec64=1
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.dalvik.vm.native.bridge=libhoudini.so
# vim device/TARGET_CPU_ABI := x86_64
TARGET_ARCH := x86_64
TARGET_ARCH_VARIANT := x86_64
TARGET_2ND_CPU_ABI := x86
TARGET_2ND_ARCH := x86
TARGET_2ND_ARCH_VARIANT := x86_64
include build/make/target/board/BoardConfigGsiCommon.mk
TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE := 16777216
BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE := 16777216
BOARD_MESA3D_USES_MESON_BUILD := true
BOARD_MESA3D_GALLIUM_DRIVERS := virgl radeonsi i915 iris crocus
BOARD_MESA3D_VULKAN_DRIVERS := virtio-experimental amd intel
DEVICE_MANIFEST_FILE += device/redroid/manifest.xml
PRC_COMPATIBILITY_PACKAGE := true
BUILD_ARM_FOR_X86 := true
-include vendor/google/chromeos-x86/board/native_bridge_arm_on_x86.mk
# Native Bridge ABI List
NB_ABI_LIST_32_BIT := armeabi-v7a armeabi
NB_ABI_LIST_64_BIT := arm64-v8a
TARGET_CPU_ABI_LIST_64_BIT ?= $(TARGET_CPU_ABI) $(TARGET_CPU_ABI2)
TARGET_CPU_ABI_LIST_32_BIT ?= $(TARGET_2ND_CPU_ABI) $(TARGET_2ND_CPU_ABI2)
TARGET_CPU_ABI_LIST := \
$(TARGET_CPU_ABI_LIST_64_BIT) \
$(TARGET_CPU_ABI_LIST_32_BIT) \
$(NB_ABI_LIST_64_BIT) \
$(NB_ABI_LIST_32_BIT)
TARGET_CPU_ABI_LIST_32_BIT += $(NB_ABI_LIST_32_BIT)
TARGET_CPU_ABI_LIST_64_BIT += $(NB_ABI_LIST_64_BIT)
Nov 10, 2021
Technology前提
基准操作系统为ubuntu-20.04.3-live-server-amd64.iso
, 不可以安装为desktop
版本的iso。
系统及包更新
确保系统更新到最新:
$ sudo apt-get update -y && sudo apt-get upgrade -y
安装必要的包(这里需要严格按照顺序来安装,否则会出现多安装包的情况导致gdm
被安装后sddm
无法正常工作):
$ sudo apt-get install -y sddm unzip autoconf automake libtool pkg-config build-essential x11proto-dev xserver-xorg-dev libxcb-util-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-shm0-dev libxcb-randr0-dev vim cmake cmake-extras extra-cmake-modules libpam-dev libxcb-xkb-dev qt5-default libqt5qml5 qt5-qmltooling-plugins qtdeclarative5-dev xutils-dev
$ sudo apt-get install openbox --no-install-recommends --no-install-suggests
$ sudo apt-get install -y xinit
Multi-seat编译/配置
将multi-seat-2004.tar.gz
上传到机器上,解压:
$ tar xzvf multi-seat-2004.tar.gz
$ ls
multi-seat sddm
$ cd multi-seat/
$ ls
sddm_config sddm-nested-multiseat udev_config xf86-video-nested xorg_config
注意在20.04的系统中,不需要编译sddm-nested-multiseat
,因为编译的过程中会引入gdm3
,后期我们用直接拷贝二进制文件的方式安装sddm-nested-multiseat
。
编译xf86-video-nested
包:
$ cd xf86-video-nested
$ ./autogen.sh && ./configure --prefix=/usr && make -j2 && sudo make install
安装sddm-nested
:
$ cd sddm
$ ./install.sh
更新sddm
登陆免密配置文件:
$ cd sddm_config
$ sudo cp * /etc/pam.d
配置桌面登陆
更新xorg
定义文件:
$ cd xorg_config
$ sudo mkdir -p /etc/X11/xorg.conf.d
$ sudo cp xorg.conf.d/20-intel.conf /etc/X11/xorg.conf.d
$ sudo cp seat* /etc/X11
$ sudo cp /bin/sed /usr/bin/sed
配置USB口与seat的映射关系(从已有的例子进行修改):
$ cd udev_config
$ vim 70-seat.rules
修改完毕后:
$ sudo cp 70-seat.rules /etc/udev/rules.d/70-seat.rules
开启multi-seat:
$ sudo vim /etc/default/grub
.....
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash startseat=true"
GRUB_CMDLINE_LINUX="startseat=true"
....
$ sudo update-grub2
建立两个用于登陆的用户:
$ sudo useradd -m seat1
$ sudo useradd -m seat2
$ sudo passwd seat1
$ sudo passwd seat2
配置sddm
为两个用户的自动登陆([AutoLogin]
内只保留如下所示部分):
# cat /etc/sddm.conf | more
[Autologin]
# Whether sddm should automatically log back into sessions when they exit
# Whether sddm should automatically log back into sessions when they exit
Relogin=false,false
SeatName=seat1,seat2
#Session=awesome,awesome
Session=xfce,xfce
User=seat1,seat2
....
此时重启后可以看到,双屏方案在登陆前自动进入到图形界面并已经实现分屏.