Android显示系统探索一:一个简单的C++程序

文章通过一个简单的C++程序展示了如何使用SurfaceControl在Android系统中创建并绘制浮窗视图,探讨了SurfaceFlinger在其中的作用,以及与ViewRootImpl和SurfaceFlinger的交互过程,包括Surface的lock和unlock操作。
摘要由CSDN通过智能技术生成


前言

设想这样一个需求:在屏幕上显示一个浮窗视图。程序员一般会写下如程序:

WindowManager mWindowManager = (WindowManager)getSystemService(WindowManager.class);
WindowManager.LayoutoutParms lps= new WindowManager.LayoutParms(**);
lps.x =100;
lps.y = 100;
lps.token = new Binder();
View view = LayoutInflater.from(**)inflate(**);
mWindowManager.addView(view,lps)

完工,So easy。作为一名有追求的程序员,刨根问底少不了:这个流程究竟是怎么工作。于是乎网上找资源,打断点、打日志,阅读代码,一顿操作下来也是云里雾里。这个时候一般就会十万个为什么了,其中一个或许是这样的:

有没有一个更精简的程序,可以实现上图的基本功能,哪怕只是实现一个纯色视图,精简流程,方便我们熟悉整个流程。

回答当然是 yes

一、SurfaceControl绘制

上述代码为应用层代码,整个调用流程涉及到多个系统服务、调用了多个系统库,例如WindowManagerService、SurfaceFlineger、Skia图形库等。探索这段调用过程,很容易走向放弃,原因之一笔者认为是由于抓不住流程的主干,受困于android海量代码,受困于对android分层思想理解不够深刻。下面从SurfaceFlinger代理服务作为中间件切入,通过几行代码实现了纯色浮窗效果。
示例代码如下所示(Android软件环境为Android 11):

static const int LAYER_BASE = INT32_MAX - 10;

struct Color {
public:
    uint8_t r;
    uint8_t g;
    uint8_t b;
    uint8_t a;
};

constexpr static Color RED = {195, 63, 63, 255};
constexpr static Color BLUE = {63, 63, 195, 255};
namespace android{
     using Transaction = SurfaceComposerClient::Transaction;
     class SurfaceControlTest{
       public:
         SurfaceControlTest() {
            //方法1:创建SurfaceComposerClient
            mComposerClient = new SurfaceComposerClient;
            if(NO_ERROR!=mComposerClient->initCheck()){
              return;
            }
            //方法2:创建SurfaceControl
            mSurfaceControl = mComposerClient->createSurface(String8("SurfaceControl Test"), 500, 500,
                  PIXEL_FORMAT_RGBA_8888, 0);
         }


        void fillSurfaceRGBA8(const Color& color,
                                     bool unlock = true) {
            ANativeWindow_Buffer outBuffer;
            sp<Surface> surface = mSurfaceControl->getSurface();
            //方法3
            surface->lock(&outBuffer, NULL);
            //方法4
            uint8_t* img = reinterpret_cast<uint8_t*>(outBuffer.bits);
            for (int y = 0; y < outBuffer.height; y++) {
                for (int x = 0; x < outBuffer.width; x++) {
                    uint8_t* pixel = img + (4 * (y * outBuffer.stride + x));
                    pixel[0] = color.r;
                    pixel[1] = color.g;
                    pixel[2] = color.b;
                    pixel[3] = color.a;
                }
            }
            if (unlock) {
                 //方法5
                 surface->unlockAndPost();
            }
        }

        void tearDown(){
              mComposerClient->dispose();
        }

        void fillSurfaceColor(){

        }
      public:
         sp<SurfaceComposerClient> mComposerClient;
         sp<SurfaceControl> mSurfaceControl;
     };

}

int main(){
   android::SurfaceControlTest sc;
   sc.fillSurfaceRGBA8(RED,true);
   usleep(5000000);
   sc.fillSurfaceRGBA8(BLUE,true);
   usleep(5000000);
   sc.tearDown();
   return 1;
}

代码运行效果图如下所示:

SurfaceControl测试效果图


示例代码通过5步实现了如上所示的效果。主要是对SurfaceFlinger代理类SurfaceControl进行操作。方法3、方法5对View绘制有一定了解的小伙伴应该不陌生,方法4是对数据进行填充。
SurfaceControl作为SurfaceFlinger代理类在android Framework UI绘制做了承上启下的作用:上接android UI Framework,下接SurfaceFlinger。

二、SurfaceControl上层类

本节简要介绍SurfaceControl直接对接上层类:ViewRootImpl。这里我们摘取ViewRootImpl中CPU绘制的部分代码:

//frameworks/base/core/java/android/view/ViewRootImpl.java
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
            boolean scalingRequired, Rect dirty, Rect surfaceInsets) {
            ...
       //步骤1:Surface进行lock操做
       canvas = mSurface.lockCanvas(dirty);
            ...
       //步骤2:调用了ViewGroup的 draw 方法
       mView.draw(canvas);
            ...
       //步骤3:数据发送给 SurfaceFlinger
       surface.unlockCanvasAndPost(canvas);
}

步骤1,步骤3后续会调用native代码:

//frameworks/base/core/jni/android_view_Surface.cpp
static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
        jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
        ...
       ANativeWindow_Buffer buffer;
       status_t err = surface->lock(&buffer, dirtyRectPtr);
        ...
}

static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
        jlong nativeObject, jobject canvasObj) {
    sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
    ...
    // unlock surface
    status_t err = surface->unlockAndPost();
    ...
}

surface->lock(),*surface->unlockAndPost()*与C++程序方法3,方法5一致。
步骤2(作用类似C++程序方法4)流程比较复杂,调用二维图形库Skia,这里不做赘述。下面附录一张时序图,简要描述这个流程。
软件绘制

总结

一个简单的C++程序到这里就介绍完了。本节简要介绍了SurfaceControl,下一章笔者将从WindowManager.addView()这个方法开始,梳理View创建过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值