]> glassweightruler.freedombox.rocks Git - waydroid.git/blobdiff - tools/helpers/lxc.py
Policies have been adjusted for Android 11.
[waydroid.git] / tools / helpers / lxc.py
index 5e7b31078900c472d7bef94fccd54c3a4b469e4e..d77493600b06409142e3ef052f70e6c652a4ad5e 100644 (file)
@@ -7,6 +7,7 @@ import logging
 import glob
 import shutil
 import platform
+import gbinder
 import tools.config
 import tools.helpers.run
 
@@ -38,6 +39,7 @@ def generate_nodes_lxc_config(args):
     # Necessary dev nodes
     make_entry("tmpfs", "dev", "tmpfs", "nosuid 0 0", False)
     make_entry("/dev/zero")
+    make_entry("/dev/null")
     make_entry("/dev/full")
     make_entry("/dev/ashmem", check=False)
     make_entry("/dev/fuse")
@@ -49,13 +51,15 @@ def generate_nodes_lxc_config(args):
     make_entry("/dev/mali0")
     make_entry("/dev/pvr_sync")
     make_entry("/dev/pmsg0")
-    make_entry("/dev/fb0")
-    make_entry("/dev/graphics/fb0")
-    make_entry("/dev/fb1")
-    make_entry("/dev/graphics/fb1")
-    make_entry("/dev/fb2")
-    make_entry("/dev/graphics/fb2")
-    make_entry("/dev/dri", options="bind,create=dir,optional 0 0")
+    make_entry("/dev/dxg")
+    make_entry(tools.helpers.gpu.getDriNode(args), "dev/dri/renderD128")
+
+    for n in glob.glob("/dev/fb*"):
+        make_entry(n)
+    for n in glob.glob("/dev/graphics/fb*"):
+        make_entry(n)
+    for n in glob.glob("/dev/video*"):
+        make_entry(n)
 
     # Binder dev nodes
     make_entry("/dev/" + args.BINDER_DRIVER, "dev/binder", check=False)
@@ -71,6 +75,9 @@ def generate_nodes_lxc_config(args):
     make_entry("none", "dev/pts", "devpts", "defaults,mode=644,ptmxmode=666,create=dir 0 0", False)
     make_entry("/dev/uhid")
 
+    # TUN/TAP device node for VPN
+    make_entry("/dev/net/tun", "dev/tun")
+
     # Low memory killer sys node
     make_entry("/sys/module/lowmemorykiller", options="bind,create=dir,optional 0 0")
 
@@ -89,35 +96,82 @@ def generate_nodes_lxc_config(args):
     make_entry("/dev/sw_sync")
     make_entry("/sys/kernel/debug", options="rbind,create=dir,optional 0 0")
 
+    # Vibrator
+    make_entry("/sys/class/leds/vibrator",
+               options="bind,create=dir,optional 0 0")
+    make_entry("/sys/devices/virtual/timed_output/vibrator",
+               options="bind,create=dir,optional 0 0")
+
     # Media dev nodes (for Mediatek)
     make_entry("/dev/Vcodec")
     make_entry("/dev/MTK_SMI")
     make_entry("/dev/mdp_sync")
     make_entry("/dev/mtk_cmdq")
 
-    # Media dev nodes (for Qcom)
-    make_entry("/dev/video32")
-    make_entry("/dev/video33")
+    # WSLg
+    make_entry("tmpfs", "mnt_extra", "tmpfs", "nodev 0 0", False)
+    make_entry("/mnt/wslg", "mnt_extra/wslg",
+               options="rbind,create=dir,optional 0 0")
+
+    # var
+    make_entry("tmpfs", "var", "tmpfs", "nodev 0 0", False)
+    make_entry("/var/run", options="rbind,create=dir,optional 0 0")
+
+    # tmp
+    make_entry("tmpfs", "tmp", "tmpfs", "nodev 0 0", False)
+    for n in glob.glob("/tmp/run-*"):
+        make_entry(n, options="rbind,create=dir,optional 0 0")
+
+    # NFC config
+    make_entry("/system/etc/libnfc-nci.conf", options="bind,optional 0 0")
 
     return nodes
 
 
 def set_lxc_config(args):
     lxc_path = tools.config.defaults["lxc"] + "/waydroid"
-    config_file = "config_2"
     lxc_ver = get_lxc_version(args)
     if lxc_ver == 0:
         raise OSError("LXC is not installed")
-    elif lxc_ver <= 2:
-        config_file = "config_1"
-    config_path = tools.config.tools_src + "/data/configs/" + config_file
+    config_paths = tools.config.tools_src + "/data/configs/config_"
+    seccomp_profile = tools.config.tools_src + "/data/configs/waydroid.seccomp"
+    apparmor_profiles = [tools.config.tools_src + "/data/configs/" + "lxc-waydroid",tools.config.tools_src + "/data/configs/" + "android_app",tools.config.tools_src + "/data/configs/" + "adbd"]
+    apparmor_profile_dir = "/etc/apparmor.d/"
+
+    config_snippets = [ config_paths + "base" ]
+    # lxc v1 is a bit special because some options got renamed later
+    if lxc_ver == 1:
+        config_snippets.append(config_paths + "1")
+    else:
+        for ver in range(2, 5):
+            snippet = config_paths + str(ver)
+            if lxc_ver >= ver and os.path.exists(snippet):
+                config_snippets.append(snippet)
 
     command = ["mkdir", "-p", lxc_path]
-    tools.helpers.run.root(args, command)
-    command = ["cp", "-fpr", config_path, lxc_path + "/config"]
-    tools.helpers.run.root(args, command)
+    tools.helpers.run.user(args, command)
+    command = ["sh", "-c", "cat {} > \"{}\"".format(' '.join('"{0}"'.format(w) for w in config_snippets), lxc_path + "/config")]
+    tools.helpers.run.user(args, command)
     command = ["sed", "-i", "s/LXCARCH/{}/".format(platform.machine()), lxc_path + "/config"]
-    tools.helpers.run.root(args, command)
+    tools.helpers.run.user(args, command)
+    command = ["cp", "-fpr", seccomp_profile, lxc_path + "/waydroid.seccomp"]
+    tools.helpers.run.user(args, command)
+
+    try:
+        command = ["cp", "-i", apparmor_profiles[0], apparmor_profile_dir + "lxc/lxc-waydroid"]
+        tools.helpers.run.user(args, command)
+        command = ["apparmor_parser", "-r", apparmor_profile_dir + "lxc/lxc-waydroid"]
+        tools.helpers.run.user(args, command)
+        command = ["cp", "-i", apparmor_profiles[1], apparmor_profile_dir + "android_app"]
+        tools.helpers.run.user(args, command)
+        command = ["apparmor_parser", "-r", apparmor_profile_dir + "android_app"]
+        tools.helpers.run.user(args, command)
+        command = ["cp", "-i", apparmor_profiles[2], apparmor_profile_dir + "adbd"]
+        tools.helpers.run.user(args, command)
+        command = ["apparmor_parser", "-r", apparmor_profile_dir + "adbd"]
+        tools.helpers.run.user(args, command)
+    except:
+        logging.warning("An error has occurred while installing AppArmor profiles. If profiles are not installed, or AppArmor is disabled or not supported on your system, then the container will run without AppArmor protection.")
 
     nodes = generate_nodes_lxc_config(args)
     config_nodes_tmp_path = args.work + "/config_nodes"
@@ -126,7 +180,7 @@ def set_lxc_config(args):
         config_nodes.write(node + "\n")
     config_nodes.close()
     command = ["mv", config_nodes_tmp_path, lxc_path]
-    tools.helpers.run.root(args, command)
+    tools.helpers.run.user(args, command)
 
 
 def make_base_props(args):
@@ -139,30 +193,45 @@ def make_base_props(args):
             "ro.board.platform"]
         for p in hardware_props:
             prop = tools.helpers.props.host_get(args, p)
-            hal_prop = ""
             if prop != "":
-                for lib in ["lib", "lib64"]:
-                    hal_file = "/vendor/" + lib + "/hw/" + hardware + "." + prop + ".so"
-                    command = ["readlink", "-f", hal_file]
-                    hal_file_path = tools.helpers.run.root(args, command, output_return=True).strip()
-                    if os.path.isfile(hal_file_path):
-                        hal_prop = re.sub(".*" + hardware + ".", "", hal_file_path)
-                        hal_prop = re.sub(".so", "", hal_prop)
-                        if hal_prop != "":
-                            return hal_prop
-            if hal_prop != "":
-                return hal_prop
+                for lib in ["/odm/lib", "/odm/lib64", "/vendor/lib", "/vendor/lib64", "/system/lib", "/system/lib64"]:
+                    hal_file = lib + "/hw/" + hardware + "." + prop + ".so"
+                    if os.path.isfile(hal_file):
+                        return prop
         return ""
 
+    def find_hidl(intf):
+        if args.vendor_type == "MAINLINE":
+            return False
+
+        try:
+            sm = gbinder.ServiceManager("/dev/hwbinder")
+            return intf in sm.list_sync()
+        except:
+            return False
+
     props = []
+
+    if not os.path.exists("/dev/ashmem"):
+        props.append("sys.use_memfd=true")
+
+    egl = tools.helpers.props.host_get(args, "ro.hardware.egl")
+    dri = tools.helpers.gpu.getDriNode(args)
+
     gralloc = find_hal("gralloc")
-    if gralloc == "":
-        gralloc = "gbm"
-        props.append("ro.hardware.egl=mesa")
+    if not gralloc:
+        if find_hidl("android.hardware.graphics.allocator@4.0::IAllocator/default"):
+            gralloc = "android"
+    if not gralloc:
+        if dri:
+            gralloc = "gbm"
+            egl = "mesa"
+        else:
+            gralloc = "default"
+            egl = "swiftshader"
         props.append("debug.stagefright.ccodec=0")
     props.append("ro.hardware.gralloc=" + gralloc)
 
-    egl = tools.helpers.props.host_get(args, "ro.hardware.egl")
     if egl != "":
         props.append("ro.hardware.egl=" + egl)
 
@@ -183,18 +252,61 @@ def make_base_props(args):
         props.append("ro.vendor.extension_library=" + ext_library)
 
     vulkan = find_hal("vulkan")
-    if vulkan != "":
+    if not vulkan and dri:
+        vulkan = tools.helpers.gpu.getVulkanDriver(args, os.path.basename(dri))
+    if vulkan:
         props.append("ro.hardware.vulkan=" + vulkan)
 
+    treble = tools.helpers.props.host_get(args, "ro.treble.enabled")
+    if treble != "true":
+        camera = find_hal("camera")
+        if camera != "":
+            props.append("ro.hardware.camera=" + camera)
+        else:
+            if args.vendor_type == "MAINLINE":
+                props.append("ro.hardware.camera=v4l2")
+
     opengles = tools.helpers.props.host_get(args, "ro.opengles.version")
     if opengles == "":
-        opengles = "196608"
+        opengles = "196609"
     props.append("ro.opengles.version=" + opengles)
 
-    props.append("waydroid.system_ota=" + args.system_ota)
-    props.append("waydroid.vendor_ota=" + args.vendor_ota)
+    if args.images_path not in tools.config.defaults["preinstalled_images_paths"]:
+        props.append("waydroid.system_ota=" + args.system_ota)
+        props.append("waydroid.vendor_ota=" + args.vendor_ota)
+    else:
+        props.append("waydroid.updater.disabled=true")
+
     props.append("waydroid.tools_version=" + tools.config.version)
 
+    if args.vendor_type == "MAINLINE":
+        props.append("ro.vndk.lite=true")
+
+    for product in ["brand", "device", "manufacturer", "model", "name"]:
+        prop_product = tools.helpers.props.host_get(
+            args, "ro.product.vendor." + product)
+        if prop_product != "":
+            props.append("ro.product.waydroid." + product + "=" + prop_product)
+        else:
+            if os.path.isfile("/proc/device-tree/" + product):
+                with open("/proc/device-tree/" + product) as f:
+                    f_value = f.read().strip().rstrip('\x00')
+                    if f_value != "":
+                        props.append("ro.product.waydroid." +
+                                     product + "=" + f_value)
+
+    prop_fp = tools.helpers.props.host_get(args, "ro.vendor.build.fingerprint")
+    if prop_fp != "":
+        props.append("ro.build.fingerprint=" + prop_fp)
+
+    # now append/override with values in [properties] section of waydroid.cfg
+    cfg = tools.config.load(args)
+    for k, v in cfg["properties"].items():
+        for idx, elem in enumerate(props):
+            if (k+"=") in elem:
+                props.pop(idx)
+        props.append(k+"="+v)
+
     base_props = open(args.work + "/waydroid_base.prop", "w")
     for prop in props:
         base_props.write(prop + "\n")
@@ -202,6 +314,13 @@ def make_base_props(args):
 
 
 def setup_host_perms(args):
+    if not os.path.exists(tools.config.defaults["host_perms"]):
+        os.mkdir(tools.config.defaults["host_perms"])
+
+    treble = tools.helpers.props.host_get(args, "ro.treble.enabled")
+    if treble != "true":
+        return
+
     sku = tools.helpers.props.host_get(args, "ro.boot.product.hardware.sku")
     copy_list = []
     copy_list.extend(
@@ -219,34 +338,33 @@ def setup_host_perms(args):
             copy_list.append(
                 "/odm/etc/permissions/sku_{}/android.hardware.consumerir.xml".format(sku))
 
-    if not os.path.exists(tools.config.defaults["host_perms"]):
-        os.mkdir(tools.config.defaults["host_perms"])
-
     for filename in copy_list:
         shutil.copy(filename, tools.config.defaults["host_perms"])
 
 def status(args):
-    command = ["sudo", "lxc-info", "-P", tools.config.defaults["lxc"], "-n", "waydroid", "-sH"]
-    return subprocess.run(command, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
+    command = ["lxc-info", "-P", tools.config.defaults["lxc"], "-n", "waydroid", "-sH"]
+    out = subprocess.run(command, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
+    os.chmod(args.log, 0o666)
+    return out
 
 def start(args):
     command = ["lxc-start", "-P", tools.config.defaults["lxc"],
                "-F", "-n", "waydroid", "--", "/init"]
-    tools.helpers.run.root(args, command, output="background")
+    tools.helpers.run.user(args, command, output="background")
 
 def stop(args):
     command = ["lxc-stop", "-P",
                tools.config.defaults["lxc"], "-n", "waydroid", "-k"]
-    tools.helpers.run.root(args, command)
+    tools.helpers.run.user(args, command)
 
 def freeze(args):
     command = ["lxc-freeze", "-P", tools.config.defaults["lxc"], "-n", "waydroid"]
-    tools.helpers.run.root(args, command)
+    tools.helpers.run.user(args, command)
 
 def unfreeze(args):
     command = ["lxc-unfreeze", "-P",
                tools.config.defaults["lxc"], "-n", "waydroid"]
-    tools.helpers.run.root(args, command)
+    tools.helpers.run.user(args, command)
 
 def shell(args):
     if status(args) != "RUNNING":
@@ -258,7 +376,7 @@ def shell(args):
         command.append(args.COMMAND)
     else:
         command.append("/system/bin/sh")
-    subprocess.run(command, env={"PATH": os.environ['PATH'] + "/system/bin:/vendor/bin"})
+    subprocess.run(command, env={"PATH": os.environ['PATH'] + ":/system/bin:/vendor/bin"})
 
 def logcat(args):
     if status(args) != "RUNNING":