采纳答案成功!
向帮助你的同学说点啥吧!感谢那些助人为乐的人
我看源码里面ISurfaceComposerClient的createSurface函数里面跨进程传递的是一个GBP的sp,是一个内部GBP指针为空的出参,跟踪发现传给Parcel的是一个NULL,Parcel内部写处理为NULL的IBinder是标记为BINDER_TYPE_BINDER的flat_binder_obj,它里binder和cookie都是0,这时候该怎么理解这个本应该是代理对象却被标记成了本地对象的Binder呢?还是我流程搞错了呢?
老师谢谢,我知道哪里错了,它模板方法里专门判断了如果参数是指针就当成出参,不进行传递
// Since we assume that pointer arguments are outputs, we can use this template struct to
// determine whether or not a given argument is fundamentally a pointer type and thus an output
template <typename T>
struct IsPointerIfDecayed {
private:
using Decayed = typename std::decay<T>::type;
public:
static constexpr bool value = std::is_pointer<Decayed>::value;
};
下面是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);
}
一、BpSurfaceComposerClient是proxy端,createSurface调用之后,parcel里面读出gbp。 二、BnSurfaceComposerClient是实体端,createSurface之后,gbp就有值了,然后写到parcel里面返回。createSurface具体实现在Client这个类里,Client继承了BnSurfaceComposerClient。 proxy端在发起createSurface调用的时候,没有传sp之类的,只是带了parcel,parcel里面也没有带这个sp,而是调用结束之后,从parcel里读出gbp,然后设置给这个sp。 remote()->transact(CREATE_SURFACE, data, &reply); *gbp = interface_cast<IGraphicBufferProducer>(reply.readStrongBinder());
登录后可查看更多问答,登录/注册