Merge "Moved bugreport intents to the com.android.internal namespace."
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index aa32d6b..0fb207b 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -854,13 +854,16 @@
return open(file_name, flags, permissions);
}
-static bool set_permissions_and_ownership(int fd, bool is_public, int uid, const char* path) {
+static bool set_permissions_and_ownership(
+ int fd, bool is_public, int uid, const char* path, bool is_secondary_dex) {
+ // Primary apks are owned by the system. Secondary dex files are owned by the app.
+ int owning_uid = is_secondary_dex ? uid : AID_SYSTEM;
if (fchmod(fd,
S_IRUSR|S_IWUSR|S_IRGRP |
(is_public ? S_IROTH : 0)) < 0) {
ALOGE("installd cannot chmod '%s' during dexopt\n", path);
return false;
- } else if (fchown(fd, AID_SYSTEM, uid) < 0) {
+ } else if (fchown(fd, owning_uid, uid) < 0) {
ALOGE("installd cannot chown '%s' during dexopt\n", path);
return false;
}
@@ -1009,10 +1012,11 @@
// (re)Creates the app image if needed.
Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, bool profile_guided,
- bool is_public, int uid) {
+ bool is_public, int uid, bool is_secondary_dex) {
// Use app images only if it is enabled (by a set image format) and we are compiling
// profile-guided (so the app image doesn't conservatively contain all classes).
- if (!profile_guided) {
+ // Note that we don't create an image for secondary dex files.
+ if (is_secondary_dex || !profile_guided) {
return Dex2oatFileWrapper();
}
@@ -1043,7 +1047,7 @@
}
}
} else if (!set_permissions_and_ownership(
- wrapper_fd.get(), is_public, uid, image_path.c_str())) {
+ wrapper_fd.get(), is_public, uid, image_path.c_str(), is_secondary_dex)) {
ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str());
wrapper_fd.reset(-1);
}
@@ -1101,7 +1105,7 @@
// Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
// out_vdex_wrapper_fd. Returns true for success or false in case of errors.
bool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_needed,
- const char* instruction_set, bool is_public, int uid,
+ const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
Dex2oatFileWrapper* in_vdex_wrapper_fd,
Dex2oatFileWrapper* out_vdex_wrapper_fd) {
CHECK(in_vdex_wrapper_fd != nullptr);
@@ -1164,7 +1168,7 @@
}
}
if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
- out_vdex_path_str.c_str())) {
+ out_vdex_path_str.c_str(), is_secondary_dex)) {
ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str());
return false;
}
@@ -1187,7 +1191,8 @@
[out_oat_path_str]() { unlink(out_oat_path_str.c_str()); });
if (wrapper_fd.get() < 0) {
PLOG(ERROR) << "installd cannot open output during dexopt" << out_oat_path;
- } else if (!set_permissions_and_ownership(wrapper_fd.get(), is_public, uid, out_oat_path)) {
+ } else if (!set_permissions_and_ownership(
+ wrapper_fd.get(), is_public, uid, out_oat_path, is_secondary_dex)) {
ALOGE("installd cannot set owner '%s' for output during dexopt\n", out_oat_path);
wrapper_fd.reset(-1);
}
@@ -1445,7 +1450,7 @@
Dex2oatFileWrapper in_vdex_fd;
Dex2oatFileWrapper out_vdex_fd;
if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid,
- &in_vdex_fd, &out_vdex_fd)) {
+ is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
return -1;
}
@@ -1454,7 +1459,7 @@
// Create the app image file if needed.
Dex2oatFileWrapper image_fd =
- maybe_open_app_image(out_oat_path, profile_guided, is_public, uid);
+ maybe_open_app_image(out_oat_path, profile_guided, is_public, uid, is_secondary_dex);
// Open the reference profile if needed.
Dex2oatFileWrapper reference_profile_fd =
diff --git a/include/audiomanager/IPlayer.h b/include/audiomanager/IPlayer.h
index 94afae5..de5c1c7 100644
--- a/include/audiomanager/IPlayer.h
+++ b/include/audiomanager/IPlayer.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <media/VolumeShaper.h>
#include <utils/RefBase.h>
#include <utils/Errors.h>
#include <binder/IInterface.h>
@@ -45,6 +46,9 @@
virtual void setStartDelayMs(int delayMs) = 0;
+ virtual void applyVolumeShaper(
+ const sp<VolumeShaper::Configuration>& configuration,
+ const sp<VolumeShaper::Operation>& operation) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 46ca2c2..9e1ae94 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -95,6 +95,11 @@
std::shared_ptr<FenceTime> releaseFence{FenceTime::NO_FENCE};
};
+struct CompositorTiming {
+ nsecs_t deadline{0};
+ nsecs_t interval{16666667};
+ nsecs_t presentLatency{0};
+};
// A short history of frames that are synchronized between the consumer and
// producer via deltas.
@@ -111,6 +116,8 @@
protected:
std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames;
+
+ CompositorTiming mCompositorTiming;
};
@@ -119,6 +126,16 @@
public:
~ProducerFrameEventHistory() override;
+ // Public for testing.
+ static nsecs_t snapToNextTick(
+ nsecs_t timestamp, nsecs_t tickPhase, nsecs_t tickInterval);
+
+ nsecs_t getNextCompositeDeadline(const nsecs_t now) const;
+ nsecs_t getCompositeInterval() const { return mCompositorTiming.interval; }
+ nsecs_t getCompositeToPresentLatency() const {
+ return mCompositorTiming.presentLatency;
+ }
+
// virtual for testing.
virtual void updateAcquireFence(
uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire);
@@ -189,12 +206,15 @@
public:
~ConsumerFrameEventHistory() override;
+ void initializeCompositorTiming(const CompositorTiming& compositorTiming);
+
void addQueue(const NewFrameEventsEntry& newEntry);
void addLatch(uint64_t frameNumber, nsecs_t latchTime);
void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime);
void addPostComposition(uint64_t frameNumber,
const std::shared_ptr<FenceTime>& gpuCompositionDone,
- const std::shared_ptr<FenceTime>& displayPresent);
+ const std::shared_ptr<FenceTime>& displayPresent,
+ const CompositorTiming& compositorTiming);
void addRetire(uint64_t frameNumber,
const std::shared_ptr<FenceTime>& displayRetire);
void addRelease(uint64_t frameNumber, nsecs_t dequeueReadyTime,
@@ -244,7 +264,7 @@
size_t& count);
private:
- static size_t minFlattenedSize();
+ static constexpr size_t minFlattenedSize();
size_t mIndex{0};
uint64_t mFrameNumber{0};
@@ -306,9 +326,10 @@
size_t& count);
private:
- static size_t minFlattenedSize();
+ static constexpr size_t minFlattenedSize();
std::vector<FrameEventsDelta> mDeltas;
+ CompositorTiming mCompositorTiming;
};
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 966e70d..a3c2bfa 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -135,12 +135,18 @@
status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence, float outTransformMatrix[16]);
+ status_t getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration);
+
/* Enables or disables frame timestamp tracking. It is disabled by default
* to avoid overhead during queue and dequeue for applications that don't
* need the feature. If disabled, calls to getFrameTimestamps will fail.
*/
void enableFrameTimestamps(bool enable);
+ status_t getCompositorTiming(
+ nsecs_t* compositeDeadline, nsecs_t* compositeInterval,
+ nsecs_t* compositeToPresentLatency);
+
// See IGraphicBufferProducer::getFrameTimestamps
status_t getFrameTimestamps(uint64_t frameNumber,
nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
@@ -148,7 +154,6 @@
nsecs_t* outLastRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
nsecs_t* outDisplayPresentTime, nsecs_t* outDisplayRetireTime,
nsecs_t* outDequeueReadyTime, nsecs_t* outReleaseTime);
- status_t getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration);
status_t getUniqueId(uint64_t* outId) const;
@@ -157,6 +162,7 @@
// Virtual for testing.
virtual sp<ISurfaceComposer> composerService() const;
+ virtual nsecs_t now() const;
private:
// can't be copied
@@ -204,10 +210,11 @@
int dispatchSetSurfaceDamage(va_list args);
int dispatchSetSharedBufferMode(va_list args);
int dispatchSetAutoRefresh(va_list args);
+ int dispatchGetDisplayRefreshCycleDuration(va_list args);
int dispatchGetNextFrameId(va_list args);
int dispatchEnableFrameTimestamps(va_list args);
+ int dispatchGetCompositorTiming(va_list args);
int dispatchGetFrameTimestamps(va_list args);
- int dispatchGetDisplayRefreshCycleDuration(va_list args);
protected:
virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index 73537bf..a6fa38a 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -235,6 +235,23 @@
ProducerFrameEventHistory::~ProducerFrameEventHistory() = default;
+nsecs_t ProducerFrameEventHistory::snapToNextTick(
+ nsecs_t timestamp, nsecs_t tickPhase, nsecs_t tickInterval) {
+ nsecs_t tickOffset = (tickPhase - timestamp) % tickInterval;
+ // Integer modulo rounds towards 0 and not -inf before taking the remainder,
+ // so adjust the offset if it is negative.
+ if (tickOffset < 0) {
+ tickOffset += tickInterval;
+ }
+ return timestamp + tickOffset;
+}
+
+nsecs_t ProducerFrameEventHistory::getNextCompositeDeadline(
+ const nsecs_t now) const{
+ return snapToNextTick(
+ now, mCompositorTiming.deadline, mCompositorTiming.interval);
+}
+
void ProducerFrameEventHistory::updateAcquireFence(
uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire) {
FrameEvents* frame = getFrame(frameNumber, &mAcquireOffset);
@@ -256,6 +273,8 @@
void ProducerFrameEventHistory::applyDelta(
const FrameEventHistoryDelta& delta) {
+ mCompositorTiming = delta.mCompositorTiming;
+
for (auto& d : delta.mDeltas) {
// Avoid out-of-bounds access.
if (d.mIndex >= mFrames.size()) {
@@ -346,6 +365,11 @@
ConsumerFrameEventHistory::~ConsumerFrameEventHistory() = default;
+void ConsumerFrameEventHistory::initializeCompositorTiming(
+ const CompositorTiming& compositorTiming) {
+ mCompositorTiming = compositorTiming;
+}
+
void ConsumerFrameEventHistory::addQueue(const NewFrameEventsEntry& newEntry) {
// Overwrite all fields of the frame with default values unless set here.
FrameEvents newTimestamps;
@@ -393,7 +417,10 @@
void ConsumerFrameEventHistory::addPostComposition(uint64_t frameNumber,
const std::shared_ptr<FenceTime>& gpuCompositionDone,
- const std::shared_ptr<FenceTime>& displayPresent) {
+ const std::shared_ptr<FenceTime>& displayPresent,
+ const CompositorTiming& compositorTiming) {
+ mCompositorTiming = compositorTiming;
+
FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
if (frame == nullptr) {
ALOGE_IF(mProducerWantsEvents,
@@ -450,6 +477,8 @@
void ConsumerFrameEventHistory::getAndResetDelta(
FrameEventHistoryDelta* delta) {
+ delta->mCompositorTiming = mCompositorTiming;
+
// Write these in order of frame number so that it is easy to
// add them to a FenceTimeline in the proper order producer side.
delta->mDeltas.reserve(mFramesDirty.size());
@@ -499,9 +528,8 @@
}
}
-size_t FrameEventsDelta::minFlattenedSize() {
- constexpr size_t min =
- sizeof(FrameEventsDelta::mFrameNumber) +
+constexpr size_t FrameEventsDelta::minFlattenedSize() {
+ return sizeof(FrameEventsDelta::mFrameNumber) +
sizeof(uint8_t) + // mIndex
sizeof(uint8_t) + // mAddPostCompositeCalled
sizeof(uint8_t) + // mAddRetireCalled
@@ -512,7 +540,6 @@
sizeof(FrameEventsDelta::mFirstRefreshStartTime) +
sizeof(FrameEventsDelta::mLastRefreshStartTime) +
sizeof(FrameEventsDelta::mDequeueReadyTime);
- return min;
}
// Flattenable implementation
@@ -618,6 +645,8 @@
FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
FrameEventHistoryDelta&& src) {
+ mCompositorTiming = src.mCompositorTiming;
+
if (CC_UNLIKELY(!mDeltas.empty())) {
ALOGE("FrameEventHistoryDelta: Clobbering history.");
}
@@ -626,8 +655,9 @@
return *this;
}
-size_t FrameEventHistoryDelta::minFlattenedSize() {
- return sizeof(uint32_t);
+constexpr size_t FrameEventHistoryDelta::minFlattenedSize() {
+ return sizeof(uint32_t) + // mDeltas.size()
+ sizeof(mCompositorTiming);
}
size_t FrameEventHistoryDelta::getFlattenedSize() const {
@@ -654,6 +684,8 @@
return NO_MEMORY;
}
+ FlattenableUtils::write(buffer, size, mCompositorTiming);
+
FlattenableUtils::write(
buffer, size, static_cast<uint32_t>(mDeltas.size()));
for (auto& d : mDeltas) {
@@ -671,6 +703,8 @@
return NO_MEMORY;
}
+ FlattenableUtils::read(buffer, size, mCompositorTiming);
+
uint32_t deltaCount = 0;
FlattenableUtils::read(buffer, size, deltaCount);
if (deltaCount > FrameEventHistory::MAX_FRAME_HISTORY) {
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index d1f9f6a..d285ef0 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -100,6 +100,10 @@
return ComposerService::getComposerService();
}
+nsecs_t Surface::now() const {
+ return systemTime();
+}
+
sp<IGraphicBufferProducer> Surface::getIGraphicBufferProducer() const {
return mGraphicBufferProducer;
}
@@ -142,11 +146,51 @@
outTransformMatrix);
}
+status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) {
+ ATRACE_CALL();
+
+ DisplayStatInfo stats;
+ status_t err = composerService()->getDisplayStats(NULL, &stats);
+
+ *outRefreshDuration = stats.vsyncPeriod;
+
+ return NO_ERROR;
+}
+
void Surface::enableFrameTimestamps(bool enable) {
Mutex::Autolock lock(mMutex);
+ // If going from disabled to enabled, get the initial values for
+ // compositor and display timing.
+ if (!mEnableFrameTimestamps && enable) {
+ FrameEventHistoryDelta delta;
+ mGraphicBufferProducer->getFrameTimestamps(&delta);
+ mFrameEventHistory->applyDelta(delta);
+ }
mEnableFrameTimestamps = enable;
}
+status_t Surface::getCompositorTiming(
+ nsecs_t* compositeDeadline, nsecs_t* compositeInterval,
+ nsecs_t* compositeToPresentLatency) {
+ Mutex::Autolock lock(mMutex);
+ if (!mEnableFrameTimestamps) {
+ return INVALID_OPERATION;
+ }
+
+ if (compositeDeadline != nullptr) {
+ *compositeDeadline =
+ mFrameEventHistory->getNextCompositeDeadline(now());
+ }
+ if (compositeInterval != nullptr) {
+ *compositeInterval = mFrameEventHistory->getCompositeInterval();
+ }
+ if (compositeToPresentLatency != nullptr) {
+ *compositeToPresentLatency =
+ mFrameEventHistory->getCompositeToPresentLatency();
+ }
+ return NO_ERROR;
+}
+
static bool checkConsumerForUpdates(
const FrameEvents* e, const uint64_t lastFrameNumber,
const nsecs_t* outLatchTime,
@@ -260,16 +304,6 @@
return NO_ERROR;
}
-status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) {
- ATRACE_CALL();
-
- DisplayStatInfo stats;
- status_t err = composerService()->getDisplayStats(NULL, &stats);
-
- *outRefreshDuration = stats.vsyncPeriod;
-
- return NO_ERROR;
-}
int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
Surface* c = getSelf(window);
@@ -831,18 +865,21 @@
case NATIVE_WINDOW_SET_AUTO_REFRESH:
res = dispatchSetAutoRefresh(args);
break;
+ case NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION:
+ res = dispatchGetDisplayRefreshCycleDuration(args);
+ break;
case NATIVE_WINDOW_GET_NEXT_FRAME_ID:
res = dispatchGetNextFrameId(args);
break;
case NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS:
res = dispatchEnableFrameTimestamps(args);
break;
+ case NATIVE_WINDOW_GET_COMPOSITOR_TIMING:
+ res = dispatchGetCompositorTiming(args);
+ break;
case NATIVE_WINDOW_GET_FRAME_TIMESTAMPS:
res = dispatchGetFrameTimestamps(args);
break;
- case NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION:
- res = dispatchGetDisplayRefreshCycleDuration(args);
- break;
default:
res = NAME_NOT_FOUND;
break;
@@ -963,6 +1000,11 @@
return setAutoRefresh(autoRefresh);
}
+int Surface::dispatchGetDisplayRefreshCycleDuration(va_list args) {
+ nsecs_t* outRefreshDuration = va_arg(args, int64_t*);
+ return getDisplayRefreshCycleDuration(outRefreshDuration);
+}
+
int Surface::dispatchGetNextFrameId(va_list args) {
uint64_t* nextFrameId = va_arg(args, uint64_t*);
*nextFrameId = getNextFrameNumber();
@@ -975,6 +1017,14 @@
return NO_ERROR;
}
+int Surface::dispatchGetCompositorTiming(va_list args) {
+ nsecs_t* compositeDeadline = va_arg(args, int64_t*);
+ nsecs_t* compositeInterval = va_arg(args, int64_t*);
+ nsecs_t* compositeToPresentLatency = va_arg(args, int64_t*);
+ return getCompositorTiming(compositeDeadline, compositeInterval,
+ compositeToPresentLatency);
+}
+
int Surface::dispatchGetFrameTimestamps(va_list args) {
uint64_t frameId = va_arg(args, uint64_t);
nsecs_t* outRequestedPresentTime = va_arg(args, int64_t*);
@@ -994,11 +1044,6 @@
outDisplayRetireTime, outDequeueReadyTime, outReleaseTime);
}
-int Surface::dispatchGetDisplayRefreshCycleDuration(va_list args) {
- nsecs_t* outRefreshDuration = va_arg(args, int64_t*);
- return getDisplayRefreshCycleDuration(outRefreshDuration);
-}
-
int Surface::connect(int api) {
static sp<IProducerListener> listener = new DummyProducerListener();
return connect(api, listener);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 3f56665..5298027 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -479,8 +479,17 @@
return mFakeSurfaceComposer;
}
+ nsecs_t now() const override {
+ return mNow;
+ }
+
+ void setNow(nsecs_t now) {
+ mNow = now;
+ }
+
public:
sp<FakeSurfaceComposer> mFakeSurfaceComposer;
+ nsecs_t mNow = 0;
// mFrameEventHistory owns the instance of FakeProducerFrameEventHistory,
// but this raw pointer gives access to test functionality.
@@ -500,10 +509,12 @@
struct RefreshEvents {
RefreshEvents(FenceToFenceTimeMap& fenceMap, nsecs_t refreshStart)
- : mFenceMap(fenceMap),
- kStartTime(refreshStart + 1),
- kGpuCompositionDoneTime(refreshStart + 2),
- kPresentTime(refreshStart + 3) {}
+ : mFenceMap(fenceMap),
+ kCompositorTiming(
+ {refreshStart, refreshStart + 1, refreshStart + 2 }),
+ kStartTime(refreshStart + 3),
+ kGpuCompositionDoneTime(refreshStart + 4),
+ kPresentTime(refreshStart + 5) {}
void signalPostCompositeFences() {
mFenceMap.signalAllForTest(
@@ -516,6 +527,8 @@
FenceAndFenceTime mGpuCompositionDone { mFenceMap };
FenceAndFenceTime mPresent { mFenceMap };
+ const CompositorTiming kCompositorTiming;
+
const nsecs_t kStartTime;
const nsecs_t kGpuCompositionDoneTime;
const nsecs_t kPresentTime;
@@ -592,6 +605,12 @@
native_window_set_buffer_count(mWindow.get(), 4);
}
+ void disableFrameTimestamps() {
+ mFakeConsumer->mGetFrameTimestampsEnabled = false;
+ native_window_enable_frame_timestamps(mWindow.get(), 0);
+ mFrameTimestampsEnabled = false;
+ }
+
void enableFrameTimestamps() {
mFakeConsumer->mGetFrameTimestampsEnabled = true;
native_window_enable_frame_timestamps(mWindow.get(), 1);
@@ -681,7 +700,8 @@
oldFrame->mRefreshes[2].mGpuCompositionDone.mFenceTime :
FenceTime::NO_FENCE;
mCfeh->addPostComposition(nOldFrame, gpuDoneFenceTime,
- oldFrame->mRefreshes[2].mPresent.mFenceTime);
+ oldFrame->mRefreshes[2].mPresent.mFenceTime,
+ oldFrame->mRefreshes[2].kCompositorTiming);
}
// Latch the new frame.
@@ -698,7 +718,8 @@
std::shared_ptr<FenceTime>(oldFrame->mRelease.mFenceTime));
}
mCfeh->addPostComposition(nNewFrame, gpuDoneFenceTime,
- newFrame->mRefreshes[0].mPresent.mFenceTime);
+ newFrame->mRefreshes[0].mPresent.mFenceTime,
+ newFrame->mRefreshes[0].kCompositorTiming);
// Retire the previous buffer just after compositing the new buffer.
if (oldFrame != nullptr) {
@@ -710,7 +731,8 @@
newFrame->mRefreshes[1].mGpuCompositionDone.mFenceTime :
FenceTime::NO_FENCE;
mCfeh->addPostComposition(nNewFrame, gpuDoneFenceTime,
- newFrame->mRefreshes[1].mPresent.mFenceTime);
+ newFrame->mRefreshes[1].mPresent.mFenceTime,
+ newFrame->mRefreshes[1].kCompositorTiming);
}
void QueryPresentRetireSupported(
@@ -740,7 +762,8 @@
int64_t outDequeueReadyTime = -1;
int64_t outReleaseTime = -1;
- FrameEvents mFrames[2] { { mFenceMap, 1000 }, { mFenceMap, 2000 } };
+ FrameEvents mFrames[3] {
+ { mFenceMap, 1000 }, { mFenceMap, 2000 }, { mFenceMap, 3000 } };
};
@@ -773,25 +796,55 @@
int result = getAllFrameTimestamps(fId);
EXPECT_EQ(INVALID_OPERATION, result);
EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
+
+ // Verify compositor timing query fails.
+ nsecs_t compositeDeadline = 0;
+ nsecs_t compositeInterval = 0;
+ nsecs_t compositeToPresentLatency = 0;
+ result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(INVALID_OPERATION, result);
}
// This test verifies that the frame timestamps are retrieved if explicitly
// enabled via native_window_enable_frame_timestamps.
TEST_F(GetFrameTimestampsTest, EnabledSimple) {
+ CompositorTiming initialCompositorTiming {
+ 1000000000, // 1s deadline
+ 16666667, // 16ms interval
+ 50000000, // 50ms present latency
+ };
+ mCfeh->initializeCompositorTiming(initialCompositorTiming);
+
enableFrameTimestamps();
+ // Verify the compositor timing query gets the initial compositor values
+ // after timststamps are enabled; even before the first frame is queued
+ // or dequeued.
+ nsecs_t compositeDeadline = 0;
+ nsecs_t compositeInterval = 0;
+ nsecs_t compositeToPresentLatency = 0;
+ mSurface->setNow(initialCompositorTiming.deadline - 1);
+ int result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline);
+ EXPECT_EQ(initialCompositorTiming.interval, compositeInterval);
+ EXPECT_EQ(initialCompositorTiming.presentLatency,
+ compositeToPresentLatency);
+
int fence;
ANativeWindowBuffer* buffer;
EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount);
- EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(1, mFakeConsumer->mGetFrameTimestampsCount);
const uint64_t fId1 = getNextFrameId();
// Verify getFrameTimestamps is piggybacked on dequeue.
ASSERT_EQ(NO_ERROR, mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence));
EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount);
- EXPECT_EQ(1, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(2, mFakeConsumer->mGetFrameTimestampsCount);
NewFrameEventsEntry f1;
f1.frameNumber = 1;
@@ -808,13 +861,13 @@
ASSERT_EQ(NO_ERROR, mWindow->queueBuffer(mWindow.get(), buffer, fence));
EXPECT_EQ(1, mFakeConsumer->mAddFrameTimestampsCount);
EXPECT_EQ(1u, mFakeConsumer->mLastAddedFrameNumber);
- EXPECT_EQ(2, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(3, mFakeConsumer->mGetFrameTimestampsCount);
// Verify queries for timestamps that the producer doesn't know about
// triggers a call to see if the consumer has any new timestamps.
- int result = getAllFrameTimestamps(fId1);
+ result = getAllFrameTimestamps(fId1);
EXPECT_EQ(NO_ERROR, result);
- EXPECT_EQ(3, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(4, mFakeConsumer->mGetFrameTimestampsCount);
}
void GetFrameTimestampsTest::QueryPresentRetireSupported(
@@ -842,6 +895,234 @@
QueryPresentRetireSupported(false, true);
}
+TEST_F(GetFrameTimestampsTest, SnapToNextTickBasic) {
+ nsecs_t phase = 4000;
+ nsecs_t interval = 1000;
+
+ // Timestamp in previous interval.
+ nsecs_t timestamp = 3500;
+ EXPECT_EQ(4000, ProducerFrameEventHistory::snapToNextTick(
+ timestamp, phase, interval));
+
+ // Timestamp in next interval.
+ timestamp = 4500;
+ EXPECT_EQ(5000, ProducerFrameEventHistory::snapToNextTick(
+ timestamp, phase, interval));
+
+ // Timestamp multiple intervals before.
+ timestamp = 2500;
+ EXPECT_EQ(3000, ProducerFrameEventHistory::snapToNextTick(
+ timestamp, phase, interval));
+
+ // Timestamp multiple intervals after.
+ timestamp = 6500;
+ EXPECT_EQ(7000, ProducerFrameEventHistory::snapToNextTick(
+ timestamp, phase, interval));
+
+ // Timestamp on previous interval.
+ timestamp = 3000;
+ EXPECT_EQ(3000, ProducerFrameEventHistory::snapToNextTick(
+ timestamp, phase, interval));
+
+ // Timestamp on next interval.
+ timestamp = 5000;
+ EXPECT_EQ(5000, ProducerFrameEventHistory::snapToNextTick(
+ timestamp, phase, interval));
+
+ // Timestamp equal to phase.
+ timestamp = 4000;
+ EXPECT_EQ(4000, ProducerFrameEventHistory::snapToNextTick(
+ timestamp, phase, interval));
+}
+
+// int(big_timestamp / interval) < 0, which can cause a crash or invalid result
+// if the number of intervals elapsed is internally stored in an int.
+TEST_F(GetFrameTimestampsTest, SnapToNextTickOverflow) {
+ nsecs_t phase = 0;
+ nsecs_t interval = 4000;
+ nsecs_t big_timestamp = 8635916564000;
+ int32_t intervals = big_timestamp / interval;
+
+ EXPECT_LT(intervals, 0);
+ EXPECT_EQ(8635916564000, ProducerFrameEventHistory::snapToNextTick(
+ big_timestamp, phase, interval));
+ EXPECT_EQ(8635916564000, ProducerFrameEventHistory::snapToNextTick(
+ big_timestamp, big_timestamp, interval));
+}
+
+// This verifies the compositor timing is updated by refresh events
+// and piggy backed on a queue, dequeue, and enabling of timestamps..
+TEST_F(GetFrameTimestampsTest, CompositorTimingUpdatesBasic) {
+ CompositorTiming initialCompositorTiming {
+ 1000000000, // 1s deadline
+ 16666667, // 16ms interval
+ 50000000, // 50ms present latency
+ };
+ mCfeh->initializeCompositorTiming(initialCompositorTiming);
+
+ enableFrameTimestamps();
+
+ // We get the initial values before any frames are submitted.
+ nsecs_t compositeDeadline = 0;
+ nsecs_t compositeInterval = 0;
+ nsecs_t compositeToPresentLatency = 0;
+ mSurface->setNow(initialCompositorTiming.deadline - 1);
+ int result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline);
+ EXPECT_EQ(initialCompositorTiming.interval, compositeInterval);
+ EXPECT_EQ(initialCompositorTiming.presentLatency,
+ compositeToPresentLatency);
+
+ const uint64_t fId1 = getNextFrameId();
+ dequeueAndQueue(0);
+ addFrameEvents(true, NO_FRAME_INDEX, 0);
+
+ // Still get the initial values because the frame events for frame 0
+ // didn't get a chance to piggyback on a queue or dequeue yet.
+ result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline);
+ EXPECT_EQ(initialCompositorTiming.interval, compositeInterval);
+ EXPECT_EQ(initialCompositorTiming.presentLatency,
+ compositeToPresentLatency);
+
+ const uint64_t fId2 = getNextFrameId();
+ dequeueAndQueue(1);
+ addFrameEvents(true, 0, 1);
+
+ // Now expect the composite values associated with frame 1.
+ mSurface->setNow(mFrames[0].mRefreshes[1].kCompositorTiming.deadline);
+ result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[0].mRefreshes[1].kCompositorTiming.deadline,
+ compositeDeadline);
+ EXPECT_EQ(mFrames[0].mRefreshes[1].kCompositorTiming.interval,
+ compositeInterval);
+ EXPECT_EQ(mFrames[0].mRefreshes[1].kCompositorTiming.presentLatency,
+ compositeToPresentLatency);
+
+ dequeueAndQueue(2);
+ addFrameEvents(true, 1, 2);
+
+ // Now expect the composite values associated with frame 2.
+ mSurface->setNow(mFrames[1].mRefreshes[1].kCompositorTiming.deadline);
+ result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[1].mRefreshes[1].kCompositorTiming.deadline,
+ compositeDeadline);
+ EXPECT_EQ(mFrames[1].mRefreshes[1].kCompositorTiming.interval,
+ compositeInterval);
+ EXPECT_EQ(mFrames[1].mRefreshes[1].kCompositorTiming.presentLatency,
+ compositeToPresentLatency);
+
+ // Re-enabling frame timestamps should get the latest values.
+ disableFrameTimestamps();
+ enableFrameTimestamps();
+
+ // Now expect the composite values associated with frame 3.
+ mSurface->setNow(mFrames[2].mRefreshes[1].kCompositorTiming.deadline);
+ result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(mFrames[2].mRefreshes[1].kCompositorTiming.deadline,
+ compositeDeadline);
+ EXPECT_EQ(mFrames[2].mRefreshes[1].kCompositorTiming.interval,
+ compositeInterval);
+ EXPECT_EQ(mFrames[2].mRefreshes[1].kCompositorTiming.presentLatency,
+ compositeToPresentLatency);
+}
+
+// This verifies the compositor deadline properly snaps to the the next
+// deadline based on the current time.
+TEST_F(GetFrameTimestampsTest, CompositorTimingDeadlineSnaps) {
+ CompositorTiming initialCompositorTiming {
+ 1000000000, // 1s deadline
+ 16666667, // 16ms interval
+ 50000000, // 50ms present latency
+ };
+ mCfeh->initializeCompositorTiming(initialCompositorTiming);
+
+ enableFrameTimestamps();
+
+ nsecs_t compositeDeadline = 0;
+ nsecs_t compositeInterval = 0;
+ nsecs_t compositeToPresentLatency = 0;
+
+ // A "now" just before the deadline snaps to the deadline.
+ mSurface->setNow(initialCompositorTiming.deadline - 1);
+ int result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(NO_ERROR, result);
+ EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline);
+ nsecs_t expectedDeadline = initialCompositorTiming.deadline;
+ EXPECT_EQ(expectedDeadline, compositeDeadline);
+
+ const uint64_t fId1 = getNextFrameId();
+ dequeueAndQueue(0);
+ addFrameEvents(true, NO_FRAME_INDEX, 0);
+
+ // A "now" just after the deadline snaps properly.
+ mSurface->setNow(initialCompositorTiming.deadline + 1);
+ result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(NO_ERROR, result);
+ expectedDeadline =
+ initialCompositorTiming.deadline +initialCompositorTiming.interval;
+ EXPECT_EQ(expectedDeadline, compositeDeadline);
+
+ const uint64_t fId2 = getNextFrameId();
+ dequeueAndQueue(1);
+ addFrameEvents(true, 0, 1);
+
+ // A "now" just after the next interval snaps properly.
+ mSurface->setNow(
+ mFrames[0].mRefreshes[1].kCompositorTiming.deadline +
+ mFrames[0].mRefreshes[1].kCompositorTiming.interval + 1);
+ result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(NO_ERROR, result);
+ expectedDeadline =
+ mFrames[0].mRefreshes[1].kCompositorTiming.deadline +
+ mFrames[0].mRefreshes[1].kCompositorTiming.interval * 2;
+ EXPECT_EQ(expectedDeadline, compositeDeadline);
+
+ dequeueAndQueue(2);
+ addFrameEvents(true, 1, 2);
+
+ // A "now" over 1 interval before the deadline snaps properly.
+ mSurface->setNow(
+ mFrames[1].mRefreshes[1].kCompositorTiming.deadline -
+ mFrames[1].mRefreshes[1].kCompositorTiming.interval - 1);
+ result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(NO_ERROR, result);
+ expectedDeadline =
+ mFrames[1].mRefreshes[1].kCompositorTiming.deadline -
+ mFrames[1].mRefreshes[1].kCompositorTiming.interval;
+ EXPECT_EQ(expectedDeadline, compositeDeadline);
+
+ // Re-enabling frame timestamps should get the latest values.
+ disableFrameTimestamps();
+ enableFrameTimestamps();
+
+ // A "now" over 2 intervals before the deadline snaps properly.
+ mSurface->setNow(
+ mFrames[2].mRefreshes[1].kCompositorTiming.deadline -
+ mFrames[2].mRefreshes[1].kCompositorTiming.interval * 2 - 1);
+ result = native_window_get_compositor_timing(mWindow.get(),
+ &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+ EXPECT_EQ(NO_ERROR, result);
+ expectedDeadline =
+ mFrames[2].mRefreshes[1].kCompositorTiming.deadline -
+ mFrames[2].mRefreshes[1].kCompositorTiming.interval * 2;
+ EXPECT_EQ(expectedDeadline, compositeDeadline);
+}
+
// This verifies the timestamps recorded in the consumer's
// FrameTimestampsHistory are properly retrieved by the producer for the
// correct frames.
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 6485ae5..6572cab 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -632,24 +632,31 @@
#ifndef EGL_ANDROID_get_frame_timestamps
#define EGL_ANDROID_get_frame_timestamps 1
#define EGL_TIMESTAMPS_ANDROID 0x314D
-#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x314E
-#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F
-#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3150
-#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3151
-#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3152
-#define EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3153
-#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3154
-#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3155
-#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3156
-#define EGL_READS_DONE_TIME_ANDROID 0x3157
+#define EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
+#define EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
+#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
+#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
+#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
+#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
+#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
+#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
+#define EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3156
+#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
+#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3158
+#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3159
+#define EGL_READS_DONE_TIME_ANDROID 0x315A
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
+EGLAPI EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
+EGLAPI EGLBoolean eglGetCompositorTimingSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint name);
EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
-EGLAPI EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
+EGLAPI EGLBoolean eglGetFrameTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
#else
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETNEXTFRAMEIDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCOMPOSITORTIMINGANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCOMPOSITORTIMINGSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint name);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYTIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
#endif
#endif
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 2d02b72..4681b89 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -56,8 +56,6 @@
using namespace android;
-#define ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS 0
-
// ----------------------------------------------------------------------------
namespace android {
@@ -88,9 +86,7 @@
"EGL_KHR_swap_buffers_with_damage "
"EGL_ANDROID_create_native_client_buffer "
"EGL_ANDROID_front_buffer_auto_refresh "
-#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
"EGL_ANDROID_get_frame_timestamps "
-#endif
;
extern char const * const gExtensionString =
"EGL_KHR_image " // mandatory
@@ -218,10 +214,14 @@
// EGL_ANDROID_get_frame_timestamps
{ "eglGetNextFrameIdANDROID",
(__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID },
+ { "eglGetCompositorTimingANDROID",
+ (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID },
+ { "eglGetCompositorTimingSupportedANDROID",
+ (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID },
{ "eglGetFrameTimestampsANDROID",
(__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
- { "eglQueryTimestampSupportedANDROID",
- (__eglMustCastToProperFunctionPointerType)&eglQueryTimestampSupportedANDROID },
+ { "eglGetFrameTimestampSupportedANDROID",
+ (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID },
};
/*
@@ -1242,7 +1242,6 @@
setError(EGL_BAD_SURFACE, EGL_FALSE);
}
-#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
if (attribute == EGL_TIMESTAMPS_ANDROID) {
if (!s->win.get()) {
return setError(EGL_BAD_SURFACE, EGL_FALSE);
@@ -1252,7 +1251,6 @@
return (err == NO_ERROR) ? EGL_TRUE :
setError(EGL_BAD_SURFACE, EGL_FALSE);
}
-#endif
if (s->cnx->egl.eglSurfaceAttrib) {
return s->cnx->egl.eglSurfaceAttrib(
@@ -2084,6 +2082,95 @@
return EGL_TRUE;
}
+EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface,
+ EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) {
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ }
+
+ SurfaceRef _s(dp.get(), surface);
+ if (!_s.get()) {
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ egl_surface_t const * const s = get_surface(surface);
+
+ if (!s->win.get()) {
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ nsecs_t* compositeDeadline = nullptr;
+ nsecs_t* compositeInterval = nullptr;
+ nsecs_t* compositeToPresentLatency = nullptr;
+
+ for (int i = 0; i < numTimestamps; i++) {
+ switch (names[i]) {
+ case EGL_COMPOSITE_DEADLINE_ANDROID:
+ compositeDeadline = &values[i];
+ break;
+ case EGL_COMPOSITE_INTERVAL_ANDROID:
+ compositeInterval = &values[i];
+ break;
+ case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
+ compositeToPresentLatency = &values[i];
+ break;
+ default:
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+ }
+
+ status_t ret = native_window_get_compositor_timing(s->win.get(),
+ compositeDeadline, compositeInterval, compositeToPresentLatency);
+
+ switch (ret) {
+ case NO_ERROR:
+ return EGL_TRUE;
+ case INVALID_OPERATION:
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ default:
+ // This should not happen. Return an error that is not in the spec
+ // so it's obvious something is very wrong.
+ ALOGE("eglGetCompositorTiming: Unexpected error.");
+ return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+ }
+}
+
+EGLBoolean eglGetCompositorTimingSupportedANDROID(
+ EGLDisplay dpy, EGLSurface surface, EGLint name)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) {
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ }
+
+ SurfaceRef _s(dp.get(), surface);
+ if (!_s.get()) {
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ egl_surface_t const * const s = get_surface(surface);
+
+ ANativeWindow* window = s->win.get();
+ if (!window) {
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ switch (name) {
+ case EGL_COMPOSITE_DEADLINE_ANDROID:
+ case EGL_COMPOSITE_INTERVAL_ANDROID:
+ case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
+ return EGL_TRUE;
+ default:
+ return EGL_FALSE;
+ }
+}
+
EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
EGLnsecsANDROID *values)
@@ -2176,8 +2263,8 @@
}
}
-EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface,
- EGLint timestamp)
+EGLBoolean eglGetFrameTimestampSupportedANDROID(
+ EGLDisplay dpy, EGLSurface surface, EGLint timestamp)
{
clearError();
@@ -2199,7 +2286,9 @@
}
switch (timestamp) {
-#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
+ case EGL_COMPOSITE_DEADLINE_ANDROID:
+ case EGL_COMPOSITE_INTERVAL_ANDROID:
+ case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
case EGL_REQUESTED_PRESENT_TIME_ANDROID:
case EGL_RENDERING_COMPLETE_TIME_ANDROID:
case EGL_COMPOSITION_LATCH_TIME_ANDROID:
@@ -2221,7 +2310,6 @@
NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_RETIRE, &value);
return value == 0 ? EGL_FALSE : EGL_TRUE;
}
-#endif
default:
return EGL_FALSE;
}
diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
index f24d634..d0ed8e1 100644
--- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
+++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
@@ -8,11 +8,19 @@
Contributors
+ Brian Anderson
+ Dan Stoza
Pablo Ceballos
+ Jesse Hall
+ Fabien Sanglard
Contact
+ Brian Anderson, Google Inc. (brianderson 'at' google.com)
+ Dan Stoza, Google Inc. (stoza 'at' google.com)
Pablo Ceballos, Google Inc. (pceballos 'at' google.com)
+ Jesse Hall, Google Inc. (jessehall 'at' google.com)
+ Fabien Sanglard, Google Inc. (sanglardf 'at' google.com)
Status
@@ -20,7 +28,7 @@
Version
- Version 1, May 31, 2016
+ Version 1, January 13, 2017
Number
@@ -60,26 +68,33 @@
EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
EGLuint64KHR *frameId);
+ EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy,
+ EGLSurface surface, EGLint numTimestamps,
+ const EGLint *names, EGLnsecsANDROID *values);
+
EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
EGLuint64KHR frameId, EGLint numTimestamps,
const EGLint *timestamps, EGLnsecsANDROID *values);
- EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface
- surface, EGLint timestamp);
+ EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy,
+ EGLSurface surface, EGLint timestamp);
New Tokens
EGL_TIMESTAMPS_ANDROID 0x314D
- EGL_REQUESTED_PRESENT_TIME_ANDROID 0x314E
- EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F
- EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3150
- EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3151
- EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3152
- EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3153
- EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3154
- EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3155
- EGL_DEQUEUE_READY_TIME_ANDROID 0x3156
- EGL_READS_DONE_TIME_ANDROID 0x3157
+ EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
+ EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
+ EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
+ EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
+ EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
+ EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
+ EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
+ EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
+ EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3156
+ EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
+ EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3158
+ EGL_DEQUEUE_READY_TIME_ANDROID 0x3159
+ EGL_READS_DONE_TIME_ANDROID 0x315A
Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
"Surface Attributes", page 43:
@@ -89,7 +104,6 @@
enables timestamp collection, while a value of EGL_FALSE disables it. The
initial value is false. If surface is not a window surface this has no
effect.
-
Changes to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors)
Add a new subsection under Section 3,
@@ -108,6 +122,29 @@
The function
+ EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy,
+ EGLSurface surface, EGLint numTimestamps,
+ const EGLint *names, EGLnsecsANDROID *values);
+
+ allows querying anticipated timestamps and durations related to the
+ composition and display of a window surface. The values are not associated
+ with a particular frame and can be retrieved before the first swap.
+
+ The eglGetCompositorTimingANDROID function takes an array of names to
+ query and returns their values in the corresponding indices of the values
+ array. The possible names that can be queried are:
+ - EGL_COMPOSITE_DEADLINE_ANDROID - The timestamp of the next time the
+ compositor will begin composition. This is effectively the deadline
+ for when the compositor must receive a newly queued frame.
+ - EGL_COMPOSITE_INTERVAL_ANDROID - The time delta between subsequent
+ composition events.
+ - EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID - The time delta between
+ the start of composition and the expected present time of that
+ composition. This can be used to estimate the latency of the
+ actual present time.
+
+ The function
+
EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy,
EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps,
const EGLint *timestamps, EGLnsecsANDROID *values);
@@ -124,6 +161,12 @@
supported will generate an EGL_BAD_PARAMETER error. If any error is
generated the function will return EGL_FALSE.
+ The application can poll for the timestamp of particular events by calling
+ eglGetFrameTimestamps over and over without needing to call any other EGL
+ function between calls. This is true even for the most recently swapped
+ frame. eglGetFrameTimestamps is thread safe and can be called from a
+ different thread than the swapping thread.
+
The eglGetFrameTimestampsANDROID function takes an array of timestamps to
query and returns timestamps in the corresponding indices of the values
array. The possible timestamps that can be queried are:
@@ -162,12 +205,19 @@
purpose of display/composition were completed for this frame.
Not all implementations may support all of the above timestamp queries. The
- function
+ functions
- EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface
- surface, EGLint timestamp);
+ EGLBoolean eglGetCompositorTimingSupportedANDROID(EGLDisplay dpy,
+ EGLSurface surface, EGLint name);
- allows querying which timestamps are supported on the implementation."
+ and
+
+ EGLBoolean eglGetFrameTimestampsSupportedANDROID(EGLDisplay dpy,
+ EGLSurface surface, EGLint timestamp);
+
+ allows querying which values are supported by the implementations of
+ eglGetCompositoTimingANDROID and eglGetFrameTimestampsSupportedANDROID
+ respectively."
Issues
@@ -175,17 +225,21 @@
Revision History
-#1 (Pablo Ceballos, May 31, 2016)
- - Initial draft.
+#5 (Brian Anderson, January 13, 2017)
+ - Add eglGetCompositorTimingANDROID.
-#2 (Brian Anderson, July 22, 2016)
- - Replace EGL_QUEUE_TIME_ANDROID with EGL_REQUESTED_PRESENT_TIME_ANDROID.
- - Add DISPLAY_PRESENT_TIME_ANDROID.
+#4 (Brian Anderson, January 10, 2017)
+ - Use an absolute frameId rather than a relative framesAgo.
#3 (Brian Anderson, November 30, 2016)
- Add EGL_COMPOSITION_LATCH_TIME_ANDROID,
EGL_LAST_COMPOSITION_START_TIME_ANDROID, and
EGL_DEQUEUE_READY_TIME_ANDROID.
-#4 (Brian Anderson, January 10, 2017)
- - Use an absolute frameId rather than a relative framesAgo.
+#2 (Brian Anderson, July 22, 2016)
+ - Replace EGL_QUEUE_TIME_ANDROID with EGL_REQUESTED_PRESENT_TIME_ANDROID.
+ - Add DISPLAY_PRESENT_TIME_ANDROID.
+
+#1 (Pablo Ceballos, May 31, 2016)
+ - Initial draft.
+
diff --git a/opengl/specs/README b/opengl/specs/README
index 1853214..0c49023 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -20,14 +20,17 @@
0x314B EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop)
0x314C EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh)
0x314D EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314E EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314F EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3150 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3151 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3152 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3153 EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3154 EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3155 EGL_DISPLAY_RETIRE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3156 EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3157 EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3158 - 0x315F (unused)
+0x314E EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x314F EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3150 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3151 EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3152 EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3153 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3154 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3155 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3156 EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3157 EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3158 EGL_DISPLAY_RETIRE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3159 EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x315A EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x315B - 0x315F (unused)
diff --git a/services/audiomanager/IPlayer.cpp b/services/audiomanager/IPlayer.cpp
index 47edc4b..e8a9c34 100644
--- a/services/audiomanager/IPlayer.cpp
+++ b/services/audiomanager/IPlayer.cpp
@@ -35,6 +35,7 @@
SET_VOLUME = IBinder::FIRST_CALL_TRANSACTION + 3,
SET_PAN = IBinder::FIRST_CALL_TRANSACTION + 4,
SET_START_DELAY_MS = IBinder::FIRST_CALL_TRANSACTION + 5,
+ APPLY_VOLUME_SHAPER = IBinder::FIRST_CALL_TRANSACTION + 6,
};
class BpPlayer : public BpInterface<IPlayer>
@@ -88,6 +89,36 @@
data.writeInt32(delayMs);
remote()->transact(SET_START_DELAY_MS, data, &reply);
}
+
+ virtual void applyVolumeShaper(
+ const sp<VolumeShaper::Configuration>& configuration,
+ const sp<VolumeShaper::Operation>& operation) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
+
+ status_t status = configuration.get() == nullptr
+ ? data.writeInt32(0)
+ : data.writeInt32(1)
+ ?: configuration->writeToParcel(&data);
+ if (status != NO_ERROR) {
+ ALOGW("applyVolumeShaper failed configuration parceling: %d", status);
+ return; // ignore error
+ }
+
+ status = operation.get() == nullptr
+ ? status = data.writeInt32(0)
+ : data.writeInt32(1)
+ ?: operation->writeToParcel(&data);
+ if (status != NO_ERROR) {
+ ALOGW("applyVolumeShaper failed operation parceling: %d", status);
+ return; // ignore error
+ }
+
+ status = remote()->transact(APPLY_VOLUME_SHAPER, data, &reply);
+
+ ALOGW_IF(status != NO_ERROR, "applyVolumeShaper failed transact: %d", status);
+ return; // one way transaction, ignore error
+ }
};
IMPLEMENT_META_INTERFACE(Player, "android.media.IPlayer");
@@ -128,6 +159,28 @@
setStartDelayMs(data.readInt32());
return NO_ERROR;
} break;
+ case APPLY_VOLUME_SHAPER: {
+ CHECK_INTERFACE(IPlayer, data, reply);
+ sp<VolumeShaper::Configuration> configuration;
+ sp<VolumeShaper::Operation> operation;
+
+ int32_t present;
+ status_t status = data.readInt32(&present);
+ if (status == NO_ERROR && present != 0) {
+ configuration = new VolumeShaper::Configuration();
+ status = configuration->readFromParcel(data);
+ }
+ status = status ?: data.readInt32(&present);
+ if (status == NO_ERROR && present != 0) {
+ operation = new VolumeShaper::Operation();
+ status = operation->readFromParcel(data);
+ }
+ if (status == NO_ERROR) {
+ // one way transaction, no error returned
+ applyVolumeShaper(configuration, operation);
+ }
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index c41630a..d61f26f 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -10,6 +10,7 @@
OrientationSensor.cpp \
RecentEventLogger.cpp \
RotationVectorSensor.cpp \
+ SensorDevice.cpp \
SensorDirectConnection.cpp \
SensorEventConnection.cpp \
SensorFusion.cpp \
@@ -25,13 +26,6 @@
LOCAL_CFLAGS += -fvisibility=hidden
-ifeq ($(ENABLE_TREBLE), true)
-LOCAL_SRC_FILES += SensorDeviceTreble.cpp
-LOCAL_CFLAGS += -DENABLE_TREBLE=1
-else
-LOCAL_SRC_FILES += SensorDevice.cpp
-endif
-
LOCAL_SHARED_LIBRARIES := \
libcutils \
libhardware \
@@ -42,10 +36,6 @@
libui \
libgui \
libcrypto \
-
-ifeq ($(ENABLE_TREBLE), true)
-
-LOCAL_SHARED_LIBRARIES += \
libbase \
libhidlbase \
libhidltransport \
@@ -55,8 +45,6 @@
LOCAL_STATIC_LIBRARIES := \
android.hardware.sensors@1.0-convert
-endif # ENABLE_TREBLE
-
LOCAL_MODULE:= libsensorservice
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index de0321d..3edd50b 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -14,138 +14,167 @@
* limitations under the License.
*/
+#include <inttypes.h>
+#include <math.h>
+#include <stdint.h>
+#include <sys/types.h>
-#include "SensorDevice.h"
-#include "SensorService.h"
-
-
-#include <binder/BinderService.h>
-#include <binder/Parcel.h>
-#include <binder/IServiceManager.h>
-#include <cutils/ashmem.h>
-#include <hardware/sensors.h>
+#include <android-base/logging.h>
#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/Singleton.h>
-#include <inttypes.h>
-#include <math.h>
-#include <sys/mman.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sstream>
-#include <unistd.h>
+#include "SensorDevice.h"
+#include "SensorService.h"
+
+#include <sensors/convert.h>
+
+using android::hardware::hidl_vec;
+
+using namespace android::hardware::sensors::V1_0;
+using namespace android::hardware::sensors::V1_0::implementation;
namespace android {
// ---------------------------------------------------------------------------
ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
-SensorDevice::SensorDevice()
- : mSensorDevice(0),
- mSensorModule(0) {
- status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
- (hw_module_t const**)&mSensorModule);
-
- ALOGE_IF(err, "couldn't load %s module (%s)",
- SENSORS_HARDWARE_MODULE_ID, strerror(-err));
-
- if (mSensorModule) {
- err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
-
- ALOGE_IF(err, "couldn't open device for module %s (%s)",
- SENSORS_HARDWARE_MODULE_ID, strerror(-err));
-
- if (mSensorDevice) {
-
- sensor_t const* list;
- ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
-
- if (mSensorDevice->common.version < SENSORS_DEVICE_API_VERSION_1_3) {
- ALOGE(">>>> WARNING <<< Upgrade sensor HAL to version 1_3, ignoring sensors reported by this device");
- count = 0;
- }
-
- mActivationCount.setCapacity(count);
- Info model;
- for (size_t i=0 ; i<size_t(count) ; i++) {
- mActivationCount.add(list[i].handle, model);
- mSensorDevice->activate(
- reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
- list[i].handle, 0);
- }
- }
+static status_t StatusFromResult(Result result) {
+ switch (result) {
+ case Result::OK:
+ return OK;
+ case Result::BAD_VALUE:
+ return BAD_VALUE;
+ case Result::PERMISSION_DENIED:
+ return PERMISSION_DENIED;
+ case Result::INVALID_OPERATION:
+ return INVALID_OPERATION;
+ case Result::NO_MEMORY:
+ return NO_MEMORY;
}
}
+SensorDevice::SensorDevice() {
+ mSensors = ISensors::getService();
+
+ if (mSensors == NULL) {
+ return;
+ }
+
+ mSensors->getSensorsList(
+ [&](const auto &list) {
+ const size_t count = list.size();
+
+ mActivationCount.setCapacity(count);
+ Info model;
+ for (size_t i=0 ; i < count; i++) {
+ sensor_t sensor;
+ convertToSensor(list[i], &sensor);
+ mSensorList.push_back(sensor);
+
+ mActivationCount.add(list[i].sensorHandle, model);
+
+ mSensors->activate(list[i].sensorHandle, 0 /* enabled */);
+ }
+ });
+
+ mIsDirectReportSupported =
+ (mSensors->unregisterDirectChannel(-1) != Result::INVALID_OPERATION);
+}
+
void SensorDevice::handleDynamicSensorConnection(int handle, bool connected) {
if (connected) {
Info model;
mActivationCount.add(handle, model);
- mSensorDevice->activate(
- reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), handle, 0);
+ mSensors->activate(handle, 0 /* enabled */);
} else {
mActivationCount.removeItem(handle);
}
}
std::string SensorDevice::dump() const {
- if (!mSensorModule) return "HAL not initialized\n";
+ if (mSensors == NULL) return "HAL not initialized\n";
String8 result;
- sensor_t const* list;
- int count = mSensorModule->get_sensors_list(mSensorModule, &list);
+ mSensors->getSensorsList([&](const auto &list) {
+ const size_t count = list.size();
- result.appendFormat("HAL: %s (%s), version %#010x\n",
- mSensorModule->common.name,
- mSensorModule->common.author,
- getHalDeviceVersion());
- result.appendFormat("Total %d h/w sensors, %zu running:\n", count, mActivationCount.size());
+ result.appendFormat(
+ "Total %zu h/w sensors, %zu running:\n",
+ count,
+ mActivationCount.size());
- Mutex::Autolock _l(mLock);
- for (int i = 0 ; i < count ; i++) {
- const Info& info = mActivationCount.valueFor(list[i].handle);
- if (info.batchParams.isEmpty()) continue;
- result.appendFormat("0x%08x) active-count = %zu; ", list[i].handle,
- info.batchParams.size());
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0 ; i < count ; i++) {
+ const Info& info = mActivationCount.valueFor(
+ list[i].sensorHandle);
- result.append("sampling_period(ms) = {");
- for (size_t j = 0; j < info.batchParams.size(); j++) {
- const BatchParams& params = info.batchParams.valueAt(j);
- result.appendFormat("%.1f%s", params.batchDelay / 1e6f,
- j < info.batchParams.size() - 1 ? ", " : "");
- }
- result.appendFormat("}, selected = %.1f ms; ", info.bestBatchParams.batchDelay / 1e6f);
+ if (info.batchParams.isEmpty()) continue;
+ result.appendFormat(
+ "0x%08x) active-count = %zu; ",
+ list[i].sensorHandle,
+ info.batchParams.size());
- result.append("batching_period(ms) = {");
- for (size_t j = 0; j < info.batchParams.size(); j++) {
- BatchParams params = info.batchParams.valueAt(j);
- result.appendFormat("%.1f%s", params.batchTimeout / 1e6f,
- j < info.batchParams.size() - 1 ? ", " : "");
- }
- result.appendFormat("}, selected = %.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f);
- }
+ result.append("sampling_period(ms) = {");
+ for (size_t j = 0; j < info.batchParams.size(); j++) {
+ const BatchParams& params = info.batchParams.valueAt(j);
+ result.appendFormat(
+ "%.1f%s",
+ params.batchDelay / 1e6f,
+ j < info.batchParams.size() - 1 ? ", " : "");
+ }
+ result.appendFormat(
+ "}, selected = %.1f ms; ",
+ info.bestBatchParams.batchDelay / 1e6f);
+
+ result.append("batching_period(ms) = {");
+ for (size_t j = 0; j < info.batchParams.size(); j++) {
+ BatchParams params = info.batchParams.valueAt(j);
+
+ result.appendFormat(
+ "%.1f%s",
+ params.batchTimeout / 1e6f,
+ j < info.batchParams.size() - 1 ? ", " : "");
+ }
+
+ result.appendFormat(
+ "}, selected = %.1f ms\n",
+ info.bestBatchParams.batchTimeout / 1e6f);
+ }
+ });
+
return result.string();
}
ssize_t SensorDevice::getSensorList(sensor_t const** list) {
- if (!mSensorModule) return NO_INIT;
- ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list);
- return count;
+ *list = &mSensorList[0];
+
+ return mSensorList.size();
}
status_t SensorDevice::initCheck() const {
- return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT;
+ return mSensors != NULL ? NO_ERROR : NO_INIT;
}
ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
- if (!mSensorDevice) return NO_INIT;
- ssize_t c;
- do {
- c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
- buffer, count);
- } while (c == -EINTR);
- return c;
+ if (mSensors == NULL) return NO_INIT;
+
+ ssize_t err;
+
+ mSensors->poll(
+ count,
+ [&](auto result,
+ const auto &events,
+ const auto &dynamicSensorsAdded) {
+ if (result == Result::OK) {
+ convertToSensorEvents(events, dynamicSensorsAdded, buffer);
+ err = (ssize_t)events.size();
+ } else {
+ err = StatusFromResult(result);
+ }
+ });
+
+ return err;
}
void SensorDevice::autoDisable(void *ident, int handle) {
@@ -155,7 +184,8 @@
}
status_t SensorDevice::activate(void* ident, int handle, int enabled) {
- if (!mSensorDevice) return NO_INIT;
+ if (mSensors == NULL) return NO_INIT;
+
status_t err(NO_ERROR);
bool actuateHardware = false;
@@ -187,24 +217,30 @@
} else {
ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident));
+ // If a connected dynamic sensor is deactivated, remove it from the
+ // dictionary.
+ auto it = mConnectedDynamicSensors.find(handle);
+ if (it != mConnectedDynamicSensors.end()) {
+ delete it->second;
+ mConnectedDynamicSensors.erase(it);
+ }
+
if (info.removeBatchParamsForIdent(ident) >= 0) {
if (info.numActiveClients() == 0) {
// This is the last connection, we need to de-activate the underlying h/w sensor.
actuateHardware = true;
} else {
- const int halVersion = getHalDeviceVersion();
- if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
- // Call batch for this sensor with the previously calculated best effort
- // batch_rate and timeout. One of the apps has unregistered for sensor
- // events, and the best effort batch parameters might have changed.
- ALOGD_IF(DEBUG_CONNECTIONS,
- "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
- info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout);
- mSensorDevice->batch(mSensorDevice, handle,info.bestBatchParams.flags,
- info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout);
- }
+ // Call batch for this sensor with the previously calculated best effort
+ // batch_rate and timeout. One of the apps has unregistered for sensor
+ // events, and the best effort batch parameters might have changed.
+ ALOGD_IF(DEBUG_CONNECTIONS,
+ "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
+ info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout);
+ mSensors->batch(
+ handle,
+ info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout);
}
} else {
// sensor wasn't enabled for this ident
@@ -218,8 +254,7 @@
if (actuateHardware) {
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
enabled);
- err = mSensorDevice->activate(
- reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), handle, enabled);
+ err = StatusFromResult(mSensors->activate(handle, enabled));
ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
strerror(-err));
@@ -229,31 +264,21 @@
}
}
- // On older devices which do not support batch, call setDelay().
- if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.numActiveClients() > 0) {
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %" PRId64, handle,
- info.bestBatchParams.batchDelay);
- mSensorDevice->setDelay(
- reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
- handle, info.bestBatchParams.batchDelay);
- }
return err;
}
-status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
- int64_t maxBatchReportLatencyNs) {
- if (!mSensorDevice) return NO_INIT;
+status_t SensorDevice::batch(
+ void* ident,
+ int handle,
+ int flags,
+ int64_t samplingPeriodNs,
+ int64_t maxBatchReportLatencyNs) {
+ if (mSensors == NULL) return NO_INIT;
if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
}
- const int halVersion = getHalDeviceVersion();
- if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 && maxBatchReportLatencyNs != 0) {
- // Batch is not supported on older devices return invalid operation.
- return INVALID_OPERATION;
- }
-
ALOGD_IF(DEBUG_CONNECTIONS,
"SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64,
ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
@@ -282,21 +307,17 @@
status_t err(NO_ERROR);
// If the min period or min timeout has changed since the last batch call, call batch.
if (prevBestBatchParams != info.bestBatchParams) {
- if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
- info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout);
- err = mSensorDevice->batch(mSensorDevice, handle, info.bestBatchParams.flags,
- info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout);
- } else {
- // For older devices which do not support batch, call setDelay() after activate() is
- // called. Some older devices may not support calling setDelay before activate(), so
- // call setDelay in SensorDevice::activate() method.
- }
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
+ info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout);
+ err = StatusFromResult(
+ mSensors->batch(
+ handle,
+ info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout));
if (err != NO_ERROR) {
ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s",
- mSensorDevice, handle,
+ mSensors.get(), handle,
info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
info.bestBatchParams.batchTimeout, strerror(-err));
info.removeBatchParamsForIdent(ident);
@@ -306,7 +327,7 @@
}
status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) {
- if (!mSensorDevice) return NO_INIT;
+ if (mSensors == NULL) return NO_INIT;
if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
}
@@ -325,22 +346,20 @@
BatchParams& params = info.batchParams.editValueAt(index);
params.batchDelay = samplingPeriodNs;
info.selectBatchParams();
- return mSensorDevice->setDelay(reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
- handle, info.bestBatchParams.batchDelay);
+
+ return StatusFromResult(
+ mSensors->batch(handle, info.bestBatchParams.batchDelay, 0));
}
int SensorDevice::getHalDeviceVersion() const {
- if (!mSensorDevice) return -1;
- return mSensorDevice->common.version;
+ if (mSensors == NULL) return -1;
+ return SENSORS_DEVICE_API_VERSION_1_4;
}
status_t SensorDevice::flush(void* ident, int handle) {
- if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) {
- return INVALID_OPERATION;
- }
if (isClientDisabled(ident)) return INVALID_OPERATION;
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
- return mSensorDevice->flush(mSensorDevice, handle);
+ return StatusFromResult(mSensors->flush(handle));
}
bool SensorDevice::isClientDisabled(void* ident) {
@@ -356,7 +375,6 @@
Mutex::Autolock _l(mLock);
mDisabledClients.clear();
ALOGI("cleared mDisabledClients");
- const int halVersion = getHalDeviceVersion();
for (size_t i = 0; i< mActivationCount.size(); ++i) {
Info& info = mActivationCount.editValueAt(i);
if (info.batchParams.isEmpty()) continue;
@@ -364,42 +382,32 @@
const int sensor_handle = mActivationCount.keyAt(i);
ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
sensor_handle);
- status_t err(NO_ERROR);
- if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) {
- err = mSensorDevice->batch(mSensorDevice, sensor_handle,
- info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout);
- ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
- }
+ status_t err = StatusFromResult(
+ mSensors->batch(
+ sensor_handle,
+ info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout));
+ ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
if (err == NO_ERROR) {
- err = mSensorDevice->activate(
- reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
- sensor_handle, 1);
+ err = StatusFromResult(
+ mSensors->activate(sensor_handle, 1 /* enabled */));
ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
}
-
- if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0) {
- err = mSensorDevice->setDelay(
- reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
- sensor_handle, info.bestBatchParams.batchDelay);
- ALOGE_IF(err, "Error calling setDelay sensor %d (%s)", sensor_handle, strerror(-err));
- }
}
}
void SensorDevice::disableAllSensors() {
Mutex::Autolock _l(mLock);
- for (size_t i = 0; i< mActivationCount.size(); ++i) {
+ for (size_t i = 0; i< mActivationCount.size(); ++i) {
const Info& info = mActivationCount.valueAt(i);
// Check if this sensor has been activated previously and disable it.
if (info.batchParams.size() > 0) {
const int sensor_handle = mActivationCount.keyAt(i);
ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
sensor_handle);
- mSensorDevice->activate(
- reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
- sensor_handle, 0);
+ mSensors->activate(sensor_handle, 0 /* enabled */);
+
// Add all the connections that were registered for this sensor to the disabled
// clients list.
for (size_t j = 0; j < info.batchParams.size(); ++j) {
@@ -410,25 +418,27 @@
}
}
-status_t SensorDevice::injectSensorData(const sensors_event_t *injected_sensor_event) {
- ALOGD_IF(DEBUG_CONNECTIONS,
- "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
- injected_sensor_event->sensor,
- injected_sensor_event->timestamp, injected_sensor_event->data[0],
- injected_sensor_event->data[1], injected_sensor_event->data[2],
- injected_sensor_event->data[3], injected_sensor_event->data[4],
- injected_sensor_event->data[5]);
- if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
- return INVALID_OPERATION;
- }
- return mSensorDevice->inject_sensor_data(mSensorDevice, injected_sensor_event);
+status_t SensorDevice::injectSensorData(
+ const sensors_event_t *injected_sensor_event) {
+ ALOGD_IF(DEBUG_CONNECTIONS,
+ "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
+ injected_sensor_event->sensor,
+ injected_sensor_event->timestamp, injected_sensor_event->data[0],
+ injected_sensor_event->data[1], injected_sensor_event->data[2],
+ injected_sensor_event->data[3], injected_sensor_event->data[4],
+ injected_sensor_event->data[5]);
+
+ Event ev;
+ convertFromSensorEvent(*injected_sensor_event, &ev);
+
+ return StatusFromResult(mSensors->injectSensorData(ev));
}
status_t SensorDevice::setMode(uint32_t mode) {
- if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
- return INVALID_OPERATION;
- }
- return mSensorModule->set_operation_mode(mode);
+
+ return StatusFromResult(
+ mSensors->setOperationMode(
+ static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
}
// ---------------------------------------------------------------------------
@@ -491,44 +501,139 @@
}
int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
-
- if (!isDirectReportSupported()) {
- return INVALID_OPERATION;
- }
-
Mutex::Autolock _l(mLock);
- int32_t channelHandle = mSensorDevice->register_direct_channel(
- mSensorDevice, memory, -1 /*channel_handle*/);
- return channelHandle;
+ SharedMemType type;
+ switch (memory->type) {
+ case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
+ type = SharedMemType::ASHMEM;
+ break;
+ case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
+ type = SharedMemType::GRALLOC;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+
+ SharedMemFormat format;
+ if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) {
+ return BAD_VALUE;
+ }
+ format = SharedMemFormat::SENSORS_EVENT;
+
+ SharedMemInfo mem = {
+ .type = type,
+ .format = format,
+ .size = static_cast<uint32_t>(memory->size),
+ .memoryHandle = memory->handle,
+ };
+
+ int32_t ret;
+ mSensors->registerDirectChannel(mem,
+ [&ret](auto result, auto channelHandle) {
+ if (result == Result::OK) {
+ ret = channelHandle;
+ } else {
+ ret = StatusFromResult(result);
+ }
+ });
+ return ret;
}
void SensorDevice::unregisterDirectChannel(int32_t channelHandle) {
Mutex::Autolock _l(mLock);
-
- mSensorDevice->register_direct_channel(mSensorDevice, nullptr, channelHandle);
+ mSensors->unregisterDirectChannel(channelHandle);
}
-int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
- const struct sensors_direct_cfg_t *config) {
-
- if (!isDirectReportSupported()) {
- return INVALID_OPERATION;
- }
-
+int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle,
+ int32_t channelHandle, const struct sensors_direct_cfg_t *config) {
Mutex::Autolock _l(mLock);
- int32_t ret = mSensorDevice->config_direct_report(
- mSensorDevice, sensorHandle, channelHandle, config);
- ALOGE_IF(ret < 0, "SensorDevice::configureDirectChannel ret %d", ret);
+ RateLevel rate;
+ switch(config->rate_level) {
+ case SENSOR_DIRECT_RATE_STOP:
+ rate = RateLevel::STOP;
+ break;
+ case SENSOR_DIRECT_RATE_NORMAL:
+ rate = RateLevel::NORMAL;
+ break;
+ case SENSOR_DIRECT_RATE_FAST:
+ rate = RateLevel::FAST;
+ break;
+ case SENSOR_DIRECT_RATE_VERY_FAST:
+ rate = RateLevel::VERY_FAST;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+
+ int32_t ret;
+ mSensors->configDirectReport(sensorHandle, channelHandle, rate,
+ [&ret, rate] (auto result, auto token) {
+ if (rate == RateLevel::STOP) {
+ ret = StatusFromResult(result);
+ } else {
+ if (result == Result::OK) {
+ ret = token;
+ } else {
+ ret = StatusFromResult(result);
+ }
+ }
+ });
+
return ret;
}
bool SensorDevice::isDirectReportSupported() const {
- bool ret = mSensorDevice->register_direct_channel != nullptr
- && mSensorDevice->config_direct_report != nullptr;
- return ret;
+ return mIsDirectReportSupported;
}
+
+void SensorDevice::convertToSensorEvent(
+ const Event &src, sensors_event_t *dst) {
+ ::android::hardware::sensors::V1_0::implementation::convertToSensorEvent(
+ src, dst);
+
+ if (src.sensorType == SensorType::DYNAMIC_SENSOR_META) {
+ const DynamicSensorInfo &dyn = src.u.dynamic;
+
+ dst->dynamic_sensor_meta.connected = dyn.connected;
+ dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
+ if (dyn.connected) {
+ auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
+ CHECK(it != mConnectedDynamicSensors.end());
+
+ dst->dynamic_sensor_meta.sensor = it->second;
+
+ memcpy(dst->dynamic_sensor_meta.uuid,
+ dyn.uuid.data(),
+ sizeof(dst->dynamic_sensor_meta.uuid));
+ }
+ }
+}
+
+void SensorDevice::convertToSensorEvents(
+ const hidl_vec<Event> &src,
+ const hidl_vec<SensorInfo> &dynamicSensorsAdded,
+ sensors_event_t *dst) {
+ // Allocate a sensor_t structure for each dynamic sensor added and insert
+ // it into the dictionary of connected dynamic sensors keyed by handle.
+ for (size_t i = 0; i < dynamicSensorsAdded.size(); ++i) {
+ const SensorInfo &info = dynamicSensorsAdded[i];
+
+ auto it = mConnectedDynamicSensors.find(info.sensorHandle);
+ CHECK(it == mConnectedDynamicSensors.end());
+
+ sensor_t *sensor = new sensor_t;
+ convertToSensor(info, sensor);
+
+ mConnectedDynamicSensors.insert(
+ std::make_pair(sensor->handle, sensor));
+ }
+
+ for (size_t i = 0; i < src.size(); ++i) {
+ convertToSensorEvent(src[i], &dst[i]);
+ }
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
-
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 7dd256a..7f95429 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -20,19 +20,16 @@
#include "SensorServiceUtils.h"
#include <gui/Sensor.h>
+#include <stdint.h>
+#include <sys/types.h>
#include <utils/KeyedVector.h>
#include <utils/Singleton.h>
#include <utils/String8.h>
-#include <stdint.h>
-#include <sys/types.h>
#include <string>
-
-#ifdef ENABLE_TREBLE
#include <map>
#include "android/hardware/sensors/1.0/ISensors.h"
-#endif
// ---------------------------------------------------------------------------
@@ -76,14 +73,10 @@
virtual std::string dump() const;
private:
friend class Singleton<SensorDevice>;
-#ifdef ENABLE_TREBLE
+
sp<android::hardware::sensors::V1_0::ISensors> mSensors;
Vector<sensor_t> mSensorList;
std::map<int32_t, sensor_t*> mConnectedDynamicSensors;
-#else
- sensors_poll_device_1_t* mSensorDevice;
- struct sensors_module_t* mSensorModule;
-#endif
static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz
mutable Mutex mLock; // protect mActivationCount[].batchParams
@@ -138,7 +131,6 @@
bool isClientDisabled(void* ident);
bool isClientDisabledLocked(void* ident);
-#ifdef ENABLE_TREBLE
using Event = hardware::sensors::V1_0::Event;
using SensorInfo = hardware::sensors::V1_0::SensorInfo;
@@ -150,7 +142,6 @@
sensors_event_t *dst);
bool mIsDirectReportSupported;
-#endif // ENABLE_TREBLE
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorDeviceTreble.cpp b/services/sensorservice/SensorDeviceTreble.cpp
deleted file mode 100644
index 3edd50b..0000000
--- a/services/sensorservice/SensorDeviceTreble.cpp
+++ /dev/null
@@ -1,639 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <inttypes.h>
-#include <math.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <android-base/logging.h>
-#include <utils/Atomic.h>
-#include <utils/Errors.h>
-#include <utils/Singleton.h>
-
-#include "SensorDevice.h"
-#include "SensorService.h"
-
-#include <sensors/convert.h>
-
-using android::hardware::hidl_vec;
-
-using namespace android::hardware::sensors::V1_0;
-using namespace android::hardware::sensors::V1_0::implementation;
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
-
-static status_t StatusFromResult(Result result) {
- switch (result) {
- case Result::OK:
- return OK;
- case Result::BAD_VALUE:
- return BAD_VALUE;
- case Result::PERMISSION_DENIED:
- return PERMISSION_DENIED;
- case Result::INVALID_OPERATION:
- return INVALID_OPERATION;
- case Result::NO_MEMORY:
- return NO_MEMORY;
- }
-}
-
-SensorDevice::SensorDevice() {
- mSensors = ISensors::getService();
-
- if (mSensors == NULL) {
- return;
- }
-
- mSensors->getSensorsList(
- [&](const auto &list) {
- const size_t count = list.size();
-
- mActivationCount.setCapacity(count);
- Info model;
- for (size_t i=0 ; i < count; i++) {
- sensor_t sensor;
- convertToSensor(list[i], &sensor);
- mSensorList.push_back(sensor);
-
- mActivationCount.add(list[i].sensorHandle, model);
-
- mSensors->activate(list[i].sensorHandle, 0 /* enabled */);
- }
- });
-
- mIsDirectReportSupported =
- (mSensors->unregisterDirectChannel(-1) != Result::INVALID_OPERATION);
-}
-
-void SensorDevice::handleDynamicSensorConnection(int handle, bool connected) {
- if (connected) {
- Info model;
- mActivationCount.add(handle, model);
- mSensors->activate(handle, 0 /* enabled */);
- } else {
- mActivationCount.removeItem(handle);
- }
-}
-
-std::string SensorDevice::dump() const {
- if (mSensors == NULL) return "HAL not initialized\n";
-
- String8 result;
- mSensors->getSensorsList([&](const auto &list) {
- const size_t count = list.size();
-
- result.appendFormat(
- "Total %zu h/w sensors, %zu running:\n",
- count,
- mActivationCount.size());
-
- Mutex::Autolock _l(mLock);
- for (size_t i = 0 ; i < count ; i++) {
- const Info& info = mActivationCount.valueFor(
- list[i].sensorHandle);
-
- if (info.batchParams.isEmpty()) continue;
- result.appendFormat(
- "0x%08x) active-count = %zu; ",
- list[i].sensorHandle,
- info.batchParams.size());
-
- result.append("sampling_period(ms) = {");
- for (size_t j = 0; j < info.batchParams.size(); j++) {
- const BatchParams& params = info.batchParams.valueAt(j);
- result.appendFormat(
- "%.1f%s",
- params.batchDelay / 1e6f,
- j < info.batchParams.size() - 1 ? ", " : "");
- }
- result.appendFormat(
- "}, selected = %.1f ms; ",
- info.bestBatchParams.batchDelay / 1e6f);
-
- result.append("batching_period(ms) = {");
- for (size_t j = 0; j < info.batchParams.size(); j++) {
- BatchParams params = info.batchParams.valueAt(j);
-
- result.appendFormat(
- "%.1f%s",
- params.batchTimeout / 1e6f,
- j < info.batchParams.size() - 1 ? ", " : "");
- }
-
- result.appendFormat(
- "}, selected = %.1f ms\n",
- info.bestBatchParams.batchTimeout / 1e6f);
- }
- });
-
- return result.string();
-}
-
-ssize_t SensorDevice::getSensorList(sensor_t const** list) {
- *list = &mSensorList[0];
-
- return mSensorList.size();
-}
-
-status_t SensorDevice::initCheck() const {
- return mSensors != NULL ? NO_ERROR : NO_INIT;
-}
-
-ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
- if (mSensors == NULL) return NO_INIT;
-
- ssize_t err;
-
- mSensors->poll(
- count,
- [&](auto result,
- const auto &events,
- const auto &dynamicSensorsAdded) {
- if (result == Result::OK) {
- convertToSensorEvents(events, dynamicSensorsAdded, buffer);
- err = (ssize_t)events.size();
- } else {
- err = StatusFromResult(result);
- }
- });
-
- return err;
-}
-
-void SensorDevice::autoDisable(void *ident, int handle) {
- Info& info( mActivationCount.editValueFor(handle) );
- Mutex::Autolock _l(mLock);
- info.removeBatchParamsForIdent(ident);
-}
-
-status_t SensorDevice::activate(void* ident, int handle, int enabled) {
- if (mSensors == NULL) return NO_INIT;
-
- status_t err(NO_ERROR);
- bool actuateHardware = false;
-
- Mutex::Autolock _l(mLock);
- Info& info( mActivationCount.editValueFor(handle) );
-
- ALOGD_IF(DEBUG_CONNECTIONS,
- "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu",
- ident, handle, enabled, info.batchParams.size());
-
- if (enabled) {
- ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));
-
- if (isClientDisabledLocked(ident)) {
- ALOGE("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d",
- ident, handle);
- return INVALID_OPERATION;
- }
-
- if (info.batchParams.indexOfKey(ident) >= 0) {
- if (info.numActiveClients() == 1) {
- // This is the first connection, we need to activate the underlying h/w sensor.
- actuateHardware = true;
- }
- } else {
- // Log error. Every activate call should be preceded by a batch() call.
- ALOGE("\t >>>ERROR: activate called without batch");
- }
- } else {
- ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident));
-
- // If a connected dynamic sensor is deactivated, remove it from the
- // dictionary.
- auto it = mConnectedDynamicSensors.find(handle);
- if (it != mConnectedDynamicSensors.end()) {
- delete it->second;
- mConnectedDynamicSensors.erase(it);
- }
-
- if (info.removeBatchParamsForIdent(ident) >= 0) {
- if (info.numActiveClients() == 0) {
- // This is the last connection, we need to de-activate the underlying h/w sensor.
- actuateHardware = true;
- } else {
- // Call batch for this sensor with the previously calculated best effort
- // batch_rate and timeout. One of the apps has unregistered for sensor
- // events, and the best effort batch parameters might have changed.
- ALOGD_IF(DEBUG_CONNECTIONS,
- "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
- info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout);
- mSensors->batch(
- handle,
- info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout);
- }
- } else {
- // sensor wasn't enabled for this ident
- }
-
- if (isClientDisabledLocked(ident)) {
- return NO_ERROR;
- }
- }
-
- if (actuateHardware) {
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
- enabled);
- err = StatusFromResult(mSensors->activate(handle, enabled));
- ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
- strerror(-err));
-
- if (err != NO_ERROR && enabled) {
- // Failure when enabling the sensor. Clean up on failure.
- info.removeBatchParamsForIdent(ident);
- }
- }
-
- return err;
-}
-
-status_t SensorDevice::batch(
- void* ident,
- int handle,
- int flags,
- int64_t samplingPeriodNs,
- int64_t maxBatchReportLatencyNs) {
- if (mSensors == NULL) return NO_INIT;
-
- if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
- samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
- }
-
- ALOGD_IF(DEBUG_CONNECTIONS,
- "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64,
- ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
-
- Mutex::Autolock _l(mLock);
- Info& info(mActivationCount.editValueFor(handle));
-
- if (info.batchParams.indexOfKey(ident) < 0) {
- BatchParams params(flags, samplingPeriodNs, maxBatchReportLatencyNs);
- info.batchParams.add(ident, params);
- } else {
- // A batch has already been called with this ident. Update the batch parameters.
- info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
- }
-
- BatchParams prevBestBatchParams = info.bestBatchParams;
- // Find the minimum of all timeouts and batch_rates for this sensor.
- info.selectBatchParams();
-
- ALOGD_IF(DEBUG_CONNECTIONS,
- "\t>>> curr_period=%" PRId64 " min_period=%" PRId64
- " curr_timeout=%" PRId64 " min_timeout=%" PRId64,
- prevBestBatchParams.batchDelay, info.bestBatchParams.batchDelay,
- prevBestBatchParams.batchTimeout, info.bestBatchParams.batchTimeout);
-
- status_t err(NO_ERROR);
- // If the min period or min timeout has changed since the last batch call, call batch.
- if (prevBestBatchParams != info.bestBatchParams) {
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
- info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout);
- err = StatusFromResult(
- mSensors->batch(
- handle,
- info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout));
- if (err != NO_ERROR) {
- ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s",
- mSensors.get(), handle,
- info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout, strerror(-err));
- info.removeBatchParamsForIdent(ident);
- }
- }
- return err;
-}
-
-status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) {
- if (mSensors == NULL) return NO_INIT;
- if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
- samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
- }
- Mutex::Autolock _l(mLock);
- if (isClientDisabledLocked(ident)) return INVALID_OPERATION;
- Info& info( mActivationCount.editValueFor(handle) );
- // If the underlying sensor is NOT in continuous mode, setDelay() should return an error.
- // Calling setDelay() in batch mode is an invalid operation.
- if (info.bestBatchParams.batchTimeout != 0) {
- return INVALID_OPERATION;
- }
- ssize_t index = info.batchParams.indexOfKey(ident);
- if (index < 0) {
- return BAD_INDEX;
- }
- BatchParams& params = info.batchParams.editValueAt(index);
- params.batchDelay = samplingPeriodNs;
- info.selectBatchParams();
-
- return StatusFromResult(
- mSensors->batch(handle, info.bestBatchParams.batchDelay, 0));
-}
-
-int SensorDevice::getHalDeviceVersion() const {
- if (mSensors == NULL) return -1;
- return SENSORS_DEVICE_API_VERSION_1_4;
-}
-
-status_t SensorDevice::flush(void* ident, int handle) {
- if (isClientDisabled(ident)) return INVALID_OPERATION;
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
- return StatusFromResult(mSensors->flush(handle));
-}
-
-bool SensorDevice::isClientDisabled(void* ident) {
- Mutex::Autolock _l(mLock);
- return isClientDisabledLocked(ident);
-}
-
-bool SensorDevice::isClientDisabledLocked(void* ident) {
- return mDisabledClients.indexOf(ident) >= 0;
-}
-
-void SensorDevice::enableAllSensors() {
- Mutex::Autolock _l(mLock);
- mDisabledClients.clear();
- ALOGI("cleared mDisabledClients");
- for (size_t i = 0; i< mActivationCount.size(); ++i) {
- Info& info = mActivationCount.editValueAt(i);
- if (info.batchParams.isEmpty()) continue;
- info.selectBatchParams();
- const int sensor_handle = mActivationCount.keyAt(i);
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
- sensor_handle);
- status_t err = StatusFromResult(
- mSensors->batch(
- sensor_handle,
- info.bestBatchParams.batchDelay,
- info.bestBatchParams.batchTimeout));
- ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
-
- if (err == NO_ERROR) {
- err = StatusFromResult(
- mSensors->activate(sensor_handle, 1 /* enabled */));
- ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
- }
- }
-}
-
-void SensorDevice::disableAllSensors() {
- Mutex::Autolock _l(mLock);
- for (size_t i = 0; i< mActivationCount.size(); ++i) {
- const Info& info = mActivationCount.valueAt(i);
- // Check if this sensor has been activated previously and disable it.
- if (info.batchParams.size() > 0) {
- const int sensor_handle = mActivationCount.keyAt(i);
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
- sensor_handle);
- mSensors->activate(sensor_handle, 0 /* enabled */);
-
- // Add all the connections that were registered for this sensor to the disabled
- // clients list.
- for (size_t j = 0; j < info.batchParams.size(); ++j) {
- mDisabledClients.add(info.batchParams.keyAt(j));
- ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
- }
- }
- }
-}
-
-status_t SensorDevice::injectSensorData(
- const sensors_event_t *injected_sensor_event) {
- ALOGD_IF(DEBUG_CONNECTIONS,
- "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
- injected_sensor_event->sensor,
- injected_sensor_event->timestamp, injected_sensor_event->data[0],
- injected_sensor_event->data[1], injected_sensor_event->data[2],
- injected_sensor_event->data[3], injected_sensor_event->data[4],
- injected_sensor_event->data[5]);
-
- Event ev;
- convertFromSensorEvent(*injected_sensor_event, &ev);
-
- return StatusFromResult(mSensors->injectSensorData(ev));
-}
-
-status_t SensorDevice::setMode(uint32_t mode) {
-
- return StatusFromResult(
- mSensors->setOperationMode(
- static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
-}
-
-// ---------------------------------------------------------------------------
-
-int SensorDevice::Info::numActiveClients() {
- SensorDevice& device(SensorDevice::getInstance());
- int num = 0;
- for (size_t i = 0; i < batchParams.size(); ++i) {
- if (!device.isClientDisabledLocked(batchParams.keyAt(i))) {
- ++num;
- }
- }
- return num;
-}
-
-status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,
- int64_t samplingPeriodNs,
- int64_t maxBatchReportLatencyNs) {
- ssize_t index = batchParams.indexOfKey(ident);
- if (index < 0) {
- ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%" PRId64 " timeout=%" PRId64 ") failed (%s)",
- ident, samplingPeriodNs, maxBatchReportLatencyNs, strerror(-index));
- return BAD_INDEX;
- }
- BatchParams& params = batchParams.editValueAt(index);
- params.flags = flags;
- params.batchDelay = samplingPeriodNs;
- params.batchTimeout = maxBatchReportLatencyNs;
- return NO_ERROR;
-}
-
-void SensorDevice::Info::selectBatchParams() {
- BatchParams bestParams(0, -1, -1);
- SensorDevice& device(SensorDevice::getInstance());
-
- for (size_t i = 0; i < batchParams.size(); ++i) {
- if (device.isClientDisabledLocked(batchParams.keyAt(i))) continue;
- BatchParams params = batchParams.valueAt(i);
- if (bestParams.batchDelay == -1 || params.batchDelay < bestParams.batchDelay) {
- bestParams.batchDelay = params.batchDelay;
- }
- if (bestParams.batchTimeout == -1 || params.batchTimeout < bestParams.batchTimeout) {
- bestParams.batchTimeout = params.batchTimeout;
- }
- }
- bestBatchParams = bestParams;
-}
-
-ssize_t SensorDevice::Info::removeBatchParamsForIdent(void* ident) {
- ssize_t idx = batchParams.removeItem(ident);
- if (idx >= 0) {
- selectBatchParams();
- }
- return idx;
-}
-
-void SensorDevice::notifyConnectionDestroyed(void* ident) {
- Mutex::Autolock _l(mLock);
- mDisabledClients.remove(ident);
-}
-
-int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
- Mutex::Autolock _l(mLock);
-
- SharedMemType type;
- switch (memory->type) {
- case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
- type = SharedMemType::ASHMEM;
- break;
- case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
- type = SharedMemType::GRALLOC;
- break;
- default:
- return BAD_VALUE;
- }
-
- SharedMemFormat format;
- if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) {
- return BAD_VALUE;
- }
- format = SharedMemFormat::SENSORS_EVENT;
-
- SharedMemInfo mem = {
- .type = type,
- .format = format,
- .size = static_cast<uint32_t>(memory->size),
- .memoryHandle = memory->handle,
- };
-
- int32_t ret;
- mSensors->registerDirectChannel(mem,
- [&ret](auto result, auto channelHandle) {
- if (result == Result::OK) {
- ret = channelHandle;
- } else {
- ret = StatusFromResult(result);
- }
- });
- return ret;
-}
-
-void SensorDevice::unregisterDirectChannel(int32_t channelHandle) {
- Mutex::Autolock _l(mLock);
- mSensors->unregisterDirectChannel(channelHandle);
-}
-
-int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle,
- int32_t channelHandle, const struct sensors_direct_cfg_t *config) {
- Mutex::Autolock _l(mLock);
-
- RateLevel rate;
- switch(config->rate_level) {
- case SENSOR_DIRECT_RATE_STOP:
- rate = RateLevel::STOP;
- break;
- case SENSOR_DIRECT_RATE_NORMAL:
- rate = RateLevel::NORMAL;
- break;
- case SENSOR_DIRECT_RATE_FAST:
- rate = RateLevel::FAST;
- break;
- case SENSOR_DIRECT_RATE_VERY_FAST:
- rate = RateLevel::VERY_FAST;
- break;
- default:
- return BAD_VALUE;
- }
-
- int32_t ret;
- mSensors->configDirectReport(sensorHandle, channelHandle, rate,
- [&ret, rate] (auto result, auto token) {
- if (rate == RateLevel::STOP) {
- ret = StatusFromResult(result);
- } else {
- if (result == Result::OK) {
- ret = token;
- } else {
- ret = StatusFromResult(result);
- }
- }
- });
-
- return ret;
-}
-
-bool SensorDevice::isDirectReportSupported() const {
- return mIsDirectReportSupported;
-}
-
-void SensorDevice::convertToSensorEvent(
- const Event &src, sensors_event_t *dst) {
- ::android::hardware::sensors::V1_0::implementation::convertToSensorEvent(
- src, dst);
-
- if (src.sensorType == SensorType::DYNAMIC_SENSOR_META) {
- const DynamicSensorInfo &dyn = src.u.dynamic;
-
- dst->dynamic_sensor_meta.connected = dyn.connected;
- dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
- if (dyn.connected) {
- auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
- CHECK(it != mConnectedDynamicSensors.end());
-
- dst->dynamic_sensor_meta.sensor = it->second;
-
- memcpy(dst->dynamic_sensor_meta.uuid,
- dyn.uuid.data(),
- sizeof(dst->dynamic_sensor_meta.uuid));
- }
- }
-}
-
-void SensorDevice::convertToSensorEvents(
- const hidl_vec<Event> &src,
- const hidl_vec<SensorInfo> &dynamicSensorsAdded,
- sensors_event_t *dst) {
- // Allocate a sensor_t structure for each dynamic sensor added and insert
- // it into the dictionary of connected dynamic sensors keyed by handle.
- for (size_t i = 0; i < dynamicSensorsAdded.size(); ++i) {
- const SensorInfo &info = dynamicSensorsAdded[i];
-
- auto it = mConnectedDynamicSensors.find(info.sensorHandle);
- CHECK(it == mConnectedDynamicSensors.end());
-
- sensor_t *sensor = new sensor_t;
- convertToSensor(info, sensor);
-
- mConnectedDynamicSensors.insert(
- std::make_pair(sensor->handle, sensor));
- }
-
- for (size_t i = 0; i < src.size(); ++i) {
- convertToSensorEvent(src[i], &dst[i]);
- }
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index aa8f189..9e81a8c 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -133,6 +133,7 @@
LOCAL_STATIC_LIBRARIES := \
libhwcomposer-command-buffer \
+ android.hardware.configstore-utils \
libtrace_proto \
libvkjson \
libvr_manager \
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 6c18ef7..9af4402 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -47,6 +47,9 @@
#include "SurfaceFlinger.h"
#include "Layer.h"
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
+
// ----------------------------------------------------------------------------
using namespace android;
// ----------------------------------------------------------------------------
@@ -57,6 +60,14 @@
static constexpr bool kEGLAndroidSwapRectangle = false;
#endif
+// retrieve triple buffer setting from configstore
+using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
+
+static bool useTripleFramebuffer = getBool<
+ ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::useTripleFramebuffer>(false);
+
#if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle)
// Dummy implementation in case it is missing.
inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) {
@@ -165,9 +176,9 @@
// initialize the display orientation transform.
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
-#ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS
- surface->allocateBuffers();
-#endif
+ if (useTripleFramebuffer) {
+ surface->allocateBuffers();
+ }
}
DisplayDevice::~DisplayDevice() {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6e0a489..a854aec 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -155,6 +155,10 @@
flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
#endif
mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
+
+ CompositorTiming compositorTiming;
+ flinger->getCompositorTiming(&compositorTiming);
+ mFrameEventHistory.initializeCompositorTiming(compositorTiming);
}
void Layer::onFirstRef() {
@@ -1882,10 +1886,10 @@
return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
}
-bool Layer::onPostComposition(
- const std::shared_ptr<FenceTime>& glDoneFence,
+bool Layer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
const std::shared_ptr<FenceTime>& presentFence,
- const std::shared_ptr<FenceTime>& retireFence) {
+ const std::shared_ptr<FenceTime>& retireFence,
+ const CompositorTiming& compositorTiming) {
mAcquireTimeline.updateSignalTimes();
mReleaseTimeline.updateSignalTimes();
@@ -1898,7 +1902,7 @@
{
Mutex::Autolock lock(mFrameEventHistoryMutex);
mFrameEventHistory.addPostComposition(mCurrentFrameNumber,
- glDoneFence, presentFence);
+ glDoneFence, presentFence, compositorTiming);
mFrameEventHistory.addRetire(mPreviousFrameNumber,
retireFence);
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 12166a8..8227dae 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -296,10 +296,10 @@
* called after composition.
* returns true if the layer latched a new buffer this frame.
*/
- bool onPostComposition(
- const std::shared_ptr<FenceTime>& glDoneFence,
+ bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
const std::shared_ptr<FenceTime>& presentFence,
- const std::shared_ptr<FenceTime>& retireFence);
+ const std::shared_ptr<FenceTime>& retireFence,
+ const CompositorTiming& compositorTiming);
#ifdef USE_HWC2
// If a buffer was replaced this frame, release the former buffer
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index cbc209d..c21c816 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -87,6 +87,7 @@
#include <cutils/compiler.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
#define DISPLAY_COUNT 1
@@ -100,22 +101,9 @@
namespace android {
+using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
-static sp<ISurfaceFlingerConfigs> getConfigs() {
- static sp<ISurfaceFlingerConfigs> configs
- = ISurfaceFlingerConfigs::getService();
- return configs;
-}
-
-static int64_t getVsyncEventPhaseOffsetNs() {
- int64_t ret = 1000000; // default value
- getConfigs()->vsyncEventPhaseOffsetNs([&](OptionalInt64 value) {
- if (value.specified) ret = value.value;
- });
- return ret;
-}
-
// This is the phase offset in nanoseconds of the software vsync event
// relative to the vsync event reported by HWComposer. The software vsync
// event is when SurfaceFlinger and Choreographer-based applications run each
@@ -136,10 +124,12 @@
// the latency will end up being an additional vsync period, and animations
// will hiccup. Therefore, this latency should be tuned somewhat
// conservatively (or at least with awareness of the trade-off being made).
-static int64_t vsyncPhaseOffsetNs = getVsyncEventPhaseOffsetNs();
+static int64_t vsyncPhaseOffsetNs = getInt64<
+ ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
// This is the phase offset at which SurfaceFlinger's composition runs.
-static const int64_t sfVsyncPhaseOffsetNs = SF_VSYNC_EVENT_PHASE_OFFSET_NS;
+static constexpr int64_t sfVsyncPhaseOffsetNs = SF_VSYNC_EVENT_PHASE_OFFSET_NS;
// ---------------------------------------------------------------------------
@@ -1126,6 +1116,11 @@
}
}
+void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
+ std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+ *compositorTiming = mCompositorTiming;
+}
+
void SurfaceFlinger::onHotplugReceived(int32_t disp, bool connected) {
ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false");
if (disp == DisplayDevice::DISPLAY_PRIMARY) {
@@ -1265,7 +1260,8 @@
bool frameMissed = !mHadClientComposition &&
mPreviousPresentFence != Fence::NO_FENCE &&
- mPreviousPresentFence->getSignalTime() == INT64_MAX;
+ (mPreviousPresentFence->getSignalTime() ==
+ Fence::SIGNAL_TIME_PENDING);
ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
if (mPropagateBackpressure && frameMissed) {
signalLayerUpdate();
@@ -1314,7 +1310,7 @@
setUpHWComposer();
doDebugFlashRegions();
doComposition();
- postComposition();
+ postComposition(refreshStartTime);
mPreviousPresentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
@@ -1389,7 +1385,61 @@
}
}
-void SurfaceFlinger::postComposition()
+void SurfaceFlinger::updateCompositorTiming(
+ nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
+ std::shared_ptr<FenceTime>& presentFenceTime) {
+ // Update queue of past composite+present times and determine the
+ // most recently known composite to present latency.
+ mCompositePresentTimes.push({compositeTime, presentFenceTime});
+ nsecs_t compositeToPresentLatency = -1;
+ while (!mCompositePresentTimes.empty()) {
+ CompositePresentTime& cpt = mCompositePresentTimes.front();
+ // Cached values should have been updated before calling this method,
+ // which helps avoid duplicate syscalls.
+ nsecs_t displayTime = cpt.display->getCachedSignalTime();
+ if (displayTime == Fence::SIGNAL_TIME_PENDING) {
+ break;
+ }
+ compositeToPresentLatency = displayTime - cpt.composite;
+ mCompositePresentTimes.pop();
+ }
+
+ // Don't let mCompositePresentTimes grow unbounded, just in case.
+ while (mCompositePresentTimes.size() > 16) {
+ mCompositePresentTimes.pop();
+ }
+
+ // Integer division and modulo round toward 0 not -inf, so we need to
+ // treat negative and positive offsets differently.
+ nsecs_t idealLatency = (sfVsyncPhaseOffsetNs >= 0) ?
+ (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
+ ((-sfVsyncPhaseOffsetNs) % vsyncInterval);
+
+ // Snap the latency to a value that removes scheduling jitter from the
+ // composition and present times, which often have >1ms of jitter.
+ // Reducing jitter is important if an app attempts to extrapolate
+ // something (such as user input) to an accurate diasplay time.
+ // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
+ // with (presentLatency % interval).
+ nsecs_t snappedCompositeToPresentLatency = -1;
+ if (compositeToPresentLatency >= 0) {
+ nsecs_t bias = vsyncInterval / 2;
+ int64_t extraVsyncs =
+ (compositeToPresentLatency - idealLatency + bias) /
+ vsyncInterval;
+ nsecs_t extraLatency = extraVsyncs * vsyncInterval;
+ snappedCompositeToPresentLatency = idealLatency + extraLatency;
+ }
+
+ std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+ mCompositorTiming.deadline = vsyncPhase - idealLatency;
+ mCompositorTiming.interval = vsyncInterval;
+ if (snappedCompositeToPresentLatency >= 0) {
+ mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
+ }
+}
+
+void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
{
ATRACE_CALL();
ALOGV("postComposition");
@@ -1424,9 +1474,19 @@
} else {
retireFenceTime = &displayFenceTime;
}
+
+ nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
+ nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
+
+ // We use the refreshStartTime which might be sampled a little later than
+ // when we started doing work for this frame, but that should be okay
+ // since updateCompositorTiming has snapping logic.
+ updateCompositorTiming(
+ vsyncPhase, vsyncInterval, refreshStartTime, displayFenceTime);
+
mDrawingState.traverseInZOrder([&](Layer* layer) {
bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime,
- *presentFenceTime, *retireFenceTime);
+ *presentFenceTime, *retireFenceTime, mCompositorTiming);
if (frameLatched) {
recordBufferingStats(layer->getName().string(),
layer->getOccupancyHistory(false));
@@ -1471,9 +1531,8 @@
if (mHasPoweredOff) {
mHasPoweredOff = false;
} else {
- nsecs_t period = mPrimaryDispSync.getPeriod();
nsecs_t elapsedTime = currentTime - mLastSwapTime;
- size_t numPeriods = static_cast<size_t>(elapsedTime / period);
+ size_t numPeriods = static_cast<size_t>(elapsedTime / vsyncInterval);
if (numPeriods < NUM_BUCKETS - 1) {
mFrameBuckets[numPeriods] += elapsedTime;
} else {
@@ -2876,6 +2935,11 @@
const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
const nsecs_t period = activeConfig->getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(period);
+
+ {
+ std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+ mCompositorTiming.interval = period;
+ }
}
void SurfaceFlinger::initializeDisplays() {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 02e4a0c..f52bd2d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -42,6 +42,7 @@
#include <ui/PixelFormat.h>
#include <ui/mat4.h>
+#include <gui/FrameTimestamps.h>
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
#include <gui/OccupancyTracker.h>
@@ -65,7 +66,10 @@
#include "Effects/Daltonizer.h"
#include <map>
+#include <mutex>
+#include <queue>
#include <string>
+#include <utility>
namespace android {
@@ -413,7 +417,10 @@
Region& dirtyRegion, Region& opaqueRegion);
void preComposition(nsecs_t refreshStartTime);
- void postComposition();
+ void postComposition(nsecs_t refreshStartTime);
+ void updateCompositorTiming(
+ nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
+ std::shared_ptr<FenceTime>& presentFenceTime);
void rebuildLayerStacks();
void setUpHWComposer();
void doComposition();
@@ -434,12 +441,13 @@
/* ------------------------------------------------------------------------
* VSync
*/
- void enableHardwareVsync();
- void resyncToHardwareVsync(bool makeAvailable);
- void disableHardwareVsync(bool makeUnavailable);
+ void enableHardwareVsync();
+ void resyncToHardwareVsync(bool makeAvailable);
+ void disableHardwareVsync(bool makeUnavailable);
public:
- void resyncWithRateLimit();
+ void resyncWithRateLimit();
+ void getCompositorTiming(CompositorTiming* compositorTiming);
private:
/* ------------------------------------------------------------------------
@@ -581,6 +589,17 @@
bool mPrimaryHWVsyncEnabled;
bool mHWVsyncAvailable;
+ // protected by mCompositorTimingLock;
+ mutable std::mutex mCompositeTimingLock;
+ CompositorTiming mCompositorTiming;
+
+ // Only accessed from the main thread.
+ struct CompositePresentTime {
+ nsecs_t composite { -1 };
+ std::shared_ptr<FenceTime> display { FenceTime::NO_FENCE };
+ };
+ std::queue<CompositePresentTime> mCompositePresentTimes;
+
/* ------------------------------------------------------------------------
* Feature prototyping
*/
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 40a27e8..477eb27 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -1036,6 +1036,11 @@
}
}
+void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
+ std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+ *compositorTiming = mCompositorTiming;
+}
+
void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
if (mEventThread == NULL) {
// This is a temporary workaround for b/7145521. A non-null pointer
@@ -1114,7 +1119,7 @@
setUpHWComposer();
doDebugFlashRegions();
doComposition();
- postComposition();
+ postComposition(refreshStartTime);
}
void SurfaceFlinger::doDebugFlashRegions()
@@ -1171,7 +1176,61 @@
}
}
-void SurfaceFlinger::postComposition()
+void SurfaceFlinger::updateCompositorTiming(
+ nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
+ std::shared_ptr<FenceTime>& presentFenceTime) {
+ // Update queue of past composite+present times and determine the
+ // most recently known composite to present latency.
+ mCompositePresentTimes.push({compositeTime, presentFenceTime});
+ nsecs_t compositeToPresentLatency = -1;
+ while (!mCompositePresentTimes.empty()) {
+ CompositePresentTime& cpt = mCompositePresentTimes.front();
+ // Cached values should have been updated before calling this method,
+ // which helps avoid duplicate syscalls.
+ nsecs_t displayTime = cpt.display->getCachedSignalTime();
+ if (displayTime == Fence::SIGNAL_TIME_PENDING) {
+ break;
+ }
+ compositeToPresentLatency = displayTime - cpt.composite;
+ mCompositePresentTimes.pop();
+ }
+
+ // Don't let mCompositePresentTimes grow unbounded, just in case.
+ while (mCompositePresentTimes.size() > 16) {
+ mCompositePresentTimes.pop();
+ }
+
+ // Integer division and modulo round toward 0 not -inf, so we need to
+ // treat negative and positive offsets differently.
+ nsecs_t idealLatency = (sfVsyncPhaseOffsetNs >= 0) ?
+ (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
+ ((-sfVsyncPhaseOffsetNs) % vsyncInterval);
+
+ // Snap the latency to a value that removes scheduling jitter from the
+ // composition and present times, which often have >1ms of jitter.
+ // Reducing jitter is important if an app attempts to extrapolate
+ // something (such as user input) to an accurate diasplay time.
+ // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
+ // with (presentLatency % interval).
+ nsecs_t snappedCompositeToPresentLatency = -1;
+ if (compositeToPresentLatency >= 0) {
+ nsecs_t bias = vsyncInterval / 2;
+ int64_t extraVsyncs =
+ (compositeToPresentLatency - idealLatency + bias) /
+ vsyncInterval;
+ nsecs_t extraLatency = extraVsyncs * vsyncInterval;
+ snappedCompositeToPresentLatency = idealLatency + extraLatency;
+ }
+
+ std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+ mCompositorTiming.deadline = vsyncPhase - idealLatency;
+ mCompositorTiming.interval = vsyncInterval;
+ if (snappedCompositeToPresentLatency >= 0) {
+ mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
+ }
+}
+
+void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
{
const HWComposer& hwc = getHwComposer();
const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
@@ -1192,10 +1251,18 @@
mDisplayTimeline.push(retireFenceTime);
mDisplayTimeline.updateSignalTimes();
+ nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
+ nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
+
+ // We use the refreshStartTime which might be sampled a little later than
+ // when we started doing work for this frame, but that should be okay
+ // since updateCompositorTiming has snapping logic.
+ updateCompositorTiming(
+ vsyncPhase, vsyncInterval, refreshStartTime, retireFenceTime);
+
mDrawingState.traverseInZOrder([&](Layer* layer) {
bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime,
- presentFenceTime, retireFenceTime);
-
+ presentFenceTime, retireFenceTime, mCompositorTiming);
if (frameLatched) {
recordBufferingStats(layer->getName().string(),
layer->getOccupancyHistory(false));
diff --git a/services/vr/sensord/Android.mk b/services/vr/sensord/Android.mk
index 36d8400..e213bd6 100644
--- a/services/vr/sensord/Android.mk
+++ b/services/vr/sensord/Android.mk
@@ -46,21 +46,10 @@
cFlags := -DLOG_TAG=\"sensord\" \
-DTRACE=0
-ifeq ($(TARGET_USES_QCOM_BSP), true)
-ifneq ($(TARGET_QCOM_DISPLAY_VARIANT),)
- platform := .
-else
- platform := $(TARGET_BOARD_PLATFORM)
-endif
- cFlags += -DQCOM_B_FAMILY \
- -DQCOM_BSP
-endif
-
include $(CLEAR_VARS)
# Don't strip symbols so we see stack traces in logcat.
LOCAL_STRIP_MODULE := false
LOCAL_SRC_FILES := $(sourceFiles)
-PLATFORM := $(platform)
LOCAL_CFLAGS := $(cFlags)
LOCAL_STATIC_LIBRARIES := $(staticLibraries)
LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
diff --git a/services/vr/vr_window_manager/hwc_callback.cpp b/services/vr/vr_window_manager/hwc_callback.cpp
index 12a76d8..e0c6c08 100644
--- a/services/vr/vr_window_manager/hwc_callback.cpp
+++ b/services/vr/vr_window_manager/hwc_callback.cpp
@@ -12,11 +12,16 @@
namespace {
sp<GraphicBuffer> GetBufferFromHandle(const native_handle_t* handle) {
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ if (mapper.registerBuffer(handle) != OK) {
+ ALOGE("Failed to register buffer");
+ return nullptr;
+ }
+
uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
uint64_t producer_usage = 0, consumer_usage = 0;
int32_t format = 0;
- GraphicBufferMapper& mapper = GraphicBufferMapper::get();
if (mapper.getDimensions(handle, &width, &height) ||
mapper.getStride(handle, &stride) ||
mapper.getFormat(handle, &format) ||
@@ -33,10 +38,6 @@
sp<GraphicBuffer> buffer = new GraphicBuffer(
width, height, format, layer_count, producer_usage, consumer_usage,
stride, native_handle_clone(handle), true);
- if (mapper.registerBuffer(buffer.get()) != OK) {
- ALOGE("Failed to register buffer");
- return nullptr;
- }
return buffer;
}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index a23056c..32f777d 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -739,10 +739,8 @@
const InstanceData& data = GetData(physicalDevice);
static const std::array<VkExtensionProperties, 2> loader_extensions = {{
// WSI extensions
-#if 0 // Remove this "#if 0" once the VK_KHR_incremental_present extension is ratified
{VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION},
-#endif
{VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION},
}};