Android6.0 SurfaceControl分析(二)SurfaceControlとSurfaceFlinger通信
20742 ワード
前のブログでは、SurfaceControlがopenTransactionとcloseTransactionを呼び出し、すべてのSurfaceControlのプロパティなどをSurfaceFlingerに伝えると述べています.この過程を見てみましょう.
まず、このプログラムを見てみましょう.JAvaの関連関数は、JNI関数が呼び出されます.
androidを見てみましょうview_SurfaceControl.cppの下にあるいくつかのJNI関数は、nativeOpenTransactionとnativeCloseTransactionがSurfaceComposerClientを呼び出した静的関数であり、その他はc層を呼び出したSurfaceControlの関数である.
SurfaceComposerClientの相関関数は、layerの状態とdisplayの状態の2つに分類されます.
次にlayerの状態を見てみましょう.getLayerStateLockedで関連layerの状態をクエリーし、なければmComposerStatesに追加する関数があります.次はComposerStateの構造体です.
前と同様にdisplay関連関数を設定します.いずれもgetDisplayStateLocked関数を呼び出して関連するdisplayステータスを取得し、mDisplayStatesに参加しない場合です.
DisplayStateの構造体は次のとおりです.
各相関設定displayの関数は、getDisplayStateLocked関数を呼び出して相関displayステータスを取得し、mDisplayStatesに追加されていない場合は取得します.
次のopenGlobalTransactionImpl関数を見て、鍵をかけてmTransactionNestCountを直接1に追加し、closeGlobalTransactionImpl関数でmTransactionNestCountの値が1であるかどうかを確認します.1より大きい場合は、直接終了します.これはopenGlobalTransactionとcloseGlobalTransactionを複数の場所で呼び出した場合、SurfaceFlingerと通信するのは最後の1回だけです.最後にmComposerStatesとmDisplayStatesをSurfaceFlingerのsetTransactionStateメソッドを呼び出してSurfaceFlingerに転送する.
SurfaceFlingerではsetTransactionState関数で処理され、各DisplayState呼び出しsetDisplayStateLocked設定display状態、次にComposerStateを巡りsetClientStateLocked設定状態が呼び出されます.最後にsetTransactionFlags関数が呼び出され、最後にINVALLIDATEメッセージが送信されます.このメッセージの処理は前のブログで分析されました.
setDisplayStateLocked関数は、mCurrentStateからDisplayStateを取得し、いくつかの変数を設定します.
setClientStateLockedはlayerを取得し、いくつかのlayerのプロパティを設定し、最後にmCurrentStateを再読み込みます.LayersSortedByZにあります.
これらの関数はブログでhttp://blog.csdn.net/kc58236582/article/details/52778333では、各layerのonFrameAvailableでは最後にsignalLayerUpdate関数が呼び出され、最後にINVALidateメッセージが送信されます.このメッセージの処理については,このブログで分析したが,各layer属性,displayを更新する.
Surfaceについては、以前にSurfaceでmGraphicBufferProducerのdequeueBuffer関数を呼び出してから、mGraphicBufferProducerのqueueBuffer関数を呼び出すことを分析しました.これにより、Surface Flingerの各LayerのonFrameAvailable関数が実行され、各layerのデータが変化したことも統計されます.
一、Surface Control
まず、このプログラムを見てみましょう.JAvaの関連関数は、JNI関数が呼び出されます.
public static void openTransaction() {
nativeOpenTransaction();
}
/** end a transaction */
public static void closeTransaction() {
nativeCloseTransaction();
}
/** flag the transaction as an animation */
public static void setAnimationTransaction() {
nativeSetAnimationTransaction();
}
public void setLayer(int zorder) {
checkNotReleased();
nativeSetLayer(mNativeObject, zorder);
}
androidを見てみましょうview_SurfaceControl.cppの下にあるいくつかのJNI関数は、nativeOpenTransactionとnativeCloseTransactionがSurfaceComposerClientを呼び出した静的関数であり、その他はc層を呼び出したSurfaceControlの関数である.
static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
SurfaceComposerClient::openGlobalTransaction();
}
static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
SurfaceComposerClient::closeGlobalTransaction();
}
static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
SurfaceComposerClient::setAnimationTransaction();
}
static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong nativeObject, jint zorder) {
SurfaceControl* const ctrl = reinterpret_cast(nativeObject);
status_t err = ctrl->setLayer(zorder);
if (err < 0 && err != NO_INIT) {
doThrowIAE(env);
}
}
static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat x, jfloat y) {
SurfaceControl* const ctrl = reinterpret_cast(nativeObject);
status_t err = ctrl->setPosition(x, y);
if (err < 0 && err != NO_INIT) {
doThrowIAE(env);
}
}
そしてSurface Control.cppの関数は,SurfaceComposerClientを呼び出した関連関数である.status_t SurfaceControl::setLayerStack(uint32_t layerStack) {
status_t err = validate();
if (err < 0) return err;
return mClient->setLayerStack(mHandle, layerStack);
}
status_t SurfaceControl::setLayer(uint32_t layer) {
status_t err = validate();
if (err < 0) return err;
return mClient->setLayer(mHandle, layer);
}
status_t SurfaceControl::setPosition(float x, float y) {
status_t err = validate();
if (err < 0) return err;
return mClient->setPosition(mHandle, x, y);
}
1.1 Surface Component設定関連関数
SurfaceComposerClientの相関関数は、layerの状態とdisplayの状態の2つに分類されます.
1.1.1 layer関連関数の設定
次にlayerの状態を見てみましょう.getLayerStateLockedで関連layerの状態をクエリーし、なければmComposerStatesに追加する関数があります.次はComposerStateの構造体です.
struct ComposerState {
sp client;
layer_state_t state;
status_t write(Parcel& output) const;
status_t read(const Parcel& input);
};
getLayerStateLocked関数は、mComposerStatesから関連layerを取得するstateです.layer_state_t* Composer::getLayerStateLocked(
const sp& client, const sp& 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);
}
status_t Composer::setPosition(const sp& client,
const sp& id, float x, float y) {
Mutex::Autolock _l(mLock);
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
return BAD_INDEX;
s->what |= layer_state_t::ePositionChanged;
s->x = x;
s->y = y;
return NO_ERROR;
}
status_t Composer::setSize(const sp& client,
const sp& id, uint32_t w, uint32_t h) {
Mutex::Autolock _l(mLock);
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
return BAD_INDEX;
s->what |= layer_state_t::eSizeChanged;
s->w = w;
s->h = h;
// Resizing a surface makes the transaction synchronous.
mForceSynchronous = true;
return NO_ERROR;
}
status_t Composer::setLayer(const sp& client,
const sp& id, uint32_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;
}
status_t Composer::setFlags(const sp& client,
const sp& id, uint32_t flags,
uint32_t mask) {
Mutex::Autolock _l(mLock);
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
return BAD_INDEX;
if (mask & layer_state_t::eLayerOpaque ||
mask & layer_state_t::eLayerHidden ||
mask & layer_state_t::eLayerSecure) {
s->what |= layer_state_t::eFlagsChanged;
}
s->flags &= ~mask;
s->flags |= (flags & mask);
s->mask |= mask;
return NO_ERROR;
}
status_t Composer::setTransparentRegionHint(
const sp& client, const sp& id,
const Region& transparentRegion) {
Mutex::Autolock _l(mLock);
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
return BAD_INDEX;
s->what |= layer_state_t::eTransparentRegionChanged;
s->transparentRegion = transparentRegion;
return NO_ERROR;
}
status_t Composer::setAlpha(const sp& client,
const sp& id, float alpha) {
Mutex::Autolock _l(mLock);
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
return BAD_INDEX;
s->what |= layer_state_t::eAlphaChanged;
s->alpha = alpha;
return NO_ERROR;
}
status_t Composer::setLayerStack(const sp& client,
const sp& id, uint32_t layerStack) {
Mutex::Autolock _l(mLock);
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
return BAD_INDEX;
s->what |= layer_state_t::eLayerStackChanged;
s->layerStack = layerStack;
return NO_ERROR;
}
status_t Composer::setMatrix(const sp& client,
const sp& id, float dsdx, float dtdx,
float dsdy, float dtdy) {
Mutex::Autolock _l(mLock);
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
return BAD_INDEX;
s->what |= layer_state_t::eMatrixChanged;
layer_state_t::matrix22_t matrix;
matrix.dsdx = dsdx;
matrix.dtdx = dtdx;
matrix.dsdy = dsdy;
matrix.dtdy = dtdy;
s->matrix = matrix;
return NO_ERROR;
}
status_t Composer::setCrop(const sp& client,
const sp& id, const Rect& crop) {
Mutex::Autolock _l(mLock);
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
return BAD_INDEX;
s->what |= layer_state_t::eCropChanged;
s->crop = crop;
return NO_ERROR;
}
1.1.2 display関連関数の設定
前と同様にdisplay関連関数を設定します.いずれもgetDisplayStateLocked関数を呼び出して関連するdisplayステータスを取得し、mDisplayStatesに参加しない場合です.
DisplayStateの構造体は次のとおりです.
struct DisplayState {
enum {
eOrientationDefault = 0,
eOrientation90 = 1,
eOrientation180 = 2,
eOrientation270 = 3,
eOrientationUnchanged = 4,
eOrientationSwapMask = 0x01
};
enum {
eSurfaceChanged = 0x01,
eLayerStackChanged = 0x02,
eDisplayProjectionChanged = 0x04,
eDisplaySizeChanged = 0x08
};
uint32_t what;
sp token;
sp surface;
uint32_t layerStack;
uint32_t orientation;
Rect viewport;
Rect frame;
uint32_t width, height;
status_t write(Parcel& output) const;
status_t read(const Parcel& input);
};
各相関設定displayの関数は、getDisplayStateLocked関数を呼び出して相関displayステータスを取得し、mDisplayStatesに追加されていない場合は取得します.
DisplayState& Composer::getDisplayStateLocked(const sp& token) {
DisplayState s;
s.token = token;
ssize_t index = mDisplayStates.indexOf(s);
if (index < 0) {
// we don't have it, add an initialized layer_state to our list
s.what = 0;
index = mDisplayStates.add(s);
}
return mDisplayStates.editItemAt(static_cast(index));
}
void Composer::setDisplaySurface(const sp& token,
const sp& bufferProducer) {
Mutex::Autolock _l(mLock);
DisplayState& s(getDisplayStateLocked(token));
s.surface = bufferProducer;
s.what |= DisplayState::eSurfaceChanged;
}
void Composer::setDisplayLayerStack(const sp& token,
uint32_t layerStack) {
Mutex::Autolock _l(mLock);
DisplayState& s(getDisplayStateLocked(token));
s.layerStack = layerStack;
s.what |= DisplayState::eLayerStackChanged;
}
void Composer::setDisplayProjection(const sp& token,
uint32_t orientation,
const Rect& layerStackRect,
const Rect& displayRect) {
Mutex::Autolock _l(mLock);
DisplayState& s(getDisplayStateLocked(token));
s.orientation = orientation;
s.viewport = layerStackRect;
s.frame = displayRect;
s.what |= DisplayState::eDisplayProjectionChanged;
mForceSynchronous = true; // TODO: do we actually still need this?
}
void Composer::setDisplaySize(const sp& token, uint32_t width, uint32_t height) {
Mutex::Autolock _l(mLock);
DisplayState& s(getDisplayStateLocked(token));
s.width = width;
s.height = height;
s.what |= DisplayState::eDisplaySizeChanged;
}
1.3 SurfaceFlingerとの通信
次のopenGlobalTransactionImpl関数を見て、鍵をかけてmTransactionNestCountを直接1に追加し、closeGlobalTransactionImpl関数でmTransactionNestCountの値が1であるかどうかを確認します.1より大きい場合は、直接終了します.これはopenGlobalTransactionとcloseGlobalTransactionを複数の場所で呼び出した場合、SurfaceFlingerと通信するのは最後の1回だけです.最後にmComposerStatesとmDisplayStatesをSurfaceFlingerのsetTransactionStateメソッドを呼び出してSurfaceFlingerに転送する.
void Composer::openGlobalTransactionImpl() {
{ // scope for the lock
Mutex::Autolock _l(mLock);
mTransactionNestCount += 1;
}
}
void Composer::closeGlobalTransactionImpl(bool synchronous) {
sp sm(ComposerService::getComposerService());
Vector transaction;
Vector 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) {// mTransactionNestCount 1 SurfaceFlinger
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);// SurfaceFlinger setTransactionState
}
二、Surface Flinger
SurfaceFlingerではsetTransactionState関数で処理され、各DisplayState呼び出しsetDisplayStateLocked設定display状態、次にComposerStateを巡りsetClientStateLocked設定状態が呼び出されます.最後にsetTransactionFlags関数が呼び出され、最後にINVALLIDATEメッセージが送信されます.このメッセージの処理は前のブログで分析されました.
void SurfaceFlinger::setTransactionState(
const Vector& state,
const Vector& displays,
uint32_t flags)
{
ATRACE_CALL();
Mutex::Autolock _l(mStateLock);
uint32_t transactionFlags = 0;
if (flags & eAnimation) {
// For window updates that are part of an animation we must wait for
// previous animation "frames" to be handled.
while (mAnimTransactionPending) {
status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
if (CC_UNLIKELY(err != NO_ERROR)) {
// just in case something goes wrong in SF, return to the
// caller after a few seconds.
ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
"waiting for previous animation frame");
mAnimTransactionPending = false;
break;
}
}
}
size_t count = displays.size();
for (size_t i=0 ; i binder = IInterface::asBinder(s.client);
if (binder != NULL) {
String16 desc(binder->getInterfaceDescriptor());
if (desc == ISurfaceComposerClient::descriptor) {
sp client( static_cast(s.client.get()) );
transactionFlags |= setClientStateLocked(client, s.state);
}
}
}
}
if (transactionFlags) {
// this triggers the transaction
setTransactionFlags(transactionFlags);
// if this is a synchronous transaction, wait for it to take effect
// before returning.
if (flags & eSynchronous) {
mTransactionPending = true;
}
if (flags & eAnimation) {
mAnimTransactionPending = true;
}
while (mTransactionPending) {
status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
if (CC_UNLIKELY(err != NO_ERROR)) {
// just in case something goes wrong in SF, return to the
// called after a few seconds.
ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
mTransactionPending = false;
break;
}
}
}
}
setDisplayStateLocked関数は、mCurrentStateからDisplayStateを取得し、いくつかの変数を設定します.
uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
{
ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
if (dpyIdx < 0)
return 0;
uint32_t flags = 0;
DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
if (disp.isValid()) {
const uint32_t what = s.what;
if (what & DisplayState::eSurfaceChanged) {
if (IInterface::asBinder(disp.surface) != IInterface::asBinder(s.surface)) {
disp.surface = s.surface;
flags |= eDisplayTransactionNeeded;
}
}
if (what & DisplayState::eLayerStackChanged) {
if (disp.layerStack != s.layerStack) {
disp.layerStack = s.layerStack;
flags |= eDisplayTransactionNeeded;
}
}
if (what & DisplayState::eDisplayProjectionChanged) {
if (disp.orientation != s.orientation) {
disp.orientation = s.orientation;
flags |= eDisplayTransactionNeeded;
}
if (disp.frame != s.frame) {
disp.frame = s.frame;
flags |= eDisplayTransactionNeeded;
}
if (disp.viewport != s.viewport) {
disp.viewport = s.viewport;
flags |= eDisplayTransactionNeeded;
}
}
if (what & DisplayState::eDisplaySizeChanged) {
if (disp.width != s.width) {
disp.width = s.width;
flags |= eDisplayTransactionNeeded;
}
if (disp.height != s.height) {
disp.height = s.height;
flags |= eDisplayTransactionNeeded;
}
}
}
return flags;
}
setClientStateLockedはlayerを取得し、いくつかのlayerのプロパティを設定し、最後にmCurrentStateを再読み込みます.LayersSortedByZにあります.
uint32_t SurfaceFlinger::setClientStateLocked(
const sp& client,
const layer_state_t& s)
{
uint32_t flags = 0;
sp layer(client->getLayerUser(s.surface));// layer
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::eFlagsChanged) {
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;
}
これらの関数はブログでhttp://blog.csdn.net/kc58236582/article/details/52778333では、各layerのonFrameAvailableでは最後にsignalLayerUpdate関数が呼び出され、最後にINVALidateメッセージが送信されます.このメッセージの処理については,このブログで分析したが,各layer属性,displayを更新する.
三、Surface
Surfaceについては、以前にSurfaceでmGraphicBufferProducerのdequeueBuffer関数を呼び出してから、mGraphicBufferProducerのqueueBuffer関数を呼び出すことを分析しました.これにより、Surface Flingerの各LayerのonFrameAvailable関数が実行され、各layerのデータが変化したことも統計されます.