Gralloc与上层libui/libsurfaceflinger的关系

himax hx8369a lcd driver 1. 注册设备 static int __init himax_hx8369a_init(void) { printk("%s\n", __FUNCTION__); return comipfb_dev_register(&himax_hx8369a_dev); //注册comipfb设备,即兼容与comipfb平台的lcd设备。 } 阅读详情

如前所述,Gralloc模块主要由 gralloc_module_t 模块,alloc_device_t 设备和 framebuffer_device_t 设备3个结构体来描述。
1. Gralloc模块的主要调用者是ui库中的以下文件:
frameworks/base/libs/ui/FramebufferNativeWindow.cpp


FramebufferNativeWindow的构造函数如下:

    /*
     * This implements the (main) framebuffer management. This class is used
     * mostly by SurfaceFlinger, but also by command line GL application.
     *
     * In fact this is an implementation of ANativeWindow on top of
     * the framebuffer.
     *
     * This implementation is able to manage any number of buffers,
     * defined by NUM_FRAME_BUFFERS (currently set to 2: front
     * and back buffer)
     *
     */
    FramebufferNativeWindow::FramebufferNativeWindow()
        : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
    {
        hw_module_t const* module;
        if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
            int stride;
            int err;
    #ifdef OMAP_ENHANCEMENT
            int i;
    #endif
            err = framebuffer_open(module, &fbDev);                //打开framebuffer设备
            LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
            err = gralloc_open(module, &grDev);                      //打开gralloc设备
            LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));
            // bail out if we can't initialize the modules
            if (!fbDev || !grDev)                         //只有framebuffer和gralloc都存在,才能继续运行
                return;
            mUpdateOnDemand = (fbDev->setUpdateRect != 0);    //可选的setUpdateRect
            // initialize the buffer FIFO
    #ifdef OMAP_ENHANCEMENT
            mNumBuffers = NUM_FRAME_BUFFERS;
            mNumFreeBuffers = NUM_FRAME_BUFFERS;
    #else
            mNumBuffers = 2;                //初始化 buffer FIFO,双缓冲,有2块内存。
            mNumFreeBuffers = 2;
    #endif
            mBufferHead = mNumBuffers-1;
    #ifdef OMAP_ENHANCEMENT
            for(i = 0; i < NUM_FRAME_BUFFERS; i++){
                buffers[i] = new NativeBuffer(
                        fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
            }
            for(i = 0; i < NUM_FRAME_BUFFERS; i++){
                err = grDev->alloc(grDev,
                        fbDev->width, fbDev->height, fbDev->format,
                        GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);
                LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",
                        i, fbDev->width, fbDev->height, strerror(-err));
                if(err){
                    mNumBuffers = i;
                    mNumFreeBuffers = i;
                    mBufferHead = mNumBuffers-1;
                    break;
                }
           }
    #else
            buffers[0] = new NativeBuffer(         //初始化2个缓冲区          
                    fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
            buffers[1] = new NativeBuffer(
                    fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
            err = grDev->alloc(grDev,              //从gralloc设备中分配内存
                    fbDev->width, fbDev->height, fbDev->format,
                    GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);
            LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",
                    fbDev->width, fbDev->height, strerror(-err));
            err = grDev->alloc(grDev,
                   fbDev->width, fbDev->height, fbDev->format,
                    GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
            LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
                    fbDev->width, fbDev->height, strerror(-err));
    #endif    
            const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;  //从framebuffer设备中获得常量
            const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
            const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
            const_cast<int&>(ANativeWindow::minSwapInterval) =
                fbDev->minSwapInterval;
            const_cast<int&>(ANativeWindow::maxSwapInterval) =
                fbDev->maxSwapInterval;
        } else {
            LOGE("Couldn't get gralloc module");
        }
        ANativeWindow::setSwapInterval = setSwapInterval;   //处理函数指针
        ANativeWindow::dequeueBuffer = dequeueBuffer;
        ANativeWindow::lockBuffer = lockBuffer;
        ANativeWindow::queueBuffer = queueBuffer;
        ANativeWindow::query = query;
        ANativeWindow::perform = perform;
        ANativeWindow::cancelBuffer = 0;
    #ifdef OMAP_ENHANCEMENT
        LOGE("%d buffers flip-chain implementation enabled\n", mNumBuffers);
    #endif
    }

FramebufferNativeWindow 实际上是Gralloc模块的一层封装,向android本地代码层提供了用于显示的android_native_window_t结构。

2. libui库中的 GraphicBufferAllocator.cpp 用于分配显示缓冲:
    status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
            int usage, buffer_handle_t* handle, int32_t* stride)
    {
        // make sure to not allocate a N x 0 or 0 x N buffer, since this is
        // allowed from an API stand-point allocate a 1x1 buffer instead.
        if (!w || !h)
            w = h = 1;
        // we have a h/w allocator and h/w buffer is requested
        status_t err;
        //mAllocDev 类型为 alloc_device_t,当调用的参数有GRALLOC_USAGE_HW_MASK标志时,有alloc_device_t调用分配一个内存,否则从软件分配一个内存。
        if (usage & GRALLOC_USAGE_HW_MASK) {     
            err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
        } else {
            err = sw_gralloc_handle_t::alloc(w, h, format, usage, handle, stride);
        }
        LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
                w, h, format, usage, err, strerror(-err));
        
        if (err == NO_ERROR) {
            Mutex::Autolock _l(sLock);
            KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
            alloc_rec_t rec;
            rec.w = w;
            rec.h = h;
            rec.s = *stride;
            rec.format = format;
            rec.usage = usage;
            rec.size = h * stride[0] * bytesPerPixel(format);
            list.add(*handle, rec);
        }
        return err;
    }


软件分配内存
    status_t sw_gralloc_handle_t::alloc(uint32_t w, uint32_t h,int format,
            int usage, buffer_handle_t* pHandle, int32_t* pStride)
    {
        int align = 4;
        int bpp = 0;
        switch (format){
            case HAL_PIXEL_FORMAT_RGBA_8888:
            case HAL_PIXEL_FORMAT_RGBX_8888:
            case HAL_PIXEL_FORMAT_BGRA_8888:
                bpp = 4;
                break;
            case HAL_PIXEL_FORMAT_RGB_888:
                bpp = 3;
                break;
            case HAL_PIXEL_FORMAT_RGB_565:
            case HAL_PIXEL_FORMAT_RGBA_5551:
            case HAL_PIXEL_FORMAT_RGBA_4444:
                bpp = 2;
                break;
            default:
                return -EINVAL;
        }
        size_t bpr = (w*bpp +(align-1))& ~(align-1);
        size_t size = bpr * h;
        size_t stride = bpr / bpp;
        size =(size + (PAGE_SIZE-1))& ~(PAGE_SIZE-1);
        int fd = ashmem_create_region("sw-gralloc-buffer",size);
        if (fd< 0) {
            LOGE("ashmem_create_region(size=%d) failed (%s)",
                    size, strerror(-errno));
            return -errno;
        }
        int prot = PROT_READ;
        if (usage& GRALLOC_USAGE_SW_WRITE_MASK)
            prot |= PROT_WRITE;
        if (ashmem_set_prot_region(fd, prot)< 0) {
            LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)",
                    fd, prot, strerror(-errno));
            close(fd);
            return -errno;
        }
        void*base = mmap(0,size, prot, MAP_SHARED, fd, 0);
        if (base== MAP_FAILED){
            LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)",
                    fd, size, prot, strerror(-errno));
            close(fd);
            return -errno;
        }
        sw_gralloc_handle_t* hnd = new sw_gralloc_handle_t();
        hnd->fd= fd;
        hnd->size= size;
        hnd->base= intptr_t(base);
        hnd->prot= prot;
        *pStride = stride;
        *pHandle = hnd;
        return NO_ERROR;
    }

3.libui库中的GraphicBufferMapper.cpp文件用于显示缓冲的映射:
    status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
    {
        status_t err;
       //mAllocMod的类型为 gralloc_module_t,可以从Gralloc模块中注册Buffer,也可以从软件注册Buffer
        if (sw_gralloc_handle_t::validate(handle)< 0) {
            err = mAllocMod->registerBuffer(mAllocMod, handle);  
        } else{
            err = sw_gralloc_handle_t::registerBuffer((sw_gralloc_handle_t*)handle);
        }
        LOGW_IF(err,"registerBuffer(%p) failed %d (%s)",
                handle, err, strerror(-err));
        return err;
    }

4. libui库中的 GraphicBuffer.cpp 定义类GraphicBuffer继承实现了android_native_buffer_t. 这个类是
分配器GraphicBufferAllocator 和映射器 GraphicBufferMapper的调用者。

    GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
            PixelFormat reqFormat, uint32_t reqUsage)
        : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), //调用GraphicBufferMapper
          mInitCheck(NO_ERROR), mIndex(-1)
    {
        width =
        height =
        stride =
        format =
        usage =
        transform = 0;
        handle = NULL;
        mInitCheck = initSize(w, h, reqFormat, reqUsage);
    }

    status_t GraphicBuffer::initSize(uint32_t w, uint32_t h,PixelFormat format,
            uint32_t reqUsage)
    {
        GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); //调用GraphicBufferAllocator
        status_t err = allocator.alloc(w, h, format, reqUsage, &handle,&stride);
        if (err== NO_ERROR){
            this->width= w;
            this->height= h;
            this->format= format;
            this->usage= reqUsage;
        }
        return err;
    }

5. 在图层管理库libSufaceFlinger中, 也有对Gralloc模块的调用部分:
frameworks/base/services/surfaceflinger/LayerBuffer.cpp 中定义了一个Buffer类。其构造函数如下:

    // ============================================================================
    // LayerBuffer::Buffer
    // ============================================================================
    LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers,
            ssize_t offset, size_t bufferSize)
        : mBufferHeap(buffers), mSupportsCopybit(false)
    {
        NativeBuffer& src(mNativeBuffer);
        src.crop.l= 0;                  //剪切区域
        src.crop.t= 0;
        src.crop.r= buffers.w;
        src.crop.b= buffers.h;
        src.img.w= buffers.hor_stride?: buffers.w;      //区域大小和颜色
        src.img.h= buffers.ver_stride?: buffers.h;
        src.img.format= buffers.format;
        src.img.base= (void*)(intptr_t(buffers.heap->base())+ offset);
        src.img.handle= 0;
        gralloc_module_t const * module = LayerBuffer::getGrallocModule();
        if (module&& module->perform){         //根据情况调用perform
            int err = module->perform(module,
                    GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER,
                    buffers.heap->heapID(), bufferSize,
                    offset, buffers.heap->base(),
                    &src.img.handle);
            // we can fail here is the passed buffer is purely software
            mSupportsCopybit = (err == NO_ERROR);
        }
     }

这里调用的perform是gralloc_module_t的一个可选实现的函数指针,如果当前的gralloc模块中实现了该指针,则在这里调用该函数,并使用GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER命令,表示从Buffer中创建一个句柄,可以获得加速效果。
FMCW雷达基本原理(通俗易懂)篇2 FMCW雷达(Frequency Modulated Continuous Wave Radar)是一种使用频率调制连续波的雷达系统。它使用一个发射器发射一个连续波,但是这个连续波的频率会在一定的范围内不断变化。当这个连续波遇到一个目标物体并被反射回来时,接收器会检测到这个反射波的频率变化,并计算出目标物体的距离和速度等信息。FMCW雷达的原理可以理解为:1.发射器发射一个连续波,这个波的频率会从一个固定的起始频率开始,逐渐变化至一个固定的终止频率。 阅读详情

相关推荐

STM32G070xx将Flash页分块方式存储,固定数据块存储,实现一次擦除多次写入

本例程使用STM32G070xx芯片,Flash大小128KB,Flash每页(2048字节)写满后再擦除。操作存储区分为64块,每块32字节,即写满64次擦除一次;标定存储区分为16块,每块128字节,即写满16次擦除一次,每个存储区的块都有各自的头部标记

RaphaelCeo的博客 1545

PPI_DPI 对比

PPI --- 每英寸所拥有的像素数目。pixels per inch所表示的是每英寸所拥有的像素(pixel)数目。因此PPI数值越高,即代表显示屏能够以越高的密度显示图像。当然,显示的密度越高,拟真度就越高。   pixels per inch是图像分辨率的单位,图像ppi值越高,画面的细节就越丰富,因为单位面积的像素数量更多,数码相机拍出来的图片因品牌或生产时间不同可能有所不同,常见的有7

1万+

OsgEarth实战:飞机模型动态轨迹与雷达扫描效果实现详解

本文详细介绍了如何使用OsgEarth实现飞机模型动态轨迹与雷达扫描效果。通过实战案例,讲解了模型加载、路径规划、动态轨迹绘制、飞行姿态计算以及雷达扫描效果的实现方法,并提供了性能优化技巧,帮助开发者高效完成三维可视化项目开发。

weixin_29214199的博客 303

Gralloc 模块

1. 在Android Eclair 及其之后的版本中,显示系统增加了一个名为Gralloc的硬件模块。 Gralloc的含义为, Graphics Alloc(图形分配),这个模块位于libui和显示设备的驱动程序之间。 Gralloc模块被放在/system/lib/hw/下,下面是omap3的一个gralloc: $ ls system/lib/hw -l 总用量 14

1702

C#操作SQLite数据库帮助类——SQLiteHelper

using System; using System.Collections.Generic; using System.Data.SQLite; using System.Data; namespace Com.ZCWL.Rock.Helper { public class SQLiteHelper { private static string connectionString =

跟健哥出去走走 2万+

【温室气体】GOSAT 数据产品

【温室气体】GOSAT 数据产品

WW、forever的博客 238

像素深度_比特每像素bpp

比特每像素bpp ---bit per pixel.   表示图像像素值的位数叫做图像的像素深度,又称为位/像素(BPP)。这个数值用来表示图像的每个像素值所需要的位数(bits per pixel),它决定了该图像的类别。   一个像素所能表达的不同颜色数取决于比特每像素(BPP)。这个最大数可以通过取二的色彩深度次幂来得到。例如,常见的取值有 : 8 bpp [28=256;(256色

1573

统信UOS丨开机无法进入系统 无法打开控制台访问权限,root账号被锁定(cannot open access to console, the root account is locked)

步骤四:分别打开文件发现Roota下的fstab就是我们要找的文件,打开查看Roota的属性发现其为挂载的磁盘nvme0n1p3。步骤三:按Win+E打开文件管理器在分区中查找/etc/fstab文件,发现Roota和Rootb下都有该文件。步骤二:按键盘Ctrl+Alt+F4,进入终端控制台,如下图所示输入startx回车,进入桌面。步骤一:找到UOS系统安装的U盘,选择U盘启动进入安装界面,如下图所示。步骤七:关机,拔出U盘,启动电脑,OK,问题解决。

Reyn_观极 1万+

android是怎么整合framebuffer显示驱动的

在linux中,framebuffer驱动是标准的显示设备的驱动;对于pc系统,framebuffer驱动是显卡的驱动;对于嵌入式系统的SOC处理器,framebuffer通常作为其LCD控制器或者其它显示设备的驱动。      Framebuffer驱动是一个字符设备,这个驱动在文件系统中的设备节点通常是:/dev/fbX 主设备号是29,次设备号递增生成(由每个Framebuffe

1484

信息传输仿真:卫星通信系统仿真_(12).基于SystemVue的卫星通信仿真

SystemVue是Cadence公司开发的一款用于系统级设计和仿真的软件工具。它主要用于无线通信系统的设计和验证,特别是在卫星通信、雷达、射频和微波通信等领域。SystemVue提供了一个集成的环境,用户可以通过拖拽和连接各种预定义的模块来构建复杂的通信系统模型,从而进行性能分析和优化。

2401_87715305的博客 1370

《低功耗方法学》翻译——第一章:介绍

第一章:介绍

记录所学,分享知识,结识挚友 2067

Gralloc.default.so 的实现

默认的Gralloc模块实现的代码路径如下: hardware/libhardware/modules/gralloc/* $ ls hardware/libhardware/modules/gralloc/Android.mk framebuffer.cpp gralloc.cpp gralloc_priv.h gr.h mapper.cpp 1. gralloc.c,

1453

YOLOv13优化Faster_Block:卷积(Partial Convolution)、多层感知机(MLP)结构和残差连接

Faster_Block 代表了现代深度学习中效率与性能平衡的一个典型案例。它通过部分卷积技术巧妙地减少了计算开销,同时通过精心设计的架构保持了强大的特征学习能力。这种设计思想对于移动端部署、实时应用和大规模模型训练都具有重要意义。 未来的发展方向可能包括更智能的动态分割策略、与新兴硬件的深度适配,以及与其他先进技术(如自注意力机制、神经架构搜索等)的结合。Faster_Block 的成功展示了在深度学习领域,创新往往来自于对问题本质的深刻理解和巧妙的工程实现。

FJN110的博客 427

LCD 的各种接口

目前一般彩色LCD的连接方式有这么几种:MCU模式,RGB模式,SPI模式,VSYNC模式,MDDI模式等。还有的用MIPI接口。 MCU模式:目前最常用的连接模式,一般是80系统(68系统已经不存在了)。数据位传输有8位,9位,          16位和18位。连线分为:CS/,RS(寄存器选择),RD/,WR/,再就是数据线了。优点是:控          制简单方便,无需时钟和同步

1295

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

18_2_帧缓冲

帧缓冲 framebuffer : 是linux系统为显示设备提供的一个接口。 帧缓冲是显示缓冲区的抽象,而不需要考虑底层硬件的差异,允许上层应用在图形模式下,直接对显示缓冲区进行读写操作。 屏幕上的显示点,与显示缓冲区一一对应,可以通过读写显示缓冲区的操作,来控制屏幕上的显示输出。、 帧缓冲设备为标准字符设备,主设备号29,对应于/dev/fb%d设备文件。 1. fb_

1006

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Led Blinking 功能驱动设计

这是OBM里的一段代码,实现了LED 闪烁的功能,下面是LED原理图: Led blinking  The LEDR, LEDG, LEDB, controlled by the 8806, can be programed to blinking by set the 8806 internal regs. Such as 0x0c,0x0d,0x0e,0x0f. the

877

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

WVGA LCD density

一般大的屏幕 density值需要改下,来调节icon在屏幕上显示的大小。 1. 这个数值一般都在 system.prop 或 build.prop 中设置. 如/device/***/system.prop ro.sf.lcd_density = 160    //一般3.5寸屏就可以设成160 WVGA 屏, 比如 480x800分辨率下: ro.sf.lcd_d

875

linux中测试LCD 显示功能

echo "LCD display log" > /dev/tty0 LCD屏上就会显示 LCD display log

859

18_1_LCD硬件原理

早期的LCD显示器有以下几种类型:   1. TN   2. STN   3. TFT   TFT屏好像也有些过时了,但是原理还是差不多:   时序图中都会有以下3个信号:   1. VCLK, 像素时钟信号,用于锁存图像数据的像素时钟。   2. HSYNC, 行同步信号, 每发出一个行同步脉冲,就表示新的一行图像数据开始发送。   3. VSYNC. 帧同步信号

812

medfield 平台 lvds bridge 驱动

lvds bridge, 应该是一个I2C接口控制的,采用lvds数据接口,液晶屏驱动器桥。 这也是个I2C 驱动,挂接在 I2C_2 总线上。 1. 初始化如下: /* ************************************************************************* *\ * FUNCTION: dsi_lvd

792

HDMI_VGA_CBVS同时显示

STi7105同一时间只能播放一个视频文件。 但是可以用2个播放处理器同时播放该视频文件。一个高清通道(主),一个标清通道(辅)。 每个通道,可以设置不同的VTG(即分辨率格式)。 HDMI和VGA共用一个主通道。CVBS用辅通道。 ST7105 > VID_INJSTART 1 "/18T_D1_NTSC.264" 0 V_ES V_AUX   //只输出辅通道 ST7105 > vi

642

具身智能 2026:启元人形机器人开发者生态的“安卓时刻”来了吗

一个贯穿全文的问题:人形机器人开发者生态,是否正从「封闭垂直」走向「开源平台化」?本文以开源底座的公开数据为标尺,盘点 SDK、URDF、仿真与技能分发的开放程度,并落回启元机器人的开源路径。所有关键数据均标注来源,文末附社区与学堂链接。

在北风吹起的时候加入我们的队伍 在秋雨到来的时候成为彼此的温暖 749

android-ad-cleaner:android免 Root 批量关闭系统开屏与营销推送

橘子,计算机视觉方向工程师,深耕 AIGC 与多媒体处理领域,专注技术实用化落地。本文为原创内容,转载请注明来源与作者。优快云 首发 | 版权所有 © 2026。

下载资源或查看教程前,请务必阅读置顶的《免责声明》 525

Android 14 SELinux策略深度解析

init 的全局公开约束(如 neverallow init execute_no_trans,放 public 才能约束所有分区的规则)这就是"哪些可见"的强制机制。alps_s0(MTK 工程)的 device/mediatek/sepolicy/basic/ 提供。所有分区(system/system_ext/product/vendor)都可引用。init的公开约束、跨分区共用的 type/attribute/neverallow。——vendor 的 .cil 只能引用 plat 的。

新时代农民工 103

Android 开发入门实践(二):Kotlin 空安全,从可空类型到安全访问

延续 NewsApp 项目中的新闻标题练习,记录 Kotlin 安全调用。

Easyhood的博客 277

Android 模块化收口:能力组合框架、手写 LifecycleOwner 与热修复共存

二十多个模块业务高度相似却各有差异,核心矛盾在于“统一与灵活”的平衡。通过角色接口组合(如IProjectAware、IVoiceAware)实现能力按需注入,新增功能零侵入;用模板方法锁定生命周期流程,确保顺序一致;结合@CallSuper与工厂方法,既约束关键逻辑,又保留子类自由。最终实现:骨架统一、填空自由,管得住业务,又不侵入业务。

mmsx990的博客 395
上一篇: Gralloc.default.so 的实现
下一篇: Gralloc 模块
lamdoc
博客等级 码龄18年 155粉丝 655原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值