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

Commit 2f260339 authored by Jiwen 'Steve' Cai's avatar Jiwen 'Steve' Cai
Browse files

Remove legacy persistent BufferHub use case

This CL cleans up unused BufferHub code path. The motivation of doing
this is multifold:

1. Reduces future maintainace cost (e.g. when moving to libgui, there
   will be less code to rename and re-style).
2. Removes unnecessary code complexity so that the code base is easier
   and cleaner for future new reader to understand.
3. Prepares future work for supporting standalone GraphicBuffer in
   BufferHub by avoid future logical and naming conflicts between
   legacy PersistentBuffer/Detach/Attach and newly proposed detached
   GraphicBuffer in BufferHub.

Bug: 70046255
Bug: 70912269
Test: buffer_hub-test, buffer_hub_queue-test,
      buffer_hub_queue_producer-test, dvr_api-test, libgui_test

Change-Id: Ie9a0f55e3f620769bac58c81439d840402451b82
parent e65ab704
Loading
Loading
Loading
Loading
+0 −68
Original line number Diff line number Diff line
@@ -599,74 +599,6 @@ TEST_F(LibBufferHubTest, TestFailureToPostMetaFromABufferWithoutMeta) {
  EXPECT_NE(0, p->Post(LocalHandle(), sequence));
}

TEST_F(LibBufferHubTest, TestPersistentBufferPersistence) {
  auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
                                  kHeight, kFormat, kUsage);
  ASSERT_NE(nullptr, p);

  // Record the original buffer id for later comparison.
  const int buffer_id = p->id();

  auto c = BufferConsumer::Import(p->CreateConsumer());
  ASSERT_NE(nullptr, c);

  EXPECT_EQ(0, p->Post<void>(LocalHandle()));

  // Close the connection to the producer. This should not affect the consumer.
  p = nullptr;

  LocalHandle fence;
  EXPECT_EQ(0, c->Acquire(&fence));
  EXPECT_EQ(0, c->Release(LocalHandle()));

  // Attempt to reconnect to the persistent buffer.
  p = BufferProducer::Create("TestPersistentBuffer");
  ASSERT_NE(nullptr, p);
  EXPECT_EQ(buffer_id, p->id());
  EXPECT_EQ(0, p->Gain(&fence));
}

TEST_F(LibBufferHubTest, TestPersistentBufferMismatchParams) {
  auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
                                  kHeight, kFormat, kUsage);
  ASSERT_NE(nullptr, p);

  // Close the connection to the producer.
  p = nullptr;

  // Mismatch the params.
  p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth * 2,
                             kHeight, kFormat, kUsage);
  ASSERT_EQ(nullptr, p);
}

TEST_F(LibBufferHubTest, TestRemovePersistentBuffer) {
  auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
                                  kHeight, kFormat, kUsage);
  ASSERT_NE(nullptr, p);

  LocalHandle fence;
  auto c = BufferConsumer::Import(p->CreateConsumer());
  ASSERT_NE(nullptr, c);
  EXPECT_EQ(0, p->Post<void>(LocalHandle()));
  EXPECT_EQ(0, c->Acquire(&fence));
  EXPECT_EQ(0, c->Release(LocalHandle()));
  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));

  // Test that removing persistence and closing the producer orphans the
  // consumer.
  EXPECT_EQ(0, p->Gain(&fence));
  EXPECT_EQ(0, p->Post<void>(LocalHandle()));
  EXPECT_EQ(0, p->RemovePersistence());
  p = nullptr;

  // Orphaned consumer can acquire the posted buffer one more time in
  // asynchronous manner. But synchronous call will fail.
  DvrNativeBufferMetadata meta;
  EXPECT_EQ(0, c->AcquireAsync(&meta, &fence));
  EXPECT_EQ(-EPIPE, c->Release(LocalHandle()));
}

namespace {

int PollFd(int fd, int timeout_ms) {
+0 −125
Original line number Diff line number Diff line
@@ -431,50 +431,6 @@ BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
  }
}

BufferProducer::BufferProducer(const std::string& name, int user_id,
                               int group_id, uint32_t width, uint32_t height,
                               uint32_t format, uint32_t usage,
                               size_t user_metadata_size)
    : BufferProducer(name, user_id, group_id, width, height, format, usage,
                     usage, user_metadata_size) {}

BufferProducer::BufferProducer(const std::string& name, int user_id,
                               int group_id, uint32_t width, uint32_t height,
                               uint32_t format, uint64_t producer_usage,
                               uint64_t consumer_usage,
                               size_t user_metadata_size)
    : BASE(BufferHubRPC::kClientPath) {
  ATRACE_NAME("BufferProducer::BufferProducer");
  ALOGD_IF(TRACE,
           "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
           "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64
           " consumer_usage=%" PRIx64 " user_metadata_size=%zu",
           event_fd(), name.c_str(), user_id, group_id, width, height, format,
           producer_usage, consumer_usage, user_metadata_size);

  // (b/37881101) Deprecate producer/consumer usage
  auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
      name, user_id, group_id, width, height, format,
      (producer_usage | consumer_usage), user_metadata_size);
  if (!status) {
    ALOGE(
        "BufferProducer::BufferProducer: Failed to create/get persistent "
        "buffer \"%s\": %s",
        name.c_str(), status.GetErrorMessage().c_str());
    Close(-status.error());
    return;
  }

  const int ret = ImportBuffer();
  if (ret < 0) {
    ALOGE(
        "BufferProducer::BufferProducer: Failed to import producer buffer "
        "\"%s\": %s",
        name.c_str(), strerror(-ret));
    Close(ret);
  }
}

BufferProducer::BufferProducer(uint32_t usage, size_t size)
    : BufferProducer(usage, usage, size) {}

@@ -511,73 +467,6 @@ BufferProducer::BufferProducer(uint64_t producer_usage, uint64_t consumer_usage,
  }
}

BufferProducer::BufferProducer(const std::string& name, int user_id,
                               int group_id, uint32_t usage, size_t size)
    : BufferProducer(name, user_id, group_id, usage, usage, size) {}

BufferProducer::BufferProducer(const std::string& name, int user_id,
                               int group_id, uint64_t producer_usage,
                               uint64_t consumer_usage, size_t size)
    : BASE(BufferHubRPC::kClientPath) {
  ATRACE_NAME("BufferProducer::BufferProducer");
  ALOGD_IF(TRACE,
           "BufferProducer::BufferProducer: name=%s user_id=%d group=%d "
           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64 " size=%zu",
           name.c_str(), user_id, group_id, producer_usage, consumer_usage,
           size);
  const int width = static_cast<int>(size);
  const int height = 1;
  const int format = HAL_PIXEL_FORMAT_BLOB;
  const size_t user_metadata_size = 0;

  // (b/37881101) Deprecate producer/consumer usage
  auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
      name, user_id, group_id, width, height, format,
      (producer_usage | consumer_usage), user_metadata_size);
  if (!status) {
    ALOGE(
        "BufferProducer::BufferProducer: Failed to create persistent "
        "buffer \"%s\": %s",
        name.c_str(), status.GetErrorMessage().c_str());
    Close(-status.error());
    return;
  }

  const int ret = ImportBuffer();
  if (ret < 0) {
    ALOGE(
        "BufferProducer::BufferProducer: Failed to import producer buffer "
        "\"%s\": %s",
        name.c_str(), strerror(-ret));
    Close(ret);
  }
}

BufferProducer::BufferProducer(const std::string& name)
    : BASE(BufferHubRPC::kClientPath) {
  ATRACE_NAME("BufferProducer::BufferProducer");
  ALOGD_IF(TRACE, "BufferProducer::BufferProducer: name=%s", name.c_str());

  auto status = InvokeRemoteMethod<BufferHubRPC::GetPersistentBuffer>(name);
  if (!status) {
    ALOGE(
        "BufferProducer::BufferProducer: Failed to get producer buffer by name "
        "\"%s\": %s",
        name.c_str(), status.GetErrorMessage().c_str());
    Close(-status.error());
    return;
  }

  const int ret = ImportBuffer();
  if (ret < 0) {
    ALOGE(
        "BufferProducer::BufferProducer: Failed to import producer buffer "
        "\"%s\": %s",
        name.c_str(), strerror(-ret));
    Close(ret);
  }
}

BufferProducer::BufferProducer(LocalChannelHandle channel)
    : BASE(std::move(channel)) {
  const int ret = ImportBuffer();
@@ -736,19 +625,5 @@ std::unique_ptr<BufferProducer> BufferProducer::Import(
                       : LocalChannelHandle{nullptr, -status.error()});
}

int BufferProducer::MakePersistent(const std::string& name, int user_id,
                                   int group_id) {
  ATRACE_NAME("BufferProducer::MakePersistent");
  return ReturnStatusOrError(
      InvokeRemoteMethod<BufferHubRPC::ProducerMakePersistent>(name, user_id,
                                                               group_id));
}

int BufferProducer::RemovePersistence() {
  ATRACE_NAME("BufferProducer::RemovePersistence");
  return ReturnStatusOrError(
      InvokeRemoteMethod<BufferHubRPC::ProducerRemovePersistence>());
}

}  // namespace dvr
}  // namespace android
+0 −43
Original line number Diff line number Diff line
@@ -221,19 +221,6 @@ class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
  // succeeded, or a negative errno code if local error check fails.
  int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);

  // Attaches the producer to |name| so that it becomes a persistent buffer that
  // may be retrieved by name at a later time. This may be used in cases where a
  // shared memory buffer should persist across the life of the producer process
  // (i.e. the buffer may be held by clients across a service restart). The
  // buffer may be associated with a user and/or group id to restrict access to
  // the buffer. If user_id or group_id is -1 then checks for the respective id
  // are disabled. If user_id or group_id is 0 then the respective id of the
  // calling process is used instead.
  int MakePersistent(const std::string& name, int user_id, int group_id);

  // Removes the persistence of the producer.
  int RemovePersistence();

 private:
  friend BASE;

@@ -248,40 +235,10 @@ class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
                 uint64_t producer_usage, uint64_t consumer_usage,
                 size_t metadata_size);

  // Constructs a persistent buffer with the given geometry and parameters and
  // binds it to |name| in one shot. If a persistent buffer with the same name
  // and settings already exists and matches the given geometry and parameters,
  // that buffer is connected to this client instead of creating a new buffer.
  // If the name matches but the geometry or settings do not match then
  // construction fails and BufferProducer::Create() returns nullptr.
  //
  // Access to the persistent buffer may be restricted by |user_id| and/or
  // |group_id|; these settings are established only when the buffer is first
  // created and cannot be changed. A user or group id of -1 disables checks for
  // that respective id. A user or group id of 0 is substituted with the
  // effective user or group id of the calling process.
  BufferProducer(const std::string& name, int user_id, int group_id,
                 uint32_t width, uint32_t height, uint32_t format,
                 uint32_t usage, size_t metadata_size = 0);
  BufferProducer(const std::string& name, int user_id, int group_id,
                 uint32_t width, uint32_t height, uint32_t format,
                 uint64_t producer_usage, uint64_t consumer_usage,
                 size_t user_metadata_size);

  // Constructs a blob (flat) buffer with the given usage flags.
  BufferProducer(uint32_t usage, size_t size);
  BufferProducer(uint64_t producer_usage, uint64_t consumer_usage, size_t size);

  // Constructs a persistent blob (flat) buffer and binds it to |name|.
  BufferProducer(const std::string& name, int user_id, int group_id,
                 uint32_t usage, size_t size);
  BufferProducer(const std::string& name, int user_id, int group_id,
                 uint64_t producer_usage, uint64_t consumer_usage, size_t size);

  // Constructs a channel to persistent buffer by name only. The buffer must
  // have been previously created or made persistent.
  explicit BufferProducer(const std::string& name);

  // Imports the given file handle to a producer channel, taking ownership.
  explicit BufferProducer(LocalChannelHandle channel);

+0 −14
Original line number Diff line number Diff line
@@ -366,12 +366,8 @@ struct BufferHubRPC {
  // Op codes.
  enum {
    kOpCreateBuffer = 0,
    kOpCreatePersistentBuffer,
    kOpGetPersistentBuffer,
    kOpGetBuffer,
    kOpNewConsumer,
    kOpProducerMakePersistent,
    kOpProducerRemovePersistence,
    kOpProducerPost,
    kOpProducerGain,
    kOpConsumerAcquire,
@@ -394,19 +390,9 @@ struct BufferHubRPC {
  PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
                    void(uint32_t width, uint32_t height, uint32_t format,
                         uint64_t usage, size_t user_metadata_size));
  PDX_REMOTE_METHOD(CreatePersistentBuffer, kOpCreatePersistentBuffer,
                    void(const std::string& name, int user_id, int group_id,
                         uint32_t width, uint32_t height, uint32_t format,
                         uint64_t usage, size_t user_metadata_size));
  PDX_REMOTE_METHOD(GetPersistentBuffer, kOpGetPersistentBuffer,
                    void(const std::string& name));
  PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer,
                    BufferDescription<LocalHandle>(Void));
  PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void));
  PDX_REMOTE_METHOD(ProducerMakePersistent, kOpProducerMakePersistent,
                    void(const std::string& name, int user_id, int group_id));
  PDX_REMOTE_METHOD(ProducerRemovePersistence, kOpProducerRemovePersistence,
                    void(Void));
  PDX_REMOTE_METHOD(ProducerPost, kOpProducerPost,
                    void(LocalFence acquire_fence));
  PDX_REMOTE_METHOD(ProducerGain, kOpProducerGain, LocalFence(Void));
+18 −194
Original line number Diff line number Diff line
@@ -62,8 +62,6 @@ std::string BufferHubService::DumpState(size_t /*max_length*/) {
  stream << std::setw(18) << "Signaled";
  stream << " ";
  stream << std::setw(10) << "Index";
  stream << " ";
  stream << "Name";
  stream << std::endl;

  for (const auto& channel : channels) {
@@ -100,8 +98,6 @@ std::string BufferHubService::DumpState(size_t /*max_length*/) {
      stream << std::dec << std::setfill(' ');
      stream << " ";
      stream << std::setw(8) << info.index;
      stream << " ";
      stream << info.name;
      stream << std::endl;
    }
  }
@@ -166,9 +162,7 @@ std::string BufferHubService::DumpState(size_t /*max_length*/) {
  stream << std::right;
  stream << std::setw(6) << "Id";
  stream << " ";
  stream << std::setw(14) << "Geometry";
  stream << " ";
  stream << "Name";
  stream << std::setw(14) << "Info";
  stream << std::endl;

  for (const auto& channel : channels) {
@@ -216,16 +210,6 @@ pdx::Status<void> BufferHubService::HandleMessage(Message& message) {
          *this, &BufferHubService::OnCreateBuffer, message);
      return {};

    case BufferHubRPC::CreatePersistentBuffer::Opcode:
      DispatchRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
          *this, &BufferHubService::OnCreatePersistentBuffer, message);
      return {};

    case BufferHubRPC::GetPersistentBuffer::Opcode:
      DispatchRemoteMethod<BufferHubRPC::GetPersistentBuffer>(
          *this, &BufferHubService::OnGetPersistentBuffer, message);
      return {};

    case BufferHubRPC::CreateProducerQueue::Opcode:
      DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>(
          *this, &BufferHubService::OnCreateProducerQueue, message);
@@ -236,12 +220,6 @@ pdx::Status<void> BufferHubService::HandleMessage(Message& message) {
  }
}

void BufferHubService::OnChannelClose(Message&,
                                      const std::shared_ptr<Channel>& channel) {
  if (auto buffer = std::static_pointer_cast<BufferHubChannel>(channel))
    buffer->Detach();
}

Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
                                              uint32_t height, uint32_t format,
                                              uint64_t usage,
@@ -273,117 +251,6 @@ Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
  }
}

Status<void> BufferHubService::OnCreatePersistentBuffer(
    Message& message, const std::string& name, int user_id, int group_id,
    uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
    size_t meta_size_bytes) {
  const uint32_t kDefaultLayerCount = 1;
  const int channel_id = message.GetChannelId();
  ALOGD_IF(TRACE,
           "BufferHubService::OnCreatePersistentBuffer: channel_id=%d name=%s "
           "user_id=%d group_id=%d width=%u height=%u format=%u "
           "usage=%" PRIx64 " meta_size_bytes=%zu",
           channel_id, name.c_str(), user_id, group_id, width, height, format,
           usage, meta_size_bytes);

  // See if this channel is already attached to a buffer.
  if (const auto channel = message.GetChannel<BufferHubChannel>()) {
    ALOGE(
        "BufferHubService::OnCreatePersistentBuffer: Channel already attached "
        "to buffer: channel_id=%d buffer_id=%d",
        channel_id, channel->buffer_id());
    return ErrorStatus(EALREADY);
  }

  const int euid = message.GetEffectiveUserId();
  const int egid = message.GetEffectiveGroupId();

  if (auto buffer = GetNamedBuffer(name)) {
    if (!buffer->CheckAccess(euid, egid)) {
      ALOGE(
          "BufferHubService::OnCreatePersistentBuffer: Requesting process does "
          "not have permission to access named buffer: name=%s euid=%d egid=%d",
          name.c_str(), euid, euid);
      return ErrorStatus(EPERM);
    } else if (!buffer->CheckParameters(width, height, kDefaultLayerCount,
                                        format, usage, meta_size_bytes)) {
      ALOGE(
          "BufferHubService::OnCreatePersistentBuffer: Requested an existing "
          "buffer with different parameters: name=%s",
          name.c_str());
      return ErrorStatus(EINVAL);
    } else if (!buffer->IsDetached()) {
      ALOGE(
          "BufferHubService::OnCreatePersistentBuffer: Requesting a persistent "
          "buffer that is already attached to a channel: name=%s",
          name.c_str());
      return ErrorStatus(EINVAL);
    } else {
      buffer->Attach(channel_id);
      message.SetChannel(buffer);
      return {};
    }
  } else {
    auto status = ProducerChannel::Create(this, channel_id, width, height,
                                          kDefaultLayerCount, format, usage,
                                          meta_size_bytes);
    if (!status) {
      ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
      return status.error_status();
    }
    auto persistent_buffer = status.take();
    auto make_persistent_status = persistent_buffer->OnProducerMakePersistent(
        message, name, user_id, group_id);
    if (make_persistent_status)
      message.SetChannel(persistent_buffer);
    return make_persistent_status;
  }
}

Status<void> BufferHubService::OnGetPersistentBuffer(Message& message,
                                                     const std::string& name) {
  const int channel_id = message.GetChannelId();
  ALOGD_IF(TRACE,
           "BufferHubService::OnGetPersistentBuffer: channel_id=%d name=%s",
           channel_id, name.c_str());

  // See if this channel is already attached to a buffer.
  if (const auto channel = message.GetChannel<BufferHubChannel>()) {
    ALOGE(
        "BufferHubService::OnGetPersistentBuffer: Channel already attached to "
        "buffer: channel_id=%d buffer_id=%d",
        channel_id, channel->buffer_id());
    return ErrorStatus(EALREADY);
  }

  const int euid = message.GetEffectiveUserId();
  const int egid = message.GetEffectiveGroupId();

  if (auto buffer = GetNamedBuffer(name)) {
    if (!buffer->CheckAccess(euid, egid)) {
      ALOGE(
          "BufferHubService::OnGetPersistentBuffer: Requesting process does "
          "not have permission to access named buffer: name=%s euid=%d egid=%d",
          name.c_str(), euid, egid);
      return ErrorStatus(EPERM);
    } else if (!buffer->IsDetached()) {
      ALOGE(
          "BufferHubService::OnGetPersistentBuffer: Requesting a persistent "
          "buffer that is already attached to a channel: name=%s",
          name.c_str());
      return ErrorStatus(EINVAL);
    } else {
      buffer->Attach(channel_id);
      message.SetChannel(buffer);
      return {};
    }
  } else {
    ALOGE("BufferHubService::OnGetPersistentBuffer: Buffer \"%s\" not found!",
          name.c_str());
    return ErrorStatus(ENOENT);
  }
}

Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
    pdx::Message& message, const ProducerQueueConfig& producer_config,
    const UsagePolicy& usage_policy) {
@@ -410,52 +277,17 @@ Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
  }
}

bool BufferHubService::AddNamedBuffer(
    const std::string& name, const std::shared_ptr<ProducerChannel>& buffer) {
  auto search = named_buffers_.find(name);
  if (search == named_buffers_.end()) {
    named_buffers_.emplace(name, buffer);
    return true;
  } else {
    return false;
  }
}

std::shared_ptr<ProducerChannel> BufferHubService::GetNamedBuffer(
    const std::string& name) {
  auto search = named_buffers_.find(name);
  if (search != named_buffers_.end())
    return search->second;
  else
    return nullptr;
}

bool BufferHubService::RemoveNamedBuffer(const ProducerChannel& buffer) {
  for (auto it = named_buffers_.begin(); it != named_buffers_.end();) {
    if (it->second.get() == &buffer) {
      named_buffers_.erase(it);
      return true;
    }
    ++it;
  }
  return false;
}

void BufferHubChannel::SignalAvailable() {
  ATRACE_NAME("BufferHubChannel::SignalAvailable");
  ALOGD_IF(TRACE,
           "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d",
           channel_id(), buffer_id());
  if (!IsDetached()) {
  signaled_ = true;
  const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLIN);
  ALOGE_IF(!status,
           "BufferHubChannel::SignalAvailable: failed to signal availability "
           "channel_id=%d: %s",
           channel_id_, status.GetErrorMessage().c_str());
  } else {
    ALOGD_IF(TRACE, "BufferHubChannel::SignalAvailable: detached buffer.");
  }
}

void BufferHubChannel::ClearAvailable() {
@@ -463,31 +295,23 @@ void BufferHubChannel::ClearAvailable() {
  ALOGD_IF(TRACE,
           "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d",
           channel_id(), buffer_id());
  if (!IsDetached()) {
  signaled_ = false;
  const auto status = service_->ModifyChannelEvents(channel_id_, POLLIN, 0);
  ALOGE_IF(!status,
           "BufferHubChannel::ClearAvailable: failed to clear availability "
           "channel_id=%d: %s",
           channel_id_, status.GetErrorMessage().c_str());
  } else {
    ALOGD_IF(TRACE, "BufferHubChannel::ClearAvailable: detached buffer.");
  }
}

void BufferHubChannel::Hangup() {
  ATRACE_NAME("BufferHubChannel::Hangup");
  ALOGD_IF(TRACE, "BufferHubChannel::Hangup: channel_id=%d buffer_id=%d",
           channel_id(), buffer_id());
  if (!IsDetached()) {
  const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLHUP);
  ALOGE_IF(
      !status,
      "BufferHubChannel::Hangup: failed to signal hangup channel_id=%d: %s",
      channel_id_, status.GetErrorMessage().c_str());
  } else {
    ALOGD_IF(TRACE, "BufferHubChannel::Hangup: detached buffer.");
  }
}

}  // namespace dvr
Loading