Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d94e2ee6 authored by Fan Xu's avatar Fan Xu
Browse files

Add duplicate to BufferClient

Calling BufferClient::duplicate() will now return you an uint64_t token
stands for a specific BufferNode. In later CLs users could pass this
IPC-friendly token everywhere and use it to create a IBufferClient
linked to that BufferNode.

The token is derived from the mt19936_64 random algorithm. No same
tokens will be generated at the same time by checking the token_map_.
The map holds a weak_ptr so that if the BufferNode goes away by some
reason the map will not keep it, preventing from memory leak.

Add test case to test on the function.

Test: "atest buffer_hub_binder_service-test" passed.
Bug: 116681016
Change-Id: I54c34d9fabe882326faa141a6f0691419b740694
parent 27631c9c
Loading
Loading
Loading
Loading
+33 −1
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@ class BpBufferClient : public BpInterface<IBufferClient> {
      : BpInterface<IBufferClient>(impl) {}

  bool isValid() override;

  status_t duplicate(uint64_t* outToken) override;
};

IMPLEMENT_META_INTERFACE(BufferClient, "android.dvr.IBufferClient");
@@ -17,6 +19,7 @@ IMPLEMENT_META_INTERFACE(BufferClient, "android.dvr.IBufferClient");
// Transaction code
enum {
  IS_VALID = IBinder::FIRST_CALL_TRANSACTION,
  DUPLICATE,
};

bool BpBufferClient::isValid() {
@@ -38,13 +41,42 @@ bool BpBufferClient::isValid() {
  }
}

status_t BpBufferClient::duplicate(uint64_t* outToken) {
  Parcel data, reply;
  status_t ret =
      data.writeInterfaceToken(IBufferClient::getInterfaceDescriptor());
  if (ret != NO_ERROR) {
    ALOGE("BpBufferClient::duplicate: failed to write into parcel; errno=%d",
          ret);
    return ret;
  }

  ret = remote()->transact(DUPLICATE, data, &reply);
  if (ret == NO_ERROR) {
    *outToken = reply.readUint64();
    return NO_ERROR;
  } else {
    ALOGE("BpBufferClient::duplicate: failed to transact; errno=%d", ret);
    return ret;
  }
}

status_t BnBufferClient::onTransact(uint32_t code, const Parcel& data,
                                    Parcel* reply, uint32_t flags) {
  switch (code) {
    case IS_VALID: {
      CHECK_INTERFACE(IBufferClient, data, reply);
      return reply->writeBool(isValid());
    } break;
    }
    case DUPLICATE: {
      CHECK_INTERFACE(IBufferClient, data, reply);
      uint64_t token = 0;
      status_t ret = duplicate(&token);
      if (ret != NO_ERROR) {
        return ret;
      }
      return reply->writeUint64(token);
    }
    default:
      // Should not reach except binder defined transactions such as dumpsys
      return BBinder::onTransact(code, data, reply, flags);
+4 −0
Original line number Diff line number Diff line
@@ -14,6 +14,10 @@ class IBufferClient : public IInterface {

  // Checks if the buffer node is valid.
  virtual bool isValid() = 0;

  // Duplicates the client. Token_out will be set to a new token when succeed,
  // and not changed when failed.
  virtual status_t duplicate(uint64_t* outToken) = 0;
};

// BnInterface for IBufferClient. Should only be created in bufferhub service.
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ cc_library_static {
    name: "libbufferhubd",
    srcs: [
        "buffer_channel.cpp",
        "buffer_client.cpp",
        "buffer_hub.cpp",
        "buffer_hub_binder.cpp",
        "buffer_node.cpp",
+1 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ status_t BnBufferHub::onTransact(uint32_t code, const Parcel& data,
      sp<IBufferClient> ret = createBuffer(width, height, layer_count, format,
                                           usage, user_metadata_size);
      return reply->writeStrongBinder(IInterface::asBinder(ret));
    } break;
    }
    default:
      // Should not reach except binder defined transactions such as dumpsys
      return BBinder::onTransact(code, data, reply, flags);
+18 −0
Original line number Diff line number Diff line
#include <private/dvr/buffer_client.h>
#include <private/dvr/buffer_hub_binder.h>

namespace android {
namespace dvr {

status_t BufferClient::duplicate(uint64_t* outToken) {
  if (!buffer_node_) {
    // Should never happen
    ALOGE("BufferClient::duplicate: node is missing.");
    return UNEXPECTED_NULL;
  }
  return service_->registerToken(std::weak_ptr<BufferNode>(buffer_node_),
                                 outToken);
}

}  // namespace dvr
}  // namespace android
 No newline at end of file
Loading