├── .dockerignore ├── .gitignore ├── Android.mk ├── README.md ├── binder_alloc ├── Android.bp └── main.cpp ├── gpu_config.sh ├── gralloc ├── Android.bp ├── framebuffer.cpp ├── gr.h ├── gralloc.cpp ├── gralloc_priv.h └── mapper.cpp ├── ipconfigstore ├── Android.bp ├── data.cc ├── data.h └── main.cc ├── post-fs-data.redroid.sh ├── redroid.common.rc ├── redroid.legacy.rc └── vendor.mk /.dockerignore: -------------------------------------------------------------------------------- 1 | ** 2 | 3 | !/root/** 4 | !/system/** 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/C,C++,Linux,macOS,vim 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=C,C++,Linux,macOS,vim 4 | 5 | ### C ### 6 | # Prerequisites 7 | *.d 8 | 9 | # Object files 10 | *.o 11 | *.ko 12 | *.obj 13 | *.elf 14 | 15 | # Linker output 16 | *.ilk 17 | *.map 18 | *.exp 19 | 20 | # Precompiled Headers 21 | *.gch 22 | *.pch 23 | 24 | # Libraries 25 | *.lib 26 | *.a 27 | *.la 28 | *.lo 29 | 30 | # Shared objects (inc. Windows DLLs) 31 | *.dll 32 | *.so 33 | *.so.* 34 | *.dylib 35 | 36 | # Executables 37 | *.exe 38 | *.out 39 | *.app 40 | *.i*86 41 | *.x86_64 42 | *.hex 43 | 44 | # Debug files 45 | *.dSYM/ 46 | *.su 47 | *.idb 48 | *.pdb 49 | 50 | # Kernel Module Compile Results 51 | *.mod* 52 | *.cmd 53 | .tmp_versions/ 54 | modules.order 55 | Module.symvers 56 | Mkfile.old 57 | dkms.conf 58 | 59 | ### C++ ### 60 | # Prerequisites 61 | 62 | # Compiled Object files 63 | *.slo 64 | 65 | # Precompiled Headers 66 | 67 | # Compiled Dynamic libraries 68 | 69 | # Fortran module files 70 | *.mod 71 | *.smod 72 | 73 | # Compiled Static libraries 74 | *.lai 75 | 76 | # Executables 77 | 78 | ### Linux ### 79 | *~ 80 | 81 | # temporary files which can be created if a process still has a handle open of a deleted file 82 | .fuse_hidden* 83 | 84 | # KDE directory preferences 85 | .directory 86 | 87 | # Linux trash folder which might appear on any partition or disk 88 | .Trash-* 89 | 90 | # .nfs files are created when an open file is removed but is still being accessed 91 | .nfs* 92 | 93 | ### macOS ### 94 | # General 95 | .DS_Store 96 | .AppleDouble 97 | .LSOverride 98 | 99 | # Icon must end with two \r 100 | Icon 101 | 102 | # Thumbnails 103 | ._* 104 | 105 | # Files that might appear in the root of a volume 106 | .DocumentRevisions-V100 107 | .fseventsd 108 | .Spotlight-V100 109 | .TemporaryItems 110 | .Trashes 111 | .VolumeIcon.icns 112 | .com.apple.timemachine.donotpresent 113 | 114 | # Directories potentially created on remote AFP share 115 | .AppleDB 116 | .AppleDesktop 117 | Network Trash Folder 118 | Temporary Items 119 | .apdisk 120 | 121 | ### Vim ### 122 | # Swap 123 | [._]*.s[a-v][a-z] 124 | !*.svg # comment out if you don't need vector files 125 | [._]*.sw[a-p] 126 | [._]s[a-rt-v][a-z] 127 | [._]ss[a-gi-z] 128 | [._]sw[a-p] 129 | 130 | # Session 131 | Session.vim 132 | Sessionx.vim 133 | 134 | # Temporary 135 | .netrwhist 136 | # Auto-generated tag files 137 | tags 138 | # Persistent undo 139 | [._]*.un~ 140 | 141 | # End of https://www.toptal.com/developers/gitignore/api/C,C++,Linux,macOS,vim 142 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | LOCAL_PATH := $(call my-dir) 18 | 19 | include $(call all-makefiles-under,$(LOCAL_PATH)) 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [ReDroid Doc](https://github.com/remote-android/redroid-doc) 2 | -------------------------------------------------------------------------------- /binder_alloc/Android.bp: -------------------------------------------------------------------------------- 1 | cc_binary { 2 | name: "binder_alloc", 3 | srcs: ["main.cpp"], 4 | cflags: ["-Wall", "-Werror"], 5 | vendor: true, 6 | } 7 | 8 | -------------------------------------------------------------------------------- /binder_alloc/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define BINDERFS_MAX_NAME 255 13 | struct binderfs_device { 14 | char name[BINDERFS_MAX_NAME + 1]; 15 | __u32 major; 16 | __u32 minor; 17 | }; 18 | #define BINDER_CTL_ADD _IOWR('b', 1, struct binderfs_device) 19 | 20 | void usage(char *bin) { 21 | printf("USAGE: %s BINDER-CONTROL-PATH DEVICE1 [DEVICE2 ...]\n", bin); 22 | printf("EXAMPLE: binder_alloc /dev/binderfs/binder-control binder hwbinder vndbinder\n"); 23 | } 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | int fd, ret; 28 | size_t len; 29 | struct binderfs_device device{}; 30 | 31 | if (argc < 3) { 32 | usage(basename(argv[0])); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | fd = open(argv[1], O_RDONLY | O_CLOEXEC); 37 | if (fd < 0) { 38 | printf("%s - Failed to open binder-control device\n", strerror(errno)); 39 | exit(EXIT_FAILURE); 40 | } 41 | 42 | char *dir = dirname(argv[1]); // "/dev/binderfs" 43 | char *pathname = (char *) malloc(strlen(dir) + BINDERFS_MAX_NAME + 2); // "/dev/binderfs/binder" 44 | 45 | for (int i = 2; i < argc; ++i) { 46 | sprintf(pathname, "%s/%s", dir, argv[i]); 47 | if (access(pathname, F_OK) != -1) { 48 | printf("binder device already allocated, path: %s\n", pathname); 49 | chmod(pathname, 0666); 50 | continue; 51 | } 52 | len = strlen(argv[i]); 53 | if (len > BINDERFS_MAX_NAME) exit(EXIT_FAILURE); 54 | 55 | memcpy(device.name, argv[i], len); 56 | device.name[len] = '\0'; 57 | 58 | ret = ioctl(fd, BINDER_CTL_ADD, &device); 59 | if (ret < 0) { 60 | printf("%s - Failed to allocate new binder device\n", 61 | strerror(errno)); 62 | exit(EXIT_FAILURE); 63 | } 64 | chmod(pathname, 0666); 65 | printf("Allocated new binder device with major %d, minor %d, and " 66 | "name %s\n", device.major, device.minor, 67 | device.name); 68 | } 69 | free(pathname); 70 | close(fd); 71 | 72 | exit(EXIT_SUCCESS); 73 | } 74 | -------------------------------------------------------------------------------- /gpu_config.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | # args: driver 4 | setup_vulkan() { 5 | echo "setup vulkan for driver: $1" 6 | case "$1" in 7 | i915) 8 | setprop ro.hardware.vulkan intel 9 | ;; 10 | amdgpu) 11 | setprop ro.hardware.vulkan radeon 12 | ;; 13 | virtio_gpu) 14 | setprop ro.hardware.vulkan virtio 15 | ;; 16 | v3d|vc4) 17 | setprop ro.hardware.vulkan broadcom 18 | ;; 19 | msm_drm) 20 | setprop ro.hardware.vulkan freedreno 21 | ;; 22 | panfrost) 23 | setprop ro.hardware.vulkan panfrost 24 | ;; 25 | *) 26 | echo "not supported driver: $1" 27 | ;; 28 | esac 29 | } 30 | 31 | setup_render_node() { 32 | node=$(getprop ro.boot.redroid_gpu_node) 33 | if [ -n "$node" ]; then 34 | echo "force render node: $node" 35 | 36 | setprop gralloc.gbm.device "$node" 37 | chmod 666 "$node" 38 | 39 | # setup vulkan 40 | driver=$(cut -d' ' -f1 "/sys/kernel/debug/dri/${node#/dev/dri/renderD}/name") 41 | setup_vulkan "$driver" 42 | return 0 43 | fi 44 | 45 | cd /sys/kernel/debug/dri || exit 46 | for d in * ; do 47 | if [ "$d" -ge "128" ]; then 48 | driver="$(cut -d' ' -f1 "$d/name")" 49 | echo "DRI node exists, driver: $driver" 50 | setup_vulkan "$driver" 51 | case $driver in 52 | i915|amdgpu|nouveau|virtio_gpu|v3d|vc4|msm_drm|panfrost) 53 | node="/dev/dri/renderD$d" 54 | echo "use render node: $node" 55 | setprop gralloc.gbm.device "$node" 56 | chmod 666 "$node" 57 | return 0 58 | ;; 59 | esac 60 | fi 61 | done 62 | 63 | echo "NO qualified render node found" 64 | return 1 65 | } 66 | 67 | gpu_setup_host() { 68 | echo "use GPU host mode" 69 | 70 | setprop ro.hardware.egl mesa 71 | setprop ro.hardware.gralloc gbm 72 | setprop ro.boot.redroid_fps 30 73 | } 74 | 75 | gpu_setup_guest() { 76 | echo "use GPU guest mode" 77 | 78 | VENDOR_EGL_DIR=/vendor/lib64/egl 79 | SYSTEM_EGL_DIR=/system/lib64 80 | EGL_ANGLE=libEGL_angle.so 81 | EGL_SS=libEGL_swiftshader.so 82 | egl= 83 | 84 | if [ -f $VENDOR_EGL_DIR/$EGL_ANGLE ] || [ -f $SYSTEM_EGL_DIR/$EGL_ANGLE ]; then 85 | egl=angle 86 | elif [ -f $VENDOR_EGL_DIR/$EGL_SS ] || [ -f $SYSTEM_EGL_DIR/$EGL_SS ]; then 87 | egl=swiftshader 88 | else 89 | echo "ERROR no SW egl found!!!" 90 | fi 91 | 92 | setprop ro.hardware.egl $egl 93 | setprop ro.hardware.gralloc redroid 94 | setprop ro.hardware.vulkan pastel 95 | } 96 | 97 | gpu_setup() { 98 | ## mode=(auto, host, guest) 99 | ## node=(/dev/dri/renderDxxx) 100 | 101 | mode=$(getprop ro.boot.redroid_gpu_mode guest) 102 | if [ "$mode" = "host" ]; then 103 | setup_render_node 104 | gpu_setup_host 105 | elif [ "$mode" = "guest" ]; then 106 | gpu_setup_guest 107 | elif [ "$mode" = "auto" ]; then 108 | echo "use GPU auto mode" 109 | if setup_render_node; then 110 | gpu_setup_host 111 | else 112 | gpu_setup_guest 113 | fi 114 | else 115 | echo "unknown mode: $mode" 116 | fi 117 | } 118 | 119 | gpu_setup 120 | 121 | -------------------------------------------------------------------------------- /gralloc/Android.bp: -------------------------------------------------------------------------------- 1 | cc_library_shared { 2 | name: "gralloc.redroid", 3 | vendor: true, 4 | 5 | srcs: [ 6 | "*.cpp", 7 | ], 8 | 9 | shared_libs: [ 10 | "liblog", 11 | "libcutils", 12 | ], 13 | 14 | header_libs: [ 15 | "libhardware_headers", 16 | ], 17 | 18 | cflags: [ 19 | "-Wall", "-Werror", 20 | "-DLOG_TAG=\"gralloc\"", 21 | ], 22 | 23 | relative_install_path: "hw", 24 | } 25 | -------------------------------------------------------------------------------- /gralloc/framebuffer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | #ifdef __ANDROID__ 33 | #include 34 | #endif 35 | 36 | #include "gralloc_priv.h" 37 | #include "gr.h" 38 | 39 | /*****************************************************************************/ 40 | 41 | // Set TARGET_USE_PAN_DISPLAY to true at compile time if the 42 | // board uses FBIOPAN_DISPLAY to setup page flipping, otherwise 43 | // default ioctl to do page-flipping is FBIOPUT_VSCREENINFO. 44 | #ifndef USE_PAN_DISPLAY 45 | #define USE_PAN_DISPLAY 0 46 | #endif 47 | 48 | // numbers of buffers for page flipping 49 | #define NUM_BUFFERS 2 50 | 51 | 52 | enum { 53 | PAGE_FLIP = 0x00000001, 54 | LOCKED = 0x00000002 55 | }; 56 | 57 | struct fb_context_t { 58 | framebuffer_device_t device; 59 | }; 60 | 61 | /*****************************************************************************/ 62 | 63 | static int fb_setSwapInterval(struct framebuffer_device_t* dev, 64 | int interval) 65 | { 66 | if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) 67 | return -EINVAL; 68 | // FIXME: implement fb_setSwapInterval 69 | return 0; 70 | } 71 | 72 | static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) 73 | { 74 | if (private_handle_t::validate(buffer) < 0) 75 | return -EINVAL; 76 | 77 | private_handle_t const* hnd = reinterpret_cast(buffer); 78 | private_module_t* m = reinterpret_cast( 79 | dev->common.module); 80 | 81 | if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { 82 | const size_t offset = hnd->base - m->framebuffer->base; 83 | m->info.activate = FB_ACTIVATE_VBL; 84 | m->info.yoffset = offset / m->finfo.line_length; 85 | if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { 86 | ALOGE("FBIOPUT_VSCREENINFO failed"); 87 | m->base.unlock(&m->base, buffer); 88 | return -errno; 89 | } 90 | m->currentBuffer = buffer; 91 | 92 | } else { 93 | // If we can't do the page_flip, just copy the buffer to the front 94 | // FIXME: use copybit HAL instead of memcpy 95 | 96 | void* fb_vaddr; 97 | void* buffer_vaddr; 98 | 99 | m->base.lock(&m->base, m->framebuffer, 100 | GRALLOC_USAGE_SW_WRITE_RARELY, 101 | 0, 0, m->info.xres, m->info.yres, 102 | &fb_vaddr); 103 | 104 | m->base.lock(&m->base, buffer, 105 | GRALLOC_USAGE_SW_READ_RARELY, 106 | 0, 0, m->info.xres, m->info.yres, 107 | &buffer_vaddr); 108 | 109 | memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); 110 | 111 | m->base.unlock(&m->base, buffer); 112 | m->base.unlock(&m->base, m->framebuffer); 113 | } 114 | 115 | return 0; 116 | } 117 | 118 | /*****************************************************************************/ 119 | 120 | int mapFrameBufferLocked(struct private_module_t* module) 121 | { 122 | // already initialized... 123 | if (module->framebuffer) { 124 | return 0; 125 | } 126 | 127 | char const * const device_template[] = { 128 | "/dev/graphics/fb%u", 129 | "/dev/fb%u", 130 | 0 }; 131 | 132 | int fd = -1; 133 | int i=0; 134 | char name[64]; 135 | 136 | while ((fd==-1) && device_template[i]) { 137 | snprintf(name, 64, device_template[i], 0); 138 | fd = open(name, O_RDWR, 0); 139 | i++; 140 | } 141 | if (fd < 0) 142 | return -errno; 143 | 144 | struct fb_fix_screeninfo finfo; 145 | if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) 146 | return -errno; 147 | 148 | struct fb_var_screeninfo info; 149 | if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) 150 | return -errno; 151 | 152 | info.reserved[0] = 0; 153 | info.reserved[1] = 0; 154 | info.reserved[2] = 0; 155 | info.xoffset = 0; 156 | info.yoffset = 0; 157 | info.activate = FB_ACTIVATE_NOW; 158 | 159 | /* 160 | * Request NUM_BUFFERS screens (at lest 2 for page flipping) 161 | */ 162 | info.yres_virtual = info.yres * NUM_BUFFERS; 163 | 164 | 165 | uint32_t flags = PAGE_FLIP; 166 | #if USE_PAN_DISPLAY 167 | if (ioctl(fd, FBIOPAN_DISPLAY, &info) == -1) { 168 | ALOGW("FBIOPAN_DISPLAY failed, page flipping not supported"); 169 | #else 170 | if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { 171 | ALOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); 172 | #endif 173 | info.yres_virtual = info.yres; 174 | flags &= ~PAGE_FLIP; 175 | } 176 | 177 | if (info.yres_virtual < info.yres * 2) { 178 | // we need at least 2 for page-flipping 179 | info.yres_virtual = info.yres; 180 | flags &= ~PAGE_FLIP; 181 | ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)", 182 | info.yres_virtual, info.yres*2); 183 | } 184 | 185 | if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) 186 | return -errno; 187 | 188 | uint64_t refreshQuotient = 189 | ( 190 | uint64_t( info.upper_margin + info.lower_margin + info.yres ) 191 | * ( info.left_margin + info.right_margin + info.xres ) 192 | * info.pixclock 193 | ); 194 | 195 | /* Beware, info.pixclock might be 0 under emulation, so avoid a 196 | * division-by-0 here (SIGFPE on ARM) */ 197 | int refreshRate = refreshQuotient > 0 ? (int)(1000000000000000LLU / refreshQuotient) : 0; 198 | 199 | if (refreshRate == 0) { 200 | // bleagh, bad info from the driver 201 | refreshRate = 60*1000; // 60 Hz 202 | } 203 | 204 | if (int(info.width) <= 0 || int(info.height) <= 0) { 205 | // the driver doesn't return that information 206 | // default to 160 dpi 207 | info.width = ((info.xres * 25.4f)/160.0f + 0.5f); 208 | info.height = ((info.yres * 25.4f)/160.0f + 0.5f); 209 | } 210 | 211 | float xdpi = (info.xres * 25.4f) / info.width; 212 | float ydpi = (info.yres * 25.4f) / info.height; 213 | float fps = refreshRate / 1000.0f; 214 | 215 | ALOGI( "using (fd=%d)\n" 216 | "id = %s\n" 217 | "xres = %d px\n" 218 | "yres = %d px\n" 219 | "xres_virtual = %d px\n" 220 | "yres_virtual = %d px\n" 221 | "bpp = %d\n" 222 | "r = %2u:%u\n" 223 | "g = %2u:%u\n" 224 | "b = %2u:%u\n", 225 | fd, 226 | finfo.id, 227 | info.xres, 228 | info.yres, 229 | info.xres_virtual, 230 | info.yres_virtual, 231 | info.bits_per_pixel, 232 | info.red.offset, info.red.length, 233 | info.green.offset, info.green.length, 234 | info.blue.offset, info.blue.length 235 | ); 236 | 237 | ALOGI( "width = %d mm (%f dpi)\n" 238 | "height = %d mm (%f dpi)\n" 239 | "refresh rate = %.2f Hz\n", 240 | info.width, xdpi, 241 | info.height, ydpi, 242 | fps 243 | ); 244 | 245 | 246 | if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) 247 | return -errno; 248 | 249 | if (finfo.smem_len <= 0) 250 | return -errno; 251 | 252 | 253 | module->flags = flags; 254 | module->info = info; 255 | module->finfo = finfo; 256 | module->xdpi = xdpi; 257 | module->ydpi = ydpi; 258 | module->fps = fps; 259 | 260 | /* 261 | * map the framebuffer 262 | */ 263 | 264 | size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual); 265 | module->framebuffer = new private_handle_t(dup(fd), fbSize, 0); 266 | 267 | module->numBuffers = info.yres_virtual / info.yres; 268 | module->bufferMask = 0; 269 | 270 | void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 271 | if (vaddr == MAP_FAILED) { 272 | ALOGE("Error mapping the framebuffer (%s)", strerror(errno)); 273 | return -errno; 274 | } 275 | module->framebuffer->base = intptr_t(vaddr); 276 | memset(vaddr, 0, fbSize); 277 | return 0; 278 | } 279 | 280 | static int mapFrameBuffer(struct private_module_t* module) 281 | { 282 | pthread_mutex_lock(&module->lock); 283 | int err = mapFrameBufferLocked(module); 284 | pthread_mutex_unlock(&module->lock); 285 | return err; 286 | } 287 | 288 | /*****************************************************************************/ 289 | 290 | static int fb_close(struct hw_device_t *dev) 291 | { 292 | fb_context_t* ctx = (fb_context_t*)dev; 293 | if (ctx) { 294 | free(ctx); 295 | } 296 | return 0; 297 | } 298 | 299 | int fb_device_open(hw_module_t const* module, const char* name, 300 | hw_device_t** device) 301 | { 302 | int status = -EINVAL; 303 | if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { 304 | /* initialize our state here */ 305 | fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev)); 306 | memset(dev, 0, sizeof(*dev)); 307 | 308 | /* initialize the procs */ 309 | dev->device.common.tag = HARDWARE_DEVICE_TAG; 310 | dev->device.common.version = 0; 311 | dev->device.common.module = const_cast(module); 312 | dev->device.common.close = fb_close; 313 | dev->device.setSwapInterval = fb_setSwapInterval; 314 | dev->device.post = fb_post; 315 | dev->device.setUpdateRect = 0; 316 | 317 | private_module_t* m = (private_module_t*)module; 318 | status = mapFrameBuffer(m); 319 | if (status >= 0) { 320 | int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); 321 | int format = (m->info.bits_per_pixel == 32) 322 | ? (m->info.red.offset ? HAL_PIXEL_FORMAT_BGRA_8888 : HAL_PIXEL_FORMAT_RGBX_8888) 323 | : HAL_PIXEL_FORMAT_RGB_565; 324 | const_cast(dev->device.flags) = 0; 325 | const_cast(dev->device.width) = m->info.xres; 326 | const_cast(dev->device.height) = m->info.yres; 327 | const_cast(dev->device.stride) = stride; 328 | const_cast(dev->device.format) = format; 329 | const_cast(dev->device.xdpi) = m->xdpi; 330 | const_cast(dev->device.ydpi) = m->ydpi; 331 | const_cast(dev->device.fps) = m->fps; 332 | const_cast(dev->device.minSwapInterval) = 1; 333 | const_cast(dev->device.maxSwapInterval) = 1; 334 | *device = &dev->device.common; 335 | } 336 | } 337 | return status; 338 | } 339 | -------------------------------------------------------------------------------- /gralloc/gr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef GR_H_ 18 | #define GR_H_ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | /*****************************************************************************/ 31 | 32 | struct private_module_t; 33 | struct private_handle_t; 34 | 35 | #ifndef PAGE_SIZE 36 | #define PAGE_SIZE 4096 37 | #endif 38 | inline size_t roundUpToPageSize(size_t x) { 39 | return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); 40 | } 41 | 42 | int mapFrameBufferLocked(struct private_module_t* module); 43 | int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd); 44 | int mapBuffer(gralloc_module_t const* module, private_handle_t* hnd); 45 | 46 | /*****************************************************************************/ 47 | 48 | class Locker { 49 | pthread_mutex_t mutex; 50 | public: 51 | class Autolock { 52 | Locker& locker; 53 | public: 54 | inline explicit Autolock(Locker& locker) : locker(locker) { locker.lock(); } 55 | inline ~Autolock() { locker.unlock(); } 56 | }; 57 | inline Locker() { pthread_mutex_init(&mutex, 0); } 58 | inline ~Locker() { pthread_mutex_destroy(&mutex); } 59 | inline void lock() { pthread_mutex_lock(&mutex); } 60 | inline void unlock() { pthread_mutex_unlock(&mutex); } 61 | }; 62 | 63 | #endif /* GR_H_ */ 64 | -------------------------------------------------------------------------------- /gralloc/gralloc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | #include "gralloc_priv.h" 37 | #include "gr.h" 38 | 39 | /*****************************************************************************/ 40 | 41 | struct gralloc_context_t { 42 | alloc_device_t device; 43 | /* our private data here */ 44 | }; 45 | 46 | static int gralloc_alloc_buffer(alloc_device_t* dev, 47 | size_t size, int usage, buffer_handle_t* pHandle); 48 | 49 | /*****************************************************************************/ 50 | 51 | int fb_device_open(const hw_module_t* module, const char* name, 52 | hw_device_t** device); 53 | 54 | static int gralloc_device_open(const hw_module_t* module, const char* name, 55 | hw_device_t** device); 56 | 57 | extern int gralloc_lock(gralloc_module_t const* module, 58 | buffer_handle_t handle, int usage, 59 | int l, int t, int w, int h, 60 | void** vaddr); 61 | 62 | extern int gralloc_unlock(gralloc_module_t const* module, 63 | buffer_handle_t handle); 64 | 65 | extern int gralloc_register_buffer(gralloc_module_t const* module, 66 | buffer_handle_t handle); 67 | 68 | extern int gralloc_unregister_buffer(gralloc_module_t const* module, 69 | buffer_handle_t handle); 70 | 71 | /*****************************************************************************/ 72 | 73 | static struct hw_module_methods_t gralloc_module_methods = { 74 | .open = gralloc_device_open 75 | }; 76 | 77 | struct private_module_t HAL_MODULE_INFO_SYM = { 78 | .base = { 79 | .common = { 80 | .tag = HARDWARE_MODULE_TAG, 81 | .version_major = 1, 82 | .version_minor = 0, 83 | .id = GRALLOC_HARDWARE_MODULE_ID, 84 | .name = "Graphics Memory Allocator Module", 85 | .author = "The Android Open Source Project", 86 | .methods = &gralloc_module_methods 87 | }, 88 | .registerBuffer = gralloc_register_buffer, 89 | .unregisterBuffer = gralloc_unregister_buffer, 90 | .lock = gralloc_lock, 91 | .unlock = gralloc_unlock, 92 | }, 93 | .framebuffer = 0, 94 | .flags = 0, 95 | .numBuffers = 0, 96 | .bufferMask = 0, 97 | .lock = PTHREAD_MUTEX_INITIALIZER, 98 | .currentBuffer = 0, 99 | }; 100 | 101 | /*****************************************************************************/ 102 | 103 | static int gralloc_alloc_buffer(alloc_device_t* dev, 104 | size_t size, int /*usage*/, buffer_handle_t* pHandle) 105 | { 106 | int err = 0; 107 | int fd = -1; 108 | 109 | size = roundUpToPageSize(size); 110 | 111 | fd = ashmem_create_region("gralloc-buffer", size); 112 | if (fd < 0) { 113 | ALOGE("couldn't create ashmem (%s)", strerror(-errno)); 114 | err = -errno; 115 | } 116 | 117 | if (err == 0) { 118 | private_handle_t* hnd = new private_handle_t(fd, size, 0); 119 | gralloc_module_t* module = reinterpret_cast( 120 | dev->common.module); 121 | err = mapBuffer(module, hnd); 122 | if (err == 0) { 123 | *pHandle = hnd; 124 | } 125 | } 126 | 127 | ALOGE_IF(err, "gralloc failed err=%s", strerror(-err)); 128 | 129 | return err; 130 | } 131 | 132 | /*****************************************************************************/ 133 | 134 | inline size_t align(size_t value, size_t alignment) 135 | { 136 | return ((value + alignment - 1) / alignment) * alignment; 137 | } 138 | 139 | static int gralloc_alloc(alloc_device_t* dev, 140 | int width, int height, int format, int usage, 141 | buffer_handle_t* pHandle, int* pStride) 142 | { 143 | if (!pHandle || !pStride) 144 | return -EINVAL; 145 | 146 | int bytesPerPixel = 0; 147 | switch (format) { 148 | case HAL_PIXEL_FORMAT_RGBA_FP16: 149 | bytesPerPixel = 8; 150 | break; 151 | case HAL_PIXEL_FORMAT_RGBA_8888: 152 | case HAL_PIXEL_FORMAT_RGBX_8888: 153 | case HAL_PIXEL_FORMAT_BGRA_8888: 154 | bytesPerPixel = 4; 155 | break; 156 | case HAL_PIXEL_FORMAT_RGB_888: 157 | bytesPerPixel = 3; 158 | break; 159 | case HAL_PIXEL_FORMAT_RGB_565: 160 | case HAL_PIXEL_FORMAT_RAW16: 161 | case HAL_PIXEL_FORMAT_YV12: 162 | bytesPerPixel = 2; 163 | break; 164 | default: 165 | return -EINVAL; 166 | } 167 | 168 | const size_t tileWidth = 2; 169 | const size_t tileHeight = 2; 170 | 171 | size_t stride = align(width, tileWidth); 172 | size_t size = align(height, tileHeight) * stride * bytesPerPixel + 4; 173 | 174 | int err = gralloc_alloc_buffer(dev, size, usage, pHandle); 175 | if (err < 0) { 176 | return err; 177 | } 178 | 179 | *pStride = stride; 180 | return 0; 181 | } 182 | 183 | static int gralloc_free(alloc_device_t* dev, 184 | buffer_handle_t handle) 185 | { 186 | if (private_handle_t::validate(handle) < 0) 187 | return -EINVAL; 188 | 189 | private_handle_t const* hnd = reinterpret_cast(handle); 190 | if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { 191 | // free this buffer 192 | private_module_t* m = reinterpret_cast( 193 | dev->common.module); 194 | const size_t bufferSize = m->finfo.line_length * m->info.yres; 195 | int index = (hnd->base - m->framebuffer->base) / bufferSize; 196 | m->bufferMask &= ~(1<( 199 | dev->common.module); 200 | terminateBuffer(module, const_cast(hnd)); 201 | } 202 | 203 | close(hnd->fd); 204 | delete hnd; 205 | return 0; 206 | } 207 | 208 | /*****************************************************************************/ 209 | 210 | static int gralloc_close(struct hw_device_t *dev) 211 | { 212 | gralloc_context_t* ctx = reinterpret_cast(dev); 213 | if (ctx) { 214 | /* TODO: keep a list of all buffer_handle_t created, and free them 215 | * all here. 216 | */ 217 | free(ctx); 218 | } 219 | return 0; 220 | } 221 | 222 | int gralloc_device_open(const hw_module_t* module, const char* name, 223 | hw_device_t** device) 224 | { 225 | int status = -EINVAL; 226 | if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { 227 | gralloc_context_t *dev; 228 | dev = (gralloc_context_t*)malloc(sizeof(*dev)); 229 | 230 | /* initialize our state here */ 231 | memset(dev, 0, sizeof(*dev)); 232 | 233 | /* initialize the procs */ 234 | dev->device.common.tag = HARDWARE_DEVICE_TAG; 235 | dev->device.common.version = 0; 236 | dev->device.common.module = const_cast(module); 237 | dev->device.common.close = gralloc_close; 238 | 239 | dev->device.alloc = gralloc_alloc; 240 | dev->device.free = gralloc_free; 241 | 242 | *device = &dev->device.common; 243 | status = 0; 244 | } else { 245 | status = fb_device_open(module, name, device); 246 | } 247 | return status; 248 | } 249 | -------------------------------------------------------------------------------- /gralloc/gralloc_priv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef GRALLOC_PRIV_H_ 18 | #define GRALLOC_PRIV_H_ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include 31 | 32 | /*****************************************************************************/ 33 | 34 | struct private_module_t; 35 | struct private_handle_t; 36 | 37 | struct private_module_t { 38 | gralloc_module_t base; 39 | 40 | private_handle_t* framebuffer; 41 | uint32_t flags; 42 | uint32_t numBuffers; 43 | uint32_t bufferMask; 44 | pthread_mutex_t lock; 45 | buffer_handle_t currentBuffer; 46 | int pmem_master; 47 | void* pmem_master_base; 48 | 49 | struct fb_var_screeninfo info; 50 | struct fb_fix_screeninfo finfo; 51 | float xdpi; 52 | float ydpi; 53 | float fps; 54 | }; 55 | 56 | /*****************************************************************************/ 57 | 58 | #ifdef __cplusplus 59 | struct private_handle_t : public native_handle { 60 | #else 61 | struct private_handle_t { 62 | struct native_handle nativeHandle; 63 | #endif 64 | 65 | enum { 66 | PRIV_FLAGS_FRAMEBUFFER = 0x00000001 67 | }; 68 | 69 | // file-descriptors 70 | int fd; 71 | // ints 72 | int magic; 73 | int flags; 74 | int size; 75 | int offset; 76 | 77 | // FIXME: the attributes below should be out-of-line 78 | uint64_t base __attribute__((aligned(8))); 79 | int pid; 80 | 81 | #ifdef __cplusplus 82 | static inline int sNumInts() { 83 | return (((sizeof(private_handle_t) - sizeof(native_handle_t))/sizeof(int)) - sNumFds); 84 | } 85 | static const int sNumFds = 1; 86 | static const int sMagic = 0x3141592; 87 | 88 | private_handle_t(int fd, int size, int flags) : 89 | fd(fd), magic(sMagic), flags(flags), size(size), offset(0), 90 | base(0), pid(getpid()) 91 | { 92 | version = sizeof(native_handle); 93 | numInts = sNumInts(); 94 | numFds = sNumFds; 95 | } 96 | ~private_handle_t() { 97 | magic = 0; 98 | } 99 | 100 | static int validate(const native_handle* h) { 101 | const private_handle_t* hnd = (const private_handle_t*)h; 102 | if (!h || h->version != sizeof(native_handle) || 103 | h->numInts != sNumInts() || h->numFds != sNumFds || 104 | hnd->magic != sMagic) 105 | { 106 | ALOGE("invalid gralloc handle (at %p)", h); 107 | return -EINVAL; 108 | } 109 | return 0; 110 | } 111 | #endif 112 | }; 113 | 114 | #endif /* GRALLOC_PRIV_H_ */ 115 | -------------------------------------------------------------------------------- /gralloc/mapper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | #include "gralloc_priv.h" 33 | 34 | 35 | /*****************************************************************************/ 36 | 37 | static int gralloc_map(gralloc_module_t const* /*module*/, 38 | buffer_handle_t handle, 39 | void** vaddr) 40 | { 41 | private_handle_t* hnd = (private_handle_t*)handle; 42 | if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { 43 | size_t size = hnd->size; 44 | void* mappedAddress = mmap(0, size, 45 | PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); 46 | if (mappedAddress == MAP_FAILED) { 47 | ALOGE("Could not mmap %s", strerror(errno)); 48 | return -errno; 49 | } 50 | hnd->base = uintptr_t(mappedAddress) + hnd->offset; 51 | //ALOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", 52 | // hnd->fd, hnd->offset, hnd->size, mappedAddress); 53 | } 54 | *vaddr = (void*)hnd->base; 55 | return 0; 56 | } 57 | 58 | static int gralloc_unmap(gralloc_module_t const* /*module*/, 59 | buffer_handle_t handle) 60 | { 61 | private_handle_t* hnd = (private_handle_t*)handle; 62 | if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { 63 | void* base = (void*)hnd->base; 64 | size_t size = hnd->size; 65 | //ALOGD("unmapping from %p, size=%d", base, size); 66 | if (munmap(base, size) < 0) { 67 | ALOGE("Could not unmap %s", strerror(errno)); 68 | } 69 | } 70 | hnd->base = 0; 71 | return 0; 72 | } 73 | 74 | /*****************************************************************************/ 75 | 76 | int gralloc_register_buffer(gralloc_module_t const* module, 77 | buffer_handle_t handle) 78 | { 79 | if (private_handle_t::validate(handle) < 0) 80 | return -EINVAL; 81 | 82 | // *** WARNING WARNING WARNING *** 83 | // 84 | // If a buffer handle is passed from the process that allocated it to a 85 | // different process, and then back to the allocator process, we will 86 | // create a second mapping of the buffer. If the process reads and writes 87 | // through both mappings, normal memory ordering guarantees may be 88 | // violated, depending on the processor cache implementation*. 89 | // 90 | // If you are deriving a new gralloc implementation from this code, don't 91 | // do this. A "real" gralloc should provide a single reference-counted 92 | // mapping for each buffer in a process. 93 | // 94 | // In the current system, there is one case that needs a buffer to be 95 | // registered in the same process that allocated it. The SurfaceFlinger 96 | // process acts as the IGraphicBufferAlloc Binder provider, so all gralloc 97 | // allocations happen in its process. After returning the buffer handle to 98 | // the IGraphicBufferAlloc client, SurfaceFlinger free's its handle to the 99 | // buffer (unmapping it from the SurfaceFlinger process). If 100 | // SurfaceFlinger later acts as the producer end of the buffer queue the 101 | // buffer belongs to, it will get a new handle to the buffer in response 102 | // to IGraphicBufferProducer::requestBuffer(). Like any buffer handle 103 | // received through Binder, the SurfaceFlinger process will register it. 104 | // Since it already freed its original handle, it will only end up with 105 | // one mapping to the buffer and there will be no problem. 106 | // 107 | // Currently SurfaceFlinger only acts as a buffer producer for a remote 108 | // consumer when taking screenshots and when using virtual displays. 109 | // 110 | // Eventually, each application should be allowed to make its own gralloc 111 | // allocations, solving the problem. Also, this ashmem-based gralloc 112 | // should go away, replaced with a real ion-based gralloc. 113 | // 114 | // * Specifically, associative virtually-indexed caches are likely to have 115 | // problems. Most modern L1 caches fit that description. 116 | 117 | private_handle_t* hnd = (private_handle_t*)handle; 118 | ALOGD_IF(hnd->pid == getpid(), 119 | "Registering a buffer in the process that created it. " 120 | "This may cause memory ordering problems."); 121 | 122 | void *vaddr; 123 | return gralloc_map(module, handle, &vaddr); 124 | } 125 | 126 | int gralloc_unregister_buffer(gralloc_module_t const* module, 127 | buffer_handle_t handle) 128 | { 129 | if (private_handle_t::validate(handle) < 0) 130 | return -EINVAL; 131 | 132 | private_handle_t* hnd = (private_handle_t*)handle; 133 | if (hnd->base) 134 | gralloc_unmap(module, handle); 135 | 136 | return 0; 137 | } 138 | 139 | int mapBuffer(gralloc_module_t const* module, 140 | private_handle_t* hnd) 141 | { 142 | void* vaddr; 143 | return gralloc_map(module, hnd, &vaddr); 144 | } 145 | 146 | int terminateBuffer(gralloc_module_t const* module, 147 | private_handle_t* hnd) 148 | { 149 | if (hnd->base) { 150 | // this buffer was mapped, unmap it now 151 | gralloc_unmap(module, hnd); 152 | } 153 | 154 | return 0; 155 | } 156 | 157 | int gralloc_lock(gralloc_module_t const* /*module*/, 158 | buffer_handle_t handle, int /*usage*/, 159 | int /*l*/, int /*t*/, int /*w*/, int /*h*/, 160 | void** vaddr) 161 | { 162 | // this is called when a buffer is being locked for software 163 | // access. in thin implementation we have nothing to do since 164 | // not synchronization with the h/w is needed. 165 | // typically this is used to wait for the h/w to finish with 166 | // this buffer if relevant. the data cache may need to be 167 | // flushed or invalidated depending on the usage bits and the 168 | // hardware. 169 | 170 | if (private_handle_t::validate(handle) < 0) 171 | return -EINVAL; 172 | 173 | private_handle_t* hnd = (private_handle_t*)handle; 174 | *vaddr = (void*)hnd->base; 175 | return 0; 176 | } 177 | 178 | int gralloc_unlock(gralloc_module_t const* /*module*/, 179 | buffer_handle_t handle) 180 | { 181 | // we're done with a software buffer. nothing to do in this 182 | // implementation. typically this is used to flush the data cache. 183 | 184 | if (private_handle_t::validate(handle) < 0) 185 | return -EINVAL; 186 | return 0; 187 | } 188 | -------------------------------------------------------------------------------- /ipconfigstore/Android.bp: -------------------------------------------------------------------------------- 1 | cc_binary { 2 | name: "ipconfigstore", 3 | srcs: ["*.cc"], 4 | cflags: ["-Wall", "-Werror"], 5 | shared_libs: ["libbase"], 6 | vendor: true, 7 | } 8 | 9 | -------------------------------------------------------------------------------- /ipconfigstore/data.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "data.h" 8 | 9 | uint16_t convertBigEndianUInt16(uint16_t value) 10 | { 11 | union { uint16_t value; unsigned char data[2]; } aux = { 0x4142 }; 12 | 13 | if (aux.data[0] == 0x41) 14 | { 15 | return value; 16 | } 17 | 18 | aux.data[0] = (value >> 8) & 0xff; 19 | aux.data[1] = value & 0xff; 20 | 21 | return aux.value; 22 | } 23 | 24 | uint32_t convertBigEndianUInt32(uint32_t value) 25 | { 26 | union { uint32_t value; unsigned char data[4]; } aux = { 0x41424344 }; 27 | 28 | if (aux.data[0] == 0x41) 29 | { 30 | return value; 31 | } 32 | 33 | aux.data[0] = (value >> 24) & 0xff; 34 | aux.data[1] = (value >> 16) & 0xff; 35 | aux.data[2] = (value >> 8) & 0xff; 36 | aux.data[3] = value & 0xff; 37 | 38 | return aux.value; 39 | } 40 | 41 | bool writePackedString(const std::string& str, FILE *stream) 42 | { 43 | const char *string = str.c_str(); 44 | size_t stringLength = strlen(string); 45 | 46 | if (!writePackedUInt16(stringLength, stream)) 47 | { 48 | return false; 49 | } 50 | 51 | return fwrite(string, stringLength, 1, stream) == 1; 52 | } 53 | 54 | bool writePackedUInt16(uint16_t value, FILE *stream) 55 | { 56 | uint16_t buffer = convertBigEndianUInt16(value); 57 | return fwrite(&buffer, sizeof buffer, 1, stream) == 1; 58 | } 59 | 60 | bool writePackedUInt32(uint32_t value, FILE *stream) 61 | { 62 | uint32_t buffer = convertBigEndianUInt32(value); 63 | return fwrite(&buffer, sizeof buffer, 1, stream) == 1; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /ipconfigstore/data.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | uint16_t convertBigEndianUInt16(uint16_t value); 9 | uint32_t convertBigEndianUInt32(uint32_t value); 10 | 11 | bool writePackedString(const std::string& str, FILE *stream); 12 | bool writePackedUInt16(uint16_t value, FILE *stream); 13 | bool writePackedUInt32(uint32_t value, FILE *stream); 14 | -------------------------------------------------------------------------------- /ipconfigstore/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | 18 | #include "data.h" 19 | 20 | using namespace android::base; 21 | 22 | struct ipconfig { 23 | uint32_t mask; 24 | char ipv4[16]; 25 | char gateway[16]; 26 | }; 27 | 28 | static int get_gateway(char *dev, char *ret) { 29 | FILE *fp; 30 | char buf[256]; // 128 is enough for linux 31 | char iface[16]; 32 | unsigned long dest_addr, gate_addr; 33 | fp = fopen("/proc/net/route", "r"); 34 | if (fp == NULL) return -1; 35 | /* Skip title line */ 36 | fgets(buf, sizeof(buf), fp); 37 | while (fgets(buf, sizeof(buf), fp)) { 38 | if (sscanf(buf, "%s\t%lX\t%lX", iface, &dest_addr, &gate_addr) != 3 || dest_addr != 0 || strcmp(dev, iface)) continue; 39 | inet_ntop(AF_INET, &gate_addr, ret, INET_ADDRSTRLEN); 40 | break; 41 | } 42 | 43 | fclose(fp); 44 | return 0; 45 | } 46 | 47 | static int bitcount(uint32_t n) 48 | { 49 | int count=0; 50 | while (n) { 51 | count++; 52 | n &= (n - 1); 53 | } 54 | return count; 55 | } 56 | 57 | static int get_conf(struct ipconfig *conf) { 58 | struct ifaddrs *ifAddrStruct; 59 | void *tmpAddrPtr=NULL; 60 | getifaddrs(&ifAddrStruct); 61 | while (ifAddrStruct != NULL) { 62 | if (ifAddrStruct->ifa_addr->sa_family==AF_INET && !strcmp("eth0", ifAddrStruct->ifa_name)) { 63 | tmpAddrPtr=&((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr; 64 | inet_ntop(AF_INET, tmpAddrPtr, conf->ipv4, INET_ADDRSTRLEN); 65 | conf->mask = bitcount(((struct sockaddr_in *)ifAddrStruct->ifa_netmask)->sin_addr.s_addr); 66 | break; 67 | } 68 | ifAddrStruct=ifAddrStruct->ifa_next; 69 | } 70 | freeifaddrs(ifAddrStruct); 71 | get_gateway((char *) "eth0", conf->gateway); 72 | return 0; 73 | } 74 | 75 | static void write_dns(FILE *fp) { 76 | std::set dnsList; 77 | auto ndns = GetIntProperty("ro.boot.redroid_net_ndns", 0); 78 | for (int i = 1; i <= ndns; ++i) { 79 | dnsList.insert(GetProperty("ro.boot.redroid_net_dns" + std::to_string(i), "")); 80 | } 81 | if (dnsList.empty()) dnsList.insert("8.8.8.8"); 82 | 83 | for (auto& dns: dnsList) { 84 | writePackedString("dns", fp); 85 | writePackedString(dns.c_str(), fp); 86 | } 87 | } 88 | 89 | static void write_proxy(FILE *fp) { 90 | // static | pac | none | unassigned 91 | std::string proxy_type = GetProperty("ro.boot.redroid_net_proxy_type", ""); 92 | if ("static" == proxy_type) { 93 | writePackedString("proxySettings", fp); 94 | writePackedString("STATIC", fp); 95 | 96 | writePackedString("proxyHost", fp); 97 | writePackedString(GetProperty("ro.boot.redroid_net_proxy_host", "").c_str(), fp); 98 | 99 | writePackedString("proxyPort", fp); 100 | writePackedUInt32(GetIntProperty("ro.boot.redroid_net_proxy_port", 3128), fp); 101 | 102 | writePackedString("exclusionList", fp); 103 | writePackedString(GetProperty("ro.boot.redroid_net_proxy_exclude_list", "").c_str(), fp); 104 | } else if ("pac" == proxy_type) { 105 | writePackedString("proxySettings", fp); 106 | writePackedString("PAC", fp); 107 | 108 | writePackedString("proxyPac", fp); 109 | writePackedString(GetProperty("ro.boot.redroid_net_proxy_pac", "").c_str(), fp); 110 | } else if ("none" == proxy_type) { 111 | writePackedString("proxySettings", fp); 112 | writePackedString("NONE", fp); 113 | } else { 114 | // ignored 115 | } 116 | } 117 | 118 | static int write_conf(struct ipconfig *conf, uint32_t v) { 119 | FILE *fp = fopen("/data/misc/ethernet/ipconfig.txt", "w+"); 120 | 121 | writePackedUInt32(v, fp); // version 122 | 123 | writePackedString("ipAssignment", fp); 124 | writePackedString("STATIC", fp); 125 | 126 | writePackedString("linkAddress", fp); 127 | writePackedString(conf->ipv4, fp); 128 | writePackedUInt32(conf->mask, fp); 129 | 130 | writePackedString("gateway", fp); 131 | writePackedUInt32(1, fp); // Default route (dest). 132 | writePackedString("0.0.0.0", fp); 133 | writePackedUInt32(0, fp); 134 | writePackedUInt32(1, fp); // Have a gateway. 135 | writePackedString(conf->gateway, fp); 136 | 137 | write_dns(fp); 138 | 139 | write_proxy(fp); 140 | 141 | writePackedString("id", fp); 142 | if (v == 2) writePackedUInt32(0, fp); 143 | else writePackedString("eth0", fp); 144 | 145 | writePackedString("eos", fp); 146 | 147 | fclose(fp); 148 | return 0; 149 | } 150 | 151 | int main(int argc, char **argv) { 152 | (void)argc; 153 | (void)argv; 154 | 155 | uint32_t v = 3; 156 | // use V2 for Android 8.1 157 | if (GetIntProperty("ro.build.version.sdk", 0) <= 27) v = 2; 158 | 159 | struct ipconfig conf; 160 | get_conf(&conf); 161 | printf("ipconfig: ipv4: %s, mask: %i, gateway: %s", conf.ipv4, conf.mask, conf.gateway); 162 | write_conf(&conf, v); 163 | return 0; 164 | } 165 | 166 | -------------------------------------------------------------------------------- /post-fs-data.redroid.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | ## enable `memfd` if `ashmem` missing 4 | ## memfd is disabled in post-fs-data (init.rc) 5 | [ -c /dev/ashmem ] || setprop sys.use_memfd 1 6 | -------------------------------------------------------------------------------- /redroid.common.rc: -------------------------------------------------------------------------------- 1 | on early-init 2 | mount debugfs debugfs /sys/kernel/debug mode=755 3 | 4 | # ueventd fix 5 | chmod 0666 /dev/null 6 | chmod 0666 /dev/zero 7 | chmod 0666 /dev/full 8 | chmod 0666 /dev/ptmx 9 | chmod 0666 /dev/pts/ptmx 10 | chmod 0666 /dev/tty 11 | chmod 0666 /dev/random 12 | chmod 0666 /dev/urandom 13 | chmod 0666 /dev/ashmem 14 | chmod 0666 /dev/ion 15 | 16 | chmod 0444 /dev/dma_heap/system 17 | chown system system /dev/dma_heap/system 18 | 19 | # used to place domain sockets 20 | mkdir /ipc 0777 21 | 22 | exec -- /bin/rm -rf /dev/input 23 | # inputflinger require this dir 24 | mkdir /dev/input 25 | 26 | # disable codec2 by default, DMA Heap required 27 | setprop debug.stagefright.ccodec 0 28 | 29 | # disable some verbose logs 30 | setprop log.tag.libprocessgroup F 31 | 32 | # assume GLES 3.2 supported 33 | setprop ro.opengles.version 196610 34 | 35 | # setup overlay data partition 36 | on early-init && property:ro.boot.use_redroid_overlayfs=1 37 | trigger use_redroid_overlayfs 38 | 39 | 40 | on use_redroid_overlayfs 41 | mkdir /data-diff/upper 42 | rmdir /data-diff/work 43 | mkdir /data-diff/work 44 | mount overlay overlay /data lowerdir=/data-base,upperdir=/data-diff/upper,workdir=/data-diff/work 45 | 46 | 47 | on early-init && property:ro.boot.redroid_dpi=* 48 | setprop ro.sf.lcd_density ${ro.boot.redroid_dpi} 49 | 50 | 51 | on property:ro.zygote=zygote64_32 52 | write /proc/sys/kernel/pid_max 65535 53 | 54 | 55 | # use memfd (ashmem removed in 5.18), memfd is disabled in post-fs-data (init.rc) 56 | on post-fs-data && property:ro.boot.use_memfd=* 57 | setprop sys.use_memfd ${ro.boot.use_memfd} 58 | 59 | 60 | on init 61 | # lxcfs better 62 | write /data/.empty 0 63 | mount none /data/.empty /proc/vmallocinfo bind 64 | 65 | # fix suspend host system? 66 | mount none /data/.empty /sys/power/state bind 67 | 68 | setprop debug.renderengine.backend gles 69 | 70 | # set dpi if missing 71 | setprop ro.sf.lcd_density 320 72 | 73 | 74 | on post-fs-data 75 | # fix for static IP, must after post-fs-data and before netd 76 | # rm apex config (use legacy path) 77 | rm /data/misc/apexdata/com.android.tethering/misc/ethernet/ipconfig.txt 78 | exec - system system -- /vendor/bin/ipconfigstore 79 | 80 | # no need to mount, and encryption not supported yet 81 | trigger nonencrypted 82 | 83 | exec -- /vendor/bin/post-fs-data.redroid.sh 84 | 85 | 86 | on early-boot 87 | 88 | # before HAL / SurfaceFlinger 89 | exec -- /vendor/bin/gpu_config.sh 90 | -------------------------------------------------------------------------------- /redroid.legacy.rc: -------------------------------------------------------------------------------- 1 | # convert legacy props 2 | 3 | # overlay data 4 | on early-init && property:ro.kernel.redroid.overlay=1 5 | trigger use_redroid_overlayfs 6 | 7 | 8 | # display 9 | on early-init && property:ro.kernel.redroid.width=* 10 | setprop ro.boot.redroid_width ${ro.kernel.redroid.width} 11 | 12 | on early-init && property:ro.kernel.redroid.height=* 13 | setprop ro.boot.redroid_height ${ro.kernel.redroid.height} 14 | 15 | on early-init && property:ro.kernel.redroid.fps=* 16 | setprop ro.boot.redroid_fps ${ro.kernel.redroid.fps} 17 | 18 | 19 | # DNS 20 | on early-init && property:ro.kernel.net.eth0.dns1=* 21 | setprop ro.boot.redroid_net_ndns 1 22 | setprop ro.boot.redroid_net_dns1 ${ro.kernel.net.eth0.dns1} 23 | 24 | 25 | # network proxy 26 | on early-init && property:ro.kernel.net.eth0.proxy.type=* 27 | setprop ro.boot.redroid_net_proxy_type ${ro.kernel.net.eth0.proxy.type} 28 | 29 | on early-init && property:ro.kernel.net.eth0.proxy.host=* 30 | setprop ro.boot.redroid_net_proxy_host ${ro.kernel.net.eth0.proxy.host} 31 | 32 | on early-init && property:ro.kernel.net.eth0.proxy.port=* 33 | setprop ro.boot.redroid_net_proxy_port ${ro.kernel.net.eth0.proxy.port} 34 | 35 | on early-init && property:ro.kernel.net.eth0.proxy.exclusionList=* 36 | setprop ro.boot.redroid_net_proxy_exclude ${ro.kernel.net.eth0.proxy.exclusionList} 37 | 38 | on early-init && property:ro.kernel.net.eth0.proxy.pac=* 39 | setprop ro.boot.redroid_net_proxy_pac ${ro.kernel.net.eth0.proxy.pac} 40 | 41 | 42 | # GPU 43 | on early-init && property:ro.kernel.redroid.gpu.mode=* 44 | setprop ro.boot.redroid_gpu_mode ${ro.kernel.redroid.gpu.mode} 45 | 46 | on early-init && property:ro.kernel.redroid.gpu.node=* 47 | setprop ro.boot.redroid_gpu_node ${ro.kernel.redroid.gpu.node} 48 | -------------------------------------------------------------------------------- /vendor.mk: -------------------------------------------------------------------------------- 1 | # skip androidx.window.extensions check 2 | PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true 3 | 4 | PRODUCT_PACKAGES += \ 5 | binder_alloc \ 6 | gralloc.redroid \ 7 | ipconfigstore \ 8 | 9 | 10 | PRODUCT_COPY_FILES += \ 11 | vendor/redroid/gpu_config.sh:$(TARGET_COPY_OUT_VENDOR)/bin/gpu_config.sh \ 12 | vendor/redroid/post-fs-data.redroid.sh:$(TARGET_COPY_OUT_VENDOR)/bin/post-fs-data.redroid.sh \ 13 | vendor/redroid/redroid.common.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/redroid.common.rc \ 14 | vendor/redroid/redroid.legacy.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/redroid.legacy.rc \ 15 | 16 | 17 | PRODUCT_COPY_FILES += \ 18 | frameworks/native/data/etc/android.hardware.touchscreen.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.touchscreen.xml \ 19 | --------------------------------------------------------------------------------