首页 文章 精选 留言 我的

精选列表

搜索[SpringBoot4],共10000篇文章
优秀的个人博客,低调大师

Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析(4

成员变量fd指向一个文件描述符,这个文件描述符要么指向帧缓冲区设备,要么指向一块匿名共享内存,取决于它的宿主结构体private_handle_t描述的一个图形缓冲区是在帧缓冲区分配的,还是在内存中分配的。 成员变量magic指向一个魔数,它的值由静态成员变量sMagic来指定,用来标识一个private_handle_t结构体。 成员变量flags用来描述一个图形缓冲区的标志,它的值要么等于0,要么等于PRIV_FLAGS_FRAMEBUFFER。当一个图形缓冲区的标志值等于PRIV_FLAGS_FRAMEBUFFER的时候,就表示它是在帧缓冲区中分配的。 成员变量size用来描述一个图形缓冲区的大小。 成员变量offset用来描述一个图形缓冲区的偏移地址。例如,当一个图形缓冲区是在一块内存中分块的时候,假设这块内存的地址为start,那么这个图形缓冲区的起始地址就为start + offset。 成员变量base用来描述一个图形缓冲区的实际地址,它是通过成员变量offset来计算得到的。例如,上面计算得到的start + offset的值就保存在成员变量base中。 成员变量pid用来描述一个图形缓冲区的创建者的PID。例如,如果一个图形缓冲区是在ID值为1000的进程中创建的,那么用来描述这个图形缓冲区的private_handle_t结构体的成员变量pid的值就等于1000。 结构体private_handle_t的静态成员变量sMagic前面已经描述过了,另外两个静态成员变量sNumInts和sNumFds的值分别等于1和6,表示结构体private_handle_t包含有1个文件描述符和6个整数,它们是用来初始化结构体private_handle_t的父类native_handle_t的成员变量numInts和numFds的,如结构体private_handle_t的构造函数所示。从这里就可以看出,结构体private_handle_t的父类native_handle_t的成员变量data所指向的缓冲区就是由结构体private_handle_t的成员变量fds、magic、flags、size、offset、base和pid所占用的连续内存块来组成的,一共包含有7个整数。 结构体private_handle_t还定义了一个静态成员函数validate,用来验证一个native_handle_t指针是否指向了一个private_handle_t结构体。 至此,Gralloc模块的加载过程以及相关的数据结构体就介绍到这里,接下来我们分别分析定义在Gralloc模块中的gralloc和fb设备的打开过程。 2. gralloc设备的打开过程 在Gralloc模块中,gralloc设备的ID值定义为GRALLOC_HARDWARE_GPU0。GRALLOC_HARDWARE_GPU0是一个宏,定义在文件hardware/libhardware/include/hardware/gralloc.h中, 如下所示: #defineGRALLOC_HARDWARE_GPU0"gpu0" gralloc设备使用结构体alloc_device_t 来描述。结构体alloc_device_t有两个成员函数alloc和free,分别用来分配和释放图形缓冲区。 结构体alloc_device_t 也是定义在文件hardware/libhardware/include/hardware/gralloc.h中, 如下所示: typedefstructalloc_device_t{ structhw_device_tcommon; int(*alloc)(structalloc_device_t*dev, intw,inth,intformat,intusage, buffer_handle_t*handle,int*stride); int(*free)(structalloc_device_t*dev, buffer_handle_thandle); }alloc_device_t; Gralloc模块在在文件hardware/libhardware/include/hardware/gralloc.h中定义了一个帮助函数gralloc_open,用来打开gralloc设备,如下所示: staticinlineintgralloc_open(conststructhw_module_t*module, structalloc_device_t**device){ returnmodule->methods->open(module, GRALLOC_HARDWARE_GPU0,(structhw_device_t**)device); } 参数module指向的是一个用来描述Gralloc模块的hw_module_t结构体,它的成员变量methods所指向的一个hw_module_methods_t结构体的成员函数open指向了Gralloc模块中的函数gralloc_device_open。 函数gralloc_device_open定义在文件hardware/libhardware/modules/gralloc/gralloc.cpp文件中,如下所示: structgralloc_context_t{ alloc_device_tdevice; /*ourprivatedatahere*/ }; ...... intgralloc_device_open(consthw_module_t*module,constchar*name, hw_device_t**device) { intstatus=-EINVAL; if(!strcmp(name,GRALLOC_HARDWARE_GPU0)){ gralloc_context_t*dev; dev=(gralloc_context_t*)malloc(sizeof(*dev)); /*initializeourstatehere*/ memset(dev,0,sizeof(*dev)); /*initializetheprocs*/ dev->device.common.tag=HARDWARE_DEVICE_TAG; dev->device.common.version=0; dev->device.common.module=const_cast<hw_module_t*>(module); dev->device.common.close=gralloc_close; dev->device.alloc=gralloc_alloc; dev->device.free=gralloc_free; *device=&dev->device.common; status=0; } ...... returnstatus; } 这个函数主要是用来创建一个gralloc_context_t结构体,并且对它的成员变量device进行初始化。结构体gralloc_context_t的成员变量device的类型为gralloc_device_t,它用来描述一个gralloc设备。前面提到,gralloc设备是用来分配和释放图形缓冲区的,这是通过调用它的成员函数alloc和free来实现的。从这里可以看出,函数gralloc_device_open所打开的gralloc设备的成员函数alloc和free分别被设置为Gralloc模块中的函数gralloc_alloc和gralloc_free,后面我们再详细分析它们的实现。 至此,gralloc设备的打开过程就分析完成了,接下来我们继续分析fb设备的打开过程。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/967071,如需转载请自行联系原作者

优秀的个人博客,低调大师

MaxCompute Studio使用心得系列4——可视化查看所有job并分析运行情况

在使用MaxCompute的时候,很多同学会关注当前项目有多少任务在执行,哪些任务耗时长,哪些任务已经完成,并且能通过任务的logview来分析任务耗时长的原因。 ofo的同学选择自己搭建任务管理平台通过sdk函数获取MaxCompute 相关job信息进行管理。如《MaxCompute的任务状态和多任务执行》所分享。 其他的没有精力自己搭建平台,可以通过show p -all;命令查看所有job,再通过wait instanceid;查看这个job的logview,最后通过logview再查看具体的执行日志。如《如何在客户端上追踪一个任务信息》所介绍。 今天我要分享的是通过MaxCompute Studio可以可视化查看项目想的所有job并分析运行情况。具体操作如下: 查看某个项目下,过去24小时的所有job列表,并查看那些job耗时最

优秀的个人博客,低调大师

Android应用程序组件Content Provider在应用程序之间共享数据的原理分析(4

Step 16. CursorWindow.native_init 这个函数定义在frameworks/base/core/jni/android_database_CursorWindow.cpp文件中,对应的函数为native_init_memory函数: staticJNINativeMethodsMethods[]= { ...... {"native_init","(Landroid/os/IBinder;)V",(void*)native_init_memory}, }; 函数native_init_memory的实现如下所示: staticvoidnative_init_memory(JNIEnv*env,jobjectobject,jobjectmemObj) { sp<IMemory>memory=interface_cast<IMemory>(ibinderForJavaObject(env,memObj)); ...... CursorWindow*window=newCursorWindow(); ...... if(!window->setMemory(memory)){ ...... } ...... SET_WINDOW(env,object,window); } 函数首先是将前面Step 15中传进来的Binder接口转换为IMemory接口,接着创建一个C++层的CursorWindow对象,再接着用这个IMemory接口来初始化这个C++层的CursorWindow对象,最后像前面的Step 8一样,通过宏SET_WINDOW把这个C++层的CursorWindow对象和前面在Step 15中创建的Java层CursorWindow对象关联起来。 下面我们就重点关注CursorWindow类的setMemory函数的实现,看看它是如何使用这个IMemory接口来初始化其内部的匿名共享内存对象的。 Step 17. CursorWindow.setMemory 这个函数定义在frameworks/base/core/jni/CursorWindow.cpp文件中: boolCursorWindow::setMemory(constsp<IMemory>&memory) { mMemory=memory; mData=(uint8_t*)memory->pointer(); ...... mHeader=(window_header_t*)mData; //Makethewindowread-only ssize_tsize=memory->size(); mSize=size; mMaxSize=size; mFreeOffset=size; ...... returntrue; } 从前面一篇文章 Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析中,我们知道,这里得到的IMemory接口,实际上是一个Binder引用,它指向前面在Step 9中创建的MemoryBase对象,当我们第一次调用这个接口的pointer函数时,它便会通过Binder进程间通信机制去请求这个MemoryBase对象把它内部的匿名共享内存文件描述符返回来给它,而Binder驱动程序发现要传输的是一个文件描述符的时候,就会在目标进程中创建另外一个文件描述符,这个新建的文件描述符与要传输的文件描述符指向的是同一个文件,在我们这个情景中,这个文件就是我们前面创建的匿名共享内存文件了。因此,在目标进程中,即在Content Provider进程中,它可以通过这个新建的文件描述符来访问这块匿名共享内存,这也是匿名共享内存在进程间的共享原理,具体可以参考另外一篇文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析 。 这样,在Content Provider这一侧,就可以把第三方应用程序请求的数据保存在这个匿名共享内存中了,回到前面的Step 14中,下一步要执行的函数便是bulkQuery了,它的作用为请求的数据制定好一个SQL数据库查询计划。这个bulkQuery函数是由一个实现了IContentProvider接口的Binder对象来实现的,具体可以参考前面一篇文章 Android应用程序组件Content Provider的启动过程源代码分析 中,这个Binder对象的实际类型是定义在ContentProivder类内部的Transport类。 Step 18. Transport.bulkQuery 这个函数定义在frameworks/base/core/java/android/content/ContentProvider.java文件中: publicabstractclassContentProviderimplementsComponentCallbacks{ ...... classTransportextendsContentProviderNative{ ...... publicIBulkCursorbulkQuery(Uriuri,String[]projection, Stringselection,String[]selectionArgs,StringsortOrder, IContentObserverobserver,CursorWindowwindow){ ...... Cursorcursor=ContentProvider.this.query(uri,projection, selection,selectionArgs,sortOrder); ...... returnnewCursorToBulkCursorAdaptor(cursor,observer, ContentProvider.this.getClass().getName(), hasWritePermission(uri),window); } ...... } ...... } 这个函数主要做了两件事情,一是调用ContentProvider的子类的query函数构造一个数据库查询计划,注意,从这个函数返回来的时候,还没有真正执行数据库查询的操作,而只是按照查询条件准备好了一个SQL语句,要等到第一次使用的时候才会去执行数据库查询操作;二是使用前面一步得到的Cursor接口以及传下来的参数window来创建一个CursorToBulkCursorAdaptor对象,这个对象实现了IBulkCursor接口,同时它也是一个Binder对象,是用来返回给第三方应用程序使用的,第三方应用程序必须通过这个接口来获取从ContentProvider中查询得到的数据,而这个CursorToBulkCursorAdaptor对象的功能就是利用前面获得的Cursor接口来执行数据库查询操作,然后把查询得到的结果保存在从参数传下来的window对象内部所引用的匿名共享内存中去。我们先来看ContentProvider的子类的query函数的实现,在我们这个情景中,这个子类就是ArticlesProvider了,然后再回过头来看看这个CursorToBulkCursorAdaptor对象是如何把数据库查询计划与匿名共享内存关联起来的。 Step 19. ArticlesProvider.query 这个函数定义在前面一篇文章 Android应用程序组件Content Provider应用实例 介绍的应用程序ArtilcesProvider源代码工程目录下,在文件packages/experimental/ArticlesProvider/src/shy/luo/providers/articles/ArticlesProvider.java中: publicclassArticlesProviderextendsContentProvider{ ...... @Override publicCursorquery(Uriuri,String[]projection,Stringselection,String[]selectionArgs,StringsortOrder){ SQLiteDatabasedb=dbHelper.getReadableDatabase(); SQLiteQueryBuildersqlBuilder=newSQLiteQueryBuilder(); Stringlimit=null; switch(uriMatcher.match(uri)){ ...... caseArticles.ITEM_POS:{ Stringpos=uri.getPathSegments().get(1); sqlBuilder.setTables(DB_TABLE); sqlBuilder.setProjectionMap(articleProjectionMap); limit=pos+",1"; break; } ...... } Cursorcursor=sqlBuilder.query(db,projection,selection,selectionArgs,null,null,TextUtils.isEmpty(sortOrder)?Articles.DEFAULT_SORT_ORDER:sortOrder,limit); ...... returncursor; } ...... } 从前面的Step 1中可以看到,传进来的参数uri的值为“content://shy.luo.providers.articles/pos”,通过uriMatcher的match函数来匹配这个uri的时候,得到的匹配码为Articles.ITEM_POS,这个知识点可以参考前面这篇文章 Android应用程序组件Content Provider应用实例 。因为我们的数据是保存在SQLite数据库里面的,因此,必须要构造一个SQL语句来将所请求的数据查询出来。这里是通过SQLiteQueryBuilder类来构造这个SQL查询语句的,构造好了以后,就调用它的query函数来准备一个数据库查询计划。Step 20.SQLiteQueryBuilder.query 这个函数定义在frameworks/base/core/java/android/database/sqlite/SQLiteQueryBuilder.java文件中: publicclassSQLiteQueryBuilder { ...... publicCursorquery(SQLiteDatabasedb,String[]projectionIn, Stringselection,String[]selectionArgs,StringgroupBy, Stringhaving,StringsortOrder,Stringlimit){ ...... Stringsql=buildQuery( projectionIn,selection,groupBy,having, sortOrder,limit); ...... returndb.rawQueryWithFactory( mFactory,sql,selectionArgs, SQLiteDatabase.findEditTable(mTables)); } ...... } 这里首先是调用buildQuery函数来构造一个SQL语句,它无非就是根据从参数传来列名子句、select子句、where子句、group by子句、having子句、order子句以及limit子句来构造一个完整的SQL子句,这些都是SQL语法的基础知识了,这里我们就不关注了。构造好这个SQL查询语句之后,就调用从参数传下来的数据库对象db的rawQueryWithFactory函数来进一步操作了。 Step 21. SQLiteDatabase.rawQueryWithFactory 这个函数定义在frameworks/base/core/java/android/database/sqlite/SQLiteDatabase.java文件中: publicclassSQLiteDatabaseextendsSQLiteClosable{ ...... publicCursorrawQueryWithFactory( CursorFactorycursorFactory,Stringsql,String[]selectionArgs, StringeditTable){ ...... SQLiteCursorDriverdriver=newSQLiteDirectCursorDriver(this,sql,editTable); Cursorcursor=null; try{ cursor=driver.query( cursorFactory!=null?cursorFactory:mFactory, selectionArgs); }finally{ ...... } returncursor; } ...... } 这个函数会在内部创建一个SQLiteCursorDriver对象driver,然后调用它的query函数来创建一个Cursor对象,这个Cursor对象的实际类型是SQLiteCursor,下面我们将会看到,前面我们也已经看到,这个SQLiteCursor的内部就包含了一个数据库查询计划。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/967007,如需转载请自行联系原作者

优秀的个人博客,低调大师

仿:Android - 微信 - 朋友圈 - 小视频播放,多 4 句废话算我输

作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguanh/ GitHub : https://github.com/af913337456/ 为了您的直观体验,请务必看完下面 gif 图,源码 gitHub 链接在其之后。 做这个东西的目的是: 完善毕设: 一个没依赖各种云,而使用C++和Golang做后端的仿微信APP 为了避免大家浪费时间,直接先看下面的 Gif,略大,请耐心点。看完后,若你觉得会需要到,那么就请听我继续。 gif 链接 http://123.57.244.105:8081/commentthumb/GIF.gif git显示,略大,请耐心 GitHub 链接 废话一句:这个显示只是其中一部分,重点是:FFmpeg + Camera 的录制部分,所以,你的星星(star)也是一种更新通知 (我通知你)。 https://github.com/af913337456/WeChatVideoView 功能点 如果你看完上面的gif图,你会发现如下几点功能 (Function list): 1,直观的 播放前,可以显示封面缩略图 播放时,如果还没有本地缓存,那么先进行下载 下载过程中,显示圆型区域进度效果 下载后,播放完毕后可以循环播放 播放已经播放过的,是具备本地缓存的,也就是既能播放网络,也能播放本地 2,隐藏的 低耗电量 低内存占用 无延迟图与视频切换 低耦合,高内聚,几行代码接入,一共3个类 解析 直观的功能点,几乎就是和新版微信的一样,从朋友圈点击一个视频,然后进入到一个 Activity 页面进行加载以及播放。 为什么低耗电量和低内存占用? 因为采用的是 SurfaceView 而不是 TextureView,图与视频切换的切换延迟也是这个原因。 在你的 Activity 中这样使用 这样就会以 id 为 activity_main 的 Relativelayout 为父容器装载。 因为要避免内存泄露,所以你还需要做完下面的一些步骤,不会超过6行代码。 技术点 (可以不看) 1,下载操作: 自定义 AsyncTask。PS:AsyncTask 比 Thread + handler 重量级却方便(回调进度),但是,如果是 即放即用,结束即销毁,那么,no need to think about this; 2,视频播放组合拳: surfaceView + mediaPlayer surfaceView 用作显示,mediaPlayer 用来解码 两者关系: mediaPlayer 绑定 surfaceView。 为什么不用 TextrueView? 3,进度区域 自定义 View,3个画笔绘制,一个圆,一个边,一个扇区。 如果您认为这篇文章还不错或者有所收获,您可以通过扫描一下下面的支付宝二维码 打赏我一杯咖啡【物质支持】,也可以点击右下角的【推荐】按钮【精神支持】,因为这两种支持都是我继续写作,分享的最大动力、

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册