【网学网提醒】:网学会员编辑为广大网友搜集整理了:Android经典rom改造绩等信息,祝愿广大网友取得需要的信息,参考学习。
jdming1982(
网学)贡献
1.Android体系结构android介绍Android的软件层次结构包括一个操作系统,中间件,应用程序。其软件层次结构自上而下可分为:****应用程序应用
程序框架各种库和Android的运行时环境操作系统层
应用程序:以java语言编写,设计用户界面交互设计。Android本身提供了桌面,联系人,电话,浏览器等很多核心的应用。应用程序框架:为应用程序提供系统的API。通过Android的应用程序框架,开发人员可重用各种组件和服务。应用程序的框架组成部分:*UI组件:包括列表,文本框,按钮等UI组件,是用户可视的部分。*ContentProviders:提供了一种应用程序程序可实现数据的访问和共享的机制。*NotificationManager:能让应用程序将自己的警告信息显示在状态栏上,如显示收到新短信,提示电池信息。*ActivityManager:管理应用程序的生命周期,并提供应用程序页面退出的机制。Android库和运行时环境Android包含一些核心的C/C++库,这些库能通过JNI技术供系统的各种组件使用。这些库包括:*系统C库:从BSD继承来的标准C库。*媒体库:包括多种常用的音频,视频格式回放和录制。同时支持静态图像文件,支持MPEG4,MP3,AAC,JPG,PNG,H.264,AMR等多种编码格式。*SurfaceManager:管理显示子系统,并为多个应用程序提供2D和3D的无缝融合。*LibWebCore:浏览器引擎。*SGL:底层的2D图形引擎。*3Dlibrarie:提供3D加速。*FreeType:提供位位图和矢量的字体显示。*SQLite:数据库应用。Android包含了一个核心库,该核心库提供了java语言核心库的大多数功能。每一个Android应用
程序都在自己的进程空间内运行,都拥有一个独立的dalvik虚拟机实现。Dalvik被设计成一个设备,可同时高效的运行多个虚拟系统。dalvik虚拟机依赖于linux内核的一些功能,如线程调度,内存管理。
一.实现Camera功能的相关模块为:1.android_cupcake/packages/apps/Camera/src/com/android/camera此部分内容被编译为Camera.apkandroid_cupcake/framework/base/core/java/android/hardware/Camera.javaandroid_cupcake/framework/base/core/jni/android_hardware_Camera.cpp此部分内容被编译为libandroid_runtime.so中的一部分。2.frameworks/base/include/ui/目录中Camera相关的头文件有以下几个:Camera.hCameraParameters.hICamera.hICameraClient.hICameraService.hCameraHardwareInterface.hFrameworks/base/libs/ui目录中Camera相关的实现文件有以下几个:Camera.cppCameraParameters.cppICamera.cppICameraClient.cppICameraService.cpp这部分的内容
被编译成libui.so。3.Framework/base/camera/libcameraservice其中包含以下两个文件:CameraService.hCameraService.cpp这部分内容被编译成libCameraService.so
4.android_cupcake/vendor/sec_proprietary/libcamera其中包含以下四个文件:S3C6410CameraHWInterface.hS3C6410CameraHWInterface.cppS3C6410Camera.hS3C6410Camera.cpp这部分内容被编译成libcamera.so二.上述四个模块的功能介绍及具体实现2.Android应用程序组成Android应用程序剖析Android应用
程序由四部分组成:1.Activity
2.IntentReceiver3.Service4.ContentProvider并非所有的应用程序都要包括所有四个部分,但是您的应用程序是由其中的组合构成的。一旦您决定使用哪个组件,您需要把它们列出在名为AndroidManifest.xml的文件中。这是一个XML文件,其中声明了您的应用程序中所需要的组件以及它们的功能和需求。ActivityActivity是四个Android构造块中最基本的组件。一个activity通常是一个单独的屏幕。每一个activity作为一个独立的类来实现,均继承自Activity基类。您的activity类将显示一个由若干Views控件组成的用户界面并对事件做出响应。大多数应用程序包含多个屏幕。举例来说,一个文本消息应用程序也许会有一个屏幕,用来显示联系人列表,第二个屏幕用来编辑短消息,还有用来浏览历史消息或者用来更改设置的屏幕。每一个这样的屏幕都将作为一个activity。切换屏幕是通过打开一个新的activity来实现的。在一些实例中,一个activity会将返回值返回给前一个activity,比如,一个允许用户选择图片的activity将返回选中的
图片到调用方。当一个新的屏幕打开,前一个屏幕将暂停并保存在历史堆栈中。用户在历史堆栈中可以回退到前一个屏幕。当屏幕不再使用时,还可以在历史堆栈中删除。Android将保留历史堆栈为从主屏幕开始的每一个应用。Intent以及IntentFiltersAndroid使用一个名为Intent的类来完成屏幕间的切换。Intent类描述了应用
程序想要做什么。一个intent的数据结构包含两个最重要的部分为action(动作)data和(数据)典型的action。有MAIN(activity的入口)、VIEW、PICK、EDIT等。data是以URI的形式表示的。例如,要显示一个人的联系方式,您需要创建一个intent,其中action为VIEW,data为表示这个人的URI。还有一个相关的名叫IntentFilter的类。如果说intent是一个要做什么事的请求的话,那么IntentFilter则是用来描述一个activity能够操作哪些intent。一个能够显示联系人信息的activity将声明一个IntentFilter来描述如何操作VIEW动作和表示这个人的URI。Activities在AndroidManifest.xml中声明IntentFilter类
。屏幕间的切换是通过解析Intent实现的。当前向导航时,activity会自动调用startActivity(intentmyintent)方法。系统会在所有应用
程序中定义的IntentFilter中查找,选择最匹配myintent的Intent对应的activity。新的activity收到intent的通知后,开始运行。Intents解析过程在startActivity()方法被调用时发生,提供了两个好处:
1.Activity能够通过简单的以Intent的形式发送请求来重用其他组件中的功能。2.Activity能够在任何时候由一个带有相同IntentFilter的Activity来替换。IntentReceiver您可以使用IntentReceiver来使您的应用程序代码能够响应外部事件,如电话呼入、数据网络可用、处于晚上时。尽管IntentReceiver可以使用NotificationManager来提醒用户一些感兴趣的事件的发生,但是它并不显示用户界面。IntentReceiver在AndroidManifest.xml中完成注册,当然您也可以在代码中通过Context.registerReceiver()方法完成
注册。您的应用程序的触发不必调用intentreceiver;系统会在需要的时候启动您的应用程序,intentreceiver当被触发时。应用程序也可以通过Context.broadcastIntent()将自身的intent广播给其他应用程序。ServiceService是具有长生命周期,且没有用户界面的程序。典型的例子是正从播放列表中播放歌曲的媒体播放器。在媒体播放器中,可能将有一个或多个activities允许用户选择歌曲并播放它们。然而,音乐回放并不需要activity的操纵,因为用户希望音乐播放能够在屏幕切换到新的屏幕时继续播放。在这个例子中,媒体播放器会调用Context.startService()来启动一个Service在后台运行来播放歌曲。系统将会保持音乐回放service的运行直到其结束。注意您可以通过Context.bindService()方法连接一个service(如果它还没有运行将启动它)。当连接到一个service后,我们还可以通过service提供的接口与之通讯。正如媒体播放器,我们还可以进行暂停、重播等操作。ContentProvider应用程序能够将数据存储在文件、SQLite数据库或者其他有效的机制中。当您想要与其他应用程序共享您的数据时,ContentProvider将会非常有用。ContentProvider也是一个类,其被实现为一组标准的方法,使其他应用
程序能够存储和检索此ContentProvider操作的数据类型。androidIntent机制简介:Android中各个组件主要是通过Intent来通讯。Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,
实现调用者与被调用者之间的解耦。在应用中,我们可以以两种形式来使用Intent:显式Intent:指定了component属性的Intent(调用setComponent(ComponentName)或者setClass(Context,Class)来指定)。通过指定具体的组件类,通知应用启动对应的组件。隐式Intent:没有指定comonent属性的Intent。这些Intent需要包含足够的信息,这样系统才能根据这些信息,在在所有的可用组件中,确定满足此Intent的组件。
对于直接Intent,Android不需要去做解析,因为目标组件已经很明确,Android需要解析的是那些间接Intent,通过解析,将Intent映射给可以处理此Intent的Activity、IntentReceiver或Service。Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。在这个解析过程中,Android是通过Intent的action、type、category这三个属性来进行判断的。1.Camera.APK(androidIntent机制)
Camera.apk实现了五个功能Camerapreview:相机的preview模式Cameratakepic
takePicture完成后,surfaceChanged()将被调用将刚照下的照片显示在屏幕上。Camera.java中的回调接口JpegPictureCallback中的函数onPictureTaken()接着执行。这个函数先调用ImageCapture.storeImage()将jpeg图像数据存储在内存。picture的thumbnail显示过程:ImageCapture.storeImage()>ImageCapture.setLastPictureThumb()>BitmapFactory.decodeByteArray>ImageManager.extractMiniThumb()-->setImageDrawable()ImageManager.extractMiniThumb()通过调用ImageLoader.transform()完成。通过调用MainHandler延迟调用dismissFreezeFrame()释放takepicture分配的空间。然后重新启动RestartPreview().MainHandler.sendEmptyMessageDelayed(RESTART_PREVIEW)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\以上为Camera.java实现takepicture的流程,顺序图。\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
takePicture流程结束,回到preview模式后,按下menu菜单键中的gallery,Camera.java中会执行以下流程:onKeyDown()>onCreateOptionsMenu()>>addBaseMenuItems()会调用MenuHelper.addSwitchModeMenuItem()(switchtovideo;gallery;setting)>onKeyUp()>onMenuOpened()>gotoGallery()会调用Menuhlper.gotoCameraImageGallery()其中的关键代码是:Uritarget=Images.Media.INTERNAL_CONTENT_URI.buildUpon().appendQueryParameter("bucketId",ImageManager.CAMERA_IMAGE_BUCKET_ID).build();Intentintent=newIntent(Intent.ACTION_VIEW,target);activity.startActivity(intent);在函数gotoCameraImageGallery()中构造了一个Intent,并调用ActivityManager的startActivity函数将该Intent发送出去,从而启动另一个Activity.ImageGallery2.同时下拉菜单关闭。通过函数onOptionsMenuClosed()实现的。同时onPause()函数被调
用,在该函数中调用了stopPreview().当跳转到ImageGallery2.java后,执行流程如下:onCreate()>onResume()>ImageGallery2::GridViewspecial.scrollTo()>rebake()>CheckThumbnails()>CameraThreadstartthread()>allImages()>GridViewspecial::start()>ImageBlockManager()>rebake()先调用CheckThumbnails(),在CheckThumbnails()中开了一个线程用来在屏幕上以thumbnails形式显示所有照片:关键语句为:mThumbnailCheckThread.setName("check_thumbnails");
mThumbnailCheckThread.start();mThumbnailCheckThread.toBackground();ImageManager.IImageListlist=allImages(true);mNoImagesView.setVisibility(list.getCount()>0?View.GONE:View.VISIBLE);allImages()中的关键语句:mAllImages=ImageManager.instance().allImages(ImageGallery2.this,getContentResolver(),ImageManager.DataLocation.NONE,mInclusion,mSortAscending?ImageManager.SORT_ASCENDING:ImageManager.SORT_DESCENDING,uri!=null?uri.getQueryParameter("bucketId"):null);allImage调用GridViewspecial::start()GridViewspecial::start()函数调用GridViewspecial::startLoading获得所有图片的thumbnail形式。GridViewspecial::startLoading调用了ImageBlockManager()该函数ImageBlockManager()是通过调用ImageLoader().getBitmap()获得图片的thumbnail形式的。当图片以thumbnail形式显示在屏幕上后,点击其中的任意一个图片将触发以下流程:Menuhelper.addImageMenuItems(增加菜单选项slideshow,rotate,delete,crop,share,setas等)>Menuhelper.MenuItemsResult()>ImageGallery2.addSlideShowMenu()addSlideShowMenu()会发送Intent给ViewImage.java从而使界面跳转到另一个ActivityViewImage.addSlideShowMenu()中的关键语句:Intentintent=newIntent(Intent.ACTION_VIEW,targetUri);intent.putExtra("slideshow",true);startActivity(intent);转到ViewImage.java后的执行流程:onCreate()>ActionMenuButton.init()(初始化Activity上的按钮,左右查看图片的按钮,zoomin,zoomout,)>init()函数会调用makeGetter()>ImageGetter()在ImageGetter中会新开一个线程来获取选中的图片并全屏显示出来。该线程会调用imageLoaded()函数,>setImage()该函数负责将图片显示出来。具体流程如下:>ImageViewTouchBase.setImageBitmapResetBase()>ImageViewTouchBase.setImageBitmap()>ImageViewTouchBase.getImageViewMatrix>ImageViewTouchBase.onLayout()当点击左右查看
图片的按钮或zoomin,zoomout时,viewImage.handleTouchEvent()会响应点击事件,根据所选择的按钮进行不同处理。
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\以上为Camera.java实现
Gallery的过程顺序图
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
当按下屏幕上的switchtovideo按钮后,ActivityManager会发送一个Intent给videoCamera。同时Camera.java调用onOptionsMenuClosed()关闭下拉菜单。同时Camera.java调用onPause
()onPause()中调用stopPreview()退出preview模式。当转到新的ActivityVideoCamera.java后,执行流程如下:onCreate()>ActionMenuButton.init()(初始化屏幕上的Button)>onStart()>onResume()>initializeVideo()>initializeVideo()函数newMediaRecorder(),调用MediaRecorder中的相关函数为录制作准备。接着调用createVideoPath()创建video文件,然后调用MediaRecorder.setPreviewDisplay()MediaRecorder.setPreviewDisplay()通过调用Camera.cpp中的setPreviewDisplay()使Camera进入preview模式。当按下屏幕上的VideoRecorder按钮后,执行流程如下:initializeVideo()函数新建的MediaRecorder开始工作,将收集到的图像数据encoder后存储在创建好的3gp文件中。当再次按下屏幕上的VideoRecorder按钮后,videoCamera.stopVideoRecordingAndDisplayDialog()被调用,它会先调用stopVideoRecording()停止录制过程,再在屏幕上显示按钮:playshareDelete当按下play按钮后,ActivityManager会通过Binder机制发消息给VideoPlayActivity完成播放功能。
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\以上为Camera.java实现VideoRecord的功能\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\当按下下拉菜单中的Setting按钮后,Camera.java会调用stopPreview()停止preview模式。同时ActivityManager发送Intent给CameraSetting,camerasetting中的执行流程:onCreate()>initUI()>onResume()onResume()执行完后,界面上出现setting选项:storelocationinpictures,selectvideoquality当选择selectvideoquality后,updateVideoQuality()>getBooleanPreference()>getIntPreference()被执行界面上会出现:selectvideoquality:Low(forMMSmesssage)High(forSDcard))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\以上为Camera.java实现函数
CameraSeting的过程
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
frameworks/base/core/java/android/hardware/Camera.java通过JNI调用frameworks/base/core/java/android/harware/android_hardware_Camera.cpp中的函数。这部分内容编译进目标libandroid_runtime.so。是Camra.apk的本地部分。android_hardware_Camera.cpp通过调用frameworks/base/include/ui/Camera.h中的函数提供对上层java的接口。
==============================================================libui.so的功能介绍及具体实现================================================================libui.so是Camera功能中实现Binder机制的接口类。提供上层Camera.apk所需要的接口。具体功能的实现由该接口类的实现子类CameraService完成,这部分被编译成libCameraService.so.libui.so中包含的接口类包括:ICameraClientICameraServiceICamera以下分别介绍他们的功能以及包含的主要函数:I
CameraClient代表一个逻辑上的Camera设备,包含与实际Camera通信的全部函数。应用层可以通过接口类ICameraClient的实现子类BpCameraClient中的相关函数来与Camera设备通信。通信过程应用了android提供的Binder机制(后面会介绍)大致过程为:BpCameraClient中的相应函数调用remote()->transact(),这时ICameraClient的实际实现类BnCameraClient中的onTransact()函数会被调用,onTransact()函数中包含一个switch-case函数,根据传过来的参数调用BnCamera端实现的相应函数。由于Camera.apk与libui.so中的Camera接口类同属于一个进程,所以Camera.apk中的本地部分直接调用了ICameraClient的实现子类BnCameraClient中的函数,而不必通过Binder机制。ICameraClient接口中的主要函数:virtualvoidshutterCallback()=0;//按下ShutterButton的回调函数virtualvoidrawCallback(constsp&;picture)=0;//按下ShutterButton的回调函数virtualvoidjpegCallback(constsp&;picture)=0;//按下ShutterButton的回调函数virtualvoidframeCallback(constsp&;frame)=0;//preview模式下,收集到一帧数据时的回调函数。virtualvoiderrorCallback(status_terror)=0;//出错时的回调函数virtualvoidautoFocusCallback(boolfocused)=0;//按下ShutterButton,先会执行autoFocus,执行完autoFocus的回调函数。
ICameraClient的二级子类Camera中的主要函数与ICamera接口中的函数相对应:voiddisconnect();//将ICameraClient与ICamera的绑定断开status_tlock();//防止其他进程使用该ICamera接口status_tunlock();//允许其他进程使用该ICamera接口status_tsetPreviewDisplay(constsp&;surface);//进入preview模式前surface的一些设置status_tstartPreview();//进入到preview模式voidstopPreview();//停止preview模式boolpreviewEnabled();//判断是否处于preview模式status_tautoFocus();//autoFocus过程status_ttakePicture();//takepicturestatus_tsetParameters(constString8&;params);//设置preview或takePicture时的Camera参数String8getParameters()const;//取得preview或takePicture时的Camera参数voidshutterCallback();//按下ShutterButton的回调函数voidrawCallback(constsp&;picture);//按下ShutterButton的回调函数voidjpegCallback(constsp&;picture);//按下ShutterButton的回调函数voidframeCallback(constsp&;frame);//preview模式下,收集到一帧数据时的回调函数。voiderrorCallback(status_terror);//出错时的回调函数voidautoFocusCallback(boolfocused);//按下ShutterButton,先会执行autoFocus,执行完autoFocus的回调函数。CameraClient只是一个逻辑上的Camera设备,并不直接与实际的Camera设备通信。BnCameraClient的子类Camera中定义了函数getCameraService()用于得到CameraService实例。再通过调用CameraServi
ce中的connect()函数得到Camera实例。Camera.cpp中与Camera通信的函数都是通过调用这个Camera实例中的相应函数实现的。ICameraService接口的功能是将逻辑上的Camera(即CameraClient)与实际与Camera通信的类Camera绑定起来。该接口类只包含一个函数connect():virtualspconnect(constsp&;cameraClient)=0;//将一个ICameraClient与一个iCamera绑定
ICamera接口类的BnCamera实现子类是负责与实际的Camera设备通信。ICamera中的接口函数:virtualvoiddisconnect()=0;//将ICameraClient与ICamera的绑定断开virtualstatus_tlock()=0;//防止其他进程使用该ICamera接口virtualstatus_tunlock()=0;//允许其他进程使用该ICamera接口
virtualstatus_tsetPreviewDisplay(constsp&;surface)=0;//进入preview模式前surface的一些设置virtualstatus_tstartPreview()=0;//进入到preview模式virtualvoidstopPreview()=0;//停止preview模式virtualboolpreviewEnabled()=0;//判断是否处于preview模式virtualstatus_tautoFocus()=0;//autoFocus过程virtualstatus_ttakePicture()=0;//takepicturevirtualstatus_tsetParameters(constString8&;params)=0;//设置preview或takePicture时的Camera参数virtualString8getParameters()const=0;//取得preview或takePicture时的Camera参数类CameraParameters是一个辅助类用于设置/获取Camera的参数。
========================================================libCameraService.so的功能及实现===================================================================libCameraService.so是libui.so中ICameraService和ICamera这两个接口类的实现类。应用层APK调用的接口ICameraClient中的函数最终是通过Binder机制调用libCameraService.so中的相应函数完成的。libCameraService中包含两个类:ICameraService的二级子类CameraServiceICamera的二级子类CameraService::ClientCameraService::Client中的函数:voiddisconnect();//将ICameraClient与ICamera的绑定断开status_tlock();//防止其他进程使用该ICamera接口status_tunlock();//允许其他进程使用该ICamera接口status_tsetPreviewDisplay(constsp&;surface);//进入preview模式前surface的一些设置status_tstartPreview();//进入到preview模式voidstopPreview();//停止preview模式boolpreviewEnabled();//判断是否处于preview模式status_tautoFocus();//autoFocus过程status_ttakePicture();//takepicturestatus_tsetParameters(constString8&;params);//设置preview或takePicture时的Camera参数String8getParameters()const;//取得preview或takePicture时的Camera参数voidvoid调函数voidshutterCallback();//按下ShutterButton的回调函数rawCallback(constsp&;picture);//按下ShutterButton的回jpegCallback(constsp&;picture);//按下ShutterButton的回
调函数voidframeCallback(cons
tsp&;frame);//preview模式下,收集到一帧数据时的回调函数。voiderrorCallback(status_terror);//出错时的回调函数voidautoFocusCallback(boolfocused);//按下ShutterButton,先会执行autoFocus,执行完autoFocus的回调函数。CameraService::Client中与实际Camera通信的函数是通过调用头文件CameraHardwareInterface.h中的函数完成的。该头文件的具体实现是libCamera.so。==========================================================libCamera.so的实现=============================================================================libCamera.so是CameraHardwareInterface.h的具体实现。CameraHardwareInterface.h的定义如下:namespaceandroid{/**CallbackforstartPreview()*/typedefvoid(*preview_callback)(constsp&;mem,void*user);/**CallbackfortakePicture()*/typedefvoid(*shutter_callback)(void*user);/**CallbackfortakePicture()*/typedefvoid(*raw_callback)(constsp&;mem,void*user);/**CallbackfortakePicture()*/typedefvoid(*jpeg_callback)(constsp&;mem,void*user);/**CallbackforautoFocus()*/typedefvoid(*autofocus_callback)(boolfocused,void*user);classCameraHardwareInterface:publicvirtualRefBase{public:virtual~CameraHardwareInterface(){}/**ReturntheIMemoryHeapforthepreviewimageheap*/virtualspgetPreviewHeap()const=0;/***Startpreviewmode.Whenapreviewimageisavailable*preview_callbackiscalledwiththeuserparameter.The*callbackparametermaybenull.
*/virtualstatus_t
startPreview(preview_callbackcb,void*user)=0;
/***Stopapreviouslystartedpreview.*/virtualvoidstopPreview()=0;/***Returnstrueifpreviewisenabled.*/virtualboolpreviewEnabled()=0;/***Startautofocus,thecallbackroutineiscalled*oncewhenfocusingiscomplete.autoFocus()will*becalledagainifanotherautofocusisneeded.*/virtualstatus_tautoFocus(autofocus_callback,void*user)=0;/***Takeapicture.Theraw_callbackiscalledwhen*theuncompressedimageisavailable.Thejpeg_callback*iscalledwhenthecompressedimageisavailable.These*callbacksmaybenull.Theuserparameterispassed*toeachofthecallbackroutines.*/virtualstatus_ttakePicture(shutter_callback,raw_callback,jpeg_callback,void*user)=0;/***CancelapicturethatwasstartedwithtakePicture.Youmaycancelany*oftheshutter,raw,orjpegcallbacks.Callingthismethodwhenno*pictureisbeingtakenisano-op.*/virtualstatus_tcancelPicture(boolcancel_shutter,boolcancel_raw,boolcancel_jpeg)=0;/**Setthecameraparameters.*/virtualstatus_tsetParameters(constCameraParameters&;params)=0;
/**Returnthecameraparameters.*/virtualCameraParametersgetParameters()const=0;/***Releasethehardwareresourcesownedbythisobject.**not*doneinthedestructor.*/virtualvoidrelease()=0;
Notethatthisis
/***Dumpstateofthecamerahardware*/virtualstatus_tdump(intfd,constVector&;args)const=0;};/**factoryfunctiontoinstantiateacamerahardwareobject*/extern"C"sp
openCameraHardware();};//namespaceandroid#endiflibCamera.so包含两个类:CameraHardwareS3C6410是CameraHardwareInterface的子类。S3C6410Camera负责与Cameradriver通信,所有与设备相关的操作最终都是通过这个函数完成的。它被S3C6410CameraHWInterface调用。回调函数:回调函数就是一个通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用它所指向的函数时,我们就说这是回调函数。回调函数的实现机制:(1)定义一个回调函数;(2)提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;(3)当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。libCamera.so中的回调机制实现:CameraHardwareS3C6410.h中定义的五个函数指针分别指向CameraService.cpp中定义的5个callback函数:回调函数是在CameraService.cpp中定义的。当CameraService.cpp在调用CameraHardwareS3C6410.h中的函数startPreview(),autoFocus(),takePicture()时会将自己定义好的回调函数的地址传进去,这样,回调函数的函数指针就注册给了CameraHardwareS3C6410中的函数。当preview模式下收集到一帧数据,autoFocus完成,takePicture收集完数据时,CameraHardwareS3C6410中的函数就会使用传进来的函数指针来调用CameraService.cpp中定义的回调函数。
以下详细介绍libCamera.so的具体实现:CameraHardwareS3C6410.cpp中主要函数:initDefaultParameters()完成参数的初始化工作,包括preview,snapshot时的宽高,preview时的帧率,亮度等。initHeapLocked()用来分配preview数据的内存空间,具体实现如下:voidCameraHardwareS3C6410::initHeapLocked(){intwidth,height;mParameters.getPreviewSize(&;width,&;height);inthow_big=width*height*BPP;if(how_big==mPreviewFrameSize)return;mPreviewFrameSize=how_big;if(mHeap!=NULL)mHeap.clear();mHeap=newMemoryHeapBase(mPreviewFrameSize*kBufferCount);//在内存堆上分配一块内存,该内存会被AudioFlinger进程使用,
for(inti=0;i 堆空间在进程间的共享。CameraService中的相关代码为:{mSurface->unregisterBuffers();mSurface->registerBuffers(w,h,w,h,pixel_format,mHardware->getPreviewHeap());}intCameraHardwareS3C6410::previewThread()该函数是实现preview的主要函数:
intCameraHardwareS3C6410::previewThread(){mCurrentPreviewFrame=(mCurrentPreviewFrame+1)%kBufferCount;mLock.lock();//用来锁定共享堆内存的,因为该堆空间是与AndioFlinger进程共享的intpreviewFrameRate=mParameters.getPreviewFrameRate();ssize_toffset=mCurrentPreviewFrame*mPreviewFrameSize;//计算当前这帧数据的首地址在堆内存中的偏移量spheap=mHeap;S3C6410Camera*S3C6410Camera=mS3C6410Camera;spbuffer=mBuffers[mCurrentPreviewFrame];mLock.unlock();//释放对该共享内存的锁定if(buffer!=0){intdelay=mPreviewFrameRateMicrosec;//两帧数据之间的时间间隔void*base=heap->base();uint8_t*frame=((uint8_t*)base)+offset;//存放当前这一帧数据的堆空间的首地址。S3C6410Camera->getPreview()会将收集到的一帧数据存入该地址。intpreview_width=0;intpreview_height=0;intpreview_framesize=0;S3C6410Camera->getPreviewSize(&;preview_width,&;preview_framesize);&;preview_height,
if(S3C6410Camera->getPreview(frame,preview_framesize)<0){LOGE("ERR(%s):FailonS3C6410Camera->getPreview(frame(%p),preview_framesize(%d))",__FUNCTION__,frame,preview_framesize);returnUNKNOWN_ERROR;}mPreviewCallback(buffer,mPreviewCallbackCookie);//调用CameraService中的previewCallback函数,将得到的这帧数据的地址传到CameraService.usleep(delay);}returnNO_ERROR;}intCameraHardwareS3C6410::autoFocusThread()是实现autoFocus()的主要函数:intCameraHardwareS3C6410::autoFocusThread(){LOGE("%s",__func__);if(mS3C6410Camera->setAutofocus()<0)
{LOGE("ERR(%s):FailonmS3C6410Camera->setAutofocus()",__FUNCTION__);returnUNKNOWN_ERROR;}
if(mAutoFocusCallback!=NULL){mAutoFocusCallback(true,mAutoFocusCallbackCookie);mAutoFocusCallback=NULL;returnNO_ERROR;}returnUNKNOWN_ERROR;}intCameraHardwareS3C6410::pictureThread()实现takePicture的主要函数:intCameraHardwareS3C6410::pictureThread(){LOGE("%s",__func__);if(mShutterCallback)mShutterCallback(mPictureCallbackCookie);if(mRawPictureCallback){spmem=mBuffers[mCurrentPreviewFrame];mRawPictureCallback(mem,mPreviewCallbackCookie);//这个回调函数调用的是CameraService::Client::yuvPictureCallback(),这个函数会将当前的preview数据显示出来。}if(mJpegPictureCallback){longintjpeg_size=0;char*jpeg_data=mS3C6410Camera->getJpeg(&;jpeg_size);//得到jpeg数据流的首地址和大小,此时jpeg数据流在S3C6410Camera开辟的内存空间中。if(jpeg_data){spheap1=newMemoryHeapBase(jpeg_size);spmem1=newMe
moryBase(heap1,0,jpeg_size);memcpy((uint8_t*)heap1->base(),jpeg_data,jpeg_size);//将jpeg数据流copy到新开辟的堆内存中,mJpegPictureCallback(mem1,mPictureCallbackCookie);//该回调函数调用的是
CameraService::Client::jpegPictureCallback()mem1.clear();heap1.clear();}}returnNO_ERROR;}status_tCameraHardwareS3C6410::setParameters(constCameraParameters&;params)//设置Camera的各种参数:preview_heigh,preview_width,previewsize,previewformat,previewFrameRate,picture_heigh,picture_width,picturesize,pictureformat等。S3C6410Camera的实现:S3C6410Camera采用V4L与Cameradriver通信。V4L介绍:Video4linux(简称V4L),是linux中关于视频设备的内核驱动,现在已有Video4linux2。2.Video4linux下视频编程的流程(1)打开视频设备:(2)读取设备信息(3)更改设备当前设置(没必要的话可以不做)(4)进行视频采集,两种方法:a.内存映射b.直接从设备读取(5)对采集的视频进行处理(6)关闭视频设备。V4L编程需要的命令字定义在linuxkernel的头文件videodev.h中。V4L编程流程中的每一步都是通过发送相应命令字给Cameradriver来完成的。Cameradriver中有对应命令字的具体实现。
三.androidBinder机制四.C++共享内存机制五.协同工作流程具体实现libCameraService.so会先执行,从而使CameraService处于运行状态。
1.preview流程2.snapshot流程3.videoRecord流程
六.Camera功能的整体架构图
应用层Apk为packages/apps/Camera当在Launcher中启动Camera应用程序时,Camera.java开始运行。该apk需要调用的Camera相关的类为frameworks/base/core/java/android/hardware/Camera.java。
androidIntent机制介绍
frameworks/base/core/java/android/hardware/Camera.java通过JNI调用frameworks/base/core/java/android/harware/android_hardware_Camera.cpp中的函数。这部分内容编译成目标libandroid_runtime.so。android_hardware_Camera.cpp通过调用frameworks/base/include/ui/Camera.h中的函数提供对上层java的接口。
Camera.h中定义了一个类classCamera:publicBnCameraClient,,publicIBinder:eathRecipient。Camera.cpp中定义函数getCameraService()用于得到CameraService实例。再通过调用CameraService.h中的connect()函数得到Camera实例。Camera.cpp中的大部分函数都是通过调用这个Camera实例中的相应函数实现的。当Camera.cpp调用CameraService.h中的connect()函数时,ICameraService.cpp中定义的类BpCameraService的函数connect()被调用。通过android的binder机制,BpCameraService端的函数通过调用remote->transact()来调用BnCameraService端的onTransact()函数。onTransact()函数中包含一个switch-case函数,根据传过来的参数调用BnCameraSerivce端
实现的相应函数。Libcameraservice.so继承自libui.so是libui.so的具体实现。Libui.so与
Libcameraservice.so之间通过androidbinder机制通信。
Androidbinder机制简介(待补)
Framework/base/camera/libcameraservice下的CameraService.h中定义的类CameraService继承了BnCameraService.CameraService.cpp中定义了connect函数的具体实现。Camera.cpp中得到Camera实例后,通过该实例调用ICamera.h中的函数时,ICamera.cpp中定义的类BpCamera的相应函数将被调用。通过android的binder机制,BpCamera端的函数通过调用remote->transact()来调用BnCamera端的onTransact()函数。onTransact()函数中包含一个switch-case函数,根据传过来的参数调用BnCamera端实现的相应函数。Framework/base/camera/libcameraservice下的CameraService.h中定义的类CameraService的内置类Client继承了BnCamera.该类中的函数是Camera.cpp最终调用的函数。Framework/base/camera/libcameraservice这部分被编译成库libcameraservice.so。Libcameraservice.so与libcamera.so之间通过共享内存传递图像数据。共享内存机制的简介。
CameraService.cpp的内置类Client主要通过调用CameraHardwareInterface.h中的函数实现具体功能。framework/base/include/ui下的CameraHardwareInterface.h定义了libCameraService.so需要的所有接口:getPreviewHeap(),startPreview(preview_callbackcb,void*user),stopPreview(),previewEnabled(),autoFocus(autofocus_callback,void*user),takePicture(shutter_callback,raw_callback,jpeg_callback,void*user)cancelPicture(boolcancel_shutter,boolcancel_raw,boolcancel_jpeg)setParameters(),getParameters()release(),dump(),openCameraHardware()其中还定义了5个函数指针,分别指向CameraService.cpp中定义的5个callback函数:void(*preview_callback)(constsp&;mem,void*user);void(*shutter_callback)(void*user);void(*raw_callback)(constsp&;mem,void*user);void(*jpeg_callback)(constsp&;mem,void*user);void(*autofocus_callback)(boolfocused,void*user);libCamera.so是对CameraHardwareInterface.h的具体实现。其中S3C6410CameraHWInterface.cpp实现了接口中的全部函数。S3C6410Camera.cpp负责与设备通信。被S3C6410CameraHWInterface.cpp调用。libcameraService.so先调用openCameraHardware(),得到Camera实例。然后调用S3C6410CameraHWInterface.cpp中的getParameters(),setParameters()初始化这个
Camera实例.S3C6410CameraHWInterface.cpp在setParameters()之后会调用initHeapLocked(),该函数用来分配存放帧数据的堆,并在已分配的堆空间上分配Buffer数组,每个数组变量存储一帧数据。libcameraService.so在Startpreview()中调用getPreviewHeap()得到libcamera.so中存放帧数据的堆的首地址。然后将这个地址注册到SurfaceFlinger的Buffer
中以便提高preview的显示效率。CameraService.cpp在调用S3C6410CameraHWInterface.cpp的Startpreview()时会将自己的previewCallback()函数传进去,这样当libcamera.so在调用getPreview()收集到一帧新数据时,就可以通过函数指针调用libcameraService.so中的回调函数previewCallback(),将新收集到的帧数据的首地址传出去。CameraService.cpp接着调用postFrame(),surfcace->postBuffer()等将该地址传到surfaceFlinger中以显示当前的帧数据。S3C6410CameraHWInterface.cpp在startpreview()中新建一个线程previewThread(),在该线程中调用S3C6410Camera.cpp中的getpreview()将设备收集到的帧数据copy到存放帧数据的堆中。然后在线程中接着调用CameraService.cpp中的回调函数previewCallback(),将当前帧的偏移地址传给surfaceFlinger。以上是camera的preview过程的实现流程。在调用takePicture()之前,cameraService.cpp会先调用autofocus(),同时将自己定义的autofocus函数传进去。cameraService.cpp中的autofocus()会调用S3C6410CameraHWInterface.cpp中的autoFocus()函数创建一个线程,在该线程中通过函数指针调用CameraService.cpp中的autoFocuscallback()通知CameraServiceautofocus成功。之后,上层的APK会调用getParameter(),setParameter()重新初始化Camera实例。当调用takePicture()时,CameraService.cpp会将自己定义的shuttercallback(),rawcallback(),jpegcallback()函数传给S3C6410CameraHWInterface.cpp中的takepicture()函数。它会创建一个线程beginPictureThread(),在其中调用函数pictureThread()。pictureThread()函数通过函数指针调用CameraService.cpp中的shuttercallback(),yuvPictureCallback(),其中yuvPictureCallback()的作用是将要拍摄的图像在preview模式下显示出来。为了调用CameraService.cpp中的jpegPictureCallback(),pictureThread()需要先调用S3C6410Camera中的getjpeg()函数取得jpeg数据流,再重新开辟一块堆空间,将jpeg数据流copy进去。之后就可以通过函数指针调用CameraService.cpp中的jpegPictureCallback(),将得到的jpeg数据流传给CameraService.cpp.得到jpeg数据流的过程:S3C6410Camera中的getjpeg()先调用m_frameSize()计算getsnapshot()得到的原始数据所需的空间,按此大小开辟一块内存区存放getsnapshot()得到的原始数据。在通过yuv2Jpeg()函数将得到的原始数据压缩成jpeg数据流。framework/base/include/ui下的CameraHardwareInterface.h的实现类负责与具体的Camera设备通信。这部分需要自己实现。将其放在vendor/sec_proprietary/libcamera.编译后为libcamera.so.
libcamera.so通过v4l2与该cameraDriver通信。V4l2简介及使用流程例子(待补)CameraDriver简介
setbootargsconsole=ttySAC0,
115200root=/dev/nfsrwnfsroot=192.168.1.105:/home/hunk/android/code/rootfsinit=/initip=192.168.1.222:192.168.1.105:192.168.1.255:255.255.255.0:egk2:eth0:off一.实现Camera功能的相关模块为:1.android_cupcake/packages/apps/Camera/src/com/android/camera此部分内容被编译为Camera.apkandroid_cupcake/framework/base/core/java/android/hardware/Camera.javaandroid_cupcake/framework/base/core/jni/android_hardware_Camera.cpp此部分内容被编译为libandroid_runtime.so中的一部分。2.frameworks/base/include/ui/目录中Camera相关的头文件有以下几个:Camera.hCameraParameters.hICamera.hICameraClient.hICameraService.hCameraHardwareInterface.hFrameworks/base/libs/ui目录中Camera相关的实现文件有以下几个:Camera.cppCameraParameters.cppICamera.cppICameraClient.cppICameraService.cpp这部分的内容被编译成libui.so。3.Framework/base/camera/libcameraservice其中包含以下两个文件:CameraService.hCameraService.cpp这部分内容被编译成libCameraService.so
4.android_cupcake/vendor/sec_proprietary/libcamera其中包含以下四个文件:S3C6410CameraHWInterface.hS3C6410CameraHWInterface.cppS3C6410Camera.hS3C6410Camera.cpp
这部分内容被编译成libcamera.so二.上述四个模块的功能介绍及具体实现android应用程序的组成,Intent机制1.Camera.APK(androidIntent机制)
Camera.apk实现了五个功能Camerapreview:相机的preview模式Cameratakepicture:在preview模式下,按下takepicture按钮得到一张相片,并存于指定文件夹下。gallery:照片预览功能,所有照片以thumbnail的形式排列在屏幕上,选中某个照片后可以全屏显示。Cameravideo:录制功能,将录制后的文件以3gp的格式存入指定文件夹下。CameraSetting:对storelocationinpictures,selectvideoquality(Low(forMMSmesssage)High(forSDcard))这两个属性的设置
Camerapreview和takepicture功能在Camera.java中实现。gallery功能主要由GalleryPicker.java,GalleryPickerItem.java,GallerySetting.java,ImageGallery2.java这几个类实现。Cameravideo功能主要由VideoCamera.java实现。videoplay功能主要由MovieView.java实现。CameraSetting:由CameraSettings.java实现。
Camera.java组成:publicclassCameraextendsActivityimplementsView.OnClickListener,ShutterButton.OnShutterButtonListener,SurfaceHolder.Callback=================================Camera.java中的主要属===============================================================ImageCapture负责与takepicture相关的所有功能privateclassImageCaptureimplementsCapturer{}privateinterfaceCapturer{UrigetLastCaptureUri();voidonSnap();voiddismissFreezeFrame(booleankeep);voidcancelSave();voidcancelAutoDismiss();voidsetDone(booleanwait);}性
MainHandler类负责将消息传给应用的
主线程privateclassMainHandlerextendsHandler{}VideoPreview.javaclassVideoPreviewextendsSurfaceView用来更新preview模式下的显示内容。android.hardware.Camera负责与Camera通信的类。以下四个类是android.hardware.Camera中各个回调接口的实现类,供下层函数调用privatefinalclassShutterCallbackimplementsandroid.hardware.Camera.ShutterCallbackprivatefinalclassRawPictureCallbackimplementsPictureCallbackprivatefinalclassJpegPictureCallbackimplementsPictureCallbackprivatefinalclassAutoFocusCallbackimplementsandroid.hardware.Camera.AutoFocusCallback===================================Camera.java中的主要方法================================================================Camera.java中的主要函数onCreate()这个函数负责在Camera刚启动时,设置界面的显示。onStart()函数中newThread()在线程中调用MainHandler()的post().在屏幕上显示动画,先用白色铺满屏幕。onResume()函数注册了一个intentfilter用来接收SD卡相关的事件。中调用了restartPreview();startReceivingLocationUpdates();updateFocusIndicator();onShutterButtonFocus()当shutterButtonfocus时,调用doFocus()onShutterButtonClick()当shutterButtonpress时,调用dosnap()onStop()函数用来停止一个Camera实例,它调用stopPreview(),closeCamera();mHandler.removeMessages(CLEAR_SCREEN_DELAY);setViewFinder()调用android.hardware.Camera.setPreviewDisplay()进入preview模式。stopPreview()退出preview模式gotoGallery()进入Gallery模式(即图片预览)calculatePicturesRemaining()计算存储picture所需要的空间。onCreateOptionsMenu(),onPrepareOptionsMenu(),onOptionsMenuClosed()//与菜单控件相关的函数surfaceChanged(),surfaceChanged(),surfaceDestroyed(),这三个函数用来在preview模式下更新屏幕。restartPreview()使Camera进入preview模式=====================================Camera.java的执行流程==================================================================点击Launcher上的Camera.apk的图标时,ActivityManager发Intent给Camera.apk,触发Camera.java实现的Activity。在onCreate()函数创建Camera.java需要的对象实例。其中创建VideoPreview的SurfaceHolder,同时注册callback函数,VideoPreview的长宽变化时,当调用SurfaceChanged()
函数。此部分代码:mSurfaceView=(VideoPreview)findViewById(R.id.camera_preview);SurfaceHolderholder=mSurfaceView.getHolder();holder.addCallback(this);在onResume()中调用restartPreview(),在此函数中创建了一个VideoPreview实例,这个创建动作使SurfaceHolder的回调函数SurfaceChanged()被调用。同时调用ShutterButton.java,显示ShutterButton按钮,同时启动一个线程监听Shutterbutton按下事件。Camera.java
重新实现了SurfaceChanged()。在SurfaceChanged()中,调用了setViewFinder()函数,该函数用来设置preview的display.此函数完成后Camera处于preview模式。同时创建了ImagePicture实例,为takePicture作准备。setViewFinder()的实现过程:ensureCameraDevice()>mCameraDevice.setPreviewDisplay()-->mCameraDevice.getParameters()>mCameraDevice.setParameters(p)>mCameraDevice.startPreview().ensureCameraDevice()调用android.hardware.Camera.open()得到一个android.hardwareCamera实例mCameraDevice.
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\以上为Camera.java实现preview的流程,顺序图。\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
按下屏幕上的ShutterButton按钮。ShutterButton.java中的监听线程调用callShutterButtonFocus(),这个函数会调用接口ShutterButton.OnShutterButtonListener的函数onShutterButtonFocus()。Camera.java实现了接口ShutterButton.OnShutterButtonListener。故Camera.java中的函数onShutterButtonFocus()被调用。接着的执行流程为>doFocus()>autoFocus()>mCameraDevice.autoFocus()之后ShutterButton.java调用performClick(),这个函数中调用了Camera.java中的onShutterButtonClick().接着的执行流程为>dosnap()>ImagePicture.onSnap()>ImageCapture.initiate()>ImageCapture.capture()此函数执行完后,takepicture过程完成。ImageCapture.capture()的实现过程:mCameraDevice.getParameters()>mCameraDevice.takePicture()
mCameraDevice.setParameters()>
takePicture完成后,surfaceChanged()将被调用将刚照下的照片显示在屏幕上。Camera.java中的回调接口JpegPictureCallback中的函数onPictureTaken()接着执行。这个函数先调用ImageCapture.storeImage()将jpeg图像数据存储在内存。picture的thumbnail显示过程:ImageCapture.storeImage()>ImageCapture.setLastPictureThumb()>BitmapFactory.decodeByteArray>ImageManager.extractMiniThumb()-->setImageDrawable()ImageManager.extractMiniThumb()通过调用ImageLoader.transform()完成。通过调用MainHandler延迟调用dismissFreezeFrame()释放takepicture分配的空间。然后重新启动RestartPreview().MainHandler.sendEmptyMessageDelayed(RESTART_PREVIEW)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\以上为Camera.java实现takepicture的流程,顺序图。\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
takePicture流程结束,回到preview模式后,按下menu菜单键中的gallery,Camera.java中会执行以下流程:onKeyDown()>onCreateOptionsMenu()>>addBaseMenuItems()会调用MenuHelper.addSwitchModeMenuItem()(switchtovideo;gallery;setting)>onKeyUp()>onMenuOpened()>gotoGallery()会调用Menuhlper.gotoCameraImageGallery()其中的关键代码是:Uritarget=Images.Media.INTERNAL_CONTENT_URI.buildUpon().appendQueryParameter("bucketId",I
mageManager.CAMERA_IMAGE_BUCKET_ID).build();Intentintent=newIntent(Intent.ACTION_VIEW,target);activity.startActivity(intent);在函数gotoCameraImageGallery()中构造了一个Intent,并调用ActivityManager的startActivity函数将该Intent发送出去,从而启动另一个Activity.ImageGallery2.同时下拉菜单关闭。通过函数onOptionsMenuClosed()实现的。同时onPause()函数被调用,在该函数中调用了stopPreview().当跳转到ImageGallery2.java后,执行流程如下:onCreate()>onResume()>ImageGallery2::GridViewspecial.scrollTo()>rebake()>CheckThumbnails()>CameraThreadstartthread()>allImages()>GridViewspecial::start()>ImageBlockManager()>rebake()先调用CheckThumbnails(),在CheckThumbnails()中开了一个线程用来在屏幕上以thumbnails形式显示所有照片:关键语句为:mThumbnailCheckThread.setName("check_thumbnails");mThumbnailCheckThread.start();mThumbnailCheckThread.toBackground();
ImageManager.IImageListlist=allImages(true);mNoImagesView.setVisibility(list.getCount()>0?View.GONE:View.VISIBLE);allImages()中的关键语句:mAllImages=ImageManager.instance().allImages(ImageGallery2.this,getContentResolver(),ImageManager.DataLocation.NONE,mInclusion,mSortAscending?ImageManager.SORT_ASCENDING:ImageManager.SORT_DESCENDING,uri!=null?uri.getQueryParameter("bucketId"):null);allImage调用GridViewspecial::start()GridViewspecial::start()函数调用GridViewspecial::startLoading获得所有图片的thumbnail形式。GridViewspecial::startLoading调用了ImageBlockManager()该函数ImageBlockManager()是通过调用ImageLoader().getBitmap()获得图片的thumbnail形式的。当图片以thumbnail形式显示在屏幕上后,点击其中的任意一个图片将触发以下流程:Menuhelper.addImageMenuItems(增加菜单选项slideshow,rotate,delete,crop,share,setas等)>Menuhelper.MenuItemsResult()>ImageGallery2.addSlideShowMenu()addSlideShowMenu()会发送Intent给ViewImage.java从而使界面跳转到另一个ActivityViewImage.addSlideShowMenu()中的关键语句:Intentintent=newIntent(Intent.ACTION_VIEW,targetUri);intent.putExtra("slideshow",true);startActivity(intent);转到ViewImage.java后的执行流程:onCreate()>ActionMenuButton.init()(初始化Activity上的按钮,左右查看图片的按钮,zoomin,zoomout,)>init()函数会调用makeGetter()>ImageGetter()在ImageGetter中会新开一个线程来获取选中的图片并全屏显示出来。该线程会调用imageLoaded()函数,>setImage()该函数负责将图片显示出来。具体流程如下:>ImageViewTouchBase.setImageBitmapResetBase()>ImageViewTouchBase.setImageBitmap()>ImageViewTouchBase.getImageViewMatrix>ImageViewTouchBase.onLayout()当点击左右查看图片的按钮或zoomin,zoomout时,viewImage.handleTouchEvent()会响应点击事件,根据所选择的按钮进行不同处理。
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\以上为Camera.java实现\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Gallery的过程顺序图
当按下屏幕上的switchtovideo按钮后,ActivityManager会发送一个Intent给videoCamera。同时Camera.java调用onOptionsMenuClosed()关闭下拉菜单。同时Camera.java调用onPause()onPause()中调用stopPreview()退出preview模式。当转到新的ActivityVideoCamera.java后,执行流程如下:onCreate()>ActionMenuButton.init()(初始化屏幕上的Button)>onStart()>onResume()>initializeVideo()>initializeVideo()函数newMediaRecorder(),调用MediaRecorder中的相关函数为录制作准备。接着调用createVideoPath()创建video文件,然后调用MediaRecorder.setPreviewDisplay()MediaRecorder.setPreviewDisplay()通过调用Camera.cpp中的setPreviewDisplay()使Camera进入preview模式。当按下屏幕上的VideoRecorder按钮后,执行流程如下:initializeVideo()函数新建的MediaRecorder开始工作,将收集到的图像数据encoder后存储在创建好的3gp文件中。当再次按下屏幕上的VideoRecorder按钮后,videoCamera.stopVideoRecordingAndDisplayDialog()被调用,它会先调用stopVideoRecording()停止录制过程,再在屏幕上显示按钮:playshareDelete当按下play按钮后,ActivityManager会通过Binder机制发消息给VideoPlayActivity完成播放功能。
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\以上为Camera.java实现VideoRecord的功能\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\当按下下拉菜单中的Setting按钮后,Camera.java会调用stopPreview()停止preview模式。同时ActivityManager发送Intent给CameraSetting,camerasetting中的执行流程:onCreate()>initUI()>onResume()onResume()执行完后,界面上出现setting选项:storelocationinpictures,selectvideoquality当选择selectvideoquality后,updateVideoQuality()>getBooleanPreference()>getIntPreference()被执行界面上会出现:selectvideoquality:Low(forMMSmesssage)High(forSDcard))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\以上为Camera.java实现\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\函数
CameraSeting的过程
frameworks/base/core/java/android/hardware/Camera.java通过JNI调用frameworks/base/core/java/android/harware/android_hardware_Camera.cpp中的函数。这部分内容编译进目标libandroid_runtime.so。是Camra.apk的本地部分。android_hardware_Camera.cpp通过调用frameworks/base/include/ui/Camera.h中的函数提供对上层java的接口。
==============================================================libui.so的功能介绍及具体实现=================================================
===============libui.so是Camera功能中实现Binder机制的接口类。提供上层Camera.apk所需要的接口。具体功能的实现由该接口类的实现子类CameraService完成,这部分被编译成libCameraService.so.libui.so中包含的接口类包括:ICameraClientICameraServiceICamera以下分别介绍他们的功能以及包含的主要函数:ICameraClient代表一个逻辑上的Camera设备,包含与实际Camera通信的全部函数。应用层可以通过接口类ICameraClient的实现子类BpCameraClient中的相关函数来与Camera设备通信。通信过程应用了android提供的Binder机制(后面会介绍)大致过程为:BpCameraClient中的相应函数调用remote()->transact(),这时ICameraClient的实际实现类BnCameraClient中的onTransact()函数会被调用,onTransact()函数中包含一个switch-case函数,根据传过来的参数调用BnCamera端实现的相应函数。由于Camera.apk与libui.so中的Camera接口类同属于一个进程,所以Camera.apk中的本地部分直接调用了ICameraClient的实现子类BnCameraClient中的函数,而不必通过Binder机制。ICameraClient接口中的主要函数:virtualvoidshutterCallback()=0;//按下ShutterButton的回调函数virtualvoidrawCallback(constsp&;picture)=0;//按下ShutterButton的回调函数virtualvoidjpegCallback(constsp&;picture)=0;//按下ShutterButton的回调函数virtualvoidframeCallback(constsp&;frame)=0;//preview模式下,收集到一帧数据时的回调函数。virtualvoiderrorCallback(status_terror)=0;//出错时的回调函数virtualvoidautoFocusCallback(boolfocused)=0;//按下ShutterButton,先会执行autoFocus,执行完autoFocus的回调函数。ICameraClient的二级子类Camera中的主要函数与ICamera接口中的函数相对应:
voidstatus_tstatus_tstatus_tsurface的一些设置status_tvoidboolstatus_tstatus_tstatus_tCamera参数String8
disconnect();//将ICameraClient与ICamera的绑定断开lock();//防止其他进程使用该ICamera接口unlock();//允许其他进程使用该ICamera接口setPreviewDisplay(constsp&;surface);//进入preview模式前startPreview();//进入到preview模式stopPreview();//停止preview模式previewEnabled();//判断是否处于preview模式autoFocus();//autoFocus过程takePicture();//takepicturesetParameters(constString8&;params);//设置preview或takePicture时的getParameters()const;//取得preview或takePicture时的Camera参数
voidshutterCallback();//按下ShutterButton的回调函数voidrawCallback(constsp&;picture);//按下ShutterButton的回调函数voidjpegCallback(constsp&;picture);//按下ShutterButton的回调函数voidframeCallback(constsp&;frame);//preview模式下,收集到一帧数据时的回调函数。voide
rrorCallback(status_terror);//出错时的回调函数voidautoFocusCallback(boolfocused);//按下ShutterButton,先会执行autoFocus,执行完autoFocus的回调函数。CameraClient只是一个逻辑上的Camera设备,并不直接与实际的Camera设备通信。BnCameraClient的子类Camera中定义了函数getCameraService()用于得到CameraService实例。再通过调用CameraService中的connect()函数得到Camera实例。Camera.cpp中与Camera通信的函数都是通过调用这个Camera实例中的相应函数实现的。ICameraService接口的功能是将逻辑上的Camera(即CameraClient)与实际与Camera通信的类Camera绑定起来。该接口类只包含一个函数connect():virtualspconnect(constsp&;cameraClient)=0;//将一个ICameraClient与一个iCamera绑定
ICamera接口类的BnCamera实现子类是负责与实际的Camera设备通信。ICamera中的接口函数:virtualvoiddisconnect()=0;//将ICameraClient与ICamera的绑定断开virtualstatus_tlock()=0;//防止其他进程使用该ICamera接口virtualstatus_tunlock()=0;//允许其他进程使用该ICamera接口virtualstatus_tsetPreviewDisplay(constsp&;surface)=0;//进入preview模式前surface的一些设置
virtualstatus_tstartPreview()=0;//进入到preview模式virtualvoidstopPreview()=0;//停止preview模式virtualboolpreviewEnabled()=0;//判断是否处于preview模式virtualstatus_tautoFocus()=0;//autoFocus过程virtualstatus_ttakePicture()=0;//takepicturevirtualstatus_tsetParameters(constString8&;params)=0;//设置preview或takePicture时的Camera参数virtualString8getParameters()const=0;//取得preview或takePicture时的Camera参数类CameraParameters是一个辅助类用于设置/获取Camera的参数。
========================================================libCameraService.so的功能及实现===================================================================libCameraService.so是libui.so中ICameraService和ICamera这两个接口类的实现类。应用层APK调用的接口ICameraClient中的函数最终是通过Binder机制调用libCameraService.so中的相应函数完成的。libCameraService中包含两个类:ICameraService的二级子类CameraServiceICamera的二级子类CameraService::ClientCameraService::Client中的函数:voiddisconnect();//将ICameraClient与ICamera的绑定断开status_tlock();//防止其他进程使用该ICamera接口status_tunlock();//允许其他进程使用该ICamera接口status_tsetPreviewDisplay(constsp&;surface);//进入preview模式前surface的一些设置status_tstartPreview();//进入到preview模式voidstopPreview();//停止preview模式boolpreviewEnabled();//判断是否处于preview模式status_tautoFocus();//autoFocus过程status_ttakePicture();//takepicturestatu
s_tsetParameters(constString8&;params);//设置preview或takePicture时的Camera参数String8getParameters()const;//取得preview或takePicture时的Camera参数voidvoid调函数void调函数voidshutterCallback();//按下ShutterButton的回调函数rawCallback(constsp&;picture);//按下ShutterButton的回jpegCallback(constsp&;picture);//按下ShutterButton的回frameCallback(constsp&;frame);//preview模式下,收集到
一帧数据时的回调函数。voiderrorCallback(status_terror);//出错时的回调函数voidautoFocusCallback(boolfocused);//按下ShutterButton,先会执行autoFocus,执行完autoFocus的回调函数。CameraService::Client中与实际Camera通信的函数是通过调用头文件CameraHardwareInterface.h中的函数完成的。该头文件的具体实现是libCamera.so。==========================================================libCamera.so的实现=============================================================================libCamera.so是CameraHardwareInterface.h的具体实现。CameraHardwareInterface.h的定义如下:namespaceandroid{/**CallbackforstartPreview()*/typedefvoid(*preview_callback)(constsp&;mem,void*user);/**CallbackfortakePicture()*/typedefvoid(*shutter_callback)(void*user);/**CallbackfortakePicture()*/typedefvoid(*raw_callback)(constsp&;mem,void*user);/**CallbackfortakePicture()*/typedefvoid(*jpeg_callback)(constsp&;mem,void*user);/**CallbackforautoFocus()*/typedefvoid(*autofocus_callback)(boolfocused,void*user);classCameraHardwareInterface:publicvirtualRefBase{public:virtual~CameraHardwareInterface(){}/**ReturntheIMemoryHeapforthepreviewimageheap*/virtualspgetPreviewHeap()const=0;/***Startpreviewmode.Whenapreviewimageisavailable*preview_callbackiscalledwiththeuserparameter.The*callbackparametermaybenull.*/virtualstatus_tstartPreview(preview_callbackcb,void*user)=0;
/***Stopapreviouslystartedpreview.*/virtualvoidstopPreview()=0;/***Returnstrueifpreviewisenabled.*/virtualboolpreviewEnabled()=0;/***Startautofocus,thecallbackroutineiscalled*oncewhenfocusingiscomplete.autoFocus()will*becalledagainifanotherautofocusisneeded.*/virtualstatus_tautoFocus(autofocus_callback,void*user)=0;/***Takeapicture.Theraw_callbackiscalledwhen*theuncompressedimageisavailable.Thejpeg_callback*iscalledwhenthecompressedimageisavailable.These*callbacksmaybenull.Theuserparameterispassed*toeachofthecallbackroutines.*/virtualstatus_ttakePicture(shutter_callback,raw_callback,jpeg_callback,void*user)=0;/***CancelapicturethatwasstartedwithtakePicture.Youmaycancelany*oftheshutter,raw,orjpegcallbacks.Callingthismethodwhenno*pictureisbeingtakenisano-op.*/virtualstatus_tcan
celPicture(boolcancel_shutter,boolcancel_raw,boolcancel_jpeg)=0;/**Setthecameraparameters.*/virtualstatus_tsetParameters(constCameraParameters&;params)=0;/**Returnthecameraparameters.*/
virtualCameraParametersgetParameters()const=0;/***Releasethehardwareresourcesownedbythisobject.**not*doneinthedestructor.*/virtualvoidrelease()=0;
Notethatthisis
/***Dumpstateofthecamerahardware*/virtualstatus_tdump(intfd,constVector&;args)const=0;};/**factoryfunctiontoinstantiateacamerahardwareobject*/extern"C"spopenCameraHardware();};//namespaceandroid#endiflibCamera.so包含两个类:CameraHardwareS3C6410是CameraHardwareInterface的子类。S3C6410Camera负责与Cameradriver通信,所有与设备相关的操作最终都是通过这个函数完成的。它被S3C6410CameraHWInterface调用。回调函数:回调函数就是一个通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用它所指向的函数时,我们就说这是回调函数。回调函数的实现机制:(1)定义一个回调函数;(2)提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;(3)当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。libCamera.so中的回调机制实现:CameraHardwareS3C6410.h中定义的五个函数指针分别指向CameraService.cpp中定义的5个callback函数:回调函数是在CameraService.cpp中定义的。当CameraService.cpp在调用CameraHardwareS3C6410.h中的函数startPreview(),autoFocus(),takePicture()时会将自己定义好的回调函数的地址传进去,这样,回调函数的函数指针就注册给了CameraHardwareS3C6410中的函数。当preview模式下收集到一帧数据,autoFocus完成,takePicture收集完数据时,CameraHardwareS3C6410中的函数就会使用传进来的函数指针来调用CameraService.cpp中定义的回调函数。以下详细介绍libCamera.so的具体实现:
CameraHardwareS3C6410.cpp中主要函数:initDefaultParameters()完成参数的初始化工作,包括preview,snapshot时的宽高,preview时的帧率,亮度等。initHeapLocked()用来分配preview数据的内存空间,具体实现如下:voidCameraHardwareS3C6410::initHeapLocked(){intwidth,height;mParameters.getPreviewSize(&;width,&;height);inthow_big=width*height*BPP;if(how_big==mPreviewFrameSize)return;mPreviewFrameSize=how_big;if(mHeap!=NULL)mHeap.clear();mHeap=newMemoryHeapBase(mPreviewFrameSize*kBufferCount);//在内存堆上分配一块内存,该内存会被AudioFlinger进程使用,
for(inti=0;i 堆内存分成kBufferCount个,每个大小为一帧preview数据,以便重复利用这些堆块if(mBuffers[i]!=NULL)mBuffers[i].clear();mBuffers[i]=newMemoryBase(mHeap,i*mPreviewFrameSize,mPreviewFrameSize);}}spCameraHardwareS3C6410::getPreviewHeap()返回分配的共享堆内存的首地址。该地址在CameraService中被注册到AndioFlinger进程中,从而实现了这个堆空间在进程间的共享。CameraService中的相关代码为:{mSurface->unregisterBuffers();mSurface->registerBuffers(w,h,w,h,pixel_format,mHardware->getPreviewHeap());}intCameraHardwareS3C6410::previewThread()该函数是实现preview的主要函数:intCameraHardwareS3C6410::previewThread(){
mCurrentPreviewFrame=(mCurrentPreviewFrame+1)%kBufferCount;mLock.lock();//用来锁定共享堆内存的,因为该堆空间是与AndioFlinger进程共享的intpreviewFrameRate=mParameters.getPreviewFrameRate();ssize_toffset=mCurrentPreviewFrame*mPreviewFrameSize;//计算当前这帧数据的首地址在堆内存中的偏移量spheap=mHeap;S3C6410Camera*S3C6410Camera=mS3C6410Camera;spbuffer=mBuffers[mCurrentPreviewFrame];mLock.unlock();//释放对该共享内存的锁定if(buffer!=0){intdelay=mPreviewFrameRateMicrosec;//两帧数据之间的时间间隔void*base=heap->base();uint8_t*frame=((uint8_t*)base)+offset;//存放当前这一帧数据的堆空间的首地址。S3C6410Camera->getPreview()会将收集到的一帧数据存入该地址。intpreview_width=0;intpreview_height=0;intpreview_framesize=0;S3C6410Camera->getPreviewSize(&;preview_width,&;preview_framesize);&;preview_height,
if(S3C6410Camera->getPreview(frame,preview_framesize)<0){LOGE("ERR(%s):FailonS3C6410Camera->getPreview(frame(%p),preview_framesize(%d))",__FUNCTION__,frame,preview_framesize);returnUNKNOWN_ERROR;}mPreviewCallback(buffer,mPreviewCallbackCookie);//调用CameraService中的previewCallback函数,将得到的这帧数据的地址传到CameraService.usleep(delay);}returnNO_ERROR;}intCameraHardwareS3C6410::autoFocusThread()是实现autoFocus()的主要函数:intCameraHardwareS3C6410::autoFocusThread(){LOGE("%s",__func__);if(mS3C6410Camera->setAutofocus()<0){LOGE("E, RR(%s):FailonmS3C6410Camera->setAutofocus()",__FUNCTION__);
returnUNKNOWN_ERROR;}
if(mAutoFocusCallback!=NULL){mAutoFocusCallback(true,mAutoFocusCallbackCookie);mAutoFocusCallback=NULL;returnNO_ERROR;}returnUNKNOWN_ERROR;}intCameraHardwareS3C6410::pictureThread()实现takePicture的主要函数:intCameraHardwareS3C6410::pictureThread(){LOGE("%s",__func__);if(mShutterCallback)mShutterCallback(mPictureCallbackCookie);if(mRawPictureCallback){spmem=mBuffers[mCurrentPreviewFrame];mRawPictureCallback(mem,mPreviewCallbackCookie);//这个回调函数调用的是CameraService::Cli
ent::yuvPictureCallback(),这个函数会将当前的preview数据显示出来。}if(mJpegPictureCallback){longintjpeg_size=0;char*jpeg_data=mS3C6410Camera->getJpeg(&;jpeg_size);//得到jpeg数据流的首地址和大小,此时jpeg数据流在S3C6410Camera开辟的内存空间中。if(jpeg_data){spheap1=newMemoryHeapBase(jpeg_size);spmem1=newMemoryBase(heap1,0,jpeg_size);memcpy((uint8_t*)heap1->base(),jpeg_data,jpeg_size);//将jpeg数据流copy到新开辟的堆内存中,mJpegPictureCallback(mem1,mPictureCallbackCookie);//该回调函数调用的是CameraService::Client::jpegPictureCallback()mem1.clear();
heap1.clear();}}returnNO_ERROR;}status_tCameraHardwareS3C6410::setParameters(constCameraParameters&;params)//设置Camera的各种参数:preview_heigh,preview_width,previewsize,previewformat,previewFrameRate,picture_heigh,picture_width,picturesize,pictureformat等。S3C6410Camera的实现:S3C6410Camera采用V4L与Cameradriver通信。V4L介绍:Video4linux(简称V4L),是linux中关于视频设备的内核驱动,现在已有Video4linux2。2.Video4linux下视频编程的流程(1)打开视频设备:(2)读取设备信息(3)更改设备当前设置(没必要的话可以不做)(4)进行视频采集,两种方法:a.内存映射b.直接从设备读取(5)对采集的视频进行处理(6)关闭视频设备。V4L编程需要的命令字定义在linuxkernel的头文件videodev.h中。V4L编程流程中的每一步都是通过发送相应命令字给Cameradriver来完成的。Cameradriver中有对应命令字的具体实现。S3C6410Camera中的基本函数,(即用来发送V4L命令字的函数)如下:intv4lgetcapability(v4ldevice*vd){if(ioctl(vd->fd,VIDIOCGCAP,&;(vd->capability))<0){LOGE("anerrorhappenwhengetcapability");return-1;}//PrintcapabilityinfomationsLOGV("CapabilityInformations:\n");LOGV("name:%s\n",vd->capability.name);LOGV("type:%d\n",vd->capability.type);LOGV("maxwidth:%d\n",vd->capability.maxwidth);LOGV("maxheight:%08X\n",vd->capability.maxheight);
LOGV("minwidth:%d\n",vd->capability.minwidth);LOGV("minheight:%08X\n",vd->capability.minheight);return0;}video_capability包含设备的基本信息(设备名称、支持的最大最小分辨率、信号源信息等),包含的分量:name[32]//设备名称type//彩色还是黑白,是否能裁剪等等。maxwidth,maxheight,minwidth,minheight//最大最小分辨率
intv4lgetpicture(v4ldevice*vd){//readinformationinvideo_picturememset(&;(vd->picture),0,sizeof(vd->picture));intret=ioctl(vd->fd,VIDIOCGPICT,&;(vd->picture));if(ret<0){LOGE("VIDIOCGPICTfailed(%d)\n",ret);returnret;}LOGV("PICPTInformations:\n");LOGV("depth:%d\n",(vd->picture).depth);LOGV("palette:%d\n",(vd->picture).palette);}intv4lsetpicture(v4l
device*vd){//setinformationinvideo_pictureintret=ioctl(vd->fd,VIDIOCSPICT,&;(vd->picture));if(ret<0){LOGE("VIDIOCGPICTfailed(%d)\n",ret);returnret;}}video_picture设备采集的图象的各种属性brightness//亮度contrast//对比度depth//像素深度,即一个像素占几个字节palette//颜色空间类型。例如VIDEO_PALETTE_RGB565,yuv422
intv4lgetmbuf(v4ldevice*vd)
{if(ioctl(vd->fd,VIDIOCGMBUF,&;(vd->mbuf))<0){LOGE("v4lgetmbuf:VIDIOCGMBUF");return-1;}return0;}video_mbuf//利用mmap进行映射的帧的信息size//每帧大小Frames//最多支持的帧数Offsets//每帧相对基址的偏移intv4lmmap(v4ldevice*vd){if(v4lgetmbuf(vd)<0)return-1;if((vd->map=(unsignedchar*)mmap(0,vd->mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,vd->fd,0))<0){return-1;}return0;}intv4lgrabinit(v4ldevice*vd,intwidth,intheight){vd->mmap.width=width;vd->mmap.height=height;vd->mmap.format=vd->picture.palette;vd->frame=0;vd->framestat[0]=0;vd->framestat[1]=0;return0;}intv4lgrabstart(v4ldevice*vd,intframe){vd->mmap.frame=frame;if(ioctl(vd->fd,VIDIOCMCAPTURE,&;(vd->mmap))<0){return-1;}vd->framestat[frame]=1;return0;}
unsignedchar*v4lgetaddress(v4ldevice*vd){return(vd->map+vd->mbuf.offsets[vd->frame]);}intv4lsync(v4ldevice*vd,intframe){if(ioctl(vd->fd,VIDIOCSYNC,&;frame)<0){return-1;}vd->framestat[frame]=0;return0;}intv4lcapture(v4ldevice*vd,intframe){vd->mmap.frame=frame;if(ioctl(vd->fd,VIDIOCMCAPTURE,&;(vd->mmap))<0){return-1;}vd->framestat[frame]=1;}mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝以下详细说明用mmap(内存映射)方式截取视频的过程:intv4lgetmbuf(v4ldevice*vd)函数用来初始化video_mbuf,以得到所映射的buffer的信息调用intv4lgrabinit()可以修改video_mmapvoid*mmap(void*addr,size_tlen,intprot,intflags,intfd,off_toffset)将mmap与video_mbuf绑定len//映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起Prot//指定共享内存的访问权限PROT_READ(可读)PROT_WRITE(可写)PROT_EXEC,,(可执行)flags//MAP_SHAREDMAP_PRIVATE中必选一个//offset//共内存享的起始地址,一般设0,表示由系统分配Mmap()返回值是系统实际分配的
起始地址,该函数完成后,内存映射完成,调用进程可以通过函数unsignedchar*v4lgetaddress()得到图像数据的内存地址。intv4lcapture(v4ldevice*vd,intframe)函数是Mmap方式下真正做视频截取的
若调用成功,开始一帧的截取,是非阻塞的,intv4lsync(v4ldevice*vd,intframe)函数用来判断是否截取完毕,该函数等待一帧截取结束若成功,表明一帧截取已完成。可以开始做下一次VIDIOCMCAPTUREframe是当前截取的帧的序号。S3C6410Camera中的主要函数是利用上述基本函数实现的,主要函数如下:intS3C6410Camera::startPreview(void){//aleadystartedif(m_flag_camera_start==1)return0;if(m_cam_fd<=0)return-1;memset(&;m_events_c,0,sizeof(m_events_c));m_events_c.fd=m_cam_fd;m_events_c.events=POLLIN|POLLERR;init_yuv_buffers(m_buffers_c,m_preview_v4lformat);v4lgetpicture(&;deviceio);//setcaptureattributesdeviceio.picture.palette=VIDEO_PALETTE_RGB565;//differentcamerahasdifferentpalettedeviceio.picture.depth=16;v4lsetpicture(deviceio);v4lgrabinit(&;deviceio,m_preview_width,m_preview_height);v4lmmap(&;deviceio);m_flag_camera_start=1;return0;}intS3C6410Camera::stopPreview(void){LOGV("%s",__func__);if(m_flag_camera_start==0)return0;if(m_cam_fd<=0)m_preview_width,m_preview_height,
{LOGE("ERR(%s):Camerawasclosed\n",__FUNCTION__);return-1;}munmap(deviceio.map,deviceio.mbuf.size);close_buffers(m_buffers_c);m_flag_camera_start=0;return0;}
intS3C6410Camera::getPreview(unsignedchar*buffer,unsignedintbuffer_size){if(m_flag_camera_start==0){LOGE("ERR(%s):Previewisnotstartedyet\n",__FUNCTION__);return-1;}if(buffer==NULL||buffer_size==0){LOGE("ERR(%s):bufferisnullorbuffersizeis0\n",__FUNCTION__);return-1;}if(m_cam_fd<=0){LOGE("ERR(%s):Camerawasclosed\n",__FUNCTION__);return-1;}
inti,frame=0;v4lgrabstart(&;deviceio,frame);//开始获取影像v4lsync(&;deviceio,frame);//等待传完一帧frame=(frame+1)%2;//下一帧的framev4lcapture(&;deviceio,frame);//获取下一帧char*bufferaddr=(char*)v4lgetaddress(&;deviceio);//得到这一帧的地址//buffer给出了图像的首地址,你可以选择将图像显示或保存……
//图像的大小为width*height*2longsize=m_preview_width*m_preview_height*2;memset(buffer,0,size);memcpy(buffer,bufferaddr,size);check_performance();return0;}char*S3C6410Camera::getJpeg(longint*size){if(m_cam_fd<=0)returnNULL;if(m_flag_camera_start==1)stopPreview();longintjpeg_size=m_snapshot_width*m_snapshot_height*1;
memset(&;m_events_c,0,sizeof(m_events_c));m_events_c.fd=m_cam_fd;m_events_c.events=POLLIN|POLLERR;//setpicturetojpegmodedeviceio.picture.palette=VIDEO_PALETTE_JPEG;//differentcamerahasdifferentpalettedeviceio.picture.depth=8;v4lsetpicture(deviceio);v4lgrabinit(&;deviceio,m_snapshot_
width,m_snapshot_height);if(v4lmmap(&;deviceio)==-1){LOGE("cann'tmaped");};fimc_poll(&;m_events_c);
inti,frame=0;v4lgrabstart(&;deviceio,frame);//开始获取影像v4lsync(&;deviceio,frame);//等待传完一帧
frame=(frame+1)%2;//下一帧的framev4lcapture(&;deviceio,frame);//获取下一帧char*bufferaddr=(char*)v4lgetaddress(&;deviceio);//得到这一帧的地址*size=jpeg_size;returnbufferaddr;//将jpeg数据的存储地址返回给CameraHardwareS3C6410}================================================================androidbinder机制介绍=================================================================Binder是android提供的一种进程间通讯机制。它包括Binder驱动程序、Binder服务器及Binder客户端。Binder驱动程序:进程间传输的数据被称为Binder对象,Binder对象的传递是通过binder_transaction_data来实现的,即Binder对象实际是封装在binder_transaction_data结构体中。Binder中的一个重要概念就是对象的映射和索引。就是要把对象从一个进程映射到另一个进程中,以实现线程迁移的概念。Binder的一个重要概念是进程/线程迁移,即当一个进程需要同另一个进程通信时,它可以“迁移”远程的进程/线程到本地来执行。对于调用进程来说,看起来就像是在本地执行一样。这是Binder与其他IPC机制的不同点或者说是优点。当然迁移的工作是由Binder驱动来完成的,而实现的基础和核心就是对象的映射和索引。Binder中有两种索引,一是本地进程地址空间的一个地址,另一个是一个抽象的32位句柄(HANDLE),它们之间是互斥的:所有的进程本地对象的索引都是本地进程的一个地址(address,ptr,binder),所有的远程进程的对象的索引都是一个句柄(handle)。对于发送者进程来说,索引就是一个远端对象的一个句柄,当Binder对象数据被发送到远端接收进程时,远端接受进程则会认为索引是一个本地对象地址,因此从第三方的角度来说,尽管名称不同,对于一次Binder调用,两种索引指的是同一个对象,Binder驱动则负责两种索引的映射,这样才能把数据发送给正确的进程。所以真正通讯的机制,是内核空间中的一块共享内存。Binder服务器和Binder客户端:从应用程序的角度看Binder一共有三个方面:Native本地:例如BnABC,这是一个需要被继承和实现的类。实现BnABC::BnTransact().注册服务:IServiceManager::AddService.实现具体功能。Proxy代理:例如BpABC,这是一个在接口框架中被实现,但是在接口中没有体现的类。实现几个功能函数,调用BpABC::remote()->transact()Client:例如客户端得到一个接口ABC,在调用的时候实际上被调用的是BpABC。获得ABC接口,
然后调用接口(实际上调用了BpABC,继而通过IPC调用了BnABC,然后调用了具体的功能)在程序的实现过程中BnABC和BpABC是双继承了接口ABC。一般来说BpABC是一个实现类,这个实现类不需要在接口中体现,它实际上负责的只是通讯功能,不执行具体的功能;BnABC则是一个接口类,需要一个真正工作的类来继承、实现它,这个类才是真正执行具体功能的类。在客户端中,从ISeriviceManager中获得一个ABC的接口,客户端调用这个接口,实际上是在调用BpABC,而BpABC又通过Binder的IPC机制和BnABC通讯,BnABC的实现类
在后面执行。事实上,服务器的具体实现和客户端是两个不同的进程,如果不考虑进程间通讯的过程,从调用者的角度,似乎客户端在直接调用另外一个进程间的函数(这个函数必须是接口ABC中定义的)。Camera中利用Binder机制的一个例子:BnCameraClient的子类Camera中的相应函数得到Icamera接口,调用该接口中的函数,这时实际被调用的是BpCamera中的函数,BpCamera中的函数调用remote()->transact(),这时BnCamera的子类CameraService::Client中的onTransact()函数会被调用,onTransact()函数中包含一个switch-case函数,根据传过来的参数调用CameraService::Client中的相应函数。执行具体功能的就是这个函数。Camera中利用Binder机制的地方很多,具体流程都是一样的。=======================================================linux共享内存机制=============================================================================共享内存是进程间通信中最简单的方式之一。共享内存允许两个或更多进程访问同一块内存,当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。因为所有进程共享同一块内存,共享内存在各种进程间通信方式中具有最高的效率。访问共享内存区域和访问进程独有的内存区域一样快,并不需要通过系统调用或者其它需要切入内核的过程来完成。同时它也避免了对数据的各种不必要的复制。在Linux系统中,每个进程的虚拟内存是被分为许多页面的。这些内存页面中包含了实际的数据。每个进程都会维护一个从内存地址到虚拟内存页面之间的映射关系。尽管每个进程都有自己的内存地址,不同的进程可以同时将同一个内存页面映射到自己的地址空间中,从而达到共享内存的目的。分配一个新的共享内存块会创建新的内存页面。因为所有进程都希望共享对同一块内存的访问,只应由一个进程创建一块新的共享内存。再次分配一块已经存在的内存块不会创建新的页面,而只是会返回一个标识该内存块的标识符。一
个进程如需使用这个共享内存块,则首先需要将它绑定到自己的地址空间中。这样会创建一个从进程本身虚拟地址到共享页面的映射关系。当对共享内存的使用结束之后,这个映射关系将被删除。当再也没有进程需要使用这个共享内存块的时候,必须有一个(且只能是一个)进程负责释放这个被共享的内存页面。因为系统内核没有对访问共享内存进行同步,必须提供自己的同步措施。CameraService和AudioFlinger之间的通信使用了共享内存机制。
===============================================libCameraService.so与libCamera.so的通信流程============================================================CameraHardwareInterface.h中定义了5个函数指针,分别指向CameraService.cpp中定义的5个callback函数:void(*preview_callback)(constsp&;mem,void*user);void(*shutter_callback)(void*user);void(*raw_callback)(constsp&;mem,void*user);void(*jpeg_callback)(constsp&;mem,void*user);
void(*autofocus_callback)(boolfocused,void*user);libCamera.so是对CameraHardwareInterface.h的具体实现。其中S3C6410CameraHWInterface.cpp实现了接口中的全部函数。S3C6410Camera.cpp负责与设备通信。被S3C6410CameraHWInterface.cpp调用。libcameraService.so先调用openCameraHardware(),得到Camera实例。然后调用S3C6410CameraHWInterface.cpp中的getParameters(),setParameters()初始化这个Camera实例.S3C6410CameraHWInterface.cpp在setParameters()之后会调用initHeapLocked(),该函数用来分配存放帧数据的堆,并在已分配的堆空间上分配Buffer数组,每个数组变量存储一帧数据。libcameraService.so在Startpreview()中调用getPreviewHeap()得到libcamera.so中存放帧数据的堆的首地址。然后将这个地址注册到SurfaceFlinger的Buffer中以便提高preview的显示效率。CameraService.cpp在调用S3C6410CameraHWInterface.cpp的Startpreview()时会将自己的previewCallback()函数传进去,这样当libcamera.so在调用getPreview()收集到一帧新数据时,就可以通过函数指针调用libcameraService.so中的回调函数previewCallback(),将新收集到的帧数据的首地址传出去。CameraService.cpp接着调用postFrame(),surfcace->postBuffer()等将该地址传到surfaceFlinger中以显示当前的帧数据。S3C6410CameraHWInterface.cpp在startpreview()中新建一个线程previewThread(),在该线程中调用S3C6410Camera.cpp中的getpreview()将设备收集到的帧数据copy到存放帧数据的堆中。然后在线程中接着调用CameraService.cpp中的回调函数previewCallback(),将当前帧的偏移地址传给surfaceFlinger。以上是camera的preview过程的实现流程。在调用takePicture()之前,cameraService.cpp会先调用
autofocus(),同时将自己定义的autofocus函数传进去。cameraService.cpp中的autofocus()会调用S3C6410CameraHWInterface.cpp中的autoFocus()函数创建一个线程,在该线程中通过函数指针调用CameraService.cpp中的autoFocuscallback()通知CameraServiceautofocus成功。之后,上层的APK会调用getParameter(),setParameter()重新初始化Camera实例。当调用takePicture()时,CameraService.cpp会将自己定义的shuttercallback(),rawcallback(),jpegcallback()函数传给S3C6410CameraHWInterface.cpp中的takepicture()函数。它会创建一个线程beginPictureThread(),在其中调用函数pictureThread()。pictureThread()函数通过函数指针调用CameraService.cpp中的shuttercallback(),yuvPictureCallback(),其中yuvPictureCallback()的作用是将要拍摄的图像在preview模式下显示出来。为了调用CameraService.cpp中的jpegPictureCallback(),pictureThread()需要先调用S3C6410Camera中的getjpeg()函数取得jpeg数据流,再重新开辟一块堆空间,将jpeg数据流copy进去。之后就可以通过函数指针调用CameraService.cpp中的jpegPictureCallback(),将得到的jpeg数据流传给CameraService.cpp.得到jpeg数据流的过程:S3C6410Camera中的getjpeg()先调用m_frameSize()计算getsnapshot()得到的原始数据所需的
空间,按此大小开辟一块内存区存放getsnapshot()得到的原始数据。在通过yuv2Jpeg()函数将得到的原始数据压缩成jpeg数据流。在系统启动时,ServiceManager会加载libCameraService.so,从而使CameraService处于运行状态。==========================================================preview流程的具体实现=========================================================================点击Launcher上的Camera.apk的图标时,ActivityManager发Intent给Camera.apk,触发Camera.java实现的Activity。Camera::onCreate()>Camera::onStart()>Camera::onResume()>Camera::restartPreview()>Camera::SurfaceChanged()>Camera::setViewFinder()>Camera::ensureCameraDevice()>android.hardware.Camera::open()>android.hardware.Camera::setPreviewDisplay()(ui.ICameraClient::setPreviewDisplay()>ui::Camera.setPreviewDisplay()>ui::Camera::getCameraService()>ui::ICameraService.connect()--ui::BPCameraService.connect()>libCameraService::CameraService::connect()>ui::ICamera::setPreviewDisplay()>BpCamera::setPreviewDisplay()>libCameraservice::CameraService::Client.setPreviewDisplay())>android.hardware.Camera:getParameters()(ui::ICamera::getParameters()>BpCamera::getParameters()>libCameraservice::CameraService::Client.getParameters()>libCamera.getParameters())>android.hardware.Camera::setParameters(ui::ICamera::setParameteres()>BpCamera::setParameters()>libCameraservice::CameraService::Client.setParameters()>libCamera::setParameters())>android.hardware.Camera::startPreview()(ui::ICamera::
startPreview()>BpCamera::startPreview()>libCameraservice::CameraService::Client.startPreview()>libCamera.startPreview()>libCamera.previewThread()>libCameraservice::CameraService::Client.previewCallback()>libCameraService::CameraService::Client.postFrame()>AudioFlinger.postBuffer()每次搜集到一帧数据时重复最后三步ibCameraService::CameraService::Client将收集到的图像数据的地址传给AudioFlinger,两者之间通过共享内存通信)。上述流程中多次用到了android提供的binder机制。============================================================takepicture流程的具体实现==============================================================按下屏幕上的ShutterButton按钮。ShutterButton.java中的监听线程调用callShutterButtonFocus(),这个函数会调用接口ShutterButton.OnShutterButtonListener的函数onShutterButtonFocus()。Camera.java实现了接口ShutterButton.OnShutterButtonListener。故Camera.java中的函数onShutterButtonFocus()被调用。接着的执行流程为>doFocus()>autoFocus()>android.hardware.Camera.autoFocus()(ui::ICamera::autoFocus()-->BpCamera::autoFocus()>libCameraservice::CameraService::Client.autoFocus()>libCamera.autoFocus())
之后ShutterButton.java调用performClick(),这个函数中调用了Camera.java中的onShutterButtonClick().接着的执行流程为>dosnap()>ImagePicture.onSnap()>ImageCapture.initiate()>ImageCapture.capture()此函数执行完后,takepicture过程完成。ImageCapture.capture()的实现过程:android.hardware.Camera.getParameters()>android.hardware.Camera.setParameters()>android.hardware.Camera.takePicture(ui::ICamera::takePicture()>BpCamera::takePicture()>libCameraservice::CameraService::Client.takePicture()>libCamera.takePicure()>libCamera.pictureThread()>libCameraservice::CameraService::Client.shutterCallback()>CameraService::Client::yuvPictureCallback()(libCameraService::CameraService::Client.postFrame()>AudioFlinger.postBuffer()))>libCamera.getJpeg()>CameraService::Client::jpegPictureCallback()六.Camera功能的整体架构图============================================================CameraDriver简介========================CameraDriver实现了v4l2-ioctl.h中定义的所有命令字。当libCamera.so通过V4l与CameraDriver通信时,命令字先经过v4l-ioctl.c中相应函数的处理,再由v4l-ioctl.c调用具体的CameraDrvier.通常kerneldriver中会包含多个CameraDriver,如:fimc类型的Cameradriver,usb类型的Cameradriver.本文中调用的是sangdung提供的fimc类型的CameraDriver.该driver完成v4l2-ioctl.h中定义的命令字的具体功能。本文来自CSDN博客,转载请blog.csdn.net/jaylin2013/archive/2010/07/11/5712373.aspx标明出处:
1
ture:在preview模式下,按下takepicture按钮得到一张相
片,并存于指定文件夹下。gallery:照片预览功能,所有照片以thumbnail的形式排列在屏幕上,选中某个照片后可以全屏显示。Cameravideo:录制功能,将录制后的文件以3gp的格式存入指定文件夹下。CameraSetting:对storelocationinpictures,selectvideoquality(Low(forMMSmesssage)High(forSDcard))这两个属性的设置
Camerapreview和takepicture功能在Camera.java中实现。gallery功能主要由GalleryPicker.java,GalleryPickerItem.java,GallerySetting.java,ImageGallery2.java这几个类实现。Cameravideo功能主要由VideoCamera.java实现。videoplay功能主要由MovieView.java实现。CameraSetting:由CameraSettings.java实现。
Camera.java组成:publicclassCameraextendsActivityimplementsView.OnClickListener,ShutterButton.OnShutterButtonListener,SurfaceHolder.Callback=================================Camera.java中的主要属===============================================================ImageCapture负责与takepicture相关的所有功能privateclassImageCaptureimplementsCapturer{}privateinterfaceCapturer{UrigetLastCaptureUri();voidonSnap();voiddismissFreezeFrame(booleankeep);voidcancelSave();voidcancelAutoDismiss();性
voidsetDone(booleanwait);}MainHandler类负责将消息传给应用的主线程privateclassMainHandlerextendsHandler{}VideoPreview.javaclassVideoPreviewextendsSurfaceView用来更新preview模式下的显示内容。android.hardware.Camera负责与Camera通信的类。以下四个类是android.hardware.Camera中各个回调接口的实现类,供下层函数调用privatefinalclassShutterCallbackimplementsandroid.hardware.Camera.ShutterCallbackprivatefinalclassRawPictureCallbackimplementsPictureCallbackprivatefinalclassJpegPictureCallbackimplementsPictureCallbackprivatefinalclassAutoFocusCallbackimplementsandroid.hardware.Camera.AutoFocusCallback===================================Camera.java中的主要方法================================================================Camera.java中的主要函数onCreate()这个函数负责在Camera刚启动时,设置界面的显示。onStart()函数中newThread()在线程中调用MainHandler()的post().在屏幕上显示动画,先用白色铺满屏幕。onResume()函数注册了一个intentfilter用来接收SD卡相关的事件。中调用了restartPreview();startReceivingLocationUpdates();updateFocusIndicator();onShutterButtonFocus()当shutterButtonfocus时,调用doFocus()onShutterButtonClick()当shutterButtonpress时,调用dosnap()onStop()函数用来停止一个Camera实例,它调用stopPreview(),closeCamera();mHandler.removeMessages(CLEAR_SCREEN_DELAY);setViewFinder()调用android.hardware.Camera.setPreviewDisplay()进入preview模式。stopPreview()退出pre
view模式gotoGallery()进入Gallery模式(即图片预览)calculatePicturesRemaining()计算存储picture所需要的空间。onCreateOptionsMenu(),onPrepareOptionsMenu(),onOptionsMenuClosed()//与菜单控件相关的函数surfaceChanged(),surfaceChanged(),surfaceDestroyed(),这三个函数用来在preview模式下更新屏幕。restartPreview()使Camera进入preview模式=====================================Camera.java的执行流程==================================================================点击Launcher上的Camera.apk的图标时,ActivityManager发Intent给Camera.apk,触发Camera.java实现的Activity。
在onCreate()函数创建Camera.java需要的对象实例。其中创建VideoPreview的SurfaceHolder,同时注册callback函数,VideoPreview的长宽变化时,当调用SurfaceChanged()函数。此部分代码:mSurfaceView=(VideoPreview)findViewById(R.id.camera_preview);SurfaceHolderholder=mSurfaceView.getHolder();holder.addCallback(this);在onResume()中调用restartPreview(),在此函数中创建了一个VideoPreview实例,这个创建动作使SurfaceHolder的回调函数SurfaceChanged()被调用。同时调用ShutterButton.java,显示ShutterButton按钮,同时启动一个线程监听Shutterbutton按下事件。Camera.java重新实现了SurfaceChanged()。在SurfaceChanged()中,调用了setViewFinder()函数,该函数用来设置preview的display.此函数完成后Camera处于preview模式。同时创建了ImagePicture实例,为takePicture作准备。setViewFinder()的实现过程:ensureCameraDevice()>mCameraDevice.setPreviewDisplay()-->mCameraDevice.getParameters()>mCameraDevice.setParameters(p)>mCameraDevice.startPreview().ensureCameraDevice()调用android.hardware.Camera.open()得到一个android.hardwareCamera实例mCameraDevice.
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\以上为Camera.java实现preview的流程,顺序图。\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
按下屏幕上的ShutterButton按钮。ShutterButton.java中的监听线程调用callShutterButtonFocus(),这个函数会调用接口ShutterButton.OnShutterButtonListener的函数onShutterButtonFocus()。Camera.java实现了接口ShutterButton.OnShutterButtonListener。故Camera.java中的函数onShutterButtonFocus()被调用。接着的执行流程为>doFocus()>autoFocus()>mCameraDevice.autoFocus()之后ShutterButton.java调用performClick(),这个函数中调用了Camera.java中的onShutterButtonClick().接着的执行流程为>dosnap()>ImagePicture.onSnap()>ImageCapture.initiate()>ImageCapture.capture()此函数执行完后,takepicture过程完成。ImageCapture.capture()的实现过程:
mCameraDevice.getParameters()>mCameraDevice.takePicture()
mCameraDevice.set
Parameters()>