Merge "Add property for mute events from volume shaper"
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 891b1c6..2e0c95a 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -300,6 +300,12 @@
chmod 0666 /sys/kernel/debug/tracing/events/kmem/rss_stat/trigger
chmod 0666 /sys/kernel/tracing/events/kmem/rss_stat/trigger
+on late-init && property:ro.boot.fastboot.boottrace=enabled
+ setprop debug.atrace.tags.enableflags 802922
+ setprop persist.traced.enable 0
+ write /sys/kernel/debug/tracing/tracing_on 1
+ write /sys/kernel/tracing/tracing_on 1
+
# Only create the tracing instance if persist.mm_events.enabled
# Attempting to remove the tracing instance after it has been created
# will likely fail with EBUSY as it would be in use by traced_probes.
@@ -395,3 +401,10 @@
service boottrace /system/bin/atrace --async_start -f /data/misc/boottrace/categories
disabled
oneshot
+
+on property:sys.boot_completed=1 && property:ro.boot.fastboot.boottrace=enabled
+ setprop debug.atrace.tags.enableflags 0
+ setprop persist.traced.enable 1
+ write /sys/kernel/debug/tracing/tracing_on 0
+ write /sys/kernel/tracing/tracing_on 0
+
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index f6f8939..585ea3c 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -240,8 +240,7 @@
KeyCharacterMap(const std::string& filename);
bool getKey(int32_t keyCode, const Key** outKey) const;
- bool getKeyBehavior(int32_t keyCode, int32_t metaState,
- const Key** outKey, const Behavior** outBehavior) const;
+ const Behavior* getKeyBehavior(int32_t keyCode, int32_t metaState) const;
static bool matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState);
bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const;
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index e6dbd79..d347262 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -36,6 +36,7 @@
#include <utils/Compat.h>
#include <utils/String8.h>
+#include "BuildFlags.h"
#include "FdTrigger.h"
#include "OS.h"
#include "RpcSocketAddress.h"
@@ -78,10 +79,8 @@
void RpcSession::setMaxIncomingThreads(size_t threads) {
RpcMutexLockGuard _l(mMutex);
- LOG_ALWAYS_FATAL_IF(!mConnections.mOutgoing.empty() || !mConnections.mIncoming.empty(),
- "Must set max incoming threads before setting up connections, but has %zu "
- "client(s) and %zu server(s)",
- mConnections.mOutgoing.size(), mConnections.mIncoming.size());
+ LOG_ALWAYS_FATAL_IF(mStartedSetup,
+ "Must set max incoming threads before setting up connections");
mMaxIncomingThreads = threads;
}
@@ -92,10 +91,8 @@
void RpcSession::setMaxOutgoingThreads(size_t threads) {
RpcMutexLockGuard _l(mMutex);
- LOG_ALWAYS_FATAL_IF(!mConnections.mOutgoing.empty() || !mConnections.mIncoming.empty(),
- "Must set max outgoing threads before setting up connections, but has %zu "
- "client(s) and %zu server(s)",
- mConnections.mOutgoing.size(), mConnections.mIncoming.size());
+ LOG_ALWAYS_FATAL_IF(mStartedSetup,
+ "Must set max outgoing threads before setting up connections");
mMaxOutgoingThreads = threads;
}
@@ -104,7 +101,7 @@
return mMaxOutgoingThreads;
}
-bool RpcSession::setProtocolVersion(uint32_t version) {
+bool RpcSession::setProtocolVersionInternal(uint32_t version, bool checkStarted) {
if (version >= RPC_WIRE_PROTOCOL_VERSION_NEXT &&
version != RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL) {
ALOGE("Cannot start RPC session with version %u which is unknown (current protocol version "
@@ -114,6 +111,8 @@
}
RpcMutexLockGuard _l(mMutex);
+ LOG_ALWAYS_FATAL_IF(checkStarted && mStartedSetup,
+ "Must set protocol version before setting up connections");
if (mProtocolVersion && version > *mProtocolVersion) {
ALOGE("Cannot upgrade explicitly capped protocol version %u to newer version %u",
*mProtocolVersion, version);
@@ -124,12 +123,19 @@
return true;
}
+bool RpcSession::setProtocolVersion(uint32_t version) {
+ return setProtocolVersionInternal(version, true);
+}
+
std::optional<uint32_t> RpcSession::getProtocolVersion() {
RpcMutexLockGuard _l(mMutex);
return mProtocolVersion;
}
void RpcSession::setFileDescriptorTransportMode(FileDescriptorTransportMode mode) {
+ RpcMutexLockGuard _l(mMutex);
+ LOG_ALWAYS_FATAL_IF(mStartedSetup,
+ "Must set file descriptor transport mode before setting up connections");
mFileDescriptorTransportMode = mode;
}
@@ -445,9 +451,16 @@
bool incoming)>& connectAndInit) {
{
RpcMutexLockGuard _l(mMutex);
- LOG_ALWAYS_FATAL_IF(mConnections.mOutgoing.size() != 0,
- "Must only setup session once, but already has %zu clients",
- mConnections.mOutgoing.size());
+ LOG_ALWAYS_FATAL_IF(mStartedSetup, "Must only setup session once");
+ mStartedSetup = true;
+
+ if constexpr (!kEnableRpcThreads) {
+ LOG_ALWAYS_FATAL_IF(mMaxIncomingThreads > 0,
+ "Incoming threads are not supported on single-threaded libbinder");
+ // mMaxIncomingThreads should not change from here to its use below,
+ // since we set mStartedSetup==true and setMaxIncomingThreads checks
+ // for that
+ }
}
if (auto status = initShutdownTrigger(); status != OK) return status;
@@ -488,7 +501,7 @@
sp<RpcSession>::fromExisting(this), &version);
status != OK)
return status;
- if (!setProtocolVersion(version)) return BAD_VALUE;
+ if (!setProtocolVersionInternal(version, false)) return BAD_VALUE;
}
// TODO(b/189955605): we should add additional sessions dynamically
@@ -506,11 +519,7 @@
return status;
}
-#ifdef BINDER_RPC_SINGLE_THREADED
- constexpr size_t outgoingThreads = 1;
-#else // BINDER_RPC_SINGLE_THREADED
size_t outgoingThreads = std::min(numThreadsAvailable, mMaxOutgoingThreads);
-#endif // BINDER_RPC_SINGLE_THREADED
ALOGI_IF(outgoingThreads != numThreadsAvailable,
"Server hints client to start %zu outgoing threads, but client will only start %zu "
"because it is preconfigured to start at most %zu outgoing threads.",
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 9d94e00..428e272 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -207,6 +207,10 @@
friend RpcState;
explicit RpcSession(std::unique_ptr<RpcTransportCtx> ctx);
+ // internal version of setProtocolVersion that
+ // optionally skips the mStartedSetup check
+ [[nodiscard]] bool setProtocolVersionInternal(uint32_t version, bool checkStarted);
+
// for 'target', see RpcState::sendDecStrongToTarget
[[nodiscard]] status_t sendDecStrongToTarget(uint64_t address, size_t target);
@@ -344,6 +348,7 @@
RpcMutex mMutex; // for all below
+ bool mStartedSetup = false;
size_t mMaxIncomingThreads = 0;
size_t mMaxOutgoingThreads = kDefaultMaxOutgoingThreads;
std::optional<uint32_t> mProtocolVersion;
diff --git a/libs/binder/rust/src/error.rs b/libs/binder/rust/src/error.rs
index 2598ebc..f6b09ed 100644
--- a/libs/binder/rust/src/error.rs
+++ b/libs/binder/rust/src/error.rs
@@ -18,7 +18,7 @@
use crate::sys;
use std::error;
-use std::ffi::CStr;
+use std::ffi::{CStr, CString};
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::result;
@@ -104,6 +104,10 @@
// A thread-local `AStatus` would not be valid.
unsafe impl Send for Status {}
+fn to_cstring<T: AsRef<str>>(message: T) -> Option<CString> {
+ CString::new(message.as_ref()).ok()
+}
+
impl Status {
/// Create a status object representing a successful transaction.
pub fn ok() -> Self {
@@ -146,6 +150,11 @@
Self(ptr)
}
+ /// Creates a status object from a service specific error.
+ pub fn new_service_specific_error_str<T: AsRef<str>>(err: i32, message: Option<T>) -> Status {
+ Self::new_service_specific_error(err, message.and_then(to_cstring).as_deref())
+ }
+
/// Create a status object from an exception code
pub fn new_exception(exception: ExceptionCode, message: Option<&CStr>) -> Status {
if let Some(message) = message {
@@ -158,6 +167,14 @@
}
}
+ /// Creates a status object from an exception code and message.
+ pub fn new_exception_str<T: AsRef<str>>(
+ exception: ExceptionCode,
+ message: Option<T>,
+ ) -> Status {
+ Self::new_exception(exception, message.and_then(to_cstring).as_deref())
+ }
+
/// Create a status object from a raw `AStatus` pointer.
///
/// # Safety
@@ -371,3 +388,41 @@
self.0
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn make_service_specific_error() {
+ let status = Status::new_service_specific_error_str(-42, Some("message"));
+
+ assert!(!status.is_ok());
+ assert_eq!(status.exception_code(), ExceptionCode::SERVICE_SPECIFIC);
+ assert_eq!(status.service_specific_error(), -42);
+ assert_eq!(
+ status.get_description(),
+ "Status(-8, EX_SERVICE_SPECIFIC): '-42: message'".to_string()
+ );
+ }
+
+ #[test]
+ fn make_exception() {
+ let status = Status::new_exception_str(ExceptionCode::ILLEGAL_STATE, Some("message"));
+
+ assert!(!status.is_ok());
+ assert_eq!(status.exception_code(), ExceptionCode::ILLEGAL_STATE);
+ assert_eq!(status.service_specific_error(), 0);
+ assert_eq!(status.get_description(), "Status(-5, EX_ILLEGAL_STATE): 'message'".to_string());
+ }
+
+ #[test]
+ fn make_exception_null() {
+ let status = Status::new_exception_str(ExceptionCode::ILLEGAL_STATE, Some("one\0two"));
+
+ assert!(!status.is_ok());
+ assert_eq!(status.exception_code(), ExceptionCode::ILLEGAL_STATE);
+ assert_eq!(status.service_specific_error(), 0);
+ assert_eq!(status.get_description(), "Status(-5, EX_ILLEGAL_STATE): ''".to_string());
+ }
+}
diff --git a/libs/cputimeinstate/fuzz/cputimeinstate_fuzzer/Android.bp b/libs/cputimeinstate/fuzz/cputimeinstate_fuzzer/Android.bp
index 416e34e..2399acd 100644
--- a/libs/cputimeinstate/fuzz/cputimeinstate_fuzzer/Android.bp
+++ b/libs/cputimeinstate/fuzz/cputimeinstate_fuzzer/Android.bp
@@ -16,6 +16,15 @@
*
*****************************************************************************
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_fuzz {
name: "cputimeinstate_fuzzer",
srcs: [
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index 2039fa6..5cb844e 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -304,9 +304,8 @@
char16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const {
char16_t result = 0;
- const Key* key;
- const Behavior* behavior;
- if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
+ const Behavior* behavior = getKeyBehavior(keyCode, metaState);
+ if (behavior != nullptr) {
result = behavior->character;
}
#if DEBUG_MAPPING
@@ -321,9 +320,8 @@
outFallbackAction->metaState = 0;
bool result = false;
- const Key* key;
- const Behavior* behavior;
- if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
+ const Behavior* behavior = getKeyBehavior(keyCode, metaState);
+ if (behavior != nullptr) {
if (behavior->fallbackKeyCode) {
outFallbackAction->keyCode = behavior->fallbackKeyCode;
outFallbackAction->metaState = metaState & ~behavior->metaState;
@@ -438,9 +436,8 @@
*outKeyCode = keyCode;
*outMetaState = metaState;
- const Key* key;
- const Behavior* behavior;
- if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
+ const Behavior* behavior = getKeyBehavior(keyCode, metaState);
+ if (behavior != nullptr) {
if (behavior->replacementKeyCode) {
*outKeyCode = behavior->replacementKeyCode;
int32_t newMetaState = metaState & ~behavior->metaState;
@@ -484,21 +481,19 @@
return false;
}
-bool KeyCharacterMap::getKeyBehavior(int32_t keyCode, int32_t metaState,
- const Key** outKey, const Behavior** outBehavior) const {
+const KeyCharacterMap::Behavior* KeyCharacterMap::getKeyBehavior(int32_t keyCode,
+ int32_t metaState) const {
const Key* key;
if (getKey(keyCode, &key)) {
const Behavior* behavior = key->firstBehavior;
while (behavior) {
if (matchesMetaState(metaState, behavior->metaState)) {
- *outKey = key;
- *outBehavior = behavior;
- return true;
+ return behavior;
}
behavior = behavior->next;
}
}
- return false;
+ return nullptr;
}
bool KeyCharacterMap::matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState) {
diff --git a/libs/sensor/fuzz/bittube_fuzzer/Android.bp b/libs/sensor/fuzz/bittube_fuzzer/Android.bp
index 5d8f401..7af22cc 100644
--- a/libs/sensor/fuzz/bittube_fuzzer/Android.bp
+++ b/libs/sensor/fuzz/bittube_fuzzer/Android.bp
@@ -16,6 +16,15 @@
*
*****************************************************************************
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_fuzz {
name: "bittube_fuzzer",
srcs: [
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 542efae..29a0e4f 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -190,6 +190,7 @@
"libinputservice_test",
"Bug-115739809",
"StructLayout_test",
+ "inputflinger_latencytracker_fuzzer",
// Java/Kotlin targets
"CtsWindowManagerDeviceTestCases",
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index a17d2c0..bfa44ac 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -1310,7 +1310,8 @@
if (!identifier.uniqueId.empty()) {
rawDescriptor += "uniqueId:";
rawDescriptor += identifier.uniqueId;
- } else if (identifier.nonce != 0) {
+ }
+ if (identifier.nonce != 0) {
rawDescriptor += StringPrintf("nonce:%04x", identifier.nonce);
}
@@ -1338,16 +1339,20 @@
// of Android. In practice we sometimes get devices that cannot be uniquely
// identified. In this case we enforce uniqueness between connected devices.
// Ideally, we also want the descriptor to be short and relatively opaque.
+ // Note that we explicitly do not use the path or location for external devices
+ // as their path or location will change as they are plugged/unplugged or moved
+ // to different ports. We do fallback to using name and location in the case of
+ // internal devices which are detected by the vendor and product being 0 in
+ // generateDescriptor. If two identical descriptors are detected we will fallback
+ // to using a 'nonce' and incrementing it until the new descriptor no longer has
+ // a match with any existing descriptors.
identifier.nonce = 0;
std::string rawDescriptor = generateDescriptor(identifier);
- if (identifier.uniqueId.empty()) {
- // If it didn't have a unique id check for conflicts and enforce
- // uniqueness if necessary.
- while (getDeviceByDescriptorLocked(identifier.descriptor) != nullptr) {
- identifier.nonce++;
- rawDescriptor = generateDescriptor(identifier);
- }
+ // Enforce that the generated descriptor is unique.
+ while (hasDeviceWithDescriptorLocked(identifier.descriptor)) {
+ identifier.nonce++;
+ rawDescriptor = generateDescriptor(identifier);
}
ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.c_str(),
identifier.descriptor.c_str());
@@ -1422,13 +1427,22 @@
return vibrators;
}
-EventHub::Device* EventHub::getDeviceByDescriptorLocked(const std::string& descriptor) const {
- for (const auto& [id, device] : mDevices) {
+/**
+ * Checks both mDevices and mOpeningDevices for a device with the descriptor passed.
+ */
+bool EventHub::hasDeviceWithDescriptorLocked(const std::string& descriptor) const {
+ for (const auto& device : mOpeningDevices) {
if (descriptor == device->identifier.descriptor) {
- return device.get();
+ return true;
}
}
- return nullptr;
+
+ for (const auto& [id, device] : mDevices) {
+ if (descriptor == device->identifier.descriptor) {
+ return true;
+ }
+ }
+ return false;
}
EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 79901f0..11a2dbe 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -38,6 +38,26 @@
namespace android {
+/**
+ * Determines if the identifiers passed are a sub-devices. Sub-devices are physical devices
+ * that expose multiple input device paths such a keyboard that also has a touchpad input.
+ * These are separate devices with unique descriptors in EventHub, but InputReader should
+ * create a single InputDevice for them.
+ * Sub-devices are detected by the following criteria:
+ * 1. The vendor, product, bus, version, and unique id match
+ * 2. The location matches. The location is used to distinguish a single device with multiple
+ * inputs versus the same device plugged into multiple ports.
+ */
+
+static bool isSubDevice(const InputDeviceIdentifier& identifier1,
+ const InputDeviceIdentifier& identifier2) {
+ return (identifier1.vendor == identifier2.vendor &&
+ identifier1.product == identifier2.product && identifier1.bus == identifier2.bus &&
+ identifier1.version == identifier2.version &&
+ identifier1.uniqueId == identifier2.uniqueId &&
+ identifier1.location == identifier2.location);
+}
+
// --- InputReader ---
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
@@ -270,8 +290,9 @@
std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
int32_t eventHubId, const InputDeviceIdentifier& identifier) {
auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
- return devicePair.second->getDescriptor().size() && identifier.descriptor.size() &&
- devicePair.second->getDescriptor() == identifier.descriptor;
+ const InputDeviceIdentifier identifier2 =
+ devicePair.second->getDeviceInfo().getIdentifier();
+ return isSubDevice(identifier, identifier2);
});
std::shared_ptr<InputDevice> device;
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 79188aa..4733ecb 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -652,7 +652,6 @@
base::Result<void> readNotifyLocked() REQUIRES(mLock);
void handleNotifyEventLocked(const inotify_event&) REQUIRES(mLock);
- Device* getDeviceByDescriptorLocked(const std::string& descriptor) const REQUIRES(mLock);
Device* getDeviceLocked(int32_t deviceId) const REQUIRES(mLock);
Device* getDeviceByPathLocked(const std::string& devicePath) const REQUIRES(mLock);
/**
@@ -662,6 +661,9 @@
Device* getDeviceByFdLocked(int fd) const REQUIRES(mLock);
int32_t getNextControllerNumberLocked(const std::string& name) REQUIRES(mLock);
+
+ bool hasDeviceWithDescriptorLocked(const std::string& descriptor) const REQUIRES(mLock);
+
void releaseControllerNumberLocked(int32_t num) REQUIRES(mLock);
void reportDeviceAddedForStatisticsLocked(const InputDeviceIdentifier& identifier,
ftl::Flags<InputDeviceClass> classes) REQUIRES(mLock);
diff --git a/services/inputflinger/tests/EventHub_test.cpp b/services/inputflinger/tests/EventHub_test.cpp
index ef68a84..6ef6e44 100644
--- a/services/inputflinger/tests/EventHub_test.cpp
+++ b/services/inputflinger/tests/EventHub_test.cpp
@@ -180,6 +180,20 @@
}
/**
+ * Ensure that two identical devices get assigned unique descriptors from EventHub.
+ */
+TEST_F(EventHubTest, DevicesWithMatchingUniqueIdsAreUnique) {
+ std::unique_ptr<UinputHomeKey> keyboard2 = createUinputDevice<UinputHomeKey>();
+ int32_t deviceId2;
+ ASSERT_NO_FATAL_FAILURE(deviceId2 = waitForDeviceCreation());
+
+ ASSERT_NE(mEventHub->getDeviceIdentifier(mDeviceId).descriptor,
+ mEventHub->getDeviceIdentifier(deviceId2).descriptor);
+ keyboard2.reset();
+ waitForDeviceClose(deviceId2);
+}
+
+/**
* Ensure that input_events are generated with monotonic clock.
* That means input_event should receive a timestamp that is in the future of the time
* before the event was sent.
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 8680900..bff301e 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -136,10 +136,6 @@
mDeviceProductInfo = std::move(info);
}
-uint32_t DisplayDevice::getPageFlipCount() const {
- return mCompositionDisplay->getRenderSurface()->getPageFlipCount();
-}
-
auto DisplayDevice::getInputInfo() const -> InputInfo {
gui::DisplayInfo info;
info.displayId = getLayerStack().id;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 2161436..10fc095 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -259,7 +259,6 @@
/* ------------------------------------------------------------------------
* Debugging
*/
- uint32_t getPageFlipCount() const;
std::string getDebugName() const;
void dump(std::string& result) const;
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Time.h b/services/surfaceflinger/Scheduler/include/scheduler/Time.h
index 2b3ad2d..487709b 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/Time.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/Time.h
@@ -32,6 +32,7 @@
struct Duration;
struct TimePoint : scheduler::SchedulerClock::time_point {
+ constexpr TimePoint() = default;
explicit constexpr TimePoint(const Duration&);
// Implicit conversion from std::chrono counterpart.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1fcbdfa..8e19c35 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2247,7 +2247,6 @@
scheduleComposite(FrameHint::kNone);
}
- postFrame();
postComposition();
const bool prevFrameHadClientComposition = mHadClientComposition;
@@ -2363,7 +2362,7 @@
void SurfaceFlinger::postComposition() {
ATRACE_CALL();
- ALOGV("postComposition");
+ ALOGV(__func__);
const auto* display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()).get();
@@ -2378,18 +2377,19 @@
}
mPreviousPresentFences[1] = mPreviousPresentFences[0];
- mPreviousPresentFences[0].fence =
- display ? getHwComposer().getPresentFence(display->getPhysicalId()) : Fence::NO_FENCE;
- mPreviousPresentFences[0].fenceTime =
- std::make_shared<FenceTime>(mPreviousPresentFences[0].fence);
- nsecs_t now = systemTime();
+ auto presentFence =
+ display ? getHwComposer().getPresentFence(display->getPhysicalId()) : Fence::NO_FENCE;
+
+ auto presentFenceTime = std::make_shared<FenceTime>(presentFence);
+ mPreviousPresentFences[0] = {presentFence, presentFenceTime};
+
+ const TimePoint presentTime = scheduler::SchedulerClock::now();
// Set presentation information before calling Layer::releasePendingBuffer, such that jank
// information from previous' frame classification is already available when sending jank info
// to clients, so they get jank classification as early as possible.
- mFrameTimeline->setSfPresent(/* sfPresentTime */ now, mPreviousPresentFences[0].fenceTime,
- glCompositionDoneFenceTime);
+ mFrameTimeline->setSfPresent(presentTime.ns(), presentFenceTime, glCompositionDoneFenceTime);
// We use the CompositionEngine::getLastFrameRefreshTimestamp() which might
// be sampled a little later than when we started doing work for this frame,
@@ -2397,11 +2397,10 @@
const TimePoint compositeTime =
TimePoint::fromNs(mCompositionEngine->getLastFrameRefreshTimestamp());
const Duration presentLatency =
- mPresentLatencyTracker.trackPendingFrame(compositeTime,
- mPreviousPresentFences[0].fenceTime);
+ mPresentLatencyTracker.trackPendingFrame(compositeTime, presentFenceTime);
const auto& schedule = mScheduler->getVsyncSchedule();
- const TimePoint vsyncDeadline = schedule.vsyncDeadlineAfter(TimePoint::fromNs(now));
+ const TimePoint vsyncDeadline = schedule.vsyncDeadlineAfter(presentTime);
const Period vsyncPeriod = schedule.period();
const nsecs_t vsyncPhase = mVsyncConfiguration->getCurrentConfigs().late.sfOffset;
@@ -2409,9 +2408,9 @@
presentLatency.ns());
for (const auto& layer: mLayersWithQueuedFrames) {
- layer->onPostComposition(display, glCompositionDoneFenceTime,
- mPreviousPresentFences[0].fenceTime, compositorTiming);
- layer->releasePendingBuffer(/*dequeueReadyTime*/ now);
+ layer->onPostComposition(display, glCompositionDoneFenceTime, presentFenceTime,
+ compositorTiming);
+ layer->releasePendingBuffer(presentTime.ns());
}
std::vector<std::pair<std::shared_ptr<compositionengine::Display>, sp<HdrLayerInfoReporter>>>
@@ -2468,13 +2467,16 @@
mSomeDataspaceChanged = false;
mVisibleRegionsWereDirtyThisFrame = false;
- mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0].fence);
+ mTransactionCallbackInvoker.addPresentFence(std::move(presentFence));
mTransactionCallbackInvoker.sendCallbacks(false /* onCommitOnly */);
mTransactionCallbackInvoker.clearCompletedTransactions();
+ mTimeStats->incrementTotalFrames();
+ mTimeStats->setPresentFenceGlobal(presentFenceTime);
+
if (display && display->isInternal() && display->getPowerMode() == hal::PowerMode::ON &&
- mPreviousPresentFences[0].fenceTime->isValid()) {
- mScheduler->addPresentFence(mPreviousPresentFences[0].fenceTime);
+ presentFenceTime->isValid()) {
+ mScheduler->addPresentFence(std::move(presentFenceTime));
}
const bool isDisplayConnected =
@@ -2486,9 +2488,6 @@
}
}
- mTimeStats->incrementTotalFrames();
- mTimeStats->setPresentFenceGlobal(mPreviousPresentFences[0].fenceTime);
-
const size_t sfConnections = mScheduler->getEventThreadConnectionCount(mSfConnectionHandle);
const size_t appConnections = mScheduler->getEventThreadConnectionCount(mAppConnectionHandle);
mTimeStats->recordDisplayEventConnectionCount(sfConnections + appConnections);
@@ -2498,20 +2497,19 @@
return;
}
- nsecs_t currentTime = systemTime();
if (mHasPoweredOff) {
mHasPoweredOff = false;
} else {
- nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime;
- const size_t numPeriods = static_cast<size_t>(elapsedTime / vsyncPeriod.ns());
+ const Duration elapsedTime = presentTime - getBE().mLastPresentTime;
+ const size_t numPeriods = static_cast<size_t>(elapsedTime.ns() / vsyncPeriod.ns());
if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) {
- getBE().mFrameBuckets[numPeriods] += elapsedTime;
+ getBE().mFrameBuckets[numPeriods] += elapsedTime.ns();
} else {
- getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] += elapsedTime;
+ getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] += elapsedTime.ns();
}
- getBE().mTotalTime += elapsedTime;
+ getBE().mTotalTime += elapsedTime.ns();
}
- getBE().mLastSwapTime = currentTime;
+ getBE().mLastPresentTime = presentTime;
// Cleanup any outstanding resources due to rendering a prior frame.
getRenderEngine().cleanupPostRender();
@@ -2539,6 +2537,8 @@
// getTotalSize returns the total number of buffers that were allocated by SurfaceFlinger
ATRACE_INT64("Total Buffer Size", GraphicBufferAllocator::get().getTotalSize());
}
+
+ logFrameStats(presentTime);
}
FloatRect SurfaceFlinger::getMaxDisplayBounds() {
@@ -2571,16 +2571,6 @@
}
}
-void SurfaceFlinger::postFrame() {
- const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
- if (display && getHwComposer().isConnected(display->getPhysicalId())) {
- uint32_t flipCount = display->getPageFlipCount();
- if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
- logFrameStats();
- }
- }
-}
-
void SurfaceFlinger::commitTransactions() {
ATRACE_CALL();
@@ -4956,7 +4946,14 @@
mFrameTimeline->parseArgs(args, result);
}
-void SurfaceFlinger::logFrameStats() {
+void SurfaceFlinger::logFrameStats(TimePoint now) {
+ using namespace std::chrono_literals;
+
+ static TimePoint sTimestamp = now;
+ if (now - sTimestamp < 30min) return;
+ sTimestamp = now;
+
+ ATRACE_CALL();
mDrawingState.traverse([&](Layer* layer) { layer->logFrameStats(); });
}
@@ -5560,15 +5557,8 @@
reply->writeInt32(0);
reply->writeInt32(mDebugDisableHWC);
return NO_ERROR;
- case 1013: {
- const auto display = getDefaultDisplayDevice();
- if (!display) {
- return NAME_NOT_FOUND;
- }
-
- reply->writeInt32(display->getPageFlipCount());
- return NO_ERROR;
- }
+ case 1013: // Unused.
+ return NAME_NOT_FOUND;
case 1014: {
Mutex::Autolock _l(mStateLock);
// daltonize
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 7609241..8fddb70 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -56,6 +56,7 @@
#include <compositionengine/OutputColorSetting.h>
#include <scheduler/Fps.h>
#include <scheduler/PresentLatencyTracker.h>
+#include <scheduler/Time.h>
#include "ClientCache.h"
#include "DisplayDevice.h"
@@ -174,7 +175,7 @@
static const size_t NUM_BUCKETS = 8; // < 1-7, 7+
nsecs_t mFrameBuckets[NUM_BUCKETS] = {};
nsecs_t mTotalTime = 0;
- std::atomic<nsecs_t> mLastSwapTime = 0;
+ TimePoint mLastPresentTime;
};
class SurfaceFlinger : public BnSurfaceComposer,
@@ -197,29 +198,6 @@
static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; }
- // This is the phase offset in nanoseconds of the software vsync event
- // relative to the vsync event reported by HWComposer. The software vsync
- // event is when SurfaceFlinger and Choreographer-based applications run each
- // frame.
- //
- // This phase offset allows adjustment of the minimum latency from application
- // wake-up time (by Choreographer) to the time at which the resulting window
- // image is displayed. This value may be either positive (after the HW vsync)
- // or negative (before the HW vsync). Setting it to 0 will result in a lower
- // latency bound of two vsync periods because the app and SurfaceFlinger
- // will run just after the HW vsync. Setting it to a positive number will
- // result in the minimum latency being:
- //
- // (2 * VSYNC_PERIOD - (vsyncPhaseOffsetNs % VSYNC_PERIOD))
- //
- // Note that reducing this latency makes it more likely for the applications
- // to not have their window content image ready in time. When this happens
- // the latency will end up being an additional vsync period, and animations
- // will hiccup. Therefore, this latency should be tuned somewhat
- // conservatively (or at least with awareness of the trade-off being made).
- static int64_t vsyncPhaseOffsetNs;
- static int64_t sfVsyncPhaseOffsetNs;
-
// If fences from sync Framework are supported.
static bool hasSyncFramework;
@@ -386,10 +364,6 @@
using DumpArgs = Vector<String16>;
using Dumper = std::function<void(const DumpArgs&, bool asProto, std::string&)>;
- // This value is specified in number of frames. Log frame stats at most
- // every half hour.
- enum { LOG_FRAME_STATS_PERIOD = 30*60*60 };
-
class State {
public:
explicit State(LayerVector::StateSet set) : stateSet(set), layersSortedByZ(set) {}
@@ -938,7 +912,6 @@
* Compositing
*/
void postComposition() REQUIRES(kMainThreadContext);
- void postFrame() REQUIRES(kMainThreadContext);
/*
* Display management
@@ -1038,7 +1011,7 @@
void clearStatsLocked(const DumpArgs& args, std::string& result);
void dumpTimeStats(const DumpArgs& args, bool asProto, std::string& result) const;
void dumpFrameTimeline(const DumpArgs& args, std::string& result) const;
- void logFrameStats() REQUIRES(kMainThreadContext);
+ void logFrameStats(TimePoint now) REQUIRES(kMainThreadContext);
void dumpVSync(std::string& result) const REQUIRES(mStateLock);
void dumpStaticScreenStats(std::string& result) const;
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
index d2c2e29..e5de759 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.cpp
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -178,8 +178,8 @@
return NO_ERROR;
}
-void TransactionCallbackInvoker::addPresentFence(const sp<Fence>& presentFence) {
- mPresentFence = presentFence;
+void TransactionCallbackInvoker::addPresentFence(sp<Fence> presentFence) {
+ mPresentFence = std::move(presentFence);
}
void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) {
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h
index 81d79f0..59abe33 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -70,7 +70,7 @@
status_t registerUnpresentedCallbackHandle(const sp<CallbackHandle>& handle);
void addEmptyTransaction(const ListenerCallbacks& listenerCallbacks);
- void addPresentFence(const sp<Fence>& presentFence);
+ void addPresentFence(sp<Fence>);
void sendCallbacks(bool onCommitOnly);
void clearCompletedTransactions() {
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index c592358..86b7a7a 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -425,7 +425,8 @@
mFlinger->clearStatsLocked(dumpArgs, result);
mFlinger->dumpTimeStats(dumpArgs, fdp->ConsumeBool(), result);
- FTL_FAKE_GUARD(kMainThreadContext, mFlinger->logFrameStats());
+ FTL_FAKE_GUARD(kMainThreadContext,
+ mFlinger->logFrameStats(TimePoint::fromNs(fdp->ConsumeIntegral<nsecs_t>())));
result = fdp->ConsumeRandomLengthString().c_str();
mFlinger->dumpFrameTimeline(dumpArgs, result);
@@ -612,7 +613,6 @@
mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mFdp.ConsumeIntegral<uid_t>());
FTL_FAKE_GUARD(kMainThreadContext, mFlinger->postComposition());
- FTL_FAKE_GUARD(kMainThreadContext, mFlinger->postFrame());
mFlinger->calculateExpectedPresentTime({});