android-匿名binder
7610 ワード
前の記事「android-binderプロセス間通信プロセス分析」では、サービスは一般的にサービスマネージャに登録してから使用する必要があると分析しています.匿名binderはサービスマネージャに登録されていないサービスであり、登録されていない以上、カーネルには対応するbinder_がありません.nodeとbinder_ref構造ですが、どうやって使いますか?以下、
上の
定義から見ると、
主なコードは
BufferQueue
のmGraphicBufferAlloc
オブジェクトの生成を例に挙げる.BufferQueue::BufferQueue(const sp<IGraphicBufferAlloc>& allocator) :
mDefaultWidth(1),
mDefaultHeight(1),
mMaxAcquiredBufferCount(1),
mDefaultMaxBufferCount(2),
mOverrideMaxBufferCount(0),
mConsumerControlledByApp(false),
mDequeueBufferCannotBlock(false),
mUseAsyncBuffer(true),
mConnectedApi(NO_CONNECTED_API),
mAbandoned(false),
mFrameCounter(0),
mBufferHasBeenQueued(false),
mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
mConsumerUsageBits(0),
mTransformHint(0)
{
// Choose a name using the PID and a process-unique ID.
mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
ST_LOGV("BufferQueue");
if (allocator == NULL) {
//① BpSurfaceComposer
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
//② mGraphicBufferAlloc
mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
if (mGraphicBufferAlloc == 0) {
ST_LOGE("createGraphicBufferAlloc() failed in BufferQueue()");
}
} else {
mGraphicBufferAlloc = allocator;
}
}
上の
BufferQueue
のコンストラクション関数では、まず1でBpSurfaceComposerを取得し、前に説明があり、展開しません.②はmGraphicBufferAllocを取得し、以下で詳細に分析する.sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
定義から見ると、
mGraphicBufferAlloc
はGraphicBufferAlloc
サービスのエージェントオブジェクトであるべきであるが、GraphicBufferAlloc
はサービスマネージャに登録されていない.BpSurfaceComposer
のcreateGraphicBufferAlloc()
関数を見てみましょう. virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
{
uint32_t n;
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply);
// reply , readStrongBinder
return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder());
}
主なコードは
interface_cast(reply.readStrongBinder());
であり、reply.readStrongBinder()
からBpBinder(handle)が返され、interface_cast
を介してBpGraphicBufferAlloc
オブジェクトに変換される.では、このbinderオブジェクトはどのようにserver、すなわちsurface flingerから伝わったのでしょうか.次にserverエンドコードを見て、status_t BnSurfaceComposer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
case CREATE_GRAPHIC_BUFFER_ALLOC: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
// surface flinger createGraphicBufferAlloc
//GraphicBufferAlloc BnInterface
sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
// binder
reply->writeStrongBinder(b);
return NO_ERROR;
}
}
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
{
// GraphicBufferAlloc
//class GraphicBufferAlloc : public BnGraphicBufferAlloc
sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
return gba;
}
GraphicBufferAlloc
クラスはBnInterface
から継承され、ここではBnInterface
のonAsBinder()
を呼び出すので、GraphicBufferAlloc
newから出たポインタが返されます.template<typename INTERFACE>
IBinder* BnInterface::onAsBinder()
{
return this;
}
reply->writeStrongBinder(b);
を呼び出して、GraphicBufferAlloc
オブジェクトをカーネルに転送します.これは前述したとおりです.binderエンティティGraphicBufferAlloc
オブジェクトをカーネルに転送すると、カーネルはエンティティに対応するプロセスのbinder_になります.Proc、すなわちsurface flingerでは、エンティティに対応するbinder_を作成します.Nodeは、ターゲットプロセス、すなわちBufferQueueが存在するプロセスにbinder_を作成します.refは前のbinder_を指すNodeは、BufferQueueが存在するプロセスにhandleを返します.これはbinderの伝達プロセスを通じています.上の分析から、以下の結論を得た:1サービスはサービスマネージャに登録してから使用しなければならないわけではない.②匿名binderは実名binderの上に構築されなければならない.実名binderはservice managerに登録されている.まずclientとserverは実名binderを通じて連絡を確立し、匿名binderをこの実名チャネルを通じて「伝達」し、相手もserviceのエージェントBpxxxを正しく取得することができる.③なぜ匿名binderが必要なのか?Android graphicシステムでは、1つのLayerが1つのBufferQueueに対応するため、1つのアプリケーションに複数のBufferQueueがある可能性があります.BufferQueueが構築されると、surface flingerプロセスでnew GraphicBufferAlloc()が作成されるので、1つのアプリケーションはsurface flingerプロセスで複数のGraphicBufferAllocオブジェクトを作成します.匿名Binderは一般的にこのシナリオで発生していると思います.serviceには複数のエンティティがあり、使用する必要がある場合はBinderエンティティを現場で作成します.一般的な実名Binder、すなわちサービスマネージャに登録されているサービスには、サービスエンティティが1つしかありません.つまり、newは1回しかありません.