mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-15 22:13:24 +09:00
[Docs] (Anland): the desktop starts from the app and idles while hidden, with no manual bring-up
This commit is contained in:
@@ -18,12 +18,12 @@ nobody else is mid-test. Use your own `ct.sh` channel names (others use c, c2,
|
||||
## Architecture (10 lines)
|
||||
|
||||
1. Phone: Lenovo TB321FU (Y700, Adreno 750, Android 15, kernel 6.1), rooted with **KernelSU** (`/data/adb/ksu`, `ksud`; `su -c` works). USB serial `HA27Q3LQ`, or wireless adb `ip:port`.
|
||||
2. anland APK `com.anland.consumer.mobilegl` (debuggable build of anland branch `legacy-mobilegl-unified`): UI process + private service process `:mobilegl` (`MobileGLWorker`), which loads the **server** `libMobileGL.so` (NDK, from MobileGL `feat/disaggregated`) and listens on abstract socket `@anland-mobilegl`. One process serves every client (KWin, plasmashell, ksplash, Chrome...), one backend per process.
|
||||
3. Backend = `setprop debug.mobilegl.backend DirectGLES|DirectVulkan` (Espryt = DirectGLES, Magma = DirectVulkan; prop lost on reboot) and must equal the container's `/etc/mobilegl/backend` (what every client reports; mismatch = "Hello.backendType disagrees with pinned backend").
|
||||
4. Experiment display daemon `/data/adb/modules/anland-daemon/display_daemon /data/local/tmp/anland-mobilegl/display.sock` (display/input broker; NOT started at boot - the module only starts the original one on `/data/local/tmp/display_daemon.sock`, leave that alone).
|
||||
2. anland APK `com.anland.consumer.mobilegl` (debuggable build of anland branch `legacy-mobilegl-unified`): UI process + private service process `:mobilegl` (`MobileGLWorker`), which loads the **server** `libMobileGL.so` (NDK, from MobileGL `feat/disaggregated`) and listens on abstract socket `@anland-mobilegl` from the first attached window on. One process serves every client (KWin, plasmashell, ksplash, Chrome...), one backend per process. `MobileGLWorker` is a **foreground service** (notification "Linux desktop is running" / action "Stop desktop"), so the server and the session outlive a hidden, locked or swiped-away window.
|
||||
3. Backend = the app setting "Renderer backend" (Settings > Connection > MobileGL desktop; file `/data/data/<pkg>/files/mobilegl-backend`, default DirectGLES; also `am start ... --es mobilegl_backend X`). Espryt = DirectGLES, Magma = DirectVulkan. The server reads it when its process starts; the app publishes it as `/data/local/tmp/anland-mobilegl/backend` and the session copies that into the container's `/etc/mobilegl/backend` (what every client reports; mismatch = "Hello.backendType disagrees with pinned backend"). `debug.mobilegl.backend`, if someone sets it, still overrides the setting until the next reboot.
|
||||
4. Experiment display daemon `/data/adb/modules/anland-daemon/display_daemon /data/local/tmp/anland-mobilegl/display.sock` (display/input broker), started by the app (below). The module only starts the original one on `/data/local/tmp/display_daemon.sock` at boot; leave that alone.
|
||||
5. Container `arch-kde-mgl` (Droidspaces 6.4.5, Arch Linux ARM aarch64 glibc, host net, `rootfs.img` mounted at `/mnt/Droidspaces/arch-kde-mgl` on the Android side). Bind mounts: `/data/local/tmp/anland-mobilegl` -> `/run/anland-mobilegl`, `/data/local/tmp/display_daemon.sock` -> `/run/display.sock`.
|
||||
6. `desktop-session.service` (User=swung0x48) has drop-in `ExecStart=/opt/mobilegl/bin/mobilegl-startup.sh plasma`, which writes a user drop-in for `plasma-kwin_wayland.service` (kwin_wayland_wrapper -> `/opt/mobilegl/kwin/bin/kwin_wayland` + `/opt/mobilegl/kwin/lib/libkwin.so.6.7.4`, `ANLAND_MOBILEGL=1`, `MOBILEGL_IPC_SURFACE=server`) and runs `startplasma-wayland`.
|
||||
7. KWin 6.7.4 with anland's `anland` backend renders straight into the anland Android Surface through the server. Every other GL process is `MOBILEGL_IPC_SURFACE=offscreen` and presents through KWin.
|
||||
6. `desktop-session.service` (User=swung0x48, **enabled**: the container boots straight into it, as the original image does) has drop-in `/etc/systemd/system/desktop-session.service.d/mobilegl.conf` (anland `producers/kde/Arch_v5/desktop-session-mobilegl.conf`, installed + enabled by `sync-build-kwin.sh`): `ExecStartPre=mobilegl-startup.sh wait` (until `@anland-mobilegl` listens in `/proc/net/unix` and the daemon socket exists), `ExecStartPre=+... sync-backend`, `Restart=always`, then `ExecStart=/opt/mobilegl/bin/mobilegl-startup.sh plasma`, which deletes the sticky software-renderer key, sets `MOBILEGL_IPC_PROBE_TIMEOUT_MS=0` session-wide (MobileGL never declines, so glvnd never falls through to another GL stack), writes a user drop-in for `plasma-kwin_wayland.service` (kwin_wayland_wrapper -> `/opt/mobilegl/kwin/bin/kwin_wayland` + `/opt/mobilegl/kwin/lib/libkwin.so.6.7.4`, `ANLAND_MOBILEGL=1`, `MOBILEGL_IPC_SURFACE=server`) and runs `startplasma-wayland`.
|
||||
7. KWin 6.7.4 with anland's `anland` backend renders straight into the anland Android Surface through the server. While the window is not on screen (consumer disconnected) the backend powers its output down (DPMS Off + RenderLoop inhibited: no compositing, no frame callbacks) and back up when the window returns. Every other GL process is `MOBILEGL_IPC_SURFACE=offscreen` and presents through KWin.
|
||||
8. Client = `/opt/mobilegl/lib/libMobileGL.so` (glibc aarch64), the container's **system-wide** GL vendor (section below): glvnd EGL vendor `/usr/share/glvnd/egl_vendor.d/10_mobilegl.json` (sorts before the distribution's `50_*.json`, which serves whenever MobileGL declines), GLX vendor `/usr/lib/libGLX_mobilegl.so.0`, settings from `/etc/mobilegl/client.conf` (`MOBILEGL_TRANSPORT=spawn MOBILEGL_IPC_DATA=shm MOBILEGL_IPC_CONTROL=unix:@anland-mobilegl`) + `/etc/mobilegl/backend`. No per-process environment is needed.
|
||||
9. Zero-copy windows: client `wl_egl_window` frames are server-allocated AHardwareBuffer "shared images" exported as dma-buf fds over `zwp_linux_dmabuf_v1`; KWin imports them with EGL and the server recognises its own buffer by inode. KWin gets a DRM device via `GBM_BACKEND=mobilegl` -> `/usr/lib/gbm/mobilegl_gbm.so` (node is only an identity, never ioctl'd). Without linux-dmabuf the client falls back to wl_shm readback.
|
||||
10. X11 apps (Xwayland) use the MobileGL GLX vendor with per-frame readback + `xcb_put_image`. Chrome runs ANGLE-GLES over MobileGL EGL with the GPU in-process (`mobilegl-startup.sh chrome`).
|
||||
@@ -40,23 +40,21 @@ nobody else is mid-test. Use your own `ct.sh` channel names (others use c, c2,
|
||||
|
||||
Run host scripts from Git Bash as `bash scripts/<x>.sh`. Raw adb with device paths needs `MSYS_NO_PATHCONV=1` and the whole root command in one quoted string: `adb shell 'su -c "..."'`. A device script can also be run without pushing: `MSYS_NO_PATHCONV=1 adb shell 'su -c sh' < scripts/device/status.sh`.
|
||||
|
||||
## Bring-up after a phone reboot
|
||||
## Starting, idling, stopping - no manual steps
|
||||
|
||||
Nothing of the session survives a reboot. Either `adb shell 'su -c "sh /data/local/tmp/anl/bringup.sh [DirectGLES|DirectVulkan]"'`, or by hand, in this order:
|
||||
Nothing starts at phone boot (container `run_at_boot=0`). **Opening the app** (launcher icon = `am start -n com.anland.consumer.mobilegl/com.anland.consumer.MainActivity`, no extras; the APK's default socket is the experiment's, `-PanlandDefaultSocket`) calls `MobileGLDesktop.ensureStarted()` - the single trigger - which starts the foreground service and runs the APK's `assets/mobilegl-desktop.sh up` as root (`su`): display daemon if absent (the script leaves the app's cgroup first, so it survives the app) -> backend published -> container started if stopped -> `systemctl start --no-block desktop-session`. The window waits for the daemon socket; the server listens once the Surface is attached; the session's `wait` step then lets Plasma start. A reopen with everything up only reattaches the window. Log: `/data/local/tmp/anland-mobilegl/desktop.log`, logcat `AnlandMobileGL` ("MobileGL desktop up done in N ms").
|
||||
|
||||
Hidden window, screen off, lock screen or swiped-away task: server and session stay (foreground service); KWin logs "viewer gone: output powered down" and idles, "viewer back" on return. **Stop desktop** (notification action, or `am startservice -n <pkg>/com.anland.consumer.MobileGLWorker -a com.anland.consumer.mobilegl.STOP`) runs `mobilegl-desktop.sh down` (session + container stopped, daemon stays), closes the windows, ends `:mobilegl`.
|
||||
|
||||
```sh
|
||||
adb connect <ip>:<port> # only for wireless debugging (e.g. USB cannot power it)
|
||||
adb connect <ip>:<port> # only for wireless debugging
|
||||
export MSYS_NO_PATHCONV=1
|
||||
adb shell 'su -c "svc power stayon true"'
|
||||
adb shell 'su -c "setprop debug.mobilegl.backend DirectVulkan"' # or DirectGLES; match /etc/mobilegl/backend
|
||||
adb shell 'su -c "am start -n com.anland.consumer.mobilegl/com.anland.consumer.MainActivity --es socket_path /data/local/tmp/anland-mobilegl/display.sock"'
|
||||
adb shell 'su -c "/data/local/Droidspaces/bin/droidspaces -C /data/local/Droidspaces/Containers/arch-kde-mgl/container.config start"'
|
||||
adb shell 'su -c "sh /data/local/tmp/anl/restart-daemon.sh"' # experiment display daemon, chmod 777 dir / 666 socket
|
||||
adb shell 'su -c "sh /data/local/tmp/anl/run-plasma.sh"' # restarts app + desktop-session, ~90 s
|
||||
adb shell 'su -c "sh /data/local/tmp/anl/bringup.sh"' # after a reboot: wake, dismiss keyguard, open the app, print the timeline
|
||||
bash scripts/desktop-verify.sh push cold reopen idle # timed cold start, swipe-away + reopen, CPU/GPU visible/hidden/locked
|
||||
adb shell 'su -c "sh /data/local/tmp/anl/status.sh"'
|
||||
```
|
||||
|
||||
`droidspaces` has no `status` command; `droidspaces show` lists running containers. Do not use the old
|
||||
`/data/local/tmp/restart-daemon.sh` (it kills a hard-coded PID). Check with `device/status.sh`.
|
||||
`droidspaces` has no `status` command; `droidspaces show` lists running containers. `device/run-plasma.sh` is a developer restart (session + logind user, then the app), needed after a rebuild because KWin does not reconnect to a new server process. `device/desktop-reset.sh` takes everything down to the post-reboot state. The old manual sequence (setprop, start container, `restart-daemon.sh`, `run-plasma.sh`) is gone; `restart-daemon.sh` remains for daemon debugging only.
|
||||
|
||||
## Build and deploy loops
|
||||
|
||||
@@ -91,7 +89,7 @@ MSYS2_ARG_CONV_EXCL='*' wsl -d archlinux -- bash -lc 'cd ~/mgl-anl-bld && ctest
|
||||
|
||||
## Switching backends
|
||||
|
||||
`adb shell 'su -c "sh /data/local/tmp/anl/switch.sh DirectGLES"'` (sets the prop, writes `/etc/mobilegl/backend`, restarts the app), then `run-plasma.sh` - the running session's clients are pinned to the old backend. `cyc.sh` keeps whatever is set.
|
||||
In the app: Settings > Connection > MobileGL desktop > Renderer backend, then Stop desktop and open the app. Or `adb shell 'su -c "sh /data/local/tmp/anl/switch.sh DirectGLES"'`, which does the same (saves the setting through the launch extra, STOPs the service, reopens; clears a stale `debug.mobilegl.backend`). No setprop, no file to edit in the container: the session copies the published backend into `/etc/mobilegl/backend` on its next start. `cyc.sh` keeps whatever is set.
|
||||
|
||||
## System-wide vendor and fallback
|
||||
|
||||
@@ -102,7 +100,7 @@ Installed by `xdeploy.sh` (and anland's `anland-build-client.sh`), so any proces
|
||||
| `/usr/share/glvnd/egl_vendor.d/10_mobilegl.json` | EGL vendor, asked before the system's `50_*.json` |
|
||||
| `/opt/mobilegl/share/glvnd/egl_vendor.d/50_mobilegl.json` | same JSON, for per-process forcing with `__EGL_VENDOR_LIBRARY_FILENAMES` |
|
||||
| `/etc/mobilegl/client.conf` | `KEY=value` defaults for every client (transport, data, endpoint); rewritten on deploy |
|
||||
| `/etc/mobilegl/backend` | the backend (`switch.sh` writes it); wins over a `MOBILEGL_BACKEND_TYPE` line in client.conf |
|
||||
| `/etc/mobilegl/backend` | the backend (the session's `sync-backend` step copies the app's choice in); wins over a `MOBILEGL_BACKEND_TYPE` line in client.conf |
|
||||
| `/etc/environment.d/10-mobilegl.conf` | `__GLX_VENDOR_LIBRARY_NAME=mobilegl`, `GBM_BACKEND=mobilegl` for the systemd user manager (all Plasma services and what they start, terminals included) |
|
||||
| `/etc/profile.d/mobilegl.sh` | the same two for login shells (`bash -l`, `su -l`, ssh, `droidspaces run bash -l`) |
|
||||
|
||||
@@ -144,6 +142,8 @@ Reference (glmark2-es2-wayland 1280x720, zero-copy vs wl_shm): Espryt 187 vs 49,
|
||||
| Native crashes | `adb logcat -b crash -d`; container `coredumpctl list` |
|
||||
| Session / KWin stderr | container `journalctl -u desktop-session --no-pager`, `journalctl --no-pager --since -2min \| grep kwin_wayland` |
|
||||
| Display daemon | `/data/local/tmp/anland-mobilegl/display-daemon.log` |
|
||||
| Desktop start/stop (app's su script) | `/data/local/tmp/anland-mobilegl/desktop.log`, `container-start.log`; logcat `-s AnlandMobileGL` |
|
||||
| Session wait / backend sync | container `journalctl -u desktop-session --no-pager` ("waiting for the MobileGL server ...") |
|
||||
|
||||
`MOBILEGL_LOG_FILE_PATH=/tmp/x.log` produces `/tmp/x.client.log` (and `.server.log` for forwarded lines); files are truncated on open, so one base per process. Client builds log at INFO. Symbolize server frames with `$ANDROID_NDK/toolchains/llvm/prebuilt/windows-x86_64/bin/llvm-addr2line.exe -Cfe build-android/libMobileGL.so <offset>`.
|
||||
|
||||
@@ -151,10 +151,10 @@ Reference (glmark2-es2-wayland 1280x720, zero-copy vs wl_shm): Espryt 187 vs 49,
|
||||
|
||||
- **pkill -f self-match**: a `ct.sh`/`droidspaces run bash -lc "<script>"` process carries the script in its argv; `pkill -f chrome` kills the runner. Use `pkill -x`.
|
||||
- **Root-owned /tmp files**: a log created by a root-run client cannot be reopened by swung0x48 later (no log appears). `rm -f` it as root first.
|
||||
- **Sticky Plasma software renderer**: after any server crash Plasma writes `[QtQuickRendererSettings] SceneGraphBackend=software` into `~swung0x48/.config/kdeglobals`; plasmashell then renders on the CPU and screenshots still look fine (tray icon "正在使用的软件渲染器"). Delete before any verdict: `sudo -u swung0x48 kwriteconfig6 --file kdeglobals --group QtQuickRendererSettings --key SceneGraphBackend --delete` (cyc.sh does it), restart the session.
|
||||
- **Sticky Plasma software renderer**: after any server crash Plasma writes `[QtQuickRendererSettings] SceneGraphBackend=software` into `~swung0x48/.config/kdeglobals`; plasmashell then renders on the CPU and screenshots still look fine (tray icon "正在使用的软件渲染器"). `mobilegl-startup.sh plasma` deletes it at every session start; within a running session that hit a crash, restart the session (`run-plasma.sh`) before any verdict.
|
||||
- **Lock screen**: autolock is off (`kscreenlockerrc [Daemon] Autolock=false`); a real lock can only be left by typing the password (logind lock/unlock is not supported for this session type - `device/unlock.sh` is unverified). Test the greeter with `/usr/lib/kscreenlocker_greet --testing` and kill it.
|
||||
- **CRLF**: `core.autocrlf=true` here; anland's backend sources and `sync-build-kwin.sh` are CRLF in the Windows checkout. Strip CR before anything runs on Linux/Android (`tr -d '\r'`; `ct.sh`, `push-tools.sh`, `kwin-stage.sh` do). This skill has a `.gitattributes` forcing LF.
|
||||
- **Display daemon not auto-started** after reboot: KWin logs "failed to connect to display daemon at /run/anland-mobilegl/display.sock" and the session exits in ~3 s.
|
||||
- **Display daemon**: the app starts it; the session's `wait` step keeps KWin from starting without it (a KWin that cannot reach it logs "failed to connect to display daemon at /run/anland-mobilegl/display.sock" and exits in ~3 s). Anything started from the app's `su` must leave the app's cgroup (`echo $$ > /sys/fs/cgroup/cgroup.procs`) or a force-stop kills it.
|
||||
- **Device power/connection**: low battery or the screen turning off (30 s default) can kill the SurfaceView - `svc power stayon true`; wireless adb `ip:port` changes per pairing - never pin `-s HA27Q3LQ`, use `ANDROID_SERIAL` if several devices are attached.
|
||||
- **Container vs phone paths**: container `/tmp` is a different place from the phone's `/data/local/tmp`; move files via `/mnt/Droidspaces/arch-kde-mgl/root` (container `/root`) or `/data/local/tmp/anland-mobilegl` (= container `/run/anland-mobilegl`).
|
||||
- **Never overwrite a mapped .so in place** (container or APK while running): copy to a new inode and `mv -f`; the APK swap force-stops the app first.
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env bash
|
||||
# desktop-verify.sh <phase>... - check that the MobileGL desktop starts, idles and stops by itself
|
||||
# (anland app: foreground service + mobilegl-desktop.sh; container: desktop-session.service).
|
||||
# Phases run in the order given; screenshots go to $ANL_DIR/dv-<phase>.png.
|
||||
#
|
||||
# push install device/*.sh into $DEV_TOOLS (push-tools.sh's device half)
|
||||
# reset everything down: app force-stopped (its service with it), container stopped,
|
||||
# experiment display daemon killed - the state after a phone reboot
|
||||
# cold reset, then open the app like its icon does and time each piece (desktop-timeline.sh)
|
||||
# open open the app without resetting (after a reboot: the reboot was the reset)
|
||||
# chrome (re)start Chrome in the session on an animated WebGL page (kills a running Chrome)
|
||||
# idle CPU/GPU for visible, hidden (HOME), locked (screen off), visible again (measure.sh)
|
||||
# reopen swipe the app away (remove its task), check KWin survives, open it again, time it
|
||||
# stop Stop desktop from the notification (the service's STOP action) and check it all ends
|
||||
# rtest lock/unlock + window resize regression ($ANL_DIR/rtest.sh)
|
||||
# Env: SECS (idle window, default 20), URL (chrome page).
|
||||
set -euo pipefail
|
||||
here=$(cd "$(dirname "$0")" && pwd)
|
||||
. "$here/env.sh"
|
||||
SECS=${SECS:-20}
|
||||
URL=${URL:-https://webglsamples.org/aquarium/aquarium.html}
|
||||
SOCK=$DEV_SHARE/display.sock
|
||||
su_() { adb_ shell "su -c '$*'"; }
|
||||
shot() {
|
||||
su_ "screencap -p $DEV_SHARE/dv-$1.png"
|
||||
adb_ pull "$DEV_SHARE/dv-$1.png" "$ANL_DIR/dv-$1.png" > /dev/null && echo "screenshot $ANL_DIR/dv-$1.png"
|
||||
}
|
||||
kwin_log() { # the anland backend's lines since <time>
|
||||
printf '%s\n' "journalctl --no-pager --since '$1' 2>/dev/null | grep -a -E 'viewer (gone|back)|consumer (reconnected|disconnected)|failed to connect' | tail -${2:-8}" |
|
||||
bash "$here/ct.sh" dv 2>/dev/null | grep -v pushed || true
|
||||
}
|
||||
task_id() {
|
||||
su_ "am stack list" | tr -d '\r' | grep -m1 "$MGL_PKG/" | sed -n 's/.*taskId=\([0-9]*\).*/\1/p'
|
||||
}
|
||||
wake() {
|
||||
su_ "input keyevent KEYCODE_WAKEUP"; sleep 1; su_ "wm dismiss-keyguard"; sleep 2
|
||||
}
|
||||
|
||||
for phase in "$@"; do
|
||||
echo "=== $phase"
|
||||
case $phase in
|
||||
push)
|
||||
for f in "$here"/device/*.sh; do
|
||||
tr -d '\r' < "$f" > "$ANL_DIR/push.tmp"
|
||||
adb_ push "$ANL_DIR/push.tmp" "$DEV_TOOLS/$(basename "$f")" > /dev/null
|
||||
done
|
||||
rm -f "$ANL_DIR/push.tmp"; echo "device scripts in $DEV_TOOLS" ;;
|
||||
reset)
|
||||
su_ "sh $DEV_TOOLS/desktop-reset.sh" ;;
|
||||
cold)
|
||||
bash "$0" reset
|
||||
wake
|
||||
su_ "sh $DEV_TOOLS/desktop-timeline.sh 240"
|
||||
sleep 3; shot cold ;;
|
||||
open)
|
||||
wake
|
||||
su_ "sh $DEV_TOOLS/desktop-timeline.sh 300"
|
||||
sleep 3; shot open ;;
|
||||
chrome)
|
||||
WAIT=15 bash "$here/chrome-launch.sh" dv "$URL" ;;
|
||||
idle)
|
||||
su_ "sh $DEV_TOOLS/measure.sh visible $SECS"
|
||||
t=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
||||
su_ "input keyevent KEYCODE_HOME"; sleep 4
|
||||
su_ "sh $DEV_TOOLS/measure.sh hidden $SECS"
|
||||
su_ "am start -n $MGL_PKG/com.anland.consumer.MainActivity >/dev/null"; sleep 5
|
||||
su_ "input keyevent KEYCODE_SLEEP"; sleep 4
|
||||
su_ "sh $DEV_TOOLS/measure.sh locked $SECS"
|
||||
wake
|
||||
su_ "am start -n $MGL_PKG/com.anland.consumer.MainActivity >/dev/null"; sleep 5
|
||||
su_ "sh $DEV_TOOLS/measure.sh visible2 $SECS"
|
||||
shot idle
|
||||
kwin_log "$t" 12 ;;
|
||||
reopen)
|
||||
t=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
||||
id=$(task_id); echo "removing task $id"
|
||||
[ -n "$id" ] && su_ "am stack remove $id"
|
||||
sleep 8
|
||||
su_ "echo server: \$(pidof $MGL_PKG:mobilegl) ui: \$(pidof $MGL_PKG) kwin: \$(pidof kwin_wayland) plasmashell: \$(pidof plasmashell)"
|
||||
su_ "sh $DEV_TOOLS/measure.sh closed 10"
|
||||
su_ "sh $DEV_TOOLS/desktop-timeline.sh 120"
|
||||
sleep 3; shot reopen
|
||||
kwin_log "$t" ;;
|
||||
stop)
|
||||
su_ "am startservice -n $MGL_PKG/com.anland.consumer.MobileGLWorker -a com.anland.consumer.mobilegl.STOP" || true
|
||||
sleep 25
|
||||
su_ "echo server: \$(pidof $MGL_PKG:mobilegl) ui: \$(pidof $MGL_PKG); $DS_BIN show"
|
||||
su_ "tail -3 $DEV_SHARE/desktop.log" ;;
|
||||
rtest)
|
||||
bash "$ANL_DIR/rtest.sh" dv ;;
|
||||
*)
|
||||
echo "unknown phase $phase" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
@@ -1,29 +1,7 @@
|
||||
# bringup.sh [DirectGLES|DirectVulkan] - (Android root shell) bring the stack up after a phone reboot:
|
||||
# stay-awake, container, backend property, experiment display daemon, anland app, then the Plasma
|
||||
# session (run-plasma.sh, ~90 s; skip with NO_PLASMA=1). The backend defaults to the container's
|
||||
# /etc/mobilegl/backend (persists across reboots; the property does not).
|
||||
# Assembled from the documented manual steps; not exercised as one unit yet. Re-running restarts the
|
||||
# daemon, the app and the session. Run: su -c "sh /data/local/tmp/anl/bringup.sh"
|
||||
# Env: PKG, CONTAINER, DS, SOCK, TOOLS (dir holding run-plasma.sh / restart-daemon.sh; default: this dir).
|
||||
D=${DS:-/data/local/Droidspaces/bin/droidspaces}
|
||||
P=${PKG:-com.anland.consumer.mobilegl}
|
||||
C=${CONTAINER:-arch-kde-mgl}
|
||||
SOCK=${SOCK:-/data/local/tmp/anland-mobilegl/display.sock}
|
||||
T=${TOOLS:-$(dirname $0)}
|
||||
svc power stayon true
|
||||
if $D show 2>/dev/null | grep -q " $C "; then
|
||||
echo "container $C already running"
|
||||
else
|
||||
$D -C /data/local/Droidspaces/Containers/$C/container.config start
|
||||
sleep 5
|
||||
fi
|
||||
B=${1:-$(cat /mnt/Droidspaces/$C/etc/mobilegl/backend 2>/dev/null)}
|
||||
B=${B:-DirectGLES}
|
||||
setprop debug.mobilegl.backend $B
|
||||
echo "$B" > /mnt/Droidspaces/$C/etc/mobilegl/backend
|
||||
echo "backend: $(getprop debug.mobilegl.backend)"
|
||||
sh $T/restart-daemon.sh
|
||||
am start -n $P/com.anland.consumer.MainActivity --es socket_path $SOCK >/dev/null
|
||||
sleep 3
|
||||
if pidof $P:mobilegl >/dev/null; then echo "server process $P:mobilegl up"; else echo "WARNING: $P:mobilegl not running"; fi
|
||||
[ "${NO_PLASMA:-0}" = 1 ] || sh $T/run-plasma.sh
|
||||
# bringup.sh - (Android root shell) bring the MobileGL desktop up after a phone reboot. There is
|
||||
# nothing left to do by hand: opening the anland app (its launcher icon, or this am start) starts
|
||||
# the display daemon, the MobileGL server, the container and its Plasma session. Prints the timeline.
|
||||
# Run: su -c "sh /data/local/tmp/anl/bringup.sh" Env: as desktop-timeline.sh.
|
||||
input keyevent KEYCODE_WAKEUP
|
||||
wm dismiss-keyguard
|
||||
sh "$(dirname "$0")/desktop-timeline.sh" 300
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# desktop-reset.sh - (Android root shell) take the MobileGL desktop fully down, as after a phone
|
||||
# reboot: the app force-stopped (its foreground service and server with it), the container
|
||||
# stopped, the experiment display daemon killed. Leaves the original anland daemon alone.
|
||||
# Run: su -c "sh /data/local/tmp/anl/desktop-reset.sh" Env: PKG, CONTAINER, SOCK, DS.
|
||||
P=${PKG:-com.anland.consumer.mobilegl}
|
||||
C=${CONTAINER:-arch-kde-mgl}
|
||||
SOCK=${SOCK:-/data/local/tmp/anland-mobilegl/display.sock}
|
||||
D=${DS:-/data/local/Droidspaces/bin/droidspaces}
|
||||
am force-stop $P
|
||||
$D --name=$C stop > /dev/null 2>&1
|
||||
for p in $(pidof display_daemon); do
|
||||
tr '\0' ' ' < /proc/$p/cmdline | grep -qF " $SOCK " && kill $p
|
||||
done
|
||||
rm -f $SOCK
|
||||
sleep 2
|
||||
echo "app: $(pidof $P) server: $(pidof $P:mobilegl) daemon: $(ls $SOCK 2>/dev/null)"
|
||||
$D show
|
||||
@@ -0,0 +1,30 @@
|
||||
# desktop-timeline.sh [timeout-s] - (Android root shell) open the anland app the way its launcher
|
||||
# icon does (am start, no extras) and print when each piece of the MobileGL desktop comes up,
|
||||
# in seconds after the open: display daemon socket, the app's MobileGL server listening, the
|
||||
# container, kwin_wayland, plasmashell, and the splash (ksplashqml) gone = desktop on screen.
|
||||
# Pieces that already run show 0.0. Read-only apart from the am start.
|
||||
# Run: su -c "sh /data/local/tmp/anl/desktop-timeline.sh 180" Env: PKG, CONTAINER, SOCK, DS.
|
||||
T=${1:-180}
|
||||
P=${PKG:-com.anland.consumer.mobilegl}
|
||||
C=${CONTAINER:-arch-kde-mgl}
|
||||
SOCK=${SOCK:-/data/local/tmp/anland-mobilegl/display.sock}
|
||||
D=${DS:-/data/local/Droidspaces/bin/droidspaces}
|
||||
now() { awk '{print $1}' /proc/uptime; }
|
||||
since() { awk -v a="$1" -v b="$(now)" 'BEGIN{printf "%.1f", b - a}'; }
|
||||
listening() { grep -q '00010000 0001 01 [0-9]* @anland-mobilegl$' /proc/net/unix; }
|
||||
t0=$(now)
|
||||
am start -n $P/com.anland.consumer.MainActivity > /dev/null
|
||||
for k in daemon server container kwin shell splash_seen shown; do eval "t_$k="; done
|
||||
while :; do
|
||||
[ -z "$t_daemon" ] && [ -S "$SOCK" ] && t_daemon=$(since $t0) && echo "daemon socket +${t_daemon}s"
|
||||
[ -z "$t_server" ] && listening && t_server=$(since $t0) && echo "server listening +${t_server}s"
|
||||
[ -z "$t_container" ] && [ -n "$($D --name=$C pid 2>/dev/null | tr -dc 0-9)" ] && t_container=$(since $t0) && echo "container up +${t_container}s"
|
||||
[ -z "$t_kwin" ] && pidof kwin_wayland > /dev/null && t_kwin=$(since $t0) && echo "kwin_wayland +${t_kwin}s"
|
||||
[ -z "$t_shell" ] && pidof plasmashell > /dev/null && t_shell=$(since $t0) && echo "plasmashell +${t_shell}s"
|
||||
[ -z "$t_splash_seen" ] && pidof ksplashqml > /dev/null && t_splash_seen=1
|
||||
if [ -n "$t_shell" ] && [ -z "$t_shown" ] && ! pidof ksplashqml > /dev/null; then
|
||||
t_shown=$(since $t0); echo "splash gone +${t_shown}s (desktop on screen)"; break
|
||||
fi
|
||||
[ "$(since $t0 | cut -d. -f1)" -ge "$T" ] && { echo "TIMEOUT after ${T}s"; break; }
|
||||
sleep 0.3
|
||||
done
|
||||
@@ -0,0 +1,47 @@
|
||||
# measure.sh <label> [seconds] - (Android root shell) CPU and GPU load of the MobileGL desktop over a
|
||||
# window: % of ONE core (so 800 = all 8 cores) for the whole phone, KWin (+Xwayland), plasmashell,
|
||||
# Chrome (all its processes), the app's :mobilegl server and its UI process, plus the mean of the
|
||||
# kgsl gpu_busy_percentage samples (1/s). The container's processes are visible from Android's
|
||||
# /proc (Droidspaces only gives them their own pid namespace).
|
||||
# Run: su -c "sh /data/local/tmp/anl/measure.sh visible 20" Env: PKG.
|
||||
L=${1:-sample}
|
||||
N=${2:-20}
|
||||
P=${PKG:-com.anland.consumer.mobilegl}
|
||||
GPU=/sys/class/kgsl/kgsl-3d0/gpu_busy_percentage
|
||||
|
||||
pids_named() { # exact process names (comm or argv0 basename)
|
||||
for n in "$@"; do pidof "$n"; done
|
||||
}
|
||||
pids_matching() { # argv contains the word
|
||||
for d in /proc/[0-9]*; do
|
||||
{ tr '\0' ' ' < $d/cmdline; } 2>/dev/null | grep -q "$1" && echo ${d#/proc/}
|
||||
done
|
||||
}
|
||||
ticks() { # utime+stime of the pids, in clock ticks
|
||||
t=0
|
||||
for p in "$@"; do
|
||||
[ -r /proc/$p/stat ] || continue
|
||||
v=$(sed 's/^.*) //' /proc/$p/stat | awk '{print $12 + $13}')
|
||||
t=$((t + v))
|
||||
done
|
||||
echo $t
|
||||
}
|
||||
total() { awk '/^cpu /{print $2+$3+$4+$6+$7+$8}' /proc/stat; }
|
||||
|
||||
KW="$(pids_named kwin_wayland Xwayland)"
|
||||
SH="$(pids_named plasmashell)"
|
||||
CH="$(pids_matching /opt/google/chrome/)"
|
||||
SV="$(pidof $P:mobilegl)"
|
||||
UI="$(pidof $P)"
|
||||
|
||||
a0=$(total); k0=$(ticks $KW); s0=$(ticks $SH); c0=$(ticks $CH); v0=$(ticks $SV); u0=$(ticks $UI)
|
||||
g=0; i=0
|
||||
while [ $i -lt $N ]; do
|
||||
sleep 1
|
||||
b=$(cat $GPU 2>/dev/null | tr -dc '0-9'); g=$((g + ${b:-0})); i=$((i + 1))
|
||||
done
|
||||
a1=$(total); k1=$(ticks $KW); s1=$(ticks $SH); c1=$(ticks $CH); v1=$(ticks $SV); u1=$(ticks $UI)
|
||||
# CLK_TCK is 100: ticks per second == percent of one core.
|
||||
pct() { echo $(( ($2 - $1) / N )); }
|
||||
printf '%-10s %3ss phone %4s%% kwin %3s%% plasmashell %3s%% chrome %3s%% server %3s%% app-ui %3s%% gpu %3s%%\n' \
|
||||
"$L" "$N" "$(pct $a0 $a1)" "$(pct $k0 $k1)" "$(pct $s0 $s1)" "$(pct $c0 $c1)" "$(pct $v0 $v1)" "$(pct $u0 $u1)" "$((g / N))"
|
||||
@@ -1,24 +1,25 @@
|
||||
# run-plasma.sh - (Android root shell) restart the anland app and the container's Plasma session
|
||||
# (desktop-session.service -> mobilegl-startup.sh plasma). Takes ~90 s (two 40 s waits: logind must
|
||||
# finish tearing the old user session down before the new one starts). Prints the unit status, the
|
||||
# plasma user units and recent coredumps. Run: su -c "sh /data/local/tmp/anl/run-plasma.sh"
|
||||
# Env: PKG, CONTAINER, DESKTOP_USER (swung0x48), SOCK, DS (droidspaces binary).
|
||||
# run-plasma.sh - (Android root shell) DEVELOPER restart of the whole MobileGL desktop, e.g. after a
|
||||
# server, client or KWin rebuild: ends the Plasma session (and the user's logind session, which takes
|
||||
# a while to wind down), then restarts the anland app; opening it brings up the server, starts
|
||||
# desktop-session.service again and the session waits for the server. Normal use needs none of this:
|
||||
# opening the app is enough. ~60 s. Prints the unit status, plasma user units and recent coredumps.
|
||||
# Run: su -c "sh /data/local/tmp/anl/run-plasma.sh"
|
||||
# Env: PKG, CONTAINER, DESKTOP_USER (swung0x48), DS (droidspaces binary).
|
||||
D=${DS:-/data/local/Droidspaces/bin/droidspaces}
|
||||
P=${PKG:-com.anland.consumer.mobilegl}
|
||||
C=${CONTAINER:-arch-kde-mgl}
|
||||
U=${DESKTOP_USER:-swung0x48}
|
||||
SOCK=${SOCK:-/data/local/tmp/anland-mobilegl/display.sock}
|
||||
am force-stop $P
|
||||
am start -n $P/com.anland.consumer.MainActivity --es socket_path $SOCK >/dev/null
|
||||
sleep 3
|
||||
$D --name=$C run bash -lc "
|
||||
systemctl stop desktop-session.service 2>/dev/null
|
||||
loginctl terminate-user $U 2>/dev/null; sleep 40
|
||||
loginctl terminate-user $U 2>/dev/null; sleep 30
|
||||
systemctl reset-failed desktop-session.service
|
||||
rm -f /tmp/mobilegl-compositor.log
|
||||
date +%s > /tmp/plasma-start
|
||||
systemctl start desktop-session.service
|
||||
sleep 40
|
||||
"
|
||||
am force-stop $P
|
||||
am start -n $P/com.anland.consumer.MainActivity > /dev/null
|
||||
sleep 30
|
||||
$D --name=$C run bash -lc "
|
||||
systemctl --no-pager status desktop-session.service | head -8
|
||||
UID_=\$(id -u $U)
|
||||
sudo -u $U XDG_RUNTIME_DIR=/run/user/\$UID_ systemctl --user --no-pager list-units --all 'plasma*' 2>&1 | head -30
|
||||
|
||||
@@ -5,7 +5,8 @@ P=${PKG:-com.anland.consumer.mobilegl}
|
||||
C=${CONTAINER:-arch-kde-mgl}
|
||||
SOCK=${SOCK:-/data/local/tmp/anland-mobilegl/display.sock}
|
||||
echo "battery: $(dumpsys battery | grep ' level:' | tr -d ' ') $(dumpsys power | grep -o 'mStayOn=[a-z]*')"
|
||||
echo "prop debug.mobilegl.backend=$(getprop debug.mobilegl.backend) container /etc/mobilegl/backend=$(cat /mnt/Droidspaces/$C/etc/mobilegl/backend 2>/dev/null)"
|
||||
echo "backend: app setting=$(cat /data/data/$P/files/mobilegl-backend 2>/dev/null || echo 'DirectGLES (default)') published=$(cat ${SOCK%/*}/backend 2>/dev/null) container /etc/mobilegl/backend=$(cat /mnt/Droidspaces/$C/etc/mobilegl/backend 2>/dev/null) prop override=$(getprop debug.mobilegl.backend)"
|
||||
echo "desktop service log: $(tail -1 ${SOCK%/*}/desktop.log 2>/dev/null)"
|
||||
echo "app pid: $(pidof $P) server (:mobilegl) pid: $(pidof $P:mobilegl)"
|
||||
ps -A -o PID,ARGS | grep "display_daemon $SOCK" | grep -v grep || echo "experiment display daemon NOT running"
|
||||
$D show
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
# switch.sh <DirectGLES|DirectVulkan> - (Android root shell) select the server backend: Espryt =
|
||||
# DirectGLES, Magma = DirectVulkan. Sets the system property the server reads (lost on reboot), writes
|
||||
# the container's /etc/mobilegl/backend (what every client and the KWin drop-in report; it must match or
|
||||
# the server refuses the client: "Hello.backendType disagrees with pinned backend"), restarts the app.
|
||||
# The running Plasma session still speaks the old backend: run run-plasma.sh afterwards.
|
||||
# Env: PKG, CONTAINER (arch-kde-mgl), SOCK (display daemon socket).
|
||||
# switch.sh <DirectGLES|DirectVulkan> - (Android root shell) change the MobileGL backend the anland
|
||||
# app's server runs (Espryt = DirectGLES, Magma = DirectVulkan). The choice is the app's setting
|
||||
# (Settings > Connection > MobileGL desktop, saved in the app's files/mobilegl-backend); this does
|
||||
# what a user does there: save it, Stop desktop, open the app again. The new server publishes the
|
||||
# backend and the container's session copies it to /etc/mobilegl/backend before it starts, so
|
||||
# server and clients agree. ~30-60 s. No setprop: debug.mobilegl.backend, if set, still overrides
|
||||
# the setting until the next reboot - this clears it.
|
||||
# Env: PKG, SOCK.
|
||||
B=${1:?usage: switch.sh DirectGLES|DirectVulkan}
|
||||
P=${PKG:-com.anland.consumer.mobilegl}
|
||||
C=${CONTAINER:-arch-kde-mgl}
|
||||
SOCK=${SOCK:-/data/local/tmp/anland-mobilegl/display.sock}
|
||||
setprop debug.mobilegl.backend $B
|
||||
echo $B > /mnt/Droidspaces/$C/etc/mobilegl/backend
|
||||
am force-stop $P
|
||||
am start -n $P/com.anland.consumer.MainActivity --es socket_path $SOCK >/dev/null
|
||||
sleep 4
|
||||
[ -n "$(getprop debug.mobilegl.backend)" ] && setprop debug.mobilegl.backend ""
|
||||
if pidof $P:mobilegl > /dev/null; then
|
||||
am startservice -n $P/com.anland.consumer.MobileGLWorker -a com.anland.consumer.mobilegl.STOP > /dev/null
|
||||
i=0; while pidof $P:mobilegl > /dev/null && [ $i -lt 60 ]; do sleep 1; i=$((i + 1)); done
|
||||
fi
|
||||
am start -n $P/com.anland.consumer.MainActivity --es mobilegl_backend $B > /dev/null
|
||||
echo "backend $B saved; the desktop is starting (watch: sh $(dirname $0)/status.sh)"
|
||||
|
||||
@@ -27,7 +27,7 @@ for f in "$K"/anland_backend_Arch_v5/src/backends/anland/*; do
|
||||
lf "$f" "$st/kwsync/anland_backend_Arch_v5/src/backends/anland/$b"
|
||||
lf "$f" "$st/kwin-sync/anland/$b"
|
||||
done
|
||||
for f in kwin.patch mobilegl-startup.sh; do
|
||||
for f in kwin.patch mobilegl-startup.sh desktop-session-mobilegl.conf; do
|
||||
lf "$K/Arch_v5/$f" "$st/kwsync/Arch_v5/$f"
|
||||
lf "$K/Arch_v5/$f" "$st/kwin-sync/misc/$f"
|
||||
done
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
## 架构
|
||||
|
||||
- **平板**:Lenovo TB321FU(Y700,Adreno 750,Android 15,内核 6.1),**KernelSU** root(`/data/adb/ksu`、`ksud`;不是 Magisk),`su -c` 可用。USB 序列号 `HA27Q3LQ`,也常走无线调试 `ip:port`。
|
||||
- **anland APK** `com.anland.consumer.mobilegl`(anland 分支 `legacy-mobilegl-unified` 的 debuggable 构建):UI 进程 + 私有 Service 进程 `:mobilegl`(`MobileGLWorker`)。后者加载 **server** `libMobileGL.so`(NDK 构建,MobileGL 分支 `feat/disaggregated`),监听抽象 socket `@anland-mobilegl`。一个进程服务所有 client(KWin、plasmashell、ksplash、Chrome……),一个进程只服务一种后端。
|
||||
- **后端**:`setprop debug.mobilegl.backend DirectGLES|DirectVulkan`(Espryt = DirectGLES,Magma = DirectVulkan;重启丢失),必须与容器里的 `/etc/mobilegl/backend` 一致——所有 client 按这个文件报后端,不一致 server 拒绝("Hello.backendType disagrees with pinned backend")。
|
||||
- **实验用 display daemon**:`/data/adb/modules/anland-daemon/display_daemon /data/local/tmp/anland-mobilegl/display.sock`(显示 / 输入中介)。**开机不会自动起**——模块的 `service.sh` 只起原版那个(`/data/local/tmp/display_daemon.sock`),原版不要动。
|
||||
- **anland APK** `com.anland.consumer.mobilegl`(anland 分支 `legacy-mobilegl-unified` 的 debuggable 构建):UI 进程 + 私有 Service 进程 `:mobilegl`(`MobileGLWorker`)。后者加载 **server** `libMobileGL.so`(NDK 构建,MobileGL 分支 `feat/disaggregated`),从第一个 attach 上来的窗口起监听抽象 socket `@anland-mobilegl`。一个进程服务所有 client(KWin、plasmashell、ksplash、Chrome……),一个进程只服务一种后端。`MobileGLWorker` 是**前台服务**(通知"Linux 桌面正在运行",带"停止桌面"按钮),窗口隐藏、锁屏、从最近任务划掉之后 server 和会话都还在。
|
||||
- **后端**:app 设置"渲染后端"(设置 > 连接 > MobileGL 桌面;存在 `/data/data/<包名>/files/mobilegl-backend`,默认 DirectGLES;启动参数 `--es mobilegl_backend X` 也会写它)。Espryt = DirectGLES,Magma = DirectVulkan。server 进程启动时读一次;app 把它发布成 `/data/local/tmp/anland-mobilegl/backend`,会话启动前拷进容器的 `/etc/mobilegl/backend`——所有 client 按这个文件报后端,不一致 server 拒绝("Hello.backendType disagrees with pinned backend")。如果有人设了 `debug.mobilegl.backend`,它在下次重启前仍然覆盖设置。
|
||||
- **实验用 display daemon**:`/data/adb/modules/anland-daemon/display_daemon /data/local/tmp/anland-mobilegl/display.sock`(显示 / 输入中介),由 app 拉起(见下)。模块的 `service.sh` 开机只起原版那个(`/data/local/tmp/display_daemon.sock`),原版不要动。
|
||||
- **容器** `arch-kde-mgl`:Droidspaces 6.4.5,Arch Linux ARM(aarch64 glibc),host 网络;Android 侧 `rootfs.img` 挂在 `/mnt/Droidspaces/arch-kde-mgl`。bind mount:`/data/local/tmp/anland-mobilegl` → `/run/anland-mobilegl`,`/data/local/tmp/display_daemon.sock` → `/run/display.sock`。
|
||||
- **会话**:`desktop-session.service`(User=swung0x48)的 drop-in 把 ExecStart 换成 `/opt/mobilegl/bin/mobilegl-startup.sh plasma`;它每次写 `plasma-kwin_wayland.service` 的用户 drop-in(经 `kwin_wayland_wrapper` 起 `/opt/mobilegl/kwin/bin/kwin_wayland` + `/opt/mobilegl/kwin/lib/libkwin.so.6.7.4`,`ANLAND_MOBILEGL=1`、`MOBILEGL_IPC_SURFACE=server`),然后 `startplasma-wayland`。
|
||||
- **KWin 6.7.4** 带 anland 的 `anland` 后端,经 server 直接画进 anland 的 Android Surface。其余 GL 进程都是 `MOBILEGL_IPC_SURFACE=offscreen`,经 KWin 合成上屏。
|
||||
- **会话**:`desktop-session.service`(User=swung0x48,**已 enable**:容器一启动就进会话,和原版镜像一样)。drop-in `/etc/systemd/system/desktop-session.service.d/mobilegl.conf`(anland 的 `producers/kde/Arch_v5/desktop-session-mobilegl.conf`,由 `sync-build-kwin.sh` 安装并 enable):先 `mobilegl-startup.sh wait`(等 `/proc/net/unix` 里 `@anland-mobilegl` 在监听、daemon socket 存在),再以 root 跑 `sync-backend`,`Restart=always`,ExecStart 是 `/opt/mobilegl/bin/mobilegl-startup.sh plasma`——它删掉粘滞的软件渲染键,整个会话设 `MOBILEGL_IPC_PROBE_TIMEOUT_MS=0`(MobileGL 永不拒绝,glvnd 不会把 KWin / plasmashell 交给别的 GL 栈),它每次写 `plasma-kwin_wayland.service` 的用户 drop-in(经 `kwin_wayland_wrapper` 起 `/opt/mobilegl/kwin/bin/kwin_wayland` + `/opt/mobilegl/kwin/lib/libkwin.so.6.7.4`,`ANLAND_MOBILEGL=1`、`MOBILEGL_IPC_SURFACE=server`),然后 `startplasma-wayland`。
|
||||
- **KWin 6.7.4** 带 anland 的 `anland` 后端,经 server 直接画进 anland 的 Android Surface。窗口不在屏幕上(consumer 断开)时后端把输出关掉(DPMS Off + RenderLoop inhibit:不合成、不发 frame callback),窗口回来再打开。其余 GL 进程都是 `MOBILEGL_IPC_SURFACE=offscreen`,经 KWin 合成上屏。
|
||||
- **client 库** `/opt/mobilegl/lib/libMobileGL.so`(glibc aarch64),是容器里**全系统**的 GL vendor(见下节):EGL vendor `/usr/share/glvnd/egl_vendor.d/10_mobilegl.json`(排在发行版的 `50_*.json` 前面,MobileGL 拒绝时由它接手)、GLX vendor `/usr/lib/libGLX_mobilegl.so.0`,配置来自 `/etc/mobilegl/client.conf`(`MOBILEGL_TRANSPORT=spawn MOBILEGL_IPC_DATA=shm MOBILEGL_IPC_CONTROL=unix:@anland-mobilegl`)+ `/etc/mobilegl/backend`。进程不需要任何专门的环境变量。
|
||||
- **零拷贝窗口**:client 的 `wl_egl_window` 帧是 server 分配的 AHardwareBuffer(shared image),以 dma-buf fd 经 `zwp_linux_dmabuf_v1` 交给 KWin;KWin 用 EGL 导入,server 按 inode 认出是自己发出的那块。KWin 的 DRM 设备来自 `GBM_BACKEND=mobilegl` → `/usr/lib/gbm/mobilegl_gbm.so`(节点只当身份,从不 ioctl)。没有 linux-dmabuf 时退回 wl_shm 回读。
|
||||
- **X11**(Xwayland)走 MobileGL 的 GLX vendor,每帧回读 + `xcb_put_image`。Chrome 用 `mobilegl-startup.sh chrome`:ANGLE GLES 跑在 MobileGL EGL 上,GPU 在浏览器进程内。
|
||||
@@ -29,22 +29,21 @@
|
||||
|
||||
主机脚本都在 Git Bash 里 `bash scripts/<x>.sh` 运行。直接敲 adb 时,带设备路径要加 `MSYS_NO_PATHCONV=1`(否则 `/data/...` 被改写成 Git 安装目录),root 命令整个包进一层引号:`adb shell 'su -c "..."'`。设备脚本也可以不推送直接跑:`MSYS_NO_PATHCONV=1 adb shell 'su -c sh' < scripts/device/status.sh`。
|
||||
|
||||
## 平板重启后的拉起
|
||||
## 启动、闲置、停止——没有手动步骤
|
||||
|
||||
重启后整套会话一样都不在。可以一条 `adb shell 'su -c "sh /data/local/tmp/anl/bringup.sh [DirectGLES|DirectVulkan]"'`(按下面的步骤拼出来的,还没整体跑过),或者按顺序手敲:
|
||||
开机什么都不起(容器 `run_at_boot=0`)。**打开 app**(桌面图标,等同 `am start -n com.anland.consumer.mobilegl/com.anland.consumer.MainActivity`,不带参数;APK 的默认 socket 是实验 daemon 那个,见 `-PanlandDefaultSocket`)会调 `MobileGLDesktop.ensureStarted()`——唯一的触发点——启动前台服务,并以 root(`su`)跑 APK 里的 `assets/mobilegl-desktop.sh up`:daemon 不在就起(脚本先离开 app 的 cgroup,app 被杀时 daemon 和容器不受牵连)→ 发布后端 → 容器没跑就启动 → `systemctl start --no-block desktop-session`。窗口等 daemon socket 出现;Surface attach 后 server 开始监听;会话的 `wait` 放行,Plasma 起来。全都在跑时再打开只是重新挂上窗口。日志:`/data/local/tmp/anland-mobilegl/desktop.log`,logcat `AnlandMobileGL`("MobileGL desktop up done in N ms")。
|
||||
|
||||
窗口隐藏、熄屏、锁屏、从最近任务划掉:server 与会话都留着(前台服务);KWin 记 "viewer gone: output powered down" 然后闲置,回来时记 "viewer back"。**停止桌面**(通知按钮,或 `am startservice -n <包名>/com.anland.consumer.MobileGLWorker -a com.anland.consumer.mobilegl.STOP`)跑 `mobilegl-desktop.sh down`(停会话、停容器,daemon 留着),关窗口,结束 `:mobilegl` 进程。
|
||||
|
||||
```sh
|
||||
adb connect <ip>:<port> # 只有无线调试才需要(比如 USB 供不上电时)
|
||||
adb connect <ip>:<port> # 只有无线调试才需要
|
||||
export MSYS_NO_PATHCONV=1
|
||||
adb shell 'su -c "svc power stayon true"'
|
||||
adb shell 'su -c "setprop debug.mobilegl.backend DirectVulkan"' # 或 DirectGLES,与 /etc/mobilegl/backend 一致
|
||||
adb shell 'su -c "am start -n com.anland.consumer.mobilegl/com.anland.consumer.MainActivity --es socket_path /data/local/tmp/anland-mobilegl/display.sock"'
|
||||
adb shell 'su -c "/data/local/Droidspaces/bin/droidspaces -C /data/local/Droidspaces/Containers/arch-kde-mgl/container.config start"'
|
||||
adb shell 'su -c "sh /data/local/tmp/anl/restart-daemon.sh"' # 实验 daemon;目录 777、socket 666(容器里 uid 1000 要连)
|
||||
adb shell 'su -c "sh /data/local/tmp/anl/run-plasma.sh"' # 重启 app 与 desktop-session,约 90 秒
|
||||
adb shell 'su -c "sh /data/local/tmp/anl/bringup.sh"' # 重启后:点亮、解开锁屏、打开 app、打印各步耗时
|
||||
bash scripts/desktop-verify.sh push cold reopen idle # 冷启动计时、划掉再打开、可见/隐藏/锁屏的 CPU 与 GPU
|
||||
adb shell 'su -c "sh /data/local/tmp/anl/status.sh"'
|
||||
```
|
||||
|
||||
`droidspaces` 没有 `status` 子命令,`droidspaces show` 列出在跑的容器。不要用旧的 `/data/local/tmp/restart-daemon.sh`(里面 kill 的是写死的 PID)。起完用 `device/status.sh` 检查:两个进程、daemon、会话 active、kwin_wayland 与 plasmashell 在跑、kdeglobals 里没有软件渲染键。
|
||||
`droidspaces` 没有 `status` 子命令,`droidspaces show` 列出在跑的容器。`device/run-plasma.sh` 是开发用的重启(会话 + logind 用户,再重开 app),重新构建之后需要——KWin 不会重连新的 server 进程。`device/desktop-reset.sh` 把一切停到"刚重启"的状态。以前的手动序列(setprop、起容器、`restart-daemon.sh`、`run-plasma.sh`)不再需要;`restart-daemon.sh` 只留作调试 daemon。
|
||||
|
||||
## 构建与部署循环
|
||||
|
||||
@@ -89,7 +88,7 @@ MSYS2_ARG_CONV_EXCL='*' wsl -d archlinux -- bash -lc 'cd ~/mgl-anl-bld && ctest
|
||||
|
||||
## 切换后端
|
||||
|
||||
`adb shell 'su -c "sh /data/local/tmp/anl/switch.sh DirectGLES"'`(设属性、写 `/etc/mobilegl/backend`、重启 app),然后 `run-plasma.sh`——正在跑的会话里各 client 还钉在旧后端上。`cyc.sh` 不改后端。
|
||||
在 app 里:设置 > 连接 > MobileGL 桌面 > 渲染后端,然后通知里"停止桌面",再打开 app。或者 `adb shell 'su -c "sh /data/local/tmp/anl/switch.sh DirectGLES"'`,做的是同一件事(用启动参数保存设置、STOP 服务、重新打开;顺手清掉残留的 `debug.mobilegl.backend`)。不用 setprop,也不用改容器里的文件:会话下次启动时把发布的后端拷进 `/etc/mobilegl/backend`。`cyc.sh` 不改后端。
|
||||
|
||||
## 全系统 vendor 与回退
|
||||
|
||||
@@ -152,10 +151,10 @@ Chrome:`bash scripts/chrome-launch.sh <tag> [参数]`(日志 `/tmp/mgl-chrom
|
||||
|
||||
- **pkill -f 误杀自己**:`ct.sh` / `droidspaces run bash -lc "<脚本>"` 的进程参数里带着整段脚本,`pkill -f chrome` 会先把执行者杀掉。用 `pkill -x`。
|
||||
- **/tmp 里 root 的文件**:root 跑 client 留下的日志,之后 swung0x48 打不开(日志不出现)。先以 root `rm -f`。
|
||||
- **Plasma 软件渲染是粘滞的**:server 一崩,Plasma 就把 `[QtQuickRendererSettings] SceneGraphBackend=software` 写进 `~swung0x48/.config/kdeglobals`,之后 plasmashell 全用 CPU 渲染,截图照样正常(托盘里有"正在使用的软件渲染器"图标)。下结论前删掉:`sudo -u swung0x48 kwriteconfig6 --file kdeglobals --group QtQuickRendererSettings --key SceneGraphBackend --delete`(cyc.sh 会做),再重启会话。
|
||||
- **Plasma 软件渲染是粘滞的**:server 一崩,Plasma 就把 `[QtQuickRendererSettings] SceneGraphBackend=software` 写进 `~swung0x48/.config/kdeglobals`,之后 plasmashell 全用 CPU 渲染,截图照样正常(托盘里有"正在使用的软件渲染器"图标)。`mobilegl-startup.sh plasma` 每次会话启动都会删掉它;一个已经崩过的会话里,下结论前先重启会话(`run-plasma.sh`)。
|
||||
- **锁屏**:自动锁屏已关(`kscreenlockerrc` 的 `[Daemon] Autolock=false`);真锁上只能输密码——这种 logind 会话不支持 lock-session,`device/unlock.sh` 的 unlock-session 能否解开未验证。测 greeter 用 `/usr/lib/kscreenlocker_greet --testing` 再杀掉。
|
||||
- **CRLF**:本机 `core.autocrlf=true`,anland 的后端源码和 `sync-build-kwin.sh` 在 Windows checkout 里是 CRLF。凡是要在 Linux / Android 上执行的先 `tr -d '\r'`(`ct.sh`、`push-tools.sh`、`kwin-stage.sh` 已处理);skill 目录有 `.gitattributes` 强制 LF。
|
||||
- **display daemon 开机不自启**:KWin 报 "failed to connect to display daemon at /run/anland-mobilegl/display.sock",会话约 3 秒退出。
|
||||
- **display daemon**:由 app 拉起;会话的 `wait` 步骤保证 KWin 不会在它之前启动(连不上时 KWin 报 "failed to connect to display daemon at /run/anland-mobilegl/display.sock",约 3 秒退出)。从 app 的 `su` 拉起的东西必须先离开 app 的 cgroup(`echo $$ > /sys/fs/cgroup/cgroup.procs`),否则 force-stop 会一并杀掉。
|
||||
- **电量 / 连接**:电量低或熄屏(默认 30 秒)可能让 SurfaceView 被回收——`svc power stayon true`;无线调试的端口每次配对都变——脚本里不要写死 `-s HA27Q3LQ`,多设备时设 `ANDROID_SERIAL`。
|
||||
- **容器与 Android 路径**:容器的 `/tmp` 和平板的 `/data/local/tmp` 不是一个地方;文件经 `/mnt/Droidspaces/arch-kde-mgl/root`(= 容器 `/root`)或 `/data/local/tmp/anland-mobilegl`(= 容器 `/run/anland-mobilegl`)中转。
|
||||
- **正在映射的 .so 不要原地覆盖**(容器里或运行中的 APK):拷成新 inode 再 `mv -f`;APK 换库前先 force-stop。
|
||||
|
||||
Reference in New Issue
Block a user