검색결과 리스트
글
안드로이드 프레임워크 프로그래밍(11) [JAVA 프레임워크와 Native 프레임워크 연결 원리]
어느덧 안드로이드 프레임워크를 연구한지 3달 정도 되어갑니다. 초반에는 온갖 삽질이 길어져서 작업 하나를 수행하는 데에도 많은 시간이 소요되었습니다만 현재 조금 프로그램의 흐름을 볼 수 있는 눈이 생겨 어느 정도 감을 잡아가는 단계가 되었다고 조심스럽게 말해봅니다.
이번 포스팅에서는 안드로이드 기기가 부팅된 후 Java와 Native 프레임워크가 JNI로 연결되는 과정에 대해 다루어 보도록 하겠습니다.
이전 포스팅에서 service의 JNI 연결과정을 다룬 바 있습니다. 이번 포스팅에서는 '/framework/base/core'에 있는 프레임워크들이 JNI를 통해 Native와 서로 연결되는 과정을 다루게 됩니다. Java Service와 Native Service의 연결 과정에 대해서는 아래 포스팅을 참조해 주시길 바랍니다.
본 포스팅은 안드로이드 카메라 시스템인 Camera.java와 android_hardware_Camera.cpp가 JNI로 함수가 연결되는 과정을 예로 설명드리겠습니다.
안드로이드 Framework는 기기의 전원이 들어온 후 부팅이 완료되었을 때 init를 통해 zygote가 실행됩니다. 이 zygote가 동작하는 과정에서 AndroidRuntime::start() 함수를 소환함으로서 안드로이드 기기의 동작을 준비하는 과정을 거칩니다. 해당 코드를 살펴보면 다음과 같습니다.
/frameworks/base/core/jni/AndroidRuntime.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | void AndroidRuntime::start(const char* className, const char* options) { .... /* * Register android functions. */ if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } .... } | cs |
AndroidRuntime::start() 함수가 실행된 후 startReg()함수를 불러들이는 모습입니다. startReg() 함수를 통해 JNI가 동작되는 함수들을 실행하게 되는데 해당 함수를 자세히 살펴보도록 하겠습니다.
/frameworks/base/core/jni/AndroidRuntime.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | /* * Register android native functions with the VM. */ /*static*/ int AndroidRuntime::startReg(JNIEnv* env) { /* * This hook causes all future threads created in this process to be * attached to the JavaVM. (This needs to go away in favor of JNI * Attach calls.) */ androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc); ALOGV("--- registering native functions ---\n"); /* * Every "register" function calls one or more things that return * a local reference (e.g. FindClass). Because we haven't really * started the VM yet, they're all getting stored in the base frame * and never released. Use Push/Pop to manage the storage. */ env->PushLocalFrame(200); if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { env->PopLocalFrame(NULL); return -1; } env->PopLocalFrame(NULL); //createJavaThread("fubar", quickTest, (void*) "hello"); return 0; } | cs |
startReg() 함수 내에서 JNI를 등록하는 register_jni_procs()함수가 동작하는 것을 확인하실 수 있습니다. 그 안에 있는 인자인 gRegJNI는 JNI로 연결시킬 Register 함수들이 등록되어있는 구조체입니다. 코드를 통해 좀 더 자세히 구성요소를 확인해 보도록 하겠습니다.
/frameworks/base/core/jni/AndroidRuntime.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | extern int register_android_hardware_Camera(JNIEnv *env); #ifdef NDEBUG #define REG_JNI(name) { name } struct RegJNIRec { int (*mProc)(JNIEnv*); }; #else #define REG_JNI(name) { name, #name } struct RegJNIRec { int (*mProc)(JNIEnv*); const char* mName; }; #endif typedef void (*RegJAMProc)(); static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env) { for (size_t i = 0; i < count; i++) { if (array[i].mProc(env) < 0) { #ifndef NDEBUG ALOGD("----------!!! %s failed to load\n", array[i].mName); #endif return -1; } } return 0; } static const RegJNIRec gRegJNI[] = { .... REG_JNI(register_android_hardware_Camera), .... }; | cs |
위 코드 내용을 읽어보니 상당히 흥미로운 부분을 확인할 수 있었습니다. 각 함수들을 하나씩 살펴보도록 하겠습니다.
static const RegJNIRec gRegJNI[]
구조체 RegJNIRec를 배열로 선언하고 있습니다. 배열은 초기화가 진행중인데 그 안에 있는 REG_JNI()는 코드 내에서 define 되어 있는 것을 확인하실 수 있습니다.
#define REG_JNI(name) { name }
위에서 보시면 아시듯 'REG_JNI(name)'으로 선언된 부분이 { name }으로 변경되고 있는 것을 확인하실 수 있습니다. 그래고 바로 아래에는 구조체 RegJNIRec가 선언되고 있는 것을 보실 수 있습니다. 구조체 내부에 있는 int(*mProc)(JNIEnv*)는 포인터 함수로서 extern으로 선언되어 있던 함수 register_android_hardware_Camera()를 등록하는 구조임을 알 수 있습니다.
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
위 함수를 통해 드디어 본격적으로 JNI가 동작하게 됩니다. 함수 내부의 코드를 살펴보면 다음과 같은 것을 보실 수 있습니다.
if (array[i].mProc(env) < 0)
위에서 설명한 gRegJNI[] 배열 내에 있던 구조체 RegJNIRec 내에 설정했던 함수 포인터들이 위 코드를 통해 반복문으로 모두 실행하는 것을 보실 수 있습니다. 위 과정을 실행하게 되면 프레임워크 내에 존재하는 모든 Java와 Native 함수들이 연결됩니다.
다음으로 우리들이 등록하였던 register_android_hardware_Camera()함수를 보도록 하겠습니다.
/frameworks/base/core/jni/android_hardware_Camera.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | static JNINativeMethod camMethods[] = { .... { "native_setup", "(Ljava/lang/Object;ILjava/lang/String;)V", (void*)android_hardware_Camera_native_setup }, .... }; // Get all the required offsets in java class and register native functions int register_android_hardware_Camera(JNIEnv *env) { .... // Register native functions return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera", camMethods, NELEM(camMethods)); } | cs |
위 코드를 보았을 때 JNINativeMethod 배열을 선언하는 과정을 보실 수 있는데 해당 배열 내에 선언된 값을 하나 보시면 다음과 같습니다.
위의 구조를 보았을 때 JNINativeMethod가 struct 구조체로 구성되어 있다는 사실을 어느 정도 직감하실 수 있으실 겁니다! 해당 구조체 내에는 3개의 변수를 저장할 수 있는대 내용은 다음과 같습니다.
{ Java에서 선언된 native method, Signature, C++에서 연결하고자 하는 함수 }
위와 같은 방식으로 값들을 선언해 주시면 되겠습니다. 위에서 Signature는 Java에서 선안된 함수의 인자와 return을 간단하게 나타낸 것을 말합니다. Signature에 대해 좀 더 자세히 알고 싶으신 분들은 아래 포스팅을 참조해 주시기 바랍니다.
다음으로 AndroidRuntime.cpp에서 연결했었던 register_android_hardware_Camera(JNIEnv *env)함수를 확인해 보면 리턴형으로 다시 AndroidRuntime 내의 함수를 호출하고 있는 모습을 보실 수 있습니다. 이를 다시 AndroidRuntime.cpp 에서 확인해 보도록 하겠습니다.
/frameworks/base/core/jni/AndroidRuntime.cpp
1 2 3 4 5 6 7 8 | /* * Register native methods using JNI. */ /*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { return jniRegisterNativeMethods(env, className, gMethods, numMethods); } | cs |
드디어 이번 포스팅의 핵심이라 할 수 있는 jniRegisterNativeMethods()함수가 등장하였습니다! 해당 함수가 실행되게 되면 C++과 Java와의 함수가 최종적으로 연결됩니다. 해당 함수의 인자는 다음과 같이 구성되어 있습니다.
(Java VM 환경변수, 연결하고자 하는 Class의 경로, Native와 Java 사이에 연결하고자 하는 함수들의 내역이 있는 구조체 JNINativeMethod, gMethod의 길이);
위의 과정을 통해 연결된 Java 매소드는 해당 코드를 통하여 확실하게 확인하실 수 있습니다!
/frameworks/base/core/java/android/hardware/Camera.java
1 2 3 4 5 6 7 8 9 | public class Camera { .... private native final void native_setup(Object camera_this, int cameraId, String packageName); .... } | cs |
/frameworks/base/core/jni/android_hardware_Camera.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | // connect to camera service static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint cameraId, jstring clientPackageName) { // Convert jstring to String16 const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL); jsize rawClientNameLen = env->GetStringLength(clientPackageName); String16 clientName(rawClientName, rawClientNameLen); env->ReleaseStringChars(clientPackageName, rawClientName); sp<Camera> camera = Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID); if (camera == NULL) { jniThrowRuntimeException(env, "Fail to connect to camera service"); return; } // make sure camera hardware is alive if (camera->getStatus() != NO_ERROR) { jniThrowRuntimeException(env, "Camera initialization failed"); return; } jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { jniThrowRuntimeException(env, "Can't find android/hardware/Camera"); return; } // We use a weak reference so the Camera object can be garbage collected. // The reference is only used as a proxy for callbacks. sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera); context->incStrong((void*)android_hardware_Camera_native_setup); camera->setListener(context); // save context in opaque field env->SetIntField(thiz, fields.context, (int)context.get()); } | cs |
'안드로이드 > 프레임워크' 카테고리의 다른 글
| 안드로이드 프레임워크 프로그래밍(13) [커널이미지 적용후 부팅화면만 나올 때 대처법] (0) | 2015.03.24 |
|---|---|
| 안드로이드 프레임워크 프로그래밍(12) [IServiceManager 등록과정] (1) | 2015.03.23 |
| 안드로이드 Native 코드 분석 : sp<> - Smart Pointer (0) | 2015.03.02 |
| SurfaceView에서 SurfaceHolder의 동작원리(Principle of SurfaceHolder in SurfaceView) (1) | 2015.02.26 |
| 안드로이드 프레임워크 프로그래밍(10) [Native C/C++ 코드에서 Java 호출] (0) | 2015.02.18 |
설정
트랙백
댓글
글
티스토리 블로그를 반년간 하면서...
안녕하세요. '늦깎이 공대생의 좌충우돌 이야기'를 연재하고 있는 흔한 공대생입니다!
블로그를 시작한 지도 어느덧 반년이 넘어가고 있습니다. 그 동안 글을 쓰면서 많은 생각을 해 보았고 어떻게 하면 사람들에게 나의 주장을 좀 더 쉽게 이해할 수 있게 적을 수 있을까 하는 고민도 해보기도 합니다. 글을 쓰면서도 이 글이 과연 사람들에게 도움을 줄 수는 있을까 하는 생각도 해보고 내가 쓴 글을 통해 사람들이 제 글을 읽어주시길 바라는 마음도 들기도 했습니다.
지금껏 블로그를 운영하면서 이렇게 블로그에 큰 애정을 쏟아본 것도 처음이고 블로그라는 사람들과 소통할 수 있다는 것도 저에게는 큰 재미 중 하나 이기도 합니다. 초기에 블로그가 개설되었을 당시에는 이틀에 한 명 들어올까 말까 하던 제 블로그가 현재는 하루에 50명 정도 방문해 주시고 계십니다. 지금까지 작성된 포스팅이 80개 정도 되는 것을 생각한다면 참으로 많은 분들에 제 블로그에 와주신다는 것에 가끔은 행복하기도 합니다.
비록 하루에 만 명 단위로 사람들이 오는 블로그들에 비하면 초라하지만 제 포스팅이 하나 둘 늘어날 수록 방문해주시는 분들이 점점 늘어나고 있는 모습을 볼 때마다 항상 행복한 생각이 많이 듭니다. 이 자리를 빌어 제 블로그를 찾아와주신 분들께 진심으로 감사의 말씀을 드리고 싶습니다!
처음 블로그를 만들던 당시에는 제 취미 중 하나인 여행기도 함께 포스팅을 해보려 했습니다만, 역시 공대생 답게 공부한 내용들에 대한 포스팅이 태반인건 다소 아쉬운 느낌이 듭니다. 저도 가끔은 계속 미루기만 하던 여행기를 다른 분들이 생각치 못한 관점으로 사람들에게 보여주고자 하는 생각도 조금은 들기도 합니다.
그 덕분인지 제 포스팅을 읽고 제게 도움을 청하시는 공대생 분들의 사연을 접하기도 합니다. 심지어 같은 학교에 다니는 같은 작품을 만들고 있는 동료가 저에게 도움을 요청하였던 재미있는 일도 있었습니다. 저 또한 그 분들의 심정을 매우 잘 알기에 자신의 능력 내에서 많은 도움이 될 수 있게 도와주는 것도 어떻게 보면 블로그를 통한 소통의 방법이 아닐까 하는 생각이 듭니다.
티스토리, 저에게 티스토리는 정말로 좋은 추억을 만들어 주었습니다. 다른 사람들에게 제 지식을 피력할 수 있었던 곳이었고, 저에게 다른 사람들의 이야기를 들려주는 장소가 되어주기도 했었습니다. 저에게 있어 티스토리는 제 일상에서 보지 못했던 사람의 일상을 보여주는 곳이 아닌가 생각합니다.
비록 지금 저의 필력은 많이 모자릅니다만, 티스토리를 통해 글을 쓰는 데에 좀 더 많은 노력을 하게 되는 기회가 되었으면 합니다. 그리고 좀 더 많은 사람들과 교류하며 다양한 사람사는 이야기를 공유할 수 있는 곳이 되어 주기를 바랍니다!
※제게 큰 즐거움을 주셨던 티스토리 블로거 여러분들께 진심으로 감사드립니다!
'공대생의 팁' 카테고리의 다른 글
| 우분투에서 인터넷창을 통해 윈도 미디어 플레이어 관련 영상 보는 방법 (0) | 2015.04.04 |
|---|---|
| 우분투 사용중 안보이거나 깨진 언어가 나올 때 언어 설치방법 (0) | 2015.03.26 |
| [VMware] NX / XD is required. The processor must support and it must be enabled in the BIOS. (0) | 2015.02.21 |
| Windows XP에서 DOS 파일 실행시 EMS 문제 해결방법 (0) | 2015.01.26 |
| WF2411 공유기를 통한 외부 기기와 소켓 통신 프로그래밍 (3) | 2014.11.02 |
설정
트랙백
댓글
글
안드로이드 Framework에서 Camera 동작 원리 분석(1)
안드로이드 프레임워크를 공부하면서 느끼는 점이 애플리케이션 단계에서는 함수 몇 줄만 쓰면 쉽게 구현되는 기능이 프레임워크를 공부하면서 안드로이드 세계의 심오함을 몸소 느끼고 있습니다. 정말로 운영체제를 만든 분들이 존경스러울 정도 입니다.
이번 포스팅 부터는 안드로이드 카메라가 Framework 단계에서 동작하는 과정에 대해 살펴보도록 하겠습니다. 내용이 상당히 방대하기 때문에 분량을 중간에 나누어 가면서 다루도록 하겠습니다.
우리들이 Applycation 단계에서 Camera를 사용할 때 보통은 SurfaceHolder를 통해서 Camera를 사용합니다. 혹시 SurfaceHolder의 동작 원리에 대해 자세히 알고 싶으신 분은 아래 포스팅을 참조해 주셨으면 합니다.
Application 단계에서 Camera 클래스가 사용되는 사례를 보도록 합시다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | private SurfaceHolder.Callback surfaceListener = new SurfaceHolder.Callback() { @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub camera.release(); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub camera = Camera.open(); try { camera.setPreviewDisplay(holder); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(width, height); camera.startPreview(); } }; | cs |
흔히들 위의 방식대로 Camera 클래스를 사용하고 계시리라 생각합니다. 그렇다면 각 함수별로 좀 더 들어가보도록 하겠습니다.
SurfaceView가 화면에 보이게 되면 SurfaceHolder에서 surfaceCreated()함수가 실행됩니다. 이 때 Camera 관련 기능들이 동작을 시작하게 되는 것이지요.
camera = Camera.open();
이 부분은 Camera의 기능을 활성화 하는 단계입니다. Camera의 코드 내부를 살펴보면 다음과 같습니다.
/frameworks/base/core/java/android/hardware/Camera.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | public class Camera { .... public static Camera open(int cameraId) { return new Camera(cameraId); } public static Camera open() { int numberOfCameras = getNumberOfCameras(); CameraInfo cameraInfo = new CameraInfo(); for (int i = 0; i < numberOfCameras; i++) { getCameraInfo(i, cameraInfo); if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) { return new Camera(i); } } return null; } Camera(int cameraId) { mShutterCallback = null; mRawImageCallback = null; mJpegCallback = null; mPreviewCallback = null; mPostviewCallback = null; mUsingPreviewAllocation = false; mZoomListener = null; Looper looper; if ((looper = Looper.myLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else if ((looper = Looper.getMainLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else { mEventHandler = null; } String packageName = ActivityThread.currentPackageName(); native_setup(new WeakReference<Camera>(this), cameraId, packageName); } private native final void native_setup(Object camera_this, int cameraId, String packageName); .... } | cs |
위에서 보시는 바와 같이 JNI를 통해 native_setup()를 호출하는 모습을 보실 수 있습니다. 이번에는 Native 코드를 확인해 보도록 하겠습니다.
/frameworks/base/core/jni/android_hardware_Camera.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | // connect to camera service static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint cameraId, jstring clientPackageName) { // Convert jstring to String16 const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL); jsize rawClientNameLen = env->GetStringLength(clientPackageName); String16 clientName(rawClientName, rawClientNameLen); env->ReleaseStringChars(clientPackageName, rawClientName); sp<Camera> camera = Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID); if (camera == NULL) { jniThrowRuntimeException(env, "Fail to connect to camera service"); return; } // make sure camera hardware is alive if (camera->getStatus() != NO_ERROR) { jniThrowRuntimeException(env, "Camera initialization failed"); return; } jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { jniThrowRuntimeException(env, "Can't find android/hardware/Camera"); return; } // We use a weak reference so the Camera object can be garbage collected. // The reference is only used as a proxy for callbacks. sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera); context->incStrong((void*)android_hardware_Camera_native_setup); camera->setListener(context); // save context in opaque field env->SetIntField(thiz, fields.context, (int)context.get()); } | cs |
이 함수들을 처음 접하시는 분들은 상당한 압박감이 오시리라 생각합니다. 당연히 처음 프레임워크 소스를 분석할 때 뭐가 뭔지 전허 알 길이 없기 때문에 초기에는 해멜 수 밖에 없는 것은 사실입니다. 하지만 겁먹지 않고 차근차근 살펴보다 보면 어느덧 수많은 코드에 익숙해져 있는 자신을 발견하게 될 것입니다.
위 과정에서 sp<>의 기능에 대해 생소해 하실 분들이 계실 겁니다. 이전 포스팅에서 제가 아는 한에서 나마 설명한 자료가 있으니 해당 자료를 참조해 주셨으면 합니다.
다음으로 해당 함수가 실행되는 것을 보실 수 있습니다.
sp<Camera> camera = Camera::connect(cameraId, clientName,
이는 Camera.cpp 의 클래스에서 카메라와 연결되는 과정을 다루고 있는 것입니다. 이를 한 번 자세히 보도록 하겠습니다.
/frameworks/av/camera/Camera.cpp
1 2 3 4 5 | sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName, int clientUid) { return CameraBaseT::connect(cameraId, clientPackageName, clientUid); } | cs |
여기까지 쉼없이 달려왔건만 이번에는 CameraBaseT라는 함수가 튀어나오는군요!
/frameworks/av/include/camera/CameraBase.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | template <typename TCam> struct CameraTraits { }; template <typename TCam, typename TCamTraits = CameraTraits<TCam> > class CameraBase : public IBinder::DeathRecipient { public: typedef typename TCamTraits::TCamListener TCamListener; typedef typename TCamTraits::TCamUser TCamUser; typedef typename TCamTraits::TCamCallbacks TCamCallbacks; typedef typename TCamTraits::TCamConnectService TCamConnectService; static sp<TCam> connect(int cameraId, const String16& clientPackageName, int clientUid); virtual void disconnect(); void setListener(const sp<TCamListener>& listener); static int getNumberOfCameras(); static status_t getCameraInfo(int cameraId, /*out*/ struct CameraInfo* cameraInfo); static status_t addServiceListener( const sp<ICameraServiceListener>& listener); static status_t removeServiceListener( const sp<ICameraServiceListener>& listener); sp<TCamUser> remote(); // Status is set to 'UNKNOWN_ERROR' after successful (re)connection status_t getStatus(); protected: CameraBase(int cameraId); virtual ~CameraBase(); //////////////////////////////////////////////////////// // TCamCallbacks implementation //////////////////////////////////////////////////////// virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2); //////////////////////////////////////////////////////// // Common instance variables //////////////////////////////////////////////////////// Mutex mLock; virtual void binderDied(const wp<IBinder>& who); // helper function to obtain camera service handle static const sp<ICameraService>& getCameraService(); sp<TCamUser> mCamera; status_t mStatus; sp<TCamListener> mListener; const int mCameraId; typedef CameraBase<TCam> CameraBaseT; }; | cs |
/frameworks/av/camera/CameraBase.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | template <typename TCam, typename TCamTraits> sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId, const String16& clientPackageName, int clientUid) { ALOGV("%s: connect", __FUNCTION__); sp<TCam> c = new TCam(cameraId); sp<TCamCallbacks> cl = c; status_t status = NO_ERROR; const sp<ICameraService>& cs = getCameraService(); if (cs != 0) { TCamConnectService fnConnectService = TCamTraits::fnConnectService; status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, /*out*/ c->mCamera); } if (status == OK && c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); c->mStatus = NO_ERROR; } else { ALOGW("An error occurred while connecting to camera: %d", cameraId); c.clear(); } return c; } | cs |
드디어 가장 중요한 CameraService와 IPC통신을 할 수 있는 부분까지 나온 것을 확인하게 되었습니다. Camera에서 Open() 함수를 좇다 CameraService와의 연계점을 직접 보게 된 상황입니다.
우선 여기까지 잘 따라와 주신 분이라면 Camera 클래스가 IPC로 연결되기 바로 직전의 부분에 이르렀음을 말씀드리고 싶네요. 다음 시간에는 CameraService와 Camera가 연결되는 과정을 살펴보도록 하겠습니다.
안드로이드 Framework에서 Camera 동작 원리 분석(2)
'안드로이드 > 카메라' 카테고리의 다른 글
| 안드로이드 Camera의 Framework 구조 (0) | 2015.08.27 |
|---|---|
| 안드로이드 Framework에서 Camera 동작 원리 분석(4) (0) | 2015.05.01 |
| 안드로이드 Framework에서 Camera 동작 원리 분석(3) (0) | 2015.04.27 |
| 안드로이드 Framework에서 Camera 동작 원리 분석(2) (3) | 2015.04.26 |
| Kitkat 이후의 버전에서 SrufaceView를 활용하여 Camera 활용하기 (0) | 2015.02.04 |