commit fffe32888cfa81923fd78644c204648539a0823d Author: CoderKang Date: Tue Sep 16 15:54:17 2025 +0800 first commit diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fc6e400 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +** + +!/root/** +!/system/** diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1bf98db --- /dev/null +++ b/.gitignore @@ -0,0 +1,141 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/C,C++,Linux,macOS,vim +# Edit at https://www.toptal.com/developers/gitignore?templates=C,C++,Linux,macOS,vim + +### C ### +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +### C++ ### +# Prerequisites + +# Compiled Object files +*.slo + +# Precompiled Headers + +# Compiled Dynamic libraries + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai + +# Executables + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +# End of https://www.toptal.com/developers/gitignore/api/C,C++,Linux,macOS,vim diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..9385aee --- /dev/null +++ b/Android.mk @@ -0,0 +1,19 @@ +# +# Copyright 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/README.md b/README.md new file mode 100644 index 0000000..5ff2151 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +[ReDroid Doc](https://github.com/remote-android/redroid-doc) diff --git a/binder_alloc/Android.bp b/binder_alloc/Android.bp new file mode 100644 index 0000000..751f98e --- /dev/null +++ b/binder_alloc/Android.bp @@ -0,0 +1,7 @@ +cc_binary { + name: "binder_alloc", + srcs: ["main.cpp"], + cflags: ["-Wall", "-Werror"], + vendor: true, +} + diff --git a/binder_alloc/main.cpp b/binder_alloc/main.cpp new file mode 100644 index 0000000..708b606 --- /dev/null +++ b/binder_alloc/main.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BINDERFS_MAX_NAME 255 +struct binderfs_device { + char name[BINDERFS_MAX_NAME + 1]; + __u32 major; + __u32 minor; +}; +#define BINDER_CTL_ADD _IOWR('b', 1, struct binderfs_device) + +void usage(char *bin) { + printf("USAGE: %s BINDER-CONTROL-PATH DEVICE1 [DEVICE2 ...]\n", bin); + printf("EXAMPLE: binder_alloc /dev/binderfs/binder-control binder hwbinder vndbinder\n"); +} + +int main(int argc, char *argv[]) +{ + int fd, ret; + size_t len; + struct binderfs_device device{}; + + if (argc < 3) { + usage(basename(argv[0])); + exit(EXIT_FAILURE); + } + + fd = open(argv[1], O_RDONLY | O_CLOEXEC); + if (fd < 0) { + printf("%s - Failed to open binder-control device\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + char *dir = dirname(argv[1]); // "/dev/binderfs" + char *pathname = (char *) malloc(strlen(dir) + BINDERFS_MAX_NAME + 2); // "/dev/binderfs/binder" + + for (int i = 2; i < argc; ++i) { + sprintf(pathname, "%s/%s", dir, argv[i]); + if (access(pathname, F_OK) != -1) { + printf("binder device already allocated, path: %s\n", pathname); + chmod(pathname, 0666); + continue; + } + len = strlen(argv[i]); + if (len > BINDERFS_MAX_NAME) exit(EXIT_FAILURE); + + memcpy(device.name, argv[i], len); + device.name[len] = '\0'; + + ret = ioctl(fd, BINDER_CTL_ADD, &device); + if (ret < 0) { + printf("%s - Failed to allocate new binder device\n", + strerror(errno)); + exit(EXIT_FAILURE); + } + chmod(pathname, 0666); + printf("Allocated new binder device with major %d, minor %d, and " + "name %s\n", device.major, device.minor, + device.name); + } + free(pathname); + close(fd); + + exit(EXIT_SUCCESS); +} diff --git a/gpu_config.sh b/gpu_config.sh new file mode 100644 index 0000000..f43e935 --- /dev/null +++ b/gpu_config.sh @@ -0,0 +1,120 @@ +#!/system/bin/sh + +# args: driver +setup_vulkan() { + echo "setup vulkan for driver: $1" + case "$1" in + i915) + setprop ro.hardware.vulkan intel + ;; + amdgpu) + setprop ro.hardware.vulkan radeon + ;; + virtio_gpu) + setprop ro.hardware.vulkan virtio + ;; + v3d|vc4) + setprop ro.hardware.vulkan broadcom + ;; + msm_drm) + setprop ro.hardware.vulkan freedreno + ;; + panfrost) + setprop ro.hardware.vulkan panfrost + ;; + *) + echo "not supported driver: $1" + ;; + esac +} + +setup_render_node() { + node=$(getprop ro.boot.redroid_gpu_node) + if [ -n "$node" ]; then + echo "force render node: $node" + + setprop gralloc.gbm.device "$node" + chmod 666 "$node" + + # setup vulkan + driver=$(cut -d' ' -f1 "/sys/kernel/debug/dri/${node#/dev/dri/renderD}/name") + setup_vulkan "$driver" + return 0 + fi + + cd /sys/kernel/debug/dri || exit + for d in * ; do + if [ "$d" -ge "128" ]; then + driver="$(cut -d' ' -f1 "$d/name")" + echo "DRI node exists, driver: $driver" + setup_vulkan "$driver" + case $driver in + i915|amdgpu|nouveau|virtio_gpu|v3d|vc4|msm_drm|panfrost) + node="/dev/dri/renderD$d" + echo "use render node: $node" + setprop gralloc.gbm.device "$node" + chmod 666 "$node" + return 0 + ;; + esac + fi + done + + echo "NO qualified render node found" + return 1 +} + +gpu_setup_host() { + echo "use GPU host mode" + + setprop ro.hardware.egl mesa + setprop ro.hardware.gralloc gbm + setprop ro.boot.redroid_fps 30 +} + +gpu_setup_guest() { + echo "use GPU guest mode" + + VENDOR_EGL_DIR=/vendor/lib64/egl + SYSTEM_EGL_DIR=/system/lib64 + EGL_ANGLE=libEGL_angle.so + EGL_SS=libEGL_swiftshader.so + egl= + + if [ -f $VENDOR_EGL_DIR/$EGL_ANGLE ] || [ -f $SYSTEM_EGL_DIR/$EGL_ANGLE ]; then + egl=angle + elif [ -f $VENDOR_EGL_DIR/$EGL_SS ] || [ -f $SYSTEM_EGL_DIR/$EGL_SS ]; then + egl=swiftshader + else + echo "ERROR no SW egl found!!!" + fi + + setprop ro.hardware.egl $egl + setprop ro.hardware.gralloc redroid + setprop ro.hardware.vulkan pastel +} + +gpu_setup() { + ## mode=(auto, host, guest) + ## node=(/dev/dri/renderDxxx) + + mode=$(getprop ro.boot.redroid_gpu_mode guest) + if [ "$mode" = "host" ]; then + setup_render_node + gpu_setup_host + elif [ "$mode" = "guest" ]; then + gpu_setup_guest + elif [ "$mode" = "auto" ]; then + echo "use GPU auto mode" + if setup_render_node; then + gpu_setup_host + else + gpu_setup_guest + fi + else + echo "unknown mode: $mode" + fi +} + +gpu_setup + diff --git a/gralloc/Android.bp b/gralloc/Android.bp new file mode 100644 index 0000000..7b62c9d --- /dev/null +++ b/gralloc/Android.bp @@ -0,0 +1,24 @@ +cc_library_shared { + name: "gralloc.redroid", + vendor: true, + + srcs: [ + "*.cpp", + ], + + shared_libs: [ + "liblog", + "libcutils", + ], + + header_libs: [ + "libhardware_headers", + ], + + cflags: [ + "-Wall", "-Werror", + "-DLOG_TAG=\"gralloc\"", + ], + + relative_install_path: "hw", +} diff --git a/gralloc/framebuffer.cpp b/gralloc/framebuffer.cpp new file mode 100644 index 0000000..9796457 --- /dev/null +++ b/gralloc/framebuffer.cpp @@ -0,0 +1,338 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#ifdef __ANDROID__ +#include +#endif + +#include "gralloc_priv.h" +#include "gr.h" + +/*****************************************************************************/ + +// Set TARGET_USE_PAN_DISPLAY to true at compile time if the +// board uses FBIOPAN_DISPLAY to setup page flipping, otherwise +// default ioctl to do page-flipping is FBIOPUT_VSCREENINFO. +#ifndef USE_PAN_DISPLAY +#define USE_PAN_DISPLAY 0 +#endif + +// numbers of buffers for page flipping +#define NUM_BUFFERS 2 + + +enum { + PAGE_FLIP = 0x00000001, + LOCKED = 0x00000002 +}; + +struct fb_context_t { + framebuffer_device_t device; +}; + +/*****************************************************************************/ + +static int fb_setSwapInterval(struct framebuffer_device_t* dev, + int interval) +{ + if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) + return -EINVAL; + // FIXME: implement fb_setSwapInterval + return 0; +} + +static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) +{ + if (private_handle_t::validate(buffer) < 0) + return -EINVAL; + + private_handle_t const* hnd = reinterpret_cast(buffer); + private_module_t* m = reinterpret_cast( + dev->common.module); + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + const size_t offset = hnd->base - m->framebuffer->base; + m->info.activate = FB_ACTIVATE_VBL; + m->info.yoffset = offset / m->finfo.line_length; + if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { + ALOGE("FBIOPUT_VSCREENINFO failed"); + m->base.unlock(&m->base, buffer); + return -errno; + } + m->currentBuffer = buffer; + + } else { + // If we can't do the page_flip, just copy the buffer to the front + // FIXME: use copybit HAL instead of memcpy + + void* fb_vaddr; + void* buffer_vaddr; + + m->base.lock(&m->base, m->framebuffer, + GRALLOC_USAGE_SW_WRITE_RARELY, + 0, 0, m->info.xres, m->info.yres, + &fb_vaddr); + + m->base.lock(&m->base, buffer, + GRALLOC_USAGE_SW_READ_RARELY, + 0, 0, m->info.xres, m->info.yres, + &buffer_vaddr); + + memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); + + m->base.unlock(&m->base, buffer); + m->base.unlock(&m->base, m->framebuffer); + } + + return 0; +} + +/*****************************************************************************/ + +int mapFrameBufferLocked(struct private_module_t* module) +{ + // already initialized... + if (module->framebuffer) { + return 0; + } + + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + 0 }; + + int fd = -1; + int i=0; + char name[64]; + + while ((fd==-1) && device_template[i]) { + snprintf(name, 64, device_template[i], 0); + fd = open(name, O_RDWR, 0); + i++; + } + if (fd < 0) + return -errno; + + struct fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + info.reserved[0] = 0; + info.reserved[1] = 0; + info.reserved[2] = 0; + info.xoffset = 0; + info.yoffset = 0; + info.activate = FB_ACTIVATE_NOW; + + /* + * Request NUM_BUFFERS screens (at lest 2 for page flipping) + */ + info.yres_virtual = info.yres * NUM_BUFFERS; + + + uint32_t flags = PAGE_FLIP; +#if USE_PAN_DISPLAY + if (ioctl(fd, FBIOPAN_DISPLAY, &info) == -1) { + ALOGW("FBIOPAN_DISPLAY failed, page flipping not supported"); +#else + if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { + ALOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); +#endif + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + } + + if (info.yres_virtual < info.yres * 2) { + // we need at least 2 for page-flipping + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)", + info.yres_virtual, info.yres*2); + } + + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + uint64_t refreshQuotient = + ( + uint64_t( info.upper_margin + info.lower_margin + info.yres ) + * ( info.left_margin + info.right_margin + info.xres ) + * info.pixclock + ); + + /* Beware, info.pixclock might be 0 under emulation, so avoid a + * division-by-0 here (SIGFPE on ARM) */ + int refreshRate = refreshQuotient > 0 ? (int)(1000000000000000LLU / refreshQuotient) : 0; + + if (refreshRate == 0) { + // bleagh, bad info from the driver + refreshRate = 60*1000; // 60 Hz + } + + if (int(info.width) <= 0 || int(info.height) <= 0) { + // the driver doesn't return that information + // default to 160 dpi + info.width = ((info.xres * 25.4f)/160.0f + 0.5f); + info.height = ((info.yres * 25.4f)/160.0f + 0.5f); + } + + float xdpi = (info.xres * 25.4f) / info.width; + float ydpi = (info.yres * 25.4f) / info.height; + float fps = refreshRate / 1000.0f; + + ALOGI( "using (fd=%d)\n" + "id = %s\n" + "xres = %d px\n" + "yres = %d px\n" + "xres_virtual = %d px\n" + "yres_virtual = %d px\n" + "bpp = %d\n" + "r = %2u:%u\n" + "g = %2u:%u\n" + "b = %2u:%u\n", + fd, + finfo.id, + info.xres, + info.yres, + info.xres_virtual, + info.yres_virtual, + info.bits_per_pixel, + info.red.offset, info.red.length, + info.green.offset, info.green.length, + info.blue.offset, info.blue.length + ); + + ALOGI( "width = %d mm (%f dpi)\n" + "height = %d mm (%f dpi)\n" + "refresh rate = %.2f Hz\n", + info.width, xdpi, + info.height, ydpi, + fps + ); + + + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + if (finfo.smem_len <= 0) + return -errno; + + + module->flags = flags; + module->info = info; + module->finfo = finfo; + module->xdpi = xdpi; + module->ydpi = ydpi; + module->fps = fps; + + /* + * map the framebuffer + */ + + size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual); + module->framebuffer = new private_handle_t(dup(fd), fbSize, 0); + + module->numBuffers = info.yres_virtual / info.yres; + module->bufferMask = 0; + + void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (vaddr == MAP_FAILED) { + ALOGE("Error mapping the framebuffer (%s)", strerror(errno)); + return -errno; + } + module->framebuffer->base = intptr_t(vaddr); + memset(vaddr, 0, fbSize); + return 0; +} + +static int mapFrameBuffer(struct private_module_t* module) +{ + pthread_mutex_lock(&module->lock); + int err = mapFrameBufferLocked(module); + pthread_mutex_unlock(&module->lock); + return err; +} + +/*****************************************************************************/ + +static int fb_close(struct hw_device_t *dev) +{ + fb_context_t* ctx = (fb_context_t*)dev; + if (ctx) { + free(ctx); + } + return 0; +} + +int fb_device_open(hw_module_t const* module, const char* name, + hw_device_t** device) +{ + int status = -EINVAL; + if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { + /* initialize our state here */ + fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev)); + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = 0; + dev->device.common.module = const_cast(module); + dev->device.common.close = fb_close; + dev->device.setSwapInterval = fb_setSwapInterval; + dev->device.post = fb_post; + dev->device.setUpdateRect = 0; + + private_module_t* m = (private_module_t*)module; + status = mapFrameBuffer(m); + if (status >= 0) { + int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); + int format = (m->info.bits_per_pixel == 32) + ? (m->info.red.offset ? HAL_PIXEL_FORMAT_BGRA_8888 : HAL_PIXEL_FORMAT_RGBX_8888) + : HAL_PIXEL_FORMAT_RGB_565; + const_cast(dev->device.flags) = 0; + const_cast(dev->device.width) = m->info.xres; + const_cast(dev->device.height) = m->info.yres; + const_cast(dev->device.stride) = stride; + const_cast(dev->device.format) = format; + const_cast(dev->device.xdpi) = m->xdpi; + const_cast(dev->device.ydpi) = m->ydpi; + const_cast(dev->device.fps) = m->fps; + const_cast(dev->device.minSwapInterval) = 1; + const_cast(dev->device.maxSwapInterval) = 1; + *device = &dev->device.common; + } + } + return status; +} diff --git a/gralloc/gr.h b/gralloc/gr.h new file mode 100644 index 0000000..e546fa9 --- /dev/null +++ b/gralloc/gr.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GR_H_ +#define GR_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include + +/*****************************************************************************/ + +struct private_module_t; +struct private_handle_t; + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif +inline size_t roundUpToPageSize(size_t x) { + return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); +} + +int mapFrameBufferLocked(struct private_module_t* module); +int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd); +int mapBuffer(gralloc_module_t const* module, private_handle_t* hnd); + +/*****************************************************************************/ + +class Locker { + pthread_mutex_t mutex; +public: + class Autolock { + Locker& locker; + public: + inline explicit Autolock(Locker& locker) : locker(locker) { locker.lock(); } + inline ~Autolock() { locker.unlock(); } + }; + inline Locker() { pthread_mutex_init(&mutex, 0); } + inline ~Locker() { pthread_mutex_destroy(&mutex); } + inline void lock() { pthread_mutex_lock(&mutex); } + inline void unlock() { pthread_mutex_unlock(&mutex); } +}; + +#endif /* GR_H_ */ diff --git a/gralloc/gralloc.cpp b/gralloc/gralloc.cpp new file mode 100644 index 0000000..68fb249 --- /dev/null +++ b/gralloc/gralloc.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "gralloc_priv.h" +#include "gr.h" + +/*****************************************************************************/ + +struct gralloc_context_t { + alloc_device_t device; + /* our private data here */ +}; + +static int gralloc_alloc_buffer(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle); + +/*****************************************************************************/ + +int fb_device_open(const hw_module_t* module, const char* name, + hw_device_t** device); + +static int gralloc_device_open(const hw_module_t* module, const char* name, + hw_device_t** device); + +extern int gralloc_lock(gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + void** vaddr); + +extern int gralloc_unlock(gralloc_module_t const* module, + buffer_handle_t handle); + +extern int gralloc_register_buffer(gralloc_module_t const* module, + buffer_handle_t handle); + +extern int gralloc_unregister_buffer(gralloc_module_t const* module, + buffer_handle_t handle); + +/*****************************************************************************/ + +static struct hw_module_methods_t gralloc_module_methods = { + .open = gralloc_device_open +}; + +struct private_module_t HAL_MODULE_INFO_SYM = { + .base = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = GRALLOC_HARDWARE_MODULE_ID, + .name = "Graphics Memory Allocator Module", + .author = "The Android Open Source Project", + .methods = &gralloc_module_methods + }, + .registerBuffer = gralloc_register_buffer, + .unregisterBuffer = gralloc_unregister_buffer, + .lock = gralloc_lock, + .unlock = gralloc_unlock, + }, + .framebuffer = 0, + .flags = 0, + .numBuffers = 0, + .bufferMask = 0, + .lock = PTHREAD_MUTEX_INITIALIZER, + .currentBuffer = 0, +}; + +/*****************************************************************************/ + +static int gralloc_alloc_buffer(alloc_device_t* dev, + size_t size, int /*usage*/, buffer_handle_t* pHandle) +{ + int err = 0; + int fd = -1; + + size = roundUpToPageSize(size); + + fd = ashmem_create_region("gralloc-buffer", size); + if (fd < 0) { + ALOGE("couldn't create ashmem (%s)", strerror(-errno)); + err = -errno; + } + + if (err == 0) { + private_handle_t* hnd = new private_handle_t(fd, size, 0); + gralloc_module_t* module = reinterpret_cast( + dev->common.module); + err = mapBuffer(module, hnd); + if (err == 0) { + *pHandle = hnd; + } + } + + ALOGE_IF(err, "gralloc failed err=%s", strerror(-err)); + + return err; +} + +/*****************************************************************************/ + +inline size_t align(size_t value, size_t alignment) +{ + return ((value + alignment - 1) / alignment) * alignment; +} + +static int gralloc_alloc(alloc_device_t* dev, + int width, int height, int format, int usage, + buffer_handle_t* pHandle, int* pStride) +{ + if (!pHandle || !pStride) + return -EINVAL; + + int bytesPerPixel = 0; + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_FP16: + bytesPerPixel = 8; + break; + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + bytesPerPixel = 4; + break; + case HAL_PIXEL_FORMAT_RGB_888: + bytesPerPixel = 3; + break; + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RAW16: + case HAL_PIXEL_FORMAT_YV12: + bytesPerPixel = 2; + break; + default: + return -EINVAL; + } + + const size_t tileWidth = 2; + const size_t tileHeight = 2; + + size_t stride = align(width, tileWidth); + size_t size = align(height, tileHeight) * stride * bytesPerPixel + 4; + + int err = gralloc_alloc_buffer(dev, size, usage, pHandle); + if (err < 0) { + return err; + } + + *pStride = stride; + return 0; +} + +static int gralloc_free(alloc_device_t* dev, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t const* hnd = reinterpret_cast(handle); + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + // free this buffer + private_module_t* m = reinterpret_cast( + dev->common.module); + const size_t bufferSize = m->finfo.line_length * m->info.yres; + int index = (hnd->base - m->framebuffer->base) / bufferSize; + m->bufferMask &= ~(1<( + dev->common.module); + terminateBuffer(module, const_cast(hnd)); + } + + close(hnd->fd); + delete hnd; + return 0; +} + +/*****************************************************************************/ + +static int gralloc_close(struct hw_device_t *dev) +{ + gralloc_context_t* ctx = reinterpret_cast(dev); + if (ctx) { + /* TODO: keep a list of all buffer_handle_t created, and free them + * all here. + */ + free(ctx); + } + return 0; +} + +int gralloc_device_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + int status = -EINVAL; + if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { + gralloc_context_t *dev; + dev = (gralloc_context_t*)malloc(sizeof(*dev)); + + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = 0; + dev->device.common.module = const_cast(module); + dev->device.common.close = gralloc_close; + + dev->device.alloc = gralloc_alloc; + dev->device.free = gralloc_free; + + *device = &dev->device.common; + status = 0; + } else { + status = fb_device_open(module, name, device); + } + return status; +} diff --git a/gralloc/gralloc_priv.h b/gralloc/gralloc_priv.h new file mode 100644 index 0000000..2cd1007 --- /dev/null +++ b/gralloc/gralloc_priv.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GRALLOC_PRIV_H_ +#define GRALLOC_PRIV_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +/*****************************************************************************/ + +struct private_module_t; +struct private_handle_t; + +struct private_module_t { + gralloc_module_t base; + + private_handle_t* framebuffer; + uint32_t flags; + uint32_t numBuffers; + uint32_t bufferMask; + pthread_mutex_t lock; + buffer_handle_t currentBuffer; + int pmem_master; + void* pmem_master_base; + + struct fb_var_screeninfo info; + struct fb_fix_screeninfo finfo; + float xdpi; + float ydpi; + float fps; +}; + +/*****************************************************************************/ + +#ifdef __cplusplus +struct private_handle_t : public native_handle { +#else +struct private_handle_t { + struct native_handle nativeHandle; +#endif + + enum { + PRIV_FLAGS_FRAMEBUFFER = 0x00000001 + }; + + // file-descriptors + int fd; + // ints + int magic; + int flags; + int size; + int offset; + + // FIXME: the attributes below should be out-of-line + uint64_t base __attribute__((aligned(8))); + int pid; + +#ifdef __cplusplus + static inline int sNumInts() { + return (((sizeof(private_handle_t) - sizeof(native_handle_t))/sizeof(int)) - sNumFds); + } + static const int sNumFds = 1; + static const int sMagic = 0x3141592; + + private_handle_t(int fd, int size, int flags) : + fd(fd), magic(sMagic), flags(flags), size(size), offset(0), + base(0), pid(getpid()) + { + version = sizeof(native_handle); + numInts = sNumInts(); + numFds = sNumFds; + } + ~private_handle_t() { + magic = 0; + } + + static int validate(const native_handle* h) { + const private_handle_t* hnd = (const private_handle_t*)h; + if (!h || h->version != sizeof(native_handle) || + h->numInts != sNumInts() || h->numFds != sNumFds || + hnd->magic != sMagic) + { + ALOGE("invalid gralloc handle (at %p)", h); + return -EINVAL; + } + return 0; + } +#endif +}; + +#endif /* GRALLOC_PRIV_H_ */ diff --git a/gralloc/mapper.cpp b/gralloc/mapper.cpp new file mode 100644 index 0000000..ee3e40e --- /dev/null +++ b/gralloc/mapper.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "gralloc_priv.h" + + +/*****************************************************************************/ + +static int gralloc_map(gralloc_module_t const* /*module*/, + buffer_handle_t handle, + void** vaddr) +{ + private_handle_t* hnd = (private_handle_t*)handle; + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + size_t size = hnd->size; + void* mappedAddress = mmap(0, size, + PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); + if (mappedAddress == MAP_FAILED) { + ALOGE("Could not mmap %s", strerror(errno)); + return -errno; + } + hnd->base = uintptr_t(mappedAddress) + hnd->offset; + //ALOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", + // hnd->fd, hnd->offset, hnd->size, mappedAddress); + } + *vaddr = (void*)hnd->base; + return 0; +} + +static int gralloc_unmap(gralloc_module_t const* /*module*/, + buffer_handle_t handle) +{ + private_handle_t* hnd = (private_handle_t*)handle; + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + void* base = (void*)hnd->base; + size_t size = hnd->size; + //ALOGD("unmapping from %p, size=%d", base, size); + if (munmap(base, size) < 0) { + ALOGE("Could not unmap %s", strerror(errno)); + } + } + hnd->base = 0; + return 0; +} + +/*****************************************************************************/ + +int gralloc_register_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + // *** WARNING WARNING WARNING *** + // + // If a buffer handle is passed from the process that allocated it to a + // different process, and then back to the allocator process, we will + // create a second mapping of the buffer. If the process reads and writes + // through both mappings, normal memory ordering guarantees may be + // violated, depending on the processor cache implementation*. + // + // If you are deriving a new gralloc implementation from this code, don't + // do this. A "real" gralloc should provide a single reference-counted + // mapping for each buffer in a process. + // + // In the current system, there is one case that needs a buffer to be + // registered in the same process that allocated it. The SurfaceFlinger + // process acts as the IGraphicBufferAlloc Binder provider, so all gralloc + // allocations happen in its process. After returning the buffer handle to + // the IGraphicBufferAlloc client, SurfaceFlinger free's its handle to the + // buffer (unmapping it from the SurfaceFlinger process). If + // SurfaceFlinger later acts as the producer end of the buffer queue the + // buffer belongs to, it will get a new handle to the buffer in response + // to IGraphicBufferProducer::requestBuffer(). Like any buffer handle + // received through Binder, the SurfaceFlinger process will register it. + // Since it already freed its original handle, it will only end up with + // one mapping to the buffer and there will be no problem. + // + // Currently SurfaceFlinger only acts as a buffer producer for a remote + // consumer when taking screenshots and when using virtual displays. + // + // Eventually, each application should be allowed to make its own gralloc + // allocations, solving the problem. Also, this ashmem-based gralloc + // should go away, replaced with a real ion-based gralloc. + // + // * Specifically, associative virtually-indexed caches are likely to have + // problems. Most modern L1 caches fit that description. + + private_handle_t* hnd = (private_handle_t*)handle; + ALOGD_IF(hnd->pid == getpid(), + "Registering a buffer in the process that created it. " + "This may cause memory ordering problems."); + + void *vaddr; + return gralloc_map(module, handle, &vaddr); +} + +int gralloc_unregister_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t* hnd = (private_handle_t*)handle; + if (hnd->base) + gralloc_unmap(module, handle); + + return 0; +} + +int mapBuffer(gralloc_module_t const* module, + private_handle_t* hnd) +{ + void* vaddr; + return gralloc_map(module, hnd, &vaddr); +} + +int terminateBuffer(gralloc_module_t const* module, + private_handle_t* hnd) +{ + if (hnd->base) { + // this buffer was mapped, unmap it now + gralloc_unmap(module, hnd); + } + + return 0; +} + +int gralloc_lock(gralloc_module_t const* /*module*/, + buffer_handle_t handle, int /*usage*/, + int /*l*/, int /*t*/, int /*w*/, int /*h*/, + void** vaddr) +{ + // this is called when a buffer is being locked for software + // access. in thin implementation we have nothing to do since + // not synchronization with the h/w is needed. + // typically this is used to wait for the h/w to finish with + // this buffer if relevant. the data cache may need to be + // flushed or invalidated depending on the usage bits and the + // hardware. + + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t* hnd = (private_handle_t*)handle; + *vaddr = (void*)hnd->base; + return 0; +} + +int gralloc_unlock(gralloc_module_t const* /*module*/, + buffer_handle_t handle) +{ + // we're done with a software buffer. nothing to do in this + // implementation. typically this is used to flush the data cache. + + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + return 0; +} diff --git a/ipconfigstore/Android.bp b/ipconfigstore/Android.bp new file mode 100644 index 0000000..34ed932 --- /dev/null +++ b/ipconfigstore/Android.bp @@ -0,0 +1,8 @@ +cc_binary { + name: "ipconfigstore", + srcs: ["*.cc"], + cflags: ["-Wall", "-Werror"], + shared_libs: ["libbase"], + vendor: true, +} + diff --git a/ipconfigstore/data.cc b/ipconfigstore/data.cc new file mode 100644 index 0000000..b87e770 --- /dev/null +++ b/ipconfigstore/data.cc @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +#include "data.h" + +uint16_t convertBigEndianUInt16(uint16_t value) +{ + union { uint16_t value; unsigned char data[2]; } aux = { 0x4142 }; + + if (aux.data[0] == 0x41) + { + return value; + } + + aux.data[0] = (value >> 8) & 0xff; + aux.data[1] = value & 0xff; + + return aux.value; +} + +uint32_t convertBigEndianUInt32(uint32_t value) +{ + union { uint32_t value; unsigned char data[4]; } aux = { 0x41424344 }; + + if (aux.data[0] == 0x41) + { + return value; + } + + aux.data[0] = (value >> 24) & 0xff; + aux.data[1] = (value >> 16) & 0xff; + aux.data[2] = (value >> 8) & 0xff; + aux.data[3] = value & 0xff; + + return aux.value; +} + +bool writePackedString(const std::string& str, FILE *stream) +{ + const char *string = str.c_str(); + size_t stringLength = strlen(string); + + if (!writePackedUInt16(stringLength, stream)) + { + return false; + } + + return fwrite(string, stringLength, 1, stream) == 1; +} + +bool writePackedUInt16(uint16_t value, FILE *stream) +{ + uint16_t buffer = convertBigEndianUInt16(value); + return fwrite(&buffer, sizeof buffer, 1, stream) == 1; +} + +bool writePackedUInt32(uint32_t value, FILE *stream) +{ + uint32_t buffer = convertBigEndianUInt32(value); + return fwrite(&buffer, sizeof buffer, 1, stream) == 1; +} + diff --git a/ipconfigstore/data.h b/ipconfigstore/data.h new file mode 100644 index 0000000..12c3a1a --- /dev/null +++ b/ipconfigstore/data.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +#include + +uint16_t convertBigEndianUInt16(uint16_t value); +uint32_t convertBigEndianUInt32(uint32_t value); + +bool writePackedString(const std::string& str, FILE *stream); +bool writePackedUInt16(uint16_t value, FILE *stream); +bool writePackedUInt32(uint32_t value, FILE *stream); diff --git a/ipconfigstore/main.cc b/ipconfigstore/main.cc new file mode 100644 index 0000000..f5f2e0f --- /dev/null +++ b/ipconfigstore/main.cc @@ -0,0 +1,165 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "data.h" + +using namespace android::base; + +struct ipconfig { + uint32_t mask; + char ipv4[16]; + char gateway[16]; +}; + +static int get_gateway(char *dev, char *ret) { + FILE *fp; + char buf[256]; // 128 is enough for linux + char iface[16]; + unsigned long dest_addr, gate_addr; + fp = fopen("/proc/net/route", "r"); + if (fp == NULL) return -1; + /* Skip title line */ + fgets(buf, sizeof(buf), fp); + while (fgets(buf, sizeof(buf), fp)) { + if (sscanf(buf, "%s\t%lX\t%lX", iface, &dest_addr, &gate_addr) != 3 || dest_addr != 0 || strcmp(dev, iface)) continue; + inet_ntop(AF_INET, &gate_addr, ret, INET_ADDRSTRLEN); + break; + } + + fclose(fp); + return 0; +} + +static int bitcount(uint32_t n) +{ + int count=0; + while (n) { + count++; + n &= (n - 1); + } + return count; +} + +static int get_conf(struct ipconfig *conf) { + struct ifaddrs *ifAddrStruct; + void *tmpAddrPtr=NULL; + getifaddrs(&ifAddrStruct); + while (ifAddrStruct != NULL) { + if (ifAddrStruct->ifa_addr->sa_family==AF_INET && !strcmp("eth0", ifAddrStruct->ifa_name)) { + tmpAddrPtr=&((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr; + inet_ntop(AF_INET, tmpAddrPtr, conf->ipv4, INET_ADDRSTRLEN); + conf->mask = bitcount(((struct sockaddr_in *)ifAddrStruct->ifa_netmask)->sin_addr.s_addr); + break; + } + ifAddrStruct=ifAddrStruct->ifa_next; + } + freeifaddrs(ifAddrStruct); + get_gateway((char *) "eth0", conf->gateway); + return 0; +} + +static void write_dns(FILE *fp) { + std::set dnsList; + auto ndns = GetIntProperty("ro.boot.redroid_net_ndns", 0); + for (int i = 1; i <= ndns; ++i) { + dnsList.insert(GetProperty("ro.boot.redroid_net_dns" + std::to_string(i), "")); + } + if (dnsList.empty()) dnsList.insert("8.8.8.8"); + + for (auto& dns: dnsList) { + writePackedString("dns", fp); + writePackedString(dns.c_str(), fp); + } +} + +static void write_proxy(FILE *fp) { + // static | pac | none | unassigned + std::string proxy_type = GetProperty("ro.boot.redroid_net_proxy_type", ""); + if ("static" == proxy_type) { + writePackedString("proxySettings", fp); + writePackedString("STATIC", fp); + + writePackedString("proxyHost", fp); + writePackedString(GetProperty("ro.boot.redroid_net_proxy_host", "").c_str(), fp); + + writePackedString("proxyPort", fp); + writePackedUInt32(GetIntProperty("ro.boot.redroid_net_proxy_port", 3128), fp); + + writePackedString("exclusionList", fp); + writePackedString(GetProperty("ro.boot.redroid_net_proxy_exclude_list", "").c_str(), fp); + } else if ("pac" == proxy_type) { + writePackedString("proxySettings", fp); + writePackedString("PAC", fp); + + writePackedString("proxyPac", fp); + writePackedString(GetProperty("ro.boot.redroid_net_proxy_pac", "").c_str(), fp); + } else if ("none" == proxy_type) { + writePackedString("proxySettings", fp); + writePackedString("NONE", fp); + } else { + // ignored + } +} + +static int write_conf(struct ipconfig *conf, uint32_t v) { + FILE *fp = fopen("/data/misc/ethernet/ipconfig.txt", "w+"); + + writePackedUInt32(v, fp); // version + + writePackedString("ipAssignment", fp); + writePackedString("STATIC", fp); + + writePackedString("linkAddress", fp); + writePackedString(conf->ipv4, fp); + writePackedUInt32(conf->mask, fp); + + writePackedString("gateway", fp); + writePackedUInt32(1, fp); // Default route (dest). + writePackedString("0.0.0.0", fp); + writePackedUInt32(0, fp); + writePackedUInt32(1, fp); // Have a gateway. + writePackedString(conf->gateway, fp); + + write_dns(fp); + + write_proxy(fp); + + writePackedString("id", fp); + if (v == 2) writePackedUInt32(0, fp); + else writePackedString("eth0", fp); + + writePackedString("eos", fp); + + fclose(fp); + return 0; +} + +int main(int argc, char **argv) { + (void)argc; + (void)argv; + + uint32_t v = 3; + // use V2 for Android 8.1 + if (GetIntProperty("ro.build.version.sdk", 0) <= 27) v = 2; + + struct ipconfig conf; + get_conf(&conf); + printf("ipconfig: ipv4: %s, mask: %i, gateway: %s", conf.ipv4, conf.mask, conf.gateway); + write_conf(&conf, v); + return 0; +} + diff --git a/post-fs-data.redroid.sh b/post-fs-data.redroid.sh new file mode 100644 index 0000000..67cd1b4 --- /dev/null +++ b/post-fs-data.redroid.sh @@ -0,0 +1,5 @@ +#!/system/bin/sh + +## enable `memfd` if `ashmem` missing +## memfd is disabled in post-fs-data (init.rc) +[ -c /dev/ashmem ] || setprop sys.use_memfd 1 diff --git a/redroid.common.rc b/redroid.common.rc new file mode 100644 index 0000000..c76da2b --- /dev/null +++ b/redroid.common.rc @@ -0,0 +1,89 @@ +on early-init + mount debugfs debugfs /sys/kernel/debug mode=755 + + # ueventd fix + chmod 0666 /dev/null + chmod 0666 /dev/zero + chmod 0666 /dev/full + chmod 0666 /dev/ptmx + chmod 0666 /dev/pts/ptmx + chmod 0666 /dev/tty + chmod 0666 /dev/random + chmod 0666 /dev/urandom + chmod 0666 /dev/ashmem + chmod 0666 /dev/ion + + chmod 0444 /dev/dma_heap/system + chown system system /dev/dma_heap/system + + # used to place domain sockets + mkdir /ipc 0777 + + exec -- /bin/rm -rf /dev/input + # inputflinger require this dir + mkdir /dev/input + + # disable codec2 by default, DMA Heap required + setprop debug.stagefright.ccodec 0 + + # disable some verbose logs + setprop log.tag.libprocessgroup F + + # assume GLES 3.2 supported + setprop ro.opengles.version 196610 + +# setup overlay data partition +on early-init && property:ro.boot.use_redroid_overlayfs=1 + trigger use_redroid_overlayfs + + +on use_redroid_overlayfs + mkdir /data-diff/upper + rmdir /data-diff/work + mkdir /data-diff/work + mount overlay overlay /data lowerdir=/data-base,upperdir=/data-diff/upper,workdir=/data-diff/work + + +on early-init && property:ro.boot.redroid_dpi=* + setprop ro.sf.lcd_density ${ro.boot.redroid_dpi} + + +on property:ro.zygote=zygote64_32 + write /proc/sys/kernel/pid_max 65535 + + +# use memfd (ashmem removed in 5.18), memfd is disabled in post-fs-data (init.rc) +on post-fs-data && property:ro.boot.use_memfd=* + setprop sys.use_memfd ${ro.boot.use_memfd} + + +on init + # lxcfs better + write /data/.empty 0 + mount none /data/.empty /proc/vmallocinfo bind + + # fix suspend host system? + mount none /data/.empty /sys/power/state bind + + setprop debug.renderengine.backend gles + + # set dpi if missing + setprop ro.sf.lcd_density 320 + + +on post-fs-data + # fix for static IP, must after post-fs-data and before netd + # rm apex config (use legacy path) + rm /data/misc/apexdata/com.android.tethering/misc/ethernet/ipconfig.txt + exec - system system -- /vendor/bin/ipconfigstore + + # no need to mount, and encryption not supported yet + trigger nonencrypted + + exec -- /vendor/bin/post-fs-data.redroid.sh + + +on early-boot + + # before HAL / SurfaceFlinger + exec -- /vendor/bin/gpu_config.sh diff --git a/redroid.legacy.rc b/redroid.legacy.rc new file mode 100644 index 0000000..a6d641f --- /dev/null +++ b/redroid.legacy.rc @@ -0,0 +1,47 @@ +# convert legacy props + +# overlay data +on early-init && property:ro.kernel.redroid.overlay=1 + trigger use_redroid_overlayfs + + +# display +on early-init && property:ro.kernel.redroid.width=* + setprop ro.boot.redroid_width ${ro.kernel.redroid.width} + +on early-init && property:ro.kernel.redroid.height=* + setprop ro.boot.redroid_height ${ro.kernel.redroid.height} + +on early-init && property:ro.kernel.redroid.fps=* + setprop ro.boot.redroid_fps ${ro.kernel.redroid.fps} + + +# DNS +on early-init && property:ro.kernel.net.eth0.dns1=* + setprop ro.boot.redroid_net_ndns 1 + setprop ro.boot.redroid_net_dns1 ${ro.kernel.net.eth0.dns1} + + +# network proxy +on early-init && property:ro.kernel.net.eth0.proxy.type=* + setprop ro.boot.redroid_net_proxy_type ${ro.kernel.net.eth0.proxy.type} + +on early-init && property:ro.kernel.net.eth0.proxy.host=* + setprop ro.boot.redroid_net_proxy_host ${ro.kernel.net.eth0.proxy.host} + +on early-init && property:ro.kernel.net.eth0.proxy.port=* + setprop ro.boot.redroid_net_proxy_port ${ro.kernel.net.eth0.proxy.port} + +on early-init && property:ro.kernel.net.eth0.proxy.exclusionList=* + setprop ro.boot.redroid_net_proxy_exclude ${ro.kernel.net.eth0.proxy.exclusionList} + +on early-init && property:ro.kernel.net.eth0.proxy.pac=* + setprop ro.boot.redroid_net_proxy_pac ${ro.kernel.net.eth0.proxy.pac} + + +# GPU +on early-init && property:ro.kernel.redroid.gpu.mode=* + setprop ro.boot.redroid_gpu_mode ${ro.kernel.redroid.gpu.mode} + +on early-init && property:ro.kernel.redroid.gpu.node=* + setprop ro.boot.redroid_gpu_node ${ro.kernel.redroid.gpu.node} diff --git a/vendor.mk b/vendor.mk new file mode 100644 index 0000000..3b38e0c --- /dev/null +++ b/vendor.mk @@ -0,0 +1,18 @@ +# skip androidx.window.extensions check +PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true + +PRODUCT_PACKAGES += \ + binder_alloc \ + gralloc.redroid \ + ipconfigstore \ + + +PRODUCT_COPY_FILES += \ + vendor/redroid/gpu_config.sh:$(TARGET_COPY_OUT_VENDOR)/bin/gpu_config.sh \ + vendor/redroid/post-fs-data.redroid.sh:$(TARGET_COPY_OUT_VENDOR)/bin/post-fs-data.redroid.sh \ + vendor/redroid/redroid.common.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/redroid.common.rc \ + vendor/redroid/redroid.legacy.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/redroid.legacy.rc \ + + +PRODUCT_COPY_FILES += \ + frameworks/native/data/etc/android.hardware.touchscreen.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.touchscreen.xml \