概要
SurfaceControlは、その名前が示すように、Surfaceのコントロールマネージャです。Surfaceは、アプリケーション層のユーザーがUIを描画するための描画面であり、ウィンドウオブジェクトWindowStateを管理するWindowManagerServiceによって作成されます。Windowは抽象概念であり、設計レベルで使用されるクラスに属しますが、Surfaceは実際には実装上のウィンドウエンティティです。そのため、WMSがレイヤースタック、Zオーダー、サイズ、位置などを変更した場合、SurfaceFlingerにSurfaceControlを通して通知し、SurfaceFlingerが合成レンダリングのためにSFのレイヤーを更新する必要があります。このレイヤーはアプリケーション・レイヤーが使用するサーフェスに対応しています。この記事では、SuraceControlを使用してこれらのプロパティを更新するプロセスを見ていきます。
SurfaceControl
public int relayoutWindow(Session session, IWindow client, int seq,
 WindowManager.LayoutParams attrs, int requestedWidth,
 int requestedHeight, int viewVisibility, int flags,
 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
 ....
 try {
 if (!win.mHasSurface) {
 surfaceChanged = true;
 }
 //SurfaceControl を作成し、キャンバスを準備する。
 SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
 if (surfaceControl != null) {
 outSurface.copyFrom(surfaceControl);//SurfaceSurfaceControl より
 if (SHOW_TRANSACTIONS) Slog.i(TAG,
 " OUT SURFACE " + outSurface + ": copied");
 } else {
 // For some reason there isn't a surface. Clear the
 // caller's object so they see the same state.
 outSurface.release();
 }
 } catch (Exception e) {}
 ....
}
SurfaceControl createSurfaceLocked() {
 ....
 //SurfaceControl を作成する
 mSurfaceControl = new SurfaceControl(
 mSession.mSurfaceSession,
 attrs.getTitle().toString(),
 w, h, format, flags);
 ....
 //ここでは、SurfaceControl のトランザクションを使用して、Surface の設定を送信する。
 SurfaceControl.openTransaction();
 try {
 try {
 mSurfaceX = mWin.mFrame.left + mWin.mXOffset;
 mSurfaceY = mWin.mFrame.top + mWin.mYOffset;
 mSurfaceControl.setPosition(mSurfaceX, mSurfaceY);//位置を設定する
 mSurfaceLayer = mAnimLayer;
 mSurfaceControl.setLayerStack(mLayerStack);//レイヤースタックを設定する
 mSurfaceControl.setLayer(mAnimLayer);//Z オーダーの設定
 mSurfaceControl.setAlpha(0);//透明度 0 を設定する?
 mSurfaceShown = false;
 } catch (RuntimeException e) {
 Slog.w(TAG, "Error creating surface in " + w, e);
 mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true);
 }
 mLastHidden = true;
 } finally {
 SurfaceControl.closeTransaction();
 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
 "<<< CLOSE TRANSACTION createSurfaceLocked");
 }
 ...
}
プロパティ設定とトランザクションコミット
以下は、これら2つのメソッドがプロパティ設定とトランザクション・コミットをどのように実行するかを具体的に分析したものです。
public class SurfaceControl {
 /** start a transaction */
 public static void openTransaction() {
 nativeOpenTransaction();
 }
 /** end a transaction */
 public static void closeTransaction() {
 nativeCloseTransaction();
 }
 public void setLayer(int zorder) {
 checkNotReleased();
 nativeSetLayer(mNativeObject, zorder);
 }
}
ここでZ-orderプロパティの設定を見てみると、プロパティの設定と送信はJNIレイヤを通して1ステップで処理され、android_view_SurfaceControl.cppのJNI実装に移ります。
static void nativeSetLayer(JNIEnv* env, jclass clazz, jint nativeObject, jint zorder) {
 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
 status_t err = ctrl->setLayer(zorder);
 if (err < 0 && err != NO_INIT) {
 doThrowIAE(env);
 }
}
//トランザクションを有効にする
static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
 SurfaceComposerClient::openGlobalTransaction();
}
//トランザクションを送信する
static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
 SurfaceComposerClient::closeGlobalTransaction();
}
SurfaceControlのネイティブ層を介して属性設定を設定するには、サブミットは、実際にSurfaceComposerClientによって処理され、Surfaceの作成プロセスの導入では、それが実際にWMSのクライアントのバインダエージェントのクライアント側のクライアントがSurfaceSessionセッションを作成するアプリケーションもSurfaceSessionを構築します。セッションセッションもSurfaceSessionを構築しますが、このSurfaceSessionは実は実施形態の上位レイヤーにあるSurfaceComposerClientです。
プロパティ設定
最初にプロパティを設定する方法は次のとおりです。
SurfaceControl::SurfaceControl(
 const sp<SurfaceComposerClient>& client,
 const sp<IBinder>& handle,
 const sp<IGraphicBufferProducer>& gbp)
 : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
{
}
status_t SurfaceControl::setLayer(int32_t layer) {
 status_t err = validate();
 if (err < 0) return err;
 const sp<SurfaceComposerClient>& client(mClient);
 return client->setLayer(mHandle, layer);
}
SurfaceComposerClient::SurfaceComposerClient()
 : mStatus(NO_INIT), mComposer(Composer::getInstance())
{
}
inline Composer& SurfaceComposerClient::getComposer() {
 return mComposer;
}
status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, int32_t z) {
 return getComposer().setLayer(this, id, z);
}
SurfaceComposerClient オブジェクトを作成すると、シングルトンである mComposer Composer オブジェクトも作成されます。
class Composer : public Singleton<Composer>
{
 friend class Singleton<Composer>;
 mutable Mutex mLock;
 SortedVector<ComposerState> mComposerStates;
 SortedVector<DisplayState > mDisplayStates;
 uint32_t mForceSynchronous;
 uint32_t mTransactionNestCount;
 bool mAnimation;
 Composer() : Singleton<Composer>(),
 mForceSynchronous(0), mTransactionNestCount(0),
 mAnimation(false)
 { }
 void openGlobalTransactionImpl();
 void closeGlobalTransactionImpl(bool synchronous);
 void setAnimationTransactionImpl();
 layer_state_t* getLayerStateLocked(
 const sp<SurfaceComposerClient>& client, const sp<IBinder>& id);
 DisplayState& getDisplayStateLocked(const sp<IBinder>& token);
public:
 ...
 status_t setPosition(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
 float x, float y);
 status_t setSize(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
 uint32_t w, uint32_t h);
 status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
 int32_t z);
 status_t setLayerStack(const sp<SurfaceComposerClient>& client,
 const sp<IBinder>& id, uint32_t layerStack);
 ...
 static void setAnimationTransaction() {
 Composer::getInstance().setAnimationTransactionImpl();
 }
 static void openGlobalTransaction() {
 Composer::getInstance().openGlobalTransactionImpl();
 }
 static void closeGlobalTransaction(bool synchronous) {
 Composer::getInstance().closeGlobalTransactionImpl(synchronous);
 }
};
コンポーザーの定義は、アトリビュートの設定と提出が最終的にコンポーザーを通して行われることを示しています。最初に
status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
 const sp<IBinder>& id, int32_t z) {
 Mutex::Autolock _l(mLock);
 layer_state_t* s = getLayerStateLocked(client, id);
 if (!s)
 return BAD_INDEX;
 s->what |= layer_state_t::eLayerChanged;
 s->z = z;
 return NO_ERROR;
}
layer_state_t* Composer::getLayerStateLocked(
 const sp<SurfaceComposerClient>& client, const sp<IBinder>& id) {
 ComposerState s;
 s.client = client->mClient;
 s.state.surface = id;
 ssize_t index = mComposerStates.indexOf(s);
 if (index < 0) {
 // we don't have it, add an initialized layer_state to our list
 index = mComposerStates.add(s);
 }
 ComposerState* const out = mComposerStates.editArray();
 return &(out[index].state);
}
属性トランザクションの提出
void SurfaceComposerClient::openGlobalTransaction() {
 Composer::openGlobalTransaction();
}
void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) {
 Composer::closeGlobalTransaction(synchronous);
}
static void openGlobalTransaction() {
 Composer::getInstance().openGlobalTransactionImpl();
}
static void closeGlobalTransaction(bool synchronous) {
 Composer::getInstance().closeGlobalTransactionImpl(synchronous);
}
実際にはComposerのスタティック・メソッドを使用して内部的に実装されており、Composerのクラス定義にあるように、これら2つのスタティック・メソッドの実装は、実際にはSurfaceComposerClient用に作成されたシングルトンmComposerを使用して動作します。
void Composer::openGlobalTransactionImpl() {
 { // scope for the lock
 Mutex::Autolock _l(mLock);
 mTransactionNestCount += 1;
 }
}
void Composer::closeGlobalTransactionImpl(bool synchronous) {
 sp<ISurfaceComposer> sm(ComposerService::getComposerService());
 Vector<ComposerState> transaction;
 Vector<DisplayState> displayTransaction;
 uint32_t flags = 0;
 { // scope for the lock
 Mutex::Autolock _l(mLock);
 mForceSynchronous |= synchronous;
 if (!mTransactionNestCount) {
 ALOGW("At least one call to closeGlobalTransaction() was not matched by a prior "
 "call to openGlobalTransaction().");
 } else if (--mTransactionNestCount) {
 return;
 }
 transaction = mComposerStates;
 mComposerStates.clear();
 displayTransaction = mDisplayStates;
 mDisplayStates.clear();
 if (mForceSynchronous) {
 flags |= ISurfaceComposer::eSynchronous;
 }
 if (mAnimation) {
 flags |= ISurfaceComposer::eAnimation;
 }
 mForceSynchronous = false;
 mAnimation = false;
 }
 sm->setTransactionState(transaction, displayTransaction, flags);
}
void SurfaceFlinger::setTransactionState(
 const Vector<ComposerState>& state,
 const Vector<DisplayState>& displays,
 uint32_t flags)
{
 ATRACE_CALL();
 Mutex::Autolock _l(mStateLock);
 uint32_t transactionFlags = 0;
 ...
 size_t count = displays.size();
 for (size_t i=0 ; i<count ; i++) {
 const DisplayState& s(displays[i]);
 transactionFlags |= setDisplayStateLocked(s);
 }
 count = state.size();
 for (size_t i=0 ; i<count ; i++) {
 const ComposerState& s(state[i]);
 // Here we need to check that the interface we're given is indeed
 // one of our own. A malicious client could give us a NULL
 // IInterface, or one of its own or even one of our own but a
 // different type. All these situations would cause us to crash.
 //
 // NOTE: it would be better to use RTTI as we could directly check
 // that we have a Client*. however, RTTI is disabled in Android.
 if (s.client != NULL) {
 sp<IBinder> binder = s.client->asBinder();
 if (binder != NULL) {
 String16 desc(binder->getInterfaceDescriptor());
 if (desc == ISurfaceComposerClient::descriptor) {
 sp<Client> client( static_cast<Client *>(s.client.get()) );
 transactionFlags |= setClientStateLocked(client, s.state);
 }
 }
 }
 }
 if (transactionFlags) {
 // this triggers the transaction
 setTransactionFlags(transactionFlags);
 ...
 }
}
uint32_t SurfaceFlinger::setClientStateLocked(
 const sp<Client>& client,
 const layer_state_t& s)
{
 uint32_t flags = 0;
 sp<Layer> layer(client->getLayerUser(s.surface));
 if (layer != 0) {
 const uint32_t what = s.what;
 if (what & layer_state_t::ePositionChanged) {
 if (layer->setPosition(s.x, s.y))
 flags |= eTraversalNeeded;
 }
 if (what & layer_state_t::eLayerChanged) {
 // NOTE: index needs to be calculated before we update the state
 ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
 if (layer->setLayer(s.z)) {
 mCurrentState.layersSortedByZ.removeAt(idx);
 mCurrentState.layersSortedByZ.add(layer);
 // we need traversal (state changed)
 // AND transaction (list changed)
 flags |= eTransactionNeeded|eTraversalNeeded;
 }
 }
 if (what & layer_state_t::eSizeChanged) {
 if (layer->setSize(s.w, s.h)) {
 flags |= eTraversalNeeded;
 }
 }
 if (what & layer_state_t::eAlphaChanged) {
 if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
 flags |= eTraversalNeeded;
 }
 if (what & layer_state_t::eMatrixChanged) {
 if (layer->setMatrix(s.matrix))
 flags |= eTraversalNeeded;
 }
 if (what & layer_state_t::eTransparentRegionChanged) {
 if (layer->setTransparentRegionHint(s.transparentRegion))
 flags |= eTraversalNeeded;
 }
 if (what & layer_state_t::eVisibilityChanged) {
 if (layer->setFlags(s.flags, s.mask))
 flags |= eTraversalNeeded;
 }
 if (what & layer_state_t::eCropChanged) {
 if (layer->setCrop(s.crop))
 flags |= eTraversalNeeded;
 }
 if (what & layer_state_t::eLayerStackChanged) {
 // NOTE: index needs to be calculated before we update the state
 ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
 if (layer->setLayerStack(s.layerStack)) {
 mCurrentState.layersSortedByZ.removeAt(idx);
 mCurrentState.layersSortedByZ.add(layer);
 // we need traversal (state changed)
 // AND transaction (list changed)
 flags |= eTransactionNeeded|eTraversalNeeded;
 }
 }
 }
 return flags;
}
SFでレイヤーの属性を設定した後、レイヤーの属性を変更するようにSFに通知する必要があります。これは、実際には、アプリケーションのインターフェイスを更新するために、SFに複合レンダリング操作を実行させるためであり、これはsetTransactionFlagsによって実行されます。
uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {
 uint32_t old = android_atomic_or(flags, &mTransactionFlags);
 if ((old & flags)==0) { // wake the server up
 signalTransaction();
 }
 return old;
}
void SurfaceFlinger::signalTransaction() {
 mEventQueue.invalidate();
}
void SurfaceFlinger::onMessageReceived(int32_t what) {//MessageQueueこれは setTransactionFlags によって行われる。 このメッセージは実際には SF によって処理される。
 ATRACE_CALL();
 if(mDelayFlag) {
 usleep(20000);
 mDelayFlag = 0;
 }
 switch (what) {
		//スクリーンとアプリケーションウィンドウの変更を処理する。これらの変更は、レイヤーの可視領域を変更する可能性が高く、ダーティ領域の計算に影響する。
		case MessageQueue::TRANSACTION:
			handleMessageTransaction();
			break;
		//これは setTransactionFlags を通して行われ、レイヤーまたはディスプレイの属性の変更と、レイヤーの対応するバッファーの更新を処理するために使用される。
		case MessageQueue::INVALIDATE:
			handleMessageTransaction();//画面とアプリケーションウィンドウの変更を処理する。これらの変更は、レイヤーの可視領域を変更する可能性が高く、ダーティ領域の計算に影響する。
			handleMessageInvalidate();//これは、setTransactionFlagsによって行われる。 主な目的は、各レイヤーに対応するBufferQueueからグラフィックバッファデータを取得し、その内容に応じてダーティエリアを更新することである。
			signalRefresh();//リフレッシュする
			break;
		/**
		 * これは、setTransactionFlagsによって行われる。setTransactionFlagsは、SurfaceFlingerが合成操作を行う必要があることを示す。:
		 * 1) Layer属性の変更はウィンドウの状態を変更する。;
			 2) Layer新しいバッファが届く;
			 3) HWC再描画を要求する。
		*/
		case MessageQueue::REFRESH:
			handleMessageRefresh();//出力をマージしてレンダリングする
			break;
 }
}





