老师问一下GBP传递的问题
来源:6-3 surface跨进程传递原理
慕村9285654
2019-06-22
我看源码里面ISurfaceComposerClient的createSurface函数里面跨进程传递的是一个GBP的sp,是一个内部GBP指针为空的出参,跟踪发现传给Parcel的是一个NULL,Parcel内部写处理为NULL的IBinder是标记为BINDER_TYPE_BINDER的flat_binder_obj,它里binder和cookie都是0,这时候该怎么理解这个本应该是代理对象却被标记成了本地对象的Binder呢?还是我流程搞错了呢?
2回答
-
您好,建议给代码贴出来,这样会清楚一点。
012019-06-23 -
慕村9285654
提问者
2019-06-22
下面是SurfaceComposerClient的createSurfaceChecked方法,调用的是内部mClient(ISurfaceComposerClient)代理对象跨进程调用,传入了sp<IGgrapichBufferProducer>. status_t SurfaceComposerClient::createSurfaceChecked( const String8& name, uint32_t w, uint32_t h, PixelFormat format, sp<SurfaceControl>* outSurface, uint32_t flags, SurfaceControl* parent, int32_t windowType, int32_t ownerUid) { sp<SurfaceControl> sur; status_t err = mStatus; if (mStatus == NO_ERROR) { sp<IBinder> handle; sp<IBinder> parentHandle; sp<IGraphicBufferProducer> gbp; if (parent != nullptr) { parentHandle = parent->getHandle(); } err = mClient->createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */); } } return err; }这个是代理对象的createSurface具体实现,调用了公共方法callRemote模版方法
class BpSurfaceComposerClient : public SafeBpInterface<ISurfaceComposerClient> {
public:
explicit BpSurfaceComposerClient(const sp<IBinder>& impl)
: SafeBpInterface<ISurfaceComposerClient>(impl, "BpSurfaceComposerClient") {}
~BpSurfaceComposerClient() override;
status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format,
uint32_t flags, const sp<IBinder>& parent, int32_t windowType,
int32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp) override {
return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CREATE_SURFACE,
name, width, height,
format, flags, parent,
windowType, ownerUid,
handle, gbp);
}
}
模版方法如下,主要是调用了writeInputs这个模版方法,用std::forward历遍转发了所有的参数
template <typename Method, typename TagType, typename... Args>
status_t callRemote(TagType tag, Args&&... args) const {
static_assert(sizeof(TagType) <= sizeof(uint32_t), "Tag must fit inside uint32_t");
// Verify that the arguments are compatible with the parameters
using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
static_assert(ArgsMatchParams<std::tuple<Args...>, ParamTuple>::value,
"Invalid argument type");
// Write the input arguments to the data Parcel
Parcel data;
data.writeInterfaceToken(this->getInterfaceDescriptor());
status_t error = writeInputs(&data, std::forward<Args>(args)...);
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged by writeInputs
return error;
}
// Send the data Parcel to the remote and retrieve the reply parcel
Parcel reply;
error = this->remote()->transact(static_cast<uint32_t>(tag), data, &reply);
if (CC_UNLIKELY(error != NO_ERROR)) {
ALOG(LOG_ERROR, mLogTag, "Failed to transact (%d)", error);
#if SI_DUMP_CALLSTACKS
CallStack callStack(mLogTag);
#endif
return error;
}
下面是具体的writeInputs模版方法,主要是递归调用达到历遍所有参数的目的.
template <typename T, typename... Remaining>
status_t writeInputs(Parcel* data, T&& t, Remaining&&... remaining) const {
status_t error = writeIfInput(data, std::forward<T>(t));
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged by writeIfInput
return error;
}
return writeInputs(data, std::forward<Remaining>(remaining)...);
}
static status_t writeInputs(Parcel* /*data*/) { return NO_ERROR; }
每一步调用ParcelHandler的一系列模版方法
template <typename T>
typename std::enable_if<!IsPointerIfDecayed<T>::value, status_t>::type writeIfInput(
Parcel* data, T&& t) const {
return SafeInterface::ParcelHandler{mLogTag}.write(data, std::forward<T>(t));
}
template <typename T>
typename std::enable_if<IsPointerIfDecayed<T>::value, status_t>::type writeIfInput(
Parcel* /*data*/, T&& /*t*/) const {
return NO_ERROR;
}
对于sp<IGraphicBufferProducer>这个出参会匹配到下面这个模版方法,这个模版方法又调用了另一个模版方法
template <typename T>
typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type write(
Parcel* parcel, const sp<T>& interface) const {
return write(parcel, IInterface::asBinder(interface));
}
下面这个模版方法,是上面那个模版方法调用的
template <typename T>
typename std::enable_if<std::is_same<IBinder, T>::value, status_t>::type write(
Parcel* parcel, const sp<T>& pointer) const {
return callParcel("writeStrongBinder",
[&]() { return parcel->writeStrongBinder(pointer); });
}
但是里面的pointer为null,因为IInterface::asBinder(interface)这个函数在开始判断iface == NULL 因为sp重载了 == 操作符 比较的是内部的m_ptr,因为是空的所以直接返回了null
inline bool operator _op_ (const sp<T>& o) const { \
return m_ptr _op_ o.m_ptr; \
}
// static
sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
{
if (iface == NULL) return NULL;
return iface->onAsBinder();
}
最终调用的是parcel->writeStrongBinder(pointer) 来写入,最终调用flatten_binder即下面这个函数来写入flat_binder_object,传递给binder驱动,里面的分支可以看到binder == NULL。往后面走入驱动就没法理解了,一个本来是代理Binder进入驱动变成了本地Binder.我读到这里就懵逼了,反复看了很久,我怀疑中间一定有一步读错了。。。感觉对于native层Binder通讯的出入参的理解有问题
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
/* minimum priority for all nodes is nice 0 */
obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
} else {
/* minimum priority for all nodes is MAX_NICE(19) */
obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
}
if (binder != NULL) {
IBinder *local = binder->localBinder();
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.hdr.type = BINDER_TYPE_HANDLE;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = 0;
} else {
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
} else {
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
return finish_flatten_binder(binder, obj, out);
}
132019-06-23
相似问题