Merge "SF: Set up libscheduler headers"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 4dd4f79..f054596 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,6 +1,6 @@
[Builtin Hooks]
-clang_format = true
bpfmt = true
+clang_format = true
[Builtin Hooks Options]
# Only turn on clang-format check for the following subfolders.
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 9a8ec32..bb1d206 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -239,7 +239,7 @@
} },
{ "memory", "Memory", 0, {
{ OPT, "events/mm_event/mm_event_record/enable" },
- { OPT, "events/kmem/rss_stat/enable" },
+ { OPT, "events/synthetic/rss_stat_throttled/enable" },
{ OPT, "events/kmem/ion_heap_grow/enable" },
{ OPT, "events/kmem/ion_heap_shrink/enable" },
{ OPT, "events/ion/ion_stat/enable" },
diff --git a/cmds/installd/CacheItem.cpp b/cmds/installd/CacheItem.cpp
index e29ff4c..27690a3 100644
--- a/cmds/installd/CacheItem.cpp
+++ b/cmds/installd/CacheItem.cpp
@@ -116,6 +116,7 @@
break;
}
}
+ fts_close(fts);
} else {
if (tombstone) {
if (truncate(path.c_str(), 0) != 0) {
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 3ebdeee..80c0548 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -47,6 +47,15 @@
}
cc_binary {
+ name: "servicemanager.recovery",
+ stem: "servicemanager",
+ recovery: true,
+ defaults: ["servicemanager_defaults"],
+ init_rc: ["servicemanager.recovery.rc"],
+ srcs: ["main.cpp"],
+}
+
+cc_binary {
name: "vndservicemanager",
defaults: ["servicemanager_defaults"],
init_rc: ["vndservicemanager.rc"],
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
index 8c1beac..2fb9c2b 100644
--- a/cmds/servicemanager/main.cpp
+++ b/cmds/servicemanager/main.cpp
@@ -111,6 +111,10 @@
};
int main(int argc, char** argv) {
+#ifdef __ANDROID_RECOVERY__
+ android::base::InitLogging(argv, android::base::KernelLogger);
+#endif
+
if (argc > 2) {
LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
}
diff --git a/cmds/servicemanager/servicemanager.recovery.rc b/cmds/servicemanager/servicemanager.recovery.rc
new file mode 100644
index 0000000..067faf9
--- /dev/null
+++ b/cmds/servicemanager/servicemanager.recovery.rc
@@ -0,0 +1,4 @@
+service servicemanager /system/bin/servicemanager
+ disabled
+ group system readproc
+ seclabel u:r:servicemanager:s0
diff --git a/include/input/Input.h b/include/input/Input.h
index 7cc595a..1c79c4a 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -203,6 +203,10 @@
const char* inputEventTypeToString(int32_t type);
+std::string inputEventSourceToString(int32_t source);
+
+bool isFromSource(uint32_t source, uint32_t test);
+
/*
* Flags that flow alongside events in the input dispatch system to help with certain
* policy decisions such as waking from device sleep.
@@ -373,7 +377,6 @@
// window scale. The global scale will be applied to TOUCH/TOOL_MAJOR/MINOR
// axes, however the window scaling will not.
void scale(float globalScale, float windowXScale, float windowYScale);
- void applyOffset(float xOffset, float yOffset);
void transform(const ui::Transform& transform);
@@ -563,7 +566,7 @@
inline float getYOffset() const { return mTransform.ty(); }
- inline ui::Transform getTransform() const { return mTransform; }
+ inline const ui::Transform& getTransform() const { return mTransform; }
inline float getXPrecision() const { return mXPrecision; }
@@ -579,7 +582,7 @@
void setCursorPosition(float x, float y);
- ui::Transform getRawTransform() const { return mRawTransform; }
+ inline const ui::Transform& getRawTransform() const { return mRawTransform; }
static inline bool isValidCursorPosition(float x, float y) { return !isnan(x) && !isnan(y); }
@@ -840,15 +843,12 @@
inline bool getHasFocus() const { return mHasFocus; }
- inline bool getInTouchMode() const { return mInTouchMode; }
-
- void initialize(int32_t id, bool hasFocus, bool inTouchMode);
+ void initialize(int32_t id, bool hasFocus);
void initialize(const FocusEvent& from);
protected:
bool mHasFocus;
- bool mInTouchMode;
};
/*
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index d655b28..edcb615 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -178,10 +178,9 @@
struct Focus {
int32_t eventId;
- // The following 3 fields take up 4 bytes total
+ // The following 2 fields take up 4 bytes total
bool hasFocus;
- bool inTouchMode;
- uint8_t empty[2];
+ uint8_t empty[3];
inline size_t size() const { return sizeof(Focus); }
} focus;
@@ -381,7 +380,7 @@
* Returns DEAD_OBJECT if the channel's peer has been closed.
* Other errors probably indicate that the channel is broken.
*/
- status_t publishFocusEvent(uint32_t seq, int32_t eventId, bool hasFocus, bool inTouchMode);
+ status_t publishFocusEvent(uint32_t seq, int32_t eventId, bool hasFocus);
/* Publishes a capture event to the input channel.
*
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 8270ae5..d8101fa 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -202,7 +202,7 @@
sanitize: {
misc_undefined: ["integer"],
},
- min_sdk_version: "29",
+ min_sdk_version: "30",
tidy: true,
tidy_flags: [
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 745d9e9..ba57a98 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -824,7 +824,7 @@
const size_t padded = pad_size(len);
- // sanity check for integer overflow
+ // check for integer overflow
if (mDataPos+padded < mDataPos) {
return nullptr;
}
diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
index 5de64f8..09411e7 100644
--- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
@@ -190,9 +190,9 @@
BnCInterface() {}
virtual ~BnCInterface() {}
- SpAIBinder asBinder() override;
+ SpAIBinder asBinder() override final;
- bool isRemote() override { return false; }
+ bool isRemote() override final { return false; }
protected:
/**
@@ -215,9 +215,9 @@
explicit BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
virtual ~BpCInterface() {}
- SpAIBinder asBinder() override;
+ SpAIBinder asBinder() override final;
- bool isRemote() override { return AIBinder_isRemote(mBinder.get()); }
+ bool isRemote() override final { return AIBinder_isRemote(mBinder.get()); }
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override {
return AIBinder_dump(asBinder().get(), fd, args, numArgs);
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index d323022..4561d6e 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -20,6 +20,7 @@
"libdowncast_rs",
],
host_supported: true,
+ vendor_available: true,
target: {
darwin: {
enabled: false,
@@ -64,6 +65,7 @@
"libbinder_ndk",
],
host_supported: true,
+ vendor_available: true,
target: {
darwin: {
enabled: false,
@@ -105,6 +107,7 @@
"libbinder_ndk",
],
host_supported: true,
+ vendor_available: true,
// Currently necessary for host builds
// TODO(b/31559095): bionic on host should define this
diff --git a/libs/binder/rust/binder_tokio/lib.rs b/libs/binder/rust/binder_tokio/lib.rs
index 64833b6..91047be 100644
--- a/libs/binder/rust/binder_tokio/lib.rs
+++ b/libs/binder/rust/binder_tokio/lib.rs
@@ -35,6 +35,11 @@
/// Retrieve an existing service for a particular interface, sleeping for a few
/// seconds if it doesn't yet exist.
pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Result<Strong<T>, StatusCode> {
+ if binder::is_handling_transaction() {
+ // See comment in the BinderAsyncPool impl.
+ return binder::public_api::get_interface::<T>(name);
+ }
+
let name = name.to_string();
let res = tokio::task::spawn_blocking(move || {
binder::public_api::get_interface::<T>(&name)
@@ -54,6 +59,11 @@
/// Retrieve an existing service for a particular interface, or start it if it
/// is configured as a dynamic service and isn't yet started.
pub async fn wait_for_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Result<Strong<T>, StatusCode> {
+ if binder::is_handling_transaction() {
+ // See comment in the BinderAsyncPool impl.
+ return binder::public_api::wait_for_interface::<T>(name);
+ }
+
let name = name.to_string();
let res = tokio::task::spawn_blocking(move || {
binder::public_api::wait_for_interface::<T>(&name)
@@ -86,18 +96,27 @@
B: Send + 'a,
E: From<crate::StatusCode>,
{
- let handle = tokio::task::spawn_blocking(spawn_me);
- Box::pin(async move {
- // The `is_panic` branch is not actually reachable in Android as we compile
- // with `panic = abort`.
- match handle.await {
- Ok(res) => after_spawn(res).await,
- Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
- Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION.into()),
- Err(_) => Err(StatusCode::UNKNOWN_ERROR.into()),
- }
- })
+ if binder::is_handling_transaction() {
+ // We are currently on the thread pool for a binder server, so we should execute the
+ // transaction on the current thread so that the binder kernel driver is able to apply
+ // its deadlock prevention strategy to the sub-call.
+ //
+ // This shouldn't cause issues with blocking the thread as only one task will run in a
+ // call to `block_on`, so there aren't other tasks to block.
+ let result = spawn_me();
+ Box::pin(after_spawn(result))
+ } else {
+ let handle = tokio::task::spawn_blocking(spawn_me);
+ Box::pin(async move {
+ // The `is_panic` branch is not actually reachable in Android as we compile
+ // with `panic = abort`.
+ match handle.await {
+ Ok(res) => after_spawn(res).await,
+ Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
+ Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION.into()),
+ Err(_) => Err(StatusCode::UNKNOWN_ERROR.into()),
+ }
+ })
+ }
}
}
-
-
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index bd2e695..d09ac83 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -167,6 +167,7 @@
fn ping_binder(&mut self) -> Result<()>;
/// Indicate that the service intends to receive caller security contexts.
+ #[cfg(not(android_vndk))]
fn set_requesting_sid(&mut self, enable: bool);
/// Dump this object to the given file handle
@@ -635,6 +636,7 @@
pub struct BinderFeatures {
/// Indicates that the service intends to receive caller security contexts. This must be true
/// for `ThreadState::with_calling_sid` to work.
+ #[cfg(not(android_vndk))]
pub set_requesting_sid: bool,
// Ensure that clients include a ..BinderFeatures::default() to preserve backwards compatibility
// when new fields are added. #[non_exhaustive] doesn't work because it prevents struct
@@ -837,6 +839,7 @@
/// Create a new binder service.
pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T, features: $crate::BinderFeatures) -> $crate::Strong<dyn $interface> {
let mut binder = $crate::Binder::new_with_stability($native(Box::new(inner)), $stability);
+ #[cfg(not(android_vndk))]
$crate::IBinderInternal::set_requesting_sid(&mut binder, features.set_requesting_sid);
$crate::Strong::new(Box::new(binder))
}
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index cce55c0..b94dfa1 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -114,7 +114,7 @@
};
pub use crate::binder_async::{BoxFuture, BinderAsyncPool};
pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
-pub use native::{add_service, force_lazy_services_persist, register_lazy_service, Binder};
+pub use native::{add_service, force_lazy_services_persist, is_handling_transaction, register_lazy_service, Binder};
pub use parcel::{BorrowedParcel, Parcel};
pub use proxy::{get_interface, get_service, wait_for_interface, wait_for_service};
pub use proxy::{AssociateClass, DeathRecipient, Proxy, SpIBinder, WpIBinder};
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index f5d7187..b7c7ae4 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -212,7 +212,7 @@
/// Mark this binder object with local stability, which is vendor if we are
/// building for the VNDK and system otherwise.
- #[cfg(vendor_ndk)]
+ #[cfg(any(vendor_ndk, android_vndk))]
fn mark_local_stability(&mut self) {
unsafe {
// Safety: Self always contains a valid `AIBinder` pointer, so
@@ -223,7 +223,7 @@
/// Mark this binder object with local stability, which is vendor if we are
/// building for the VNDK and system otherwise.
- #[cfg(not(vendor_ndk))]
+ #[cfg(not(any(vendor_ndk, android_vndk)))]
fn mark_local_stability(&mut self) {
unsafe {
// Safety: Self always contains a valid `AIBinder` pointer, so
@@ -517,3 +517,12 @@
}
impl Interface for () {}
+
+/// Determine whether the current thread is currently executing an incoming
+/// transaction.
+pub fn is_handling_transaction() -> bool {
+ unsafe {
+ // Safety: This method is always safe to call.
+ sys::AIBinder_isHandlingTransaction()
+ }
+}
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index 83553d7..760d862 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -323,6 +323,7 @@
status_result(status)
}
+ #[cfg(not(android_vndk))]
fn set_requesting_sid(&mut self, enable: bool) {
unsafe { sys::AIBinder_setRequestingSid(self.as_native_mut(), enable) };
}
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index e9149f3..f05426f 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -407,18 +407,9 @@
// Release all buffers that are beyond the ones that we need to hold
while (mPendingRelease.size() > numPendingBuffersToHold) {
- const auto releaseBuffer = mPendingRelease.front();
+ const auto releasedBuffer = mPendingRelease.front();
mPendingRelease.pop_front();
- auto it = mSubmitted.find(releaseBuffer.callbackId);
- if (it == mSubmitted.end()) {
- BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s",
- releaseBuffer.callbackId.to_string().c_str());
- return;
- }
- mNumAcquired--;
- BQA_LOGV("released %s", releaseBuffer.callbackId.to_string().c_str());
- mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence);
- mSubmitted.erase(it);
+ releaseBuffer(releasedBuffer.callbackId, releasedBuffer.releaseFence);
// Don't process the transactions here if mWaitForTransactionCallback is set. Instead, let
// onFrameAvailable handle processing them since it will merge with the syncTransaction.
if (!mWaitForTransactionCallback) {
@@ -432,6 +423,20 @@
mCallbackCV.notify_all();
}
+void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId,
+ const sp<Fence>& releaseFence) {
+ auto it = mSubmitted.find(callbackId);
+ if (it == mSubmitted.end()) {
+ BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s",
+ callbackId.to_string().c_str());
+ return;
+ }
+ mNumAcquired--;
+ BQA_LOGV("released %s", callbackId.to_string().c_str());
+ mBufferItemConsumer->releaseBuffer(it->second, releaseFence);
+ mSubmitted.erase(it);
+}
+
void BLASTBufferQueue::acquireNextBufferLocked(
const std::optional<SurfaceComposerClient::Transaction*> transaction) {
ATRACE_CALL();
@@ -502,7 +507,6 @@
// Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
incStrong((void*)transactionCallbackThunk);
- incStrong((void*)transactionCommittedCallbackThunk);
const bool sizeHasChanged = mRequestedSize != mSize;
mSize = mRequestedSize;
@@ -522,7 +526,7 @@
t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata);
t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage);
t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
- t->addTransactionCommittedCallback(transactionCommittedCallbackThunk, static_cast<void*>(this));
+
mSurfaceControlsWithPendingCallback.push(mSurfaceControl);
if (updateDestinationFrame) {
@@ -589,34 +593,57 @@
mBufferItemConsumer->releaseBuffer(bufferItem, bufferItem.mFence);
}
+void BLASTBufferQueue::flushAndWaitForFreeBuffer(std::unique_lock<std::mutex>& lock) {
+ if (mWaitForTransactionCallback && mNumFrameAvailable > 0) {
+ // We are waiting on a previous sync's transaction callback so allow another sync
+ // transaction to proceed.
+ //
+ // We need to first flush out the transactions that were in between the two syncs.
+ // We do this by merging them into mSyncTransaction so any buffer merging will get
+ // a release callback invoked. The release callback will be async so we need to wait
+ // on max acquired to make sure we have the capacity to acquire another buffer.
+ if (maxBuffersAcquired(false /* includeExtraAcquire */)) {
+ BQA_LOGD("waiting to flush shadow queue...");
+ mCallbackCV.wait(lock);
+ }
+ while (mNumFrameAvailable > 0) {
+ // flush out the shadow queue
+ acquireAndReleaseBuffer();
+ }
+ }
+
+ while (maxBuffersAcquired(false /* includeExtraAcquire */)) {
+ BQA_LOGD("waiting for free buffer.");
+ mCallbackCV.wait(lock);
+ }
+}
+
void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
ATRACE_CALL();
std::unique_lock _lock{mMutex};
const bool syncTransactionSet = mSyncTransaction != nullptr;
BQA_LOGV("onFrameAvailable-start syncTransactionSet=%s", boolToString(syncTransactionSet));
+
if (syncTransactionSet) {
- if (mWaitForTransactionCallback) {
- // We are waiting on a previous sync's transaction callback so allow another sync
- // transaction to proceed.
- //
- // We need to first flush out the transactions that were in between the two syncs.
- // We do this by merging them into mSyncTransaction so any buffer merging will get
- // a release callback invoked. The release callback will be async so we need to wait
- // on max acquired to make sure we have the capacity to acquire another buffer.
- if (maxBuffersAcquired(false /* includeExtraAcquire */)) {
- BQA_LOGD("waiting to flush shadow queue...");
- mCallbackCV.wait(_lock);
- }
- while (mNumFrameAvailable > 0) {
- // flush out the shadow queue
- acquireAndReleaseBuffer();
+ bool mayNeedToWaitForBuffer = true;
+ // If we are going to re-use the same mSyncTransaction, release the buffer that may already
+ // be set in the Transaction. This is to allow us a free slot early to continue processing
+ // a new buffer.
+ if (!mAcquireSingleBuffer) {
+ auto bufferData = mSyncTransaction->getAndClearBuffer(mSurfaceControl);
+ if (bufferData) {
+ BQA_LOGD("Releasing previous buffer when syncing: framenumber=%" PRIu64,
+ bufferData->frameNumber);
+ releaseBuffer(bufferData->releaseCallbackId, bufferData->acquireFence);
+ // Because we just released a buffer, we know there's no need to wait for a free
+ // buffer.
+ mayNeedToWaitForBuffer = false;
}
}
- while (maxBuffersAcquired(false /* includeExtraAcquire */)) {
- BQA_LOGD("waiting for free buffer.");
- mCallbackCV.wait(_lock);
+ if (mayNeedToWaitForBuffer) {
+ flushAndWaitForFreeBuffer(_lock);
}
}
@@ -629,8 +656,17 @@
boolToString(syncTransactionSet));
if (syncTransactionSet) {
- acquireNextBufferLocked(std::move(mSyncTransaction));
- mSyncTransaction = nullptr;
+ acquireNextBufferLocked(mSyncTransaction);
+
+ // Only need a commit callback when syncing to ensure the buffer that's synced has been sent
+ // to SF
+ incStrong((void*)transactionCommittedCallbackThunk);
+ mSyncTransaction->addTransactionCommittedCallback(transactionCommittedCallbackThunk,
+ static_cast<void*>(this));
+
+ if (mAcquireSingleBuffer) {
+ mSyncTransaction = nullptr;
+ }
mWaitForTransactionCallback = true;
} else if (!mWaitForTransactionCallback) {
acquireNextBufferLocked(std::nullopt);
@@ -652,9 +688,11 @@
mDequeueTimestamps.erase(bufferId);
};
-void BLASTBufferQueue::setSyncTransaction(SurfaceComposerClient::Transaction* t) {
+void BLASTBufferQueue::setSyncTransaction(SurfaceComposerClient::Transaction* t,
+ bool acquireSingleBuffer) {
std::lock_guard _lock{mMutex};
mSyncTransaction = t;
+ mAcquireSingleBuffer = mSyncTransaction ? acquireSingleBuffer : true;
}
bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) {
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index 8edf604..a626970 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -71,6 +71,7 @@
case HAL_PIXEL_FORMAT_Y8:
case HAL_PIXEL_FORMAT_Y16:
case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_RAW12:
case HAL_PIXEL_FORMAT_RAW10:
case HAL_PIXEL_FORMAT_RAW_OPAQUE:
case HAL_PIXEL_FORMAT_BLOB:
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index 8379675..ee80082 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -182,7 +182,6 @@
outVsyncEventData->id = ev.vsync.vsyncId;
outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp;
outVsyncEventData->frameInterval = ev.vsync.frameInterval;
- outVsyncEventData->expectedPresentTime = ev.vsync.expectedVSyncTimestamp;
outVsyncEventData->preferredFrameTimelineIndex =
ev.vsync.preferredFrameTimelineIndex;
populateFrameTimelines(ev, outVsyncEventData);
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index f848e4f..cd1c810 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -502,6 +502,10 @@
what |= eDropInputModeChanged;
dropInputMode = other.dropInputMode;
}
+ if (other.what & eColorChanged) {
+ what |= eColorChanged;
+ color = other.color;
+ }
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
"other.what=0x%" PRIX64 " what=0x%" PRIX64 " unmerged flags=0x%" PRIX64,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 2713be0..b139cf1 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -413,6 +413,14 @@
return callback;
}
+void TransactionCompletedListener::removeReleaseBufferCallback(
+ const ReleaseCallbackId& callbackId) {
+ {
+ std::scoped_lock<std::mutex> lock(mMutex);
+ popReleaseBufferCallbackLocked(callbackId);
+ }
+}
+
// ---------------------------------------------------------------------------
void removeDeadBufferCallback(void* /*context*/, uint64_t graphicBufferId);
@@ -1307,6 +1315,28 @@
return *this;
}
+std::optional<BufferData> SurfaceComposerClient::Transaction::getAndClearBuffer(
+ const sp<SurfaceControl>& sc) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ return std::nullopt;
+ }
+ if (!(s->what & layer_state_t::eBufferChanged)) {
+ return std::nullopt;
+ }
+
+ BufferData bufferData = s->bufferData;
+
+ TransactionCompletedListener::getInstance()->removeReleaseBufferCallback(
+ bufferData.releaseCallbackId);
+ BufferData emptyBufferData;
+ s->what &= ~layer_state_t::eBufferChanged;
+ s->bufferData = emptyBufferData;
+
+ mContainsBuffer = false;
+ return bufferData;
+}
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer(
const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer,
const std::optional<sp<Fence>>& fence, const std::optional<uint64_t>& frameNumber,
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index f718de8..d766173 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -94,7 +94,7 @@
const std::vector<SurfaceControlStats>& stats);
void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
std::optional<uint32_t> currentMaxAcquiredBufferCount);
- void setSyncTransaction(SurfaceComposerClient::Transaction* t);
+ void setSyncTransaction(SurfaceComposerClient::Transaction* t, bool acquireSingleBuffer = true);
void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber);
void applyPendingTransactions(uint64_t frameNumber);
@@ -132,6 +132,9 @@
void flushShadowQueue() REQUIRES(mMutex);
void acquireAndReleaseBuffer() REQUIRES(mMutex);
+ void releaseBuffer(const ReleaseCallbackId& callbackId, const sp<Fence>& releaseFence)
+ REQUIRES(mMutex);
+ void flushAndWaitForFreeBuffer(std::unique_lock<std::mutex>& lock);
std::string mName;
// Represents the queued buffer count from buffer queue,
@@ -239,7 +242,11 @@
std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex);
uint32_t mCurrentMaxAcquiredBufferCount;
- bool mWaitForTransactionCallback = false;
+ bool mWaitForTransactionCallback GUARDED_BY(mMutex) = false;
+
+ // Flag to determine if syncTransaction should only acquire a single buffer and then clear or
+ // continue to acquire buffers until explicitly cleared
+ bool mAcquireSingleBuffer GUARDED_BY(mMutex) = true;
};
} // namespace android
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index 8a3a476..40621dd 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -35,9 +35,6 @@
// The current frame interval in ns when this frame was scheduled.
int64_t frameInterval = 0;
- // The anticipated Vsync present time.
- int64_t expectedPresentTime = 0;
-
struct FrameTimeline {
// The Vsync Id corresponsing to this vsync event. This will be used to
// populate ISurfaceComposer::setFrameTimelineVsync and
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index e62c76e..e05c364 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -493,6 +493,7 @@
const std::optional<uint64_t>& frameNumber = std::nullopt,
const ReleaseCallbackId& id = ReleaseCallbackId::INVALID_ID,
ReleaseBufferCallback callback = nullptr);
+ std::optional<BufferData> getAndClearBuffer(const sp<SurfaceControl>& sc);
Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace);
Transaction& setHdrMetadata(const sp<SurfaceControl>& sc, const HdrMetadata& hdrMetadata);
Transaction& setSurfaceDamageRegion(const sp<SurfaceControl>& sc,
@@ -751,6 +752,8 @@
void onReleaseBuffer(ReleaseCallbackId, sp<Fence> releaseFence,
uint32_t currentMaxAcquiredBufferCount) override;
+ void removeReleaseBufferCallback(const ReleaseCallbackId& callbackId);
+
// For Testing Only
static void setInstance(const sp<TransactionCompletedListener>&);
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 194757f..48b8621 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -109,8 +109,8 @@
mBlastBufferQueueAdapter->update(sc, width, height, PIXEL_FORMAT_RGBA_8888);
}
- void setSyncTransaction(Transaction* sync) {
- mBlastBufferQueueAdapter->setSyncTransaction(sync);
+ void setSyncTransaction(Transaction* next, bool acquireSingleBuffer = true) {
+ mBlastBufferQueueAdapter->setSyncTransaction(next, acquireSingleBuffer);
}
int getWidth() { return mBlastBufferQueueAdapter->mSize.width; }
@@ -143,6 +143,11 @@
mBlastBufferQueueAdapter->waitForCallback(frameNumber);
}
+ void validateNumFramesSubmitted(int64_t numFramesSubmitted) {
+ std::unique_lock lock{mBlastBufferQueueAdapter->mMutex};
+ ASSERT_EQ(numFramesSubmitted, mBlastBufferQueueAdapter->mSubmitted.size());
+ }
+
private:
sp<TestBLASTBufferQueue> mBlastBufferQueueAdapter;
};
@@ -298,7 +303,7 @@
auto ret = igbp->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
nullptr, nullptr);
- ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
+ ASSERT_TRUE(ret == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION || ret == NO_ERROR);
ASSERT_EQ(OK, igbp->requestBuffer(slot, &buf));
uint32_t* bufData;
@@ -818,7 +823,7 @@
CallbackData callbackData;
transactionCallback.getCallbackData(&callbackData);
- // capture screen and verify that it is red
+ // capture screen and verify that it is green
ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
ASSERT_NO_FATAL_FAILURE(
checkScreenCapture(0, 255, 0, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
@@ -1025,6 +1030,45 @@
checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
}
+TEST_F(BLASTBufferQueueTest, SetSyncTransactionAcquireMultipleBuffers) {
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+
+ sp<IGraphicBufferProducer> igbProducer;
+ setUpProducer(adapter, igbProducer);
+
+ Transaction next;
+ adapter.setSyncTransaction(&next, false);
+ queueBuffer(igbProducer, 0, 255, 0, 0);
+ queueBuffer(igbProducer, 0, 0, 255, 0);
+ // There should only be one frame submitted since the first frame will be released.
+ adapter.validateNumFramesSubmitted(1);
+ adapter.setSyncTransaction(nullptr);
+
+ // queue non sync buffer, so this one should get blocked
+ // Add a present delay to allow the first screenshot to get taken.
+ nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count();
+ queueBuffer(igbProducer, 255, 0, 0, presentTimeDelay);
+
+ CallbackHelper transactionCallback;
+ next.addTransactionCompletedCallback(transactionCallback.function,
+ transactionCallback.getContext())
+ .apply();
+
+ CallbackData callbackData;
+ transactionCallback.getCallbackData(&callbackData);
+
+ // capture screen and verify that it is blue
+ ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
+ ASSERT_NO_FATAL_FAILURE(
+ checkScreenCapture(0, 0, 255, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
+
+ mProducerListener->waitOnNumberReleased(2);
+ // capture screen and verify that it is red
+ ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
+ ASSERT_NO_FATAL_FAILURE(
+ checkScreenCapture(255, 0, 0, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
+}
+
class TestProducerListener : public BnProducerListener {
public:
sp<IGraphicBufferProducer> mIgbp;
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 24a7720..69ea7df 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -66,10 +66,6 @@
return transformedXy - transformedOrigin;
}
-bool isFromSource(uint32_t source, uint32_t test) {
- return (source & test) == test;
-}
-
bool shouldDisregardTransformation(uint32_t source) {
// Do not apply any transformations to axes from joysticks or touchpads.
return isFromSource(source, AINPUT_SOURCE_CLASS_JOYSTICK) ||
@@ -148,6 +144,49 @@
return "UNKNOWN";
}
+std::string inputEventSourceToString(int32_t source) {
+ if (source == AINPUT_SOURCE_UNKNOWN) {
+ return "UNKNOWN";
+ }
+ if (source == static_cast<int32_t>(AINPUT_SOURCE_ANY)) {
+ return "ANY";
+ }
+ static const std::map<int32_t, const char*> SOURCES{
+ {AINPUT_SOURCE_KEYBOARD, "KEYBOARD"},
+ {AINPUT_SOURCE_DPAD, "DPAD"},
+ {AINPUT_SOURCE_GAMEPAD, "GAMEPAD"},
+ {AINPUT_SOURCE_TOUCHSCREEN, "TOUCHSCREEN"},
+ {AINPUT_SOURCE_MOUSE, "MOUSE"},
+ {AINPUT_SOURCE_STYLUS, "STYLUS"},
+ {AINPUT_SOURCE_BLUETOOTH_STYLUS, "BLUETOOTH_STYLUS"},
+ {AINPUT_SOURCE_TRACKBALL, "TRACKBALL"},
+ {AINPUT_SOURCE_MOUSE_RELATIVE, "MOUSE_RELATIVE"},
+ {AINPUT_SOURCE_TOUCHPAD, "TOUCHPAD"},
+ {AINPUT_SOURCE_TOUCH_NAVIGATION, "TOUCH_NAVIGATION"},
+ {AINPUT_SOURCE_JOYSTICK, "JOYSTICK"},
+ {AINPUT_SOURCE_HDMI, "HDMI"},
+ {AINPUT_SOURCE_SENSOR, "SENSOR"},
+ {AINPUT_SOURCE_ROTARY_ENCODER, "ROTARY_ENCODER"},
+ };
+ std::string result;
+ for (const auto& [source_entry, str] : SOURCES) {
+ if ((source & source_entry) == source_entry) {
+ if (!result.empty()) {
+ result += " | ";
+ }
+ result += str;
+ }
+ }
+ if (result.empty()) {
+ result = StringPrintf("0x%08x", source);
+ }
+ return result;
+}
+
+bool isFromSource(uint32_t source, uint32_t test) {
+ return (source & test) == test;
+}
+
VerifiedKeyEvent verifiedKeyEventFromKeyEvent(const KeyEvent& event) {
return {{VerifiedInputEvent::Type::KEY, event.getDeviceId(), event.getEventTime(),
event.getSource(), event.getDisplayId()},
@@ -304,11 +343,6 @@
scaleAxisValue(*this, AMOTION_EVENT_AXIS_RELATIVE_Y, windowYScale);
}
-void PointerCoords::applyOffset(float xOffset, float yOffset) {
- setAxisValue(AMOTION_EVENT_AXIS_X, getX() + xOffset);
- setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset);
-}
-
#ifdef __linux__
status_t PointerCoords::readFromParcel(Parcel* parcel) {
bits = parcel->readInt64();
@@ -820,17 +854,15 @@
// --- FocusEvent ---
-void FocusEvent::initialize(int32_t id, bool hasFocus, bool inTouchMode) {
+void FocusEvent::initialize(int32_t id, bool hasFocus) {
InputEvent::initialize(id, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN,
ADISPLAY_ID_NONE, INVALID_HMAC);
mHasFocus = hasFocus;
- mInTouchMode = inTouchMode;
}
void FocusEvent::initialize(const FocusEvent& from) {
InputEvent::initialize(from);
mHasFocus = from.mHasFocus;
- mInTouchMode = from.mInTouchMode;
}
// --- CaptureEvent ---
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 015bd81..ac84627 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -208,10 +208,8 @@
const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(
int32_t axis, uint32_t source) const {
- size_t numRanges = mMotionRanges.size();
- for (size_t i = 0; i < numRanges; i++) {
- const MotionRange& range = mMotionRanges[i];
- if (range.axis == axis && range.source == source) {
+ for (const MotionRange& range : mMotionRanges) {
+ if (range.axis == axis && isFromSource(range.source, source)) {
return ⦥
}
}
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 02a5a08..a065ce2 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -278,7 +278,6 @@
case InputMessage::Type::FOCUS: {
msg->body.focus.eventId = body.focus.eventId;
msg->body.focus.hasFocus = body.focus.hasFocus;
- msg->body.focus.inTouchMode = body.focus.inTouchMode;
break;
}
case InputMessage::Type::CAPTURE: {
@@ -622,13 +621,10 @@
return mChannel->sendMessage(&msg);
}
-status_t InputPublisher::publishFocusEvent(uint32_t seq, int32_t eventId, bool hasFocus,
- bool inTouchMode) {
+status_t InputPublisher::publishFocusEvent(uint32_t seq, int32_t eventId, bool hasFocus) {
if (ATRACE_ENABLED()) {
- std::string message =
- StringPrintf("publishFocusEvent(inputChannel=%s, hasFocus=%s, inTouchMode=%s)",
- mChannel->getName().c_str(), toString(hasFocus),
- toString(inTouchMode));
+ std::string message = StringPrintf("publishFocusEvent(inputChannel=%s, hasFocus=%s)",
+ mChannel->getName().c_str(), toString(hasFocus));
ATRACE_NAME(message.c_str());
}
@@ -637,7 +633,6 @@
msg.header.seq = seq;
msg.body.focus.eventId = eventId;
msg.body.focus.hasFocus = hasFocus;
- msg.body.focus.inTouchMode = inTouchMode;
return mChannel->sendMessage(&msg);
}
@@ -1371,8 +1366,7 @@
}
void InputConsumer::initializeFocusEvent(FocusEvent* event, const InputMessage* msg) {
- event->initialize(msg->body.focus.eventId, msg->body.focus.hasFocus,
- msg->body.focus.inTouchMode);
+ event->initialize(msg->body.focus.eventId, msg->body.focus.hasFocus);
}
void InputConsumer::initializeCaptureEvent(CaptureEvent* event, const InputMessage* msg) {
@@ -1491,9 +1485,8 @@
break;
}
case InputMessage::Type::FOCUS: {
- out += android::base::StringPrintf("hasFocus=%s inTouchMode=%s",
- toString(msg.body.focus.hasFocus),
- toString(msg.body.focus.inTouchMode));
+ out += android::base::StringPrintf("hasFocus=%s",
+ toString(msg.body.focus.hasFocus));
break;
}
case InputMessage::Type::CAPTURE: {
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 973194c..05bc0bc 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -290,10 +290,9 @@
constexpr uint32_t seq = 15;
int32_t eventId = InputEvent::nextId();
constexpr bool hasFocus = true;
- constexpr bool inTouchMode = true;
const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
- status = mPublisher->publishFocusEvent(seq, eventId, hasFocus, inTouchMode);
+ status = mPublisher->publishFocusEvent(seq, eventId, hasFocus);
ASSERT_EQ(OK, status) << "publisher publishFocusEvent should return OK";
uint32_t consumeSeq;
@@ -309,7 +308,6 @@
EXPECT_EQ(seq, consumeSeq);
EXPECT_EQ(eventId, focusEvent->getId());
EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
- EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
status = mConsumer->sendFinishedSignal(seq, true);
ASSERT_EQ(OK, status) << "consumer sendFinishedSignal should return OK";
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 2f88704..b6a9476 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -84,8 +84,7 @@
CHECK_OFFSET(InputMessage::Body::Focus, eventId, 0);
CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 4);
- CHECK_OFFSET(InputMessage::Body::Focus, inTouchMode, 5);
- CHECK_OFFSET(InputMessage::Body::Focus, empty, 6);
+ CHECK_OFFSET(InputMessage::Body::Focus, empty, 5);
CHECK_OFFSET(InputMessage::Body::Capture, eventId, 0);
CHECK_OFFSET(InputMessage::Body::Capture, pointerCaptureEnabled, 4);
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 93e7239..c447d31 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -162,6 +162,8 @@
static_assert(static_cast<int>(ADATASPACE_SCRGB) == static_cast<int>(HAL_DATASPACE_V0_SCRGB));
static_assert(static_cast<int>(ADATASPACE_DISPLAY_P3) == static_cast<int>(HAL_DATASPACE_DISPLAY_P3));
static_assert(static_cast<int>(ADATASPACE_BT2020_PQ) == static_cast<int>(HAL_DATASPACE_BT2020_PQ));
+ static_assert(static_cast<int>(ADATASPACE_BT2020_ITU_PQ) ==
+ static_cast<int>(HAL_DATASPACE_BT2020_ITU_PQ));
static_assert(static_cast<int>(ADATASPACE_ADOBE_RGB) == static_cast<int>(HAL_DATASPACE_ADOBE_RGB));
static_assert(static_cast<int>(ADATASPACE_JFIF) == static_cast<int>(HAL_DATASPACE_V0_JFIF));
static_assert(static_cast<int>(ADATASPACE_BT601_625) == static_cast<int>(HAL_DATASPACE_V0_BT601_625));
@@ -170,6 +172,10 @@
static_assert(static_cast<int>(ADATASPACE_BT709) == static_cast<int>(HAL_DATASPACE_V0_BT709));
static_assert(static_cast<int>(ADATASPACE_DCI_P3) == static_cast<int>(HAL_DATASPACE_DCI_P3));
static_assert(static_cast<int>(ADATASPACE_SRGB_LINEAR) == static_cast<int>(HAL_DATASPACE_V0_SRGB_LINEAR));
+ static_assert(static_cast<int>(ADATASPACE_BT2020_HLG) ==
+ static_cast<int>(HAL_DATASPACE_BT2020_HLG));
+ static_assert(static_cast<int>(ADATASPACE_BT2020_ITU_HLG) ==
+ static_cast<int>(HAL_DATASPACE_BT2020_ITU_HLG));
if (!window || !query(window, NATIVE_WINDOW_IS_VALID) ||
!isDataSpaceValid(window, dataSpace)) {
diff --git a/libs/nativewindow/include/android/data_space.h b/libs/nativewindow/include/android/data_space.h
index 0565f42..30ac220 100644
--- a/libs/nativewindow/include/android/data_space.h
+++ b/libs/nativewindow/include/android/data_space.h
@@ -444,6 +444,15 @@
ADATASPACE_BT2020_PQ = 163971072, // STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_FULL
/**
+ * ITU-R Recommendation 2020 (BT.2020)
+ *
+ * Ultra High-definition television
+ *
+ * Use limited range, SMPTE 2084 (PQ) transfer and BT2020 standard
+ */
+ ADATASPACE_BT2020_ITU_PQ = 298188800, // STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_LIMITED
+
+ /**
* Adobe RGB
*
* Use full range, gamma 2.2 transfer and Adobe RGB primaries
@@ -519,6 +528,20 @@
* components.
*/
ADATASPACE_SRGB_LINEAR = 138477568, // STANDARD_BT709 | TRANSFER_LINEAR | RANGE_FULL
+
+ /**
+ * Hybrid Log Gamma encoding:
+ *
+ * Use full range, hybrid log gamma transfer and BT2020 standard.
+ */
+ ADATASPACE_BT2020_HLG = 168165376, // STANDARD_BT2020 | TRANSFER_HLG | RANGE_FULL
+
+ /**
+ * ITU Hybrid Log Gamma encoding:
+ *
+ * Use limited range, hybrid log gamma transfer and BT2020 standard.
+ */
+ ADATASPACE_BT2020_ITU_HLG = 302383104 // STANDARD_BT2020 | TRANSFER_HLG | RANGE_LIMITED
};
__END_DECLS
diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp
index a9ea690..c7ad058 100644
--- a/libs/renderengine/RenderEngine.cpp
+++ b/libs/renderengine/RenderEngine.cpp
@@ -27,54 +27,22 @@
namespace renderengine {
std::unique_ptr<RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) {
- RenderEngineType renderEngineType = args.renderEngineType;
-
- // Keep the ability to override by PROPERTIES:
- char prop[PROPERTY_VALUE_MAX];
- property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "");
- if (strcmp(prop, "gles") == 0) {
- renderEngineType = RenderEngineType::GLES;
- }
- if (strcmp(prop, "threaded") == 0) {
- renderEngineType = RenderEngineType::THREADED;
- }
- if (strcmp(prop, "skiagl") == 0) {
- renderEngineType = RenderEngineType::SKIA_GL;
- }
- if (strcmp(prop, "skiaglthreaded") == 0) {
- renderEngineType = RenderEngineType::SKIA_GL_THREADED;
- }
-
- switch (renderEngineType) {
+ switch (args.renderEngineType) {
case RenderEngineType::THREADED:
ALOGD("Threaded RenderEngine with GLES Backend");
return renderengine::threaded::RenderEngineThreaded::create(
[args]() { return android::renderengine::gl::GLESRenderEngine::create(args); },
- renderEngineType);
+ args.renderEngineType);
case RenderEngineType::SKIA_GL:
ALOGD("RenderEngine with SkiaGL Backend");
return renderengine::skia::SkiaGLRenderEngine::create(args);
case RenderEngineType::SKIA_GL_THREADED: {
- // These need to be recreated, since they are a constant reference, and we need to
- // let SkiaRE know that it's running as threaded, and all GL operation will happen on
- // the same thread.
- RenderEngineCreationArgs skiaArgs =
- RenderEngineCreationArgs::Builder()
- .setPixelFormat(args.pixelFormat)
- .setImageCacheSize(args.imageCacheSize)
- .setUseColorManagerment(args.useColorManagement)
- .setEnableProtectedContext(args.enableProtectedContext)
- .setPrecacheToneMapperShaderOnly(args.precacheToneMapperShaderOnly)
- .setSupportsBackgroundBlur(args.supportsBackgroundBlur)
- .setContextPriority(args.contextPriority)
- .setRenderEngineType(renderEngineType)
- .build();
ALOGD("Threaded RenderEngine with SkiaGL Backend");
return renderengine::threaded::RenderEngineThreaded::create(
- [skiaArgs]() {
- return android::renderengine::skia::SkiaGLRenderEngine::create(skiaArgs);
+ [args]() {
+ return android::renderengine::skia::SkiaGLRenderEngine::create(args);
},
- renderEngineType);
+ args.renderEngineType);
}
case RenderEngineType::GLES:
default:
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index 53136e4..b43a3aa 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -104,7 +104,7 @@
uniform float4x4 in_rgbToXyz;
uniform float4x4 in_xyzToRgb;
float3 ToXYZ(float3 rgb) {
- return clamp((in_rgbToXyz * float4(rgb, 1.0)).rgb, 0.0, 1.0);
+ return (in_rgbToXyz * float4(rgb, 1.0)).rgb;
}
float3 ToRGB(float3 xyz) {
@@ -114,7 +114,8 @@
}
// Conversion from relative light to absolute light (maps from [0, 1] to [0, maxNits])
-static void generateLuminanceScalesForOOTF(ui::Dataspace inputDataspace, SkString& shader) {
+static void generateLuminanceScalesForOOTF(ui::Dataspace inputDataspace,
+ ui::Dataspace outputDataspace, SkString& shader) {
switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
case HAL_DATASPACE_TRANSFER_ST2084:
shader.append(R"(
@@ -131,12 +132,26 @@
)");
break;
default:
- shader.append(R"(
- float3 ScaleLuminance(float3 xyz) {
- return xyz * in_libtonemap_inputMaxLuminance;
- }
- )");
- break;
+ switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ case HAL_DATASPACE_TRANSFER_HLG:
+ // SDR -> HDR tonemap
+ shader.append(R"(
+ float3 ScaleLuminance(float3 xyz) {
+ return xyz * in_libtonemap_inputMaxLuminance;
+ }
+ )");
+ break;
+ default:
+ // Input and output are both SDR, so no tone-mapping is expected so
+ // no-op the luminance normalization.
+ shader.append(R"(
+ float3 ScaleLuminance(float3 xyz) {
+ return xyz * in_libtonemap_displayMaxLuminance;
+ }
+ )");
+ break;
+ }
}
}
@@ -174,7 +189,7 @@
toAidlDataspace(outputDataspace))
.c_str());
- generateLuminanceScalesForOOTF(inputDataspace, shader);
+ generateLuminanceScalesForOOTF(inputDataspace, outputDataspace, shader);
generateLuminanceNormalizationForOOTF(outputDataspace, shader);
shader.append(R"(
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index c2c05f4..5bc08ac 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -27,6 +27,9 @@
#include <renderengine/ExternalTexture.h>
#include <renderengine/RenderEngine.h>
#include <sync/sync.h>
+#include <system/graphics-base-v1.0.h>
+#include <tonemap/tonemap.h>
+#include <ui/ColorSpace.h>
#include <ui/PixelFormat.h>
#include <chrono>
@@ -282,6 +285,13 @@
void expectBufferColor(const Rect& rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a,
uint8_t tolerance = 0) {
+ auto generator = [=](Point) { return ubyte4(r, g, b, a); };
+ expectBufferColor(rect, generator, tolerance);
+ }
+
+ using ColorGenerator = std::function<ubyte4(Point location)>;
+
+ void expectBufferColor(const Rect& rect, ColorGenerator generator, uint8_t tolerance = 0) {
auto colorCompare = [tolerance](const uint8_t* colorA, const uint8_t* colorB) {
auto colorBitCompare = [tolerance](uint8_t a, uint8_t b) {
uint8_t tmp = a >= b ? a - b : b - a;
@@ -290,10 +300,10 @@
return std::equal(colorA, colorA + 4, colorB, colorBitCompare);
};
- expectBufferColor(rect, r, g, b, a, colorCompare);
+ expectBufferColor(rect, generator, colorCompare);
}
- void expectBufferColor(const Rect& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a,
+ void expectBufferColor(const Rect& region, ColorGenerator generator,
std::function<bool(const uint8_t* a, const uint8_t* b)> colorCompare) {
uint8_t* pixels;
mBuffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
@@ -304,19 +314,22 @@
const uint8_t* src = pixels +
(mBuffer->getBuffer()->getStride() * (region.top + j) + region.left) * 4;
for (int32_t i = 0; i < region.getWidth(); i++) {
- const uint8_t expected[4] = {r, g, b, a};
- bool equal = colorCompare(src, expected);
- EXPECT_TRUE(equal)
+ const auto location = Point(region.left + i, region.top + j);
+ const ubyte4 colors = generator(location);
+ const uint8_t expected[4] = {colors.r, colors.g, colors.b, colors.a};
+ bool colorMatches = colorCompare(src, expected);
+ EXPECT_TRUE(colorMatches)
<< GetParam()->name().c_str() << ": "
- << "pixel @ (" << region.left + i << ", " << region.top + j << "): "
- << "expected (" << static_cast<uint32_t>(r) << ", "
- << static_cast<uint32_t>(g) << ", " << static_cast<uint32_t>(b) << ", "
- << static_cast<uint32_t>(a) << "), "
+ << "pixel @ (" << location.x << ", " << location.y << "): "
+ << "expected (" << static_cast<uint32_t>(colors.r) << ", "
+ << static_cast<uint32_t>(colors.g) << ", "
+ << static_cast<uint32_t>(colors.b) << ", "
+ << static_cast<uint32_t>(colors.a) << "), "
<< "got (" << static_cast<uint32_t>(src[0]) << ", "
<< static_cast<uint32_t>(src[1]) << ", " << static_cast<uint32_t>(src[2])
<< ", " << static_cast<uint32_t>(src[3]) << ")";
src += 4;
- if (!equal && ++fails >= maxFails) {
+ if (!colorMatches && ++fails >= maxFails) {
break;
}
}
@@ -328,10 +341,11 @@
}
void expectAlpha(const Rect& rect, uint8_t a) {
+ auto generator = [=](Point) { return ubyte4(0, 0, 0, a); };
auto colorCompare = [](const uint8_t* colorA, const uint8_t* colorB) {
return colorA[3] == colorB[3];
};
- expectBufferColor(rect, 0.0f /* r */, 0.0f /*g */, 0.0f /* b */, a, colorCompare);
+ expectBufferColor(rect, generator, colorCompare);
}
void expectShadowColor(const renderengine::LayerSettings& castingLayer,
@@ -1099,7 +1113,7 @@
layer.source.buffer.buffer = buf;
layer.source.buffer.textureName = texName;
// Transform coordinates to only be inside the red quadrant.
- layer.source.buffer.textureTransform = mat4::scale(vec4(0.2, 0.2, 1, 1));
+ layer.source.buffer.textureTransform = mat4::scale(vec4(0.2f, 0.2f, 1.f, 1.f));
layer.alpha = 1.0f;
layer.geometry.boundaries = Rect(1, 1).toFloatRect();
@@ -1281,7 +1295,8 @@
settings.clip = fullscreenRect();
// 255, 255, 255, 255 is full opaque white.
- const ubyte4 backgroundColor(255.f, 255.f, 255.f, 255.f);
+ const ubyte4 backgroundColor(static_cast<uint8_t>(255), static_cast<uint8_t>(255),
+ static_cast<uint8_t>(255), static_cast<uint8_t>(255));
// Create layer with given color.
renderengine::LayerSettings bgLayer;
bgLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
@@ -1615,7 +1630,8 @@
TEST_P(RenderEngineTest, drawLayers_fillShadow_castsWithoutCasterLayer) {
initializeRenderEngine();
- const ubyte4 backgroundColor(255, 255, 255, 255);
+ const ubyte4 backgroundColor(static_cast<uint8_t>(255), static_cast<uint8_t>(255),
+ static_cast<uint8_t>(255), static_cast<uint8_t>(255));
const float shadowLength = 5.0f;
Rect casterBounds(DEFAULT_DISPLAY_WIDTH / 3.0f, DEFAULT_DISPLAY_HEIGHT / 3.0f);
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
@@ -1630,8 +1646,10 @@
TEST_P(RenderEngineTest, drawLayers_fillShadow_casterLayerMinSize) {
initializeRenderEngine();
- const ubyte4 casterColor(255, 0, 0, 255);
- const ubyte4 backgroundColor(255, 255, 255, 255);
+ const ubyte4 casterColor(static_cast<uint8_t>(255), static_cast<uint8_t>(0),
+ static_cast<uint8_t>(0), static_cast<uint8_t>(255));
+ const ubyte4 backgroundColor(static_cast<uint8_t>(255), static_cast<uint8_t>(255),
+ static_cast<uint8_t>(255), static_cast<uint8_t>(255));
const float shadowLength = 5.0f;
Rect casterBounds(1, 1);
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
@@ -1649,8 +1667,10 @@
TEST_P(RenderEngineTest, drawLayers_fillShadow_casterColorLayer) {
initializeRenderEngine();
- const ubyte4 casterColor(255, 0, 0, 255);
- const ubyte4 backgroundColor(255, 255, 255, 255);
+ const ubyte4 casterColor(static_cast<uint8_t>(255), static_cast<uint8_t>(0),
+ static_cast<uint8_t>(0), static_cast<uint8_t>(255));
+ const ubyte4 backgroundColor(static_cast<uint8_t>(255), static_cast<uint8_t>(255),
+ static_cast<uint8_t>(255), static_cast<uint8_t>(255));
const float shadowLength = 5.0f;
Rect casterBounds(DEFAULT_DISPLAY_WIDTH / 3.0f, DEFAULT_DISPLAY_HEIGHT / 3.0f);
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
@@ -1669,8 +1689,10 @@
TEST_P(RenderEngineTest, drawLayers_fillShadow_casterOpaqueBufferLayer) {
initializeRenderEngine();
- const ubyte4 casterColor(255, 0, 0, 255);
- const ubyte4 backgroundColor(255, 255, 255, 255);
+ const ubyte4 casterColor(static_cast<uint8_t>(255), static_cast<uint8_t>(0),
+ static_cast<uint8_t>(0), static_cast<uint8_t>(255));
+ const ubyte4 backgroundColor(static_cast<uint8_t>(255), static_cast<uint8_t>(255),
+ static_cast<uint8_t>(255), static_cast<uint8_t>(255));
const float shadowLength = 5.0f;
Rect casterBounds(DEFAULT_DISPLAY_WIDTH / 3.0f, DEFAULT_DISPLAY_HEIGHT / 3.0f);
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
@@ -1690,8 +1712,10 @@
TEST_P(RenderEngineTest, drawLayers_fillShadow_casterWithRoundedCorner) {
initializeRenderEngine();
- const ubyte4 casterColor(255, 0, 0, 255);
- const ubyte4 backgroundColor(255, 255, 255, 255);
+ const ubyte4 casterColor(static_cast<uint8_t>(255), static_cast<uint8_t>(0),
+ static_cast<uint8_t>(0), static_cast<uint8_t>(255));
+ const ubyte4 backgroundColor(static_cast<uint8_t>(255), static_cast<uint8_t>(255),
+ static_cast<uint8_t>(255), static_cast<uint8_t>(255));
const float shadowLength = 5.0f;
Rect casterBounds(DEFAULT_DISPLAY_WIDTH / 3.0f, DEFAULT_DISPLAY_HEIGHT / 3.0f);
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
@@ -2027,6 +2051,155 @@
expectBufferColor(rect, 0, 255, 0, 255);
}
}
+
+double EOTF_PQ(double channel) {
+ float m1 = (2610.0 / 4096.0) / 4.0;
+ float m2 = (2523.0 / 4096.0) * 128.0;
+ float c1 = (3424.0 / 4096.0);
+ float c2 = (2413.0 / 4096.0) * 32.0;
+ float c3 = (2392.0 / 4096.0) * 32.0;
+
+ float tmp = std::pow(std::clamp(channel, 0.0, 1.0), 1.0 / m2);
+ tmp = std::fmax(tmp - c1, 0.0) / (c2 - c3 * tmp);
+ return std::pow(tmp, 1.0 / m1);
+}
+
+vec3 EOTF_PQ(vec3 color) {
+ return vec3(EOTF_PQ(color.r), EOTF_PQ(color.g), EOTF_PQ(color.b));
+}
+
+double OETF_sRGB(double channel) {
+ return channel <= 0.0031308 ? channel * 12.92 : (pow(channel, 1.0 / 2.4) * 1.055) - 0.055;
+}
+
+int sign(float in) {
+ return in >= 0.0 ? 1 : -1;
+}
+
+vec3 OETF_sRGB(vec3 linear) {
+ return vec3(sign(linear.r) * OETF_sRGB(linear.r), sign(linear.g) * OETF_sRGB(linear.g),
+ sign(linear.b) * OETF_sRGB(linear.b));
+}
+
+TEST_P(RenderEngineTest, test_tonemapPQMatches) {
+ if (!GetParam()->useColorManagement()) {
+ return;
+ }
+
+ if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) {
+ return;
+ }
+
+ initializeRenderEngine();
+
+ constexpr int32_t kGreyLevels = 256;
+
+ const auto rect = Rect(0, 0, kGreyLevels, 1);
+ const renderengine::DisplaySettings display{
+ .physicalDisplay = rect,
+ .clip = rect,
+ .maxLuminance = 750.0f,
+ .outputDataspace = ui::Dataspace::DISPLAY_P3,
+ };
+
+ auto buf = std::make_shared<
+ renderengine::ExternalTexture>(new GraphicBuffer(kGreyLevels, 1,
+ HAL_PIXEL_FORMAT_RGBA_8888, 1,
+ GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_TEXTURE,
+ "input"),
+ *mRE,
+ renderengine::ExternalTexture::Usage::READABLE |
+ renderengine::ExternalTexture::Usage::WRITEABLE);
+ ASSERT_EQ(0, buf->getBuffer()->initCheck());
+
+ {
+ uint8_t* pixels;
+ buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+ reinterpret_cast<void**>(&pixels));
+
+ uint8_t color = 0;
+ for (int32_t j = 0; j < buf->getBuffer()->getHeight(); j++) {
+ uint8_t* dest = pixels + (buf->getBuffer()->getStride() * j * 4);
+ for (int32_t i = 0; i < buf->getBuffer()->getWidth(); i++) {
+ dest[0] = color;
+ dest[1] = color;
+ dest[2] = color;
+ dest[3] = 255;
+ color++;
+ dest += 4;
+ }
+ }
+ buf->getBuffer()->unlock();
+ }
+
+ mBuffer = std::make_shared<
+ renderengine::ExternalTexture>(new GraphicBuffer(kGreyLevels, 1,
+ HAL_PIXEL_FORMAT_RGBA_8888, 1,
+ GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_TEXTURE,
+ "output"),
+ *mRE,
+ renderengine::ExternalTexture::Usage::READABLE |
+ renderengine::ExternalTexture::Usage::WRITEABLE);
+ ASSERT_EQ(0, mBuffer->getBuffer()->initCheck());
+
+ const renderengine::LayerSettings layer{
+ .geometry.boundaries = rect.toFloatRect(),
+ .source =
+ renderengine::PixelSource{
+ .buffer =
+ renderengine::Buffer{
+ .buffer = std::move(buf),
+ .usePremultipliedAlpha = true,
+ },
+ },
+ .alpha = 1.0f,
+ .sourceDataspace = static_cast<ui::Dataspace>(HAL_DATASPACE_STANDARD_BT2020 |
+ HAL_DATASPACE_TRANSFER_ST2084 |
+ HAL_DATASPACE_RANGE_FULL),
+ };
+
+ std::vector<renderengine::LayerSettings> layers{layer};
+ invokeDraw(display, layers);
+
+ ColorSpace displayP3 = ColorSpace::DisplayP3();
+ ColorSpace bt2020 = ColorSpace::BT2020();
+
+ tonemap::Metadata metadata{.displayMaxLuminance = 750.0f};
+
+ auto generator = [=](Point location) {
+ const double normColor = static_cast<double>(location.x) / (kGreyLevels - 1);
+ const vec3 rgb = vec3(normColor, normColor, normColor);
+
+ const vec3 linearRGB = EOTF_PQ(rgb);
+
+ static constexpr float kMaxPQLuminance = 10000.f;
+ const vec3 xyz = bt2020.getRGBtoXYZ() * linearRGB * kMaxPQLuminance;
+ const double gain =
+ tonemap::getToneMapper()
+ ->lookupTonemapGain(static_cast<aidl::android::hardware::graphics::common::
+ Dataspace>(
+ HAL_DATASPACE_STANDARD_BT2020 |
+ HAL_DATASPACE_TRANSFER_ST2084 |
+ HAL_DATASPACE_RANGE_FULL),
+ static_cast<aidl::android::hardware::graphics::common::
+ Dataspace>(
+ ui::Dataspace::DISPLAY_P3),
+ linearRGB * 10000.0, xyz, metadata);
+ const vec3 scaledXYZ = xyz * gain / metadata.displayMaxLuminance;
+
+ const vec3 targetRGB = OETF_sRGB(displayP3.getXYZtoRGB() * scaledXYZ) * 255;
+ return ubyte4(static_cast<uint8_t>(targetRGB.r), static_cast<uint8_t>(targetRGB.g),
+ static_cast<uint8_t>(targetRGB.b), 255);
+ };
+
+ expectBufferColor(Rect(kGreyLevels, 1), generator, 2);
+}
} // namespace renderengine
} // namespace android
diff --git a/libs/tonemap/Android.bp b/libs/tonemap/Android.bp
index 231a342..5360fe2 100644
--- a/libs/tonemap/Android.bp
+++ b/libs/tonemap/Android.bp
@@ -30,7 +30,13 @@
shared_libs: [
"android.hardware.graphics.common-V3-ndk",
+ "liblog",
],
+
+ static_libs: [
+ "libmath",
+ ],
+
srcs: [
"tonemap.cpp",
],
diff --git a/libs/tonemap/include/tonemap/tonemap.h b/libs/tonemap/include/tonemap/tonemap.h
index d350e16..bd7b72d 100644
--- a/libs/tonemap/include/tonemap/tonemap.h
+++ b/libs/tonemap/include/tonemap/tonemap.h
@@ -17,6 +17,7 @@
#pragma once
#include <aidl/android/hardware/graphics/common/Dataspace.h>
+#include <math/vec3.h>
#include <string>
#include <vector>
@@ -48,7 +49,9 @@
class ToneMapper {
public:
virtual ~ToneMapper() {}
- // Constructs a tonemap shader whose shader language is SkSL
+ // Constructs a tonemap shader whose shader language is SkSL, which tonemaps from an
+ // input whose dataspace is described by sourceDataspace, to an output whose dataspace
+ // is described by destinationDataspace
//
// The returned shader string *must* contain a function with the following signature:
// float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz);
@@ -94,6 +97,19 @@
// assume that there are predefined floats in_libtonemap_displayMaxLuminance and
// in_libtonemap_inputMaxLuminance inside of the body of the tone-mapping shader.
virtual std::vector<ShaderUniform> generateShaderSkSLUniforms(const Metadata& metadata) = 0;
+
+ // CPU implementation of the tonemapping gain. This must match the GPU implementation returned
+ // by generateTonemapGainShaderSKSL() above, with some epsilon difference to account for
+ // differences in hardware precision.
+ //
+ // The gain is computed assuming an input described by sourceDataspace, tonemapped to an output
+ // described by destinationDataspace. To compute the gain, the input colors are provided by
+ // linearRGB, which is the RGB colors in linear space. The colors in XYZ space are also
+ // provided. Metadata is also provided for helping to compute the tonemapping curve.
+ virtual double lookupTonemapGain(
+ aidl::android::hardware::graphics::common::Dataspace sourceDataspace,
+ aidl::android::hardware::graphics::common::Dataspace destinationDataspace,
+ vec3 linearRGB, vec3 xyz, const Metadata& metadata) = 0;
};
// Retrieves a tonemapper instance.
diff --git a/libs/tonemap/tests/Android.bp b/libs/tonemap/tests/Android.bp
index e58d519..f46f3fa 100644
--- a/libs/tonemap/tests/Android.bp
+++ b/libs/tonemap/tests/Android.bp
@@ -31,6 +31,7 @@
"android.hardware.graphics.common-V3-ndk",
],
static_libs: [
+ "libmath",
"libgmock",
"libgtest",
"libtonemap",
diff --git a/libs/tonemap/tonemap.cpp b/libs/tonemap/tonemap.cpp
index 350bca4..c2372fe 100644
--- a/libs/tonemap/tonemap.cpp
+++ b/libs/tonemap/tonemap.cpp
@@ -16,6 +16,7 @@
#include <tonemap/tonemap.h>
+#include <algorithm>
#include <cstdint>
#include <mutex>
#include <type_traits>
@@ -26,10 +27,11 @@
// Flag containing the variant of tone map algorithm to use.
enum class ToneMapAlgorithm {
- AndroidO, // Default algorithm in place since Android O,
+ AndroidO, // Default algorithm in place since Android O,
+ Android13, // Algorithm used in Android 13.
};
-static const constexpr auto kToneMapAlgorithm = ToneMapAlgorithm::AndroidO;
+static const constexpr auto kToneMapAlgorithm = ToneMapAlgorithm::Android13;
static const constexpr auto kTransferMask =
static_cast<int32_t>(aidl::android::hardware::graphics::common::Dataspace::TRANSFER_MASK);
@@ -231,9 +233,416 @@
.value = buildUniformValue<float>(metadata.displayMaxLuminance)});
uniforms.push_back({.name = "in_libtonemap_inputMaxLuminance",
.value = buildUniformValue<float>(metadata.contentMaxLuminance)});
-
return uniforms;
}
+
+ double lookupTonemapGain(
+ aidl::android::hardware::graphics::common::Dataspace sourceDataspace,
+ aidl::android::hardware::graphics::common::Dataspace destinationDataspace,
+ vec3 /* linearRGB */, vec3 xyz, const Metadata& metadata) override {
+ if (xyz.y <= 0.0) {
+ return 1.0;
+ }
+ const int32_t sourceDataspaceInt = static_cast<int32_t>(sourceDataspace);
+ const int32_t destinationDataspaceInt = static_cast<int32_t>(destinationDataspace);
+
+ double targetNits = 0.0;
+ switch (sourceDataspaceInt & kTransferMask) {
+ case kTransferST2084:
+ case kTransferHLG:
+ switch (destinationDataspaceInt & kTransferMask) {
+ case kTransferST2084:
+ targetNits = xyz.y;
+ break;
+ case kTransferHLG:
+ // PQ has a wider luminance range (10,000 nits vs. 1,000 nits) than HLG, so
+ // we'll clamp the luminance range in case we're mapping from PQ input to
+ // HLG output.
+ targetNits = std::clamp(xyz.y, 0.0f, 1000.0f);
+ break;
+ default:
+ // Here we're mapping from HDR to SDR content, so interpolate using a
+ // Hermitian polynomial onto the smaller luminance range.
+
+ targetNits = xyz.y;
+ // if the max input luminance is less than what we can output then
+ // no tone mapping is needed as all color values will be in range.
+ if (metadata.contentMaxLuminance > metadata.displayMaxLuminance) {
+ // three control points
+ const double x0 = 10.0;
+ const double y0 = 17.0;
+ double x1 = metadata.displayMaxLuminance * 0.75;
+ double y1 = x1;
+ double x2 = x1 + (metadata.contentMaxLuminance - x1) / 2.0;
+ double y2 = y1 + (metadata.displayMaxLuminance - y1) * 0.75;
+
+ // horizontal distances between the last three control points
+ double h12 = x2 - x1;
+ double h23 = metadata.contentMaxLuminance - x2;
+ // tangents at the last three control points
+ double m1 = (y2 - y1) / h12;
+ double m3 = (metadata.displayMaxLuminance - y2) / h23;
+ double m2 = (m1 + m3) / 2.0;
+
+ if (targetNits < x0) {
+ // scale [0.0, x0] to [0.0, y0] linearly
+ double slope = y0 / x0;
+ targetNits *= slope;
+ } else if (targetNits < x1) {
+ // scale [x0, x1] to [y0, y1] linearly
+ double slope = (y1 - y0) / (x1 - x0);
+ targetNits = y0 + (targetNits - x0) * slope;
+ } else if (targetNits < x2) {
+ // scale [x1, x2] to [y1, y2] using Hermite interp
+ double t = (targetNits - x1) / h12;
+ targetNits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) *
+ (1.0 - t) +
+ (y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t;
+ } else {
+ // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp
+ double t = (targetNits - x2) / h23;
+ targetNits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) *
+ (1.0 - t) +
+ (metadata.displayMaxLuminance * (3.0 - 2.0 * t) +
+ h23 * m3 * (t - 1.0)) *
+ t * t;
+ }
+ }
+ break;
+ }
+ break;
+ default:
+ // source is SDR
+ switch (destinationDataspaceInt & kTransferMask) {
+ case kTransferST2084:
+ case kTransferHLG: {
+ // Map from SDR onto an HDR output buffer
+ // Here we use a polynomial curve to map from [0, displayMaxLuminance] onto
+ // [0, maxOutLumi] which is hard-coded to be 3000 nits.
+ const double maxOutLumi = 3000.0;
+
+ double x0 = 5.0;
+ double y0 = 2.5;
+ double x1 = metadata.displayMaxLuminance * 0.7;
+ double y1 = maxOutLumi * 0.15;
+ double x2 = metadata.displayMaxLuminance * 0.9;
+ double y2 = maxOutLumi * 0.45;
+ double x3 = metadata.displayMaxLuminance;
+ double y3 = maxOutLumi;
+
+ double c1 = y1 / 3.0;
+ double c2 = y2 / 2.0;
+ double c3 = y3 / 1.5;
+
+ targetNits = xyz.y;
+
+ if (targetNits <= x0) {
+ // scale [0.0, x0] to [0.0, y0] linearly
+ double slope = y0 / x0;
+ targetNits *= slope;
+ } else if (targetNits <= x1) {
+ // scale [x0, x1] to [y0, y1] using a curve
+ double t = (targetNits - x0) / (x1 - x0);
+ targetNits = (1.0 - t) * (1.0 - t) * y0 + 2.0 * (1.0 - t) * t * c1 +
+ t * t * y1;
+ } else if (targetNits <= x2) {
+ // scale [x1, x2] to [y1, y2] using a curve
+ double t = (targetNits - x1) / (x2 - x1);
+ targetNits = (1.0 - t) * (1.0 - t) * y1 + 2.0 * (1.0 - t) * t * c2 +
+ t * t * y2;
+ } else {
+ // scale [x2, x3] to [y2, y3] using a curve
+ double t = (targetNits - x2) / (x3 - x2);
+ targetNits = (1.0 - t) * (1.0 - t) * y2 + 2.0 * (1.0 - t) * t * c3 +
+ t * t * y3;
+ }
+ } break;
+ default:
+ // For completeness, this is tone-mapping from SDR to SDR, where this is
+ // just a no-op.
+ targetNits = xyz.y;
+ break;
+ }
+ }
+
+ return targetNits / xyz.y;
+ }
+};
+
+class ToneMapper13 : public ToneMapper {
+private:
+ double OETF_ST2084(double nits) {
+ nits = nits / 10000.0;
+ double m1 = (2610.0 / 4096.0) / 4.0;
+ double m2 = (2523.0 / 4096.0) * 128.0;
+ double c1 = (3424.0 / 4096.0);
+ double c2 = (2413.0 / 4096.0) * 32.0;
+ double c3 = (2392.0 / 4096.0) * 32.0;
+
+ double tmp = std::pow(nits, m1);
+ tmp = (c1 + c2 * tmp) / (1.0 + c3 * tmp);
+ return std::pow(tmp, m2);
+ }
+
+ double OETF_HLG(double nits) {
+ nits = nits / 1000.0;
+ const double a = 0.17883277;
+ const double b = 0.28466892;
+ const double c = 0.55991073;
+ return nits <= 1.0 / 12.0 ? std::sqrt(3.0 * nits) : a * std::log(12.0 * nits - b) + c;
+ }
+
+public:
+ std::string generateTonemapGainShaderSkSL(
+ aidl::android::hardware::graphics::common::Dataspace sourceDataspace,
+ aidl::android::hardware::graphics::common::Dataspace destinationDataspace) override {
+ const int32_t sourceDataspaceInt = static_cast<int32_t>(sourceDataspace);
+ const int32_t destinationDataspaceInt = static_cast<int32_t>(destinationDataspace);
+
+ std::string program;
+ // Input uniforms
+ program.append(R"(
+ uniform float in_libtonemap_displayMaxLuminance;
+ uniform float in_libtonemap_inputMaxLuminance;
+ )");
+ switch (sourceDataspaceInt & kTransferMask) {
+ case kTransferST2084:
+ case kTransferHLG:
+ switch (destinationDataspaceInt & kTransferMask) {
+ case kTransferST2084:
+ program.append(R"(
+ float libtonemap_ToneMapTargetNits(float maxRGB) {
+ return maxRGB;
+ }
+ )");
+ break;
+ case kTransferHLG:
+ // PQ has a wider luminance range (10,000 nits vs. 1,000 nits) than HLG, so
+ // we'll clamp the luminance range in case we're mapping from PQ input to
+ // HLG output.
+ program.append(R"(
+ float libtonemap_ToneMapTargetNits(float maxRGB) {
+ return clamp(maxRGB, 0.0, 1000.0);
+ }
+ )");
+ break;
+
+ default:
+ switch (sourceDataspaceInt & kTransferMask) {
+ case kTransferST2084:
+ program.append(R"(
+ float libtonemap_OETFTone(float channel) {
+ channel = channel / 10000.0;
+ float m1 = (2610.0 / 4096.0) / 4.0;
+ float m2 = (2523.0 / 4096.0) * 128.0;
+ float c1 = (3424.0 / 4096.0);
+ float c2 = (2413.0 / 4096.0) * 32.0;
+ float c3 = (2392.0 / 4096.0) * 32.0;
+
+ float tmp = pow(channel, float(m1));
+ tmp = (c1 + c2 * tmp) / (1.0 + c3 * tmp);
+ return pow(tmp, float(m2));
+ }
+ )");
+ break;
+ case kTransferHLG:
+ program.append(R"(
+ float libtonemap_OETFTone(float channel) {
+ channel = channel / 1000.0;
+ const float a = 0.17883277;
+ const float b = 0.28466892;
+ const float c = 0.55991073;
+ return channel <= 1.0 / 12.0 ? sqrt(3.0 * channel) :
+ a * log(12.0 * channel - b) + c;
+ }
+ )");
+ break;
+ }
+ // Here we're mapping from HDR to SDR content, so interpolate using a
+ // Hermitian polynomial onto the smaller luminance range.
+ program.append(R"(
+ float libtonemap_ToneMapTargetNits(float maxRGB) {
+ float maxInLumi = in_libtonemap_inputMaxLuminance;
+ float maxOutLumi = in_libtonemap_displayMaxLuminance;
+
+ float nits = maxRGB;
+
+ float x1 = maxOutLumi * 0.65;
+ float y1 = x1;
+
+ float x3 = maxInLumi;
+ float y3 = maxOutLumi;
+
+ float x2 = x1 + (x3 - x1) * 4.0 / 17.0;
+ float y2 = maxOutLumi * 0.9;
+
+ float greyNorm1 = libtonemap_OETFTone(x1);
+ float greyNorm2 = libtonemap_OETFTone(x2);
+ float greyNorm3 = libtonemap_OETFTone(x3);
+
+ float slope1 = 0;
+ float slope2 = (y2 - y1) / (greyNorm2 - greyNorm1);
+ float slope3 = (y3 - y2 ) / (greyNorm3 - greyNorm2);
+
+ if (nits < x1) {
+ return nits;
+ }
+
+ if (nits > maxInLumi) {
+ return maxOutLumi;
+ }
+
+ float greyNits = libtonemap_OETFTone(nits);
+
+ if (greyNits <= greyNorm2) {
+ nits = (greyNits - greyNorm2) * slope2 + y2;
+ } else if (greyNits <= greyNorm3) {
+ nits = (greyNits - greyNorm3) * slope3 + y3;
+ } else {
+ nits = maxOutLumi;
+ }
+
+ return nits;
+ }
+ )");
+ break;
+ }
+ break;
+ default:
+ // Inverse tone-mapping and SDR-SDR mapping is not supported.
+ program.append(R"(
+ float libtonemap_ToneMapTargetNits(float maxRGB) {
+ return maxRGB;
+ }
+ )");
+ break;
+ }
+
+ program.append(R"(
+ float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz) {
+ float maxRGB = max(linearRGB.r, max(linearRGB.g, linearRGB.b));
+ if (maxRGB <= 0.0) {
+ return 1.0;
+ }
+ return libtonemap_ToneMapTargetNits(maxRGB) / maxRGB;
+ }
+ )");
+ return program;
+ }
+
+ std::vector<ShaderUniform> generateShaderSkSLUniforms(const Metadata& metadata) override {
+ // Hardcode the max content luminance to a "reasonable" level
+ static const constexpr float kContentMaxLuminance = 4000.f;
+ std::vector<ShaderUniform> uniforms;
+ uniforms.reserve(2);
+ uniforms.push_back({.name = "in_libtonemap_displayMaxLuminance",
+ .value = buildUniformValue<float>(metadata.displayMaxLuminance)});
+ uniforms.push_back({.name = "in_libtonemap_inputMaxLuminance",
+ .value = buildUniformValue<float>(kContentMaxLuminance)});
+ return uniforms;
+ }
+
+ double lookupTonemapGain(
+ aidl::android::hardware::graphics::common::Dataspace sourceDataspace,
+ aidl::android::hardware::graphics::common::Dataspace destinationDataspace,
+ vec3 linearRGB, vec3 /* xyz */, const Metadata& metadata) override {
+ double maxRGB = std::max({linearRGB.r, linearRGB.g, linearRGB.b});
+
+ if (maxRGB <= 0.0) {
+ return 1.0;
+ }
+
+ const int32_t sourceDataspaceInt = static_cast<int32_t>(sourceDataspace);
+ const int32_t destinationDataspaceInt = static_cast<int32_t>(destinationDataspace);
+
+ double targetNits = 0.0;
+ switch (sourceDataspaceInt & kTransferMask) {
+ case kTransferST2084:
+ case kTransferHLG:
+ switch (destinationDataspaceInt & kTransferMask) {
+ case kTransferST2084:
+ targetNits = maxRGB;
+ break;
+ case kTransferHLG:
+ // PQ has a wider luminance range (10,000 nits vs. 1,000 nits) than HLG, so
+ // we'll clamp the luminance range in case we're mapping from PQ input to
+ // HLG output.
+ targetNits = std::clamp(maxRGB, 0.0, 1000.0);
+ break;
+ default:
+ // Here we're mapping from HDR to SDR content, so interpolate using a
+ // Hermitian polynomial onto the smaller luminance range.
+
+ double maxInLumi = 4000;
+ double maxOutLumi = metadata.displayMaxLuminance;
+
+ targetNits = maxRGB;
+
+ double x1 = maxOutLumi * 0.65;
+ double y1 = x1;
+
+ double x3 = maxInLumi;
+ double y3 = maxOutLumi;
+
+ double x2 = x1 + (x3 - x1) * 4.0 / 17.0;
+ double y2 = maxOutLumi * 0.9;
+
+ double greyNorm1 = 0.0;
+ double greyNorm2 = 0.0;
+ double greyNorm3 = 0.0;
+
+ if ((sourceDataspaceInt & kTransferMask) == kTransferST2084) {
+ greyNorm1 = OETF_ST2084(x1);
+ greyNorm2 = OETF_ST2084(x2);
+ greyNorm3 = OETF_ST2084(x3);
+ } else if ((sourceDataspaceInt & kTransferMask) == kTransferHLG) {
+ greyNorm1 = OETF_HLG(x1);
+ greyNorm2 = OETF_HLG(x2);
+ greyNorm3 = OETF_HLG(x3);
+ }
+
+ double slope2 = (y2 - y1) / (greyNorm2 - greyNorm1);
+ double slope3 = (y3 - y2) / (greyNorm3 - greyNorm2);
+
+ if (targetNits < x1) {
+ break;
+ }
+
+ if (targetNits > maxInLumi) {
+ targetNits = maxOutLumi;
+ break;
+ }
+
+ double greyNits = 0.0;
+ if ((sourceDataspaceInt & kTransferMask) == kTransferST2084) {
+ greyNits = OETF_ST2084(targetNits);
+ } else if ((sourceDataspaceInt & kTransferMask) == kTransferHLG) {
+ greyNits = OETF_HLG(targetNits);
+ }
+
+ if (greyNits <= greyNorm2) {
+ targetNits = (greyNits - greyNorm2) * slope2 + y2;
+ } else if (greyNits <= greyNorm3) {
+ targetNits = (greyNits - greyNorm3) * slope3 + y3;
+ } else {
+ targetNits = maxOutLumi;
+ }
+ break;
+ }
+ break;
+ default:
+ switch (destinationDataspaceInt & kTransferMask) {
+ case kTransferST2084:
+ case kTransferHLG:
+ default:
+ targetNits = maxRGB;
+ break;
+ }
+ break;
+ }
+
+ return targetNits / maxRGB;
+ }
};
} // namespace
@@ -247,10 +656,11 @@
case ToneMapAlgorithm::AndroidO:
sToneMapper = std::unique_ptr<ToneMapper>(new ToneMapperO());
break;
+ case ToneMapAlgorithm::Android13:
+ sToneMapper = std::unique_ptr<ToneMapper>(new ToneMapper13());
}
});
return sToneMapper.get();
}
-
} // namespace android::tonemap
\ No newline at end of file
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index 29d8a0f..19cad7b 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -68,7 +68,8 @@
}
static bool isTouchEvent(const NotifyMotionArgs& args) {
- return args.source == AINPUT_SOURCE_TOUCHPAD || args.source == AINPUT_SOURCE_TOUCHSCREEN;
+ return isFromSource(args.source, AINPUT_SOURCE_TOUCHPAD) ||
+ isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN);
}
// --- ClassifierEvent ---
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index c03581d..3d0818b 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -175,13 +175,13 @@
if (!GetBoolProperty("ro.debuggable", false)) {
return "KeyEvent";
}
- return StringPrintf("KeyEvent(deviceId=%d, eventTime=%" PRIu64
- ", source=0x%08x, displayId=%" PRId32 ", action=%s, "
+ return StringPrintf("KeyEvent(deviceId=%d, eventTime=%" PRIu64 ", source=%s, displayId=%" PRId32
+ ", action=%s, "
"flags=0x%08x, keyCode=%s(%d), scanCode=%d, metaState=0x%08x, "
"repeatCount=%d), policyFlags=0x%08x",
- deviceId, eventTime, source, displayId, KeyEvent::actionToString(action),
- flags, KeyEvent::getLabel(keyCode), keyCode, scanCode, metaState,
- repeatCount, policyFlags);
+ deviceId, eventTime, inputEventSourceToString(source).c_str(), displayId,
+ KeyEvent::actionToString(action), flags, KeyEvent::getLabel(keyCode),
+ keyCode, scanCode, metaState, repeatCount, policyFlags);
}
void KeyEntry::recycle() {
@@ -214,7 +214,7 @@
int32_t edgeFlags, float xPrecision, float yPrecision,
float xCursorPosition, float yCursorPosition, nsecs_t downTime,
uint32_t pointerCount, const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords, float xOffset, float yOffset)
+ const PointerCoords* pointerCoords)
: EventEntry(id, Type::MOTION, eventTime, policyFlags),
deviceId(deviceId),
source(source),
@@ -235,9 +235,6 @@
for (uint32_t i = 0; i < pointerCount; i++) {
this->pointerProperties[i].copyFrom(pointerProperties[i]);
this->pointerCoords[i].copyFrom(pointerCoords[i]);
- if (xOffset || yOffset) {
- this->pointerCoords[i].applyOffset(xOffset, yOffset);
- }
}
}
@@ -249,12 +246,12 @@
}
std::string msg;
msg += StringPrintf("MotionEvent(deviceId=%d, eventTime=%" PRIu64
- ", source=0x%08x, displayId=%" PRId32
+ ", source=%s, displayId=%" PRId32
", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, "
"buttonState=0x%08x, "
"classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, "
"xCursorPosition=%0.1f, yCursorPosition=%0.1f, pointers=[",
- deviceId, eventTime, source, displayId,
+ deviceId, eventTime, inputEventSourceToString(source).c_str(), displayId,
MotionEvent::actionToString(action).c_str(), actionButton, flags, metaState,
buttonState, motionClassificationToString(classification), edgeFlags,
xPrecision, yPrecision, xCursorPosition, yCursorPosition);
@@ -289,9 +286,11 @@
std::string SensorEntry::getDescription() const {
std::string msg;
- msg += StringPrintf("SensorEntry(deviceId=%d, source=0x%08x, sensorType=0x%08x, "
+ std::string sensorTypeStr(ftl::enum_name(sensorType).value_or("?"));
+ msg += StringPrintf("SensorEntry(deviceId=%d, source=%s, sensorType=%s, "
"accuracy=0x%08x, hwTimestamp=%" PRId64,
- deviceId, source, sensorType, accuracy, hwTimestamp);
+ deviceId, inputEventSourceToString(source).c_str(), sensorTypeStr.c_str(),
+ accuracy, hwTimestamp);
if (!GetBoolProperty("ro.debuggable", false)) {
for (size_t i = 0; i < values.size(); i++) {
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index 477781a..0f79296 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -184,8 +184,7 @@
int32_t metaState, int32_t buttonState, MotionClassification classification,
int32_t edgeFlags, float xPrecision, float yPrecision, float xCursorPosition,
float yCursorPosition, nsecs_t downTime, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
- float xOffset, float yOffset);
+ const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
std::string getDescription() const override;
~MotionEntry() override;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 6952587..04ff599 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -378,7 +378,7 @@
motionEntry.yPrecision, motionEntry.xCursorPosition,
motionEntry.yCursorPosition, motionEntry.downTime,
motionEntry.pointerCount, motionEntry.pointerProperties,
- pointerCoords.data(), 0 /* xOffset */, 0 /* yOffset */);
+ pointerCoords.data());
if (motionEntry.injectionState) {
combinedMotionEntry->injectionState = motionEntry.injectionState;
@@ -506,16 +506,6 @@
return true;
}
-bool isFromSource(uint32_t source, uint32_t test) {
- return (source & test) == test;
-}
-
-vec2 transformWithoutTranslation(const ui::Transform& transform, float x, float y) {
- const vec2 transformedXy = transform.transform(x, y);
- const vec2 transformedOrigin = transform.transform(0, 0);
- return transformedXy - transformedOrigin;
-}
-
// Returns true if the event type passed as argument represents a user activity.
bool isUserActivityEvent(const EventEntry& eventEntry) {
switch (eventEntry.type) {
@@ -3234,8 +3224,7 @@
const FocusEntry& focusEntry = static_cast<const FocusEntry&>(eventEntry);
status = connection->inputPublisher.publishFocusEvent(dispatchEntry->seq,
focusEntry.id,
- focusEntry.hasFocus,
- mInTouchMode);
+ focusEntry.hasFocus);
break;
}
@@ -3763,7 +3752,7 @@
originalMotionEntry.xCursorPosition,
originalMotionEntry.yCursorPosition,
originalMotionEntry.downTime, splitPointerCount,
- splitPointerProperties, splitPointerCoords, 0, 0);
+ splitPointerProperties, splitPointerCoords);
if (originalMotionEntry.injectionState) {
splitMotionEntry->injectionState = originalMotionEntry.injectionState;
@@ -3989,7 +3978,7 @@
args->xPrecision, args->yPrecision,
args->xCursorPosition, args->yCursorPosition,
args->downTime, args->pointerCount,
- args->pointerProperties, args->pointerCoords, 0, 0);
+ args->pointerProperties, args->pointerCoords);
if (args->id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID &&
IdGenerator::getSource(args->id) == IdGenerator::Source::INPUT_READER &&
@@ -4219,10 +4208,8 @@
motionEvent.getRawXCursorPosition(),
motionEvent.getRawYCursorPosition(),
motionEvent.getDownTime(), uint32_t(pointerCount),
- pointerProperties, samplePointerCoords,
- motionEvent.getXOffset(),
- motionEvent.getYOffset());
- transformMotionEntryForInjectionLocked(*injectedEntry);
+ pointerProperties, samplePointerCoords);
+ transformMotionEntryForInjectionLocked(*injectedEntry, motionEvent.getTransform());
injectedEntries.push(std::move(injectedEntry));
for (size_t i = motionEvent.getHistorySize(); i > 0; i--) {
sampleEventTimes += 1;
@@ -4241,9 +4228,9 @@
motionEvent.getRawYCursorPosition(),
motionEvent.getDownTime(),
uint32_t(pointerCount), pointerProperties,
- samplePointerCoords, motionEvent.getXOffset(),
- motionEvent.getYOffset());
- transformMotionEntryForInjectionLocked(*nextInjectedEntry);
+ samplePointerCoords);
+ transformMotionEntryForInjectionLocked(*nextInjectedEntry,
+ motionEvent.getTransform());
injectedEntries.push(std::move(nextInjectedEntry));
}
break;
@@ -4407,35 +4394,28 @@
}
}
-void InputDispatcher::transformMotionEntryForInjectionLocked(MotionEntry& entry) const {
- const bool isRelativeMouseEvent = isFromSource(entry.source, AINPUT_SOURCE_MOUSE_RELATIVE);
- if (!isRelativeMouseEvent && !isFromSource(entry.source, AINPUT_SOURCE_CLASS_POINTER)) {
- return;
- }
-
+void InputDispatcher::transformMotionEntryForInjectionLocked(
+ MotionEntry& entry, const ui::Transform& injectedTransform) const {
// Input injection works in the logical display coordinate space, but the input pipeline works
// display space, so we need to transform the injected events accordingly.
const auto it = mDisplayInfos.find(entry.displayId);
if (it == mDisplayInfos.end()) return;
- const auto& transformToDisplay = it->second.transform.inverse();
+ const auto& transformToDisplay = it->second.transform.inverse() * injectedTransform;
for (uint32_t i = 0; i < entry.pointerCount; i++) {
PointerCoords& pc = entry.pointerCoords[i];
- const auto xy = isRelativeMouseEvent
- ? transformWithoutTranslation(transformToDisplay, pc.getX(), pc.getY())
- : transformToDisplay.transform(pc.getXYValue());
- pc.setAxisValue(AMOTION_EVENT_AXIS_X, xy.x);
- pc.setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y);
+ // Make a copy of the injected coords. We cannot change them in place because some of them
+ // are interdependent (for example, X coordinate might depend on the Y coordinate).
+ PointerCoords injectedCoords = entry.pointerCoords[i];
- // Axes with relative values never represent points on a screen, so they should never have
- // translation applied. If a device does not report relative values, these values are always
- // 0, and will remain unaffected by the following operation.
- const auto rel =
- transformWithoutTranslation(transformToDisplay,
- pc.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
- pc.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
- pc.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, rel.x);
- pc.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, rel.y);
+ BitSet64 bits(injectedCoords.bits);
+ while (!bits.isEmpty()) {
+ const auto axis = static_cast<int32_t>(bits.clearFirstMarkedBit());
+ const float value =
+ MotionEvent::calculateTransformedAxisValue(axis, entry.source,
+ transformToDisplay, injectedCoords);
+ pc.setAxisValue(axis, value);
+ }
}
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 8a551cf..6f05670 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -280,7 +280,9 @@
bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
void setInjectionResult(EventEntry& entry,
android::os::InputEventInjectionResult injectionResult);
- void transformMotionEntryForInjectionLocked(MotionEntry&) const REQUIRES(mLock);
+ void transformMotionEntryForInjectionLocked(MotionEntry&,
+ const ui::Transform& injectedTransform) const
+ REQUIRES(mLock);
std::condition_variable mInjectionSyncFinished;
void incrementPendingForegroundDispatches(EventEntry& entry);
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
index 3bb0bc9..ad3c615 100644
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ b/services/inputflinger/dispatcher/InputState.cpp
@@ -296,8 +296,7 @@
memento.yPrecision, memento.xCursorPosition,
memento.yCursorPosition, memento.downTime,
memento.pointerCount, memento.pointerProperties,
- memento.pointerCoords, 0 /*xOffset*/,
- 0 /*yOffset*/));
+ memento.pointerCoords));
}
}
return events;
@@ -349,8 +348,7 @@
AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
memento.yPrecision, memento.xCursorPosition,
memento.yCursorPosition, memento.downTime,
- pointerCount, pointerProperties, pointerCoords,
- 0 /*xOffset*/, 0 /*yOffset*/));
+ pointerCount, pointerProperties, pointerCoords));
}
memento.firstNewPointerIdx = INVALID_POINTER_INDEX;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index d8fd16c..eaea4e2 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -842,7 +842,6 @@
FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
- EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
}
void consumeCaptureEvent(bool hasCapture) {
@@ -2080,6 +2079,33 @@
secondWindow->assertNoEvents();
}
+// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
+// event should be treated as being in the logical display space.
+TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
+ auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
+
+ const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
+ ui::Transform injectedEventTransform;
+ injectedEventTransform.set(matrix);
+ const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
+ const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
+
+ MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(untransformedPoint.x)
+ .y(untransformedPoint.y))
+ .build();
+ event.transform(matrix);
+
+ injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT);
+
+ firstWindow->consumeMotionDown();
+ secondWindow->assertNoEvents();
+}
+
TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
diff --git a/services/sensorservice/ISensorHalWrapper.h b/services/sensorservice/ISensorHalWrapper.h
new file mode 100644
index 0000000..c9e089e
--- /dev/null
+++ b/services/sensorservice/ISensorHalWrapper.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#ifndef ANDROID_ISENSOR_HAL_WRAPPER_H
+#define ANDROID_ISENSOR_HAL_WRAPPER_H
+
+#include <hardware/sensors.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "SensorService.h"
+
+namespace android {
+
+/**
+ * A wrapper for various types of HAL implementation, e.g. to distinguish HIDL and AIDL versions.
+ */
+class ISensorHalWrapper {
+public:
+ class ICallback : public ISensorsCallback {
+
+ void onDynamicSensorsConnected(
+ const std::vector<sensor_t> &dynamicSensorsAdded) = 0;
+
+ void onDynamicSensorsDisconnected(
+ const std::vector<int32_t> &dynamicSensorHandlesRemoved) = 0;
+ };
+
+ /**
+ * Connects to the underlying sensors HAL. This should also be used for any reconnections
+ * due to HAL resets.
+ */
+ virtual bool connect(ICallback *callback) = 0;
+
+ /**
+ * Polls for available sensor events. This could be using the traditional sensors
+ * polling or from a FMQ.
+ */
+ virtual ssize_t poll(sensors_event_t* buffer, size_t count) = 0;
+
+ /**
+ * The below functions directly mirrors the sensors HAL definitions.
+ */
+ virtual std::vector<sensor_t> getSensorsList() = 0;
+
+ virtual status_t setOperationMode(SensorService::Mode mode) = 0;
+
+ virtual status_t activate(int32_t sensorHandle, bool enabled) = 0;
+
+ virtual status_t batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs) = 0;
+
+ virtual status_t flush(int32_t sensorHandle) = 0;
+
+ virtual status_t injectSensorData(const sensors_event_t *event) = 0;
+
+ virtual status_t registerDirectChannel(const sensors_direct_mem_t *memory,
+ int32_t *channelHandle) = 0;
+
+ virtual void unregisterDirectChannel(int32_t channelHandle) = 0;
+
+ virtual status_t configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
+ const struct sensors_direct_cfg_t *config) = 0;
+}
+
+} // namespace android
+
+#endif // ANDROID_ISENSOR_HAL_WRAPPER_H
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index db1a1cc..c67acbf 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -23,31 +23,32 @@
#include <android-base/logging.h>
#include <android/util/ProtoOutputStream.h>
+#include <cutils/atomic.h>
#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
#include <sensors/convert.h>
-#include <cutils/atomic.h>
#include <utils/Errors.h>
#include <utils/Singleton.h>
-#include <cstddef>
#include <chrono>
#include <cinttypes>
+#include <cstddef>
#include <thread>
using namespace android::hardware::sensors;
using namespace android::hardware::sensors::V1_0;
using namespace android::hardware::sensors::V1_0::implementation;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
using android::hardware::sensors::V2_0::EventQueueFlagBits;
using android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
using android::hardware::sensors::V2_1::ISensorsCallback;
-using android::hardware::sensors::V2_1::implementation::convertToOldSensorInfo;
-using android::hardware::sensors::V2_1::implementation::convertToNewSensorInfos;
using android::hardware::sensors::V2_1::implementation::convertToNewEvents;
+using android::hardware::sensors::V2_1::implementation::convertToNewSensorInfos;
+using android::hardware::sensors::V2_1::implementation::convertToOldSensorInfo;
+using android::hardware::sensors::V2_1::implementation::convertToSensor;
using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV1_0;
using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV2_0;
using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV2_1;
-using android::hardware::hidl_vec;
-using android::hardware::Return;
using android::SensorDeviceUtils::HidlServiceRegistrationWaiter;
using android::util::ProtoOutputStream;
@@ -73,7 +74,7 @@
}
}
-template<typename EnumType>
+template <typename EnumType>
constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
return static_cast<typename std::underlying_type<EnumType>::type>(value);
}
@@ -81,14 +82,13 @@
// Used internally by the framework to wake the Event FMQ. These values must start after
// the last value of EventQueueFlagBits
enum EventQueueFlagBitsInternal : uint32_t {
- INTERNAL_WAKE = 1 << 16,
+ INTERNAL_WAKE = 1 << 16,
};
-} // anonymous namespace
+} // anonymous namespace
void SensorsHalDeathReceivier::serviceDied(
- uint64_t /* cookie */,
- const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
+ uint64_t /* cookie */, const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
ALOGW("Sensors HAL died, attempting to reconnect.");
SensorDevice::getInstance().prepareForReconnect();
}
@@ -98,29 +98,36 @@
using SensorInfo = ::android::hardware::sensors::V2_1::SensorInfo;
Return<void> onDynamicSensorsConnected_2_1(
- const hidl_vec<SensorInfo> &dynamicSensorsAdded) override {
- return SensorDevice::getInstance().onDynamicSensorsConnected(dynamicSensorsAdded);
+ const hidl_vec<SensorInfo>& dynamicSensorsAdded) override {
+ std::vector<sensor_t> sensors;
+ for (const V2_1::SensorInfo& info : dynamicSensorsAdded) {
+ sensor_t sensor;
+ convertToSensor(info, &sensor);
+ sensors.push_back(sensor);
+ }
+
+ SensorDevice::getInstance().onDynamicSensorsConnected(sensors);
+ return Return<void>();
}
Return<void> onDynamicSensorsConnected(
- const hidl_vec<V1_0::SensorInfo> &dynamicSensorsAdded) override {
- return SensorDevice::getInstance().onDynamicSensorsConnected(
- convertToNewSensorInfos(dynamicSensorsAdded));
+ const hidl_vec<V1_0::SensorInfo>& dynamicSensorsAdded) override {
+ return onDynamicSensorsConnected_2_1(convertToNewSensorInfos(dynamicSensorsAdded));
}
Return<void> onDynamicSensorsDisconnected(
- const hidl_vec<int32_t> &dynamicSensorHandlesRemoved) override {
- return SensorDevice::getInstance().onDynamicSensorsDisconnected(
- dynamicSensorHandlesRemoved);
+ const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
+ SensorDevice::getInstance().onDynamicSensorsDisconnected(dynamicSensorHandlesRemoved);
+ return Return<void>();
}
};
SensorDevice::SensorDevice()
- : mHidlTransportErrors(20),
- mRestartWaiter(new HidlServiceRegistrationWaiter()),
- mEventQueueFlag(nullptr),
- mWakeLockQueueFlag(nullptr),
- mReconnecting(false) {
+ : mHidlTransportErrors(20),
+ mRestartWaiter(new HidlServiceRegistrationWaiter()),
+ mEventQueueFlag(nullptr),
+ mWakeLockQueueFlag(nullptr),
+ mReconnecting(false) {
if (!connectHidlService()) {
return;
}
@@ -132,61 +139,59 @@
}
void SensorDevice::initializeSensorList() {
- checkReturn(mSensors->getSensorsList(
- [&](const auto &list) {
- const size_t count = list.size();
+ checkReturn(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(convertToOldSensorInfo(list[i]), &sensor);
+ mActivationCount.setCapacity(count);
+ Info model;
+ for (size_t i = 0; i < count; i++) {
+ sensor_t sensor;
+ convertToSensor(list[i], &sensor);
- if (sensor.type < static_cast<int>(SensorType::DEVICE_PRIVATE_BASE)) {
- sensor.resolution = SensorDeviceUtils::resolutionForSensor(sensor);
+ if (sensor.type < static_cast<int>(SensorType::DEVICE_PRIVATE_BASE)) {
+ sensor.resolution = SensorDeviceUtils::resolutionForSensor(sensor);
- // Some sensors don't have a default resolution and will be left at 0.
- // Don't crash in this case since CTS will verify that devices don't go to
- // production with a resolution of 0.
- if (sensor.resolution != 0) {
- float quantizedRange = sensor.maxRange;
- SensorDeviceUtils::quantizeValue(
- &quantizedRange, sensor.resolution, /*factor=*/ 1);
- // Only rewrite maxRange if the requantization produced a "significant"
- // change, which is fairly arbitrarily defined as resolution / 8.
- // Smaller deltas are permitted, as they may simply be due to floating
- // point representation error, etc.
- if (fabsf(sensor.maxRange - quantizedRange) > sensor.resolution / 8) {
- ALOGW("%s's max range %.12f is not a multiple of the resolution "
- "%.12f - updated to %.12f", sensor.name, sensor.maxRange,
- sensor.resolution, quantizedRange);
- sensor.maxRange = quantizedRange;
- }
- } else {
- // Don't crash here or the device will go into a crashloop.
- ALOGW("%s should have a non-zero resolution", sensor.name);
- }
+ // Some sensors don't have a default resolution and will be left at 0.
+ // Don't crash in this case since CTS will verify that devices don't go to
+ // production with a resolution of 0.
+ if (sensor.resolution != 0) {
+ float quantizedRange = sensor.maxRange;
+ SensorDeviceUtils::quantizeValue(&quantizedRange, sensor.resolution,
+ /*factor=*/1);
+ // Only rewrite maxRange if the requantization produced a "significant"
+ // change, which is fairly arbitrarily defined as resolution / 8.
+ // Smaller deltas are permitted, as they may simply be due to floating
+ // point representation error, etc.
+ if (fabsf(sensor.maxRange - quantizedRange) > sensor.resolution / 8) {
+ ALOGW("%s's max range %.12f is not a multiple of the resolution "
+ "%.12f - updated to %.12f",
+ sensor.name, sensor.maxRange, sensor.resolution, quantizedRange);
+ sensor.maxRange = quantizedRange;
}
-
- // Check and clamp power if it is 0 (or close)
- constexpr float MIN_POWER_MA = 0.001; // 1 microAmp
- if (sensor.power < MIN_POWER_MA) {
- ALOGI("%s's reported power %f invalid, clamped to %f",
- sensor.name, sensor.power, MIN_POWER_MA);
- sensor.power = MIN_POWER_MA;
- }
- mSensorList.push_back(sensor);
-
- mActivationCount.add(list[i].sensorHandle, model);
-
- // Only disable all sensors on HAL 1.0 since HAL 2.0
- // handles this in its initialize method
- if (!mSensors->supportsMessageQueues()) {
- checkReturn(mSensors->activate(list[i].sensorHandle,
- 0 /* enabled */));
- }
+ } else {
+ // Don't crash here or the device will go into a crashloop.
+ ALOGW("%s should have a non-zero resolution", sensor.name);
}
- }));
+ }
+
+ // Check and clamp power if it is 0 (or close)
+ constexpr float MIN_POWER_MA = 0.001; // 1 microAmp
+ if (sensor.power < MIN_POWER_MA) {
+ ALOGI("%s's reported power %f invalid, clamped to %f", sensor.name, sensor.power,
+ MIN_POWER_MA);
+ sensor.power = MIN_POWER_MA;
+ }
+ mSensorList.push_back(sensor);
+
+ mActivationCount.add(list[i].sensorHandle, model);
+
+ // Only disable all sensors on HAL 1.0 since HAL 2.0
+ // handles this in its initialize method
+ if (!mSensors->supportsMessageQueues()) {
+ checkReturn(mSensors->activate(list[i].sensorHandle, 0 /* enabled */));
+ }
+ }
+ }));
}
SensorDevice::~SensorDevice() {
@@ -231,7 +236,7 @@
// Poke ISensor service. If it has lingering connection from previous generation of
// system server, it will kill itself. There is no intention to handle the poll result,
// which will be done since the size is 0.
- if(mSensors->poll(0, [](auto, const auto &, const auto &) {}).isOk()) {
+ if (mSensors->poll(0, [](auto, const auto&, const auto&) {}).isOk()) {
// ok to continue
connectionStatus = HalConnectionStatus::CONNECTED;
break;
@@ -278,23 +283,23 @@
SensorDevice::HalConnectionStatus SensorDevice::initializeHidlServiceV2_X() {
HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
- mWakeLockQueue = std::make_unique<WakeLockQueue>(
- SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT,
- true /* configureEventFlagWord */);
+ mWakeLockQueue =
+ std::make_unique<WakeLockQueue>(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT,
+ true /* configureEventFlagWord */);
hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
- hardware::EventFlag::createEventFlag(mSensors->getEventQueue()->getEventFlagWord(), &mEventQueueFlag);
+ hardware::EventFlag::createEventFlag(mSensors->getEventQueue()->getEventFlagWord(),
+ &mEventQueueFlag);
hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
- hardware::EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(),
- &mWakeLockQueueFlag);
+ hardware::EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(), &mWakeLockQueueFlag);
- CHECK(mSensors != nullptr && mWakeLockQueue != nullptr &&
- mEventQueueFlag != nullptr && mWakeLockQueueFlag != nullptr);
+ CHECK(mSensors != nullptr && mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&
+ mWakeLockQueueFlag != nullptr);
- status_t status = checkReturnAndGetStatus(mSensors->initialize(
- *mWakeLockQueue->getDesc(),
- new SensorsCallback()));
+ mCallback = new SensorsCallback();
+ status_t status =
+ checkReturnAndGetStatus(mSensors->initialize(*mWakeLockQueue->getDesc(), mCallback));
if (status != NO_ERROR) {
connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
@@ -326,7 +331,7 @@
mActivationCount.clear();
mSensorList.clear();
- if (connectHidlServiceV2_0() == HalConnectionStatus::CONNECTED) {
+ if (connectHidlService()) {
initializeSensorList();
if (sensorHandlesChanged(previousSensorList, mSensorList)) {
@@ -338,8 +343,8 @@
mReconnecting = false;
}
-bool SensorDevice::sensorHandlesChanged(const Vector<sensor_t>& oldSensorList,
- const Vector<sensor_t>& newSensorList) {
+bool SensorDevice::sensorHandlesChanged(const std::vector<sensor_t>& oldSensorList,
+ const std::vector<sensor_t>& newSensorList) {
bool didChange = false;
if (oldSensorList.size() != newSensorList.size()) {
@@ -375,19 +380,17 @@
bool SensorDevice::sensorIsEquivalent(const sensor_t& prevSensor, const sensor_t& newSensor) {
bool equivalent = true;
if (prevSensor.handle != newSensor.handle ||
- (strcmp(prevSensor.vendor, newSensor.vendor) != 0) ||
- (strcmp(prevSensor.stringType, newSensor.stringType) != 0) ||
- (strcmp(prevSensor.requiredPermission, newSensor.requiredPermission) != 0) ||
- (prevSensor.version != newSensor.version) ||
- (prevSensor.type != newSensor.type) ||
- (std::abs(prevSensor.maxRange - newSensor.maxRange) > 0.001f) ||
- (std::abs(prevSensor.resolution - newSensor.resolution) > 0.001f) ||
- (std::abs(prevSensor.power - newSensor.power) > 0.001f) ||
- (prevSensor.minDelay != newSensor.minDelay) ||
- (prevSensor.fifoReservedEventCount != newSensor.fifoReservedEventCount) ||
- (prevSensor.fifoMaxEventCount != newSensor.fifoMaxEventCount) ||
- (prevSensor.maxDelay != newSensor.maxDelay) ||
- (prevSensor.flags != newSensor.flags)) {
+ (strcmp(prevSensor.vendor, newSensor.vendor) != 0) ||
+ (strcmp(prevSensor.stringType, newSensor.stringType) != 0) ||
+ (strcmp(prevSensor.requiredPermission, newSensor.requiredPermission) != 0) ||
+ (prevSensor.version != newSensor.version) || (prevSensor.type != newSensor.type) ||
+ (std::abs(prevSensor.maxRange - newSensor.maxRange) > 0.001f) ||
+ (std::abs(prevSensor.resolution - newSensor.resolution) > 0.001f) ||
+ (std::abs(prevSensor.power - newSensor.power) > 0.001f) ||
+ (prevSensor.minDelay != newSensor.minDelay) ||
+ (prevSensor.fifoReservedEventCount != newSensor.fifoReservedEventCount) ||
+ (prevSensor.fifoMaxEventCount != newSensor.fifoMaxEventCount) ||
+ (prevSensor.maxDelay != newSensor.maxDelay) || (prevSensor.flags != newSensor.flags)) {
equivalent = false;
}
return equivalent;
@@ -405,7 +408,7 @@
for (size_t j = 0; j < info.batchParams.size(); j++) {
const BatchParams& batchParams = info.batchParams[j];
status_t res = batchLocked(info.batchParams.keyAt(j), handle, 0 /* flags */,
- batchParams.mTSample, batchParams.mTBatch);
+ batchParams.mTSample, batchParams.mTBatch);
if (res == NO_ERROR) {
activateLocked(info.batchParams.keyAt(j), handle, true /* enabled */);
@@ -433,7 +436,7 @@
mSensorList.size(), mActivationCount.size(), mDisabledClients.size());
Mutex::Autolock _l(mLock);
- for (const auto & s : mSensorList) {
+ for (const auto& s : mSensorList) {
int32_t handle = s.handle;
const Info& info = mActivationCount.valueFor(handle);
if (info.numActiveClients() == 0) continue;
@@ -444,8 +447,9 @@
for (size_t j = 0; j < info.batchParams.size(); j++) {
const BatchParams& params = info.batchParams[j];
result.appendFormat("%.1f%s%s", params.mTSample / 1e6f,
- isClientDisabledLocked(info.batchParams.keyAt(j)) ? "(disabled)" : "",
- (j < info.batchParams.size() - 1) ? ", " : "");
+ isClientDisabledLocked(info.batchParams.keyAt(j)) ? "(disabled)"
+ : "",
+ (j < info.batchParams.size() - 1) ? ", " : "");
}
result.appendFormat("}, selected = %.2f ms; ", info.bestBatchParams.mTSample / 1e6f);
@@ -453,8 +457,9 @@
for (size_t j = 0; j < info.batchParams.size(); j++) {
const BatchParams& params = info.batchParams[j];
result.appendFormat("%.1f%s%s", params.mTBatch / 1e6f,
- isClientDisabledLocked(info.batchParams.keyAt(j)) ? "(disabled)" : "",
- (j < info.batchParams.size() - 1) ? ", " : "");
+ isClientDisabledLocked(info.batchParams.keyAt(j)) ? "(disabled)"
+ : "",
+ (j < info.batchParams.size() - 1) ? ", " : "");
}
result.appendFormat("}, selected = %.2f ms\n", info.bestBatchParams.mTBatch / 1e6f);
}
@@ -472,29 +477,29 @@
void SensorDevice::dump(ProtoOutputStream* proto) const {
using namespace service::SensorDeviceProto;
if (mSensors == nullptr) {
- proto->write(INITIALIZED , false);
+ proto->write(INITIALIZED, false);
return;
}
- proto->write(INITIALIZED , true);
- proto->write(TOTAL_SENSORS , int(mSensorList.size()));
- proto->write(ACTIVE_SENSORS , int(mActivationCount.size()));
+ proto->write(INITIALIZED, true);
+ proto->write(TOTAL_SENSORS, int(mSensorList.size()));
+ proto->write(ACTIVE_SENSORS, int(mActivationCount.size()));
Mutex::Autolock _l(mLock);
- for (const auto & s : mSensorList) {
+ for (const auto& s : mSensorList) {
int32_t handle = s.handle;
const Info& info = mActivationCount.valueFor(handle);
if (info.numActiveClients() == 0) continue;
uint64_t token = proto->start(SENSORS);
- proto->write(SensorProto::HANDLE , handle);
- proto->write(SensorProto::ACTIVE_COUNT , int(info.batchParams.size()));
+ proto->write(SensorProto::HANDLE, handle);
+ proto->write(SensorProto::ACTIVE_COUNT, int(info.batchParams.size()));
for (size_t j = 0; j < info.batchParams.size(); j++) {
const BatchParams& params = info.batchParams[j];
- proto->write(SensorProto::SAMPLING_PERIOD_MS , params.mTSample / 1e6f);
- proto->write(SensorProto::BATCHING_PERIOD_MS , params.mTBatch / 1e6f);
+ proto->write(SensorProto::SAMPLING_PERIOD_MS, params.mTSample / 1e6f);
+ proto->write(SensorProto::BATCHING_PERIOD_MS, params.mTBatch / 1e6f);
}
- proto->write(SensorProto::SAMPLING_PERIOD_SELECTED , info.bestBatchParams.mTSample / 1e6f);
- proto->write(SensorProto::BATCHING_PERIOD_SELECTED , info.bestBatchParams.mTBatch / 1e6f);
+ proto->write(SensorProto::SAMPLING_PERIOD_SELECTED, info.bestBatchParams.mTSample / 1e6f);
+ proto->write(SensorProto::BATCHING_PERIOD_SELECTED, info.bestBatchParams.mTBatch / 1e6f);
proto->end(token);
}
}
@@ -531,20 +536,19 @@
do {
auto ret = mSensors->poll(
- count,
- [&](auto result,
- const auto &events,
- const auto &dynamicSensorsAdded) {
+ count, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
if (result == Result::OK) {
convertToSensorEventsAndQuantize(convertToNewEvents(events),
- convertToNewSensorInfos(dynamicSensorsAdded), buffer);
+ convertToNewSensorInfos(
+ dynamicSensorsAdded),
+ buffer);
err = (ssize_t)events.size();
} else {
err = statusFromResult(result);
}
});
- if (ret.isOk()) {
+ if (ret.isOk()) {
hidlTransportError = false;
} else {
hidlTransportError = true;
@@ -559,7 +563,7 @@
}
} while (hidlTransportError);
- if(numHidlTransportErrors > 0) {
+ if (numHidlTransportErrors > 0) {
ALOGE("Saw %d Hidl transport failures", numHidlTransportErrors);
HidlTransportErrorLog errLog(time(nullptr), numHidlTransportErrors);
mHidlTransportErrors.add(errLog);
@@ -581,7 +585,8 @@
// events is not available, then read() would return no events, possibly introducing
// additional latency in delivering events to applications.
mEventQueueFlag->wait(asBaseType(EventQueueFlagBits::READ_AND_PROCESS) |
- asBaseType(INTERNAL_WAKE), &eventFlagState);
+ asBaseType(INTERNAL_WAKE),
+ &eventFlagState);
availableEvents = mSensors->getEventQueue()->availableToRead();
if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) {
@@ -600,47 +605,39 @@
for (size_t i = 0; i < eventsToRead; i++) {
convertToSensorEvent(mEventBuffer[i], &buffer[i]);
android::SensorDeviceUtils::quantizeSensorEventValues(&buffer[i],
- getResolutionForSensor(buffer[i].sensor));
+ getResolutionForSensor(
+ buffer[i].sensor));
}
eventsRead = eventsToRead;
} else {
- ALOGW("Failed to read %zu events, currently %zu events available",
- eventsToRead, availableEvents);
+ ALOGW("Failed to read %zu events, currently %zu events available", eventsToRead,
+ availableEvents);
}
}
return eventsRead;
}
-Return<void> SensorDevice::onDynamicSensorsConnected(
- const hidl_vec<SensorInfo> &dynamicSensorsAdded) {
+void SensorDevice::onDynamicSensorsConnected(const std::vector<sensor_t>& dynamicSensorsAdded) {
std::unique_lock<std::mutex> lock(mDynamicSensorsMutex);
// 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];
+ const sensor_t& sensor = dynamicSensorsAdded[i];
- auto it = mConnectedDynamicSensors.find(info.sensorHandle);
+ auto it = mConnectedDynamicSensors.find(sensor.handle);
CHECK(it == mConnectedDynamicSensors.end());
- sensor_t *sensor = new sensor_t();
- convertToSensor(convertToOldSensorInfo(info), sensor);
-
- mConnectedDynamicSensors.insert(
- std::make_pair(sensor->handle, sensor));
+ mConnectedDynamicSensors.insert(std::make_pair(sensor.handle, sensor));
}
mDynamicSensorsCv.notify_all();
-
- return Return<void>();
}
-Return<void> SensorDevice::onDynamicSensorsDisconnected(
- const hidl_vec<int32_t> &dynamicSensorHandlesRemoved) {
- (void) dynamicSensorHandlesRemoved;
+void SensorDevice::onDynamicSensorsDisconnected(
+ const std::vector<int32_t>& /* dynamicSensorHandlesRemoved */) {
// TODO: Currently dynamic sensors do not seem to be removed
- return Return<void>();
}
void SensorDevice::writeWakeLockHandled(uint32_t count) {
@@ -653,7 +650,7 @@
}
}
-void SensorDevice::autoDisable(void *ident, int handle) {
+void SensorDevice::autoDisable(void* ident, int handle) {
Mutex::Autolock _l(mLock);
ssize_t activationIndex = mActivationCount.indexOfKey(handle);
if (activationIndex < 0) {
@@ -687,15 +684,15 @@
Info& info(mActivationCount.editValueAt(activationIndex));
ALOGD_IF(DEBUG_CONNECTIONS,
- "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu",
- ident, handle, enabled, info.batchParams.size());
+ "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)) {
- ALOGW("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d",
- ident, handle);
+ ALOGW("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d", ident,
+ handle);
return NO_ERROR;
}
@@ -714,7 +711,6 @@
// dictionary.
auto it = mConnectedDynamicSensors.find(handle);
if (it != mConnectedDynamicSensors.end()) {
- delete it->second;
mConnectedDynamicSensors.erase(it);
}
@@ -726,11 +722,10 @@
// 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 0x%08x %" PRId64 " %" PRId64, handle,
- info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
- checkReturn(mSensors->batch(
- handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch));
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w batch 0x%08x %" PRId64 " %" PRId64,
+ handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
+ checkReturn(mSensors->batch(handle, info.bestBatchParams.mTSample,
+ info.bestBatchParams.mTBatch));
}
} else {
// sensor wasn't enabled for this ident
@@ -767,12 +762,8 @@
return err;
}
-status_t SensorDevice::batch(
- void* ident,
- int handle,
- int flags,
- int64_t samplingPeriodNs,
- int64_t maxBatchReportLatencyNs) {
+status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
+ int64_t maxBatchReportLatencyNs) {
if (mSensors == nullptr) return NO_INIT;
if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
@@ -783,7 +774,8 @@
}
ALOGD_IF(DEBUG_CONNECTIONS,
- "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64,
+ "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64
+ " timeout=%" PRId64,
ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
Mutex::Autolock _l(mLock);
@@ -807,25 +799,24 @@
info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
}
- status_t err = updateBatchParamsLocked(handle, info);
+ status_t err = updateBatchParamsLocked(handle, info);
if (err != NO_ERROR) {
- ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s",
- mSensors.get(), handle, info.bestBatchParams.mTSample,
- info.bestBatchParams.mTBatch, strerror(-err));
+ ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s", mSensors.get(),
+ handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch, strerror(-err));
info.removeBatchParamsForIdent(ident);
}
return err;
}
-status_t SensorDevice::updateBatchParamsLocked(int handle, Info &info) {
+status_t SensorDevice::updateBatchParamsLocked(int handle, Info& info) {
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,
+ "\t>>> curr_period=%" PRId64 " min_period=%" PRId64 " curr_timeout=%" PRId64
+ " min_timeout=%" PRId64,
prevBestBatchParams.mTSample, info.bestBatchParams.mTSample,
prevBestBatchParams.mTBatch, info.bestBatchParams.mTBatch);
@@ -834,8 +825,8 @@
if (prevBestBatchParams != info.bestBatchParams && info.numActiveClients() > 0) {
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH 0x%08x %" PRId64 " %" PRId64, handle,
info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
- err = checkReturnAndGetStatus(mSensors->batch(
- handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch));
+ err = checkReturnAndGetStatus(mSensors->batch(handle, info.bestBatchParams.mTSample,
+ info.bestBatchParams.mTBatch));
}
return err;
@@ -866,8 +857,8 @@
return mDisabledClients.count(ident) > 0;
}
-std::vector<void *> SensorDevice::getDisabledClientsLocked() const {
- std::vector<void *> vec;
+std::vector<void*> SensorDevice::getDisabledClientsLocked() const {
+ std::vector<void*> vec;
for (const auto& it : mDisabledClients) {
vec.push_back(it.first);
}
@@ -896,7 +887,7 @@
addDisabledReasonForIdentLocked(ident, DisabledReason::DISABLED_REASON_UID_IDLE);
}
- for (size_t i = 0; i< mActivationCount.size(); ++i) {
+ for (size_t i = 0; i < mActivationCount.size(); ++i) {
int handle = mActivationCount.keyAt(i);
Info& info = mActivationCount.editValueAt(i);
@@ -905,8 +896,7 @@
bool disable = info.numActiveClients() == 0 && info.isActive;
bool enable = info.numActiveClients() > 0 && !info.isActive;
- if ((enable || disable) &&
- doActivateHardwareLocked(handle, enable) == NO_ERROR) {
+ if ((enable || disable) && doActivateHardwareLocked(handle, enable) == NO_ERROR) {
info.isActive = enable;
}
}
@@ -941,22 +931,21 @@
if (mSensors == nullptr) return;
Mutex::Autolock _l(mLock);
- for (void *client : getDisabledClientsLocked()) {
- removeDisabledReasonForIdentLocked(
- client, DisabledReason::DISABLED_REASON_SERVICE_RESTRICTED);
+ for (void* client : getDisabledClientsLocked()) {
+ removeDisabledReasonForIdentLocked(client,
+ DisabledReason::DISABLED_REASON_SERVICE_RESTRICTED);
}
- for (size_t i = 0; i< mActivationCount.size(); ++i) {
+ 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 = checkReturnAndGetStatus(mSensors->batch(
- sensor_handle,
- info.bestBatchParams.mTSample,
- info.bestBatchParams.mTBatch));
+ sensor_handle);
+ status_t err = checkReturnAndGetStatus(mSensors->batch(sensor_handle,
+ info.bestBatchParams.mTSample,
+ info.bestBatchParams.mTBatch));
ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
if (err == NO_ERROR) {
@@ -973,38 +962,36 @@
void SensorDevice::disableAllSensors() {
if (mSensors == nullptr) return;
Mutex::Autolock _l(mLock);
- for (size_t i = 0; i< mActivationCount.size(); ++i) {
+ for (size_t i = 0; i < mActivationCount.size(); ++i) {
Info& info = mActivationCount.editValueAt(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);
- checkReturn(mSensors->activate(sensor_handle, 0 /* enabled */));
+ const int sensor_handle = mActivationCount.keyAt(i);
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
+ sensor_handle);
+ checkReturn(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) {
- addDisabledReasonForIdentLocked(
- info.batchParams.keyAt(j), DisabledReason::DISABLED_REASON_SERVICE_RESTRICTED);
- ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
- }
+ // 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) {
+ addDisabledReasonForIdentLocked(info.batchParams.keyAt(j),
+ DisabledReason::DISABLED_REASON_SERVICE_RESTRICTED);
+ ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
+ }
- info.isActive = false;
+ info.isActive = false;
}
}
}
-status_t SensorDevice::injectSensorData(
- const sensors_event_t *injected_sensor_event) {
+status_t SensorDevice::injectSensorData(const sensors_event_t* injected_sensor_event) {
if (mSensors == nullptr) return NO_INIT;
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]);
+ "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;
V2_1::implementation::convertFromSensorEvent(*injected_sensor_event, &ev);
@@ -1014,8 +1001,8 @@
status_t SensorDevice::setMode(uint32_t mode) {
if (mSensors == nullptr) return NO_INIT;
- return checkReturnAndGetStatus(mSensors->setOperationMode(
- static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
+ return checkReturnAndGetStatus(
+ mSensors->setOperationMode(static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
}
int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
@@ -1041,21 +1028,20 @@
format = SharedMemFormat::SENSORS_EVENT;
SharedMemInfo mem = {
- .type = type,
- .format = format,
- .size = static_cast<uint32_t>(memory->size),
- .memoryHandle = memory->handle,
+ .type = type,
+ .format = format,
+ .size = static_cast<uint32_t>(memory->size),
+ .memoryHandle = memory->handle,
};
int32_t ret;
- checkReturn(mSensors->registerDirectChannel(mem,
- [&ret](auto result, auto channelHandle) {
- if (result == Result::OK) {
- ret = channelHandle;
- } else {
- ret = statusFromResult(result);
- }
- }));
+ checkReturn(mSensors->registerDirectChannel(mem, [&ret](auto result, auto channelHandle) {
+ if (result == Result::OK) {
+ ret = channelHandle;
+ } else {
+ ret = statusFromResult(result);
+ }
+ }));
return ret;
}
@@ -1065,13 +1051,13 @@
checkReturn(mSensors->unregisterDirectChannel(channelHandle));
}
-int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle,
- int32_t channelHandle, const struct sensors_direct_cfg_t *config) {
+int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
+ const struct sensors_direct_cfg_t* config) {
if (mSensors == nullptr) return NO_INIT;
Mutex::Autolock _l(mLock);
RateLevel rate;
- switch(config->rate_level) {
+ switch (config->rate_level) {
case SENSOR_DIRECT_RATE_STOP:
rate = RateLevel::STOP;
break;
@@ -1090,17 +1076,17 @@
int32_t ret;
checkReturn(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);
- }
- }
- }));
+ [&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;
}
@@ -1118,13 +1104,12 @@
return num;
}
-status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int,
- int64_t samplingPeriodNs,
+status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int, 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)",
+ ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%" PRId64 " timeout=%" PRId64
+ ") failed (%s)",
ident, samplingPeriodNs, maxBatchReportLatencyNs, strerror(-index));
return BAD_INDEX;
}
@@ -1168,12 +1153,11 @@
return mIsDirectReportSupported;
}
-void SensorDevice::convertToSensorEvent(
- const Event &src, sensors_event_t *dst) {
+void SensorDevice::convertToSensorEvent(const Event& src, sensors_event_t* dst) {
V2_1::implementation::convertToSensorEvent(src, dst);
if (src.sensorType == V2_1::SensorType::DYNAMIC_SENSOR_META) {
- const DynamicSensorInfo &dyn = src.u.dynamic;
+ const DynamicSensorInfo& dyn = src.u.dynamic;
dst->dynamic_sensor_meta.connected = dyn.connected;
dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
@@ -1184,56 +1168,53 @@
// marks it as oneway.
auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
if (it == mConnectedDynamicSensors.end()) {
- mDynamicSensorsCv.wait_for(lock, MAX_DYN_SENSOR_WAIT,
- [&, dyn]{
- return mConnectedDynamicSensors.find(dyn.sensorHandle)
- != mConnectedDynamicSensors.end();
+ mDynamicSensorsCv.wait_for(lock, MAX_DYN_SENSOR_WAIT, [&, dyn] {
+ return mConnectedDynamicSensors.find(dyn.sensorHandle) !=
+ mConnectedDynamicSensors.end();
});
it = mConnectedDynamicSensors.find(dyn.sensorHandle);
CHECK(it != mConnectedDynamicSensors.end());
}
- dst->dynamic_sensor_meta.sensor = it->second;
+ dst->dynamic_sensor_meta.sensor = &it->second;
- memcpy(dst->dynamic_sensor_meta.uuid,
- dyn.uuid.data(),
+ memcpy(dst->dynamic_sensor_meta.uuid, dyn.uuid.data(),
sizeof(dst->dynamic_sensor_meta.uuid));
}
}
}
-void SensorDevice::convertToSensorEventsAndQuantize(
- const hidl_vec<Event> &src,
- const hidl_vec<SensorInfo> &dynamicSensorsAdded,
- sensors_event_t *dst) {
-
- if (dynamicSensorsAdded.size() > 0) {
- onDynamicSensorsConnected(dynamicSensorsAdded);
+void SensorDevice::convertToSensorEventsAndQuantize(const hidl_vec<Event>& src,
+ const hidl_vec<SensorInfo>& dynamicSensorsAdded,
+ sensors_event_t* dst) {
+ if (dynamicSensorsAdded.size() > 0 && mCallback != nullptr) {
+ mCallback->onDynamicSensorsConnected_2_1(dynamicSensorsAdded);
}
for (size_t i = 0; i < src.size(); ++i) {
V2_1::implementation::convertToSensorEvent(src[i], &dst[i]);
android::SensorDeviceUtils::quantizeSensorEventValues(&dst[i],
- getResolutionForSensor(dst[i].sensor));
+ getResolutionForSensor(
+ dst[i].sensor));
}
}
float SensorDevice::getResolutionForSensor(int sensorHandle) {
for (size_t i = 0; i < mSensorList.size(); i++) {
- if (sensorHandle == mSensorList[i].handle) {
- return mSensorList[i].resolution;
- }
+ if (sensorHandle == mSensorList[i].handle) {
+ return mSensorList[i].resolution;
+ }
}
auto it = mConnectedDynamicSensors.find(sensorHandle);
if (it != mConnectedDynamicSensors.end()) {
- return it->second->resolution;
+ return it->second.resolution;
}
return 0;
}
-void SensorDevice::handleHidlDeath(const std::string & detail) {
+void SensorDevice::handleHidlDeath(const std::string& detail) {
if (!mSensors->supportsMessageQueues()) {
// restart is the only option at present.
LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index bc8d20f..314ddb8 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -17,14 +17,14 @@
#ifndef ANDROID_SENSOR_DEVICE_H
#define ANDROID_SENSOR_DEVICE_H
+#include "ISensorsWrapper.h"
#include "SensorDeviceUtils.h"
#include "SensorService.h"
#include "SensorServiceUtils.h"
-#include "ISensorsWrapper.h"
#include <fmq/MessageQueue.h>
-#include <sensor/SensorEventQueue.h>
#include <sensor/Sensor.h>
+#include <sensor/SensorEventQueue.h>
#include <stdint.h>
#include <sys/types.h>
#include <utils/KeyedVector.h>
@@ -32,9 +32,10 @@
#include <utils/String8.h>
#include <utils/Timers.h>
+#include <algorithm> //std::max std::min
#include <string>
#include <unordered_map>
-#include <algorithm> //std::max std::min
+#include <vector>
#include "RingBuffer.h"
@@ -42,18 +43,18 @@
namespace android {
+using Result = ::android::hardware::sensors::V1_0::Result;
+
// ---------------------------------------------------------------------------
class SensorsHalDeathReceivier : public android::hardware::hidl_death_recipient {
virtual void serviceDied(uint64_t cookie,
const wp<::android::hidl::base::V1_0::IBase>& service) override;
};
-class SensorDevice : public Singleton<SensorDevice>,
- public SensorServiceUtil::Dumpable {
+class SensorDevice : public Singleton<SensorDevice>, public SensorServiceUtil::Dumpable {
public:
class HidlTransportErrorLog {
- public:
-
+ public:
HidlTransportErrorLog() {
mTs = 0;
mCount = 0;
@@ -66,7 +67,7 @@
String8 toString() const {
String8 result;
- struct tm *timeInfo = localtime(&mTs);
+ struct tm* timeInfo = localtime(&mTs);
result.appendFormat("%02d:%02d:%02d :: %d", timeInfo->tm_hour, timeInfo->tm_min,
timeInfo->tm_sec, mCount);
return result;
@@ -74,7 +75,7 @@
private:
time_t mTs; // timestamp of the error
- int mCount; // number of transport errors observed
+ int mCount; // number of transport errors observed
};
~SensorDevice();
@@ -99,29 +100,24 @@
status_t setMode(uint32_t mode);
bool isDirectReportSupported() const;
- int32_t registerDirectChannel(const sensors_direct_mem_t *memory);
+ int32_t registerDirectChannel(const sensors_direct_mem_t* memory);
void unregisterDirectChannel(int32_t channelHandle);
- int32_t configureDirectChannel(int32_t sensorHandle,
- int32_t channelHandle, const struct sensors_direct_cfg_t *config);
+ int32_t configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
+ const struct sensors_direct_cfg_t* config);
void disableAllSensors();
void enableAllSensors();
- void autoDisable(void *ident, int handle);
+ void autoDisable(void* ident, int handle);
- status_t injectSensorData(const sensors_event_t *event);
- void notifyConnectionDestroyed(void *ident);
+ status_t injectSensorData(const sensors_event_t* event);
+ void notifyConnectionDestroyed(void* ident);
- using Result = ::android::hardware::sensors::V1_0::Result;
- hardware::Return<void> onDynamicSensorsConnected(
- const hardware::hidl_vec<hardware::sensors::V2_1::SensorInfo> &dynamicSensorsAdded);
- hardware::Return<void> onDynamicSensorsDisconnected(
- const hardware::hidl_vec<int32_t> &dynamicSensorHandlesRemoved);
+ void onDynamicSensorsConnected(const std::vector<sensor_t>& dynamicSensorsAdded);
+ void onDynamicSensorsDisconnected(const std::vector<int32_t>& dynamicSensorHandlesRemoved);
void setUidStateForConnection(void* ident, SensorService::UidState state);
- bool isReconnecting() const {
- return mReconnecting;
- }
+ bool isReconnecting() const { return mReconnecting; }
bool isSensorActive(int handle) const;
@@ -132,12 +128,14 @@
// Dumpable
virtual std::string dump() const override;
virtual void dump(util::ProtoOutputStream* proto) const override;
+
private:
friend class Singleton<SensorDevice>;
sp<::android::hardware::sensors::V2_1::implementation::ISensorsWrapperBase> mSensors;
- Vector<sensor_t> mSensorList;
- std::unordered_map<int32_t, sensor_t*> mConnectedDynamicSensors;
+ sp<::android::hardware::sensors::V2_1::ISensorsCallback> mCallback;
+ std::vector<sensor_t> mSensorList;
+ std::unordered_map<int32_t, sensor_t> mConnectedDynamicSensors;
// A bug in the Sensors HIDL spec which marks onDynamicSensorsConnected as oneway causes dynamic
// meta events and onDynamicSensorsConnected to be received out of order. This mutex + CV are
@@ -147,26 +145,26 @@
std::condition_variable mDynamicSensorsCv;
static constexpr std::chrono::seconds MAX_DYN_SENSOR_WAIT{5};
- static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz
- mutable Mutex mLock; // protect mActivationCount[].batchParams
+ static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz
+ mutable Mutex mLock; // protect mActivationCount[].batchParams
// fixed-size array after construction
// Struct to store all the parameters(samplingPeriod, maxBatchReportLatency and flags) from
// batch call. For continous mode clients, maxBatchReportLatency is set to zero.
struct BatchParams {
- nsecs_t mTSample, mTBatch;
- BatchParams() : mTSample(INT64_MAX), mTBatch(INT64_MAX) {}
- BatchParams(nsecs_t tSample, nsecs_t tBatch): mTSample(tSample), mTBatch(tBatch) {}
- bool operator != (const BatchParams& other) {
- return !(mTSample == other.mTSample && mTBatch == other.mTBatch);
- }
- // Merge another parameter with this one. The updated mTSample will be the min of the two.
- // The update mTBatch will be the min of original mTBatch and the apparent batch period
- // of the other. the apparent batch is the maximum of mTBatch and mTSample,
- void merge(const BatchParams &other) {
- mTSample = std::min(mTSample, other.mTSample);
- mTBatch = std::min(mTBatch, std::max(other.mTBatch, other.mTSample));
- }
+ nsecs_t mTSample, mTBatch;
+ BatchParams() : mTSample(INT64_MAX), mTBatch(INT64_MAX) {}
+ BatchParams(nsecs_t tSample, nsecs_t tBatch) : mTSample(tSample), mTBatch(tBatch) {}
+ bool operator!=(const BatchParams& other) {
+ return !(mTSample == other.mTSample && mTBatch == other.mTBatch);
+ }
+ // Merge another parameter with this one. The updated mTSample will be the min of the two.
+ // The update mTBatch will be the min of original mTBatch and the apparent batch period
+ // of the other. the apparent batch is the maximum of mTBatch and mTSample,
+ void merge(const BatchParams& other) {
+ mTSample = std::min(mTSample, other.mTSample);
+ mTBatch = std::min(mTBatch, std::max(other.mTBatch, other.mTSample));
+ }
};
// Store batch parameters in the KeyedVector and the optimal batch_rate and timeout in
@@ -224,7 +222,7 @@
static_assert(DisabledReason::DISABLED_REASON_MAX < sizeof(uint8_t) * CHAR_BIT);
// Use this map to determine which client is activated or deactivated.
- std::unordered_map<void *, uint8_t> mDisabledClients;
+ std::unordered_map<void*, uint8_t> mDisabledClients;
void addDisabledReasonForIdentLocked(void* ident, DisabledReason reason);
void removeDisabledReasonForIdentLocked(void* ident, DisabledReason reason);
@@ -233,13 +231,13 @@
bool connectHidlService();
void initializeSensorList();
void reactivateSensors(const DefaultKeyedVector<int, Info>& previousActivations);
- static bool sensorHandlesChanged(const Vector<sensor_t>& oldSensorList,
- const Vector<sensor_t>& newSensorList);
+ static bool sensorHandlesChanged(const std::vector<sensor_t>& oldSensorList,
+ const std::vector<sensor_t>& newSensorList);
static bool sensorIsEquivalent(const sensor_t& prevSensor, const sensor_t& newSensor);
enum HalConnectionStatus {
- CONNECTED, // Successfully connected to the HAL
- DOES_NOT_EXIST, // Could not find the HAL
+ CONNECTED, // Successfully connected to the HAL
+ DOES_NOT_EXIST, // Could not find the HAL
FAILED_TO_CONNECT, // Found the HAL but failed to connect/initialize
UNKNOWN,
};
@@ -257,32 +255,32 @@
status_t updateBatchParamsLocked(int handle, Info& info);
status_t doActivateHardwareLocked(int handle, bool enable);
- void handleHidlDeath(const std::string &detail);
- template<typename T>
+ void handleHidlDeath(const std::string& detail);
+ template <typename T>
void checkReturn(const Return<T>& ret) {
if (!ret.isOk()) {
handleHidlDeath(ret.description());
}
}
+
status_t checkReturnAndGetStatus(const Return<Result>& ret);
- //TODO(b/67425500): remove waiter after bug is resolved.
+ // TODO(b/67425500): remove waiter after bug is resolved.
sp<SensorDeviceUtils::HidlServiceRegistrationWaiter> mRestartWaiter;
bool isClientDisabled(void* ident) const;
bool isClientDisabledLocked(void* ident) const;
- std::vector<void *> getDisabledClientsLocked() const;
+ std::vector<void*> getDisabledClientsLocked() const;
bool clientHasNoAccessLocked(void* ident) const;
using Event = hardware::sensors::V2_1::Event;
using SensorInfo = hardware::sensors::V2_1::SensorInfo;
- void convertToSensorEvent(const Event &src, sensors_event_t *dst);
+ void convertToSensorEvent(const Event& src, sensors_event_t* dst);
- void convertToSensorEventsAndQuantize(
- const hardware::hidl_vec<Event> &src,
- const hardware::hidl_vec<SensorInfo> &dynamicSensorsAdded,
- sensors_event_t *dst);
+ void convertToSensorEventsAndQuantize(const hardware::hidl_vec<Event>& src,
+ const hardware::hidl_vec<SensorInfo>& dynamicSensorsAdded,
+ sensors_event_t* dst);
float getResolutionForSensor(int sensorHandle);
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 32a0110..9bc7b8e 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -164,7 +164,6 @@
sensor_t const* list;
ssize_t count = dev.getSensorList(&list);
if (count > 0) {
- ssize_t orientationIndex = -1;
bool hasGyro = false, hasAccel = false, hasMag = false;
uint32_t virtualSensorsNeeds =
(1<<SENSOR_TYPE_GRAVITY) |
@@ -183,9 +182,6 @@
case SENSOR_TYPE_MAGNETIC_FIELD:
hasMag = true;
break;
- case SENSOR_TYPE_ORIENTATION:
- orientationIndex = i;
- break;
case SENSOR_TYPE_GYROSCOPE:
case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
hasGyro = true;
@@ -201,6 +197,8 @@
virtualSensorsNeeds &= ~(1<<list[i].type);
}
break;
+ default:
+ break;
}
if (useThisSensor) {
if (list[i].type == SENSOR_TYPE_PROXIMITY) {
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index b059e61..9b6d01a 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -89,6 +89,52 @@
UID_STATE_IDLE,
};
+ enum Mode {
+ // The regular operating mode where any application can register/unregister/call flush on
+ // sensors.
+ NORMAL = 0,
+ // This mode is only used for testing purposes. Not all HALs support this mode. In this mode,
+ // the HAL ignores the sensor data provided by physical sensors and accepts the data that is
+ // injected from the SensorService as if it were the real sensor data. This mode is primarily
+ // used for testing various algorithms like vendor provided SensorFusion, Step Counter and
+ // Step Detector etc. Typically in this mode, there will be a client (a
+ // SensorEventConnection) which will be injecting sensor data into the HAL. Normal apps can
+ // unregister and register for any sensor that supports injection. Registering to sensors
+ // that do not support injection will give an error. TODO: Allow exactly one
+ // client to inject sensor data at a time.
+ DATA_INJECTION = 1,
+ // This mode is used only for testing sensors. Each sensor can be tested in isolation with
+ // the required sampling_rate and maxReportLatency parameters without having to think about
+ // the data rates requested by other applications. End user devices are always expected to be
+ // in NORMAL mode. When this mode is first activated, all active sensors from all connections
+ // are disabled. Calling flush() will return an error. In this mode, only the requests from
+ // selected apps whose package names are allowlisted are allowed (typically CTS apps). Only
+ // these apps can register/unregister/call flush() on sensors. If SensorService switches to
+ // NORMAL mode again, all sensors that were previously registered to are activated with the
+ // corresponding parameters if the application hasn't unregistered for sensors in the mean
+ // time. NOTE: Non allowlisted app whose sensors were previously deactivated may still
+ // receive events if a allowlisted app requests data from the same sensor.
+ RESTRICTED = 2
+
+ // State Transitions supported.
+ // RESTRICTED <--- NORMAL ---> DATA_INJECTION
+ // ---> <---
+
+ // Shell commands to switch modes in SensorService.
+ // 1) Put SensorService in RESTRICTED mode with packageName .cts. If it is already in
+ // restricted mode it is treated as a NO_OP (and packageName is NOT changed).
+ //
+ // $ adb shell dumpsys sensorservice restrict .cts.
+ //
+ // 2) Put SensorService in DATA_INJECTION mode with packageName .xts. If it is already in
+ // data_injection mode it is treated as a NO_OP (and packageName is NOT changed).
+ //
+ // $ adb shell dumpsys sensorservice data_injection .xts.
+ //
+ // 3) Reset sensorservice back to NORMAL mode.
+ // $ adb shell dumpsys sensorservice enable
+ };
+
class ProximityActiveListener : public virtual RefBase {
public:
// Note that the callback is invoked from an async thread and can interact with the
@@ -276,52 +322,6 @@
const int64_t mToken;
};
- enum Mode {
- // The regular operating mode where any application can register/unregister/call flush on
- // sensors.
- NORMAL = 0,
- // This mode is only used for testing purposes. Not all HALs support this mode. In this mode,
- // the HAL ignores the sensor data provided by physical sensors and accepts the data that is
- // injected from the SensorService as if it were the real sensor data. This mode is primarily
- // used for testing various algorithms like vendor provided SensorFusion, Step Counter and
- // Step Detector etc. Typically in this mode, there will be a client (a
- // SensorEventConnection) which will be injecting sensor data into the HAL. Normal apps can
- // unregister and register for any sensor that supports injection. Registering to sensors
- // that do not support injection will give an error. TODO(aakella) : Allow exactly one
- // client to inject sensor data at a time.
- DATA_INJECTION = 1,
- // This mode is used only for testing sensors. Each sensor can be tested in isolation with
- // the required sampling_rate and maxReportLatency parameters without having to think about
- // the data rates requested by other applications. End user devices are always expected to be
- // in NORMAL mode. When this mode is first activated, all active sensors from all connections
- // are disabled. Calling flush() will return an error. In this mode, only the requests from
- // selected apps whose package names are whitelisted are allowed (typically CTS apps). Only
- // these apps can register/unregister/call flush() on sensors. If SensorService switches to
- // NORMAL mode again, all sensors that were previously registered to are activated with the
- // corresponding paramaters if the application hasn't unregistered for sensors in the mean
- // time. NOTE: Non whitelisted app whose sensors were previously deactivated may still
- // receive events if a whitelisted app requests data from the same sensor.
- RESTRICTED = 2
-
- // State Transitions supported.
- // RESTRICTED <--- NORMAL ---> DATA_INJECTION
- // ---> <---
-
- // Shell commands to switch modes in SensorService.
- // 1) Put SensorService in RESTRICTED mode with packageName .cts. If it is already in
- // restricted mode it is treated as a NO_OP (and packageName is NOT changed).
- //
- // $ adb shell dumpsys sensorservice restrict .cts.
- //
- // 2) Put SensorService in DATA_INJECTION mode with packageName .xts. If it is already in
- // data_injection mode it is treated as a NO_OP (and packageName is NOT changed).
- //
- // $ adb shell dumpsys sensorservice data_injection .xts.
- //
- // 3) Reset sensorservice back to NORMAL mode.
- // $ adb shell dumpsys sensorservice enable
- };
-
static const char* WAKE_LOCK_NAME;
virtual ~SensorService();
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 043a536..a020e2c 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -30,41 +30,30 @@
namespace android::impl {
-void MessageQueue::Handler::dispatchComposite() {
- if ((mEventMask.fetch_or(kComposite) & kComposite) == 0) {
- mQueue.mLooper->sendMessage(this, Message(kComposite));
- }
-}
-
-void MessageQueue::Handler::dispatchCommit(int64_t vsyncId, nsecs_t expectedVsyncTime) {
- if ((mEventMask.fetch_or(kCommit) & kCommit) == 0) {
+void MessageQueue::Handler::dispatchFrame(int64_t vsyncId, nsecs_t expectedVsyncTime) {
+ if (!mFramePending.exchange(true)) {
mVsyncId = vsyncId;
mExpectedVsyncTime = expectedVsyncTime;
- mQueue.mLooper->sendMessage(this, Message(kCommit));
+ mQueue.mLooper->sendMessage(this, Message());
}
}
bool MessageQueue::Handler::isFramePending() const {
- constexpr auto kPendingMask = kCommit | kComposite;
- return (mEventMask.load() & kPendingMask) != 0;
+ return mFramePending.load();
}
-void MessageQueue::Handler::handleMessage(const Message& message) {
+void MessageQueue::Handler::handleMessage(const Message&) {
+ mFramePending.store(false);
+
const nsecs_t frameTime = systemTime();
- switch (message.what) {
- case kCommit:
- mEventMask.fetch_and(~kCommit);
- if (!mQueue.mCompositor.commit(frameTime, mVsyncId, mExpectedVsyncTime)) {
- return;
- }
- // Composite immediately, rather than after pending tasks through scheduleComposite.
- [[fallthrough]];
- case kComposite:
- mEventMask.fetch_and(~kComposite);
- mQueue.mCompositor.composite(frameTime);
- mQueue.mCompositor.sample();
- break;
+ auto& compositor = mQueue.mCompositor;
+
+ if (!compositor.commit(frameTime, mVsyncId, mExpectedVsyncTime)) {
+ return;
}
+
+ compositor.composite(frameTime);
+ compositor.sample();
}
MessageQueue::MessageQueue(ICompositor& compositor)
@@ -122,7 +111,7 @@
const auto vsyncId = mVsync.tokenManager->generateTokenForPredictions(
{targetWakeupTime, readyTime, vsyncTime});
- mHandler->dispatchCommit(vsyncId, vsyncTime);
+ mHandler->dispatchFrame(vsyncId, vsyncTime);
}
void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
@@ -176,7 +165,7 @@
mLooper->sendMessage(handler, Message());
}
-void MessageQueue::scheduleCommit() {
+void MessageQueue::scheduleFrame() {
ATRACE_CALL();
{
@@ -195,18 +184,14 @@
.earliestVsync = mVsync.lastCallbackTime.count()});
}
-void MessageQueue::scheduleComposite() {
- mHandler->dispatchComposite();
-}
-
void MessageQueue::injectorCallback() {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
while ((n = DisplayEventReceiver::getEvents(&mInjector.tube, buffer, 8)) > 0) {
for (int i = 0; i < n; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
- mHandler->dispatchCommit(buffer[i].vsync.vsyncId,
- buffer[i].vsync.expectedVSyncTimestamp);
+ auto& vsync = buffer[i].vsync;
+ mHandler->dispatchFrame(vsync.vsyncId, vsync.expectedVSyncTimestamp);
break;
}
}
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
index 2c908a6..dd69d60 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.h
+++ b/services/surfaceflinger/Scheduler/MessageQueue.h
@@ -71,8 +71,7 @@
virtual void setInjector(sp<EventThreadConnection>) = 0;
virtual void waitMessage() = 0;
virtual void postMessage(sp<MessageHandler>&&) = 0;
- virtual void scheduleCommit() = 0;
- virtual void scheduleComposite() = 0;
+ virtual void scheduleFrame() = 0;
using Clock = std::chrono::steady_clock;
virtual std::optional<Clock::time_point> getScheduledFrameTime() const = 0;
@@ -83,11 +82,8 @@
class MessageQueue : public android::MessageQueue {
protected:
class Handler : public MessageHandler {
- static constexpr uint32_t kCommit = 0b1;
- static constexpr uint32_t kComposite = 0b10;
-
MessageQueue& mQueue;
- std::atomic<uint32_t> mEventMask = 0;
+ std::atomic_bool mFramePending = false;
std::atomic<int64_t> mVsyncId = 0;
std::atomic<nsecs_t> mExpectedVsyncTime = 0;
@@ -97,8 +93,7 @@
bool isFramePending() const;
- virtual void dispatchCommit(int64_t vsyncId, nsecs_t expectedVsyncTime);
- void dispatchComposite();
+ virtual void dispatchFrame(int64_t vsyncId, nsecs_t expectedVsyncTime);
};
friend class Handler;
@@ -147,8 +142,7 @@
void waitMessage() override;
void postMessage(sp<MessageHandler>&&) override;
- void scheduleCommit() override;
- void scheduleComposite() override;
+ void scheduleFrame() override;
std::optional<Clock::time_point> getScheduledFrameTime() const override;
};
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index aabd88a..0d17b0c 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -744,7 +744,6 @@
[getCallback] {
if (const auto callback = getCallback()) callback->onExpired();
});
- mIdleTimer->start();
}
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 85c31e8..8a1c206 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -356,10 +356,22 @@
std::function<void()> kernelTimerExpired) {
std::scoped_lock lock(mIdleTimerCallbacksMutex);
mIdleTimerCallbacks.emplace();
- mIdleTimerCallbacks->platform.onReset = platformTimerReset;
- mIdleTimerCallbacks->platform.onExpired = platformTimerExpired;
- mIdleTimerCallbacks->kernel.onReset = kernelTimerReset;
- mIdleTimerCallbacks->kernel.onExpired = kernelTimerExpired;
+ mIdleTimerCallbacks->platform.onReset = std::move(platformTimerReset);
+ mIdleTimerCallbacks->platform.onExpired = std::move(platformTimerExpired);
+ mIdleTimerCallbacks->kernel.onReset = std::move(kernelTimerReset);
+ mIdleTimerCallbacks->kernel.onExpired = std::move(kernelTimerExpired);
+ }
+
+ void startIdleTimer() {
+ if (mIdleTimer) {
+ mIdleTimer->start();
+ }
+ }
+
+ void stopIdleTimer() {
+ if (mIdleTimer) {
+ mIdleTimer->stop();
+ }
}
void resetIdleTimer(bool kernelOnly) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 6d45b5d..2a6de54 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -97,8 +97,7 @@
using Impl::getScheduledFrameTime;
using Impl::setDuration;
- using Impl::scheduleCommit;
- using Impl::scheduleComposite;
+ using Impl::scheduleFrame;
// Schedule an asynchronous or synchronous task on the main thread.
template <typename F, typename T = std::invoke_result_t<F>>
@@ -214,17 +213,32 @@
void setRefreshRateConfigs(std::shared_ptr<scheduler::RefreshRateConfigs> refreshRateConfigs)
EXCLUDES(mRefreshRateConfigsLock) {
- std::scoped_lock lock(mRefreshRateConfigsLock);
- mRefreshRateConfigs = std::move(refreshRateConfigs);
- mRefreshRateConfigs->setIdleTimerCallbacks(
- [this] { std::invoke(&Scheduler::idleTimerCallback, this, TimerState::Reset); },
- [this] { std::invoke(&Scheduler::idleTimerCallback, this, TimerState::Expired); },
- [this] {
- std::invoke(&Scheduler::kernelIdleTimerCallback, this, TimerState::Reset);
- },
- [this] {
- std::invoke(&Scheduler::kernelIdleTimerCallback, this, TimerState::Expired);
- });
+ // We need to stop the idle timer on the previous RefreshRateConfigs instance
+ // and cleanup the scheduler's state before we switch to the other RefreshRateConfigs.
+ {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ if (mRefreshRateConfigs) mRefreshRateConfigs->stopIdleTimer();
+ }
+ {
+ std::scoped_lock lock(mFeatureStateLock);
+ mFeatures = {};
+ }
+ {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ mRefreshRateConfigs = std::move(refreshRateConfigs);
+ mRefreshRateConfigs->setIdleTimerCallbacks(
+ [this] { std::invoke(&Scheduler::idleTimerCallback, this, TimerState::Reset); },
+ [this] {
+ std::invoke(&Scheduler::idleTimerCallback, this, TimerState::Expired);
+ },
+ [this] {
+ std::invoke(&Scheduler::kernelIdleTimerCallback, this, TimerState::Reset);
+ },
+ [this] {
+ std::invoke(&Scheduler::kernelIdleTimerCallback, this, TimerState::Expired);
+ });
+ mRefreshRateConfigs->startIdleTimer();
+ }
}
nsecs_t getVsyncPeriodFromRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 93f8406..e497d95 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -772,6 +772,25 @@
ATRACE_INT("TexturePoolSize", mTexturePool.size());
}
+static std::optional<renderengine::RenderEngine::RenderEngineType>
+chooseRenderEngineTypeViaSysProp() {
+ char prop[PROPERTY_VALUE_MAX];
+ property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "");
+
+ if (strcmp(prop, "gles") == 0) {
+ return renderengine::RenderEngine::RenderEngineType::GLES;
+ } else if (strcmp(prop, "threaded") == 0) {
+ return renderengine::RenderEngine::RenderEngineType::THREADED;
+ } else if (strcmp(prop, "skiagl") == 0) {
+ return renderengine::RenderEngine::RenderEngineType::SKIA_GL;
+ } else if (strcmp(prop, "skiaglthreaded") == 0) {
+ return renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED;
+ } else {
+ ALOGE("Unrecognized RenderEngineType %s; ignoring!", prop);
+ return {};
+ }
+}
+
// Do not call property_set on main thread which will be blocked by init
// Use StartPropertySetThread instead.
void SurfaceFlinger::init() {
@@ -782,19 +801,21 @@
// Get a RenderEngine for the given display / config (can't fail)
// TODO(b/77156734): We need to stop casting and use HAL types when possible.
// Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display.
- mCompositionEngine->setRenderEngine(renderengine::RenderEngine::create(
- renderengine::RenderEngineCreationArgs::Builder()
- .setPixelFormat(static_cast<int32_t>(defaultCompositionPixelFormat))
- .setImageCacheSize(maxFrameBufferAcquiredBuffers)
- .setUseColorManagerment(useColorManagement)
- .setEnableProtectedContext(enable_protected_contents(false))
- .setPrecacheToneMapperShaderOnly(false)
- .setSupportsBackgroundBlur(mSupportsBlur)
- .setContextPriority(
- useContextPriority
- ? renderengine::RenderEngine::ContextPriority::REALTIME
- : renderengine::RenderEngine::ContextPriority::MEDIUM)
- .build()));
+ auto builder = renderengine::RenderEngineCreationArgs::Builder()
+ .setPixelFormat(static_cast<int32_t>(defaultCompositionPixelFormat))
+ .setImageCacheSize(maxFrameBufferAcquiredBuffers)
+ .setUseColorManagerment(useColorManagement)
+ .setEnableProtectedContext(enable_protected_contents(false))
+ .setPrecacheToneMapperShaderOnly(false)
+ .setSupportsBackgroundBlur(mSupportsBlur)
+ .setContextPriority(
+ useContextPriority
+ ? renderengine::RenderEngine::ContextPriority::REALTIME
+ : renderengine::RenderEngine::ContextPriority::MEDIUM);
+ if (auto type = chooseRenderEngineTypeViaSysProp()) {
+ builder.setRenderEngineType(type.value());
+ }
+ mCompositionEngine->setRenderEngine(renderengine::RenderEngine::create(builder.build()));
mMaxRenderTargetSize =
std::min(getRenderEngine().getMaxTextureSize(), getRenderEngine().getMaxViewportDims());
@@ -1102,7 +1123,7 @@
}
}
-status_t SurfaceFlinger::setActiveMode(const sp<IBinder>& displayToken, int modeId) {
+status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp<IBinder>& displayToken, int modeId) {
ATRACE_CALL();
if (!displayToken) {
@@ -1143,7 +1164,7 @@
return future.get();
}
-void SurfaceFlinger::setActiveModeInternal() {
+void SurfaceFlinger::updateInternalStateWithChangedMode() {
ATRACE_CALL();
const auto display = getDefaultDisplayDeviceLocked();
@@ -1198,9 +1219,8 @@
updatePhaseConfiguration(refreshRate);
}
-void SurfaceFlinger::performSetActiveMode() {
+void SurfaceFlinger::setActiveModeInHwcIfNeeded() {
ATRACE_CALL();
- ALOGV("%s", __FUNCTION__);
for (const auto& iter : mDisplays) {
const auto& display = iter.second;
@@ -1235,8 +1255,7 @@
to_string(display->getId()).c_str());
if (display->getActiveMode()->getId() == desiredActiveMode->mode->getId()) {
- // display is not valid or we are already in the requested mode
- // on both cases there is nothing left to do
+ // we are already in the requested mode, there is nothing left to do
desiredActiveModeChangeDone(display);
continue;
}
@@ -1247,7 +1266,7 @@
const auto displayModeAllowed =
display->refreshRateConfigs().isModeAllowed(desiredActiveMode->mode->getId());
if (!displayModeAllowed) {
- desiredActiveModeChangeDone(display);
+ clearDesiredActiveModeState(display);
continue;
}
@@ -1702,7 +1721,7 @@
mScheduler->resetIdleTimer();
}
mPowerAdvisor.notifyDisplayUpdateImminent();
- mScheduler->scheduleCommit();
+ mScheduler->scheduleFrame();
}
void SurfaceFlinger::scheduleComposite(FrameHint hint) {
@@ -1928,14 +1947,14 @@
// fired yet just wait for the next commit.
if (mSetActiveModePending) {
if (framePending) {
- mScheduler->scheduleCommit();
+ mScheduler->scheduleFrame();
return false;
}
// We received the present fence from the HWC, so we assume it successfully updated
// the mode, hence we update SF.
mSetActiveModePending = false;
- ON_MAIN_THREAD(setActiveModeInternal());
+ ON_MAIN_THREAD(updateInternalStateWithChangedMode());
}
if (framePending) {
@@ -2002,7 +2021,7 @@
mScheduler->chooseRefreshRateForContent();
}
- ON_MAIN_THREAD(performSetActiveMode());
+ ON_MAIN_THREAD(setActiveModeInHwcIfNeeded());
updateCursorAsync();
updateInputFlinger();
@@ -5324,6 +5343,7 @@
scheduleRepaint();
return NO_ERROR;
case 1004: // Force composite ahead of next VSYNC.
+ case 1006:
scheduleComposite(FrameHint::kActive);
return NO_ERROR;
case 1005: { // Force commit ahead of next VSYNC.
@@ -5332,9 +5352,6 @@
eTraversalNeeded);
return NO_ERROR;
}
- case 1006: // Force composite immediately.
- mScheduler->scheduleComposite();
- return NO_ERROR;
case 1007: // Unused.
return NAME_NOT_FOUND;
case 1008: // Toggle forced GPU composition.
@@ -5613,7 +5630,7 @@
}();
mDebugDisplayModeSetByBackdoor = false;
- const status_t result = setActiveMode(display, modeId);
+ const status_t result = setActiveModeFromBackdoor(display, modeId);
mDebugDisplayModeSetByBackdoor = result == NO_ERROR;
return result;
}
@@ -5752,7 +5769,7 @@
const bool timerExpired = mKernelIdleTimerEnabled && expired;
if (display->onKernelTimerChanged(desiredModeId, timerExpired)) {
- mScheduler->scheduleCommit();
+ mScheduler->scheduleFrame();
}
}));
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3037593..05c058b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -660,13 +660,13 @@
void onInitializeDisplays() REQUIRES(mStateLock);
// Sets the desired active mode bit. It obtains the lock, and sets mDesiredActiveMode.
void setDesiredActiveMode(const ActiveModeInfo& info) REQUIRES(mStateLock);
- status_t setActiveMode(const sp<IBinder>& displayToken, int id);
+ status_t setActiveModeFromBackdoor(const sp<IBinder>& displayToken, int id);
// Once HWC has returned the present fence, this sets the active mode and a new refresh
// rate in SF.
- void setActiveModeInternal() REQUIRES(mStateLock);
+ void updateInternalStateWithChangedMode() REQUIRES(mStateLock);
// Calls to setActiveMode on the main thread if there is a pending mode change
// that needs to be applied.
- void performSetActiveMode() REQUIRES(mStateLock);
+ void setActiveModeInHwcIfNeeded() REQUIRES(mStateLock);
void clearDesiredActiveModeState(const sp<DisplayDevice>&) REQUIRES(mStateLock);
// Called when active mode is no longer is progress
void desiredActiveModeChangeDone(const sp<DisplayDevice>&) REQUIRES(mStateLock);
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index fb1d43b..d1dc076 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -22,9 +22,9 @@
namespace android::surfaceflinger {
-proto::TransactionState TransactionProtoParser::toProto(
- const TransactionState& t, std::function<int32_t(const sp<IBinder>&)> getLayerId,
- std::function<int32_t(const sp<IBinder>&)> getDisplayId) {
+proto::TransactionState TransactionProtoParser::toProto(const TransactionState& t,
+ LayerHandleToIdFn getLayerId,
+ DisplayHandleToIdFn getDisplayId) {
proto::TransactionState proto;
proto.set_pid(t.originPid);
proto.set_uid(t.originUid);
@@ -42,10 +42,38 @@
return proto;
}
-proto::LayerState TransactionProtoParser::toProto(
- const layer_state_t& layer, std::function<int32_t(const sp<IBinder>&)> getLayerId) {
+proto::TransactionState TransactionProtoParser::toProto(
+ std::vector<std::pair<int32_t /* layerId */, TracingLayerState>> states) {
+ proto::TransactionState proto;
+ for (auto& [layerId, state] : states) {
+ proto::LayerState layerProto = toProto(state, nullptr);
+ if (layerProto.has_buffer_data()) {
+ proto::LayerState_BufferData* bufferProto = layerProto.mutable_buffer_data();
+ bufferProto->set_buffer_id(state.bufferId);
+ bufferProto->set_width(state.bufferWidth);
+ bufferProto->set_height(state.bufferHeight);
+ }
+ layerProto.set_has_sideband_stream(state.hasSidebandStream);
+ layerProto.set_layer_id(state.layerId);
+ layerProto.set_parent_id(state.parentId);
+ layerProto.set_relative_parent_id(state.relativeParentId);
+ if (layerProto.has_window_info_handle()) {
+ layerProto.mutable_window_info_handle()->set_crop_layer_id(state.inputCropId);
+ }
+ proto.mutable_layer_changes()->Add(std::move(layerProto));
+ }
+ return proto;
+}
+
+proto::LayerState TransactionProtoParser::toProto(const layer_state_t& layer,
+ LayerHandleToIdFn getLayerId) {
proto::LayerState proto;
- proto.set_layer_id(layer.layerId);
+ if (getLayerId != nullptr) {
+ proto.set_layer_id(getLayerId(layer.surface));
+ } else {
+ proto.set_layer_id(layer.layerId);
+ }
+
proto.set_what(layer.what);
if (layer.what & layer_state_t::ePositionChanged) {
@@ -130,13 +158,13 @@
}
}
- if (layer.what & layer_state_t::eReparent) {
+ if ((layer.what & layer_state_t::eReparent) && getLayerId != nullptr) {
int32_t layerId = layer.parentSurfaceControlForChild
? getLayerId(layer.parentSurfaceControlForChild->getHandle())
: -1;
proto.set_parent_id(layerId);
}
- if (layer.what & layer_state_t::eRelativeLayerChanged) {
+ if ((layer.what & layer_state_t::eRelativeLayerChanged) && getLayerId != nullptr) {
int32_t layerId = layer.relativeLayerSurfaceControl
? getLayerId(layer.relativeLayerSurfaceControl->getHandle())
: -1;
@@ -164,8 +192,12 @@
transformProto->set_ty(inputInfo->transform.ty());
windowInfoProto->set_replace_touchable_region_with_crop(
inputInfo->replaceTouchableRegionWithCrop);
- windowInfoProto->set_crop_layer_id(
- getLayerId(inputInfo->touchableRegionCropHandle.promote()));
+ if (getLayerId != nullptr) {
+ windowInfoProto->set_crop_layer_id(
+ getLayerId(inputInfo->touchableRegionCropHandle.promote()));
+ } else {
+ windowInfoProto->set_crop_layer_id(-1);
+ }
}
}
if (layer.what & layer_state_t::eBackgroundColorChanged) {
@@ -212,11 +244,13 @@
return proto;
}
-proto::DisplayState TransactionProtoParser::toProto(
- const DisplayState& display, std::function<int32_t(const sp<IBinder>&)> getDisplayId) {
+proto::DisplayState TransactionProtoParser::toProto(const DisplayState& display,
+ DisplayHandleToIdFn getDisplayId) {
proto::DisplayState proto;
proto.set_what(display.what);
- proto.set_id(getDisplayId(display.token));
+ if (getDisplayId != nullptr) {
+ proto.set_id(getDisplayId(display.token));
+ }
if (display.what & DisplayState::eLayerStackChanged) {
proto.set_layer_stack(display.layerStack.id);
@@ -238,9 +272,18 @@
return proto;
}
-TransactionState TransactionProtoParser::fromProto(
- const proto::TransactionState& proto, std::function<sp<IBinder>(int32_t)> getLayerHandle,
- std::function<sp<IBinder>(int32_t)> getDisplayHandle) {
+proto::LayerCreationArgs TransactionProtoParser::toProto(const TracingLayerCreationArgs& args) {
+ proto::LayerCreationArgs proto;
+ proto.set_layer_id(args.layerId);
+ proto.set_name(args.name);
+ proto.set_flags(args.flags);
+ proto.set_parent_id(args.parentId);
+ return proto;
+}
+
+TransactionState TransactionProtoParser::fromProto(const proto::TransactionState& proto,
+ LayerIdToHandleFn getLayerHandle,
+ DisplayIdToHandleFn getDisplayHandle) {
TransactionState t;
t.originPid = proto.pid();
t.originUid = proto.uid();
@@ -251,7 +294,7 @@
t.states.reserve(static_cast<size_t>(layerCount));
for (int i = 0; i < layerCount; i++) {
ComposerState s;
- s.state = std::move(fromProto(proto.layer_changes(i), getLayerHandle));
+ fromProto(proto.layer_changes(i), getLayerHandle, s.state);
t.states.add(s);
}
@@ -263,88 +306,116 @@
return t;
}
-layer_state_t TransactionProtoParser::fromProto(
- const proto::LayerState& proto, std::function<sp<IBinder>(int32_t)> getLayerHandle) {
- layer_state_t layer;
- layer.layerId = proto.layer_id();
- layer.what = proto.what();
+void TransactionProtoParser::fromProto(const proto::LayerCreationArgs& proto,
+ TracingLayerCreationArgs& outArgs) {
+ outArgs.layerId = proto.layer_id();
+ outArgs.name = proto.name();
+ outArgs.flags = proto.flags();
+ outArgs.parentId = proto.parent_id();
+}
- if (layer.what & layer_state_t::ePositionChanged) {
+void TransactionProtoParser::fromProto(const proto::LayerState& proto,
+ LayerIdToHandleFn getLayerHandle,
+ TracingLayerState& outState) {
+ fromProto(proto, getLayerHandle, static_cast<layer_state_t&>(outState));
+ if (proto.what() & layer_state_t::eReparent) {
+ outState.parentId = proto.parent_id();
+ }
+ if (proto.what() & layer_state_t::eRelativeLayerChanged) {
+ outState.relativeParentId = proto.relative_parent_id();
+ }
+ if (proto.what() & layer_state_t::eInputInfoChanged) {
+ outState.inputCropId = proto.window_info_handle().crop_layer_id();
+ }
+ if (proto.what() & layer_state_t::eBufferChanged) {
+ const proto::LayerState_BufferData& bufferProto = proto.buffer_data();
+ outState.bufferId = bufferProto.buffer_id();
+ outState.bufferWidth = bufferProto.width();
+ outState.bufferHeight = bufferProto.height();
+ }
+ if (proto.what() & layer_state_t::eSidebandStreamChanged) {
+ outState.hasSidebandStream = proto.has_sideband_stream();
+ }
+}
+
+void TransactionProtoParser::fromProto(const proto::LayerState& proto,
+ LayerIdToHandleFn getLayerHandle, layer_state_t& layer) {
+ layer.layerId = proto.layer_id();
+ layer.what |= proto.what();
+
+ if (getLayerHandle != nullptr) {
+ layer.surface = getLayerHandle(layer.layerId);
+ }
+
+ if (proto.what() & layer_state_t::ePositionChanged) {
layer.x = proto.x();
layer.y = proto.y();
}
- if (layer.what & layer_state_t::eLayerChanged) {
+ if (proto.what() & layer_state_t::eLayerChanged) {
layer.z = proto.z();
}
- if (layer.what & layer_state_t::eSizeChanged) {
+ if (proto.what() & layer_state_t::eSizeChanged) {
layer.w = proto.w();
layer.h = proto.h();
}
- if (layer.what & layer_state_t::eLayerStackChanged) {
+ if (proto.what() & layer_state_t::eLayerStackChanged) {
layer.layerStack.id = proto.layer_stack();
}
- if (layer.what & layer_state_t::eFlagsChanged) {
+ if (proto.what() & layer_state_t::eFlagsChanged) {
layer.flags = proto.flags();
layer.mask = proto.mask();
}
- if (layer.what & layer_state_t::eMatrixChanged) {
+ if (proto.what() & layer_state_t::eMatrixChanged) {
const proto::LayerState_Matrix22& matrixProto = proto.matrix();
layer.matrix.dsdx = matrixProto.dsdx();
layer.matrix.dsdy = matrixProto.dsdy();
layer.matrix.dtdx = matrixProto.dtdx();
layer.matrix.dtdy = matrixProto.dtdy();
}
- if (layer.what & layer_state_t::eCornerRadiusChanged) {
+ if (proto.what() & layer_state_t::eCornerRadiusChanged) {
layer.cornerRadius = proto.corner_radius();
}
- if (layer.what & layer_state_t::eBackgroundBlurRadiusChanged) {
+ if (proto.what() & layer_state_t::eBackgroundBlurRadiusChanged) {
layer.backgroundBlurRadius = proto.background_blur_radius();
}
- if (layer.what & layer_state_t::eAlphaChanged) {
+ if (proto.what() & layer_state_t::eAlphaChanged) {
layer.alpha = proto.alpha();
}
- if (layer.what & layer_state_t::eColorChanged) {
+ if (proto.what() & layer_state_t::eColorChanged) {
const proto::LayerState_Color3& colorProto = proto.color();
layer.color.r = colorProto.r();
layer.color.g = colorProto.g();
layer.color.b = colorProto.b();
}
- if (layer.what & layer_state_t::eTransparentRegionChanged) {
+ if (proto.what() & layer_state_t::eTransparentRegionChanged) {
LayerProtoHelper::readFromProto(proto.transparent_region(), layer.transparentRegion);
}
- if (layer.what & layer_state_t::eTransformChanged) {
+ if (proto.what() & layer_state_t::eTransformChanged) {
layer.transform = proto.transform();
}
- if (layer.what & layer_state_t::eTransformToDisplayInverseChanged) {
+ if (proto.what() & layer_state_t::eTransformToDisplayInverseChanged) {
layer.transformToDisplayInverse = proto.transform_to_display_inverse();
}
- if (layer.what & layer_state_t::eCropChanged) {
+ if (proto.what() & layer_state_t::eCropChanged) {
LayerProtoHelper::readFromProto(proto.crop(), layer.crop);
}
- if (layer.what & layer_state_t::eBufferChanged) {
+ if (proto.what() & layer_state_t::eBufferChanged) {
const proto::LayerState_BufferData& bufferProto = proto.buffer_data();
- layer.bufferData.buffer = new GraphicBuffer(bufferProto.width(), bufferProto.height(),
- HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
layer.bufferData.frameNumber = bufferProto.frame_number();
layer.bufferData.flags = Flags<BufferData::BufferDataChange>(bufferProto.flags());
layer.bufferData.cachedBuffer.id = bufferProto.cached_buffer_id();
}
- if (layer.what & layer_state_t::eSidebandStreamChanged) {
- native_handle_t* handle = native_handle_create(0, 0);
- layer.sidebandStream =
- proto.has_sideband_stream() ? NativeHandle::create(handle, true) : nullptr;
- }
- if (layer.what & layer_state_t::eApiChanged) {
+ if (proto.what() & layer_state_t::eApiChanged) {
layer.api = proto.api();
}
- if (layer.what & layer_state_t::eColorTransformChanged) {
+ if (proto.what() & layer_state_t::eColorTransformChanged) {
LayerProtoHelper::readFromProto(proto.color_transform(), layer.colorTransform);
}
- if (layer.what & layer_state_t::eBlurRegionsChanged) {
+ if (proto.what() & layer_state_t::eBlurRegionsChanged) {
layer.blurRegions.reserve(static_cast<size_t>(proto.blur_regions_size()));
for (int i = 0; i < proto.blur_regions_size(); i++) {
android::BlurRegion region;
@@ -353,20 +424,20 @@
}
}
- if (layer.what & layer_state_t::eReparent) {
+ if ((proto.what() & layer_state_t::eReparent) && (getLayerHandle != nullptr)) {
int32_t layerId = proto.parent_id();
layer.parentSurfaceControlForChild =
new SurfaceControl(SurfaceComposerClient::getDefault(), getLayerHandle(layerId),
nullptr, layerId);
}
- if (layer.what & layer_state_t::eRelativeLayerChanged) {
+ if ((proto.what() & layer_state_t::eRelativeLayerChanged) && (getLayerHandle != nullptr)) {
int32_t layerId = proto.relative_parent_id();
layer.relativeLayerSurfaceControl =
new SurfaceControl(SurfaceComposerClient::getDefault(), getLayerHandle(layerId),
nullptr, layerId);
}
- if ((layer.what & layer_state_t::eInputInfoChanged) && proto.has_window_info_handle()) {
+ if ((proto.what() & layer_state_t::eInputInfoChanged) && proto.has_window_info_handle()) {
gui::WindowInfo inputInfo;
const proto::LayerState_WindowInfo& windowInfoProto = proto.window_info_handle();
@@ -385,10 +456,12 @@
inputInfo.replaceTouchableRegionWithCrop =
windowInfoProto.replace_touchable_region_with_crop();
int32_t layerId = windowInfoProto.crop_layer_id();
- inputInfo.touchableRegionCropHandle = getLayerHandle(layerId);
+ if (getLayerHandle != nullptr) {
+ inputInfo.touchableRegionCropHandle = getLayerHandle(layerId);
+ }
layer.windowInfoHandle = sp<gui::WindowInfoHandle>::make(inputInfo);
}
- if (layer.what & layer_state_t::eBackgroundColorChanged) {
+ if (proto.what() & layer_state_t::eBackgroundColorChanged) {
layer.bgColorAlpha = proto.bg_color_alpha();
layer.bgColorDataspace = static_cast<ui::Dataspace>(proto.bg_color_dataspace());
const proto::LayerState_Color3& colorProto = proto.color();
@@ -396,44 +469,43 @@
layer.color.g = colorProto.g();
layer.color.b = colorProto.b();
}
- if (layer.what & layer_state_t::eColorSpaceAgnosticChanged) {
+ if (proto.what() & layer_state_t::eColorSpaceAgnosticChanged) {
layer.colorSpaceAgnostic = proto.color_space_agnostic();
}
- if (layer.what & layer_state_t::eShadowRadiusChanged) {
+ if (proto.what() & layer_state_t::eShadowRadiusChanged) {
layer.shadowRadius = proto.shadow_radius();
}
- if (layer.what & layer_state_t::eFrameRateSelectionPriority) {
+ if (proto.what() & layer_state_t::eFrameRateSelectionPriority) {
layer.frameRateSelectionPriority = proto.frame_rate_selection_priority();
}
- if (layer.what & layer_state_t::eFrameRateChanged) {
+ if (proto.what() & layer_state_t::eFrameRateChanged) {
layer.frameRate = proto.frame_rate();
layer.frameRateCompatibility = static_cast<int8_t>(proto.frame_rate_compatibility());
layer.changeFrameRateStrategy = static_cast<int8_t>(proto.change_frame_rate_strategy());
}
- if (layer.what & layer_state_t::eFixedTransformHintChanged) {
+ if (proto.what() & layer_state_t::eFixedTransformHintChanged) {
layer.fixedTransformHint =
static_cast<ui::Transform::RotationFlags>(proto.fixed_transform_hint());
}
- if (layer.what & layer_state_t::eAutoRefreshChanged) {
+ if (proto.what() & layer_state_t::eAutoRefreshChanged) {
layer.autoRefresh = proto.auto_refresh();
}
- if (layer.what & layer_state_t::eTrustedOverlayChanged) {
+ if (proto.what() & layer_state_t::eTrustedOverlayChanged) {
layer.isTrustedOverlay = proto.is_trusted_overlay();
}
- if (layer.what & layer_state_t::eBufferCropChanged) {
+ if (proto.what() & layer_state_t::eBufferCropChanged) {
LayerProtoHelper::readFromProto(proto.buffer_crop(), layer.bufferCrop);
}
- if (layer.what & layer_state_t::eDestinationFrameChanged) {
+ if (proto.what() & layer_state_t::eDestinationFrameChanged) {
LayerProtoHelper::readFromProto(proto.destination_frame(), layer.destinationFrame);
}
- if (layer.what & layer_state_t::eDropInputModeChanged) {
+ if (proto.what() & layer_state_t::eDropInputModeChanged) {
layer.dropInputMode = static_cast<gui::DropInputMode>(proto.drop_input_mode());
}
- return layer;
}
-DisplayState TransactionProtoParser::fromProto(
- const proto::DisplayState& proto, std::function<sp<IBinder>(int32_t)> getDisplayHandle) {
+DisplayState TransactionProtoParser::fromProto(const proto::DisplayState& proto,
+ DisplayIdToHandleFn getDisplayHandle) {
DisplayState display;
display.what = proto.what();
display.token = getDisplayHandle(proto.id());
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.h b/services/surfaceflinger/Tracing/TransactionProtoParser.h
index a2b8889..e8a139f 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.h
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.h
@@ -21,24 +21,53 @@
#include "TransactionState.h"
namespace android::surfaceflinger {
+
+struct TracingLayerCreationArgs {
+ int32_t layerId;
+ std::string name;
+ uint32_t flags;
+ int32_t parentId;
+};
+
+struct TracingLayerState : layer_state_t {
+ uint64_t bufferId;
+ uint32_t bufferHeight;
+ uint32_t bufferWidth;
+ bool hasSidebandStream;
+ int32_t parentId;
+ int32_t relativeParentId;
+ int32_t inputCropId;
+ std::string name;
+ uint32_t layerCreationFlags;
+};
+
class TransactionProtoParser {
public:
+ typedef std::function<sp<IBinder>(int32_t)> LayerIdToHandleFn;
+ typedef std::function<sp<IBinder>(int32_t)> DisplayIdToHandleFn;
+ typedef std::function<int32_t(const sp<IBinder>&)> LayerHandleToIdFn;
+ typedef std::function<int32_t(const sp<IBinder>&)> DisplayHandleToIdFn;
+
+ static proto::TransactionState toProto(const TransactionState&, LayerHandleToIdFn getLayerIdFn,
+ DisplayHandleToIdFn getDisplayIdFn);
static proto::TransactionState toProto(
- const TransactionState&, std::function<int32_t(const sp<IBinder>&)> getLayerIdFn,
- std::function<int32_t(const sp<IBinder>&)> getDisplayIdFn);
+ std::vector<std::pair<int32_t /* layerId */, TracingLayerState>>);
+
+ static proto::LayerCreationArgs toProto(const TracingLayerCreationArgs& args);
+
static TransactionState fromProto(const proto::TransactionState&,
- std::function<sp<IBinder>(int32_t)> getLayerHandleFn,
- std::function<sp<IBinder>(int32_t)> getDisplayHandleFn);
+ LayerIdToHandleFn getLayerHandleFn,
+ DisplayIdToHandleFn getDisplayHandleFn);
+ static void fromProto(const proto::LayerState&, LayerIdToHandleFn getLayerHandleFn,
+ TracingLayerState& outState);
+ static void fromProto(const proto::LayerCreationArgs&, TracingLayerCreationArgs& outArgs);
private:
- static proto::LayerState toProto(const layer_state_t&,
- std::function<int32_t(const sp<IBinder>&)> getLayerId);
- static proto::DisplayState toProto(const DisplayState&,
- std::function<int32_t(const sp<IBinder>&)> getDisplayId);
- static layer_state_t fromProto(const proto::LayerState&,
- std::function<sp<IBinder>(int32_t)> getLayerHandle);
- static DisplayState fromProto(const proto::DisplayState&,
- std::function<sp<IBinder>(int32_t)> getDisplayHandle);
+ static proto::LayerState toProto(const layer_state_t&, LayerHandleToIdFn getLayerId);
+ static proto::DisplayState toProto(const DisplayState&, DisplayHandleToIdFn getDisplayId);
+ static void fromProto(const proto::LayerState&, LayerIdToHandleFn getLayerHandle,
+ layer_state_t& out);
+ static DisplayState fromProto(const proto::DisplayState&, DisplayIdToHandleFn getDisplayHandle);
};
} // namespace android::surfaceflinger
\ No newline at end of file
diff --git a/services/surfaceflinger/layerproto/transactions.proto b/services/surfaceflinger/layerproto/transactions.proto
index e7fb180..edeacfa 100644
--- a/services/surfaceflinger/layerproto/transactions.proto
+++ b/services/surfaceflinger/layerproto/transactions.proto
@@ -39,21 +39,28 @@
}
message TransactionTraceEntry {
- int64 elapsed_time = 1;
+ int64 elapsed_realtime_nanos = 1;
int64 vsync_id = 2;
repeated TransactionState transactions = 3;
+ repeated LayerCreationArgs new_layers = 4;
+ repeated DisplayState new_displays = 5;
+}
+
+message LayerCreationArgs {
+ int32 layer_id = 1;
+ string name = 2;
+ uint32 flags = 3;
+ int32 parent_id = 4;
}
message TransactionState {
- string tag = 2;
- int32 pid = 3;
- int32 uid = 4;
- int64 vsync_id = 5;
- int32 input_event_id = 6;
- int64 post_time = 7;
- repeated LayerState layer_changes = 9;
- repeated DisplayState new_displays = 10;
- repeated DisplayState display_changes = 11;
+ int32 pid = 1;
+ int32 uid = 2;
+ int64 vsync_id = 3;
+ int32 input_event_id = 4;
+ int64 post_time = 5;
+ repeated LayerState layer_changes = 6;
+ repeated DisplayState display_changes = 7;
}
// Keep insync with layer_state_t
@@ -130,8 +137,8 @@
eLayerSecure = 0x80;
eEnableBackpressure = 0x100;
};
- uint32 flags = 10;
- uint32 mask = 11;
+ uint32 flags = 9;
+ uint32 mask = 10;
message Matrix22 {
float dsdx = 1;
@@ -139,29 +146,29 @@
float dtdy = 3;
float dsdy = 4;
};
- Matrix22 matrix = 12;
- float corner_radius = 13;
- uint32 background_blur_radius = 14;
- int32 parent_id = 15;
- int32 relative_parent_id = 16;
+ Matrix22 matrix = 11;
+ float corner_radius = 12;
+ uint32 background_blur_radius = 13;
+ int32 parent_id = 14;
+ int32 relative_parent_id = 15;
- float alpha = 50;
+ float alpha = 16;
message Color3 {
float r = 1;
float g = 2;
float b = 3;
}
- Color3 color = 18;
- RegionProto transparent_region = 19;
- uint32 transform = 20;
- bool transform_to_display_inverse = 21;
- RectProto crop = 49;
+ Color3 color = 17;
+ RegionProto transparent_region = 18;
+ uint32 transform = 19;
+ bool transform_to_display_inverse = 20;
+ RectProto crop = 21;
message BufferData {
uint64 buffer_id = 1;
uint32 width = 2;
uint32 height = 3;
- uint64 frame_number = 5;
+ uint64 frame_number = 4;
enum BufferDataChange {
BufferDataChangeNone = 0;
@@ -169,14 +176,14 @@
frameNumberChanged = 0x02;
cachedBufferChanged = 0x04;
}
- uint32 flags = 6;
- uint64 cached_buffer_id = 7;
+ uint32 flags = 5;
+ uint64 cached_buffer_id = 6;
}
- BufferData buffer_data = 23;
- int32 api = 24;
- bool has_sideband_stream = 25;
- ColorTransformProto color_transform = 26;
- repeated BlurRegion blur_regions = 27;
+ BufferData buffer_data = 22;
+ int32 api = 23;
+ bool has_sideband_stream = 24;
+ ColorTransformProto color_transform = 25;
+ repeated BlurRegion blur_regions = 26;
message Transform {
float dsdx = 1;
@@ -189,38 +196,38 @@
message WindowInfo {
uint32 layout_params_flags = 1;
int32 layout_params_type = 2;
- RegionProto touchable_region = 4;
- int32 surface_inset = 5;
- bool focusable = 8;
- bool has_wallpaper = 9;
- float global_scale_factor = 10;
- int32 crop_layer_id = 13;
- bool replace_touchable_region_with_crop = 14;
- RectProto touchable_region_crop = 15;
- Transform transform = 16;
+ RegionProto touchable_region = 3;
+ int32 surface_inset = 4;
+ bool focusable = 5;
+ bool has_wallpaper = 6;
+ float global_scale_factor = 7;
+ int32 crop_layer_id = 8;
+ bool replace_touchable_region_with_crop = 9;
+ RectProto touchable_region_crop = 10;
+ Transform transform = 11;
}
- WindowInfo window_info_handle = 28;
- float bg_color_alpha = 31;
- int32 bg_color_dataspace = 32;
- bool color_space_agnostic = 33;
- float shadow_radius = 34;
- int32 frame_rate_selection_priority = 35;
- float frame_rate = 36;
- int32 frame_rate_compatibility = 37;
- int32 change_frame_rate_strategy = 38;
- uint32 fixed_transform_hint = 39;
- uint64 frame_number = 40;
- bool auto_refresh = 41;
- bool is_trusted_overlay = 42;
- RectProto buffer_crop = 44;
- RectProto destination_frame = 45;
+ WindowInfo window_info_handle = 27;
+ float bg_color_alpha = 28;
+ int32 bg_color_dataspace = 29;
+ bool color_space_agnostic = 30;
+ float shadow_radius = 31;
+ int32 frame_rate_selection_priority = 32;
+ float frame_rate = 33;
+ int32 frame_rate_compatibility = 34;
+ int32 change_frame_rate_strategy = 35;
+ uint32 fixed_transform_hint = 36;
+ uint64 frame_number = 37;
+ bool auto_refresh = 38;
+ bool is_trusted_overlay = 39;
+ RectProto buffer_crop = 40;
+ RectProto destination_frame = 41;
enum DropInputMode {
NONE = 0;
ALL = 1;
OBSCURED = 2;
};
- DropInputMode drop_input_mode = 48;
+ DropInputMode drop_input_mode = 42;
}
message DisplayState {
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 0c9e6e1..8d2c078 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -536,7 +536,7 @@
ASSERT_EQ(NO_ERROR, err);
Mock::VerifyAndClear(test->mRenderEngine);
- EXPECT_CALL(*test->mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*test->mFlinger.scheduler(), scheduleFrame()).Times(1);
enqueueBuffer(test, layer);
Mock::VerifyAndClearExpectations(test->mFlinger.scheduler());
diff --git a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
index 17d1dd6..bd4dc59 100644
--- a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
@@ -41,7 +41,7 @@
struct MockHandler : MessageQueue::Handler {
using MessageQueue::Handler::Handler;
- MOCK_METHOD(void, dispatchCommit, (int64_t, nsecs_t), (override));
+ MOCK_METHOD(void, dispatchFrame, (int64_t, nsecs_t), (override));
};
explicit TestableMessageQueue(sp<MockHandler> handler)
@@ -96,7 +96,7 @@
EXPECT_FALSE(mEventQueue.getScheduledFrameTime());
EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234));
- EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit());
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
ASSERT_TRUE(mEventQueue.getScheduledFrameTime());
EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count());
@@ -109,13 +109,13 @@
.earliestVsync = 0};
EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234));
- EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit());
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
ASSERT_TRUE(mEventQueue.getScheduledFrameTime());
EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count());
EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(4567));
- EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit());
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
ASSERT_TRUE(mEventQueue.getScheduledFrameTime());
EXPECT_EQ(4567, mEventQueue.getScheduledFrameTime()->time_since_epoch().count());
@@ -128,7 +128,7 @@
.earliestVsync = 0};
EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234));
- EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit());
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
ASSERT_TRUE(mEventQueue.getScheduledFrameTime());
EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count());
@@ -141,7 +141,7 @@
generateTokenForPredictions(
frametimeline::TimelineItem(startTime, endTime, presentTime)))
.WillOnce(Return(vsyncId));
- EXPECT_CALL(*mEventQueue.mHandler, dispatchCommit(vsyncId, presentTime)).Times(1);
+ EXPECT_CALL(*mEventQueue.mHandler, dispatchFrame(vsyncId, presentTime)).Times(1);
EXPECT_NO_FATAL_FAILURE(mEventQueue.vsyncCallback(presentTime, startTime, endTime));
EXPECT_FALSE(mEventQueue.getScheduledFrameTime());
@@ -152,7 +152,7 @@
.earliestVsync = presentTime};
EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timingAfterCallback)).WillOnce(Return(0));
- EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit());
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
}
TEST_F(MessageQueueTest, commitWithDurationChange) {
@@ -164,7 +164,7 @@
.earliestVsync = 0};
EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(0));
- EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit());
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame());
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index 115a44d..eed62a7 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -169,7 +169,7 @@
namespace {
TEST_P(SetFrameRateTest, SetAndGet) {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
const auto& layerFactory = GetParam();
@@ -180,7 +180,7 @@
}
TEST_P(SetFrameRateTest, SetAndGetParent) {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
const auto& layerFactory = GetParam();
@@ -205,7 +205,7 @@
}
TEST_P(SetFrameRateTest, SetAndGetParentAllVote) {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
const auto& layerFactory = GetParam();
@@ -244,7 +244,7 @@
}
TEST_P(SetFrameRateTest, SetAndGetChild) {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
const auto& layerFactory = GetParam();
@@ -269,7 +269,7 @@
}
TEST_P(SetFrameRateTest, SetAndGetChildAllVote) {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
const auto& layerFactory = GetParam();
@@ -308,7 +308,7 @@
}
TEST_P(SetFrameRateTest, SetAndGetChildAddAfterVote) {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
const auto& layerFactory = GetParam();
@@ -338,7 +338,7 @@
}
TEST_P(SetFrameRateTest, SetAndGetChildRemoveAfterVote) {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
const auto& layerFactory = GetParam();
@@ -369,7 +369,7 @@
}
TEST_P(SetFrameRateTest, SetAndGetParentNotInTree) {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
const auto& layerFactory = GetParam();
@@ -464,7 +464,7 @@
}
TEST_P(SetFrameRateTest, addChildForParentWithTreeVote) {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
const auto& layerFactory = GetParam();
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
index 2236db7..f7d34ac 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
@@ -52,7 +52,7 @@
// Cleanup conditions
// Creating the display commits a display transaction.
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
}
TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForSecureDisplay) {
@@ -87,7 +87,7 @@
// Cleanup conditions
// Creating the display commits a display transaction.
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp
index bcd3222..c7e61c9 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp
@@ -41,7 +41,7 @@
EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1);
// Destroying the display commits a display transaction.
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
// --------------------------------------------------------------------
// Invocation
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
index cc979c9..c9a2b00 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
@@ -39,7 +39,7 @@
// Call Expectations
// We expect a scheduled commit for the display transaction.
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
// --------------------------------------------------------------------
// Invocation
@@ -86,7 +86,7 @@
// Call Expectations
// We expect a scheduled commit for the display transaction.
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
// --------------------------------------------------------------------
// Invocation
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
index 83b150f..37cf05e 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
@@ -47,7 +47,7 @@
Case::Display::setupHwcGetActiveConfigCallExpectations(this);
// We expect a scheduled commit for the display transaction.
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
index ad696aa..b57feff 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
@@ -273,7 +273,7 @@
}
static void setupRepaintEverythingCallExpectations(DisplayTransactionTest* test) {
- EXPECT_CALL(*test->mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*test->mFlinger.scheduler(), scheduleFrame()).Times(1);
}
static void setupSurfaceInterceptorCallExpectations(DisplayTransactionTest* test,
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 32ec848..9d1fc98 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -52,7 +52,7 @@
});
}
- MOCK_METHOD(void, scheduleCommit, (), (override));
+ MOCK_METHOD(void, scheduleFrame, (), (override));
MOCK_METHOD(void, postMessage, (sp<MessageHandler>&&), (override));
// Used to inject mock event thread.
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index b3a6a1b..ec19100 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -143,7 +143,7 @@
void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
TransactionInfo transaction;
setupSingle(transaction, flags, syncInputWindows,
/*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
@@ -173,7 +173,7 @@
void PlaceOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
// first check will see desired present time has not passed,
// but afterwards it will look like the desired present time has passed
@@ -204,9 +204,9 @@
ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
nsecs_t time = systemTime();
if (!syncInputWindows) {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(2);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(2);
} else {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
}
// transaction that should go on the pending thread
TransactionInfo transactionA;
@@ -451,7 +451,7 @@
TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) {
ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_CALL(*mFlinger.scheduler(), scheduleCommit()).Times(1);
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
TransactionInfo transactionA; // transaction to go on pending queue
setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false,
diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
index cebd451..6e00748 100644
--- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
@@ -69,16 +69,16 @@
t1.displays.add(display);
}
- std::function<int32_t(const sp<IBinder>&)> getLayerIdFn = [&](const sp<IBinder>& handle) {
+ TransactionProtoParser::LayerHandleToIdFn getLayerIdFn = [&](const sp<IBinder>& handle) {
return (handle == layerHandle) ? 42 : -1;
};
- std::function<int32_t(const sp<IBinder>&)> getDisplayIdFn = [&](const sp<IBinder>& handle) {
+ TransactionProtoParser::DisplayHandleToIdFn getDisplayIdFn = [&](const sp<IBinder>& handle) {
return (handle == displayHandle) ? 43 : -1;
};
- std::function<sp<IBinder>(int32_t)> getLayerHandleFn = [&](int32_t id) {
+ TransactionProtoParser::LayerIdToHandleFn getLayerHandleFn = [&](int32_t id) {
return (id == 42) ? layerHandle : nullptr;
};
- std::function<sp<IBinder>(int32_t)> getDisplayHandleFn = [&](int32_t id) {
+ TransactionProtoParser::DisplayIdToHandleFn getDisplayHandleFn = [&](int32_t id) {
return (id == 43) ? displayHandle : nullptr;
};