Esempio n. 1
0
bool
ParamTraits<MagicGrallocBufferHandle>::Read(const Message* aMsg,
                                            void** aIter, paramType* aResult)
{
  size_t nbytes;
  size_t nfds;
  const char* data;

  if (!aMsg->ReadSize(aIter, &nbytes) ||
      !aMsg->ReadSize(aIter, &nfds) ||
      !aMsg->ReadBytes(aIter, &data, nbytes)) {
    return false;
  }

  int fds[nfds];

  for (size_t n = 0; n < nfds; ++n) {
    FileDescriptor fd;
    if (!aMsg->ReadFileDescriptor(aIter, &fd)) {
      return false;
    }
    // If the GraphicBuffer was shared cross-process, SCM_RIGHTS does
    // the right thing and dup's the fd.  If it's shared cross-thread,
    // SCM_RIGHTS doesn't dup the fd.  That's surprising, but we just
    // deal with it here.  NB: only the "default" (master) process can
    // alloc gralloc buffers.
    bool sameProcess = (XRE_GetProcessType() == GeckoProcessType_Default);
    int dupFd = sameProcess ? dup(fd.fd) : fd.fd;
    fds[n] = dupFd;
  }

  sp<GraphicBuffer> buffer(new GraphicBuffer());
#if ANDROID_VERSION >= 19
  // Make a copy of "data" and "fds" for unflatten() to avoid casting problem
  void const *pdata = (void const *)data;
  int const *pfds = fds;

  if (NO_ERROR == buffer->unflatten(pdata, nbytes, pfds, nfds)) {
#else
  Flattenable *flattenable = buffer.get();

  if (NO_ERROR == flattenable->unflatten(data, nbytes, fds, nfds)) {
#endif
    aResult->mGraphicBuffer = buffer;
    return true;
  }
  return false;
}

} // namespace IPC
void
ParamTraits<MagicGrallocBufferHandle>::Write(Message* aMsg,
                                             const paramType& aParam)
{
  Flattenable *flattenable = aParam.mGraphicBuffer.get();
  size_t nbytes = flattenable->getFlattenedSize();
  size_t nfds = flattenable->getFdCount();

  char data[nbytes];
  int fds[nfds];
  flattenable->flatten(data, nbytes, fds, nfds);

  aMsg->WriteSize(nbytes);
  aMsg->WriteSize(nfds);

  aMsg->WriteBytes(data, nbytes);
  for (size_t n = 0; n < nfds; ++n) {
    // These buffers can't die in transit because they're created
    // synchonously and the parent-side buffer can only be dropped if
    // there's a crash.
    aMsg->WriteFileDescriptor(FileDescriptor(fds[n], false));
  }
}
void
ParamTraits<MagicGrallocBufferHandle>::Write(Message* aMsg,
                                             const paramType& aParam)
{
#if ANDROID_VERSION >= 19
  sp<GraphicBuffer> flattenable = aParam.mGraphicBuffer;
#else
  Flattenable *flattenable = aParam.mGraphicBuffer.get();
#endif
  size_t nbytes = flattenable->getFlattenedSize();
  size_t nfds = flattenable->getFdCount();

  char data[nbytes];
  int fds[nfds];

#if ANDROID_VERSION >= 19
  // Make a copy of "data" and "fds" for flatten() to avoid casting problem
  void *pdata = (void *)data;
  int *pfds = fds;

  flattenable->flatten(pdata, nbytes, pfds, nfds);

  // In Kitkat, flatten() will change the value of nbytes and nfds, which dues
  // to multiple parcelable object consumption. The actual size and fd count
  // which returned by getFlattenedSize() and getFdCount() are not changed.
  // So we change nbytes and nfds back by call corresponding calls.
  nbytes = flattenable->getFlattenedSize();
  nfds = flattenable->getFdCount();
#else
  flattenable->flatten(data, nbytes, fds, nfds);
#endif
  aMsg->WriteInt(aParam.mRef.mOwner);
  aMsg->WriteInt64(aParam.mRef.mKey);
  aMsg->WriteSize(nbytes);
  aMsg->WriteSize(nfds);

  aMsg->WriteBytes(data, nbytes);
  for (size_t n = 0; n < nfds; ++n) {
    // These buffers can't die in transit because they're created
    // synchonously and the parent-side buffer can only be dropped if
    // there's a crash.
    aMsg->WriteFileDescriptor(FileDescriptor(fds[n], false));
  }
}
bool
ParamTraits<MagicGrallocBufferHandle>::Read(const Message* aMsg,
                                            PickleIterator* aIter, paramType* aResult)
{
  MOZ_ASSERT(!aResult->mGraphicBuffer.get());
  MOZ_ASSERT(aResult->mRef.mOwner == 0);
  MOZ_ASSERT(aResult->mRef.mKey == -1);

  size_t nbytes;
  int owner;
  int64_t index;

  if (!aMsg->ReadInt(aIter, &owner) ||
      !aMsg->ReadInt64(aIter, &index) ||
      !aMsg->ReadSize(aIter, &nbytes)) {
    printf_stderr("ParamTraits<MagicGrallocBufferHandle>::Read() failed to read a message\n");
    return false;
  }

  auto data = mozilla::MakeUnique<char[]>(nbytes);

  if (!aMsg->ReadBytesInto(aIter, data.get(), nbytes)) {
    printf_stderr("ParamTraits<MagicGrallocBufferHandle>::Read() failed to read a message\n");
    return false;
  }

  size_t nfds = aMsg->num_fds();
  int fds[nfds];

  for (size_t n = 0; n < nfds; ++n) {
    FileDescriptor fd;
    if (!aMsg->ReadFileDescriptor(aIter, &fd)) {
      printf_stderr("ParamTraits<MagicGrallocBufferHandle>::Read() failed to read file descriptors\n");
      return false;
    }
    // If the GraphicBuffer was shared cross-process, SCM_RIGHTS does
    // the right thing and dup's the fd. If it's shared cross-thread,
    // SCM_RIGHTS doesn't dup the fd.
    // But in shared cross-thread, dup fd is not necessary because we get
    // a pointer to the GraphicBuffer directly from SharedBufferManagerParent
    // and don't create a new GraphicBuffer around the fd.
    fds[n] = fd.fd;
  }

  aResult->mRef.mOwner = owner;
  aResult->mRef.mKey = index;
  if (XRE_IsParentProcess()) {
    // If we are in chrome process, we can just get GraphicBuffer directly from
    // SharedBufferManagerParent.
    aResult->mGraphicBuffer = SharedBufferManagerParent::GetGraphicBuffer(aResult->mRef);
  } else {
    // Deserialize GraphicBuffer
#if ANDROID_VERSION >= 19
    sp<GraphicBuffer> buffer(new GraphicBuffer());
    const void* datap = (const void*)data.get();
    const int* fdsp = &fds[0];
    if (NO_ERROR != buffer->unflatten(datap, nbytes, fdsp, nfds)) {
      buffer = nullptr;
    }
#else
    sp<GraphicBuffer> buffer(new GraphicBuffer());
    Flattenable *flattenable = buffer.get();
    if (NO_ERROR != flattenable->unflatten(data.get(), nbytes, fds, nfds)) {
      buffer = nullptr;
    }
#endif
    if (buffer.get()) {
      aResult->mGraphicBuffer = buffer;
    }
  }

  if (!aResult->mGraphicBuffer.get()) {
    printf_stderr("ParamTraits<MagicGrallocBufferHandle>::Read() failed to get gralloc buffer\n");
    return false;
  }

  return true;
}
bool
ParamTraits<MagicGrallocBufferHandle>::Read(const Message* aMsg,
                                            void** aIter, paramType* aResult)
{
  size_t nbytes;
  size_t nfds;
  const char* data;
  int owner;
  int64_t index;

  if (!aMsg->ReadInt(aIter, &owner) ||
      !aMsg->ReadInt64(aIter, &index) ||
      !aMsg->ReadSize(aIter, &nbytes) ||
      !aMsg->ReadSize(aIter, &nfds) ||
      !aMsg->ReadBytes(aIter, &data, nbytes)) {
    printf_stderr("ParamTraits<MagicGrallocBufferHandle>::Read() failed to read a message\n");
    return false;
  }

  int fds[nfds];
  bool sameProcess = (XRE_GetProcessType() == GeckoProcessType_Default);
  for (size_t n = 0; n < nfds; ++n) {
    FileDescriptor fd;
    if (!aMsg->ReadFileDescriptor(aIter, &fd)) {
      printf_stderr("ParamTraits<MagicGrallocBufferHandle>::Read() failed to read file descriptors\n");
      return false;
    }
    // If the GraphicBuffer was shared cross-process, SCM_RIGHTS does
    // the right thing and dup's the fd. If it's shared cross-thread,
    // SCM_RIGHTS doesn't dup the fd. 
    // But in shared cross-thread, dup fd is not necessary because we get
    // a pointer to the GraphicBuffer directly from SharedBufferManagerParent
    // and don't create a new GraphicBuffer around the fd.
    fds[n] = fd.fd;
  }

  aResult->mRef.mOwner = owner;
  aResult->mRef.mKey = index;
  if (sameProcess) {
    aResult->mGraphicBuffer = SharedBufferManagerParent::GetGraphicBuffer(aResult->mRef);
  } else {
    aResult->mGraphicBuffer = SharedBufferManagerChild::GetSingleton()->GetGraphicBuffer(index);
    MOZ_ASSERT(!aResult->mGraphicBuffer.get());

    // Deserialize GraphicBuffer
#if ANDROID_VERSION >= 19
    sp<GraphicBuffer> buffer(new GraphicBuffer());
    const void* datap = (const void*)data;
    const int* fdsp = &fds[0];
    if (NO_ERROR != buffer->unflatten(datap, nbytes, fdsp, nfds)) {
      buffer = nullptr;
    }
#else
    sp<GraphicBuffer> buffer(new GraphicBuffer());
    Flattenable *flattenable = buffer.get();
    if (NO_ERROR != flattenable->unflatten(data, nbytes, fds, nfds)) {
      buffer = nullptr;
    }
#endif
    if(buffer.get() && !aResult->mGraphicBuffer.get()) {
      aResult->mGraphicBuffer = buffer;
    }
  }

  if (!aResult->mGraphicBuffer.get()) {
    printf_stderr("ParamTraits<MagicGrallocBufferHandle>::Read() failed to get gralloc buffer\n");
    return false;
  }

  return true;
}