반응형
PDK에서 Surface를 제어하는 예제를 가져다가 JNI를 통해 어플과 연동시키려고 했는데
JAVA Application과 연동하면 자꾸만 Permission 문제가 발생하였다.

W/ServiceManager(  577): Permission failure: android.permission.ACCESS_SURFACE_FLINGER from uid=10020 pid=735
E/SurfaceFlinger(  577): Permission Denial: can't access SurfaceFlinger pid=735, uid=10020

위와 같이 Surface를 생성하려니까 자꾸만 Permission Denial 이라는 메세지가 나와서 ServiceManager 쪽에서 Permission 체크하는 부분을 아예 없애버렸는데 없애니까 작동을 잘 하기는 했다.

하지만 이렇게하면 올바른 방법이 아니기 때문에 한참 삽질끝에 JAVA에서 Surface를 JNI를 통해 끌어내리고 그것을 이용해서 Surface를 잡고, 또 그것을 이용해서 ISurface를 얻는 방법으로 진행했다.

다음의 코드를 참조하면 된다.

  1. #include <utils/IPCThreadState.h>  
  2. #include <utils/ProcessState.h>  
  3. #include <utils/IServiceManager.h>  
  4. #include <utils/Log.h>  
  5.  
  6. #include <ui/Surface.h>  
  7. #include <ui/ISurface.h>  
  8. #include <ui/Overlay.h>  
  9. #include <ui/SurfaceComposerClient.h>  
  10.   
  11. using namespace android;  
  12.   
  13. namespace android {  
  14. class Test {  
  15. public:  
  16.     static const sp<ISurface>& getISurface(const sp<Surface>& s) {  
  17.         return s->getISurface();  
  18.     }  
  19. };  
  20. };  
  21.   
  22. int main(int argc, char** argv)  
  23. {  
  24.     // set up the thread-pool  
  25.     sp<ProcessState> proc(ProcessState::self());  
  26.     ProcessState::self()->startThreadPool();  
  27.   
  28.     // create a client to surfaceflinger  
  29.     sp<SurfaceComposerClient> client = new SurfaceComposerClient();  
  30.   
  31.     // create pushbuffer surface  
  32.     sp<Surface> surface = client->createSurface(getpid(), 0, 320, 240,  
  33.             PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);  
  34.   
  35.     // get to the isurface  
  36.     sp<ISurface> isurface = Test::getISurface(surface);  
  37.     printf("isurface = %p\n", isurface.get());  
  38.   
  39.     // now request an overlay  
  40.     sp<OverlayRef> ref = isurface->createOverlay(320, 240, PIXEL_FORMAT_RGB_565);  
  41.     sp<Overlay> overlay = new Overlay(ref);  
  42.   
  43.   
  44.     /* 
  45.      * here we can use the overlay API  
  46.      */  
  47.   
  48.     overlay_buffer_t buffer;  
  49.     overlay->dequeueBuffer(&buffer);  
  50.     printf("buffer = %p\n", buffer);  
  51.   
  52.     void* address = overlay->getBufferAddress(buffer);  
  53.     printf("address = %p\n", address);  
  54.   
  55.     overlay->queueBuffer(buffer);  
  56.   
  57.     return 0;  
  58. }  


안드로이드의 frameworks/base/include/ui/Surface.h에 보면 getISurface가 private로 지정되어 있어서 다른 곳에서 접근 할 수가 없다.

그래서 Surface에 접근하는 Camera나 MediaRecoder, MediaPlayer 등등은 자신의 클래스를 friend class로 등록함으로써 Surface에 접근한다.

그중에 Test라는 클래스가 있는데 이놈을 이용하여 Surface에 접근 가능하다.

frameworks/base/libs/surfaceflinger/tests/overlays/overlays.cpp

를 참고하면 된다. 


반응형
Posted by Real_G