Android6.0 SurfaceControl分析(二)SurfaceControlとSurfaceFlinger通信


前のブログでは、SurfaceControlがopenTransactionとcloseTransactionを呼び出し、すべてのSurfaceControlのプロパティなどをSurfaceFlingerに伝えると述べています.この過程を見てみましょう.

一、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のデータが変化したことも統計されます.