本篇文章根据前面的分析来实际操作画一个窗口,使用纯native API来实现,这里的native API并非ndk,而是native层函数,需要在AOSP编译环境下进行。 首先在 接着来看看 我们的代码就按上面步骤来写, 上面的代码基本上是按照画窗口的流程来实现的,看下上面 会调用 这个函数指针是在 这里面有很多函数,根据传递过来的参数调用不同的 画一个窗口有很多信息必须设置,在之前分析的 编译测试程序:mmm frameworks/native/libs/gui/drawWindowTest/ 运行这个测试程序:adb shell /system/bin/drawWindow/frameworks/native/libs/gui/
目录下创建drawWindowTest
测试目录,drawWindowTest
目录中创建Android.bp
和DrawWindowTest.cpp
:
Android.bp:cc_binary { name: "drawWindow", srcs: ["DrawWindowTest.cpp"], shared_libs: [ "liblog", "libbinder", "libgui", "libui", "libutils", ], }
DrawWindowTest.cpp
怎么写,前面几篇文章的分析我们大致了解了画一个窗口的流程:
SurfaceFlinger
进程建立连接Surface
对应SurfaceFlinger
进程Layer
Surface
,还需要将Surface
连接到BufferQueue
Surface
的各种数据,如宽高,格式,Z-order,位置,缩放等dequeueBuffer
获取bufferqueueBuffer
将buffer送到SurfaceFlinger
合成DrawWindowTest.cpp
源码如下:#include <binder/ProcessState.h> #include <binder/IPCThreadState.h> #include <system/window.h> #include <ui/GraphicBuffer.h> #include <ui/Fence.h> #include <utils/Log.h> #include <utils/RefBase.h> #include <gui/SurfaceControl.h> #include <gui/SurfaceComposerClient.h> #include <binder/IBinder.h> #include <ui/DisplayInfo.h> #include <gui/Surface.h> using namespace android; //状态值 status_t err; sp<SurfaceComposerClient> mSurfaceComposerClient; sp<SurfaceControl> mSurfaceControl; //屏幕宽高 int mWidth,mHeight; //GraphicBuffer的父类ANativeWindowBuffer ANativeWindowBuffer *mNativeBuffer = nullptr; //连接SurfaceFlinger void connectSurfaceFlinger(); //获取Surface sp<ANativeWindow> getSurface(); //连接BufferQueue void connectBufferQueue(ANativeWindow *surface); //设置Transaction void setBufferTransaction(); //设置其他信息 void setBuffer(ANativeWindow *surface); int main() { sp<ProcessState> proc(ProcessState::self()); ProcessState::self()->startThreadPool(); //连接SurfaceFlinger connectSurfaceFlinger(); //获取surface ANativeWindow *surface = getSurface().get(); //surface连接bufferqueue connectBufferQueue(surface); //设置Transaction setBufferTransaction(); //设置其他信息 setBuffer(surface); int fenceFD= -1; //申请buffer err = surface->dequeueBuffer(surface, &mNativeBuffer, &fenceFD); if (err != NO_ERROR) { ALOGE("dequeueBuffer err...."); } //通过Fence确认申请的buffer是否完全被上一个使用者使用完 sp<Fence> fence(new Fence(fenceFD)); //等待收到releaseFence int waitResult = fence->waitForever("dequeueBuffer_EmptyNative"); if (waitResult != OK) { ALOGE("Fence wait err...."); } //ANativeWindowBuffer转GraphicBuffer sp<GraphicBuffer> buff(GraphicBuffer::from(mNativeBuffer)); //buffer数据 uint8_t *data = NULL; //通过lock先锁住buffer err = buff->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&data)); if (err != NO_ERROR) { ALOGE("lock buffer err...."); } //填充数据,这里直接赋值为0,会画一个黑色窗口 *data = 0; err = buff->unlock(); if (err != NO_ERROR) { ALOGE("unlock buffer err...."); } //将填充好的buffer送到SurfaceFlinger进行合成显示 err = surface->queueBuffer(surface, buff->getNativeBuffer(), -1); if (err != NO_ERROR) { ALOGE("queueBuffer buffer err...."); return err; } mNativeBuffer = NULL; IPCThreadState::self()->joinThreadPool(); return EXIT_SUCCESS; } //1.创建SurfaceComposerClient,这是SurfaceFlinger的Client端 void connectSurfaceFlinger(){ mSurfaceComposerClient = new SurfaceComposerClient; err = mSurfaceComposerClient->initCheck(); if (err != NO_ERROR) { ALOGE("SurfaceComposerClient initCheck err...."); return; } } //2.创建Surface,ANativeWindow是创建Surface父类 sp<ANativeWindow> getSurface(){ sp<IBinder> display = SurfaceComposerClient::getInternalDisplayToken(); android::DisplayInfo mainDisplayInfo; //获取手机的屏幕信息 err = SurfaceComposerClient::getDisplayInfo(display, &mainDisplayInfo); if (err != NO_ERROR) { ALOGE("getDisplayInfo err...."); } //屏幕宽 mWidth = mainDisplayInfo.w; //屏幕高 mHeight = mainDisplayInfo.h; //创建surface对应surfaceflinger进程layer mSurfaceControl = mSurfaceComposerClient->createSurface( String8("drawWindow"), mWidth/2, mHeight/2, PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque); if (mSurfaceControl == NULL || !mSurfaceControl->isValid()) { ALOGE("mSurfaceControl err...."); } //获取surface sp<ANativeWindow> anw = mSurfaceControl->getSurface(); return anw; } //3.Surface连接BufferQueue void connectBufferQueue(ANativeWindow *surface){ err = native_window_api_connect(surface, NATIVE_WINDOW_API_CPU); if (err != NO_ERROR) { ALOGE("connect bufferqueue err...."); } } //4.设置buffer数据 void setBufferTransaction(){ /* setLayer():设置窗口的Z-order setPosition():设置窗口显示的位置 show():设置窗口显示出来 apply():将设置的窗口信息应用到SurfaceFlinger,真正生效 */ SurfaceComposerClient::Transaction{} .setLayer(mSurfaceControl, 0x7FFFFFFF) .setPosition(mSurfaceControl,mWidth/4,mHeight/4) .show(mSurfaceControl) .apply(); } //5.设置buffer void setBuffer(ANativeWindow *surface){ //设置usage err = native_window_set_usage(surface, GRALLOC_USAGE_SW_WRITE_OFTEN); if (err != NO_ERROR) { ALOGE("native_window_set_usage err...."); } //设置transform err = native_window_set_buffers_transform(surface, NATIVE_WINDOW_TRANSFORM_ROT_90); if (err != NO_ERROR) { ALOGE("native_window_set_buffers_transform err...."); } //设置scaling_mode err = native_window_set_scaling_mode( surface, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); if (err != NO_ERROR) { ALOGE("native_window_set_scaling_mode err...."); } }
setBuffer
函数,里面调用了一系列native_window_set_XXX
函数来个Surface
设置各种信息,其实最终都是调用到Surface
中setXXX
函数,native_window_set_XXX
是给外部调用提供操作Surface
的接口,这些函数定义在frameworks/native/libs/nativewindow/include/system/window.h中,举个例子看看native_window_set_usage
函数static inline int native_window_set_usage(struct ANativeWindow* window, uint64_t usage) { return window->perform(window, NATIVE_WINDOW_SET_USAGE64, usage); }
ANativeWindow
的perform
函数:int (*perform)(struct ANativeWindow* window, int operation, ... );
Surface
构造函数中赋值的: ANativeWindow::perform = hook_perform; int Surface::hook_perform(ANativeWindow* window, int operation, ...) { va_list args; va_start(args, operation); Surface* c = getSelf(window); int result = c->perform(operation, args); va_end(args); return result; }
hook_perform
函数又调用Surface
的perform
函数:int Surface::perform(int operation, va_list args) { int res = NO_ERROR; switch (operation) { case NATIVE_WINDOW_CONNECT: // deprecated. must return NO_ERROR. break; case NATIVE_WINDOW_DISCONNECT: // deprecated. must return NO_ERROR. break; case NATIVE_WINDOW_SET_USAGE: res = dispatchSetUsage(args); break; case NATIVE_WINDOW_SET_CROP: res = dispatchSetCrop(args); break; case NATIVE_WINDOW_SET_BUFFER_COUNT: res = dispatchSetBufferCount(args); ....... }
dispatchXXX
,比如native_window_set_usage
传递的就是NATIVE_WINDOW_SET_USAGE64
,从而调用dispatchSetUsage64
:case NATIVE_WINDOW_SET_USAGE64: res = dispatchSetUsage64(args); break;
dispatchSetUsage64
又调用setUsage
最终将数据设置给了Surface
int Surface::dispatchSetUsage64(va_list args) { uint64_t usage = va_arg(args, uint64_t); return setUsage(usage); }
dequeueBuffer
和queueBuffer
中都有相关判断,比如宽高不能小于0,必须连接BufferQueue
等。
push进手机:
adb push out/target/product/SEOUL_ATT/system/bin/drawWindow /system/bin
效果如下:
通过这一个测试程序结合前几篇理论的文章可以更好的熟悉Android图形架构。
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算