SlideShare a Scribd company logo
1 of 26
SurfaceFlingerService
(서피스 플링거 연결-JB)




                             박철희

                         1
1.서피스 플링거 서비스 연결 요청(서비스 클라이언트)

 1.Surfaceflinger 검색 및 proxy 획득




                  ISurfaceComposer

  Android_view_Surface.cpp
  static void SurfaceSession_init(JNIEnv* env, jobject clazz)
  {
     sp<SurfaceComposerClient> client = new SurfaceComposerClient;
  }


 SurfaceComposerClient.cpp
 SurfaceComposerClient::SurfaceComposerClient(): mStatus(NO_INIT), mComposer(Composer::getInstance())
 {
 }
 SurfaceComposerClient는 Refbase를 상속받았기 때문에, onFirstRef 가 불린다.



  void SurfaceComposerClient::onFirstRef()
  {
    sp<ISurfaceComposer> sm(getComposerService());
     ..
                                                                                                  2
1.서피스 플링거 서비스 연결 요청(서비스 클라이언트)
 static inline sp<ISurfaceComposer> getComposerService() {
    return ComposerService::getComposerService();
 }


 sp<ISurfaceComposer> ComposerService::getComposerService() {
   return ComposerService::getInstance().mComposerService;
 }
                             ComposerService 는 singleton class를 상속받았음으로,
                             이미 ComposerService 객체가 있으면 그 객체를 return하고,
                             없으면, ComposerService 의 생성자를 호출해서 객체를 생성한다.

  ComposerService::ComposerService()
  : Singleton<ComposerService>() {
     const String16 name("SurfaceFlinger");
     while (getService(name, &mComposerService) != NO_ERROR) {
       usleep(250000);
     }
      SurfaceFlinger service의 proxy(ISurfaceCompser)를 mComposerService 에 저장한다.

  }

2.디스플레이 공유 메모리 서비스의 프록시 획득




                  IMemoryHeap

                                                                                  3
1.서피스 플링거 서비스 연결 요청(서비스 클라이언트)


 SurfaceComposerClient.cpp
 ComposerService::ComposerService(): Singleton<ComposerService>() {
   const String16 name("SurfaceFlinger");
   while (getService(name, &mComposerService) != NO_ERROR) {
      usleep(250000);
   }
    SurfaceFlinger service의 proxy(ISurfaceCompser)를 mComposerService 에 저장한다.
   mServerCblkMemory = mComposerService->getCblk();
   Surface flinger의 getCblk를 이용하여 디스플레이 공유 메모리의 서비스 프락시(IMemoryHep)을 획득한다.
   mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(mServerCblkMemory->getBase());
   획득한 proxy로 공유메모리의 surface_flinger_cblk_t 구조체의 주소를 획득한다.
 }




                                       surface_flinger_cblk_t                  surfaceflinger
   SurfaceComposerClient

                                             connected                         mServerCblk
      ComposerService
                                    Dislay_cblk_t dcblk

         mServerCblk                  w,h:프레임 버퍼 너비,높이
                                             Density,fps
                                          Format,orientation
                                             Xdpi,ydpi




                                                                                                4
1.서피스 플링거 서비스 연결 요청(서비스 클라이언트)

3.서비스 클라이언트 프락시 획득




                 ISurfaceComposerClient

  void SurfaceComposerClient::onFirstRef()
  {
      sp<ISurfaceComposer> sm(getComposerService());
   if (sm != 0) {                                                   ISurfaceComposerClient
        sp<ISurfaceComposerClient> conn = sm->createConnection();
        Surfaceflinger에 있는 createConnection 가 호출 됨.
  }                                                                 BnSurfaceComposerClient
  SurfaceFlinger.cpp
  sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
  {                                                                             Client
    sp<ISurfaceComposerClient> bclient;
    sp<Client> client(new Client(this));                            ~Client();
    status_t err = client->initCheck();                             createSurface;
    if (err == NO_ERROR) {                                          destroySurface
        bclient = client;                                           DefaultKeyedVector< size_t,
    }                                                               wp<LayerBaseClient> >
    return bclient;Client class의 proxy인 ISurfaceComposerClient가    mLayers;
                     return됨.
  }                                                                                  5
1.서피스 플링거 연결 요청

-서피스 클라이언트 리모트 서비스의 역할

1.서피스 플링거 서비스의 래퍼:
 서피스 플링거 서비스 기능 중 일부를 사용할 수 있도록 제공함
 (서피스 생성,삭제,서피스 상태 변경)

2.애플리케이션별 레이어 관리:
 서피스 클라이언트 별로 서피스에 대한 지역 식별자를 할당하고, DefaultKeyedVector에
 지역식별자와 layer를 함께 추가함.

3. 레이어 상태 변경:애플리케이션이 서피스의 상태 변경(가로,세로 전환)을 서피스 클라이언트 리모트
           서비스에게 요청한다.

4.애플리케이션 레이어의 생명 주기 관리:
 서피스 생성을 요청한 애플리케이션이 비정상적으로 동작을 종료하더라도 관리하고 있는 서피스와
 관련 자원을 서피스 클라이언트의 소멸자에서 자동으로 해제해 준다.
 (why? Client class는 Refbase class를 상속 받는데 이 Refbase class는 참조하는 곳이 없어질때
      자동으로 소멸자를 불러주게 된다.)




                                                                    6
2.노말 서피스 생성 요청 (서비스 클라이언트)




                             7
2.노말 서피스 생성 요청 (서비스 클라이언트)
1)노말 서피스 생성 요청(C5)
Surface.java
                                                                struct surface_data_t {
public Surface()
                                                                      int32_t        token; 지역 식별자
{
                                                                      int32_t        identity;  전역 식별자
  init(s,pid,name,display,w,h,format,flags);
                                                                      status_t readFromParcel(const Parcel& parcel);
}
                                                                      status_t writeToParcel(Parcel* parcel) const;
                                                                   };
Android_view_surface.cpp
static void Surface_init
{
  surface = client->createSurface(dpy, w, h, format, flags);}



sp<SurfaceControl> SurfaceComposerClient::createSurface(…)
{
  ISurfaceComposerClient::surface_data_t data;
  p<ISurface> surface = mClient->createSurface(&data, name, display, w, h, format, flags);
  서피스 클라이언트의 createSurface를 호출한다.
    서피스가 생성되면 서피스 핸들의 서비스 프록시(ISurface)가 반환된다.(C6)
    Isurface 서비스 프록시는 서피스 텍스쳐 리모트 서비스의 서비스 프록시(ISurfaceTexture)를 반환하는 함수를 제공한다.

     if (surface != 0) {
          result = new SurfaceControl(this, surface, data, w, h, format, flags);
          return된 Isurface proxy를 이용해서 SurfaceControl class를 생성한다.
            이 class는 BufferQueue 리모트 서비스의 서비스 프락시를 획득하거나,서피스의 상태 변경을 할 수 있다.
      }
                                        서피스 클라이언트 리모트 서비스는 서피스 플링거 서비스의 메시지 큐에 서피스
     return result;                     생성 메시지를 넣는다.
}                                       그런면 서피스 플링거는 루퍼에서 메시지를 가져와 핸들러를 호출한다.
                                        이 때 호출되는 핸들러가 서피스 플링거에 있는 createSurface 함수 이다.

                                                                                                     8
2.노말 서피스 생성 (서비스 서버)
sp<ISurface> Client::createSurface(ISurfaceComposerClient::surface_data_t* params, const String8& name,
    DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
    uint32_t flags)
{

    class MessageCreateSurface : public MessageBase {

    public:
       MessageCreateSurface(SurfaceFlinger* flinger,
              ISurfaceComposerClient::surface_data_t* params,
              const String8& name, Client* client,
              DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
              uint32_t flags)
          : flinger(flinger), params(params), client(client), name(name),
            display(display), w(w), h(h), format(format), flags(flags)
       {
       }
       sp<ISurface> getResult() const { return result; }
       virtual bool handler() {
          result = flinger->createSurface(params, name, client, display, w, h, format, flags);
          메시지 큐의 핸들러에서 서피스 플링거의 createSurface를 불러 줌.
          return true;
       }
    };

    sp<MessageBase> msg = new MessageCreateSurface(mFlinger.get(),params, name, this, display, w, h, format, flags);
    메시지 큐와 핸들러 생성(S3)
    mFlinger->postMessageSync(msg);  생성된 메시지를 서피스 플링거 서비스의 메시지 큐에 넣음.(S4)
    return static_cast<MessageCreateSurface*>( msg.get() )->getResult();

}

                                                                                                          9
2.노말 서피스 생성 (서비스 서버)
sp<ISurface> SurfaceFlinger::createSurface(…)
{
  sp<LayerBaseClient> layer;
   sp<Layer> normalLayer;
   switch (flags & eFXSurfaceMask) {
      case eFXSurfaceNormal:
         normalLayer = createNormalSurface(client, d, w, h, flags, format);
         1.노말 레이어를 생성 함.(S5)
         노말 레이어 생성 시 BufferQueue 리모트 서비스가 생성 됨. 또한, SurfaceTexture 객체도 생성 됨.(S6)
        layer = normalLayer;
        break;
    }

    if (layer != 0) {
       layer->initStates(w, h, flags); 2.생성된 layer 상태 초기화(S7)
       ssize_t token = addClientLayer(client, layer);  3.전역 레이어 목록과 지역 레이어 목록에 추가
       surfaceHandle = layer->getSurface();  4. 서피스 핸들의 서비스 프록시(Isurface)를 반환 함.(S8)
       if (surfaceHandle != 0) {  mClient->createSurface 호출시 넘겨준 surface_data_t 구조체에 값을 채움.
           params->token = token;  서피스 지역 식별자
           params->identity = surfaceHandle->getIdentity();  서피스 전역 식별자
     }
       setTransactionFlags(eTransactionNeeded); 서피스 플링거가 합성 시 참조하는 상태 플래그에 설정.

    return surfaceHandle;  서피스 핸들 proxy(Isurface)를 return함.
}




                                                                                               10
2.노말 서피스 생성 (서비스 서버)-메시지 큐와 핸들러 생성




sp<ISurface> Client::createSurface(ISurfaceComposerClient::surface_data_t* params, const String8& name,
      DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
      uint32_t flags)
{
  sp<MessageBase> msg = new MessageCreateSurface(mFlinger.get(),params, name, this, display, w, h, format, flags);
   메시지 큐와 핸들러 생성
   mFlinger->postMessageSync(msg);  생성된 메시지를 서피스 플링거 서비스에게 전달(동기식)
   return static_cast<MessageCreateSurface*>( msg.get() )->getResult();
}

status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime, uint32_t flags)
{
   status_t res = mEventQueue.postMessage(msg, reltime);
   생성된 메시지를 메시지 큐로 보냄. 이 메시지는 서피스 플링거 서비스의 네이티브 루퍼에서 처리 됨.
   msg->wait(); 메시지의 핸들러가 수행이 완료 될 때 까지 기다림.
}
                                                                                                          11
2.노말 서피스 생성 (서비스 서버)-메시지 큐와 핸들러 생성
MessageQueue.cpp
status_t MessageQueue::postMessage(const sp<MessageBase>& messageHandler, nsecs_t relTime)
{
   const Message dummyMessage;
   if (relTime > 0) {
       mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage);
   } else {
       mLooper->sendMessage(messageHandler, dummyMessage);
       서피스 플링거 서비스 네이티브 루퍼에게 메시지 전달
   }
   return NO_ERROR;
}




class MessageCreateSurface : public MessageBase {

        virtual bool handler() {
          result = flinger->createSurface(params, name, client, display, w, h, format, flags);
          메시지 큐의 핸들러에서 서피스 플링거의 createSurface를 불러 줌.
          return true;
       }
  };




                                                                                                 12
2.노말 서피스 생성 (서비스 서버)-레이어 생성

sp<Layer> SurfaceFlinger::createNormalSurface(..)                                 LayerBase(레이어 상태 변경 관리)
{
  sp<Layer> layer = new Layer(this, display, client);
  this:Surfaceflinger 인스턴스,                                                         LayerBaseClient
    display:출력될 display의 번호,                                                   (클라이언트 리모트 서비스의 자원 관리
    client:서피스 클라이언트
  status_t err = layer->setBuffers(w, h, format, flags);
    레이어 멥버 변수 초기 값 설정, 서피스 텍스처 기본 크기 결정.                                                          Layer         Layer
   return layer;  생성된 레이어 반환                                                        Layer
                                                                                                 Screenshot       Dim
}
                          Layer class 생성 시 LayerBase의 생성자 부터 호출된다.
Layerbase.cpp
LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
  : dpy(display), contentDirty(false),
    sequence(uint32_t(android_atomic_inc(&sSequence))),                                      SurfaceFlinger
     sSequence 값을 sequence에 저장하고 sSequence를 1증가 시킨다.                                                    지역 레이어 목록
     sequence 변수는 동일 Z-order 값을 가지는 레이어를 정렬할때 사용 함.
                                                                               전역 레이어 목록                  Client 1
{
  …                                                                            zorder                         Token=1
                                                                                        mIdentity
}                                                                                                             Token=2
                                                                                 4           4
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,     3           1
                                                                                                         지역 레이어 목록
     const sp<Client>& client)                                                   2           2
  : LayerBase(flinger, display), mClientRef(client),                             1           3            Client 2
    mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
    서피스 전역 식별자인 mIdentity의 값을 설정한다.                                                                          Token=1
{                                                                                                             Token=2
}



                                                                                                          13
2.노말 서피스 생성 (서비스 서버)-레이어 생성
Layer::Layer(SurfaceFlinger* flinger,
    DisplayID display, const sp<Client>& client)
  : LayerBaseClient(flinger, display, client), mTextureName,(텍스쳐 번호), …
{
  glGenTextures(1, &mTextureName);
  서피스 플링거 서비스는 하나의 레이어를 하나의 텍스쳐로 사용하여 합성함.
    따라서, 각 레이어를 구별할 수 있는 인자가 필요한데, glGenTextures에서 mTextureName에 ID를 생성 함.
}
Layer Class는 RefBase를 상속했음으로, onFirstRef()가 불림.(BufferQueue 리모트 서비스 생성)
void Layer::onFirstRef()
{
  struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
      FrameQueuedListener(Layer* layer) : mLayer(layer) { }
  private:
      wp<Layer> mLayer;
      virtual void onFrameAvailable() {
         sp<Layer> that(mLayer.promote());                      void Layer::onFrameQueued() {
         if (that != 0) {                                          android_atomic_inc(&mQueuedFrames);
             that->onFrameQueued();                                mFlinger->signalEvent();
         }                                                      }
      }
  };
   // Creates a custom BufferQueue for SurfaceTexture to use
  sp<BufferQueue> bq = new SurfaceTextureLayer();
   SurfaceTextureLayer 객체를 생성 한다. SurfaceTextureLayer는 BufferQueue class를 상속 받고 있다.
    BufferQueue는 서피스 플링거와 어플리케이션 사이에서 그래픽 버퍼 공유 및 버퍼 획득,전달을 담당 함.
  mSurfaceTexture = new SurfaceTexture(mTextureName, true,GL_TEXTURE_EXTERNAL_OES, false, bq);
  SurfaceTexture 생성 시 BufferQueue 의 포인터를 인자로 생성 함.
     (SurfaceTexture 에서 BufferQueue 를 이용해서 버퍼 획득,전달을 하겠다는 의미)
   mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
   SurfaceTextureLayer의 listener를 FrameAvailableListener 로 등록 한다.
                                                                                                    14
2.노말 서피스 생성 (서비스 서버)-레이어 생성

mSurfaceTexture->setSynchronousMode(true);
버퍼 출력 모드를 동기식으로 설정 함.
Cf. 동기 모드: 애플리케이션이 출력 요청 한 순서대로 서피스 플링거가 합성하여 화면에 출력
  비동기 모드:애플리케이션이 여러 번 출력 요청을 하더라도, 서피스 플링거 서비스는 가장 마지막에 출력 요청된 그래픽
  버퍼만 화면에 출력 함.

mSurfaceTexture->setBufferCountServer(3); 트리플 버퍼 설정.
}




                                                           15
2.노말 서피스 생성 (서비스 서버)-BufferQueue 리모트 서비스 생성

▶ 서피스 전달,획득 출력 요청등에 대한 모든 과정은 애플리케이션 측의 SurfaceTextureClient와 서버측의 BufferQueue 가
  담당한다.
▶ BufferQueue 는 레이어 생성 시 생성 됨.

BufferQueue::BufferQueue( bool allowSynchronousMode, int bufferCount ) :
  mDefaultWidth(1),  생성될 버퍼의 width
  mDefaultHeight(1), 생성될 버퍼의 Height
  mPixelFormat(PIXEL_FORMAT_RGBA_8888), 버퍼의 핏셀 포맷
   …
   mBufferCount(mMinAsyncBufferSlots), 클라이언트와 서버 간에 동시에 유지하고 있는 버퍼 슬롯의 수
  mClientBufferCount(0), 클라이언트에서 요청한 버퍼 슬롯의 수
  mServerBufferCount(mMinAsyncBufferSlots),  서버 측에서 요청한 버퍼 슬롯의 수
  mSynchronousMode(false), 버퍼 출력 모드 (true:동기식, false:비동기식)
   …
{
  sp<ISurfaceComposer> composer(ComposerService::getComposerService());
  mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
  서피스 플링거 서비스에게 GraphicBufferAlloc 리모트 서비스의 생성을 요청 하고, IGraphicBufferAlloc 서비스 프록시를
    획득한다.
}



Surfaceflinger.cpp
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
{
  sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
  return gba;
}
 BufferQueue의 그래픽 버퍼 할당은 GraphicBufferAlloc를 통해서만 이루어짐.


                                                                           16
2.노말 서피스 생성 (서비스 서버)-서피스 텍스처 생성

▶ 서피스 플링거 서비스가 서피스를 텍스처로 다룰 수 있도록 도움을 주는 class이다.

SurfaceTexture.cpp
SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
  GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
  …
{
   if (bufferQueue == 0) {
       mBufferQueue = new BufferQueue(allowSynchronousMode);
       어플리케이션(서비스 클라이언트) 측에서 SurfaceTexture를 생성하는 경우 여기서 BufferQueue 가 생성 됨.
   }
   else {
       mBufferQueue = bufferQueue;
   }
   …
   listener = static_cast<BufferQueue::ConsumerListener*>(this);
    SurfaceTexture는 BufferQueue::ConsumerListener를 상속 받는다.
       BufferQueue::ConsumerListener는 그래픽 버퍼가 추가(onFrameAvailable) 되거나,
      해제 될때 (onBuffersReleased) 불려지는 함수의 interface이다.

 proxy = new BufferQueue::ProxyConsumerListener(listener);
  BufferQueue::ProxyConsumerListener를 생성 한다.

 status_t err = mBufferQueue->consumerConnect(proxy);
  생성한 BufferQueue::ProxyConsumerListener를 BufferQueue의 이벤트 리스너로 등록한다.
  이 의미는 BufferQueue::ProxyConsumerListener::onFrameAvailable() ->
           BufferQueue::ConsumerListener의 onFrameAvailable ->
              SurfaceTexture::onFrameAvailable() ->
              virtual void onFrameAvailable()(Layer.cpp) ->
          mFlinger->signalEvent();
   로 호출된다.

                                                                          17
2.노말 서피스 생성 (서비스 서버)-노말 레이어 초기화

2.생성된 layer 상태 초기화
layer->initStates(w, h, flags);
Layerbase class의 initStates 가 호출됨.


void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags)
{

     mCurrentState.z       = 0; mCurrentState.w      = w; mCurrentState.h = h;
     mCurrentState.requested_w = w; mCurrentState.requested_h = h;
     mCurrentState.sequence    = 0;
     sequence 값은 드로잉 프레임에서의 레이어와 현재 프레임의 레이어 상태가 변경될 때 1씩 증가
     mDrawingState = mCurrentState;
      mDrawingState (화면에 출력중인 레이어의 상태 저장)과
       mCurrentState(화면 출력을 위해 합성중인 레이어의 상태 저장)를 동일하게 설정
}
    3.전역 레이어 목록과 지역 레이어 목록에 추가
    ssize_t token = addClientLayer(client, layer);


                               SurfaceFlinger                        1.전역 레이어 목록
                                                                     -서피스 플링거 서비스에서 생성된 전체 레이어 목록
                                                지역 레이어 목록            -정렬 순서:zorder 순서
         전역 레이어 목록                                                   - mCurrentState.layersSortedByZ 변수로 관리
                                                Client 1
          layersSortedByZ                                            2.지역 레이어 목록
                                                 mLayers
          zorder   mIdentity                                         -특정 Client에서 생성된 레이어 목록
                                                 Token=1
            4          4                                             -지역 레이어 목록의 레이어는 전역 레이어 목록에
            3          1
                                                 Token=2              추가됨.
                                                                     -Client class의 mLayers 변수로 관리

                                                                                                18
2.노말 서피스 생성 (서비스 서버)-노말 레이어 초기화

ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
     const sp<LayerBaseClient>& lbc)
{
  // 지역 레이어 목록에 추가
  size_t name = client->attachLayer(lbc);

    // 전역 레이어 목록에 추가
    addLayer_l(lbc);

    return ssize_t(name);
}


size_t Client::attachLayer(const sp<LayerBaseClient>& layer)
{
   size_t name = mNameGenerator++;
   mLayers.add(name, layer);
   return name;
}


status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
{
   ssize_t i = mCurrentState.layersSortedByZ.add(layer);
   return (i < 0) ? status_t(i) : status_t(NO_ERROR);
}




                                                                   19
2.노말 서피스 생성 (서비스 서버)-리모트 서비스 생성 후 반환

4. Isurfacetexture 서비스 프락시를 획득하기 위한 함수를 제공하는 서피스 핸들 리모트 서비스(Bsurface) 생성 후 반환한다.
surfaceHandle = layer->getSurface();


Layerbase.cpp의 getSurface가 호출 됨.
sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
{
  sp<Surface> s;
  Mutex::Autolock _l(mLock);
  s = mClientSurface.promote();
  if (s == 0) {
      s = createSurface();
      mClientSurface = s;
  }
  return s;         Layer.cpp의 오버라이딩 된 createSurface를 부른다.
}
                                                    class BSurface : public BnSurface, public LayerCleaner {
                                                         wp<const Layer> mOwner;
Layer.cpp                                                virtual sp<ISurfaceTexture> getSurfaceTexture() const {
sp<ISurface> Layer::createSurface()                         sp<ISurfaceTexture> res;
{                                                           sp<const Layer> that( mOwner.promote() );
  sp<ISurface> sur(new BSurface(mFlinger, this));           if (that != NULL) {
   return sur;                                                  res = that->mSurfaceTexture->getBufferQueue;
   Isurfacetexture 서비스 프락시를 획득하기 위한                            res는 BufferQueue의 sp를 가리킴.
    BSurface class를 생성하고 Bsurface의 proxy인                   }
                                                            return res;
    Isurface를 return한다.
                                                         }
   서피스 핸들을 반환 받은 서비스 클라이언트에서는
                                                      public:
    getSurfaceTexture() 로 BufferQueue에                   BSurface(const sp<SurfaceFlinger>& flinger,
    접근할 수 있다.                                                   const sp<Layer>& layer)
}                                                           : LayerCleaner(flinger, layer), mOwner(layer) { }
                                                      };
3.SurfaceTextureClient 생성(서비스 클라이언트)

 ISurface Proxy를 가진 SurfaceControl class의 getSurface함수를 통하여 ISurfaceTexture 서비스 proxy를 얻을 수 있다.
 ISurfaceTexture 는 BufferQueue와 연결 되어 있어 서피스의 그래픽 버퍼 생성,요청,출력등을 제공 한다.

Android_view_Surface.cpp
static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
{
 result = control->getSurface();
}

Surface.cpp
sp<Surface> SurfaceControl::getSurface() const
{
  if (mSurfaceData == 0) {
      sp<SurfaceControl> surface_control(const_cast<SurfaceControl*>(this));
      mSurfaceData = new Surface(surface_control);
      SurfaceTextureClient 클래스를 상속 받은 Surface class를 생성 한다.
  }
  return mSurfaceData;           Surface class의 주요 함수
}
                                        함수 명                                    설명

                                        isValid()           Surface 생성시 초기화가 정상적으로 이루어 졌는지 check

                                      getIdentity()         해당 서피스의 전역 식별자를 획득한다.

                                         Lock()             그래픽 버퍼의 가상 주소를 획득한다.

                                    Unlockandpost()         서피스 플링거 서비스에게 출력을 요청한다.

                                  getSurfaceTexture()       서피스 텍스쳐 리모트 서비스의 서비스 프락시(ISurfaceTexture)를
                                                            획득한다.
3.SurfaceTextureClient 생성(서비스 클라이언트)

Surface::Surface(const sp<SurfaceControl>& surface)                    SurfaceTextureClient::SurfaceTextureClient() {
  : SurfaceTextureClient()  SurfaceTextureClient 의 생성자 호출                SurfaceTextureClient::init();
   mSurface(surface->mSurface),                                        }
    mIdentity(surface->mIdentity)
{                                                                       ANativeWindow 함수 포인터에
  sp<ISurfaceTexture> st;                                              SurfaceTextureClient 함수를 할당 함.
  if (mSurface != NULL) {                                              void SurfaceTextureClient::init() {
      st = mSurface->getSurfaceTexture();                              ANativeWindow::dequeueBuffer
      ISurfaceTexture proxy를 획득한다.                                     = hook_dequeueBuffer;
       (SurfaceTexture는 BufferQueue를 가지고 있다.)                             ANativeWindow::cancelBuffer
  }                                                                    = hook_cancelBuffer;
  init(st);                                                               ANativeWindow::lockBuffer
}                                                                      = hook_lockBuffer;
                                                                          ANativeWindow::queueBuffer
                                                                       = hook_queueBuffer;
                                                                       }

void Surface::init(const sp<ISurfaceTexture>& surfaceTexture)
{
  if (mSurface != NULL || surfaceTexture != NULL) {
      if (surfaceTexture != NULL) {
          setISurfaceTexture(surfaceTexture);
          setUsage(GraphicBuffer::USAGE_HW_RENDER);그래픽 버퍼의 속성값을 지정 함.
           USAGE_HW_RENDER:그래픽 버퍼를 openGLES의 렌더링 대상으로 사용한다는 의미
      }
}
void SurfaceTextureClient::setISurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture)
{
  mSurfaceTexture = surfaceTexture;
}
3.서피스 생성 요청 전체 그림




       Client                                                 SurfaceFlinger
                                                                     Client
                                                   BSurface
     surfacecomposerclient                                            Layer
                                 ISurfaceTexture                              BufferQueue
          surfacecontrol


                                                                        Surfacetexturelayer
    ANativeWindow      Refbase


         surfacetextureclient                                            surfacetexture


             surface




                                                                                   23
참고.ANativeWindow 인터페이스

애플리케이션과 서피스 플링거는 ANativeWindow 인터페이스를 통해 그래픽 버퍼와 네이티브 버퍼를 획득 또는 출력한다.
차이점은, 애플리케이션은 출력대상이 그래픽 버퍼이고, 서피스 플링거는 네이티브 버퍼 이다.




                                                              24
참고.ANativeWindow 인터페이스

 애플리케이션 측- SurfaceTextureClient 이용
1)애플리케이션은 SurfaceTextureclient 를 이용하여 그래픽 버퍼를 획득하고 출력한다.
2) SurfaceTextureclient 는 ANativeWidnow interface를 상속 받는다.
3) ANativeWidnow interface에 SurfaceTextureclient 함수 포인터를 매핑한다.
  이 말은, 애플리케이션이 ANativeWidnow interface를 이용하여 버퍼를 할당 받고자 할때 실제 불리는
  함수는 SurfaceTextureclient 에 있는 함수가 불리게 된다.
  서피스 플링거의 경우는 FramebufferNativewindow의 함수를 부르게 된다.
4)Surfacetexture class는 클라이언트로 부터 그래픽 버퍼 요청이 오면 사용 가능한 버퍼를 검색하여 인덱스
  번호를 전달하고, 출력 요청이 오면 출력 대기 큐(mQueue)에 저장한다.



 서피스 플링거 서비스 측- FramebufferNativewindow 사용
5)합성 요청 signal(Vsync)를 받으면 합성을 시작하게 된다.
6)서피스 플링거 서비스는 FramebufferNativewindow 를 사용하여 네이티브 버퍼를 획득하고, 출력 요청한다.
7) FramebufferNativewindow 클래스의 함수가 ANativeWidnow interface 에 매핑된다.
FramebufferNativewindow의 출력 대상은 프레임 버퍼이다.
8)버퍼 할당 요청이 오면 프레임 버퍼를 전달하고 출력 요청이 오면 디스플레이에 출력 요청을 한다.




                                                            25
참고자료


 안드로이드 미디어 프레임워크 –”개발자가 행복한 세상”

 Goolge Jelly bean Source




                                   26

More Related Content

What's hot

What's hot (20)

Startup JavaScript 6 - 함수, 스코프, 클로저
Startup JavaScript 6 - 함수, 스코프, 클로저Startup JavaScript 6 - 함수, 스코프, 클로저
Startup JavaScript 6 - 함수, 스코프, 클로저
 
[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화
 
Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체
 
객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회
 
Blockchain 4th dapp programming
Blockchain 4th dapp programmingBlockchain 4th dapp programming
Blockchain 4th dapp programming
 
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
 
Blockchain 3rd smart contract programming
Blockchain 3rd smart contract programmingBlockchain 3rd smart contract programming
Blockchain 3rd smart contract programming
 
Clean code appendix 1
Clean code appendix 1Clean code appendix 1
Clean code appendix 1
 
NDC11_슈퍼클래스
NDC11_슈퍼클래스NDC11_슈퍼클래스
NDC11_슈퍼클래스
 
7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성
 
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - PerfornanceGCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
 
GCGC- CGCII 서버 엔진에 적용된 기술 (1)
GCGC- CGCII 서버 엔진에 적용된 기술 (1)GCGC- CGCII 서버 엔진에 적용된 기술 (1)
GCGC- CGCII 서버 엔진에 적용된 기술 (1)
 
세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화
 
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
 
5-5. html5 connectivity
5-5. html5 connectivity5-5. html5 connectivity
5-5. html5 connectivity
 
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing SystemGCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
 
Blockchain 1st bitcoin_core
Blockchain 1st bitcoin_coreBlockchain 1st bitcoin_core
Blockchain 1st bitcoin_core
 
Jupyter notebok tensorboard 실행하기_20160706
Jupyter notebok tensorboard 실행하기_20160706Jupyter notebok tensorboard 실행하기_20160706
Jupyter notebok tensorboard 실행하기_20160706
 
GCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with Exception
GCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with ExceptionGCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with Exception
GCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with Exception
 

Viewers also liked

Viewers also liked (10)

Android audio system(audiopolicy_manager)
Android audio system(audiopolicy_manager)Android audio system(audiopolicy_manager)
Android audio system(audiopolicy_manager)
 
Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)
 
Android audio system(오디오 출력-트랙생성)
Android audio system(오디오 출력-트랙생성)Android audio system(오디오 출력-트랙생성)
Android audio system(오디오 출력-트랙생성)
 
Android audio system(audioflinger)
Android audio system(audioflinger)Android audio system(audioflinger)
Android audio system(audioflinger)
 
Camera camcorder framework overview(ginger bread)
Camera camcorder framework overview(ginger bread)Camera camcorder framework overview(ginger bread)
Camera camcorder framework overview(ginger bread)
 
Stagefright recorder part1
Stagefright recorder part1Stagefright recorder part1
Stagefright recorder part1
 
Android Audio & OpenSL
Android Audio & OpenSLAndroid Audio & OpenSL
Android Audio & OpenSL
 
Android audio system(audioplicy_service)
Android audio system(audioplicy_service)Android audio system(audioplicy_service)
Android audio system(audioplicy_service)
 
Android Audio System
Android Audio SystemAndroid Audio System
Android Audio System
 
Android audio system(audio_hardwareinterace)
Android audio system(audio_hardwareinterace)Android audio system(audio_hardwareinterace)
Android audio system(audio_hardwareinterace)
 

Similar to Surface flingerservice(서피스 플링거 연결 jb)

Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)
문익 장
 

Similar to Surface flingerservice(서피스 플링거 연결 jb) (20)

[Swift] Command
[Swift] Command[Swift] Command
[Swift] Command
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)
 
Node.js and react
Node.js and reactNode.js and react
Node.js and react
 
모델링 연습 리뷰
모델링 연습 리뷰모델링 연습 리뷰
모델링 연습 리뷰
 
Android 기초강좌 애플리캐이션 구조
Android 기초강좌 애플리캐이션 구조Android 기초강좌 애플리캐이션 구조
Android 기초강좌 애플리캐이션 구조
 
세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발
 
TR 069 클라이언트 검토자료 3편
TR 069 클라이언트 검토자료 3편TR 069 클라이언트 검토자료 3편
TR 069 클라이언트 검토자료 3편
 
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JS
 
12장 상속 (고급)
12장 상속 (고급)12장 상속 (고급)
12장 상속 (고급)
 
Airflow를 이용한 데이터 Workflow 관리
Airflow를 이용한  데이터 Workflow 관리Airflow를 이용한  데이터 Workflow 관리
Airflow를 이용한 데이터 Workflow 관리
 
안드로이드 오픈소스 그리고 패턴
안드로이드 오픈소스 그리고 패턴  안드로이드 오픈소스 그리고 패턴
안드로이드 오픈소스 그리고 패턴
 
안드로이드 오픈소스 패턴 - 0.1
안드로이드 오픈소스 패턴 - 0.1안드로이드 오픈소스 패턴 - 0.1
안드로이드 오픈소스 패턴 - 0.1
 
Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs
 
웹 사이트 시각화 및 성능 관리
웹 사이트 시각화 및 성능 관리웹 사이트 시각화 및 성능 관리
웹 사이트 시각화 및 성능 관리
 
04 프로세스
04 프로세스04 프로세스
04 프로세스
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기
 
Reflow and repaint 성능 비용
Reflow and repaint 성능 비용Reflow and repaint 성능 비용
Reflow and repaint 성능 비용
 

Surface flingerservice(서피스 플링거 연결 jb)

  • 2. 1.서피스 플링거 서비스 연결 요청(서비스 클라이언트) 1.Surfaceflinger 검색 및 proxy 획득 ISurfaceComposer Android_view_Surface.cpp static void SurfaceSession_init(JNIEnv* env, jobject clazz) { sp<SurfaceComposerClient> client = new SurfaceComposerClient; } SurfaceComposerClient.cpp SurfaceComposerClient::SurfaceComposerClient(): mStatus(NO_INIT), mComposer(Composer::getInstance()) { } SurfaceComposerClient는 Refbase를 상속받았기 때문에, onFirstRef 가 불린다. void SurfaceComposerClient::onFirstRef() { sp<ISurfaceComposer> sm(getComposerService()); .. 2
  • 3. 1.서피스 플링거 서비스 연결 요청(서비스 클라이언트) static inline sp<ISurfaceComposer> getComposerService() { return ComposerService::getComposerService(); } sp<ISurfaceComposer> ComposerService::getComposerService() { return ComposerService::getInstance().mComposerService; } ComposerService 는 singleton class를 상속받았음으로, 이미 ComposerService 객체가 있으면 그 객체를 return하고, 없으면, ComposerService 의 생성자를 호출해서 객체를 생성한다. ComposerService::ComposerService() : Singleton<ComposerService>() { const String16 name("SurfaceFlinger"); while (getService(name, &mComposerService) != NO_ERROR) { usleep(250000); }  SurfaceFlinger service의 proxy(ISurfaceCompser)를 mComposerService 에 저장한다. } 2.디스플레이 공유 메모리 서비스의 프록시 획득 IMemoryHeap 3
  • 4. 1.서피스 플링거 서비스 연결 요청(서비스 클라이언트) SurfaceComposerClient.cpp ComposerService::ComposerService(): Singleton<ComposerService>() { const String16 name("SurfaceFlinger"); while (getService(name, &mComposerService) != NO_ERROR) { usleep(250000); }  SurfaceFlinger service의 proxy(ISurfaceCompser)를 mComposerService 에 저장한다. mServerCblkMemory = mComposerService->getCblk(); Surface flinger의 getCblk를 이용하여 디스플레이 공유 메모리의 서비스 프락시(IMemoryHep)을 획득한다. mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(mServerCblkMemory->getBase()); 획득한 proxy로 공유메모리의 surface_flinger_cblk_t 구조체의 주소를 획득한다. } surface_flinger_cblk_t surfaceflinger SurfaceComposerClient connected mServerCblk ComposerService Dislay_cblk_t dcblk mServerCblk w,h:프레임 버퍼 너비,높이 Density,fps Format,orientation Xdpi,ydpi 4
  • 5. 1.서피스 플링거 서비스 연결 요청(서비스 클라이언트) 3.서비스 클라이언트 프락시 획득 ISurfaceComposerClient void SurfaceComposerClient::onFirstRef() { sp<ISurfaceComposer> sm(getComposerService()); if (sm != 0) { ISurfaceComposerClient sp<ISurfaceComposerClient> conn = sm->createConnection(); Surfaceflinger에 있는 createConnection 가 호출 됨. } BnSurfaceComposerClient SurfaceFlinger.cpp sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() { Client sp<ISurfaceComposerClient> bclient; sp<Client> client(new Client(this)); ~Client(); status_t err = client->initCheck(); createSurface; if (err == NO_ERROR) { destroySurface bclient = client; DefaultKeyedVector< size_t, } wp<LayerBaseClient> > return bclient;Client class의 proxy인 ISurfaceComposerClient가 mLayers; return됨. } 5
  • 6. 1.서피스 플링거 연결 요청 -서피스 클라이언트 리모트 서비스의 역할 1.서피스 플링거 서비스의 래퍼: 서피스 플링거 서비스 기능 중 일부를 사용할 수 있도록 제공함 (서피스 생성,삭제,서피스 상태 변경) 2.애플리케이션별 레이어 관리: 서피스 클라이언트 별로 서피스에 대한 지역 식별자를 할당하고, DefaultKeyedVector에 지역식별자와 layer를 함께 추가함. 3. 레이어 상태 변경:애플리케이션이 서피스의 상태 변경(가로,세로 전환)을 서피스 클라이언트 리모트 서비스에게 요청한다. 4.애플리케이션 레이어의 생명 주기 관리: 서피스 생성을 요청한 애플리케이션이 비정상적으로 동작을 종료하더라도 관리하고 있는 서피스와 관련 자원을 서피스 클라이언트의 소멸자에서 자동으로 해제해 준다. (why? Client class는 Refbase class를 상속 받는데 이 Refbase class는 참조하는 곳이 없어질때 자동으로 소멸자를 불러주게 된다.) 6
  • 7. 2.노말 서피스 생성 요청 (서비스 클라이언트) 7
  • 8. 2.노말 서피스 생성 요청 (서비스 클라이언트) 1)노말 서피스 생성 요청(C5) Surface.java struct surface_data_t { public Surface() int32_t token; 지역 식별자 { int32_t identity;  전역 식별자 init(s,pid,name,display,w,h,format,flags); status_t readFromParcel(const Parcel& parcel); } status_t writeToParcel(Parcel* parcel) const; }; Android_view_surface.cpp static void Surface_init { surface = client->createSurface(dpy, w, h, format, flags);} sp<SurfaceControl> SurfaceComposerClient::createSurface(…) { ISurfaceComposerClient::surface_data_t data; p<ISurface> surface = mClient->createSurface(&data, name, display, w, h, format, flags); 서피스 클라이언트의 createSurface를 호출한다. 서피스가 생성되면 서피스 핸들의 서비스 프록시(ISurface)가 반환된다.(C6) Isurface 서비스 프록시는 서피스 텍스쳐 리모트 서비스의 서비스 프록시(ISurfaceTexture)를 반환하는 함수를 제공한다. if (surface != 0) { result = new SurfaceControl(this, surface, data, w, h, format, flags); return된 Isurface proxy를 이용해서 SurfaceControl class를 생성한다. 이 class는 BufferQueue 리모트 서비스의 서비스 프락시를 획득하거나,서피스의 상태 변경을 할 수 있다. } 서피스 클라이언트 리모트 서비스는 서피스 플링거 서비스의 메시지 큐에 서피스 return result; 생성 메시지를 넣는다. } 그런면 서피스 플링거는 루퍼에서 메시지를 가져와 핸들러를 호출한다. 이 때 호출되는 핸들러가 서피스 플링거에 있는 createSurface 함수 이다. 8
  • 9. 2.노말 서피스 생성 (서비스 서버) sp<ISurface> Client::createSurface(ISurfaceComposerClient::surface_data_t* params, const String8& name, DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { class MessageCreateSurface : public MessageBase { public: MessageCreateSurface(SurfaceFlinger* flinger, ISurfaceComposerClient::surface_data_t* params, const String8& name, Client* client, DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) : flinger(flinger), params(params), client(client), name(name), display(display), w(w), h(h), format(format), flags(flags) { } sp<ISurface> getResult() const { return result; } virtual bool handler() { result = flinger->createSurface(params, name, client, display, w, h, format, flags); 메시지 큐의 핸들러에서 서피스 플링거의 createSurface를 불러 줌. return true; } }; sp<MessageBase> msg = new MessageCreateSurface(mFlinger.get(),params, name, this, display, w, h, format, flags); 메시지 큐와 핸들러 생성(S3) mFlinger->postMessageSync(msg);  생성된 메시지를 서피스 플링거 서비스의 메시지 큐에 넣음.(S4) return static_cast<MessageCreateSurface*>( msg.get() )->getResult(); } 9
  • 10. 2.노말 서피스 생성 (서비스 서버) sp<ISurface> SurfaceFlinger::createSurface(…) { sp<LayerBaseClient> layer; sp<Layer> normalLayer; switch (flags & eFXSurfaceMask) { case eFXSurfaceNormal: normalLayer = createNormalSurface(client, d, w, h, flags, format);  1.노말 레이어를 생성 함.(S5)  노말 레이어 생성 시 BufferQueue 리모트 서비스가 생성 됨. 또한, SurfaceTexture 객체도 생성 됨.(S6) layer = normalLayer; break; } if (layer != 0) { layer->initStates(w, h, flags); 2.생성된 layer 상태 초기화(S7) ssize_t token = addClientLayer(client, layer);  3.전역 레이어 목록과 지역 레이어 목록에 추가 surfaceHandle = layer->getSurface();  4. 서피스 핸들의 서비스 프록시(Isurface)를 반환 함.(S8) if (surfaceHandle != 0) {  mClient->createSurface 호출시 넘겨준 surface_data_t 구조체에 값을 채움. params->token = token;  서피스 지역 식별자 params->identity = surfaceHandle->getIdentity();  서피스 전역 식별자 } setTransactionFlags(eTransactionNeeded); 서피스 플링거가 합성 시 참조하는 상태 플래그에 설정. return surfaceHandle;  서피스 핸들 proxy(Isurface)를 return함. } 10
  • 11. 2.노말 서피스 생성 (서비스 서버)-메시지 큐와 핸들러 생성 sp<ISurface> Client::createSurface(ISurfaceComposerClient::surface_data_t* params, const String8& name, DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { sp<MessageBase> msg = new MessageCreateSurface(mFlinger.get(),params, name, this, display, w, h, format, flags); 메시지 큐와 핸들러 생성 mFlinger->postMessageSync(msg);  생성된 메시지를 서피스 플링거 서비스에게 전달(동기식) return static_cast<MessageCreateSurface*>( msg.get() )->getResult(); } status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime, uint32_t flags) { status_t res = mEventQueue.postMessage(msg, reltime); 생성된 메시지를 메시지 큐로 보냄. 이 메시지는 서피스 플링거 서비스의 네이티브 루퍼에서 처리 됨. msg->wait(); 메시지의 핸들러가 수행이 완료 될 때 까지 기다림. } 11
  • 12. 2.노말 서피스 생성 (서비스 서버)-메시지 큐와 핸들러 생성 MessageQueue.cpp status_t MessageQueue::postMessage(const sp<MessageBase>& messageHandler, nsecs_t relTime) { const Message dummyMessage; if (relTime > 0) { mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage); } else { mLooper->sendMessage(messageHandler, dummyMessage); 서피스 플링거 서비스 네이티브 루퍼에게 메시지 전달 } return NO_ERROR; } class MessageCreateSurface : public MessageBase { virtual bool handler() { result = flinger->createSurface(params, name, client, display, w, h, format, flags); 메시지 큐의 핸들러에서 서피스 플링거의 createSurface를 불러 줌. return true; } }; 12
  • 13. 2.노말 서피스 생성 (서비스 서버)-레이어 생성 sp<Layer> SurfaceFlinger::createNormalSurface(..) LayerBase(레이어 상태 변경 관리) { sp<Layer> layer = new Layer(this, display, client); this:Surfaceflinger 인스턴스, LayerBaseClient display:출력될 display의 번호, (클라이언트 리모트 서비스의 자원 관리 client:서피스 클라이언트 status_t err = layer->setBuffers(w, h, format, flags); 레이어 멥버 변수 초기 값 설정, 서피스 텍스처 기본 크기 결정. Layer Layer return layer;  생성된 레이어 반환 Layer Screenshot Dim } Layer class 생성 시 LayerBase의 생성자 부터 호출된다. Layerbase.cpp LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) : dpy(display), contentDirty(false), sequence(uint32_t(android_atomic_inc(&sSequence))), SurfaceFlinger  sSequence 값을 sequence에 저장하고 sSequence를 1증가 시킨다. 지역 레이어 목록  sequence 변수는 동일 Z-order 값을 가지는 레이어를 정렬할때 사용 함. 전역 레이어 목록 Client 1 { … zorder Token=1 mIdentity } Token=2 4 4 LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, 3 1 지역 레이어 목록 const sp<Client>& client) 2 2 : LayerBase(flinger, display), mClientRef(client), 1 3 Client 2 mIdentity(uint32_t(android_atomic_inc(&sIdentity))) 서피스 전역 식별자인 mIdentity의 값을 설정한다. Token=1 { Token=2 } 13
  • 14. 2.노말 서피스 생성 (서비스 서버)-레이어 생성 Layer::Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client) : LayerBaseClient(flinger, display, client), mTextureName,(텍스쳐 번호), … { glGenTextures(1, &mTextureName); 서피스 플링거 서비스는 하나의 레이어를 하나의 텍스쳐로 사용하여 합성함. 따라서, 각 레이어를 구별할 수 있는 인자가 필요한데, glGenTextures에서 mTextureName에 ID를 생성 함. } Layer Class는 RefBase를 상속했음으로, onFirstRef()가 불림.(BufferQueue 리모트 서비스 생성) void Layer::onFirstRef() { struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener { FrameQueuedListener(Layer* layer) : mLayer(layer) { } private: wp<Layer> mLayer; virtual void onFrameAvailable() { sp<Layer> that(mLayer.promote()); void Layer::onFrameQueued() { if (that != 0) { android_atomic_inc(&mQueuedFrames); that->onFrameQueued(); mFlinger->signalEvent(); } } } }; // Creates a custom BufferQueue for SurfaceTexture to use sp<BufferQueue> bq = new SurfaceTextureLayer();  SurfaceTextureLayer 객체를 생성 한다. SurfaceTextureLayer는 BufferQueue class를 상속 받고 있다. BufferQueue는 서피스 플링거와 어플리케이션 사이에서 그래픽 버퍼 공유 및 버퍼 획득,전달을 담당 함. mSurfaceTexture = new SurfaceTexture(mTextureName, true,GL_TEXTURE_EXTERNAL_OES, false, bq); SurfaceTexture 생성 시 BufferQueue 의 포인터를 인자로 생성 함. (SurfaceTexture 에서 BufferQueue 를 이용해서 버퍼 획득,전달을 하겠다는 의미) mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this)); SurfaceTextureLayer의 listener를 FrameAvailableListener 로 등록 한다. 14
  • 15. 2.노말 서피스 생성 (서비스 서버)-레이어 생성 mSurfaceTexture->setSynchronousMode(true); 버퍼 출력 모드를 동기식으로 설정 함. Cf. 동기 모드: 애플리케이션이 출력 요청 한 순서대로 서피스 플링거가 합성하여 화면에 출력 비동기 모드:애플리케이션이 여러 번 출력 요청을 하더라도, 서피스 플링거 서비스는 가장 마지막에 출력 요청된 그래픽 버퍼만 화면에 출력 함. mSurfaceTexture->setBufferCountServer(3); 트리플 버퍼 설정. } 15
  • 16. 2.노말 서피스 생성 (서비스 서버)-BufferQueue 리모트 서비스 생성 ▶ 서피스 전달,획득 출력 요청등에 대한 모든 과정은 애플리케이션 측의 SurfaceTextureClient와 서버측의 BufferQueue 가 담당한다. ▶ BufferQueue 는 레이어 생성 시 생성 됨. BufferQueue::BufferQueue( bool allowSynchronousMode, int bufferCount ) : mDefaultWidth(1),  생성될 버퍼의 width mDefaultHeight(1), 생성될 버퍼의 Height mPixelFormat(PIXEL_FORMAT_RGBA_8888), 버퍼의 핏셀 포맷 … mBufferCount(mMinAsyncBufferSlots), 클라이언트와 서버 간에 동시에 유지하고 있는 버퍼 슬롯의 수 mClientBufferCount(0), 클라이언트에서 요청한 버퍼 슬롯의 수 mServerBufferCount(mMinAsyncBufferSlots),  서버 측에서 요청한 버퍼 슬롯의 수 mSynchronousMode(false), 버퍼 출력 모드 (true:동기식, false:비동기식) … { sp<ISurfaceComposer> composer(ComposerService::getComposerService()); mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); 서피스 플링거 서비스에게 GraphicBufferAlloc 리모트 서비스의 생성을 요청 하고, IGraphicBufferAlloc 서비스 프록시를 획득한다. } Surfaceflinger.cpp sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc() { sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc()); return gba; }  BufferQueue의 그래픽 버퍼 할당은 GraphicBufferAlloc를 통해서만 이루어짐. 16
  • 17. 2.노말 서피스 생성 (서비스 서버)-서피스 텍스처 생성 ▶ 서피스 플링거 서비스가 서피스를 텍스처로 다룰 수 있도록 도움을 주는 class이다. SurfaceTexture.cpp SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode, GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) : … { if (bufferQueue == 0) { mBufferQueue = new BufferQueue(allowSynchronousMode); 어플리케이션(서비스 클라이언트) 측에서 SurfaceTexture를 생성하는 경우 여기서 BufferQueue 가 생성 됨. } else { mBufferQueue = bufferQueue; } … listener = static_cast<BufferQueue::ConsumerListener*>(this);  SurfaceTexture는 BufferQueue::ConsumerListener를 상속 받는다. BufferQueue::ConsumerListener는 그래픽 버퍼가 추가(onFrameAvailable) 되거나, 해제 될때 (onBuffersReleased) 불려지는 함수의 interface이다. proxy = new BufferQueue::ProxyConsumerListener(listener);  BufferQueue::ProxyConsumerListener를 생성 한다. status_t err = mBufferQueue->consumerConnect(proxy);  생성한 BufferQueue::ProxyConsumerListener를 BufferQueue의 이벤트 리스너로 등록한다. 이 의미는 BufferQueue::ProxyConsumerListener::onFrameAvailable() -> BufferQueue::ConsumerListener의 onFrameAvailable -> SurfaceTexture::onFrameAvailable() -> virtual void onFrameAvailable()(Layer.cpp) -> mFlinger->signalEvent(); 로 호출된다. 17
  • 18. 2.노말 서피스 생성 (서비스 서버)-노말 레이어 초기화 2.생성된 layer 상태 초기화 layer->initStates(w, h, flags); Layerbase class의 initStates 가 호출됨. void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags) { mCurrentState.z = 0; mCurrentState.w = w; mCurrentState.h = h; mCurrentState.requested_w = w; mCurrentState.requested_h = h; mCurrentState.sequence = 0; sequence 값은 드로잉 프레임에서의 레이어와 현재 프레임의 레이어 상태가 변경될 때 1씩 증가 mDrawingState = mCurrentState;  mDrawingState (화면에 출력중인 레이어의 상태 저장)과 mCurrentState(화면 출력을 위해 합성중인 레이어의 상태 저장)를 동일하게 설정 } 3.전역 레이어 목록과 지역 레이어 목록에 추가 ssize_t token = addClientLayer(client, layer); SurfaceFlinger 1.전역 레이어 목록 -서피스 플링거 서비스에서 생성된 전체 레이어 목록 지역 레이어 목록 -정렬 순서:zorder 순서 전역 레이어 목록 - mCurrentState.layersSortedByZ 변수로 관리 Client 1 layersSortedByZ 2.지역 레이어 목록 mLayers zorder mIdentity -특정 Client에서 생성된 레이어 목록 Token=1 4 4 -지역 레이어 목록의 레이어는 전역 레이어 목록에 3 1 Token=2 추가됨. -Client class의 mLayers 변수로 관리 18
  • 19. 2.노말 서피스 생성 (서비스 서버)-노말 레이어 초기화 ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<LayerBaseClient>& lbc) { // 지역 레이어 목록에 추가 size_t name = client->attachLayer(lbc); // 전역 레이어 목록에 추가 addLayer_l(lbc); return ssize_t(name); } size_t Client::attachLayer(const sp<LayerBaseClient>& layer) { size_t name = mNameGenerator++; mLayers.add(name, layer); return name; } status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer) { ssize_t i = mCurrentState.layersSortedByZ.add(layer); return (i < 0) ? status_t(i) : status_t(NO_ERROR); } 19
  • 20. 2.노말 서피스 생성 (서비스 서버)-리모트 서비스 생성 후 반환 4. Isurfacetexture 서비스 프락시를 획득하기 위한 함수를 제공하는 서피스 핸들 리모트 서비스(Bsurface) 생성 후 반환한다. surfaceHandle = layer->getSurface(); Layerbase.cpp의 getSurface가 호출 됨. sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() { sp<Surface> s; Mutex::Autolock _l(mLock); s = mClientSurface.promote(); if (s == 0) { s = createSurface(); mClientSurface = s; } return s; Layer.cpp의 오버라이딩 된 createSurface를 부른다. } class BSurface : public BnSurface, public LayerCleaner { wp<const Layer> mOwner; Layer.cpp virtual sp<ISurfaceTexture> getSurfaceTexture() const { sp<ISurface> Layer::createSurface() sp<ISurfaceTexture> res; { sp<const Layer> that( mOwner.promote() ); sp<ISurface> sur(new BSurface(mFlinger, this)); if (that != NULL) { return sur; res = that->mSurfaceTexture->getBufferQueue;  Isurfacetexture 서비스 프락시를 획득하기 위한 res는 BufferQueue의 sp를 가리킴. BSurface class를 생성하고 Bsurface의 proxy인 } return res; Isurface를 return한다. } 서피스 핸들을 반환 받은 서비스 클라이언트에서는 public: getSurfaceTexture() 로 BufferQueue에 BSurface(const sp<SurfaceFlinger>& flinger, 접근할 수 있다. const sp<Layer>& layer) } : LayerCleaner(flinger, layer), mOwner(layer) { } };
  • 21. 3.SurfaceTextureClient 생성(서비스 클라이언트) ISurface Proxy를 가진 SurfaceControl class의 getSurface함수를 통하여 ISurfaceTexture 서비스 proxy를 얻을 수 있다. ISurfaceTexture 는 BufferQueue와 연결 되어 있어 서피스의 그래픽 버퍼 생성,요청,출력등을 제공 한다. Android_view_Surface.cpp static sp<Surface> getSurface(JNIEnv* env, jobject clazz) { result = control->getSurface(); } Surface.cpp sp<Surface> SurfaceControl::getSurface() const { if (mSurfaceData == 0) { sp<SurfaceControl> surface_control(const_cast<SurfaceControl*>(this)); mSurfaceData = new Surface(surface_control); SurfaceTextureClient 클래스를 상속 받은 Surface class를 생성 한다. } return mSurfaceData;  Surface class의 주요 함수 } 함수 명 설명 isValid() Surface 생성시 초기화가 정상적으로 이루어 졌는지 check getIdentity() 해당 서피스의 전역 식별자를 획득한다. Lock() 그래픽 버퍼의 가상 주소를 획득한다. Unlockandpost() 서피스 플링거 서비스에게 출력을 요청한다. getSurfaceTexture() 서피스 텍스쳐 리모트 서비스의 서비스 프락시(ISurfaceTexture)를 획득한다.
  • 22. 3.SurfaceTextureClient 생성(서비스 클라이언트) Surface::Surface(const sp<SurfaceControl>& surface) SurfaceTextureClient::SurfaceTextureClient() { : SurfaceTextureClient()  SurfaceTextureClient 의 생성자 호출 SurfaceTextureClient::init(); mSurface(surface->mSurface), } mIdentity(surface->mIdentity) {  ANativeWindow 함수 포인터에 sp<ISurfaceTexture> st; SurfaceTextureClient 함수를 할당 함. if (mSurface != NULL) { void SurfaceTextureClient::init() { st = mSurface->getSurfaceTexture(); ANativeWindow::dequeueBuffer ISurfaceTexture proxy를 획득한다. = hook_dequeueBuffer; (SurfaceTexture는 BufferQueue를 가지고 있다.) ANativeWindow::cancelBuffer } = hook_cancelBuffer; init(st); ANativeWindow::lockBuffer } = hook_lockBuffer; ANativeWindow::queueBuffer = hook_queueBuffer; } void Surface::init(const sp<ISurfaceTexture>& surfaceTexture) { if (mSurface != NULL || surfaceTexture != NULL) { if (surfaceTexture != NULL) { setISurfaceTexture(surfaceTexture); setUsage(GraphicBuffer::USAGE_HW_RENDER);그래픽 버퍼의 속성값을 지정 함.  USAGE_HW_RENDER:그래픽 버퍼를 openGLES의 렌더링 대상으로 사용한다는 의미 } } void SurfaceTextureClient::setISurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture) { mSurfaceTexture = surfaceTexture; }
  • 23. 3.서피스 생성 요청 전체 그림 Client SurfaceFlinger Client BSurface surfacecomposerclient Layer ISurfaceTexture BufferQueue surfacecontrol Surfacetexturelayer ANativeWindow Refbase surfacetextureclient surfacetexture surface 23
  • 24. 참고.ANativeWindow 인터페이스 애플리케이션과 서피스 플링거는 ANativeWindow 인터페이스를 통해 그래픽 버퍼와 네이티브 버퍼를 획득 또는 출력한다. 차이점은, 애플리케이션은 출력대상이 그래픽 버퍼이고, 서피스 플링거는 네이티브 버퍼 이다. 24
  • 25. 참고.ANativeWindow 인터페이스  애플리케이션 측- SurfaceTextureClient 이용 1)애플리케이션은 SurfaceTextureclient 를 이용하여 그래픽 버퍼를 획득하고 출력한다. 2) SurfaceTextureclient 는 ANativeWidnow interface를 상속 받는다. 3) ANativeWidnow interface에 SurfaceTextureclient 함수 포인터를 매핑한다. 이 말은, 애플리케이션이 ANativeWidnow interface를 이용하여 버퍼를 할당 받고자 할때 실제 불리는 함수는 SurfaceTextureclient 에 있는 함수가 불리게 된다. 서피스 플링거의 경우는 FramebufferNativewindow의 함수를 부르게 된다. 4)Surfacetexture class는 클라이언트로 부터 그래픽 버퍼 요청이 오면 사용 가능한 버퍼를 검색하여 인덱스 번호를 전달하고, 출력 요청이 오면 출력 대기 큐(mQueue)에 저장한다.  서피스 플링거 서비스 측- FramebufferNativewindow 사용 5)합성 요청 signal(Vsync)를 받으면 합성을 시작하게 된다. 6)서피스 플링거 서비스는 FramebufferNativewindow 를 사용하여 네이티브 버퍼를 획득하고, 출력 요청한다. 7) FramebufferNativewindow 클래스의 함수가 ANativeWidnow interface 에 매핑된다. FramebufferNativewindow의 출력 대상은 프레임 버퍼이다. 8)버퍼 할당 요청이 오면 프레임 버퍼를 전달하고 출력 요청이 오면 디스플레이에 출력 요청을 한다. 25
  • 26. 참고자료  안드로이드 미디어 프레임워크 –”개발자가 행복한 세상”  Goolge Jelly bean Source 26