Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save shunf4/006e9611129f41a94e4da1e1c1949af3 to your computer and use it in GitHub Desktop.

Select an option

Save shunf4/006e9611129f41a94e4da1e1c1949af3 to your computer and use it in GitHub Desktop.
使用 Bliss OS 搭建带 Magisk 的 Android 9.0 调试环境

使用 Bliss OS 搭建带 Magisk 的 Android 9.0 调试环境

  • VirtualBox 建立机器,选择 Linux 2.6 / 3.x / 4.x 64-bit,CPU 核数、内存、磁盘、显存拉高,加载 Bliss OS 安装镜像,图像驱动器选 VBoxVGA,3D 加速不要勾选。可按需增加一个 Bridged Adapter 或者 Host-only Adapter,方便之后网络连接。

  • 使用 VBoxManager 命令行工具增加一个视频模式:

    VBoxManage setextradata "<虚拟机名称>" "CustomVideoMode1" "640x1080x32"
    

    640x1080x32 中分辨率可以自行设置,但最后的色彩位数一定要置为 32。

  • 安装过程同安装 Android x86 的过程,中间有几个点要注意的。

  • 启动后先进 debug mode

cd /mnt/grub
cp menu.lst menu.lst.bak
vi menu.lst
# 主启动项上加参数 vga=864,去掉 quiet。如 864 不对,加 vga=ask 后进系统确认下数字,再 16 进制转成 10 进制。
  • syncHost键 + R
  • 进系统后,安装必要软件(可连接 VirtWifi 后,通过 10.0.2.2 访问宿主机)。使用以下脚本传输 ADB 公钥到系统:(调出软键盘按 Alt+F1 可以进 root 命令行,Alt+F7 切回来)
#!/bin/sh

# receive-adb-key.sh

# 后续可将整个文件部署至 Magisk 的 service.d
# 再将 ip addr 的这句移至 post-fs-data.d
nohup sh -c 'while true; do if [ "$(getprop sys.boot_completed)" = "1" ]; then break ; fi ; sleep 2 ; done ; ip addr add 192.168.68.121/24 dev eth1;' > /dev/null &


THIS_SCRIPT_PATH="$(realpath "$0")"

if [ "$1" = "worker" ]; then
        exec 2>&1
        echo -e Please input content from file "\"adbkey.pub\":""\r" >&2
        echo -e ==================="\r" >&2
        read INPUT_ADB_KEY
        echo "$INPUT_ADB_KEY" >> /data/misc/adb/adb_keys
        chown system:shell /data/misc/adb/adb_keys
        chmod 0640 /data/misc/adb/adb_keys
        stop adbd
        setprop service.adb.tcp.port 5555
        setprop persist.adb.tcp.port 5555
        start adbd
        echo -e ==================="\r" >&2
        echo -e Done."\r" >&2
        exit
fi

stop adbd
setprop service.adb.tcp.port 5555
setprop persist.adb.tcp.port 5555
start adbd

while true; do
        busybox nc -l -p 15555 -e sh "$THIS_SCRIPT_PATH" worker
        sleep 1
done

  • 修改 Magisk。checkout 8aaa45c62(修改过版本号的 23.0,注意不要直接 checkout tag v23.0)
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 4c50bed2b..33999e6c4 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -27,7 +27,7 @@ android {
         vectorDrawables.useSupportLibrary = true
         versionName = Config.version
         versionCode = Config.versionCode
-        ndk.abiFilters("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
+        ndk.abiFilters("x86")
     }
 
     buildTypes {
@@ -100,10 +100,10 @@ val createStubLibs by tasks.registering {
     doLast {
         val arm64 = project.file("src/main/jniLibs/arm64-v8a/libstub.so")
         arm64.parentFile.mkdirs()
-        arm64.createNewFile()
+        // arm64.createNewFile()
         val x64 = project.file("src/main/jniLibs/x86_64/libstub.so")
         x64.parentFile.mkdirs()
-        x64.createNewFile()
+        // x64.createNewFile()
     }
 }
 
diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Const.kt b/app/src/main/java/com/topjohnwu/magisk/core/Const.kt
index 5ddb8c148..386f80e0a 100644
--- a/app/src/main/java/com/topjohnwu/magisk/core/Const.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/core/Const.kt
@@ -8,8 +8,8 @@ import java.io.File
 @Suppress("DEPRECATION")
 object Const {
 
-    val CPU_ABI: String = Build.SUPPORTED_ABIS[0]
-    val CPU_ABI_32: String = Build.SUPPORTED_32_BIT_ABIS.firstOrNull() ?: CPU_ABI
+    val CPU_ABI: String = "x86_64"
+    val CPU_ABI_32: String = "x86"
 
     // Paths
     lateinit var MAGISKTMP: String
diff --git a/native/jni/Application.mk b/native/jni/Application.mk
index e1d65f416..c4c214e17 100644
--- a/native/jni/Application.mk
+++ b/native/jni/Application.mk
@@ -12,7 +12,7 @@ endif
 
 # Build 64 bit binaries
 ifdef B_64BIT
-APP_ABI += arm64-v8a x86_64
+APP_ABI += arm64-v8a
 endif
 
 # Busybox should use stock libc.a
diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp
index 336a4b0ea..7f869c96d 100644
--- a/native/jni/core/bootstages.cpp
+++ b/native/jni/core/bootstages.cpp
@@ -3,6 +3,7 @@
 #include <sys/sysmacros.h>
 #include <linux/input.h>
 #include <libgen.h>
+#include <dirent.h>
 #include <vector>
 #include <string>
 
@@ -26,20 +27,49 @@ static bool safe_mode = false;
 #define MNT_DIR_IS(dir)   (me->mnt_dir == string_view(dir))
 #define SETMIR(b, part)   sprintf(b, "%s/" MIRRDIR "/" #part, MAGISKTMP.data())
 #define SETBLK(b, part)   sprintf(b, "%s/" BLOCKDIR "/" #part, MAGISKTMP.data())
+#define SETTMPBLK(b, part)   sprintf(b, "%s/tmpblk_" #part, MAGISKTMP.data())
+#define SETTMPMNT(b, part)   sprintf(b, "%s/tmpmnt_" #part, MAGISKTMP.data())
 
-#define do_mount_mirror(part, flag) {\
+#define do_mount_mirror(part, flag, is_loop) {\
     SETMIR(buf1, part); \
     SETBLK(buf2, part); \
     unlink(buf2); \
-    mknod(buf2, S_IFBLK | 0600, st.st_dev); \
+    if (is_loop) {\
+        SETTMPBLK(buf3, part); \
+        mknod(buf3, S_IFBLK | 0600, st.st_dev); \
+        tmp_dev_fd = open(buf3, O_RDWR); \
+        if (tmp_dev_fd < -1) { LOGE("%s tmp_dev_fd fail\n", buf1); return false; } \
+        loop_dev_fd = open("/dev/block/loop6", O_RDWR); \
+        if (loop_dev_fd < -1) { LOGE("%s loop_dev_fd fail\n", buf1); return false; } \
+        if (ioctl(loop_dev_fd, 0x4C00 /* LOOP_SET_FD */, tmp_dev_fd) < 0) { LOGE("%s ioctl fail\n", buf1); return false; } \
+        close(tmp_dev_fd); \
+        if (fstat(loop_dev_fd, &loop_st) < 0) { LOGE("%s fstat fail\n", buf1); return false; } \
+        close(loop_dev_fd); \
+        mknod(buf2, S_IFBLK | 0600, loop_st.st_rdev); \
+    } else { \
+        mknod(buf2, S_IFBLK | 0600, st.st_dev); \
+    } \
     xmkdir(buf1, 0755); \
-    xmount(buf2, buf1, me->mnt_type, flag, nullptr); \
+    if (flag & MS_BIND) { \
+        /* shunf4: for BlissOS's /data partition, we need to mount the subdirectory "/bliss-x86-11.13/data" of the block device, thus MS_BIND. */ \
+        SETTMPMNT(buf3, part); \
+        xmkdir(buf3, 0755); \
+        xmount(buf2, buf3, me->mnt_type, flag & ~MS_BIND, nullptr); \
+        tmp_data_root = opendir(buf3); \
+        if (!tmp_data_root) { LOGE("%s opendir fail\n", buf1); return false; } \
+        buf4[0] = '\0'; \
+        while ((tmp_data_dirent = readdir(tmp_data_root)) != NULL) { if (strncmp(tmp_data_dirent->d_name, "bliss-", 6) == 0) { sprintf(buf4, "%s/%s/data", buf3, tmp_data_dirent->d_name); break; } } \
+        closedir(tmp_data_root); \
+        if (buf4[0] == '\0') { LOGE("%s bliss dir not found\n", buf1); return false; } \
+        xmount(buf4, buf1, 0, MS_BIND, nullptr); \
+    } else \
+        xmount(buf2, buf1, me->mnt_type, flag, nullptr); \
     LOGI("mount: %s\n", buf1); \
 }
 
-#define mount_mirror(part, flag) \
+#define mount_mirror(part, flag, is_loop) \
 else if (MNT_DIR_IS("/" #part) && me->mnt_type != "tmpfs"sv && lstat(me->mnt_dir, &st) == 0) \
-    do_mount_mirror(part, flag)
+    do_mount_mirror(part, flag, is_loop)
 
 #define link_mirror(part) \
 SETMIR(buf1, part); \
@@ -61,17 +91,24 @@ else if (MNT_DIR_IS(dir) && me->mnt_type != "tmpfs"sv) { \
 static void mount_mirrors() {
     char buf1[4096];
     char buf2[4096];
+    char buf3[4096];
+    char buf4[4096];
+    int tmp_dev_fd;
+    int loop_dev_fd;
+    struct stat loop_st;
+    DIR* tmp_data_root;
+    struct dirent* tmp_data_dirent;
 
     LOGI("* Mounting mirrors\n");
 
     parse_mnt("/proc/mounts", [&](mntent *me) {
         struct stat st;
         if (0) {}
-        mount_mirror(system, MS_RDONLY)
-        mount_mirror(vendor, MS_RDONLY)
-        mount_mirror(product, MS_RDONLY)
-        mount_mirror(system_ext, MS_RDONLY)
-        mount_mirror(data, 0)
+        mount_mirror(system, MS_RDONLY, 1)
+        mount_mirror(vendor, MS_RDONLY, 0)
+        mount_mirror(product, MS_RDONLY, 0)
+        mount_mirror(system_ext, MS_RDONLY, 0)
+        mount_mirror(data, MS_BIND, 0)
         link_orig(cache)
         link_orig(metadata)
         link_orig(persist)
@@ -88,7 +125,7 @@ static void mount_mirrors() {
         parse_mnt("/proc/mounts", [&](mntent *me) {
             struct stat st;
             if (MNT_DIR_IS("/") && me->mnt_type != "rootfs"sv && stat("/", &st) == 0) {
-                do_mount_mirror(system_root, MS_RDONLY)
+                do_mount_mirror(system_root, MS_RDONLY, 0)
                 return false;
             }
             return true;

This is my build (Download and rename extension to .zip):

https://user-images.githubusercontent.com/20991618/147526309-be931ff0-744d-4169-8414-cc67f4c47210.gif

  • 安装修改版本后的 Magisk: https://web.archive.org/web/20210228102356/https://wiki.blissroms.org/index.php?title=Bliss_OS/Extras
    • 目前使用 Magisk 23.0 正式版,因为需要在隐藏 Root 的情况下 hook,因此 MagiskHide 必不可少。
    • 但 Magisk 23.0 的 APK 无法在 x86_64 下处理 boot.img(提示失败),因此在 Shell 下解包 Magisk 的 APK,手动调用 boot_patch.sh。 修改后的 Magisk 23.0 已经可以按原教程正常使用。
    • 重启后进 debug 模式部署三个文件,记得删掉两处的 su 二进制文件。没有 SuperUser APP, 无需删除。 多打几次 sync 总没坏处。
    • 将 /data/app/com.topj..../lib/arm 下的 lib*.so 文件全部换成 x86 版本。 修改后的 Magisk 无需这步。
    • 再重启到系统,进 Magisk,应提示已经安装,无任何错误。
    • 但切换到 log 标签页看不到日志,检查 /cache/magisk.log 发现启动时出现了 busybox 错误,原因是 /sbin/.magisk/busybox/busybox 链接到了 ARM 版本的 busybox。做 Snapshot 后替换,将 /data/adb/magisk/ 下有关二进制全部链向 x86 的版本,重启。 修改后的 Magisk 无需这步。
    • 现在可以启动 MagiskHide、隐藏 Magisk App、安装 receive-adb-key 服务、安装各种模块了。
  • 其他调整:
    • Settings - Display - Smallest width 改为 480dp,可以调整 DPI。
    • VBoxManage modifyvm "<VM Name>" --defaultfrontend headless
@LinusJun
Copy link

Bliss OS 使用的版本号能告知下否?谢谢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment