Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,151 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MPL-2.0
"""Bounded replacement of the display session; restore Phosh when the trial ends."""
import argparse
import json
import os
from pathlib import Path
import pwd
import shlex
import signal
import subprocess
import time
UNIT = 'tundra-display-trial.service'
DROPIN = Path('/run/systemd/system/android-service@hwcomposer.service.d/20-phosh.conf')
SERVICE = Path('/run/systemd/system')/UNIT
CONFIG = Path('/run/tundra-phoc-trial.ini')
def command(*args,check=True):
return subprocess.run(args,check=check,capture_output=True,text=True,timeout=45)
def restore(result):
"""Attempt every restoration step even if an earlier command times out."""
errors = []
def attempt(*args):
try:
return command(*args, check=False)
except (OSError, subprocess.SubprocessError) as error:
errors.append({'command': list(args), 'error': str(error)})
return None
attempt('systemctl', 'stop', UNIT)
journal = attempt('journalctl', '-u', UNIT, '--no-pager', '-n', '300')
result['journal'] = journal.stdout if journal else ''
for path in (SERVICE, DROPIN, CONFIG):
try:
path.unlink(missing_ok=True)
except OSError as error:
errors.append({'path': str(path), 'error': str(error)})
attempt('systemctl', 'daemon-reload')
attempt('systemctl', 'reset-failed', UNIT)
attempt('systemctl', 'start', 'phosh.service')
status = attempt('systemctl', 'is-active', 'phosh.service')
result['restoredPhosh'] = status is not None and status.returncode == 0
if errors:
result['cleanupErrors'] = errors
def main():
parser=argparse.ArgumentParser(description=__doc__)
parser.add_argument('--product',type=Path,required=True)
parser.add_argument('--seconds',type=int,default=180)
parser.add_argument('--root',type=Path,help='Run Phoc and Gaia from this separate runtime tree; borrow installed Android HAL services')
args=parser.parse_args()
if os.geteuid()!=0:
raise RuntimeError('The display service switch requires administrator privileges')
product=args.product.resolve()
expected=Path('/home/droidian/vulpes-tundra-tests')
if not product.is_relative_to(expected) or not (product/'trial/session.py').is_file():
raise ValueError('Expected an existing isolated trial product')
if command('getprop','ro.product.device').stdout.strip()!='sargo':
raise ValueError('Expected Sargo')
if not 30<=args.seconds<=600:
raise ValueError('Trial duration must be between 30 and 600 seconds')
if any(p.exists() for p in (DROPIN,SERVICE,CONFIG)):
raise RuntimeError('Previous runtime configuration present; restore it before another trial')
if command('systemctl','is-active','phosh.service',check=False).returncode:
raise RuntimeError('Phosh must be active as the known return session')
account=pwd.getpwnam('droidian')
root = args.root.resolve() if args.root else None
if root:
if not root.is_relative_to(expected) or not (root/'usr/bin/phoc').is_file():
raise ValueError('Expected a staged ARM64 runtime under the trial directory')
if not (root/'opt/vulpes/trial/session.py').is_file():
raise ValueError('Common product must be staged under /opt/vulpes in the trial root')
(root/'opt/vulpes/logs').mkdir(exist_ok=True)
os.chown(root/'opt/vulpes/logs',account.pw_uid,account.pw_gid)
child=shlex.join(['/usr/bin/python3',str(Path('/opt/vulpes') if root else product)+'/trial/session.py','--own-compositor','--hybris-egl'])
result={'scope':'Own compositor on installed Droidian; not an independent root filesystem',
'startedAt':time.time(),'seconds':args.seconds,'restoredPhosh':False}
if root:
result.update(scope='Phoc and Gaia in a separate ARM64 root; Android HAL and logind borrowed from installed Droidian',runtimeRoot=str(root))
def interrupted(signum,frame):
raise KeyboardInterrupt
signal.signal(signal.SIGTERM,interrupted)
try:
DROPIN.parent.mkdir(exist_ok=True)
DROPIN.write_text('[Unit]\nBindsTo=\n')
CONFIG.write_text('[output:HWCOMPOSER-1]\nscale=3\n')
isolation = f'''RootDirectory={root}
MountAPIVFS=yes
PrivateNetwork=yes
BindPaths=/dev /run/user/{account.pw_uid}
BindReadOnlyPaths=/android/system /android/vendor /run/udev /run/dbus /run/systemd/sessions /run/systemd/seats /run/systemd/users /sys {CONFIG}
''' if root else ''
SERVICE.write_text(f'''[Unit]
Description=Temporary Vulpes display qualification
Requires=android-service@hwcomposer.service
After=android-service@hwcomposer.service systemd-user-sessions.service
Conflicts=phosh.service
[Service]
User=droidian
PAMName=login
WorkingDirectory=/home/droidian
Environment=XDG_RUNTIME_DIR=/run/user/{account.pw_uid}
Environment=XDG_SESSION_TYPE=wayland
Environment=XDG_CURRENT_DESKTOP=Vulpes
Environment=LANG=C.UTF-8
Environment=WLR_BACKENDS=hwcomposer,libinput
Environment=EGL_PLATFORM=hwcomposer
Environment=WLR_HWC_SKIP_VERSION_CHECK=1
{isolation}ExecStart={'/usr/bin/dbus-run-session -- ' if root else ''}/usr/bin/phoc --no-xwayland --socket=tundra-0 -C {CONFIG} -E {json.dumps(child)}
{'' if root else 'ExecStartPost=+chvt 7'}
TTYPath=/dev/tty7
TTYReset=yes
TTYVHangup=yes
StandardInput=tty-fail
StandardOutput={'append:'+str(root/'opt/vulpes/logs/compositor.log') if root else 'journal'}
StandardError=inherit
KillMode=control-group
TimeoutStopSec=20
RuntimeMaxSec={args.seconds+30}
''')
for p in (DROPIN,CONFIG,SERVICE):p.chmod(0o644)
command('systemctl','daemon-reload')
command('systemctl','stop','phosh.service')
command('systemctl','start',UNIT)
if root:
command('chvt','7')
print('Own compositor started; Phosh will be restored automatically.',flush=True)
deadline=time.monotonic()+args.seconds
while time.monotonic()<deadline:
if command('systemctl','is-active',UNIT,check=False).returncode:
raise RuntimeError('Dedicated compositor stopped unexpectedly')
time.sleep(2)
except Exception as e:
result['error']=str(e)
raise
finally:
restore(result)
result['finishedAt']=time.time()
report=(root/'opt/vulpes' if root else product)/'logs/compositor-trial.json'
report.parent.mkdir(exist_ok=True)
report.write_text(json.dumps(result,indent=2)+'\n')
os.chown(report,account.pw_uid,account.pw_gid)
print('Restored Phosh:',result['restoredPhosh'],flush=True)
if __name__=='__main__':
main()