首页 文章 精选 留言 我的

精选列表

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

Android SDCard UnMounted 流程分析(二)

上一篇讲到通过NetlinkManager发送uevent 命令到NetlinkHandler 的onEvent,代码如下: voidNetlinkHandler::onEvent(NetlinkEvent*evt){ VolumeManager*vm=VolumeManager::Instance(); const char*subsys=evt->getSubsystem(); if(!subsys){ SLOGW( " Nosubsystemfoundinnetlinkevent "); return; } SLOGD( " NetlinkHandler:OnEventsubsysvaluesis%s ",subsys); if(!strcmp(subsys, " block ")){ SLOGD( " NetlinkHandler:onEvent "); vm->handleBlockEvent(evt); } } 在NetlinkHandler 里面得一个VolumeManager,当收到的命令为block时调用VolumnManager的handleBlockEvent,如上加红加粗的代码。 handleBlockEvent实则是通过一个循环将事先将main事先读取的配置文件:etc/vold.fstab存进VolumeCollection,得到VolumeCollection的对象,然后调用Volume 的handleBlockEvent,如代码: voidVolumeManager::handleBlockEvent(NetlinkEvent*evt){ const char*devpath=evt->findParam( " DEVPATH "); /* Lookupavolumetohandlethisdevice */ VolumeCollection::iteratorit; boolhit= false; for(it=mVolumes->begin();it!=mVolumes->end();++it){ if(! (*it)->handleBlockEvent(evt)){ #ifdefNETLINK_DEBUG SLOGD( " Device'%s'eventhandledbyvolume%s\n ",devpath,(*it)->getLabel()); #endif hit= true; break; } } if(!hit){ #ifdefNETLINK_DEBUG SLOGW( " Novolumeshandledblockeventfor'%s' ",devpath); #endif } 看一下Volume 的handleblockEvent代码: intVolume::handleBlockEvent(NetlinkEvent*evt){ errno=ENOSYS; return- 1; 看起来好像没做什么事,其实真的实现在于Volume 的子类,DirectVolume,DirectVolme 中重写了handleBlockEvent,看代码: intDirectVolume::handleBlockEvent(NetlinkEvent*evt){ const char*dp=evt->findParam( " DEVPATH "); PathCollection::iteratorit; for(it=mPaths->begin();it!=mPaths->end();++it){ if(!strncmp(dp,*it,strlen(*it))){ /* Wecanhandlethisdisk */ intaction=evt->getAction(); const char*devtype=evt->findParam( " DEVTYPE "); if(action==NetlinkEvent::NlActionAdd){ intmajor=atoi(evt->findParam( " MAJOR ")); intminor=atoi(evt->findParam( " MINOR ")); charnodepath[ 255]; snprintf(nodepath, sizeof(nodepath), " /dev/block/vold/%d:%d ", major,minor); if(createDeviceNode(nodepath,major,minor)){ SLOGE( " Errormakingdevicenode'%s'(%s) ",nodepath, strerror(errno)); } if(!strcmp(devtype, " disk ")){ handleDiskAdded(dp,evt); } else{ handlePartitionAdded(dp,evt); } } else if(action==NetlinkEvent::NlActionRemove){ if(!strcmp(devtype, " disk ")){ handleDiskRemoved(dp,evt); } else{ SLOGD( " DirectVolume:handleBlockEvent--->handlePartitionRemoved "); handlePartitionRemoved(dp,evt); } } else if(action==NetlinkEvent::NlActionChange){ if(!strcmp(devtype, " disk ")){ handleDiskChanged(dp,evt); } else{ handlePartitionChanged(dp,evt); } } else{ SLOGW( " Ignoringnonadd/remove/changeevent "); } return 0; } } errno=ENODEV; return- 1; } 因为我的板子还未完善,所以这里它认为我的sdcard是一个分区,但无关紧要,原理一样,就根据分区的代码跟踪。:handlePartitionRemoved,由于代码过多,只贴出核心代码: voidDirectVolume::handlePartitionRemoved( const char*devpath,NetlinkEvent*evt){ if((dev_t)MKDEV(major,minor)==mCurrentlyMountedKdev){ /* *Yikes,ourmountedpartitionisgoingaway! */ snprintf(msg, sizeof(msg), " Volume%s%sbadremoval(%d:%d) ", getLabel(),getMountpoint(),major,minor); SLOGD( " DirectVolume:(dev_t)MKDEV(major,minor)==mCurrentlyMountedKdev:%d,msgis:%s. ",mCurrentlyMountedKdev,msg); mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,msg,false); if(mVm->cleanupAsec( this, true)){ SLOGE( " FailedtocleanupASEC-unmountwillprobablyfail! "); } if( Volume::unmountVol(true,false)){ SLOGE( " Failedtounmountvolumeonbadremoval(%s) ", strerror(errno)); // XXX:Atthispointwe'rescrewedfornow } else{ SLOGD( " Crisisaverted "); } } } 到此,直接调用父类的unmountVol方法,unmountVol会通过setState通知框架状态改变。代码太多,只推荐核心代码: intVolume::unmountVol( boolforce, boolrevert){ setState(Volume::State_Unmounting); } 而setState会通过socket将msg消息传给框架 mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange, msg, false); 接下去的步骤是关于socket的操作,就不深入了。 小结 到了这一步,Vold 向上层反馈的动作基本己经完成,下一篇文章将会讲解Framework 如何取得Vold 反馈过来的数据。 本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/814963 ,如需转载请自行联系原作者

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

Android OpenGL ES 应用(二) 纹理

上一篇讲了基础入门OpenGL (一),这一次主要学习OpenGL 纹理基本学习总结 要是做复杂的OpenGL应用程序,一定会用到纹理技术。纹理说白了就是把图片或者视频图像绘制到OpenGL空间中。 因此纹理也有坐标系,称ST坐标。或者UV 上面是纹理坐标空间。但没有固定的方向 以下演示载入一张image作为纹理贴图。 public class TextureUtils { public static int createTexture(InputStream ins) { int[] textures = new int[1]; GLES20.glGenTextures(1, textures, 0);//生成一个纹理 int textureId = textures[0]; GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE); //上面是纹理贴图的取样方式,包含拉伸方式,取临近值和线性值 Bitmap bitmap = BitmapFactory.decodeStream(ins); GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);//让图片和纹理关联起来。载入到OpenGl空间中 Log.d("OPENGL","bitmap:" + bitmap); bitmap.recycle();//不须要。能够释放 return textureId; } } public class MyRenderer implements Renderer { public static float[] projMatrix = new float[16];// 投影 public static float[] viewMatrix = new float[16];// 相机 public static float[] mViewPjMatrix;// 总变换矩阵 public static float[] matrixs = new float[16]; public static int textureId = -1; Context context; MyDrawModel drawModel; public MyRenderer(Context context) { this.context = context; } @Override public void onDrawFrame(GL10 arg0) { GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); Log.e("", "textureId:" + textureId); drawModel.drawFrame(textureId); } @Override public void onSurfaceChanged(GL10 arg0, int w, int h) { GLES20.glViewport(0, 0, w, h); float ratio = (float) w / h; Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1, 1, 1, 10);//投影矩阵设置 Matrix.setLookAtM(viewMatrix, 0, 0, 0, 3, 0, 0, 0, 0.0f, 1.0f, 0.0f);//摄像机坐标设置 } @Override public void onSurfaceCreated(GL10 g, EGLConfig eglConfig) { GLES20.glClearColor(0.5f,0.5f,0.5f, 1.0f); GLES20.glEnable(GLES20.GL_DEPTH_TEST); InputStream ins = null; drawModel = new MyDrawModel(); drawModel.init(); try { ins = context.getAssets().open("house.jpg"); textureId = TextureUtils.createTexture(ins); Log.e("", "textureId:" + textureId); } catch (IOException e) { e.printStackTrace(); } finally { try { ins.close(); } catch (IOException e) { e.printStackTrace(); } } GLES20.glDisable(GLES20.GL_CULL_FACE); } } public class MyDrawModel { private int programId; private int mVPMatrixHandle; // 总变换矩阵引用id private int positionHandle; // 顶点位置id private int texCoorHandle; // 顶点纹理坐标id private FloatBuffer vertexBuffer; private FloatBuffer texCoorBuffer; public MyDrawModel() { } public void init() { initData(); int vertexsharder = GLHelper.compileScript(GLES20.GL_VERTEX_SHADER, GLScript.vertex2); int fragmentsharder = GLHelper.compileScript(GLES20.GL_FRAGMENT_SHADER, GLScript.fragment2); programId = GLHelper.linkAttach(vertexsharder, fragmentsharder); boolean isOK = GLHelper.checkProgram(programId); positionHandle = GLES20.glGetAttribLocation(programId, "aPosition"); texCoorHandle = GLES20.glGetAttribLocation(programId, "aTexCoor"); mVPMatrixHandle = GLES20.glGetUniformLocation(programId, "uMVPMatrix"); Log.d("OPENGL", "positionHandle:" + positionHandle + ";texCoorHandle:" + texCoorHandle + ";mVPMatrixHandle:" + mVPMatrixHandle + ";" + isOK); } private void initData() { //X,Y,Z,绘画的顶点 float vertices[] = new float[] { 0, 0, 0, -1.8f, -1f, 0, 1.8f, -1f, 0, 1.8f, 1f, 0, -1.8f, 1f, 0, -1.8f, -1f, 0 }; ByteBuffer vb = ByteBuffer.allocateDirect(vertices.length * 4); vb.order(ByteOrder.nativeOrder()); vertexBuffer = vb.asFloatBuffer(); vertexBuffer.put(vertices); vertexBuffer.position(0); //纹理空间坐标 S,T float texCoor[] = new float[] { 0.5f, 0.5f, 0f, 1f, 1f, 1f, 1f, 0f, 0f, 0f, 0f, 1f }; ByteBuffer cb = ByteBuffer.allocateDirect(texCoor.length * 4); cb.order(ByteOrder.nativeOrder()); texCoorBuffer = cb.asFloatBuffer(); texCoorBuffer.put(texCoor); texCoorBuffer.position(0); } public void drawFrame(int textureId) { GLES20.glUseProgram(programId); // // 初始化矩阵 Matrix.setRotateM(MyRenderer.matrixs, 0, 0, 1, 0, 0); Matrix.translateM(MyRenderer.matrixs, 0, 0, 0, 1); //矩阵转换 ,投影矩阵,摄像机矩阵。模型矩阵 MyRenderer.mViewPjMatrix = new float[16]; Matrix.multiplyMM(MyRenderer.mViewPjMatrix, 0, MyRenderer.viewMatrix,0, MyRenderer.matrixs, 0); Matrix.multiplyMM(MyRenderer.mViewPjMatrix, 0, MyRenderer.projMatrix,0, MyRenderer.mViewPjMatrix, 0); GLES20.glUniformMatrix4fv(mVPMatrixHandle, 1, false, MyRenderer.mViewPjMatrix, 0); GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 3 * 4, vertexBuffer); GLES20.glVertexAttribPointer(texCoorHandle, 2, GLES20.GL_FLOAT, false, 2 * 4, texCoorBuffer); GLES20.glEnableVertexAttribArray(positionHandle); GLES20.glEnableVertexAttribArray(texCoorHandle); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 6);//六个定点,绘制三角形 } } OpenGL须要把设备的坐标归一化到[-1,-1]空间中。所以这里涉及到矩阵相乘的理论,包含世界坐标,物体坐标,摄像机坐标的转换。以后会具体介绍。 public class GLScript { public GLScript() { } public static final String vertex1 = "attribute vec4 mPosition;\n" + "void main()\n" + "{\n" + "gl_Position=mPosition;\n " + "}\n"; public static final String fragment1 = "precision mediump float;\n" + "uniform vec4 mColor;\n" + "void main(){ gl_FragColor=mColor;\n}"; public static final String vertex2 = "uniform mat4 uMVPMatrix;\n" + "attribute vec3 aPosition;\n" + "attribute vec2 aTexCoor;\n" + "varying vec2 vTextureCoord;\n" + "void main() { \n" + "gl_Position = uMVPMatrix * vec4(aPosition,1);\n" + "vTextureCoord = aTexCoor;\n" + "}\n" ; public static final String fragment2 = "precision mediump float;\n" + "varying vec2 vTextureCoord;\n" + "uniform sampler2D sTexture;\n" + "void main() { \n" + "vec2 coord = vTextureCoord;\n" + "coord.s = coord.s * 0.5;\n" //事实上是去图像的一半,向量缩小了 + "gl_FragColor = texture2D(sTexture, coord); \n" + "}\n" ; } coord.s = coord.s * 0.5; 这样是取纹理图像的一半,显示到界面上也就是图片的前半部分内容 其他的工具类和上一篇文章一样。 内容显示 原图: 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5095000.html,如需转载请自行联系原作者

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

android110 jni01

##交叉编译(编译就是编译成汇编指令,使得电脑能够识别,比如windows平台模拟linux平台编译出来得程序可以在linux上运行。) * 在一个平台下,编译出另一个平台能够执行的二进制的代码 * 平台:windows,mac os,linux * 处理器:x86,arm,mips ##交叉编译的原理 * 源代码->编译->链接->可执行程序 * 模拟其他平台的特性 ##交叉编译的工具链 * 多个工具的集合,一个工具使用完后接着调用下一个工具 ##常见工具 * NDK:native developement kit:开发jni必备类似于开发安卓需要sdk,就是模拟其他平台特性来编译代码的工具(需要在谷歌下载,) * CDT:C/C++ developement tools:高亮显示c语言关键字(CDT是一个插件,如果eclips是从sdk解压的则这个插件已经安装了,ADT也已经安装了,) * cygwin:一个模拟器,可以再windows下运行linux指令 ##NDK目录结构 * docs:帮助文档 * build/tools:linux的批处理文件 * platforms:编译c代码需要使用的头文件和类库 * prebuilt:预编译使用的二进制可执行文件 * sample:jni的使用例子 * source:ndk的源码 * toolchains:工具链 * ndk-build.cmd:编译打包c代码的一个指令 本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/p/4985824.html,如需转载请自行联系原作者

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

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文件系统,支持十年生命周期更新。

优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

用户登录
用户注册