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

Commit 95ab988e authored by Steven Thomas's avatar Steven Thomas Committed by Android (Google) Code Review
Browse files

Merge "Pass onVsync() callbacks from vr flinger back to surface flinger"

parents 2ea14d2d dfde8fa8
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -16,8 +16,8 @@ sourceFiles = [
    "display_client.cpp",
    "display_client.cpp",
    "display_manager_client.cpp",
    "display_manager_client.cpp",
    "display_protocol.cpp",
    "display_protocol.cpp",
    "vsync_client.cpp",
    "shared_buffer_helpers.cpp",
    "shared_buffer_helpers.cpp",
    "vsync_service.cpp",
]
]


localIncludeFiles = [
localIncludeFiles = [
+0 −69
Original line number Original line Diff line number Diff line
#ifndef ANDROID_DVR_VSYNC_CLIENT_H_
#define ANDROID_DVR_VSYNC_CLIENT_H_

#include <stdint.h>

#include <pdx/client.h>

struct dvr_vsync_client {};

namespace android {
namespace dvr {

/*
 * VSyncClient is a remote interface to the vsync service in displayd.
 * This class is used to wait for and retrieve information about the
 * display vsync.
 */
class VSyncClient : public pdx::ClientBase<VSyncClient>,
                    public dvr_vsync_client {
 public:
  /*
   * Wait for the next vsync signal.
   * The timestamp (in ns) is written into *ts when ts is non-NULL.
   */
  int Wait(int64_t* timestamp_ns);

  /*
   * Returns the file descriptor used to communicate with the vsync system
   * service or -1 on error.
   */
  int GetFd();

  /*
   * Clears the select/poll/epoll event so that subsequent calls to
   * these will not signal until the next vsync.
   */
  int Acknowledge();

  /*
   * Get the timestamp of the last vsync event in ns. This call has
   * the same side effect on events as Acknowledge(), which saves
   * an IPC message.
   */
  int GetLastTimestamp(int64_t* timestamp_ns);

  /*
   * Get vsync scheduling info.
   * Get the estimated timestamp of the next GPU lens warp preemption event in
   * ns. Also returns the corresponding vsync count that the next lens warp
   * operation will target. This call has the same side effect on events as
   * Acknowledge(), which saves an IPC message.
   */
  int GetSchedInfo(int64_t* vsync_period_ns, int64_t* next_timestamp_ns,
                   uint32_t* next_vsync_count);

 private:
  friend BASE;

  VSyncClient();
  explicit VSyncClient(long timeout_ms);

  VSyncClient(const VSyncClient&) = delete;
  void operator=(const VSyncClient&) = delete;
};

}  // namespace dvr
}  // namespace android

#endif  // ANDROID_DVR_VSYNC_CLIENT_H_
+65 −0
Original line number Original line Diff line number Diff line
#ifndef ANDROID_DVR_VSYNC_SERVICE_H_
#define ANDROID_DVR_VSYNC_SERVICE_H_

#include <binder/IInterface.h>

namespace android {
namespace dvr {

class IVsyncCallback : public IInterface {
 public:
  DECLARE_META_INTERFACE(VsyncCallback)

  enum {
    ON_VSYNC = IBinder::FIRST_CALL_TRANSACTION
  };

  virtual status_t onVsync(int64_t vsync_timestamp) = 0;
};

class BnVsyncCallback : public BnInterface<IVsyncCallback> {
 public:
  virtual status_t onTransact(uint32_t code, const Parcel& data,
                              Parcel* reply, uint32_t flags = 0);
};

// Register a callback with IVsyncService to be notified of vsync events and
// timestamps. There's also a shared memory vsync buffer defined in
// dvr_shared_buffers.h. IVsyncService has advantages over the vsync shared
// memory buffer that make it preferable in certain situations:
//
// 1. The shared memory buffer lifetime is controlled by VrCore. IVsyncService
// is always available as long as surface flinger is running.
//
// 2. IVsyncService will make a binder callback when a vsync event occurs. This
// allows the client to not write code to implement periodic "get the latest
// vsync" calls, which is necessary with the vsync shared memory buffer.
//
// 3. The IVsyncService provides the real vsync timestamp reported by hardware
// composer, whereas the vsync shared memory buffer only has predicted vsync
// times.
class IVsyncService : public IInterface {
public:
  DECLARE_META_INTERFACE(VsyncService)

  static const char* GetServiceName() { return "vrflinger_vsync"; }

  enum {
    REGISTER_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
    UNREGISTER_CALLBACK
  };

  virtual status_t registerCallback(const sp<IVsyncCallback> callback) = 0;
  virtual status_t unregisterCallback(const sp<IVsyncCallback> callback) = 0;
};

class BnVsyncService : public BnInterface<IVsyncService> {
 public:
  virtual status_t onTransact(uint32_t code, const Parcel& data,
                              Parcel* reply, uint32_t flags = 0);
};

}  // namespace dvr
}  // namespace android

#endif  // ANDROID_DVR_VSYNC_SERVICE_H_
+0 −76
Original line number Original line Diff line number Diff line
#include "include/private/dvr/vsync_client.h"

#include <log/log.h>

#include <pdx/default_transport/client_channel_factory.h>
#include <private/dvr/display_protocol.h>

using android::dvr::display::VSyncProtocol;
using android::pdx::Transaction;

namespace android {
namespace dvr {

VSyncClient::VSyncClient(long timeout_ms)
    : BASE(pdx::default_transport::ClientChannelFactory::Create(
               VSyncProtocol::kClientPath),
           timeout_ms) {}

VSyncClient::VSyncClient()
    : BASE(pdx::default_transport::ClientChannelFactory::Create(
          VSyncProtocol::kClientPath)) {}

int VSyncClient::Wait(int64_t* timestamp_ns) {
  auto status = InvokeRemoteMethod<VSyncProtocol::Wait>();
  if (!status) {
    ALOGE("VSyncClient::Wait: Failed to wait for vsync: %s",
          status.GetErrorMessage().c_str());
    return -status.error();
  }

  if (timestamp_ns != nullptr) {
    *timestamp_ns = status.get();
  }
  return 0;
}

int VSyncClient::GetFd() { return event_fd(); }

int VSyncClient::GetLastTimestamp(int64_t* timestamp_ns) {
  auto status = InvokeRemoteMethod<VSyncProtocol::GetLastTimestamp>();
  if (!status) {
    ALOGE("VSyncClient::GetLastTimestamp: Failed to get vsync timestamp: %s",
          status.GetErrorMessage().c_str());
    return -status.error();
  }
  *timestamp_ns = status.get();
  return 0;
}

int VSyncClient::GetSchedInfo(int64_t* vsync_period_ns, int64_t* timestamp_ns,
                              uint32_t* next_vsync_count) {
  if (!vsync_period_ns || !timestamp_ns || !next_vsync_count)
    return -EINVAL;

  auto status = InvokeRemoteMethod<VSyncProtocol::GetSchedInfo>();
  if (!status) {
    ALOGE("VSyncClient::GetSchedInfo:: Failed to get warp timestamp: %s",
          status.GetErrorMessage().c_str());
    return -status.error();
  }

  *vsync_period_ns = status.get().vsync_period_ns;
  *timestamp_ns = status.get().timestamp_ns;
  *next_vsync_count = status.get().next_vsync_count;
  return 0;
}

int VSyncClient::Acknowledge() {
  auto status = InvokeRemoteMethod<VSyncProtocol::Acknowledge>();
  ALOGE_IF(!status, "VSuncClient::Acknowledge: Failed to ack vsync because: %s",
           status.GetErrorMessage().c_str());
  return ReturnStatusOrError(status);
}

}  // namespace dvr
}  // namespace android
+146 −0
Original line number Original line Diff line number Diff line
#include "include/private/dvr/vsync_service.h"

#include <binder/Parcel.h>
#include <log/log.h>

namespace android {
namespace dvr {

status_t BnVsyncCallback::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
  switch (code) {
    case ON_VSYNC: {
      CHECK_INTERFACE(IVsyncCallback, data, reply);
      int64_t vsync_timestamp = 0;
      status_t result = data.readInt64(&vsync_timestamp);
      if (result != NO_ERROR) {
        ALOGE("onVsync failed to readInt64: %d", result);
        return result;
      }
      onVsync(vsync_timestamp);
      return NO_ERROR;
    }
    default: {
      return BBinder::onTransact(code, data, reply, flags);
    }
  }
}

class BpVsyncCallback : public BpInterface<IVsyncCallback> {
public:
  explicit BpVsyncCallback(const sp<IBinder>& impl)
      : BpInterface<IVsyncCallback>(impl) {}
  virtual ~BpVsyncCallback() {}

  virtual status_t onVsync(int64_t vsync_timestamp) {
    Parcel data, reply;
    status_t result = data.writeInterfaceToken(
        IVsyncCallback::getInterfaceDescriptor());
    if (result != NO_ERROR) {
      ALOGE("onVsync failed to writeInterfaceToken: %d", result);
      return result;
    }
    result = data.writeInt64(vsync_timestamp);
    if (result != NO_ERROR) {
      ALOGE("onVsync failed to writeInt64: %d", result);
      return result;
    }
    result = remote()->transact(
        BnVsyncCallback::ON_VSYNC, data, &reply, TF_ONE_WAY);
    if (result != NO_ERROR) {
      ALOGE("onVsync failed to transact: %d", result);
      return result;
    }
    return result;
  }
};

IMPLEMENT_META_INTERFACE(VsyncCallback, "android.dvr.IVsyncCallback");


status_t BnVsyncService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
  switch (code) {
    case REGISTER_CALLBACK: {
      CHECK_INTERFACE(IVsyncService, data, reply);
      sp<IBinder> callback;
      status_t result = data.readStrongBinder(&callback);
      if (result != NO_ERROR) {
        ALOGE("registerCallback failed to readStrongBinder: %d", result);
        return result;
      }
      registerCallback(interface_cast<IVsyncCallback>(callback));
      return NO_ERROR;
    }
    case UNREGISTER_CALLBACK: {
      CHECK_INTERFACE(IVsyncService, data, reply);
      sp<IBinder> callback;
      status_t result = data.readStrongBinder(&callback);
      if (result != NO_ERROR) {
        ALOGE("unregisterCallback failed to readStrongBinder: %d", result);
        return result;
      }
      unregisterCallback(interface_cast<IVsyncCallback>(callback));
      return NO_ERROR;
    }
    default: {
      return BBinder::onTransact(code, data, reply, flags);
    }
  }
}

class BpVsyncService : public BpInterface<IVsyncService> {
public:
  explicit BpVsyncService(const sp<IBinder>& impl)
      : BpInterface<IVsyncService>(impl) {}
  virtual ~BpVsyncService() {}

  virtual status_t registerCallback(const sp<IVsyncCallback> callback) {
    Parcel data, reply;
    status_t result = data.writeInterfaceToken(
        IVsyncService::getInterfaceDescriptor());
    if (result != NO_ERROR) {
      ALOGE("registerCallback failed to writeInterfaceToken: %d", result);
      return result;
    }
    result = data.writeStrongBinder(IInterface::asBinder(callback));
    if (result != NO_ERROR) {
      ALOGE("registerCallback failed to writeStrongBinder: %d", result);
      return result;
    }
    result = remote()->transact(
        BnVsyncService::REGISTER_CALLBACK, data, &reply);
    if (result != NO_ERROR) {
      ALOGE("registerCallback failed to transact: %d", result);
      return result;
    }
    return result;
  }

  virtual status_t unregisterCallback(const sp<IVsyncCallback> callback) {
    Parcel data, reply;
    status_t result = data.writeInterfaceToken(
        IVsyncService::getInterfaceDescriptor());
    if (result != NO_ERROR) {
      ALOGE("unregisterCallback failed to writeInterfaceToken: %d", result);
      return result;
    }
    result = data.writeStrongBinder(IInterface::asBinder(callback));
    if (result != NO_ERROR) {
      ALOGE("unregisterCallback failed to writeStrongBinder: %d", result);
      return result;
    }
    result = remote()->transact(
        BnVsyncService::UNREGISTER_CALLBACK, data, &reply);
    if (result != NO_ERROR) {
      ALOGE("unregisterCallback failed to transact: %d", result);
      return result;
    }
    return result;
  }
};

IMPLEMENT_META_INTERFACE(VsyncService, "android.dvr.IVsyncService");

}  // namespace dvr
}  // namespace android
Loading