Merge "Remove __ANDROID_API__ #if checks." into sc-dev
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 65fc46e..4dfd1d0 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1130,23 +1130,6 @@
return true;
}
-// Updates the access times of out_oat_path based on those from apk_path.
-void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
- struct stat input_stat;
- memset(&input_stat, 0, sizeof(input_stat));
- if (stat(apk_path, &input_stat) != 0) {
- PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
- return;
- }
-
- struct utimbuf ut;
- ut.actime = input_stat.st_atime;
- ut.modtime = input_stat.st_mtime;
- if (utime(out_oat_path, &ut) != 0) {
- PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
- }
-}
-
// Runs (execv) dexoptanalyzer on the given arguments.
// The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
// If this is for a profile guided compilation, profile_was_updated will tell whether or not
@@ -1843,8 +1826,6 @@
}
}
- update_out_oat_access_times(dex_path, out_oat.path().c_str());
-
// We've been successful, don't delete output.
out_oat.DisableCleanup();
out_vdex.DisableCleanup();
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index c6f656b..79aab82 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -50,11 +50,10 @@
CornerRadiusChange corner_radius = 16;
ReparentChange reparent = 17;
RelativeParentChange relative_parent = 18;
- DetachChildrenChange detach_children = 19;
- ReparentChildrenChange reparent_children = 20;
- BackgroundBlurRadiusChange background_blur_radius = 21;
- ShadowRadiusChange shadow_radius = 22;
- BlurRegionsChange blur_regions = 23;
+ ReparentChildrenChange reparent_children = 19;
+ BackgroundBlurRadiusChange background_blur_radius = 20;
+ ShadowRadiusChange shadow_radius = 21;
+ BlurRegionsChange blur_regions = 22;
}
}
@@ -200,10 +199,6 @@
required int32 z = 2;
}
-message DetachChildrenChange {
- required bool detach_children = 1;
-}
-
message ShadowRadiusChange {
required float radius = 1;
}
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 5849212..58d6582 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -417,9 +417,6 @@
case SurfaceChange::SurfaceChangeCase::kRelativeParent:
setRelativeParentChange(transaction, change.id(), change.relative_parent());
break;
- case SurfaceChange::SurfaceChangeCase::kDetachChildren:
- setDetachChildrenChange(transaction, change.id(), change.detach_children());
- break;
case SurfaceChange::SurfaceChangeCase::kShadowRadius:
setShadowRadiusChange(transaction, change.id(), change.shadow_radius());
break;
@@ -713,11 +710,6 @@
t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()], c.z());
}
-void Replayer::setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
- layer_id id, const DetachChildrenChange& c) {
- t.detachChildren(mLayers[id]);
-}
-
void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
layer_id id, const ReparentChildrenChange& c) {
if (mLayers.count(c.parent_id()) == 0 || mLayers[c.parent_id()] == nullptr) {
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index a22262a..324d591 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -116,8 +116,6 @@
layer_id id, const ReparentChange& c);
void setRelativeParentChange(SurfaceComposerClient::Transaction& t,
layer_id id, const RelativeParentChange& c);
- void setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
- layer_id id, const DetachChildrenChange& c);
void setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
layer_id id, const ReparentChildrenChange& c);
void setShadowRadiusChange(SurfaceComposerClient::Transaction& t,
diff --git a/data/etc/android.hardware.keystore.limited_use_key.xml b/data/etc/android.hardware.keystore.limited_use_key.xml
new file mode 100644
index 0000000..5217086
--- /dev/null
+++ b/data/etc/android.hardware.keystore.limited_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Feature for devices with KeyMint that can enforce limited use key
+ in hardware with any max usage count (including count equals to 1). -->
+<permissions>
+ <feature name="android.hardware.keystore.limited_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/android.hardware.keystore.single_use_key.xml b/data/etc/android.hardware.keystore.single_use_key.xml
new file mode 100644
index 0000000..40e80aa
--- /dev/null
+++ b/data/etc/android.hardware.keystore.single_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Feature for devices with KeyMint that only can enforce limited use key
+ in hardware with max usage count equals to 1. -->
+<permissions>
+ <feature name="android.hardware.keystore.single_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index cc0ee82..adfd6e2 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -47,6 +47,12 @@
<feature name="android.software.secure_lock_screen" />
<feature name="android.software.input_methods" />
+
+ <!-- Feature to support device admins -->
+ <!-- TODO(b/178412797): not fully supported yet, CTS tests are still
+ failing. -->
+ <feature name="android.software.device_admin" />
+
<!-- devices with GPS must include android.hardware.location.gps.xml -->
<!-- devices with an autofocus camera and/or flash must include either
android.hardware.camera.autofocus.xml or
diff --git a/include/android/input.h b/include/android/input.h
index b5d399e..b70d424 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -856,8 +856,10 @@
AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
/** joystick */
AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+ /** HDMI */
+ AINPUT_SOURCE_HDMI = 0x02000000 | AINPUT_SOURCE_CLASS_BUTTON,
/** sensor */
- AINPUT_SOURCE_SENSOR = 0x02000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+ AINPUT_SOURCE_SENSOR = 0x04000000 | AINPUT_SOURCE_UNKNOWN,
/** rotary encoder */
AINPUT_SOURCE_ROTARY_ENCODER = 0x00400000 | AINPUT_SOURCE_CLASS_NONE,
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 23692e9..2bd7bd2 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -213,6 +213,9 @@
inline void setVibrator(bool hasVibrator) { mHasVibrator = hasVibrator; }
inline bool hasVibrator() const { return mHasVibrator; }
+ inline void setHasBattery(bool hasBattery) { mHasBattery = hasBattery; }
+ inline bool hasBattery() const { return mHasBattery; }
+
inline void setButtonUnderPad(bool hasButton) { mHasButtonUnderPad = hasButton; }
inline bool hasButtonUnderPad() const { return mHasButtonUnderPad; }
@@ -239,6 +242,7 @@
int32_t mKeyboardType;
std::shared_ptr<KeyCharacterMap> mKeyCharacterMap;
bool mHasVibrator;
+ bool mHasBattery;
bool mHasButtonUnderPad;
bool mHasSensor;
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 454fbd0..3c90681 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -597,13 +597,6 @@
return STATUS_INVALID_OPERATION;
}
- if (!binder->isRemote()) {
- LOG(WARNING) << "A binder object at " << binder
- << " is being transacted on, however, this object is in the same process as "
- "its proxy. Transacting with this binder is expensive compared to just "
- "calling the corresponding functionality in the same process.";
- }
-
*in = new AParcel(binder);
status_t status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
binder_status_t ret = PruneStatusT(status);
diff --git a/libs/binder/rust/tests/serialization.rs b/libs/binder/rust/tests/serialization.rs
index 2ae13f4..2bf3d03 100644
--- a/libs/binder/rust/tests/serialization.rs
+++ b/libs/binder/rust/tests/serialization.rs
@@ -25,7 +25,6 @@
use binder::parcel::ParcelFileDescriptor;
use std::ffi::{c_void, CStr, CString};
-use std::panic::{self, AssertUnwindSafe};
use std::sync::Once;
#[allow(
@@ -73,22 +72,9 @@
impl ReadParcelTest for () {}
-fn on_transact(
- _service: &dyn ReadParcelTest,
- code: TransactionCode,
- parcel: &Parcel,
- reply: &mut Parcel,
-) -> Result<()> {
- panic::catch_unwind(AssertUnwindSafe(|| transact_inner(code, parcel, reply))).unwrap_or_else(
- |e| {
- eprintln!("Failure in Rust: {:?}", e.downcast_ref::<String>());
- Err(StatusCode::FAILED_TRANSACTION)
- },
- )
-}
-
#[allow(clippy::float_cmp)]
-fn transact_inner(code: TransactionCode, parcel: &Parcel, reply: &mut Parcel) -> Result<()> {
+fn on_transact(_service: &dyn ReadParcelTest, code: TransactionCode,
+ parcel: &Parcel, reply: &mut Parcel) -> Result<()> {
match code {
bindings::Transaction_TEST_BOOL => {
assert_eq!(parcel.read::<bool>()?, true);
@@ -296,7 +282,7 @@
))?;
}
bindings::Transaction_TEST_FAIL => {
- panic!("Testing expected failure");
+ return Err(StatusCode::FAILED_TRANSACTION)
}
_ => return Err(StatusCode::UNKNOWN_TRANSACTION),
}
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 462f0db..7e9bb7d 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -155,10 +155,14 @@
return true;
}
-static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+static int retrieveProgramFd(const std::string &eventType, const std::string &eventName) {
std::string path = StringPrintf(BPF_FS_PATH "prog_time_in_state_tracepoint_%s_%s",
eventType.c_str(), eventName.c_str());
- int prog_fd = retrieveProgram(path.c_str());
+ return retrieveProgram(path.c_str());
+}
+
+static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+ int prog_fd = retrieveProgramFd(eventType, eventName);
if (prog_fd < 0) return false;
return bpf_attach_tracepoint(prog_fd, eventType.c_str(), eventName.c_str()) >= 0;
}
@@ -174,6 +178,17 @@
return {};
}
+// Check if tracking is expected to work without activating it.
+bool isTrackingUidTimesSupported() {
+ auto freqs = getCpuFreqs();
+ if (!freqs || freqs->empty()) return false;
+ if (gTracking) return true;
+ if (retrieveProgramFd("sched", "sched_switch") < 0) return false;
+ if (retrieveProgramFd("power", "cpu_frequency") < 0) return false;
+ if (retrieveProgramFd("sched", "sched_process_free") < 0) return false;
+ return true;
+}
+
// Start tracking and aggregating data to be reported by getUidCpuFreqTimes and getUidsCpuFreqTimes.
// Returns true on success, false otherwise.
// Tracking is active only once a live process has successfully called this function; if the calling
diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h
index 46de669..4145374 100644
--- a/libs/cputimeinstate/cputimeinstate.h
+++ b/libs/cputimeinstate/cputimeinstate.h
@@ -22,6 +22,7 @@
namespace android {
namespace bpf {
+bool isTrackingUidTimesSupported();
bool startTrackingUidTimes();
std::optional<std::vector<std::vector<uint64_t>>> getTotalCpuFreqTimes();
std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid);
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index d25b2e9..2112b10 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -40,6 +40,11 @@
using std::vector;
+TEST(TimeInStateTest, IsTrackingSupported) {
+ isTrackingUidTimesSupported();
+ SUCCEED();
+}
+
TEST(TimeInStateTest, TotalTimeInState) {
auto times = getTotalCpuFreqTimes();
ASSERT_TRUE(times.has_value());
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 143fa13..8a82c2a 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -53,7 +53,6 @@
/* list of hal interface to dump containing process during native dumps */
static const char* hal_interfaces_to_dump[] {
- "android.hardware.audio@2.0::IDevicesFactory",
"android.hardware.audio@4.0::IDevicesFactory",
"android.hardware.audio@5.0::IDevicesFactory",
"android.hardware.audio@6.0::IDevicesFactory",
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 38ae353..fa5044c 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -49,6 +49,7 @@
srcs: [
":framework_native_aidl",
+ ":inputconstants_aidl",
":libgui_aidl",
":libgui_bufferqueue_sources",
@@ -62,6 +63,7 @@
"DebugEGLImageTracker.cpp",
"DisplayEventDispatcher.cpp",
"DisplayEventReceiver.cpp",
+ "FrameTimelineInfo.cpp",
"GLConsumer.cpp",
"IConsumerListener.cpp",
"IDisplayEventConnection.cpp",
@@ -154,6 +156,7 @@
defaults: ["libgui_bufferqueue-defaults"],
srcs: [
+ ":inputconstants_aidl",
":libgui_aidl",
":libgui_bufferqueue_sources",
],
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 42d2895..c62d9ad 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -370,9 +370,9 @@
}
t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber);
- if (!mNextFrameTimelineVsyncIdQueue.empty()) {
- t->setFrameTimelineVsync(mSurfaceControl, mNextFrameTimelineVsyncIdQueue.front());
- mNextFrameTimelineVsyncIdQueue.pop();
+ if (!mNextFrameTimelineInfoQueue.empty()) {
+ t->setFrameTimelineInfo(mSurfaceControl, mNextFrameTimelineInfoQueue.front());
+ mNextFrameTimelineInfoQueue.pop();
}
if (mAutoRefresh != bufferItem.mAutoRefresh) {
@@ -534,8 +534,8 @@
return mBbq->setFrameRate(frameRate, compatibility, shouldBeSeamless);
}
- status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId) override {
- return mBbq->setFrameTimelineVsync(frameTimelineVsyncId);
+ status_t setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) override {
+ return mBbq->setFrameTimelineInfo(frameTimelineInfo);
}
};
@@ -549,9 +549,9 @@
return t.setFrameRate(mSurfaceControl, frameRate, compatibility, shouldBeSeamless).apply();
}
-status_t BLASTBufferQueue::setFrameTimelineVsync(int64_t frameTimelineVsyncId) {
+status_t BLASTBufferQueue::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) {
std::unique_lock _lock{mMutex};
- mNextFrameTimelineVsyncIdQueue.push(frameTimelineVsyncId);
+ mNextFrameTimelineInfoQueue.push(frameTimelineInfo);
return OK;
}
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index c6c9a8f..2ad484a 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -36,7 +36,9 @@
DisplayEventDispatcher::DisplayEventDispatcher(
const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource,
ISurfaceComposer::EventRegistrationFlags eventRegistration)
- : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false) {
+ : mLooper(looper),
+ mReceiver(vsyncSource, eventRegistration),
+ mVsyncState(VsyncState::Unregistered) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
@@ -66,26 +68,37 @@
}
status_t DisplayEventDispatcher::scheduleVsync() {
- if (!mWaitingForVsync) {
- ALOGV("dispatcher %p ~ Scheduling vsync.", this);
+ switch (mVsyncState) {
+ case VsyncState::Unregistered: {
+ ALOGV("dispatcher %p ~ Scheduling vsync.", this);
- // Drain all pending events.
- nsecs_t vsyncTimestamp;
- PhysicalDisplayId vsyncDisplayId;
- uint32_t vsyncCount;
- VsyncEventData vsyncEventData;
- if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
- ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this,
- ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
+ // Drain all pending events.
+ nsecs_t vsyncTimestamp;
+ PhysicalDisplayId vsyncDisplayId;
+ uint32_t vsyncCount;
+ VsyncEventData vsyncEventData;
+ if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount,
+ &vsyncEventData)) {
+ ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "",
+ this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
+ }
+
+ status_t status = mReceiver.setVsyncRate(1);
+ if (status) {
+ ALOGW("Failed to set vsync rate, status=%d", status);
+ return status;
+ }
+
+ mVsyncState = VsyncState::RegisteredAndWaitingForVsync;
+ break;
}
-
- status_t status = mReceiver.requestNextVsync();
- if (status) {
- ALOGW("Failed to request next vsync, status=%d", status);
- return status;
+ case VsyncState::Registered: {
+ mVsyncState = VsyncState::RegisteredAndWaitingForVsync;
+ break;
}
-
- mWaitingForVsync = true;
+ case VsyncState::RegisteredAndWaitingForVsync: {
+ break;
+ }
}
return OK;
}
@@ -123,8 +136,23 @@
", displayId=%s, count=%d, vsyncId=%" PRId64,
this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount,
vsyncEventData.id);
- mWaitingForVsync = false;
- dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
+ switch (mVsyncState) {
+ case VsyncState::Unregistered:
+ ALOGW("Received unexpected VSYNC event");
+ break;
+ case VsyncState::RegisteredAndWaitingForVsync:
+ mVsyncState = VsyncState::Registered;
+ dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
+ break;
+ case VsyncState::Registered:
+ status_t status = mReceiver.setVsyncRate(0);
+ if (status) {
+ ALOGW("Failed to reset vsync rate, status=%d", status);
+ return status;
+ }
+ mVsyncState = VsyncState::Unregistered;
+ break;
+ }
}
return 1; // keep the callback
diff --git a/libs/gui/FrameTimelineInfo.cpp b/libs/gui/FrameTimelineInfo.cpp
new file mode 100644
index 0000000..f400774
--- /dev/null
+++ b/libs/gui/FrameTimelineInfo.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "FrameTimelineInfo"
+
+#include <inttypes.h>
+
+#include <android/os/IInputConstants.h>
+#include <gui/FrameTimelineInfo.h>
+#include <gui/LayerState.h>
+#include <utils/Errors.h>
+
+#include <cmath>
+
+using android::os::IInputConstants;
+
+namespace android {
+
+status_t FrameTimelineInfo::write(Parcel& output) const {
+ SAFE_PARCEL(output.writeInt64, vsyncId);
+ SAFE_PARCEL(output.writeInt32, inputEventId);
+ return NO_ERROR;
+}
+
+status_t FrameTimelineInfo::read(const Parcel& input) {
+ SAFE_PARCEL(input.readInt64, &vsyncId);
+ SAFE_PARCEL(input.readInt32, &inputEventId);
+ return NO_ERROR;
+}
+
+void FrameTimelineInfo::merge(const FrameTimelineInfo& other) {
+ // When merging vsync Ids we take the oldest valid one
+ if (vsyncId != INVALID_VSYNC_ID && other.vsyncId != INVALID_VSYNC_ID) {
+ if (other.vsyncId > vsyncId) {
+ vsyncId = other.vsyncId;
+ inputEventId = other.inputEventId;
+ }
+ } else if (vsyncId == INVALID_VSYNC_ID) {
+ vsyncId = other.vsyncId;
+ inputEventId = other.inputEventId;
+ }
+}
+
+void FrameTimelineInfo::clear() {
+ vsyncId = INVALID_VSYNC_ID;
+ inputEventId = IInputConstants::INVALID_INPUT_EVENT_ID;
+}
+
+}; // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a8d6832..f68f3e1 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -68,16 +68,19 @@
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}
- virtual status_t setTransactionState(
- int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
- const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
- const InputWindowCommands& commands, int64_t desiredPresentTime, bool isAutoTimestamp,
- const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
- const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
+ status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+ const Vector<ComposerState>& state,
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const sp<IBinder>& applyToken, const InputWindowCommands& commands,
+ int64_t desiredPresentTime, bool isAutoTimestamp,
+ const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks,
+ uint64_t transactionId) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeInt64, frameTimelineVsyncId);
+ SAFE_PARCEL(frameTimelineInfo.write, data);
+
SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(state.size()));
for (const auto& s : state) {
SAFE_PARCEL(s.write, data);
@@ -108,15 +111,14 @@
return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
}
- virtual void bootFinished()
- {
+ void bootFinished() override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
}
- virtual status_t captureDisplay(const DisplayCaptureArgs& args,
- const sp<IScreenCaptureListener>& captureListener) {
+ status_t captureDisplay(const DisplayCaptureArgs& args,
+ const sp<IScreenCaptureListener>& captureListener) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
SAFE_PARCEL(args.write, data);
@@ -125,8 +127,8 @@
return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply);
}
- virtual status_t captureDisplay(uint64_t displayOrLayerStack,
- const sp<IScreenCaptureListener>& captureListener) {
+ status_t captureDisplay(uint64_t displayOrLayerStack,
+ const sp<IScreenCaptureListener>& captureListener) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
SAFE_PARCEL(data.writeUint64, displayOrLayerStack);
@@ -135,8 +137,8 @@
return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply);
}
- virtual status_t captureLayers(const LayerCaptureArgs& args,
- const sp<IScreenCaptureListener>& captureListener) {
+ status_t captureLayers(const LayerCaptureArgs& args,
+ const sp<IScreenCaptureListener>& captureListener) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
SAFE_PARCEL(args.write, data);
@@ -145,9 +147,8 @@
return remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
}
- virtual bool authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& bufferProducer) const
- {
+ bool authenticateSurfaceTexture(
+ const sp<IGraphicBufferProducer>& bufferProducer) const override {
Parcel data, reply;
int err = NO_ERROR;
err = data.writeInterfaceToken(
@@ -180,8 +181,7 @@
return result != 0;
}
- virtual status_t getSupportedFrameTimestamps(
- std::vector<FrameEvent>* outSupported) const {
+ status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override {
if (!outSupported) {
return UNEXPECTED_NULL;
}
@@ -224,8 +224,8 @@
return NO_ERROR;
}
- virtual sp<IDisplayEventConnection> createDisplayEventConnection(
- VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) {
+ sp<IDisplayEventConnection> createDisplayEventConnection(
+ VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) override {
Parcel data, reply;
sp<IDisplayEventConnection> result;
int err = data.writeInterfaceToken(
@@ -247,8 +247,7 @@
return result;
}
- virtual sp<IBinder> createDisplay(const String8& displayName, bool secure)
- {
+ sp<IBinder> createDisplay(const String8& displayName, bool secure) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t status = data.writeString8(displayName);
@@ -272,15 +271,14 @@
return display;
}
- virtual void destroyDisplay(const sp<IBinder>& display)
- {
+ void destroyDisplay(const sp<IBinder>& display) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
remote()->transact(BnSurfaceComposer::DESTROY_DISPLAY, data, &reply);
}
- virtual std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const {
+ std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (remote()->transact(BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS, data, &reply) ==
@@ -297,7 +295,7 @@
return {};
}
- virtual sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const {
+ sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeUint64(displayId.value);
@@ -305,8 +303,7 @@
return reply.readStrongBinder();
}
- virtual void setPowerMode(const sp<IBinder>& display, int mode)
- {
+ void setPowerMode(const sp<IBinder>& display, int mode) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -314,7 +311,7 @@
remote()->transact(BnSurfaceComposer::SET_POWER_MODE, data, &reply);
}
- virtual status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState* state) {
+ status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState* state) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -326,7 +323,7 @@
return result;
}
- virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
+ status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -336,7 +333,8 @@
return reply.read(*info);
}
- virtual status_t getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayConfig>* configs) {
+ status_t getDisplayConfigs(const sp<IBinder>& display,
+ Vector<DisplayConfig>* configs) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -354,9 +352,7 @@
return result;
}
- virtual status_t getDisplayStats(const sp<IBinder>& display,
- DisplayStatInfo* stats)
- {
+ status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -370,8 +366,7 @@
return result;
}
- virtual int getActiveConfig(const sp<IBinder>& display)
- {
+ int getActiveConfig(const sp<IBinder>& display) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -379,8 +374,8 @@
return reply.readInt32();
}
- virtual status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<ColorMode>* outColorModes) {
+ status_t getDisplayColorModes(const sp<IBinder>& display,
+ Vector<ColorMode>* outColorModes) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -409,8 +404,8 @@
return result;
}
- virtual status_t getDisplayNativePrimaries(const sp<IBinder>& display,
- ui::DisplayPrimaries& primaries) {
+ status_t getDisplayNativePrimaries(const sp<IBinder>& display,
+ ui::DisplayPrimaries& primaries) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -435,7 +430,7 @@
return result;
}
- virtual ColorMode getActiveColorMode(const sp<IBinder>& display) {
+ ColorMode getActiveColorMode(const sp<IBinder>& display) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -455,8 +450,7 @@
return static_cast<ColorMode>(reply.readInt32());
}
- virtual status_t setActiveColorMode(const sp<IBinder>& display,
- ColorMode colorMode) {
+ status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -481,8 +475,8 @@
return static_cast<status_t>(reply.readInt32());
}
- virtual status_t getAutoLowLatencyModeSupport(const sp<IBinder>& display,
- bool* outSupport) const {
+ status_t getAutoLowLatencyModeSupport(const sp<IBinder>& display,
+ bool* outSupport) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t result = data.writeStrongBinder(display);
@@ -499,7 +493,7 @@
return reply.readBool(outSupport);
}
- virtual void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) {
+ void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -524,7 +518,8 @@
}
}
- virtual status_t getGameContentTypeSupport(const sp<IBinder>& display, bool* outSupport) const {
+ status_t getGameContentTypeSupport(const sp<IBinder>& display,
+ bool* outSupport) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t result = data.writeStrongBinder(display);
@@ -540,7 +535,7 @@
return reply.readBool(outSupport);
}
- virtual void setGameContentType(const sp<IBinder>& display, bool on) {
+ void setGameContentType(const sp<IBinder>& display, bool on) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -563,7 +558,7 @@
}
}
- virtual status_t clearAnimationFrameStats() {
+ status_t clearAnimationFrameStats() override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -578,7 +573,7 @@
return reply.readInt32();
}
- virtual status_t getAnimationFrameStats(FrameStats* outStats) const {
+ status_t getAnimationFrameStats(FrameStats* outStats) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::GET_ANIMATION_FRAME_STATS, data, &reply);
@@ -586,8 +581,8 @@
return reply.readInt32();
}
- virtual status_t getHdrCapabilities(const sp<IBinder>& display,
- HdrCapabilities* outCapabilities) const {
+ status_t getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t result = data.writeStrongBinder(display);
@@ -608,7 +603,7 @@
return result;
}
- virtual status_t enableVSyncInjections(bool enable) {
+ status_t enableVSyncInjections(bool enable) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -629,7 +624,7 @@
return result;
}
- virtual status_t injectVSync(nsecs_t when) {
+ status_t injectVSync(nsecs_t when) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -650,7 +645,7 @@
return result;
}
- virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) {
+ status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) override {
if (!outLayers) {
return UNEXPECTED_NULL;
}
@@ -680,10 +675,10 @@
return reply.readParcelableVector(outLayers);
}
- virtual status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
- ui::PixelFormat* defaultPixelFormat,
- ui::Dataspace* wideColorGamutDataspace,
- ui::PixelFormat* wideColorGamutPixelFormat) const {
+ status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
+ ui::PixelFormat* defaultPixelFormat,
+ ui::Dataspace* wideColorGamutDataspace,
+ ui::PixelFormat* wideColorGamutPixelFormat) const override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -703,7 +698,7 @@
return error;
}
- virtual status_t getColorManagement(bool* outGetColorManagement) const {
+ status_t getColorManagement(bool* outGetColorManagement) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::GET_COLOR_MANAGEMENT, data, &reply);
@@ -715,10 +710,10 @@
return err;
}
- virtual status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
- ui::PixelFormat* outFormat,
- ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const {
+ status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
+ ui::PixelFormat* outFormat,
+ ui::Dataspace* outDataspace,
+ uint8_t* outComponentMask) const override {
if (!outFormat || !outDataspace || !outComponentMask) return BAD_VALUE;
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -752,8 +747,8 @@
return error;
}
- virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
- uint8_t componentMask, uint64_t maxFrames) {
+ status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+ uint8_t componentMask, uint64_t maxFrames) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -766,9 +761,9 @@
return result;
}
- virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
- uint64_t timestamp,
- DisplayedFrameStats* outStats) const {
+ status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
+ uint64_t timestamp,
+ DisplayedFrameStats* outStats) const override {
if (!outStats) return BAD_VALUE;
Parcel data, reply;
@@ -805,7 +800,7 @@
return result;
}
- virtual status_t getProtectedContentSupport(bool* outSupported) const {
+ status_t getProtectedContentSupport(bool* outSupported) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t error =
@@ -817,8 +812,8 @@
return error;
}
- virtual status_t isWideColorDisplay(const sp<IBinder>& token,
- bool* outIsWideColorDisplay) const {
+ status_t isWideColorDisplay(const sp<IBinder>& token,
+ bool* outIsWideColorDisplay) const override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -837,9 +832,8 @@
return error;
}
- virtual status_t addRegionSamplingListener(const Rect& samplingArea,
- const sp<IBinder>& stopLayerHandle,
- const sp<IRegionSamplingListener>& listener) {
+ status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
+ const sp<IRegionSamplingListener>& listener) override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -868,7 +862,7 @@
return error;
}
- virtual status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) {
+ status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -888,12 +882,11 @@
return error;
}
- virtual status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t defaultConfig, bool allowGroupSwitching,
- float primaryRefreshRateMin,
- float primaryRefreshRateMax,
- float appRequestRefreshRateMin,
- float appRequestRefreshRateMax) {
+ status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t defaultConfig,
+ bool allowGroupSwitching, float primaryRefreshRateMin,
+ float primaryRefreshRateMax,
+ float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -947,13 +940,12 @@
return reply.readInt32();
}
- virtual status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t* outDefaultConfig,
- bool* outAllowGroupSwitching,
- float* outPrimaryRefreshRateMin,
- float* outPrimaryRefreshRateMax,
- float* outAppRequestRefreshRateMin,
- float* outAppRequestRefreshRateMax) {
+ status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
+ int32_t* outDefaultConfig, bool* outAllowGroupSwitching,
+ float* outPrimaryRefreshRateMin,
+ float* outPrimaryRefreshRateMax,
+ float* outAppRequestRefreshRateMin,
+ float* outAppRequestRefreshRateMax) override {
if (!outDefaultConfig || !outAllowGroupSwitching || !outPrimaryRefreshRateMin ||
!outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin ||
!outAppRequestRefreshRateMax) {
@@ -1011,8 +1003,8 @@
return reply.readInt32();
}
- virtual status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
- bool* outSupport) const {
+ status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
+ bool* outSupport) const override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -1039,7 +1031,7 @@
return NO_ERROR;
}
- virtual status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) {
+ status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -1064,7 +1056,7 @@
return NO_ERROR;
}
- virtual status_t notifyPowerBoost(int32_t boostId) {
+ status_t notifyPowerBoost(int32_t boostId) override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -1085,8 +1077,8 @@
return NO_ERROR;
}
- virtual status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
- float lightPosY, float lightPosZ, float lightRadius) {
+ status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
+ float lightPosY, float lightPosZ, float lightRadius) override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -1114,8 +1106,8 @@
return NO_ERROR;
}
- virtual status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
- int8_t compatibility, bool shouldBeSeamless) {
+ status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
+ int8_t compatibility, bool shouldBeSeamless) override {
Parcel data, reply;
status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (err != NO_ERROR) {
@@ -1156,7 +1148,7 @@
return reply.readInt32();
}
- virtual status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) {
+ status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) override {
if (!outToken) return BAD_VALUE;
Parcel data, reply;
@@ -1191,40 +1183,34 @@
return NO_ERROR;
}
- virtual status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
- int64_t frameTimelineVsyncId) {
+ status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
+ const FrameTimelineInfo& frameTimelineInfo) override {
Parcel data, reply;
status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (err != NO_ERROR) {
- ALOGE("setFrameTimelineVsync: failed writing interface token: %s (%d)", strerror(-err),
- -err);
+ ALOGE("%s: failed writing interface token: %s (%d)", __func__, strerror(-err), -err);
return err;
}
err = data.writeStrongBinder(IInterface::asBinder(surface));
if (err != NO_ERROR) {
- ALOGE("setFrameTimelineVsync: failed writing strong binder: %s (%d)", strerror(-err),
- -err);
+ ALOGE("%s: failed writing strong binder: %s (%d)", __func__, strerror(-err), -err);
return err;
}
- err = data.writeInt64(frameTimelineVsyncId);
- if (err != NO_ERROR) {
- ALOGE("setFrameTimelineVsync: failed writing int64_t: %s (%d)", strerror(-err), -err);
- return err;
- }
+ SAFE_PARCEL(frameTimelineInfo.write, data);
- err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_VSYNC, data, &reply);
+ err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_INFO, data, &reply);
if (err != NO_ERROR) {
- ALOGE("setFrameTimelineVsync: failed to transact: %s (%d)", strerror(-err), err);
+ ALOGE("%s: failed to transact: %s (%d)", __func__, strerror(-err), err);
return err;
}
return reply.readInt32();
}
- virtual status_t addTransactionTraceListener(
- const sp<gui::ITransactionTraceListener>& listener) {
+ status_t addTransactionTraceListener(
+ const sp<gui::ITransactionTraceListener>& listener) override {
Parcel data, reply;
SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener));
@@ -1235,7 +1221,7 @@
/**
* Get priority of the RenderEngine in surface flinger.
*/
- virtual int getGPUContextPriority() {
+ int getGPUContextPriority() override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t err =
@@ -1269,8 +1255,9 @@
case SET_TRANSACTION_STATE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- int64_t frameTimelineVsyncId;
- SAFE_PARCEL(data.readInt64, &frameTimelineVsyncId);
+ FrameTimelineInfo frameTimelineInfo;
+ SAFE_PARCEL(frameTimelineInfo.read, data);
+
uint32_t count = 0;
SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize());
Vector<ComposerState> state;
@@ -1324,10 +1311,10 @@
uint64_t transactionId = -1;
SAFE_PARCEL(data.readUint64, &transactionId);
- return setTransactionState(frameTimelineVsyncId, state, displays, stateFlags,
- applyToken, inputWindowCommands, desiredPresentTime,
- isAutoTimestamp, uncachedBuffer, hasListenerCallbacks,
- listenerCallbacks, transactionId);
+ return setTransactionState(frameTimelineInfo, state, displays, stateFlags, applyToken,
+ inputWindowCommands, desiredPresentTime, isAutoTimestamp,
+ uncachedBuffer, hasListenerCallbacks, listenerCallbacks,
+ transactionId);
}
case BOOT_FINISHED: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
@@ -2078,30 +2065,26 @@
}
return NO_ERROR;
}
- case SET_FRAME_TIMELINE_VSYNC: {
+ case SET_FRAME_TIMELINE_INFO: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> binder;
status_t err = data.readStrongBinder(&binder);
if (err != NO_ERROR) {
- ALOGE("setFrameTimelineVsync: failed to read strong binder: %s (%d)",
- strerror(-err), -err);
+ ALOGE("setFrameTimelineInfo: failed to read strong binder: %s (%d)", strerror(-err),
+ -err);
return err;
}
sp<IGraphicBufferProducer> surface = interface_cast<IGraphicBufferProducer>(binder);
if (!surface) {
- ALOGE("setFrameTimelineVsync: failed to cast to IGraphicBufferProducer: %s (%d)",
+ ALOGE("setFrameTimelineInfo: failed to cast to IGraphicBufferProducer: %s (%d)",
strerror(-err), -err);
return err;
}
- int64_t frameTimelineVsyncId;
- err = data.readInt64(&frameTimelineVsyncId);
- if (err != NO_ERROR) {
- ALOGE("setFrameTimelineVsync: failed to read int64_t: %s (%d)", strerror(-err),
- -err);
- return err;
- }
- status_t result = setFrameTimelineVsync(surface, frameTimelineVsyncId);
+ FrameTimelineInfo frameTimelineInfo;
+ SAFE_PARCEL(frameTimelineInfo.read, data);
+
+ status_t result = setFrameTimelineInfo(surface, frameTimelineInfo);
reply->writeInt32(result);
return NO_ERROR;
}
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index 1808571..0ded936 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -92,10 +92,8 @@
return err;
}
-JankData::JankData() :
- frameVsyncId(ISurfaceComposer::INVALID_VSYNC_ID),
- jankType(JankType::None) {
-}
+JankData::JankData()
+ : frameVsyncId(FrameTimelineInfo::INVALID_VSYNC_ID), jankType(JankType::None) {}
status_t JankData::writeToParcel(Parcel* output) const {
SAFE_PARCEL(output->writeInt64, frameVsyncId);
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 2946aae..fff3305 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -63,7 +63,7 @@
shouldBeSeamless(true),
fixedTransformHint(ui::Transform::ROT_INVALID),
frameNumber(0),
- frameTimelineVsyncId(ISurfaceComposer::INVALID_VSYNC_ID),
+ frameTimelineInfo(),
autoRefresh(false) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
@@ -151,7 +151,7 @@
SAFE_PARCEL(output.writeBool, shouldBeSeamless);
SAFE_PARCEL(output.writeUint32, fixedTransformHint);
SAFE_PARCEL(output.writeUint64, frameNumber);
- SAFE_PARCEL(output.writeInt64, frameTimelineVsyncId);
+ SAFE_PARCEL(frameTimelineInfo.write, output);
SAFE_PARCEL(output.writeBool, autoRefresh);
SAFE_PARCEL(output.writeUint32, blurRegions.size());
@@ -270,7 +270,7 @@
SAFE_PARCEL(input.readUint32, &tmpUint32);
fixedTransformHint = static_cast<ui::Transform::RotationFlags>(tmpUint32);
SAFE_PARCEL(input.readUint64, &frameNumber);
- SAFE_PARCEL(input.readInt64, &frameTimelineVsyncId);
+ SAFE_PARCEL(frameTimelineInfo.read, input);
SAFE_PARCEL(input.readBool, &autoRefresh);
uint32_t numRegions = 0;
@@ -426,9 +426,6 @@
what |= eReparentChildren;
reparentSurfaceControl = other.reparentSurfaceControl;
}
- if (other.what & eDetachChildren) {
- what |= eDetachChildren;
- }
if (other.what & eRelativeLayerChanged) {
what |= eRelativeLayerChanged;
what &= ~eLayerChanged;
@@ -537,15 +534,9 @@
what |= eFrameNumberChanged;
frameNumber = other.frameNumber;
}
- if (other.what & eFrameTimelineVsyncChanged) {
- // When merging vsync Ids we take the oldest valid one
- if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID &&
- other.frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) {
- frameTimelineVsyncId = std::max(frameTimelineVsyncId, other.frameTimelineVsyncId);
- } else if (frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) {
- frameTimelineVsyncId = other.frameTimelineVsyncId;
- }
- what |= eFrameTimelineVsyncChanged;
+ if (other.what & eFrameTimelineInfoChanged) {
+ what |= eFrameTimelineInfoChanged;
+ frameTimelineInfo.merge(other.frameTimelineInfo);
}
if (other.what & eAutoRefreshChanged) {
what |= eAutoRefreshChanged;
@@ -644,11 +635,13 @@
status_t CaptureArgs::write(Parcel& output) const {
SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(pixelFormat));
SAFE_PARCEL(output.write, sourceCrop);
- SAFE_PARCEL(output.writeFloat, frameScale);
+ SAFE_PARCEL(output.writeFloat, frameScaleX);
+ SAFE_PARCEL(output.writeFloat, frameScaleY);
SAFE_PARCEL(output.writeBool, captureSecureLayers);
SAFE_PARCEL(output.writeInt32, uid);
SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(dataspace));
SAFE_PARCEL(output.writeBool, allowProtected);
+ SAFE_PARCEL(output.writeBool, grayscale);
return NO_ERROR;
}
@@ -657,12 +650,14 @@
SAFE_PARCEL(input.readInt32, &value);
pixelFormat = static_cast<ui::PixelFormat>(value);
SAFE_PARCEL(input.read, sourceCrop);
- SAFE_PARCEL(input.readFloat, &frameScale);
+ SAFE_PARCEL(input.readFloat, &frameScaleX);
+ SAFE_PARCEL(input.readFloat, &frameScaleY);
SAFE_PARCEL(input.readBool, &captureSecureLayers);
SAFE_PARCEL(input.readInt32, &uid);
SAFE_PARCEL(input.readInt32, &value);
dataspace = static_cast<ui::Dataspace>(value);
SAFE_PARCEL(input.readBool, &allowProtected);
+ SAFE_PARCEL(input.readBool, &grayscale);
return NO_ERROR;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index e82f0cc..59ad8d2 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1496,8 +1496,8 @@
case NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER:
res = dispatchGetLastQueuedBuffer(args);
break;
- case NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC:
- res = dispatchSetFrameTimelineVsync(args);
+ case NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO:
+ res = dispatchSetFrameTimelineInfo(args);
break;
default:
res = NAME_NOT_FOUND;
@@ -1806,12 +1806,13 @@
return result;
}
-int Surface::dispatchSetFrameTimelineVsync(va_list args) {
+int Surface::dispatchSetFrameTimelineInfo(va_list args) {
ATRACE_CALL();
auto frameTimelineVsyncId = static_cast<int64_t>(va_arg(args, int64_t));
+ auto inputEventId = static_cast<int32_t>(va_arg(args, int32_t));
- ALOGV("Surface::dispatchSetFrameTimelineVsync");
- return setFrameTimelineVsync(frameTimelineVsyncId);
+ ALOGV("Surface::%s", __func__);
+ return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId});
}
bool Surface::transformToDisplayInverse() {
@@ -2579,9 +2580,8 @@
shouldBeSeamless);
}
-status_t Surface::setFrameTimelineVsync(int64_t frameTimelineVsyncId) {
- return composerService()->setFrameTimelineVsync(mGraphicBufferProducer,
- frameTimelineVsyncId);
+status_t Surface::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) {
+ return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo);
}
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 96c099b..550803d 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -396,7 +396,7 @@
mContainsBuffer(other.mContainsBuffer),
mDesiredPresentTime(other.mDesiredPresentTime),
mIsAutoTimestamp(other.mIsAutoTimestamp),
- mFrameTimelineVsyncId(other.mFrameTimelineVsyncId),
+ mFrameTimelineInfo(other.mFrameTimelineInfo),
mApplyToken(other.mApplyToken) {
mDisplayStates = other.mDisplayStates;
mComposerStates = other.mComposerStates;
@@ -427,7 +427,9 @@
const bool containsBuffer = parcel->readBool();
const int64_t desiredPresentTime = parcel->readInt64();
const bool isAutoTimestamp = parcel->readBool();
- const int64_t frameTimelineVsyncId = parcel->readInt64();
+ FrameTimelineInfo frameTimelineInfo;
+ SAFE_PARCEL(frameTimelineInfo.read, *parcel);
+
sp<IBinder> applyToken;
parcel->readNullableStrongBinder(&applyToken);
size_t count = static_cast<size_t>(parcel->readUint32());
@@ -502,7 +504,7 @@
mContainsBuffer = containsBuffer;
mDesiredPresentTime = desiredPresentTime;
mIsAutoTimestamp = isAutoTimestamp;
- mFrameTimelineVsyncId = frameTimelineVsyncId;
+ mFrameTimelineInfo = frameTimelineInfo;
mDisplayStates = displayStates;
mListenerCallbacks = listenerCallbacks;
mComposerStates = composerStates;
@@ -534,7 +536,7 @@
parcel->writeBool(mContainsBuffer);
parcel->writeInt64(mDesiredPresentTime);
parcel->writeBool(mIsAutoTimestamp);
- parcel->writeInt64(mFrameTimelineVsyncId);
+ SAFE_PARCEL(mFrameTimelineInfo.write, *parcel);
parcel->writeStrongBinder(mApplyToken);
parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size()));
for (auto const& displayState : mDisplayStates) {
@@ -613,13 +615,7 @@
mExplicitEarlyWakeupEnd = mExplicitEarlyWakeupEnd || other.mExplicitEarlyWakeupEnd;
mApplyToken = other.mApplyToken;
- // When merging vsync Ids we take the oldest one
- if (mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID &&
- other.mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) {
- mFrameTimelineVsyncId = std::max(mFrameTimelineVsyncId, other.mFrameTimelineVsyncId);
- } else if (mFrameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) {
- mFrameTimelineVsyncId = other.mFrameTimelineVsyncId;
- }
+ mFrameTimelineInfo.merge(other.mFrameTimelineInfo);
other.clear();
return *this;
@@ -639,7 +635,7 @@
mExplicitEarlyWakeupEnd = false;
mDesiredPresentTime = 0;
mIsAutoTimestamp = true;
- mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+ mFrameTimelineInfo.clear();
mApplyToken = nullptr;
}
@@ -651,9 +647,8 @@
uncacheBuffer.id = cacheId;
sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
- sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {},
- systemTime(), true, uncacheBuffer, false, {},
- 0 /* Undefined transactionId */);
+ sf->setTransactionState(FrameTimelineInfo{}, {}, {}, 0, applyToken, {}, systemTime(), true,
+ uncacheBuffer, false, {}, 0 /* Undefined transactionId */);
}
void SurfaceComposerClient::Transaction::cacheBuffers() {
@@ -773,7 +768,7 @@
? mApplyToken
: IInterface::asBinder(TransactionCompletedListener::getIInstance());
- sf->setTransactionState(mFrameTimelineVsyncId, composerStates, displayStates, flags, applyToken,
+ sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken,
mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp,
{} /*uncacheBuffer - only set in doUncacheBufferTransaction*/,
hasListenerCallbacks, listenerCallbacks, mId);
@@ -1391,19 +1386,6 @@
return *this;
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren(
- const sp<SurfaceControl>& sc) {
- layer_state_t* s = getLayerState(sc);
- if (!s) {
- mStatus = BAD_INDEX;
- return *this;
- }
- s->what |= layer_state_t::eDetachChildren;
-
- registerSurfaceControlForCallback(sc);
- return *this;
-}
-
#ifndef NO_INPUT
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo(
const sp<SurfaceControl>& sc,
@@ -1549,22 +1531,22 @@
return *this;
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync(
- int64_t frameTimelineVsyncId) {
- mFrameTimelineVsyncId = frameTimelineVsyncId;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo(
+ const FrameTimelineInfo& frameTimelineInfo) {
+ mFrameTimelineInfo = frameTimelineInfo;
return *this;
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync(
- const sp<SurfaceControl>& sc, int64_t frameTimelineVsyncId) {
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo(
+ const sp<SurfaceControl>& sc, const FrameTimelineInfo& frameTimelineInfo) {
layer_state_t* s = getLayerState(sc);
if (!s) {
mStatus = BAD_INDEX;
return *this;
}
- s->what |= layer_state_t::eFrameTimelineVsyncChanged;
- s->frameTimelineVsyncId = frameTimelineVsyncId;
+ s->what |= layer_state_t::eFrameTimelineInfoChanged;
+ s->frameTimelineInfo = frameTimelineInfo;
return *this;
}
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 7f69bc4..fa3efe1 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -92,7 +92,7 @@
void flushShadowQueue() { mFlushShadowQueue = true; }
status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless);
- status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId);
+ status_t setFrameTimelineInfo(const FrameTimelineInfo& info);
virtual ~BLASTBufferQueue();
@@ -156,7 +156,7 @@
// This is only relevant for shared buffer mode.
bool mAutoRefresh GUARDED_BY(mMutex) = false;
- std::queue<int64_t> mNextFrameTimelineVsyncIdQueue GUARDED_BY(mMutex);
+ std::queue<FrameTimelineInfo> mNextFrameTimelineInfoQueue GUARDED_BY(mMutex);
// Last acquired buffer's scaling mode. This is used to check if we should update the blast
// layer size immediately or wait until we get the next buffer. This will support scenarios
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index 5587acf..4175a49 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -25,7 +25,7 @@
// The Vsync Id corresponsing to this vsync event. This will be used to
// populate ISurfaceComposer::setFrameTimelineVsync and
// SurfaceComposerClient::setFrameTimelineVsync
- int64_t id = ISurfaceComposer::INVALID_VSYNC_ID;
+ int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID;
// The deadline in CLOCK_MONOTONIC that the app needs to complete its
// frame by (both on the CPU and the GPU)
@@ -52,7 +52,20 @@
private:
sp<Looper> mLooper;
DisplayEventReceiver mReceiver;
- bool mWaitingForVsync;
+ // The state of vsync event registration and whether the client is expecting
+ // an event or not.
+ enum class VsyncState {
+ // The dispatcher is not registered for vsync events.
+ Unregistered,
+ // The dispatcher is registered to receive vsync events but should not dispatch it to the
+ // client as the client is not expecting a vsync event.
+ Registered,
+
+ // The dispatcher is registered to receive vsync events and supposed to dispatch it to
+ // the client.
+ RegisteredAndWaitingForVsync,
+ };
+ VsyncState mVsyncState;
std::vector<FrameRateOverride> mFrameRateOverrides;
diff --git a/libs/gui/include/gui/FrameTimelineInfo.h b/libs/gui/include/gui/FrameTimelineInfo.h
new file mode 100644
index 0000000..3b4c009
--- /dev/null
+++ b/libs/gui/include/gui/FrameTimelineInfo.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <android/os/IInputConstants.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+struct FrameTimelineInfo {
+ // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java
+ static constexpr int64_t INVALID_VSYNC_ID = -1;
+
+ // The vsync id that was used to start the transaction
+ int64_t vsyncId = INVALID_VSYNC_ID;
+
+ // The id of the input event that caused this buffer
+ int32_t inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID;
+
+ status_t write(Parcel& output) const;
+ status_t read(const Parcel& input);
+
+ void merge(const FrameTimelineInfo& other);
+ void clear();
+};
+
+} // namespace android
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 86f3c60..81ff6b0 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -24,6 +24,7 @@
#include <android/gui/IScreenCaptureListener.h>
#include <android/gui/ITransactionTraceListener.h>
+#include <gui/FrameTimelineInfo.h>
#include <gui/ITransactionCompletedListener.h>
#include <input/Flags.h>
@@ -117,9 +118,6 @@
using EventRegistrationFlags = Flags<EventRegistration>;
- // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java
- static constexpr int64_t INVALID_VSYNC_ID = -1;
-
/*
* Create a connection with SurfaceFlinger.
*/
@@ -164,7 +162,7 @@
/* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
virtual status_t setTransactionState(
- int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
+ const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
@@ -494,11 +492,11 @@
virtual status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) = 0;
/*
- * Sets the frame timeline vsync id received from choreographer that corresponds to next
+ * Sets the frame timeline vsync info received from choreographer that corresponds to next
* buffer submitted on that surface.
*/
- virtual status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
- int64_t frameTimelineVsyncId) = 0;
+ virtual status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
+ const FrameTimelineInfo& frameTimelineInfo) = 0;
/*
* Adds a TransactionTraceListener to listen for transaction tracing state updates.
@@ -569,7 +567,7 @@
SET_GAME_CONTENT_TYPE,
SET_FRAME_RATE,
ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN,
- SET_FRAME_TIMELINE_VSYNC,
+ SET_FRAME_TIMELINE_INFO,
ADD_TRANSACTION_TRACE_LISTENER,
GET_GPU_CONTEXT_PRIORITY,
// Always append new enum to the end.
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index b1305c6..2f9a0c0 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -102,7 +102,7 @@
/* was ScalingModeChanged, now available 0x00000400, */
eShadowRadiusChanged = 0x00000800,
eReparentChildren = 0x00001000,
- eDetachChildren = 0x00002000,
+ /* was eDetachChildren, now available 0x00002000, */
eRelativeLayerChanged = 0x00004000,
eReparent = 0x00008000,
eColorChanged = 0x00010000,
@@ -132,7 +132,7 @@
eProducerDisconnect = 0x100'00000000,
eFixedTransformHintChanged = 0x200'00000000,
eFrameNumberChanged = 0x400'00000000,
- eFrameTimelineVsyncChanged = 0x800'00000000,
+ eFrameTimelineInfoChanged = 0x800'00000000,
eBlurRegionsChanged = 0x1000'00000000,
eAutoRefreshChanged = 0x2000'00000000,
};
@@ -238,7 +238,7 @@
// graphics producer.
uint64_t frameNumber;
- int64_t frameTimelineVsyncId;
+ FrameTimelineInfo frameTimelineInfo;
// Indicates that the consumer should acquire the next frame as soon as it
// can and not wait for a frame to become available. This is only relevant
@@ -328,7 +328,8 @@
ui::PixelFormat pixelFormat{ui::PixelFormat::RGBA_8888};
Rect sourceCrop;
- float frameScale{1};
+ float frameScaleX{1};
+ float frameScaleY{1};
bool captureSecureLayers{false};
int32_t uid{UNSET_UID};
// Force capture to be in a color space. If the value is ui::Dataspace::UNKNOWN, the captured
@@ -346,6 +347,8 @@
// the contents being accessed/captured by screenshot or unsecure display.
bool allowProtected = false;
+ bool grayscale = false;
+
virtual status_t write(Parcel& output) const;
virtual status_t read(const Parcel& input);
};
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 43b5dcd..b6b5c7c 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -18,6 +18,7 @@
#define ANDROID_GUI_SURFACE_H
#include <gui/BufferQueueDefs.h>
+#include <gui/FrameTimelineInfo.h>
#include <gui/HdrMetadata.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/IProducerListener.h>
@@ -187,7 +188,7 @@
status_t getConsumerUsage(uint64_t* outUsage) const;
virtual status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless);
- virtual status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId);
+ virtual status_t setFrameTimelineInfo(const FrameTimelineInfo& info);
protected:
virtual ~Surface();
@@ -273,7 +274,7 @@
int dispatchAddQueueInterceptor(va_list args);
int dispatchAddQueryInterceptor(va_list args);
int dispatchGetLastQueuedBuffer(va_list args);
- int dispatchSetFrameTimelineVsync(va_list args);
+ int dispatchSetFrameTimelineInfo(va_list args);
bool transformToDisplayInverse();
protected:
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 11db658..e7abfe6 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -385,8 +385,8 @@
int64_t mDesiredPresentTime = 0;
bool mIsAutoTimestamp = true;
- // The vsync Id provided by Choreographer.getVsyncId
- int64_t mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+ // The vsync id provided by Choreographer.getVsyncId and the input event id
+ FrameTimelineInfo mFrameTimelineInfo;
// If not null, transactions will be queued up using this token otherwise a common token
// per process will be used.
@@ -508,18 +508,6 @@
// Set the framenumber generated by the graphics producer to mimic BufferQueue behaviour.
Transaction& setFrameNumber(const sp<SurfaceControl>& sc, uint64_t frameNumber);
- // Detaches all child surfaces (and their children recursively)
- // from their SurfaceControl.
- // The child SurfaceControls will not throw exceptions or return errors,
- // but transactions will have no effect.
- // The child surfaces will continue to follow their parent surfaces,
- // and remain eligible for rendering, but their relative state will be
- // frozen. We use this in the WindowManager, in app shutdown/relaunch
- // scenarios, where the app would otherwise clean up its child Surfaces.
- // Sometimes the WindowManager needs to extend their lifetime slightly
- // in order to perform an exit animation or prevent flicker.
- Transaction& detachChildren(const sp<SurfaceControl>& sc);
-
#ifndef NO_INPUT
Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
Transaction& setFocusedWindow(const FocusRequest& request);
@@ -546,11 +534,12 @@
Transaction& setFixedTransformHint(const sp<SurfaceControl>& sc, int32_t transformHint);
// Sets the frame timeline vsync id received from choreographer that corresponds
- // to the transaction.
- Transaction& setFrameTimelineVsync(int64_t frameTimelineVsyncId);
+ // to the transaction, and the input event id that identifies the input event that caused
+ // the current frame.
+ Transaction& setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo);
// Variant that only applies to a specific SurfaceControl.
- Transaction& setFrameTimelineVsync(const sp<SurfaceControl>& sc,
- int64_t frameTimelineVsyncId);
+ Transaction& setFrameTimelineInfo(const sp<SurfaceControl>& sc,
+ const FrameTimelineInfo& frameTimelineInfo);
// Indicates that the consumer should acquire the next frame as soon as it
// can and not wait for a frame to become available. This is only relevant
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 63db9a7..3f7a5b1 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -695,7 +695,7 @@
void destroyDisplay(const sp<IBinder>& /*display */) override {}
std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override { return {}; }
sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId) const override { return nullptr; }
- status_t setTransactionState(int64_t /*frameTimelineVsyncId*/,
+ status_t setTransactionState(const FrameTimelineInfo& /*frameTimelineInfo*/,
const Vector<ComposerState>& /*state*/,
const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
const sp<IBinder>& /*applyToken*/,
@@ -877,8 +877,8 @@
return NO_ERROR;
}
- status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& /*surface*/,
- int64_t /*frameTimelineVsyncId*/) override {
+ status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& /*surface*/,
+ const FrameTimelineInfo& /*frameTimelineInfo*/) override {
return NO_ERROR;
}
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 2ed441d..698cf6e 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -166,6 +166,7 @@
mKeyboardType(other.mKeyboardType),
mKeyCharacterMap(other.mKeyCharacterMap),
mHasVibrator(other.mHasVibrator),
+ mHasBattery(other.mHasBattery),
mHasButtonUnderPad(other.mHasButtonUnderPad),
mHasSensor(other.mHasSensor),
mMotionRanges(other.mMotionRanges),
@@ -187,6 +188,7 @@
mSources = 0;
mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
mHasVibrator = false;
+ mHasBattery = false;
mHasButtonUnderPad = false;
mHasSensor = false;
mMotionRanges.clear();
diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl
index 6316b59..bce0ec8 100644
--- a/libs/input/android/os/IInputConstants.aidl
+++ b/libs/input/android/os/IInputConstants.aidl
@@ -28,4 +28,13 @@
* to identify apps that are using this flag.
*/
const long BLOCK_FLAG_SLIPPERY = 157929241;
+
+ // Indicate invalid battery capacity
+ const int INVALID_BATTERY_CAPACITY = -1;
+
+ /**
+ * Every input event has an id. This constant value is used when a valid input event id is not
+ * available.
+ */
+ const int INVALID_INPUT_EVENT_ID = 0;
}
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 6d91916..6b085a3 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -21,7 +21,7 @@
#include <gui/DisplayEventDispatcher.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
#include <private/android/choreographer.h>
#include <utils/Looper.h>
#include <utils/Timers.h>
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index f56b3a2..6574ae6 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -53,15 +53,13 @@
"libcutils",
"libEGL",
"libGLESv2",
- "libnativehelper",
],
- export_shared_lib_headers: [
- "libnativehelper",
- ],
+ export_header_lib_headers: ["jni_headers"],
header_libs: [
+ "jni_headers",
"libnativedisplay_headers",
+ "libnativehelper_header_only",
],
-
}
diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h
index d3a4a66..0f4fd45 100644
--- a/libs/nativedisplay/include-private/private/android/choreographer.h
+++ b/libs/nativedisplay/include-private/private/android/choreographer.h
@@ -18,7 +18,7 @@
#include <apex/choreographer.h>
#include <inttypes.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
namespace android {
diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
index f371667..85fe42f 100644
--- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
+++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
@@ -19,7 +19,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
#include <system/graphics.h>
// This file provides a facade API on top of SurfaceTexture, which avoids using
diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp
index ebe4484..c214ab7 100644
--- a/libs/nativedisplay/surfacetexture/surface_texture.cpp
+++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp
@@ -29,8 +29,7 @@
#include <mutex>
#include <jni.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/scoped_local_ref.h>
struct ASurfaceTexture {
android::sp<android::SurfaceTexture> consumer;
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 82d2e66..ffe4412 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -255,7 +255,7 @@
NATIVE_WINDOW_ALLOCATE_BUFFERS = 45, /* private */
NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */
NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */
- NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC = 48, /* private */
+ NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO = 48, /* private */
// clang-format on
};
@@ -1023,10 +1023,11 @@
(int)compatibility, (int)shouldBeSeamless);
}
-static inline int native_window_set_frame_timeline_vsync(struct ANativeWindow* window,
- int64_t frameTimelineVsyncId) {
- return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC,
- frameTimelineVsyncId);
+static inline int native_window_set_frame_timeline_info(struct ANativeWindow* window,
+ int64_t frameTimelineVsyncId,
+ int32_t inputEventId) {
+ return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO,
+ frameTimelineVsyncId, inputEventId);
}
// ------------------------------------------------------------------------------------------------
diff --git a/libs/sensorprivacy/SensorPrivacyManager.cpp b/libs/sensorprivacy/SensorPrivacyManager.cpp
index 7bddee6..4714469 100644
--- a/libs/sensorprivacy/SensorPrivacyManager.cpp
+++ b/libs/sensorprivacy/SensorPrivacyManager.cpp
@@ -64,13 +64,15 @@
}
}
-void SensorPrivacyManager::addIndividualSensorPrivacyListener(int userId, int sensor,
+status_t SensorPrivacyManager::addIndividualSensorPrivacyListener(int userId, int sensor,
const sp<hardware::ISensorPrivacyListener>& listener)
{
sp<hardware::ISensorPrivacyManager> service = getService();
if (service != nullptr) {
- service->addIndividualSensorPrivacyListener(userId, sensor, listener);
+ return service->addIndividualSensorPrivacyListener(userId, sensor, listener)
+ .transactionError();
}
+ return UNEXPECTED_NULL;
}
void SensorPrivacyManager::removeSensorPrivacyListener(
@@ -106,6 +108,19 @@
return false;
}
+status_t SensorPrivacyManager::isIndividualSensorPrivacyEnabled(int userId, int sensor,
+ bool &returnVal)
+{
+ sp<hardware::ISensorPrivacyManager> service = getService();
+ if (service != nullptr) {
+ binder::Status res = service->isIndividualSensorPrivacyEnabled(userId, sensor, &returnVal);
+ return res.transactionError();
+ }
+ // if the SensorPrivacyManager is not available then assume sensor privacy is disabled
+ returnVal = false;
+ return UNKNOWN_ERROR;
+}
+
status_t SensorPrivacyManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient)
{
sp<hardware::ISensorPrivacyManager> service = getService();
diff --git a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
index bd7c726..12778e1 100644
--- a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
+++ b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
@@ -36,11 +36,12 @@
SensorPrivacyManager();
void addSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener);
- void addIndividualSensorPrivacyListener(int userId, int sensor,
+ status_t addIndividualSensorPrivacyListener(int userId, int sensor,
const sp<hardware::ISensorPrivacyListener>& listener);
void removeSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener);
bool isSensorPrivacyEnabled();
bool isIndividualSensorPrivacyEnabled(int userId, int sensor);
+ status_t isIndividualSensorPrivacyEnabled(int userId, int sensor, bool &result);
status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
status_t unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient);
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index ea9b483..69aea84 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -108,6 +108,10 @@
virtual bool isVibrating(int32_t deviceId) = 0;
virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0;
+ /* Get battery level of a particular input device. */
+ virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId) = 0;
+ /* Get battery status of a particular input device. */
+ virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId) = 0;
/* Return true if the device can send input events to the specified display. */
virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0;
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index abda4ef..7f979f2 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -30,6 +30,7 @@
"mapper/accumulator/CursorScrollAccumulator.cpp",
"mapper/accumulator/SingleTouchMotionAccumulator.cpp",
"mapper/accumulator/TouchButtonAccumulator.cpp",
+ "mapper/BatteryInputMapper.cpp",
"mapper/CursorInputMapper.cpp",
"mapper/ExternalStylusInputMapper.cpp",
"mapper/InputMapper.cpp",
@@ -60,7 +61,11 @@
"libui",
"libutils",
],
+ static_libs: [
+ "libc++fs",
+ ],
header_libs: [
+ "libbatteryservice_headers",
"libinputreader_headers",
],
}
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index b97ff90..8f8c051 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -29,11 +29,14 @@
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/limits.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
#include <unistd.h>
#define LOG_TAG "EventHub"
// #define LOG_NDEBUG 0
+#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include <input/KeyCharacterMap.h>
@@ -64,6 +67,23 @@
static constexpr int32_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0;
static constexpr int32_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1;
+// must be kept in sync with definitions in kernel /drivers/power/supply/power_supply_sysfs.c
+static const std::unordered_map<std::string, int32_t> BATTERY_STATUS =
+ {{"Unknown", BATTERY_STATUS_UNKNOWN},
+ {"Charging", BATTERY_STATUS_CHARGING},
+ {"Discharging", BATTERY_STATUS_DISCHARGING},
+ {"Not charging", BATTERY_STATUS_NOT_CHARGING},
+ {"Full", BATTERY_STATUS_FULL}};
+
+// Mapping taken from
+// https://gitlab.freedesktop.org/upower/upower/-/blob/master/src/linux/up-device-supply.c#L484
+static const std::unordered_map<std::string, int32_t> BATTERY_LEVEL = {{"Critical", 5},
+ {"Low", 10},
+ {"Normal", 55},
+ {"High", 70},
+ {"Full", 100},
+ {"Unknown", 50}};
+
static inline const char* toString(bool value) {
return value ? "true" : "false";
}
@@ -127,6 +147,73 @@
return inputEventTime;
}
+/**
+ * Returns the sysfs root path of the input device
+ *
+ */
+static std::filesystem::path getSysfsRootPath(const char* devicePath) {
+ std::error_code errorCode;
+
+ // Stat the device path to get the major and minor number of the character file
+ struct stat statbuf;
+ if (stat(devicePath, &statbuf) == -1) {
+ ALOGE("Could not stat device %s due to error: %s.", devicePath, std::strerror(errno));
+ return std::filesystem::path();
+ }
+
+ unsigned int major_num = major(statbuf.st_rdev);
+ unsigned int minor_num = minor(statbuf.st_rdev);
+
+ // Realpath "/sys/dev/char/{major}:{minor}" to get the sysfs path to the input event
+ auto sysfsPath = std::filesystem::path("/sys/dev/char/");
+ sysfsPath /= std::to_string(major_num) + ":" + std::to_string(minor_num);
+ sysfsPath = std::filesystem::canonical(sysfsPath, errorCode);
+
+ // Make sure nothing went wrong in call to canonical()
+ if (errorCode) {
+ ALOGW("Could not run filesystem::canonical() due to error %d : %s.", errorCode.value(),
+ errorCode.message().c_str());
+ return std::filesystem::path();
+ }
+
+ // Continue to go up a directory until we reach a directory named "input"
+ while (sysfsPath != "/" && sysfsPath.filename() != "input") {
+ sysfsPath = sysfsPath.parent_path();
+ }
+
+ // Then go up one more and you will be at the sysfs root of the device
+ sysfsPath = sysfsPath.parent_path();
+
+ // Make sure we didn't reach root path and that directory actually exists
+ if (sysfsPath == "/" || !std::filesystem::exists(sysfsPath, errorCode)) {
+ if (errorCode) {
+ ALOGW("Could not run filesystem::exists() due to error %d : %s.", errorCode.value(),
+ errorCode.message().c_str());
+ }
+
+ // Not found
+ return std::filesystem::path();
+ }
+
+ return sysfsPath;
+}
+
+/**
+ * Returns the power supply node in sys fs
+ *
+ */
+static std::filesystem::path findPowerSupplyNode(const std::filesystem::path& sysfsRootPath) {
+ for (auto path = sysfsRootPath; path != "/"; path = path.parent_path()) {
+ std::error_code errorCode;
+ auto iter = std::filesystem::directory_iterator(path / "power_supply", errorCode);
+ if (!errorCode && iter != std::filesystem::directory_iterator()) {
+ return iter->path();
+ }
+ }
+ // Not found
+ return std::filesystem::path();
+}
+
// --- Global Functions ---
Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, Flags<InputDeviceClass> deviceClasses) {
@@ -976,6 +1063,56 @@
return nullptr;
}
+std::optional<int32_t> EventHub::getBatteryCapacity(int32_t deviceId) const {
+ std::scoped_lock _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ std::string buffer;
+
+ if (!device || (device->sysfsBatteryPath.empty())) {
+ return std::nullopt;
+ }
+
+ // Some devices report battery capacity as an integer through the "capacity" file
+ if (base::ReadFileToString(device->sysfsBatteryPath / "capacity", &buffer)) {
+ return std::stoi(buffer);
+ }
+
+ // Other devices report capacity as an enum value POWER_SUPPLY_CAPACITY_LEVEL_XXX
+ // These values are taken from kernel source code include/linux/power_supply.h
+ if (base::ReadFileToString(device->sysfsBatteryPath / "capacity_level", &buffer)) {
+ const auto it = BATTERY_LEVEL.find(buffer);
+ if (it != BATTERY_LEVEL.end()) {
+ return it->second;
+ }
+ }
+ return std::nullopt;
+}
+
+std::optional<int32_t> EventHub::getBatteryStatus(int32_t deviceId) const {
+ std::scoped_lock _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ std::string buffer;
+
+ if (!device || (device->sysfsBatteryPath.empty())) {
+ return std::nullopt;
+ }
+
+ if (!base::ReadFileToString(device->sysfsBatteryPath / "status", &buffer)) {
+ ALOGE("Failed to read sysfs battery info: %s", strerror(errno));
+ return std::nullopt;
+ }
+
+ // Remove trailing new line
+ buffer.erase(std::remove(buffer.begin(), buffer.end(), '\n'), buffer.end());
+ const auto it = BATTERY_STATUS.find(buffer);
+
+ if (it != BATTERY_STATUS.end()) {
+ return it->second;
+ }
+
+ return std::nullopt;
+}
+
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
ALOG_ASSERT(bufferSize >= 1);
@@ -1584,6 +1721,18 @@
return -1;
}
+ // Grab the device's sysfs path
+ device->sysfsRootPath = getSysfsRootPath(devicePath.c_str());
+
+ if (!device->sysfsRootPath.empty()) {
+ device->sysfsBatteryPath = findPowerSupplyNode(device->sysfsRootPath);
+
+ // Check if a battery exists
+ if (!device->sysfsBatteryPath.empty()) {
+ device->classes |= InputDeviceClass::BATTERY;
+ }
+ }
+
// Determine whether the device has a mic.
if (device->deviceHasMicLocked()) {
device->classes |= InputDeviceClass::MIC;
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 3e6910d..8fc6f4a 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -21,6 +21,7 @@
#include <input/Flags.h>
#include <algorithm>
+#include "BatteryInputMapper.h"
#include "CursorInputMapper.h"
#include "ExternalStylusInputMapper.h"
#include "InputReaderContext.h"
@@ -160,6 +161,11 @@
mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
}
+ // Battery-like devices.
+ if (classes.test(InputDeviceClass::BATTERY)) {
+ mappers.push_back(std::make_unique<BatteryInputMapper>(*contextPtr));
+ }
+
// Keyboard-like devices.
uint32_t keyboardSource = 0;
int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
@@ -490,6 +496,15 @@
for_each_mapper([when](InputMapper& mapper) { mapper.cancelTouch(when); });
}
+std::optional<int32_t> InputDevice::getBatteryCapacity() {
+ return first_in_mappers<int32_t>(
+ [](InputMapper& mapper) { return mapper.getBatteryCapacity(); });
+}
+
+std::optional<int32_t> InputDevice::getBatteryStatus() {
+ return first_in_mappers<int32_t>([](InputMapper& mapper) { return mapper.getBatteryStatus(); });
+}
+
int32_t InputDevice::getMetaState() {
int32_t result = 0;
for_each_mapper([&result](InputMapper& mapper) { result |= mapper.getMetaState(); });
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 7c448e4..de5d0e6 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -673,6 +673,26 @@
}
}
+std::optional<int32_t> InputReader::getBatteryCapacity(int32_t deviceId) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ return device->getBatteryCapacity();
+ }
+ return std::nullopt;
+}
+
+std::optional<int32_t> InputReader::getBatteryStatus(int32_t deviceId) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ return device->getBatteryStatus();
+ }
+ return std::nullopt;
+}
+
bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
std::scoped_lock _l(mLock);
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 2cea017..30967df 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -23,6 +23,9 @@
#include <vector>
#include <input/Flags.h>
+#include <filesystem>
+
+#include <batteryservice/BatteryService.h>
#include <input/Input.h>
#include <input/InputDevice.h>
#include <input/KeyCharacterMap.h>
@@ -121,6 +124,9 @@
/* The input device has a sensor like accelerometer, gyro, etc */
SENSOR = 0x00002000,
+ /* The input device has a battery */
+ BATTERY = 0x00004000,
+
/* The input device is virtual (not a real device, not part of UI configuration). */
VIRTUAL = 0x40000000,
@@ -242,6 +248,12 @@
virtual void cancelVibrate(int32_t deviceId) = 0;
virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0;
+ /* Query battery level. */
+ virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId) const = 0;
+
+ /* Query battery status. */
+ virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId) const = 0;
+
/* Requests the EventHub to reopen all input devices on the next call to getEvents(). */
virtual void requestReopenDevices() = 0;
@@ -404,6 +416,10 @@
void monitor() override final;
+ std::optional<int32_t> getBatteryCapacity(int32_t deviceId) const override final;
+
+ std::optional<int32_t> getBatteryStatus(int32_t deviceId) const override final;
+
bool isDeviceEnabled(int32_t deviceId) override final;
status_t enableDevice(int32_t deviceId) override final;
@@ -442,6 +458,10 @@
bool ffEffectPlaying;
int16_t ffEffectId; // initially -1
+ // The paths are invalid when .empty() returns true
+ std::filesystem::path sysfsRootPath;
+ std::filesystem::path sysfsBatteryPath;
+
int32_t controllerNumber;
Device(int fd, int32_t id, const std::string& path,
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 5af76b7..e4186c8 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -92,6 +92,9 @@
void disableSensor(InputDeviceSensorType sensorType);
void flushSensor(InputDeviceSensorType sensorType);
+ std::optional<int32_t> getBatteryCapacity();
+ std::optional<int32_t> getBatteryStatus();
+
int32_t getMetaState();
void updateMetaState(int32_t keyCode);
@@ -287,6 +290,12 @@
inline std::vector<int32_t> getVibratorIds() { return mEventHub->getVibratorIds(mId); }
+ inline std::optional<int32_t> getBatteryCapacity() {
+ return mEventHub->getBatteryCapacity(mId);
+ }
+
+ inline std::optional<int32_t> getBatteryStatus() { return mEventHub->getBatteryStatus(mId); }
+
inline bool hasAbsoluteAxis(int32_t code) const {
RawAbsoluteAxisInfo info;
mEventHub->getAbsoluteAxisInfo(mId, code, &info);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 7be932a..e2558bc 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -95,6 +95,10 @@
void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) override;
+ std::optional<int32_t> getBatteryCapacity(int32_t deviceId) override;
+
+ std::optional<int32_t> getBatteryStatus(int32_t deviceId) override;
+
protected:
// These members are protected so they can be instrumented by test cases.
virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t deviceId,
diff --git a/services/inputflinger/reader/mapper/BatteryInputMapper.cpp b/services/inputflinger/reader/mapper/BatteryInputMapper.cpp
new file mode 100644
index 0000000..afdc5ab
--- /dev/null
+++ b/services/inputflinger/reader/mapper/BatteryInputMapper.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include "../Macros.h"
+
+#include "BatteryInputMapper.h"
+
+namespace android {
+
+BatteryInputMapper::BatteryInputMapper(InputDeviceContext& deviceContext)
+ : InputMapper(deviceContext) {}
+
+uint32_t BatteryInputMapper::getSources() {
+ return 0;
+}
+
+void BatteryInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+
+ info->setHasBattery(true);
+}
+
+void BatteryInputMapper::process(const RawEvent* rawEvent) {}
+
+std::optional<int32_t> BatteryInputMapper::getBatteryCapacity() {
+ return getDeviceContext().getBatteryCapacity();
+}
+
+std::optional<int32_t> BatteryInputMapper::getBatteryStatus() {
+ return getDeviceContext().getBatteryStatus();
+}
+
+void BatteryInputMapper::dump(std::string& dump) {
+ dump += INDENT2 "Battery Input Mapper:\n";
+ dump += getBatteryCapacity().has_value()
+ ? StringPrintf(INDENT3 "Capacity: %d\n", getBatteryCapacity().value())
+ : StringPrintf(INDENT3 "Capacity: Unknown");
+
+ std::string status;
+ switch (getBatteryStatus().value_or(BATTERY_STATUS_UNKNOWN)) {
+ case BATTERY_STATUS_CHARGING:
+ status = "Charging";
+ break;
+ case BATTERY_STATUS_DISCHARGING:
+ status = "Discharging";
+ break;
+ case BATTERY_STATUS_NOT_CHARGING:
+ status = "Not charging";
+ break;
+ case BATTERY_STATUS_FULL:
+ status = "Full";
+ break;
+ default:
+ status = "Unknown";
+ }
+ dump += StringPrintf(INDENT3 "Status: %s\n", status.c_str());
+}
+
+} // namespace android
diff --git a/services/inputflinger/reader/mapper/BatteryInputMapper.h b/services/inputflinger/reader/mapper/BatteryInputMapper.h
new file mode 100644
index 0000000..4fe373e
--- /dev/null
+++ b/services/inputflinger/reader/mapper/BatteryInputMapper.h
@@ -0,0 +1,41 @@
+/*
+ * 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 _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
+#define _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
+
+#include "InputMapper.h"
+
+namespace android {
+
+class BatteryInputMapper : public InputMapper {
+public:
+ explicit BatteryInputMapper(InputDeviceContext& deviceContext);
+ virtual ~BatteryInputMapper(){};
+
+ uint32_t getSources() override;
+ void populateDeviceInfo(InputDeviceInfo* deviceInfo) override;
+ void process(const RawEvent* rawEvent) override;
+
+ std::optional<int32_t> getBatteryCapacity() override;
+ std::optional<int32_t> getBatteryStatus() override;
+
+ void dump(std::string& dump) override;
+};
+
+} // namespace android
+
+#endif // _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index 6ca6ec9..44af998 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -72,6 +72,9 @@
virtual void disableSensor(InputDeviceSensorType sensorType);
virtual void flushSensor(InputDeviceSensorType sensorType);
+ virtual std::optional<int32_t> getBatteryCapacity() { return std::nullopt; }
+ virtual std::optional<int32_t> getBatteryStatus() { return std::nullopt; }
+
virtual int32_t getMetaState();
virtual void updateMetaState(int32_t keyCode);
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 36da8dd..0e88312 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <BatteryInputMapper.h>
#include <CursorInputMapper.h>
#include <InputDevice.h>
#include <InputMapper.h>
@@ -67,6 +68,8 @@
static constexpr int32_t FIRST_TRACKING_ID = 0;
static constexpr int32_t SECOND_TRACKING_ID = 1;
static constexpr int32_t THIRD_TRACKING_ID = 2;
+static constexpr int32_t BATTERY_STATUS = 4;
+static constexpr int32_t BATTERY_CAPACITY = 66;
// Error tolerance for floating point assertions.
static const float EPSILON = 0.001f;
@@ -863,6 +866,10 @@
std::vector<int32_t> getVibratorIds(int32_t deviceId) override { return mVibrators; };
+ std::optional<int32_t> getBatteryCapacity(int32_t) const override { return BATTERY_CAPACITY; }
+
+ std::optional<int32_t> getBatteryStatus(int32_t) const override { return BATTERY_STATUS; }
+
virtual bool isExternal(int32_t) const {
return false;
}
@@ -1924,6 +1931,52 @@
ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U);
}
+class FakeBatteryInputMapper : public FakeInputMapper {
+public:
+ FakeBatteryInputMapper(InputDeviceContext& deviceContext, uint32_t sources)
+ : FakeInputMapper(deviceContext, sources) {}
+
+ std::optional<int32_t> getBatteryCapacity() override {
+ return getDeviceContext().getBatteryCapacity();
+ }
+
+ std::optional<int32_t> getBatteryStatus() override {
+ return getDeviceContext().getBatteryStatus();
+ }
+};
+
+TEST_F(InputReaderTest, BatteryGetCapacity) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
+ constexpr int32_t eventHubId = 1;
+ const char* DEVICE_LOCATION = "BLUETOOTH";
+ std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
+ FakeBatteryInputMapper& mapper =
+ device->addMapper<FakeBatteryInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ mReader->pushNextDevice(device);
+
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
+ ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
+
+ ASSERT_EQ(mReader->getBatteryCapacity(deviceId), BATTERY_CAPACITY);
+}
+
+TEST_F(InputReaderTest, BatteryGetStatus) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
+ constexpr int32_t eventHubId = 1;
+ const char* DEVICE_LOCATION = "BLUETOOTH";
+ std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
+ FakeBatteryInputMapper& mapper =
+ device->addMapper<FakeBatteryInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ mReader->pushNextDevice(device);
+
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
+ ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
+
+ ASSERT_EQ(mReader->getBatteryStatus(deviceId), BATTERY_STATUS);
+}
+
// --- InputReaderIntegrationTest ---
// These tests create and interact with the InputReader only through its interface.
@@ -2799,6 +2852,32 @@
mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
}
+// --- BatteryInputMapperTest ---
+class BatteryInputMapperTest : public InputMapperTest {
+protected:
+ void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY); }
+};
+
+TEST_F(BatteryInputMapperTest, GetSources) {
+ BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+ ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
+}
+
+TEST_F(BatteryInputMapperTest, GetBatteryCapacity) {
+ BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+ ASSERT_TRUE(mapper.getBatteryCapacity());
+ ASSERT_EQ(*mapper.getBatteryCapacity(), BATTERY_CAPACITY);
+}
+
+TEST_F(BatteryInputMapperTest, GetBatteryStatus) {
+ BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+ ASSERT_TRUE(mapper.getBatteryStatus());
+ ASSERT_EQ(*mapper.getBatteryStatus(), BATTERY_STATUS);
+}
+
// --- KeyboardInputMapperTest ---
class KeyboardInputMapperTest : public InputMapperTest {
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 39ae2fd..ec81ff7 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -377,7 +377,7 @@
displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
- const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId);
+ const nsecs_t actualPresentTime = display->getRefreshTimestamp();
mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime);
mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
actualPresentTime,
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 32e6b10..5219787 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -384,8 +384,8 @@
return NO_ERROR;
}
-void BufferQueueLayer::setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) {
- mFrameTimelineVsyncId = frameTimelineVsyncId;
+void BufferQueueLayer::setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) {
+ mFrameTimelineInfo = frameTimelineInfo;
}
// -----------------------------------------------------------------------
@@ -445,9 +445,8 @@
}
auto surfaceFrame =
- mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId,
- mOwnerPid, mOwnerUid, mName,
- mName);
+ mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid,
+ mOwnerUid, mName, mName);
surfaceFrame->setActualQueueTime(systemTime());
mQueueItems.push_back({item, surfaceFrame});
@@ -485,9 +484,8 @@
}
auto surfaceFrame =
- mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId,
- mOwnerPid, mOwnerUid, mName,
- mName);
+ mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid,
+ mOwnerUid, mName, mName);
surfaceFrame->setActualQueueTime(systemTime());
mQueueItems[mQueueItems.size() - 1].item = item;
mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame);
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 0e8fdbe..41ff012 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -101,7 +101,7 @@
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
- void setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) override;
+ void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) override;
sp<Layer> createClone() override;
@@ -145,10 +145,10 @@
sp<ContentsChangedListener> mContentsChangedListener;
- // The last vsync id received on this layer. This will be used when we get
+ // The last vsync info received on this layer. This will be used when we get
// a buffer to correlate the buffer with the vsync id. Can only be accessed
// with the SF state lock held.
- std::optional<int64_t> mFrameTimelineVsyncId;
+ FrameTimelineInfo mFrameTimelineInfo;
// Keeps track of the time SF latched the last buffer from this layer.
// Used in buffer stuffing analysis in FrameTimeline.
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 0cc15c2..3dc62e3 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -216,8 +216,7 @@
// Returns true if the most recent Transaction applied to CurrentState will be presented.
return (getSidebandStreamChanged() || getAutoRefresh() ||
(mCurrentState.modified &&
- (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))) &&
- !mLayerDetached;
+ (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr)));
}
/* TODO: vhau uncomment once deferred transaction migration complete in
@@ -461,11 +460,6 @@
return willPresent;
}
-void BufferStateLayer::forceSendCallbacks() {
- mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
- mCurrentState.callbackHandles, std::vector<JankData>());
-}
-
bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
mCurrentState.transparentRegionHint = transparent;
mCurrentState.modified = true;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index f638caa..b93d567 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -80,7 +80,6 @@
bool setApi(int32_t api) override;
bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override;
bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override;
- void forceSendCallbacks() override;
bool addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime,
nsecs_t requestedPresentTime) override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
index 6559ed8..4502eee 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
@@ -16,6 +16,7 @@
#pragma once
+#include <ui/Size.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
@@ -71,7 +72,7 @@
virtual void dumpAsString(String8& result) const = 0;
- virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0;
+ virtual void resizeBuffers(const ui::Size&) = 0;
virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
index 31b5f95..168e433 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
@@ -18,6 +18,7 @@
#include <compositionengine/DisplaySurface.h>
#include <gmock/gmock.h>
+#include <ui/Size.h>
#include <utils/String8.h>
namespace android::compositionengine::mock {
@@ -32,7 +33,7 @@
MOCK_METHOD0(advanceFrame, status_t());
MOCK_METHOD0(onFrameCommitted, void());
MOCK_CONST_METHOD1(dumpAsString, void(String8& result));
- MOCK_METHOD2(resizeBuffers, void(uint32_t, uint32_t));
+ MOCK_METHOD1(resizeBuffers, void(const ui::Size&));
MOCK_CONST_METHOD0(getClientTargetAcquireFence, const sp<Fence>&());
};
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index b47f7fd..3bef77d 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -96,8 +96,7 @@
}
void RenderSurface::setDisplaySize(const ui::Size& size) {
- mDisplaySurface->resizeBuffers(static_cast<uint32_t>(size.width),
- static_cast<uint32_t>(size.height));
+ mDisplaySurface->resizeBuffers(size);
mSize = size;
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 3133e90..ab00385 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -85,16 +85,15 @@
MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool());
MOCK_METHOD2(onVsync, bool(hal::HWDisplayId, int64_t));
MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync));
- MOCK_CONST_METHOD1(getRefreshTimestamp, nsecs_t(PhysicalDisplayId));
MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId));
- MOCK_CONST_METHOD1(getModes, DisplayModes(PhysicalDisplayId));
- MOCK_CONST_METHOD1(getActiveMode, DisplayModePtr(PhysicalDisplayId));
+ MOCK_CONST_METHOD1(getModes, std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId));
+ MOCK_CONST_METHOD1(getActiveMode, std::optional<hal::HWConfigId>(PhysicalDisplayId));
MOCK_CONST_METHOD1(getColorModes, std::vector<ui::ColorMode>(PhysicalDisplayId));
MOCK_METHOD3(setActiveColorMode, status_t(PhysicalDisplayId, ui::ColorMode, ui::RenderIntent));
MOCK_CONST_METHOD0(isUsingVrComposer, bool());
MOCK_CONST_METHOD1(getDisplayConnectionType, DisplayConnectionType(PhysicalDisplayId));
MOCK_CONST_METHOD1(isVsyncPeriodSwitchSupported, bool(PhysicalDisplayId));
- MOCK_CONST_METHOD1(getDisplayVsyncPeriod, nsecs_t(PhysicalDisplayId));
+ MOCK_CONST_METHOD2(getDisplayVsyncPeriod, status_t(PhysicalDisplayId, nsecs_t*));
MOCK_METHOD4(setActiveModeWithConstraints,
status_t(PhysicalDisplayId, hal::HWConfigId,
const hal::VsyncPeriodChangeConstraints&,
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index cd39733..5ef5d7b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -119,9 +119,10 @@
*/
TEST_F(RenderSurfaceTest, setDisplaySizeAppliesChange) {
- EXPECT_CALL(*mDisplaySurface, resizeBuffers(640, 480)).Times(1);
+ const ui::Size size(640, 480);
+ EXPECT_CALL(*mDisplaySurface, resizeBuffers(size)).Times(1);
- mSurface.setDisplaySize(ui::Size(640, 480));
+ mSurface.setDisplaySize(size);
}
/*
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b4a3ed1..a785968 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -179,6 +179,31 @@
return nullptr;
}
+nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
+ const auto physicalId = getPhysicalId();
+ if (!mHwComposer.isConnected(physicalId)) {
+ return 0;
+ }
+
+ nsecs_t vsyncPeriod;
+ const auto status = mHwComposer.getDisplayVsyncPeriod(physicalId, &vsyncPeriod);
+ if (status == NO_ERROR) {
+ return vsyncPeriod;
+ }
+
+ return getActiveMode()->getFps().getPeriodNsecs();
+}
+
+nsecs_t DisplayDevice::getRefreshTimestamp() const {
+ const nsecs_t now = systemTime(CLOCK_MONOTONIC);
+ const auto vsyncPeriodNanos = getVsyncPeriodFromHWC();
+ return now - ((now - mLastHwVsync) % vsyncPeriodNanos);
+}
+
+void DisplayDevice::onVsync(nsecs_t timestamp) {
+ mLastHwVsync = timestamp;
+}
+
ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
return mCompositionDisplay->getState().dataspace;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 6f07964..b4db933 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -176,6 +176,10 @@
// set-top boxes after a hotplug reconnect.
DisplayModePtr getMode(DisplayModeId) const;
+ void onVsync(nsecs_t timestamp);
+ nsecs_t getVsyncPeriodFromHWC() const;
+ nsecs_t getRefreshTimestamp() const;
+
// release HWC resources (if any) for removable displays
void disconnect();
@@ -207,6 +211,8 @@
DisplayModeId mActiveModeId;
const DisplayModes mSupportedModes;
+ std::atomic<nsecs_t> mLastHwVsync = 0;
+
// TODO(b/74619554): Remove special cases for primary display.
const bool mIsPrimary;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h
index 61c1b61..31d1245 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayMode.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h
@@ -22,6 +22,7 @@
#include <android-base/stringprintf.h>
#include <android/configuration.h>
+#include <ui/Size.h>
#include <utils/Timers.h>
#include <cstddef>
@@ -113,6 +114,7 @@
int32_t getWidth() const { return mWidth; }
int32_t getHeight() const { return mHeight; }
+ ui::Size getSize() const { return {mWidth, mHeight}; }
Fps getFps() const { return mFps; }
nsecs_t getVsyncPeriod() const { return mFps.getPeriodNsecs(); }
float getDpiX() const { return mDpiX; }
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 3e856bb..f7fc162 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -58,11 +58,10 @@
FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
const sp<IGraphicBufferConsumer>& consumer,
- uint32_t maxWidth, uint32_t maxHeight)
+ const ui::Size& size, const ui::Size& maxSize)
: ConsumerBase(consumer),
mDisplayId(displayId),
- mMaxWidth(maxWidth),
- mMaxHeight(maxHeight),
+ mMaxSize(maxSize),
mCurrentBufferSlot(-1),
mCurrentBuffer(),
mCurrentFence(Fence::NO_FENCE),
@@ -77,15 +76,14 @@
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
GRALLOC_USAGE_HW_RENDER |
GRALLOC_USAGE_HW_COMPOSER);
- const auto& activeMode = mHwc.getActiveMode(displayId);
- ui::Size limitedSize = limitFramebufferSize(activeMode->getWidth(), activeMode->getHeight());
+ const auto limitedSize = limitFramebufferSize(size);
mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
mConsumer->setMaxAcquiredBufferCount(
SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
}
-void FramebufferSurface::resizeBuffers(uint32_t width, uint32_t height) {
- ui::Size limitedSize = limitFramebufferSize(width, height);
+void FramebufferSurface::resizeBuffers(const ui::Size& newSize) {
+ const auto limitedSize = limitFramebufferSize(newSize);
mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
}
@@ -181,24 +179,24 @@
}
}
-ui::Size FramebufferSurface::limitFramebufferSize(uint32_t width, uint32_t height) {
- ui::Size framebufferSize(width, height);
- bool wasLimited = true;
- if (width > mMaxWidth && mMaxWidth != 0) {
- float aspectRatio = float(width) / float(height);
- framebufferSize.height = mMaxWidth / aspectRatio;
- framebufferSize.width = mMaxWidth;
+ui::Size FramebufferSurface::limitFramebufferSize(const ui::Size& size) {
+ ui::Size limitedSize = size;
+ bool wasLimited = false;
+ if (size.width > mMaxSize.width && mMaxSize.width != 0) {
+ const float aspectRatio = static_cast<float>(size.width) / size.height;
+ limitedSize.height = mMaxSize.width / aspectRatio;
+ limitedSize.width = mMaxSize.width;
wasLimited = true;
}
- if (height > mMaxHeight && mMaxHeight != 0) {
- float aspectRatio = float(width) / float(height);
- framebufferSize.height = mMaxHeight;
- framebufferSize.width = mMaxHeight * aspectRatio;
+ if (size.height > mMaxSize.height && mMaxSize.height != 0) {
+ const float aspectRatio = static_cast<float>(size.width) / size.height;
+ limitedSize.height = mMaxSize.height;
+ limitedSize.width = mMaxSize.height * aspectRatio;
wasLimited = true;
}
ALOGI_IF(wasLimited, "framebuffer size has been limited to [%dx%d] from [%dx%d]",
- framebufferSize.width, framebufferSize.height, width, height);
- return framebufferSize;
+ limitedSize.width, limitedSize.height, size.width, size.height);
+ return limitedSize;
}
void FramebufferSurface::dumpAsString(String8& result) const {
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 759943a..5d1e131 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -41,8 +41,8 @@
class FramebufferSurface : public ConsumerBase, public compositionengine::DisplaySurface {
public:
FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
- const sp<IGraphicBufferConsumer>& consumer, uint32_t maxWidth,
- uint32_t maxHeight);
+ const sp<IGraphicBufferConsumer>& consumer, const ui::Size& size,
+ const ui::Size& maxSize);
virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
@@ -50,7 +50,7 @@
virtual void onFrameCommitted();
virtual void dumpAsString(String8& result) const;
- virtual void resizeBuffers(uint32_t width, uint32_t height);
+ virtual void resizeBuffers(const ui::Size&) override;
virtual const sp<Fence>& getClientTargetAcquireFence() const override;
@@ -62,7 +62,7 @@
virtual void dumpLocked(String8& result, const char* prefix) const;
// Limits the width and height by the maximum width specified in the constructor.
- ui::Size limitFramebufferSize(uint32_t width, uint32_t height);
+ ui::Size limitFramebufferSize(const ui::Size&);
// nextBuffer waits for and then latches the next buffer from the
// BufferQueue and releases the previously latched buffer to the
@@ -74,11 +74,7 @@
// Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
// the device.
- const uint32_t mMaxWidth;
-
- // Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
- // the device.
- const uint32_t mMaxHeight;
+ const ui::Size mMaxSize;
// mCurrentBufferIndex is the slot index of the current buffer or
// INVALID_BUFFER_SLOT to indicate that either there is no current buffer
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 46dc54e..b9a8e4b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -223,8 +223,6 @@
__FUNCTION__, to_string(*displayId).c_str());
{
- std::lock_guard lock(displayData.lastHwVsyncLock);
-
// There have been reports of HWCs that signal several vsync events
// with the same timestamp when turning the display off and on. This
// is a bug in the HWC implementation, but filter the extra events
@@ -295,11 +293,10 @@
hal::DisplayType::PHYSICAL);
newDisplay->setConnected(true);
displayData.hwcDisplay = std::move(newDisplay);
- loadModes(displayData, hwcDisplayId);
}
int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
- hal::Attribute attribute) {
+ hal::Attribute attribute) const {
int32_t value = 0;
auto error = static_cast<hal::Error>(
mComposer->getDisplayAttribute(hwcDisplayId, configId, attribute, &value));
@@ -308,30 +305,6 @@
return value;
}
-void HWComposer::loadModes(DisplayData& displayData, hal::HWDisplayId hwcDisplayId) {
- ALOGV("[HWC display %" PRIu64 "] %s", hwcDisplayId, __FUNCTION__);
-
- std::vector<hal::HWConfigId> configIds;
- auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
- RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId));
-
- displayData.modes.clear();
- for (auto configId : configIds) {
- auto mode = DisplayMode::Builder(configId)
- .setId(DisplayModeId(displayData.modes.size()))
- .setWidth(getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH))
- .setHeight(getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT))
- .setVsyncPeriod(getAttribute(hwcDisplayId, configId,
- hal::Attribute::VSYNC_PERIOD))
- .setDpiX(getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X))
- .setDpiY(getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y))
- .setConfigGroup(getAttribute(hwcDisplayId, configId,
- hal::Attribute::CONFIG_GROUP))
- .build();
- displayData.modes.push_back(std::move(mode));
- }
-}
-
HWC2::Layer* HWComposer::createLayer(HalDisplayId displayId) {
RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
@@ -348,55 +321,50 @@
RETURN_IF_HWC_ERROR(error, displayId);
}
-nsecs_t HWComposer::getRefreshTimestamp(PhysicalDisplayId displayId) const {
- RETURN_IF_INVALID_DISPLAY(displayId, 0);
- const auto& displayData = mDisplayData.at(displayId);
- // this returns the last refresh timestamp.
- // if the last one is not available, we estimate it based on
- // the refresh period and whatever closest timestamp we have.
- std::lock_guard lock(displayData.lastHwVsyncLock);
- nsecs_t now = systemTime(CLOCK_MONOTONIC);
- auto vsyncPeriodNanos = getDisplayVsyncPeriod(displayId);
- return now - ((now - displayData.lastHwVsync) % vsyncPeriodNanos);
-}
-
bool HWComposer::isConnected(PhysicalDisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, false);
return mDisplayData.at(displayId).hwcDisplay->isConnected();
}
-DisplayModes HWComposer::getModes(PhysicalDisplayId displayId) const {
+std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, {});
- // We cache the modes when the DisplayData is created on hotplug. If the modes need to
- // change HWC will send a hotplug event which will recreate displayData.
- return mDisplayData.at(displayId).modes;
+ const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId();
+ std::vector<hal::HWConfigId> configIds;
+ auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
+ RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {});
+
+ std::vector<HWCDisplayMode> modes;
+ modes.reserve(configIds.size());
+ for (auto configId : configIds) {
+ modes.push_back(HWCDisplayMode{
+ .hwcId = configId,
+ .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH),
+ .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT),
+ .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD),
+ .dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X),
+ .dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y),
+ .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
+ });
+ }
+
+ return modes;
}
-DisplayModePtr HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
- RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
+std::optional<hal::HWConfigId> HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
const auto hwcId = *fromPhysicalDisplayId(displayId);
ALOGV("[%" PRIu64 "] getActiveMode", hwcId);
hal::HWConfigId configId;
auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
- const auto& modes = mDisplayData.at(displayId).modes;
if (error == hal::Error::BAD_CONFIG) {
LOG_DISPLAY_ERROR(displayId, "No active mode");
- return nullptr;
+ return std::nullopt;
}
- RETURN_IF_HWC_ERROR(error, displayId, nullptr);
-
- const auto it = std::find_if(modes.begin(), modes.end(),
- [configId](auto mode) { return mode->getHwcId() == configId; });
- if (it == modes.end()) {
- LOG_DISPLAY_ERROR(displayId, "Unknown mode");
- return nullptr;
- }
-
- return *it;
+ return configId;
}
// Composer 2.4
@@ -421,27 +389,20 @@
return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
}
-nsecs_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId) const {
+status_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+ nsecs_t* outVsyncPeriod) const {
RETURN_IF_INVALID_DISPLAY(displayId, 0);
- if (isVsyncPeriodSwitchSupported(displayId)) {
- const auto hwcId = *fromPhysicalDisplayId(displayId);
- Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
- auto error =
- static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
- RETURN_IF_HWC_ERROR(error, displayId, 0);
- return static_cast<nsecs_t>(vsyncPeriodNanos);
+ if (!isVsyncPeriodSwitchSupported(displayId)) {
+ return INVALID_OPERATION;
}
-
- // Get the default vsync period
- auto mode = getActiveMode(displayId);
-
- if (!mode) {
- // HWC has updated the display modes and hasn't notified us yet.
- RETURN_IF_HWC_ERROR(hal::Error::BAD_CONFIG, displayId, 0);
- }
-
- return mode->getVsyncPeriod();
+ const auto hwcId = *fromPhysicalDisplayId(displayId);
+ Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
+ auto error =
+ static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
+ RETURN_IF_HWC_ERROR(error, displayId, 0);
+ *outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos);
+ return NO_ERROR;
}
std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 1ffe276..f9c8e2e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -83,6 +83,16 @@
ClientTargetProperty clientTargetProperty;
};
+ struct HWCDisplayMode {
+ hal::HWConfigId hwcId;
+ int32_t width = -1;
+ int32_t height = -1;
+ nsecs_t vsyncPeriod = -1;
+ int32_t dpiX = -1;
+ int32_t dpiY = -1;
+ int32_t configGroup = -1;
+ };
+
virtual ~HWComposer();
virtual void setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) = 0;
@@ -182,12 +192,11 @@
virtual bool onVsync(hal::HWDisplayId, int64_t timestamp) = 0;
virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0;
- virtual nsecs_t getRefreshTimestamp(PhysicalDisplayId) const = 0;
virtual bool isConnected(PhysicalDisplayId) const = 0;
- virtual DisplayModes getModes(PhysicalDisplayId) const = 0;
+ virtual std::vector<HWCDisplayMode> getModes(PhysicalDisplayId) const = 0;
- virtual DisplayModePtr getActiveMode(PhysicalDisplayId) const = 0;
+ virtual std::optional<hal::HWConfigId> getActiveMode(PhysicalDisplayId) const = 0;
virtual std::vector<ui::ColorMode> getColorModes(PhysicalDisplayId) const = 0;
@@ -197,7 +206,8 @@
// Composer 2.4
virtual DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const = 0;
virtual bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const = 0;
- virtual nsecs_t getDisplayVsyncPeriod(PhysicalDisplayId) const = 0;
+ virtual status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+ nsecs_t* outVsyncPeriod) const = 0;
virtual status_t setActiveModeWithConstraints(PhysicalDisplayId, hal::HWConfigId,
const hal::VsyncPeriodChangeConstraints&,
hal::VsyncPeriodChangeTimeline* outTimeline) = 0;
@@ -314,12 +324,11 @@
bool onVsync(hal::HWDisplayId, int64_t timestamp) override;
void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override;
- nsecs_t getRefreshTimestamp(PhysicalDisplayId) const override;
bool isConnected(PhysicalDisplayId) const override;
- DisplayModes getModes(PhysicalDisplayId) const override;
+ std::vector<HWCDisplayMode> getModes(PhysicalDisplayId) const override;
- DisplayModePtr getActiveMode(PhysicalDisplayId) const override;
+ std::optional<hal::HWConfigId> getActiveMode(PhysicalDisplayId) const override;
std::vector<ui::ColorMode> getColorModes(PhysicalDisplayId) const override;
@@ -328,7 +337,8 @@
// Composer 2.4
DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const override;
bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const override;
- nsecs_t getDisplayVsyncPeriod(PhysicalDisplayId displayId) const override;
+ status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+ nsecs_t* outVsyncPeriod) const override;
status_t setActiveModeWithConstraints(PhysicalDisplayId, hal::HWConfigId,
const hal::VsyncPeriodChangeConstraints&,
hal::VsyncPeriodChangeTimeline* outTimeline) override;
@@ -365,7 +375,6 @@
std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
buffer_handle_t outbufHandle = nullptr;
sp<Fence> outbufAcquireFence = Fence::NO_FENCE;
- DisplayModes modes;
bool validateWasSkipped;
hal::Error presentError;
@@ -375,8 +384,7 @@
std::mutex vsyncEnabledLock;
hal::Vsync vsyncEnabled GUARDED_BY(vsyncEnabledLock) = hal::Vsync::DISABLE;
- mutable std::mutex lastHwVsyncLock;
- nsecs_t lastHwVsync GUARDED_BY(lastHwVsyncLock) = 0;
+ nsecs_t lastHwVsync = 0;
};
std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId);
@@ -384,8 +392,7 @@
bool shouldIgnoreHotplugConnect(hal::HWDisplayId, bool hasDisplayIdentificationData) const;
int32_t getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
- hal::Attribute attribute);
- void loadModes(DisplayData& displayData, hal::HWDisplayId hwcDisplayId);
+ hal::Attribute attribute) const;
void loadCapabilities();
void loadLayerMetadataSupport();
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 2ac67cb..e26ab11 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -291,11 +291,11 @@
void VirtualDisplaySurface::dumpAsString(String8& /* result */) const {
}
-void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) {
- mQueueBufferOutput.width = w;
- mQueueBufferOutput.height = h;
- mSinkBufferWidth = w;
- mSinkBufferHeight = h;
+void VirtualDisplaySurface::resizeBuffers(const ui::Size& newSize) {
+ mQueueBufferOutput.width = newSize.width;
+ mQueueBufferOutput.height = newSize.height;
+ mSinkBufferWidth = newSize.width;
+ mSinkBufferHeight = newSize.height;
}
const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const {
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index fba0e3b..bbb6306 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -90,7 +90,7 @@
virtual status_t advanceFrame();
virtual void onFrameCommitted();
virtual void dumpAsString(String8& result) const;
- virtual void resizeBuffers(const uint32_t w, const uint32_t h);
+ virtual void resizeBuffers(const ui::Size&) override;
virtual const sp<Fence>& getClientTargetAcquireFence() const override;
private:
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 17d1f3b..3743716 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -275,13 +275,15 @@
return ++mTraceCookie;
}
-SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
- std::string debugName, PredictionState predictionState,
+SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid,
+ uid_t ownerUid, std::string layerName, std::string debugName,
+ PredictionState predictionState,
frametimeline::TimelineItem&& predictions,
std::shared_ptr<TimeStats> timeStats,
JankClassificationThresholds thresholds,
TraceCookieCounter* traceCookieCounter)
- : mToken(token),
+ : mToken(frameTimelineInfo.vsyncId),
+ mInputEventId(frameTimelineInfo.inputEventId),
mOwnerPid(ownerPid),
mOwnerUid(ownerUid),
mLayerName(std::move(layerName)),
@@ -295,27 +297,27 @@
mTraceCookieCounter(*traceCookieCounter) {}
void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mActuals.startTime = actualStartTime;
}
void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mActualQueueTime = actualQueueTime;
}
void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
}
void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mPresentState = presentState;
mLastLatchTime = lastLatchTime;
}
std::optional<int32_t> SurfaceFrame::getJankType() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
if (mActuals.presentTime == 0) {
return std::nullopt;
}
@@ -323,32 +325,32 @@
}
nsecs_t SurfaceFrame::getBaseTime() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return getMinTime(mPredictionState, mPredictions, mActuals);
}
TimelineItem SurfaceFrame::getActuals() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mActuals;
}
SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mPresentState;
}
FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mFramePresentMetadata;
}
FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mFrameReadyMetadata;
}
void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
StringAppendF(&result, "%s", indent.c_str());
StringAppendF(&result, "Layer - %s", mDebugName.c_str());
if (mJankType != JankType::None) {
@@ -387,7 +389,7 @@
void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType,
nsecs_t vsyncPeriod) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
if (mPresentState != PresentState::Presented) {
// No need to update dropped buffers
return;
@@ -479,6 +481,9 @@
mTimeStats->incrementJankyFrames(mOwnerUid, mLayerName, mJankType);
}
+/**
+ * TODO(b/178637512): add inputEventId to the perfetto trace.
+ */
void SurfaceFrame::trace(int64_t displayFrameToken) {
using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;
@@ -486,12 +491,12 @@
bool missingToken = false;
// Expected timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
- if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+ std::scoped_lock lock(mMutex);
+ if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
ALOGD("Cannot trace SurfaceFrame - %s with invalid token", mLayerName.c_str());
missingToken = true;
return;
- } else if (displayFrameToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+ } else if (displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
ALOGD("Cannot trace SurfaceFrame - %s with invalid displayFrameToken",
mLayerName.c_str());
missingToken = true;
@@ -521,7 +526,7 @@
// Expected timeline end
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime));
@@ -535,7 +540,7 @@
int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
// Actual timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
// Actual start time is not yet available, so use expected start instead
@@ -566,7 +571,7 @@
});
// Actual timeline end
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime));
@@ -582,7 +587,7 @@
int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
const int64_t assignedToken = mCurrentToken++;
mPredictions[assignedToken] = {systemTime(), predictions};
flushTokens(systemTime());
@@ -590,7 +595,7 @@
}
std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto predictionsIterator = mPredictions.find(token);
if (predictionsIterator != mPredictions.end()) {
return predictionsIterator->second.predictions;
@@ -634,26 +639,28 @@
}
std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
- std::optional<int64_t> token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
- std::string debugName) {
+ const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+ std::string layerName, std::string debugName) {
ATRACE_CALL();
- if (!token) {
- return std::make_shared<SurfaceFrame>(ISurfaceComposer::INVALID_VSYNC_ID, ownerPid,
- ownerUid, std::move(layerName), std::move(debugName),
+ if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
+ return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+ std::move(layerName), std::move(debugName),
PredictionState::None, TimelineItem(), mTimeStats,
mJankClassificationThresholds, &mTraceCookieCounter);
}
- std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token);
+ std::optional<TimelineItem> predictions =
+ mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
if (predictions) {
- return std::make_shared<SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName),
- std::move(debugName), PredictionState::Valid,
- std::move(*predictions), mTimeStats,
- mJankClassificationThresholds, &mTraceCookieCounter);
+ return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+ std::move(layerName), std::move(debugName),
+ PredictionState::Valid, std::move(*predictions),
+ mTimeStats, mJankClassificationThresholds,
+ &mTraceCookieCounter);
}
- return std::make_shared<SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName),
- std::move(debugName), PredictionState::Expired,
- TimelineItem(), mTimeStats, mJankClassificationThresholds,
- &mTraceCookieCounter);
+ return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+ std::move(layerName), std::move(debugName),
+ PredictionState::Expired, TimelineItem(), mTimeStats,
+ mJankClassificationThresholds, &mTraceCookieCounter);
}
FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
@@ -669,13 +676,13 @@
void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
}
void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, nsecs_t vsyncPeriod) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mCurrentDisplayFrame->onSfWakeUp(token, vsyncPeriod,
mTokenManager.getPredictionsForToken(token), wakeUpTime);
}
@@ -683,7 +690,7 @@
void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
const std::shared_ptr<FenceTime>& presentFence) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
flushPendingPresentFences();
@@ -826,7 +833,7 @@
// Expected timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
auto packet = ctx.NewTracePacket();
- if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+ if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
ALOGD("Cannot trace DisplayFrame with invalid token");
missingToken = true;
return;
@@ -999,7 +1006,7 @@
}
void FrameTimeline::dumpAll(std::string& result) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
for (size_t i = 0; i < mDisplayFrames.size(); i++) {
@@ -1009,7 +1016,7 @@
}
void FrameTimeline::dumpJank(std::string& result) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
for (size_t i = 0; i < mDisplayFrames.size(); i++) {
mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
@@ -1031,7 +1038,7 @@
}
void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
// The size can either increase or decrease, clear everything, to be consistent
mDisplayFrames.clear();
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index ed38cc6..54e8efb 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -154,10 +154,10 @@
// Only FrameTimeline can construct a SurfaceFrame as it provides Predictions(through
// TokenManager), Thresholds and TimeStats pointer.
- SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
- std::string debugName, PredictionState predictionState, TimelineItem&& predictions,
- std::shared_ptr<TimeStats> timeStats, JankClassificationThresholds thresholds,
- TraceCookieCounter* traceCookieCounter);
+ SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+ std::string layerName, std::string debugName, PredictionState predictionState,
+ TimelineItem&& predictions, std::shared_ptr<TimeStats> timeStats,
+ JankClassificationThresholds thresholds, TraceCookieCounter* traceCookieCounter);
~SurfaceFrame() = default;
// Returns std::nullopt if the frame hasn't been classified yet.
@@ -166,6 +166,7 @@
// Functions called by SF
int64_t getToken() const { return mToken; };
+ int32_t getInputEventId() const { return mInputEventId; };
TimelineItem getPredictions() const { return mPredictions; };
// Actual timestamps of the app are set individually at different functions.
// Start time (if the app provides) and Queue time are accessible after queueing the frame,
@@ -198,6 +199,7 @@
private:
const int64_t mToken;
+ const int32_t mInputEventId;
const pid_t mOwnerPid;
const uid_t mOwnerUid;
const std::string mLayerName;
@@ -243,10 +245,9 @@
// Create a new surface frame, set the predictions based on a token and return it to the caller.
// Debug name is the human-readable debugging string for dumpsys.
- virtual std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(std::optional<int64_t> token,
- pid_t ownerPid, uid_t ownerUid,
- std::string layerName,
- std::string debugName) = 0;
+ virtual std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(
+ const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+ std::string layerName, std::string debugName) = 0;
// Adds a new SurfaceFrame to the current DisplayFrame. Frames from multiple layers can be
// composited into one display frame.
@@ -279,7 +280,7 @@
class TokenManager : public android::frametimeline::TokenManager {
public:
- TokenManager() : mCurrentToken(ISurfaceComposer::INVALID_VSYNC_ID + 1) {}
+ TokenManager() : mCurrentToken(FrameTimelineInfo::INVALID_VSYNC_ID + 1) {}
~TokenManager() = default;
int64_t generateTokenForPredictions(TimelineItem&& predictions) override;
@@ -353,7 +354,7 @@
private:
void dump(std::string& result, nsecs_t baseTime) const;
- int64_t mToken = ISurfaceComposer::INVALID_VSYNC_ID;
+ int64_t mToken = FrameTimelineInfo::INVALID_VSYNC_ID;
/* Usage of TimelineItem w.r.t SurfaceFlinger
* startTime Time when SurfaceFlinger wakes up to handle transactions and buffer updates
@@ -393,10 +394,9 @@
~FrameTimeline() = default;
frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
- std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(std::optional<int64_t> token,
- pid_t ownerPid, uid_t ownerUid,
- std::string layerName,
- std::string debugName) override;
+ std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(
+ const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+ std::string layerName, std::string debugName) override;
void addSurfaceFrame(std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame) override;
void setSfWakeUp(int64_t token, nsecs_t wakeupTime, nsecs_t vsyncPeriod) override;
void setSfPresent(nsecs_t sfPresentTime,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 177a81a..08a5f0f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -129,7 +129,7 @@
mCurrentState.shadowRadius = 0.f;
mCurrentState.treeHasFrameRateVote = false;
mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID;
- mCurrentState.frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+ mCurrentState.frameTimelineInfo = {};
mCurrentState.postTime = -1;
if (args.flags & ISurfaceComposerClient::eNoColorFill) {
@@ -907,14 +907,10 @@
}
if (stateUpdateAvailable) {
- const auto vsyncId =
- stateToCommit->frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID
- ? std::nullopt
- : std::make_optional(stateToCommit->frameTimelineVsyncId);
-
mSurfaceFrame =
- mFlinger->mFrameTimeline->createSurfaceFrameForToken(vsyncId, mOwnerPid, mOwnerUid,
- mName, mTransactionName);
+ mFlinger->mFrameTimeline
+ ->createSurfaceFrameForToken(stateToCommit->frameTimelineInfo, mOwnerPid,
+ mOwnerUid, mName, mTransactionName);
mSurfaceFrame->setActualQueueTime(stateToCommit->postTime);
// For transactions we set the acquire fence time to the post time as we
// don't have a buffer. For BufferStateLayer it is overridden in
@@ -1004,19 +1000,6 @@
uint32_t Layer::doTransaction(uint32_t flags) {
ATRACE_CALL();
- if (mLayerDetached) {
- // Ensure BLAST buffer callbacks are processed.
- // detachChildren and mLayerDetached were implemented to avoid geometry updates
- // to layers in the cases of animation. For BufferQueue layers buffers are still
- // consumed as normal. This is useful as otherwise the client could get hung
- // inevitably waiting on a buffer to return. We recreate this semantic for BufferQueue
- // even though it is a little consistent. detachChildren is shortly slated for removal
- // by the hierarchy mirroring work so we don't need to worry about it too much.
- forceSendCallbacks();
- mCurrentState.callbackHandles = {};
- return flags;
- }
-
if (mChildrenChanged) {
flags |= eVisibleRegion;
mChildrenChanged = false;
@@ -1491,8 +1474,8 @@
return true;
}
-void Layer::setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime) {
- mCurrentState.frameTimelineVsyncId = frameTimelineVsyncId;
+void Layer::setFrameTimelineInfoForTransaction(const FrameTimelineInfo& info, nsecs_t postTime) {
+ mCurrentState.frameTimelineInfo = info;
mCurrentState.postTime = postTime;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -1523,12 +1506,6 @@
void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
ATRACE_CALL();
- if (mLayerDetached) {
- // If the layer is detached, then we don't defer this transaction since we will not
- // commit the pending state while the layer is detached. Adding sync points may cause
- // the barrier layer to wait for the states to be committed before dequeuing a buffer.
- return;
- }
mCurrentState.barrierLayer_legacy = barrierLayer;
mCurrentState.barrierFrameNumber = frameNumber;
@@ -1814,10 +1791,6 @@
}
void Layer::reparentChildren(const sp<Layer>& newParent) {
- if (attachChildren()) {
- setTransactionFlags(eTransactionNeeded);
- }
-
for (const sp<Layer>& child : mCurrentChildren) {
newParent->addChild(child);
}
@@ -1853,17 +1826,6 @@
}
bool Layer::reparent(const sp<IBinder>& newParentHandle) {
- bool callSetTransactionFlags = false;
-
- // While layers are detached, we allow most operations
- // and simply halt performing the actual transaction. However
- // for reparent != null we would enter the mRemovedFromCurrentState
- // state, regardless of whether doTransaction was called, and
- // so we need to prevent the update here.
- if (mLayerDetached && newParentHandle == nullptr) {
- return false;
- }
-
sp<Layer> newParent;
if (newParentHandle != nullptr) {
auto handle = static_cast<Handle*>(newParentHandle.get());
@@ -1890,52 +1852,13 @@
} else {
onRemovedFromCurrentState();
}
-
- if (mLayerDetached) {
- mLayerDetached = false;
- callSetTransactionFlags = true;
- }
} else {
onRemovedFromCurrentState();
}
- if (attachChildren() || callSetTransactionFlags) {
- setTransactionFlags(eTransactionNeeded);
- }
return true;
}
-bool Layer::detachChildren() {
- for (const sp<Layer>& child : mCurrentChildren) {
- sp<Client> parentClient = mClientRef.promote();
- sp<Client> client(child->mClientRef.promote());
- if (client != nullptr && parentClient != client) {
- child->mLayerDetached = true;
- child->detachChildren();
- child->removeRemoteSyncPoints();
- }
- }
-
- return true;
-}
-
-bool Layer::attachChildren() {
- bool changed = false;
- for (const sp<Layer>& child : mCurrentChildren) {
- sp<Client> parentClient = mClientRef.promote();
- sp<Client> client(child->mClientRef.promote());
- if (client != nullptr && parentClient != client) {
- if (child->mLayerDetached) {
- child->mLayerDetached = false;
- child->attachChildren();
- changed = true;
- }
- }
- }
-
- return changed;
-}
-
bool Layer::setColorTransform(const mat4& matrix) {
static const mat4 identityMatrix = mat4();
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 357c4a4..4b40c8e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -304,8 +304,8 @@
// a fixed transform hint is not set.
ui::Transform::RotationFlags fixedTransformHint;
- // The vsync id that was used to start the transaction
- int64_t frameTimelineVsyncId;
+ // The vsync info that was used to start the transaction
+ FrameTimelineInfo frameTimelineInfo;
// When the transaction was posted
nsecs_t postTime;
@@ -434,7 +434,6 @@
virtual bool setMetadata(const LayerMetadata& data);
virtual void setChildrenDrawingParent(const sp<Layer>&);
virtual bool reparent(const sp<IBinder>& newParentHandle);
- virtual bool detachChildren();
virtual bool setColorTransform(const mat4& matrix);
virtual mat4 getColorTransform() const;
virtual bool hasColorTransform() const;
@@ -461,7 +460,6 @@
const std::vector<sp<CallbackHandle>>& /*handles*/) {
return false;
};
- virtual void forceSendCallbacks() {}
virtual bool addFrameEvent(const sp<Fence>& /*acquireFence*/, nsecs_t /*postedTime*/,
nsecs_t /*requestedPresentTime*/) {
return false;
@@ -666,8 +664,6 @@
bool reparentChildren(const sp<IBinder>& newParentHandle);
void reparentChildren(const sp<Layer>& newParent);
- bool attachChildren();
- bool isLayerDetached() const { return mLayerDetached; }
bool setShadowRadius(float shadowRadius);
// Before color management is introduced, contents on Android have to be
@@ -869,8 +865,9 @@
bool setFrameRate(FrameRate);
- virtual void setFrameTimelineVsyncForBuffer(int64_t /*frameTimelineVsyncId*/) {}
- void setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime);
+ virtual void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& /*info*/) {}
+ void setFrameTimelineInfoForTransaction(const FrameTimelineInfo& frameTimelineInfo,
+ nsecs_t postTime);
// Creates a new handle each time, so we only expect
// this to be called once.
@@ -1103,8 +1100,6 @@
wp<Layer> mDrawingParent;
// Can only be accessed with the SF state lock held.
- bool mLayerDetached{false};
- // Can only be accessed with the SF state lock held.
bool mChildrenChanged{false};
// Window types from WindowManager.LayoutParams
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 19b3d6e..9186538 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -451,7 +451,7 @@
const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
- true /* regionSampling */, captureListener);
+ true /* regionSampling */, false /* grayscale */, captureListener);
ScreenCaptureResults captureResults = captureListener->waitForResults();
std::vector<Descriptor> activeDescriptors;
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index c12a7b1..f90c130 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -303,6 +303,10 @@
std::lock_guard<std::mutex> lock(mMutex);
const auto request = rate == 0 ? VSyncRequest::None : static_cast<VSyncRequest>(rate);
+ if (request != VSyncRequest::None && connection->resyncCallback) {
+ connection->resyncCallback();
+ }
+
if (connection->vsyncRequest != request) {
connection->vsyncRequest = request;
mCondition.notify_all();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a6b05d0..e9b5875 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -68,6 +68,7 @@
#include <ui/ColorSpace.h>
#include <ui/DebugUtils.h>
#include <ui/DisplayConfig.h>
+#include <ui/DisplayId.h>
#include <ui/DisplayInfo.h>
#include <ui/DisplayStatInfo.h>
#include <ui/DisplayState.h>
@@ -275,7 +276,6 @@
const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
const String16 sRotateSurfaceFlinger("android.permission.ROTATE_SURFACE_FLINGER");
const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
-const String16 sUseBackgroundBlur("android.permission.USE_BACKGROUND_BLUR");
const String16 sDump("android.permission.DUMP");
const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
@@ -333,10 +333,6 @@
PermissionCache::checkPermission(sRotateSurfaceFlinger, pid, uid);
}
-bool originalCallerCanUseBlurs(int originPid, int originUid) {
- return PermissionCache::checkPermission(sUseBackgroundBlur, originPid, originUid);
-}
-
SurfaceFlingerBE::SurfaceFlingerBE() : mHwcServiceName(getHwcServiceName()) {}
SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
@@ -1586,12 +1582,11 @@
}
nsecs_t SurfaceFlinger::getVsyncPeriodFromHWC() const {
- const auto displayId = getInternalDisplayIdLocked();
- if (!displayId || !getHwComposer().isConnected(*displayId)) {
- return 0;
+ if (const auto display = getDefaultDisplayDeviceLocked()) {
+ return display->getVsyncPeriodFromHWC();
}
- return getHwComposer().getDisplayVsyncPeriod(*displayId);
+ return 0;
}
void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
@@ -1605,6 +1600,12 @@
return;
}
+ if (const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId)) {
+ auto token = getPhysicalDisplayTokenLocked(*displayId);
+ auto display = getDisplayDeviceLocked(token);
+ display->onVsync(timestamp);
+ }
+
if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) {
return;
}
@@ -1943,19 +1944,16 @@
bool SurfaceFlinger::handleMessageTransaction() {
ATRACE_CALL();
+
+ if (getTransactionFlags(eTransactionFlushNeeded)) {
+ flushTransactionQueues();
+ }
uint32_t transactionFlags = peekTransactionFlags();
-
- bool flushedATransaction = flushTransactionQueues();
-
bool runHandleTransaction =
- (transactionFlags && (transactionFlags != eTransactionFlushNeeded)) ||
- flushedATransaction ||
- mForceTraversal;
+ ((transactionFlags & (~eTransactionFlushNeeded)) != 0) || mForceTraversal;
if (runHandleTransaction) {
handleTransaction(eTransactionMask);
- } else {
- getTransactionFlags(eTransactionFlushNeeded);
}
if (transactionFlushNeeded()) {
@@ -2223,8 +2221,7 @@
} else if (isDisplayConnected) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
- const nsecs_t presentTime =
- getHwComposer().getRefreshTimestamp(display->getPhysicalId());
+ const nsecs_t presentTime = display->getRefreshTimestamp();
mAnimFrameTracker.setActualPresentTime(presentTime);
}
mAnimFrameTracker.advanceFrame();
@@ -2361,6 +2358,24 @@
// here the transaction has been committed
}
+DisplayModes SurfaceFlinger::loadSupportedDisplayModes(PhysicalDisplayId displayId) const {
+ const auto hwcModes = getHwComposer().getModes(displayId);
+ DisplayModes modes;
+ size_t nextModeId = 0;
+ for (const auto& hwcMode : hwcModes) {
+ modes.push_back(DisplayMode::Builder(hwcMode.hwcId)
+ .setId(DisplayModeId{nextModeId++})
+ .setWidth(hwcMode.width)
+ .setHeight(hwcMode.height)
+ .setVsyncPeriod(hwcMode.vsyncPeriod)
+ .setDpiX(hwcMode.dpiX)
+ .setDpiY(hwcMode.dpiY)
+ .setConfigGroup(hwcMode.configGroup)
+ .build());
+ }
+ return modes;
+}
+
void SurfaceFlinger::processDisplayHotplugEventsLocked() {
for (const auto& event : mPendingHotplugEvents) {
std::optional<DisplayIdentificationInfo> info =
@@ -2374,8 +2389,14 @@
const auto it = mPhysicalDisplayTokens.find(displayId);
if (event.connection == hal::Connection::CONNECTED) {
- auto supportedModes = getHwComposer().getModes(displayId);
- const auto activeMode = getHwComposer().getActiveMode(displayId);
+ auto supportedModes = loadSupportedDisplayModes(displayId);
+ const auto activeModeHwcId = getHwComposer().getActiveMode(displayId);
+ LOG_ALWAYS_FATAL_IF(!activeModeHwcId, "HWC returned no active config");
+
+ const auto activeMode = *std::find_if(supportedModes.begin(), supportedModes.end(),
+ [activeModeHwcId](const DisplayModePtr& mode) {
+ return mode->getHwcId() == *activeModeHwcId;
+ });
// TODO(b/175678215) Handle the case when activeMode is not in supportedModes
if (it == mPhysicalDisplayTokens.end()) {
@@ -2526,17 +2547,15 @@
void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
const DisplayDeviceState& state) {
- int width = 0;
- int height = 0;
+ ui::Size resolution(0, 0);
ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
if (state.physical) {
- width = state.physical->activeMode->getWidth();
- height = state.physical->activeMode->getHeight();
+ resolution = state.physical->activeMode->getSize();
pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888);
} else if (state.surface != nullptr) {
- int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width);
+ int status = state.surface->query(NATIVE_WINDOW_WIDTH, &resolution.width);
ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status);
- status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height);
+ status = state.surface->query(NATIVE_WINDOW_HEIGHT, &resolution.height);
ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status);
int intPixelFormat;
status = state.surface->query(NATIVE_WINDOW_FORMAT, &intPixelFormat);
@@ -2553,7 +2572,7 @@
if (const auto& physical = state.physical) {
builder.setPhysical({physical->id, physical->type});
}
- builder.setPixels(ui::Size(width, height));
+ builder.setPixels(resolution);
builder.setPixelFormat(pixelFormat);
builder.setIsSecure(state.isSecure);
builder.setLayerStackId(state.layerStack);
@@ -2588,7 +2607,8 @@
const auto physicalId = PhysicalDisplayId::tryCast(displayId);
LOG_FATAL_IF(!physicalId);
displaySurface = new FramebufferSurface(getHwComposer(), *physicalId, bqConsumer,
- maxGraphicsWidth, maxGraphicsHeight);
+ state.physical->activeMode->getSize(),
+ ui::Size(maxGraphicsWidth, maxGraphicsHeight));
producer = bqProducer;
}
@@ -2864,7 +2884,6 @@
});
}
- commitInputWindowCommands();
commitTransaction();
}
@@ -2905,11 +2924,6 @@
: nullptr);
}
-void SurfaceFlinger::commitInputWindowCommands() {
- mInputWindowCommands.merge(mPendingInputWindowCommands);
- mPendingInputWindowCommands.clear();
-}
-
void SurfaceFlinger::updateCursorAsync() {
compositionengine::CompositionRefreshArgs refreshArgs;
for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
@@ -3272,17 +3286,16 @@
mForceTraversal = true;
}
-bool SurfaceFlinger::flushTransactionQueues() {
+void SurfaceFlinger::flushTransactionQueues() {
// to prevent onHandleDestroyed from being called while the lock is held,
// we must keep a copy of the transactions (specifically the composer
// states) around outside the scope of the lock
std::vector<const TransactionState> transactions;
- bool flushedATransaction = false;
{
- Mutex::Autolock _l(mStateLock);
-
- auto it = mTransactionQueues.begin();
- while (it != mTransactionQueues.end()) {
+ Mutex::Autolock _l(mQueueLock);
+ // Collect transactions from pending transaction queue.
+ auto it = mPendingTransactionQueues.begin();
+ while (it != mPendingTransactionQueues.end()) {
auto& [applyToken, transactionQueue] = *it;
while (!transactionQueue.empty()) {
@@ -3294,31 +3307,55 @@
break;
}
transactions.push_back(transaction);
- applyTransactionState(transaction.frameTimelineVsyncId, transaction.states,
- transaction.displays, transaction.flags,
- mPendingInputWindowCommands, transaction.desiredPresentTime,
- transaction.isAutoTimestamp, transaction.buffer,
- transaction.postTime, transaction.privileged,
- transaction.hasListenerCallbacks,
- transaction.listenerCallbacks, transaction.originPid,
- transaction.originUid, transaction.id, /*isMainThread*/ true);
transactionQueue.pop();
- flushedATransaction = true;
}
if (transactionQueue.empty()) {
- it = mTransactionQueues.erase(it);
- mTransactionCV.broadcast();
+ it = mPendingTransactionQueues.erase(it);
+ mTransactionQueueCV.broadcast();
} else {
it = std::next(it, 1);
}
}
+
+ // Collect transactions from current transaction queue or queue to pending transactions.
+ // Case 1: push to pending when transactionIsReadyToBeApplied is false.
+ // Case 2: push to pending when there exist a pending queue.
+ // Case 3: others are ready to apply.
+ while (!mTransactionQueue.empty()) {
+ const auto& transaction = mTransactionQueue.front();
+ bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) !=
+ mPendingTransactionQueues.end();
+ // Call transactionIsReadyToBeApplied first in case we need to
+ // incrementPendingBufferCount if the transaction contains a buffer.
+ if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
+ transaction.desiredPresentTime, transaction.states,
+ true) ||
+ pendingTransactions) {
+ mPendingTransactionQueues[transaction.applyToken].push(transaction);
+ } else {
+ transactions.push_back(transaction);
+ }
+ mTransactionQueue.pop();
+ }
}
- return flushedATransaction;
+
+ // Now apply all transactions.
+ Mutex::Autolock _l(mStateLock);
+ for (const auto& transaction : transactions) {
+ applyTransactionState(transaction.frameTimelineInfo, transaction.states,
+ transaction.displays, transaction.flags,
+ transaction.inputWindowCommands, transaction.desiredPresentTime,
+ transaction.isAutoTimestamp, transaction.buffer, transaction.postTime,
+ transaction.privileged, transaction.hasListenerCallbacks,
+ transaction.listenerCallbacks, transaction.originPid,
+ transaction.originUid, transaction.id);
+ }
}
bool SurfaceFlinger::transactionFlushNeeded() {
- return !mTransactionQueues.empty();
+ Mutex::Autolock _l(mQueueLock);
+ return !mPendingTransactionQueues.empty();
}
bool SurfaceFlinger::transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
@@ -3339,8 +3376,10 @@
continue;
}
if (s.acquireFence && s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
- ready = false;
+ ready = false;
}
+
+ Mutex::Autolock _l(mStateLock);
sp<Layer> layer = nullptr;
if (s.surface) {
layer = fromHandleLocked(s.surface).promote();
@@ -3374,101 +3413,132 @@
}
status_t SurfaceFlinger::setTransactionState(
- int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
+ const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states,
const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
ATRACE_CALL();
- const int64_t postTime = systemTime();
+ {
+ Mutex::Autolock _l(mQueueLock);
- bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
+ const int64_t postTime = systemTime();
+ bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
- Mutex::Autolock _l(mStateLock);
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int originPid = ipc->getCallingPid();
+ const int originUid = ipc->getCallingUid();
- // If its TransactionQueue already has a pending TransactionState or if it is pending
- auto itr = mTransactionQueues.find(applyToken);
- // if this is an animation frame, wait until prior animation frame has
- // been applied by SF
- if (flags & eAnimation) {
- while (itr != mTransactionQueues.end()) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- ALOGW_IF(err == TIMED_OUT,
- "setTransactionState timed out "
- "waiting for animation frame to apply");
- break;
+ // If its TransactionQueue already has a pending TransactionState or if it is pending
+ auto itr = mPendingTransactionQueues.find(applyToken);
+ // if this is an animation frame, wait until prior animation frame has
+ // been applied by SF
+ if (flags & eAnimation) {
+ while (itr != mPendingTransactionQueues.end()) {
+ status_t err = mTransactionQueueCV.waitRelative(mQueueLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ ALOGW_IF(err == TIMED_OUT,
+ "setTransactionState timed out "
+ "waiting for animation frame to apply");
+ break;
+ }
+ itr = mPendingTransactionQueues.find(applyToken);
}
- itr = mTransactionQueues.find(applyToken);
}
+
+ const bool pendingTransactions = itr != mPendingTransactionQueues.end();
+ // Expected present time is computed and cached on invalidate, so it may be stale.
+ if (!pendingTransactions) {
+ const auto now = systemTime();
+ const bool nextVsyncPending = now < mExpectedPresentTime.load();
+ const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(now);
+ mExpectedPresentTime = calculateExpectedPresentTime(stats);
+ // The transaction might arrive just before the next vsync but after
+ // invalidate was called. In that case we need to get the next vsync
+ // afterwards.
+ if (nextVsyncPending) {
+ mExpectedPresentTime += stats.vsyncPeriod;
+ }
+ }
+
+ mTransactionQueue.emplace(frameTimelineInfo, states, displays, flags, applyToken,
+ inputWindowCommands, desiredPresentTime, isAutoTimestamp,
+ uncacheBuffer, postTime, privileged, hasListenerCallbacks,
+ listenerCallbacks, originPid, originUid, transactionId);
+
+ if (pendingTransactions ||
+ (!isAutoTimestamp && desiredPresentTime > mExpectedPresentTime.load())) {
+ setTransactionFlags(eTransactionFlushNeeded);
+ return NO_ERROR;
+ }
+
+ // TODO(b/159125966): Remove eEarlyWakeup completely as no client should use this flag
+ if (flags & eEarlyWakeup) {
+ ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
+ }
+
+ if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
+ ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
+ flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
+ }
+
+ const auto schedule = [](uint32_t flags) {
+ if (flags & eEarlyWakeup) return TransactionSchedule::Early;
+ if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
+ if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
+ return TransactionSchedule::Late;
+ }(flags);
+ setTransactionFlags(eTransactionFlushNeeded, schedule);
}
- const bool pendingTransactions = itr != mTransactionQueues.end();
- // Expected present time is computed and cached on invalidate, so it may be stale.
- if (!pendingTransactions) {
- const auto now = systemTime();
- const bool nextVsyncPending = now < mExpectedPresentTime.load();
- const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(now);
- mExpectedPresentTime = calculateExpectedPresentTime(stats);
- // The transaction might arrive just before the next vsync but after
- // invalidate was called. In that case we need to get the next vsync
- // afterwards.
- if (nextVsyncPending) {
- mExpectedPresentTime += stats.vsyncPeriod;
- }
- }
-
- IPCThreadState* ipc = IPCThreadState::self();
- const int originPid = ipc->getCallingPid();
- const int originUid = ipc->getCallingUid();
-
- // Call transactionIsReadyToBeApplied first in case we need to incrementPendingBufferCount
- // if the transaction contains a buffer.
- if (!transactionIsReadyToBeApplied(isAutoTimestamp, desiredPresentTime, states, true) ||
- pendingTransactions) {
- mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags,
- desiredPresentTime, isAutoTimestamp, uncacheBuffer,
- postTime, privileged, hasListenerCallbacks,
- listenerCallbacks, originPid, originUid,
- transactionId);
- setTransactionFlags(eTransactionFlushNeeded);
+ // if this is a synchronous transaction, wait for it to take effect
+ // before returning.
+ const bool synchronous = flags & eSynchronous;
+ const bool syncInput = inputWindowCommands.syncInputWindows;
+ if (!synchronous && !syncInput) {
return NO_ERROR;
}
- applyTransactionState(frameTimelineVsyncId, states, displays, flags, inputWindowCommands,
- desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged,
- hasListenerCallbacks, listenerCallbacks, originPid, originUid,
- transactionId, /*isMainThread*/ false);
+ Mutex::Autolock _l(mStateLock);
+ if (synchronous) {
+ mTransactionPending = true;
+ }
+ if (syncInput) {
+ mPendingSyncInputWindows = true;
+ }
+
+ // applyTransactionState can be called by either the main SF thread or by
+ // another process through setTransactionState. While a given process may wish
+ // to wait on synchronous transactions, the main SF thread should never
+ // be blocked. Therefore, we only wait if isMainThread is false.
+ while (mTransactionPending || mPendingSyncInputWindows) {
+ status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ // just in case something goes wrong in SF, return to the
+ // called after a few seconds.
+ ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
+ mTransactionPending = false;
+ mPendingSyncInputWindows = false;
+ break;
+ }
+ }
+
return NO_ERROR;
}
-void SurfaceFlinger::applyTransactionState(
- int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
- const Vector<DisplayState>& displays, uint32_t flags,
- const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
- bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime,
- bool privileged, bool hasListenerCallbacks,
- const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid,
- uint64_t transactionId, bool isMainThread) {
+void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+ const Vector<ComposerState>& states,
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const InputWindowCommands& inputWindowCommands,
+ const int64_t desiredPresentTime, bool isAutoTimestamp,
+ const client_cache_t& uncacheBuffer,
+ const int64_t postTime, bool privileged,
+ bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks,
+ int originPid, int originUid, uint64_t transactionId) {
uint32_t transactionFlags = 0;
- if (flags & eAnimation) {
- // For window updates that are part of an animation we must wait for
- // previous animation "frames" to be handled.
- while (!isMainThread && mAnimTransactionPending) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- // just in case something goes wrong in SF, return to the
- // caller after a few seconds.
- ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
- "waiting for previous animation frame");
- mAnimTransactionPending = false;
- break;
- }
- }
- }
-
for (const DisplayState& display : displays) {
transactionFlags |= setDisplayStateLocked(display);
}
@@ -3485,9 +3555,8 @@
uint32_t clientStateFlags = 0;
for (const ComposerState& state : states) {
clientStateFlags |=
- setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime,
- isAutoTimestamp, postTime, privileged,
- listenerCallbacksWithSurfaces, originPid, originUid);
+ setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, isAutoTimestamp,
+ postTime, privileged, listenerCallbacksWithSurfaces);
if ((flags & eAnimation) && state.state.surface) {
if (const auto layer = fromHandleLocked(state.state.surface).promote(); layer) {
mScheduler->recordLayerHistory(layer.get(),
@@ -3527,80 +3596,25 @@
transactionFlags = eTransactionNeeded;
}
- // If we are on the main thread, we are about to preform a traversal. Clear the traversal bit
- // so we don't have to wake up again next frame to preform an uneeded traversal.
- if (isMainThread && (transactionFlags & eTraversalNeeded)) {
- transactionFlags = transactionFlags & (~eTraversalNeeded);
- mForceTraversal = true;
- }
-
- const auto schedule = [](uint32_t flags) {
- if (flags & eEarlyWakeup) return TransactionSchedule::Early;
- if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
- if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
- return TransactionSchedule::Late;
- }(flags);
-
if (transactionFlags) {
if (mInterceptor->isEnabled()) {
mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags,
originPid, originUid, transactionId);
}
- // TODO(b/159125966): Remove eEarlyWakeup completly as no client should use this flag
- if (flags & eEarlyWakeup) {
- ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
+ // We are on the main thread, we are about to preform a traversal. Clear the traversal bit
+ // so we don't have to wake up again next frame to preform an unnecessary traversal.
+ if (transactionFlags & eTraversalNeeded) {
+ transactionFlags = transactionFlags & (~eTraversalNeeded);
+ mForceTraversal = true;
}
-
- if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
- ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
- flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
+ if (transactionFlags) {
+ setTransactionFlags(transactionFlags);
}
- // this triggers the transaction
- setTransactionFlags(transactionFlags, schedule);
-
if (flags & eAnimation) {
mAnimTransactionPending = true;
}
-
- // if this is a synchronous transaction, wait for it to take effect
- // before returning.
- const bool synchronous = flags & eSynchronous;
- const bool syncInput = inputWindowCommands.syncInputWindows;
- if (!synchronous && !syncInput) {
- return;
- }
-
- if (synchronous) {
- mTransactionPending = true;
- }
- if (syncInput) {
- mPendingSyncInputWindows = true;
- }
-
-
- // applyTransactionState can be called by either the main SF thread or by
- // another process through setTransactionState. While a given process may wish
- // to wait on synchronous transactions, the main SF thread should never
- // be blocked. Therefore, we only wait if isMainThread is false.
- while (!isMainThread && (mTransactionPending || mPendingSyncInputWindows)) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- // just in case something goes wrong in SF, return to the
- // called after a few seconds.
- ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
- mTransactionPending = false;
- mPendingSyncInputWindows = false;
- break;
- }
- }
- } else {
- // Update VsyncModulator state machine even if transaction is not needed.
- if (schedule == TransactionSchedule::EarlyStart ||
- schedule == TransactionSchedule::EarlyEnd) {
- modulateVsync(&VsyncModulator::setTransactionSchedule, schedule);
- }
}
}
@@ -3665,10 +3679,9 @@
}
uint32_t SurfaceFlinger::setClientStateLocked(
- int64_t frameTimelineVsyncId, const ComposerState& composerState,
+ const FrameTimelineInfo& frameTimelineInfo, const ComposerState& composerState,
int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged,
- std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks,
- int originPid, int originUid) {
+ std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks) {
const layer_state_t& s = composerState.state;
for (auto& listener : s.listeners) {
@@ -3814,14 +3827,10 @@
if (layer->setCornerRadius(s.cornerRadius))
flags |= eTraversalNeeded;
}
-
- if (what & layer_state_t::eBackgroundBlurRadiusChanged && !mDisableBlurs && mSupportsBlur &&
- originalCallerCanUseBlurs(originPid, originUid)) {
+ if (what & layer_state_t::eBackgroundBlurRadiusChanged && !mDisableBlurs && mSupportsBlur) {
if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded;
}
-
- if (what & layer_state_t::eBlurRegionsChanged &&
- originalCallerCanUseBlurs(originPid, originUid)) {
+ if (what & layer_state_t::eBlurRegionsChanged) {
if (layer->setBlurRegions(s.blurRegions)) flags |= eTraversalNeeded;
}
if (what & layer_state_t::eLayerStackChanged) {
@@ -3855,9 +3864,6 @@
flags |= eTransactionNeeded|eTraversalNeeded;
}
}
- if (what & layer_state_t::eDetachChildren) {
- layer->detachChildren();
- }
if (what & layer_state_t::eTransformChanged) {
if (layer->setTransform(s.transform)) flags |= eTraversalNeeded;
}
@@ -3925,10 +3931,10 @@
flags |= eTraversalNeeded;
}
}
- if (what & layer_state_t::eFrameTimelineVsyncChanged) {
- layer->setFrameTimelineVsyncForTransaction(s.frameTimelineVsyncId, postTime);
- } else if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) {
- layer->setFrameTimelineVsyncForTransaction(frameTimelineVsyncId, postTime);
+ if (what & layer_state_t::eFrameTimelineInfoChanged) {
+ layer->setFrameTimelineInfoForTransaction(s.frameTimelineInfo, postTime);
+ } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
+ layer->setFrameTimelineInfoForTransaction(frameTimelineInfo, postTime);
}
if (what & layer_state_t::eFixedTransformHintChanged) {
if (layer->setFixedTransformHint(s.fixedTransformHint)) {
@@ -3999,7 +4005,7 @@
}
uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) {
- bool hasChanges = mPendingInputWindowCommands.merge(inputWindowCommands);
+ bool hasChanges = mInputWindowCommands.merge(inputWindowCommands);
return hasChanges ? eTraversalNeeded : 0;
}
@@ -4264,9 +4270,11 @@
d.width = 0;
d.height = 0;
displays.add(d);
- setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, state, displays, 0, nullptr,
- mPendingInputWindowCommands, systemTime(), true, {}, false, {},
- 0 /* Undefined transactionId */);
+
+ // It should be on the main thread, apply it directly.
+ applyTransactionState(FrameTimelineInfo{}, state, displays, 0, mInputWindowCommands,
+ systemTime(), true, {}, systemTime(), true, false, {}, getpid(), getuid(),
+ 0 /* Undefined transactionId */);
setPowerModeInternal(display, hal::PowerMode::ON);
const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
@@ -4843,15 +4851,12 @@
" gpu_to_cpu_unsupported : %d\n",
mTransactionFlags.load(), !mGpuToCpuSupported);
- if (const auto displayId = getInternalDisplayIdLocked();
- displayId && getHwComposer().isConnected(*displayId)) {
- const auto activeConfig = getHwComposer().getActiveMode(*displayId);
+ if (const auto display = getDefaultDisplayDeviceLocked()) {
std::string fps, xDpi, yDpi;
- if (activeConfig) {
- const auto vsyncPeriod = getHwComposer().getDisplayVsyncPeriod(*displayId);
- fps = base::StringPrintf("%s", to_string(Fps::fromPeriodNsecs(vsyncPeriod)).c_str());
- xDpi = base::StringPrintf("%.2f", activeConfig->getDpiX());
- yDpi = base::StringPrintf("%.2f", activeConfig->getDpiY());
+ if (const auto activeMode = display->getActiveMode()) {
+ fps = to_string(activeMode->getFps());
+ xDpi = base::StringPrintf("%.2f", activeMode->getDpiX());
+ yDpi = base::StringPrintf("%.2f", activeMode->getDpiY());
} else {
fps = "unknown";
xDpi = "unknown";
@@ -4909,23 +4914,24 @@
result.append("\n");
}
-void SurfaceFlinger::updateColorMatrixLocked() {
- mat4 colorMatrix;
- if (mGlobalSaturationFactor != 1.0f) {
- // Rec.709 luma coefficients
- float3 luminance{0.213f, 0.715f, 0.072f};
- luminance *= 1.0f - mGlobalSaturationFactor;
- mat4 saturationMatrix = mat4(
- vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f},
- vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f},
- vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f},
- vec4{0.0f, 0.0f, 0.0f, 1.0f}
- );
- colorMatrix = mClientColorMatrix * saturationMatrix * mDaltonizer();
- } else {
- colorMatrix = mClientColorMatrix * mDaltonizer();
+mat4 SurfaceFlinger::calculateColorMatrix(float saturation) {
+ if (saturation == 1) {
+ return mat4();
}
+ float3 luminance{0.213f, 0.715f, 0.072f};
+ luminance *= 1.0f - saturation;
+ mat4 saturationMatrix = mat4(vec4{luminance.r + saturation, luminance.r, luminance.r, 0.0f},
+ vec4{luminance.g, luminance.g + saturation, luminance.g, 0.0f},
+ vec4{luminance.b, luminance.b, luminance.b + saturation, 0.0f},
+ vec4{0.0f, 0.0f, 0.0f, 1.0f});
+ return saturationMatrix;
+}
+
+void SurfaceFlinger::updateColorMatrixLocked() {
+ mat4 colorMatrix =
+ mClientColorMatrix * calculateColorMatrix(mGlobalSaturationFactor) * mDaltonizer();
+
if (mCurrentState.colorMatrix != colorMatrix) {
mCurrentState.colorMatrix = colorMatrix;
mCurrentState.colorMatrixChanged = true;
@@ -5015,7 +5021,7 @@
case CAPTURE_LAYERS:
case CAPTURE_DISPLAY:
case SET_DISPLAY_BRIGHTNESS:
- case SET_FRAME_TIMELINE_VSYNC:
+ case SET_FRAME_TIMELINE_INFO:
// This is not sensitive information, so should not require permission control.
case GET_GPU_CONTEXT_PRIORITY: {
return OK;
@@ -5637,7 +5643,8 @@
};
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
- args.pixelFormat, args.allowProtected, captureListener);
+ args.pixelFormat, args.allowProtected, args.grayscale,
+ captureListener);
}
status_t SurfaceFlinger::captureDisplay(uint64_t displayOrLayerStack,
@@ -5673,7 +5680,7 @@
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size,
ui::PixelFormat::RGBA_8888, false /* allowProtected */,
- captureListener);
+ false /* grayscale */, captureListener);
}
status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
@@ -5719,12 +5726,12 @@
crop.bottom = parentSourceBounds.getHeight();
}
- if (crop.isEmpty() || args.frameScale <= 0.0f) {
+ if (crop.isEmpty() || args.frameScaleX <= 0.0f || args.frameScaleY <= 0.0f) {
// Error out if the layer has no source bounds (i.e. they are boundless) and a source
// crop was not specified, or an invalid frame scale was provided.
return BAD_VALUE;
}
- reqSize = ui::Size(crop.width() * args.frameScale, crop.height() * args.frameScale);
+ reqSize = ui::Size(crop.width() * args.frameScaleX, crop.height() * args.frameScaleY);
for (const auto& handle : args.excludeHandles) {
sp<Layer> excludeLayer = fromHandleLocked(handle).promote();
@@ -5794,13 +5801,14 @@
};
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
- args.pixelFormat, args.allowProtected, captureListener);
+ args.pixelFormat, args.allowProtected, args.grayscale,
+ captureListener);
}
status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
TraverseLayersFunction traverseLayers,
ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
- const bool allowProtected,
+ bool allowProtected, bool grayscale,
const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
@@ -5831,12 +5839,13 @@
static_cast<android_pixel_format>(reqPixelFormat),
1 /* layerCount */, usage, "screenshot");
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
- false /* regionSampling */, captureListener);
+ false /* regionSampling */, grayscale, captureListener);
}
status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
TraverseLayersFunction traverseLayers,
- sp<GraphicBuffer>& buffer, const bool regionSampling,
+ sp<GraphicBuffer>& buffer, bool regionSampling,
+ bool grayscale,
const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
@@ -5852,7 +5861,7 @@
if (mRefreshPending) {
ALOGW("Skipping screenshot for now");
captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, regionSampling,
- captureListener);
+ grayscale, captureListener);
return;
}
ScreenCaptureResults captureResults;
@@ -5867,7 +5876,7 @@
status_t result = NO_ERROR;
renderArea->render([&] {
result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, forSystem,
- regionSampling, captureResults);
+ regionSampling, grayscale, captureResults);
});
captureResults.result = result;
@@ -5880,7 +5889,7 @@
status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
const sp<GraphicBuffer>& buffer, bool forSystem,
- bool regionSampling,
+ bool regionSampling, bool grayscale,
ScreenCaptureResults& captureResults) {
ATRACE_CALL();
@@ -5921,6 +5930,9 @@
clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;
+ const float colorSaturation = grayscale ? 0 : 1;
+ clientCompositionDisplay.colorTransform = calculateColorMatrix(colorSaturation);
+
const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill());
compositionengine::LayerFE::LayerSettings fillLayer;
@@ -6383,21 +6395,21 @@
}));
}
-status_t SurfaceFlinger::setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
- int64_t frameTimelineVsyncId) {
+status_t SurfaceFlinger::setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
+ const FrameTimelineInfo& frameTimelineInfo) {
Mutex::Autolock lock(mStateLock);
if (!authenticateSurfaceTextureLocked(surface)) {
- ALOGE("Attempt to set frame timeline vsync on an unrecognized IGraphicBufferProducer");
+ ALOGE("Attempt to set frame timeline info on an unrecognized IGraphicBufferProducer");
return BAD_VALUE;
}
sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer();
if (layer == nullptr) {
- ALOGE("Attempt to set frame timeline vsync on a layer that no longer exists");
+ ALOGE("Attempt to set frame timeline info on a layer that no longer exists");
return BAD_VALUE;
}
- layer->setFrameTimelineVsyncForBuffer(frameTimelineVsyncId);
+ layer->setFrameTimelineInfoForBuffer(frameTimelineInfo);
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e82095b..66fc4f0 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -343,10 +343,10 @@
virtual ~SurfaceFlinger();
virtual uint32_t setClientStateLocked(
- int64_t frameTimelineVsyncId, const ComposerState& composerState,
+ const FrameTimelineInfo& info, const ComposerState& composerState,
int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged,
- std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks,
- int originPid, int originUid) REQUIRES(mStateLock);
+ std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks)
+ REQUIRES(mStateLock);
virtual void commitTransactionLocked();
// Used internally by computeLayerBounds() to gets the clip rectangle to use for the
@@ -435,17 +435,21 @@
};
struct TransactionState {
- TransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& composerStates,
+ TransactionState(const FrameTimelineInfo& frameTimelineInfo,
+ const Vector<ComposerState>& composerStates,
const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
- int64_t desiredPresentTime, bool isAutoTimestamp,
- const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged,
- bool hasListenerCallbacks,
+ const sp<IBinder>& applyToken,
+ const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
+ bool isAutoTimestamp, const client_cache_t& uncacheBuffer,
+ int64_t postTime, bool privileged, bool hasListenerCallbacks,
std::vector<ListenerCallbacks> listenerCallbacks, int originPid,
int originUid, uint64_t transactionId)
- : frameTimelineVsyncId(frameTimelineVsyncId),
+ : frameTimelineInfo(frameTimelineInfo),
states(composerStates),
displays(displayStates),
flags(transactionFlags),
+ applyToken(applyToken),
+ inputWindowCommands(inputWindowCommands),
desiredPresentTime(desiredPresentTime),
isAutoTimestamp(isAutoTimestamp),
buffer(uncacheBuffer),
@@ -457,10 +461,12 @@
originUid(originUid),
id(transactionId) {}
- int64_t frameTimelineVsyncId;
+ FrameTimelineInfo frameTimelineInfo;
Vector<ComposerState> states;
Vector<DisplayState> displays;
uint32_t flags;
+ sp<IBinder> applyToken;
+ InputWindowCommands inputWindowCommands;
const int64_t desiredPresentTime;
const bool isAutoTimestamp;
client_cache_t buffer;
@@ -522,7 +528,8 @@
void destroyDisplay(const sp<IBinder>& displayToken) override;
std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override;
sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const override;
- status_t setTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
+ status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+ const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags,
const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
@@ -608,8 +615,8 @@
int8_t compatibility, bool shouldBeSeamless) override;
status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) override;
- status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
- int64_t frameTimelineVsyncId) override;
+ status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
+ const FrameTimelineInfo& frameTimelineInfo) override;
status_t addTransactionTraceListener(
const sp<gui::ITransactionTraceListener>& listener) override;
@@ -727,17 +734,17 @@
/*
* Transactions
*/
- void applyTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
+ void applyTransactionState(const FrameTimelineInfo& info, const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags,
const InputWindowCommands& inputWindowCommands,
const int64_t desiredPresentTime, bool isAutoTimestamp,
const client_cache_t& uncacheBuffer, const int64_t postTime,
bool privileged, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks,
- int originPid, int originUid, uint64_t transactionId,
- bool isMainThread = false) REQUIRES(mStateLock);
- // Returns true if at least one transaction was flushed
- bool flushTransactionQueues();
+ int originPid, int originUid, uint64_t transactionId)
+ REQUIRES(mStateLock);
+ // flush pending transaction that was presented after desiredPresentTime.
+ void flushTransactionQueues();
// Returns true if there is at least one transaction that needs to be flushed
bool transactionFlushNeeded();
uint32_t getTransactionFlags(uint32_t flags);
@@ -755,7 +762,7 @@
void commitOffscreenLayers();
bool transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
const Vector<ComposerState>& states,
- bool updateTransactionCounters = false) REQUIRES(mStateLock);
+ bool updateTransactionCounters = false);
uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
REQUIRES(mStateLock);
@@ -810,13 +817,14 @@
void startBootAnim();
status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize,
- ui::PixelFormat, const bool allowProtected,
+ ui::PixelFormat, bool allowProtected, bool grayscale,
const sp<IScreenCaptureListener>&);
status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, sp<GraphicBuffer>&,
- bool regionSampling, const sp<IScreenCaptureListener>&);
+ bool regionSampling, bool grayscale,
+ const sp<IScreenCaptureListener>&);
status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction,
const sp<GraphicBuffer>&, bool forSystem, bool regionSampling,
- ScreenCaptureResults&);
+ bool grayscale, ScreenCaptureResults&);
sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock);
sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack) REQUIRES(mStateLock);
@@ -894,6 +902,7 @@
/*
* Display management
*/
+ DisplayModes loadSupportedDisplayModes(PhysicalDisplayId) const;
sp<DisplayDevice> setupNewDisplayDeviceInternal(
const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay,
@@ -1019,6 +1028,8 @@
void onFrameRateFlexibilityTokenReleased();
+ static mat4 calculateColorMatrix(float saturation);
+
void updateColorMatrixLocked();
// Verify that transaction is being called by an approved process:
@@ -1172,8 +1183,11 @@
uint32_t mTexturePoolSize = 0;
std::vector<uint32_t> mTexturePool;
- std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash> mTransactionQueues;
-
+ mutable Mutex mQueueLock;
+ Condition mTransactionQueueCV;
+ std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash>
+ mPendingTransactionQueues GUARDED_BY(mQueueLock);
+ std::queue<TransactionState> mTransactionQueue GUARDED_BY(mQueueLock);
/*
* Feature prototyping
*/
@@ -1251,7 +1265,6 @@
const float mEmulatedDisplayDensity;
sp<os::IInputFlinger> mInputFlinger;
- InputWindowCommands mPendingInputWindowCommands GUARDED_BY(mStateLock);
// Should only be accessed by the main thread.
InputWindowCommands mInputWindowCommands;
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 3548923..61005c9 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -150,7 +150,6 @@
layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque |
layer_state_t::eLayerSecure);
addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentParent));
- addDetachChildrenLocked(transaction, layerId, layer->isLayerDetached());
addRelativeParentLocked(transaction, layerId,
getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf),
layer->mCurrentState.z);
@@ -409,13 +408,6 @@
overrideChange->set_parent_id(parentId);
}
-void SurfaceInterceptor::addDetachChildrenLocked(Transaction* transaction, int32_t layerId,
- bool detached) {
- SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
- DetachChildrenChange* overrideChange(change->mutable_detach_children());
- overrideChange->set_detach_children(detached);
-}
-
void SurfaceInterceptor::addRelativeParentLocked(Transaction* transaction, int32_t layerId,
int32_t parentId, int z) {
SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
@@ -498,9 +490,6 @@
addReparentChildrenLocked(transaction, layerId,
getLayerIdFromHandle(state.reparentSurfaceControl->getHandle()));
}
- if (state.what & layer_state_t::eDetachChildren) {
- addDetachChildrenLocked(transaction, layerId, true);
- }
if (state.what & layer_state_t::eRelativeLayerChanged) {
addRelativeParentLocked(transaction, layerId,
getLayerIdFromHandle(
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 3df79c6..3e27e83 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -177,7 +177,6 @@
uint64_t transactionId);
void addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
void addReparentChildrenLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
- void addDetachChildrenLocked(Transaction* transaction, int32_t layerId, bool detached);
void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId,
int z);
void addShadowRadiusLocked(Transaction* transaction, int32_t layerId, float shadowRadius);
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index e8b24b4..cfaf229 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -21,7 +21,6 @@
"CommonTypes_test.cpp",
"Credentials_test.cpp",
"DereferenceSurfaceControl_test.cpp",
- "DetachChildren_test.cpp",
"DisplayConfigs_test.cpp",
"EffectLayer_test.cpp",
"InvalidHandles_test.cpp",
diff --git a/services/surfaceflinger/tests/DetachChildren_test.cpp b/services/surfaceflinger/tests/DetachChildren_test.cpp
deleted file mode 100644
index abf8b1a..0000000
--- a/services/surfaceflinger/tests/DetachChildren_test.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include "LayerTransactionTest.h"
-
-namespace android {
-
-class DetachChildren : public LayerTransactionTest {
-protected:
- virtual void SetUp() {
- LayerTransactionTest::SetUp();
-
- mMainSurface = createLayer(String8("Main Test Surface"), mMainSurfaceBounds.width(),
- mMainSurfaceBounds.height(), 0, mBlackBgSurface.get());
-
- ASSERT_TRUE(mMainSurface != nullptr);
- ASSERT_TRUE(mMainSurface->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(mMainSurface, mMainSurfaceColor);
-
- asTransaction([&](Transaction& t) {
- t.setLayer(mMainSurface, INT32_MAX - 1)
- .setPosition(mMainSurface, mMainSurfaceBounds.left, mMainSurfaceBounds.top)
- .show(mMainSurface);
- });
- }
-
- virtual void TearDown() {
- LayerTransactionTest::TearDown();
- mMainSurface = 0;
- }
-
- sp<SurfaceControl> mMainSurface;
- Color mMainSurfaceColor = {195, 63, 63, 255};
- Rect mMainSurfaceBounds = Rect(64, 64, 128, 128);
- std::unique_ptr<ScreenCapture> mCapture;
-};
-
-TEST_F(DetachChildren, RelativesAreNotDetached) {
- Color relativeColor = {10, 10, 10, 255};
- Rect relBounds = Rect(64, 64, 74, 74);
-
- sp<SurfaceControl> relative =
- createLayer(String8("relativeTestSurface"), relBounds.width(), relBounds.height(), 0);
- TransactionUtils::fillSurfaceRGBA8(relative, relativeColor);
-
- Transaction{}
- .setRelativeLayer(relative, mMainSurface, 1)
- .setPosition(relative, relBounds.left, relBounds.top)
- .apply();
-
- {
- // The relative should be on top of the FG control.
- mCapture = screenshot();
- mCapture->expectColor(relBounds, relativeColor);
- }
- Transaction{}.detachChildren(mMainSurface).apply();
-
- {
- // Nothing should change at this point.
- mCapture = screenshot();
- mCapture->expectColor(relBounds, relativeColor);
- }
-
- Transaction{}.hide(relative).apply();
-
- {
- // Ensure that the relative was actually hidden, rather than
- // being left in the detached but visible state.
- mCapture = screenshot();
- mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenSameClient) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
- sp<SurfaceControl> child = createLayer(String8("Child surface"), childBounds.width(),
- childBounds.height(), 0, mMainSurface.get());
- ASSERT_TRUE(child->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(child, childColor);
-
- asTransaction([&](Transaction& t) {
- t.show(child);
- t.setPosition(child, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top);
- });
-
- {
- mCapture = screenshot();
- // Expect main color around the child surface
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
-
- asTransaction([&](Transaction& t) { t.hide(child); });
-
- // Since the child has the same client as the parent, it will not get
- // detached and will be hidden.
- {
- mCapture = screenshot();
- mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenDifferentClient) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- asTransaction([&](Transaction& t) {
- t.show(childNewClient);
- t.setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top);
- });
-
- {
- mCapture = screenshot();
- // Expect main color around the child surface
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
-
- asTransaction([&](Transaction& t) { t.hide(childNewClient); });
-
- // Nothing should have changed.
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenThenAttach) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- Transaction()
- .show(childNewClient)
- .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- // Expect main color around the child surface
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Transaction().detachChildren(mMainSurface).apply();
- Transaction().hide(childNewClient).apply();
-
- // Nothing should have changed.
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Color newParentColor = Color::RED;
- Rect newParentBounds = Rect(20, 20, 52, 52);
- sp<SurfaceControl> newParentSurface =
- createLayer(String8("New Parent Surface"), newParentBounds.width(),
- newParentBounds.height(), 0);
- TransactionUtils::fillSurfaceRGBA8(newParentSurface, newParentColor);
- Transaction()
- .setLayer(newParentSurface, INT32_MAX - 1)
- .show(newParentSurface)
- .setPosition(newParentSurface, newParentBounds.left, newParentBounds.top)
- .reparent(childNewClient, newParentSurface)
- .apply();
- {
- mCapture = screenshot();
- // Child is now hidden.
- mCapture->expectColor(newParentBounds, newParentColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenWithDeferredTransaction) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- Transaction()
- .show(childNewClient)
- .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Transaction()
- .deferTransactionUntil_legacy(childNewClient, mMainSurface,
- mMainSurface->getSurface()->getNextFrameNumber())
- .apply();
- Transaction().detachChildren(mMainSurface).apply();
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED,
- mMainSurfaceBounds.width(),
- mMainSurfaceBounds.height()));
-
- // BufferLayer can still dequeue buffers even though there's a detached layer with a
- // deferred transaction.
- {
- SCOPED_TRACE("new buffer");
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, Color::RED);
- mCapture->expectColor(childBounds, childColor);
- }
-}
-
-/**
- * Tests that a deferring transaction on an already detached layer will be dropped gracefully and
- * allow the barrier layer to dequeue buffers.
- *
- * Fixes b/150924737 - buffer cannot be latched because it waits for a detached layer
- * to commit its pending states.
- */
-TEST_F(DetachChildren, DeferredTransactionOnDetachedChildren) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- Transaction()
- .show(childNewClient)
- .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Transaction().detachChildren(mMainSurface).apply();
- Transaction()
- .setCrop_legacy(childNewClient, {0, 0, childBounds.width(), childBounds.height()})
- .deferTransactionUntil_legacy(childNewClient, mMainSurface,
- mMainSurface->getSurface()->getNextFrameNumber())
- .apply();
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED,
- mMainSurfaceBounds.width(),
- mMainSurfaceBounds.height()));
-
- // BufferLayer can still dequeue buffers even though there's a detached layer with a
- // deferred transaction.
- {
- SCOPED_TRACE("new buffer");
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, Color::RED);
- mCapture->expectColor(childBounds, childColor);
- }
-}
-
-TEST_F(DetachChildren, ReparentParentLayerOfDetachedChildren) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 94, 94);
- Color grandchildColor = Color::RED;
- Rect grandchildBounds = Rect(80, 80, 90, 90);
-
- sp<SurfaceComposerClient> newClient1 = new SurfaceComposerClient;
- sp<SurfaceComposerClient> newClient2 = new SurfaceComposerClient;
-
- sp<SurfaceControl> childSurface =
- createSurface(newClient1, "Child surface", childBounds.width(), childBounds.height(),
- PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- sp<SurfaceControl> grandchildSurface =
- createSurface(newClient2, "Grandchild Surface", grandchildBounds.width(),
- grandchildBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, childSurface.get());
-
- TransactionUtils::fillSurfaceRGBA8(childSurface, childColor);
- TransactionUtils::fillSurfaceRGBA8(grandchildSurface, grandchildColor);
-
- Transaction()
- .show(childSurface)
- .show(grandchildSurface)
- .setPosition(childSurface, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .setPosition(grandchildSurface, grandchildBounds.left - childBounds.left,
- grandchildBounds.top - childBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectBorder(grandchildBounds, childColor);
- mCapture->expectColor(grandchildBounds, grandchildColor);
- }
-
- Transaction().detachChildren(childSurface).apply();
-
- // Remove main surface offscreen
- Transaction().reparent(mMainSurface, nullptr).apply();
- {
- mCapture = screenshot();
- mCapture->expectColor(mMainSurfaceBounds, Color::BLACK);
- }
-
- Transaction().reparent(mMainSurface, mBlackBgSurface).apply();
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectBorder(grandchildBounds, childColor);
- mCapture->expectColor(grandchildBounds, grandchildColor);
- }
-
- Transaction().hide(grandchildSurface).apply();
-
- // grandchild is still detached so it will not hide
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectBorder(grandchildBounds, childColor);
- mCapture->expectColor(grandchildBounds, grandchildColor);
- }
-}
-
-} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/LayerState_test.cpp b/services/surfaceflinger/tests/LayerState_test.cpp
index 93d5f2f..f010786 100644
--- a/services/surfaceflinger/tests/LayerState_test.cpp
+++ b/services/surfaceflinger/tests/LayerState_test.cpp
@@ -30,12 +30,14 @@
DisplayCaptureArgs args;
args.pixelFormat = ui::PixelFormat::RGB_565;
args.sourceCrop = Rect(0, 0, 500, 200);
- args.frameScale = 2;
+ args.frameScaleX = 2;
+ args.frameScaleY = 4;
args.captureSecureLayers = true;
args.displayToken = new BBinder();
args.width = 10;
args.height = 20;
args.useIdentityTransform = true;
+ args.grayscale = true;
Parcel p;
args.write(p);
@@ -46,23 +48,27 @@
ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
- ASSERT_EQ(args.frameScale, args2.frameScale);
+ ASSERT_EQ(args.frameScaleX, args2.frameScaleX);
+ ASSERT_EQ(args.frameScaleY, args2.frameScaleY);
ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
ASSERT_EQ(args.displayToken, args2.displayToken);
ASSERT_EQ(args.width, args2.width);
ASSERT_EQ(args.height, args2.height);
ASSERT_EQ(args.useIdentityTransform, args2.useIdentityTransform);
+ ASSERT_EQ(args.grayscale, args2.grayscale);
}
TEST(LayerStateTest, ParcellingLayerCaptureArgs) {
LayerCaptureArgs args;
args.pixelFormat = ui::PixelFormat::RGB_565;
args.sourceCrop = Rect(0, 0, 500, 200);
- args.frameScale = 2;
+ args.frameScaleX = 2;
+ args.frameScaleY = 4;
args.captureSecureLayers = true;
args.layerHandle = new BBinder();
args.excludeHandles = {new BBinder(), new BBinder()};
args.childrenOnly = false;
+ args.grayscale = true;
Parcel p;
args.write(p);
@@ -73,11 +79,13 @@
ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
- ASSERT_EQ(args.frameScale, args2.frameScale);
+ ASSERT_EQ(args.frameScaleX, args2.frameScaleX);
+ ASSERT_EQ(args.frameScaleY, args2.frameScaleY);
ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
ASSERT_EQ(args.layerHandle, args2.layerHandle);
ASSERT_EQ(args.excludeHandles, args2.excludeHandles);
ASSERT_EQ(args.childrenOnly, args2.childrenOnly);
+ ASSERT_EQ(args.grayscale, args2.grayscale);
}
TEST(LayerStateTest, ParcellingScreenCaptureResults) {
@@ -106,5 +114,34 @@
ASSERT_EQ(results.result, results2.result);
}
+/**
+ * Parcel a layer_state_t struct, and then unparcel. Ensure that the object that was parceled
+ * matches the object that's unparceled.
+ */
+TEST(LayerStateTest, ParcelUnparcelLayerStateT) {
+ layer_state_t input;
+ input.frameTimelineInfo.vsyncId = 1;
+ input.frameTimelineInfo.inputEventId = 2;
+ Parcel p;
+ input.write(p);
+ layer_state_t output;
+ p.setDataPosition(0);
+ output.read(p);
+ ASSERT_EQ(input.frameTimelineInfo.vsyncId, output.frameTimelineInfo.vsyncId);
+ ASSERT_EQ(input.frameTimelineInfo.inputEventId, output.frameTimelineInfo.inputEventId);
+}
+
+TEST(LayerStateTest, LayerStateMerge_SelectsValidInputEvent) {
+ layer_state_t layer1;
+ layer1.frameTimelineInfo.inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID;
+ layer_state_t layer2;
+ layer2.frameTimelineInfo.inputEventId = 1;
+ layer2.what |= layer_state_t::eFrameTimelineInfoChanged;
+
+ layer1.merge(layer2);
+
+ ASSERT_EQ(1, layer1.frameTimelineInfo.inputEventId);
+}
+
} // namespace test
} // namespace android
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
index 214a0cd..51ce1d3 100644
--- a/services/surfaceflinger/tests/ScreenCapture_test.cpp
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -487,7 +487,9 @@
// red area to the right of the blue area
mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
- captureArgs.frameScale = 0.5f;
+ captureArgs.frameScaleX = 0.5f;
+ captureArgs.frameScaleY = 0.5f;
+
ScreenCapture::captureLayers(&mCapture, captureArgs);
// Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
@@ -768,6 +770,41 @@
mCapture->expectBorder(Rect(128, 128, 160, 160), {63, 63, 195, 255});
}
+TEST_F(ScreenCaptureTest, CaptureWithGrayscale) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32,
+ ISurfaceComposerClient::eFXSurfaceBufferState,
+ mBGSurfaceControl.get()));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ Transaction().show(layer).setLayer(layer, INT32_MAX).apply();
+
+ LayerCaptureArgs captureArgs;
+ captureArgs.layerHandle = layer->getHandle();
+
+ ScreenCapture::captureLayers(&mCapture, captureArgs);
+ mCapture->expectColor(Rect(0, 0, 32, 32), Color::RED);
+
+ captureArgs.grayscale = true;
+
+ const uint8_t tolerance = 1;
+
+ // Values based on SurfaceFlinger::calculateColorMatrix
+ float3 luminance{0.213f, 0.715f, 0.072f};
+
+ ScreenCapture::captureLayers(&mCapture, captureArgs);
+
+ uint8_t expectedColor = luminance.r * 255;
+ mCapture->expectColor(Rect(0, 0, 32, 32),
+ Color{expectedColor, expectedColor, expectedColor, 255}, tolerance);
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32));
+ ScreenCapture::captureLayers(&mCapture, captureArgs);
+
+ expectedColor = luminance.b * 255;
+ mCapture->expectColor(Rect(0, 0, 32, 32),
+ Color{expectedColor, expectedColor, expectedColor, 255}, tolerance);
+}
+
// In the following tests we verify successful skipping of a parent layer,
// so we use the same verification logic and only change how we mutate
// the parent layer to verify that various properties are ignored.
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 8dc9a12..fa88ca5 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -194,7 +194,6 @@
bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred);
bool reparentUpdateFound(const SurfaceChange& change, bool found);
bool relativeParentUpdateFound(const SurfaceChange& change, bool found);
- bool detachChildrenUpdateFound(const SurfaceChange& change, bool found);
bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found);
bool shadowRadiusUpdateFound(const SurfaceChange& change, bool found);
bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase);
@@ -232,7 +231,6 @@
void deferredTransactionUpdate(Transaction&);
void reparentUpdate(Transaction&);
void relativeParentUpdate(Transaction&);
- void detachChildrenUpdate(Transaction&);
void reparentChildrenUpdate(Transaction&);
void shadowRadiusUpdate(Transaction&);
void surfaceCreation(Transaction&);
@@ -412,10 +410,6 @@
t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl, RELATIVE_Z);
}
-void SurfaceInterceptorTest::detachChildrenUpdate(Transaction& t) {
- t.detachChildren(mBGSurfaceControl);
-}
-
void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) {
t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl);
}
@@ -452,7 +446,6 @@
runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate);
runInTransaction(&SurfaceInterceptorTest::reparentUpdate);
runInTransaction(&SurfaceInterceptorTest::reparentChildrenUpdate);
- runInTransaction(&SurfaceInterceptorTest::detachChildrenUpdate);
runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate);
runInTransaction(&SurfaceInterceptorTest::shadowRadiusUpdate);
}
@@ -667,16 +660,6 @@
return found;
}
-bool SurfaceInterceptorTest::detachChildrenUpdateFound(const SurfaceChange& change, bool found) {
- bool detachChildren(change.detach_children().detach_children());
- if (detachChildren && !found) {
- found = true;
- } else if (detachChildren && found) {
- []() { FAIL(); }();
- }
- return found;
-}
-
bool SurfaceInterceptorTest::reparentChildrenUpdateFound(const SurfaceChange& change, bool found) {
bool hasId(change.reparent_children().parent_id() == mFGLayerId);
if (hasId && !found) {
@@ -761,9 +744,6 @@
case SurfaceChange::SurfaceChangeCase::kRelativeParent:
foundUpdate = relativeParentUpdateFound(change, foundUpdate);
break;
- case SurfaceChange::SurfaceChangeCase::kDetachChildren:
- foundUpdate = detachChildrenUpdateFound(change, foundUpdate);
- break;
case SurfaceChange::SurfaceChangeCase::kShadowRadius:
foundUpdate = shadowRadiusUpdateFound(change, foundUpdate);
break;
@@ -793,7 +773,6 @@
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparent));
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparentChildren));
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kRelativeParent));
- ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDetachChildren));
}
bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) {
@@ -968,11 +947,6 @@
SurfaceChange::SurfaceChangeCase::kRelativeParent);
}
-TEST_F(SurfaceInterceptorTest, InterceptDetachChildrenUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::detachChildrenUpdate,
- SurfaceChange::SurfaceChangeCase::kDetachChildren);
-}
-
TEST_F(SurfaceInterceptorTest, InterceptShadowRadiusUpdateWorks) {
captureTest(&SurfaceInterceptorTest::shadowRadiusUpdate,
SurfaceChange::SurfaceChangeCase::kShadowRadius);
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
index a361b1e..33823d7 100644
--- a/services/surfaceflinger/tests/TransactionTestHarnesses.h
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -57,6 +57,8 @@
// Sample usage bits from screenrecord
GRALLOC_USAGE_HW_VIDEO_ENCODER |
GRALLOC_USAGE_SW_READ_OFTEN);
+ sp<BufferListener> listener = new BufferListener(this);
+ itemConsumer->setFrameAvailableListener(listener);
vDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"),
false /*secure*/);
@@ -68,6 +70,13 @@
Rect(displayState.layerStackSpaceRect), Rect(resolution));
t.apply();
SurfaceComposerClient::Transaction().apply(true);
+
+ std::unique_lock lock(mMutex);
+ mAvailable = false;
+ // Wait for frame buffer ready.
+ mCondition.wait_for(lock, std::chrono::seconds(2),
+ [this]() NO_THREAD_SAFETY_ANALYSIS { return mAvailable; });
+
BufferItem item;
itemConsumer->acquireBuffer(&item, 0, true);
auto sc = std::make_unique<ScreenCapture>(item.mGraphicBuffer);
@@ -80,6 +89,23 @@
protected:
LayerTransactionTest* mDelegate;
RenderPath mRenderPath;
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+ bool mAvailable = false;
+
+ void onFrameAvailable() {
+ std::unique_lock lock(mMutex);
+ mAvailable = true;
+ mCondition.notify_all();
+ }
+
+ class BufferListener : public ConsumerBase::FrameAvailableListener {
+ public:
+ BufferListener(LayerRenderPathTestHarness* owner) : mOwner(owner) {}
+ LayerRenderPathTestHarness* mOwner;
+
+ void onFrameAvailable(const BufferItem& /*item*/) { mOwner->onFrameAvailable(); }
+ };
};
class LayerTypeTransactionHarness : public LayerTransactionTest {
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index bd49728..efa15f1 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -63,9 +63,7 @@
// Mock test helpers
using ::testing::_;
-using ::testing::AtLeast;
using ::testing::DoAll;
-using ::testing::Invoke;
using ::testing::Return;
using ::testing::SetArgPointee;
@@ -74,9 +72,11 @@
using Display = V2_1::Display;
///////////////////////////////////////////////
-
-constexpr PhysicalDisplayId kPrimaryDisplayId = PhysicalDisplayId::fromPort(PRIMARY_DISPLAY);
-constexpr PhysicalDisplayId kExternalDisplayId = PhysicalDisplayId::fromPort(EXTERNAL_DISPLAY);
+constexpr PhysicalDisplayId physicalIdFromHwcDisplayId(Display hwcId) {
+ return PhysicalDisplayId::fromPort(hwcId);
+}
+constexpr PhysicalDisplayId kPrimaryDisplayId = physicalIdFromHwcDisplayId(PRIMARY_DISPLAY);
+constexpr PhysicalDisplayId kExternalDisplayId = physicalIdFromHwcDisplayId(EXTERNAL_DISPLAY);
struct TestColor {
public:
@@ -158,7 +158,7 @@
self->mReceivedDisplayEvents.push_back(buffer[i]);
}
}
- ALOGD_IF(n < 0, "Error reading events (%s)\n", strerror(-n));
+ ALOGD_IF(n < 0, "Error reading events (%s)", strerror(-n));
return 1;
}
@@ -174,7 +174,7 @@
void setExpectationsForConfigs(Display display, std::vector<TestConfig> testConfigs,
Config activeConfig, V2_4::VsyncPeriodNanos defaultVsyncPeriod) {
std::vector<Config> configIds;
- for (int i = 0; i < testConfigs.size(); i++) {
+ for (size_t i = 0; i < testConfigs.size(); i++) {
configIds.push_back(testConfigs[i].id);
EXPECT_CALL(*mMockComposer,
@@ -269,10 +269,10 @@
mMockComposer = nullptr;
}
- void waitForDisplayTransaction() {
+ void waitForDisplayTransaction(Display display) {
// Both a refresh and a vsync event are needed to apply pending display
// transactions.
- mFakeComposerClient->refreshDisplay(EXTERNAL_DISPLAY);
+ mFakeComposerClient->refreshDisplay(display);
mFakeComposerClient->runVSyncAndWait();
// Extra vsync and wait to avoid a 10% flake due to a race.
@@ -291,7 +291,7 @@
mReceivedDisplayEvents.pop_front();
ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG,
- "event hotplug: displayId %s, connected %d\t",
+ "event hotplug: displayId %s, connected %d",
to_string(event.header.displayId).c_str(), event.hotplug.connected);
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG &&
@@ -314,7 +314,7 @@
mReceivedDisplayEvents.pop_front();
ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED,
- "event config: displayId %s, configId %d\t",
+ "event config: displayId %s, configId %d",
to_string(event.header.displayId).c_str(), event.config.configId);
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED &&
@@ -341,7 +341,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
{
@@ -372,7 +372,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
@@ -403,7 +403,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -456,7 +456,7 @@
config.refreshRate,
config.refreshRate,
config.refreshRate));
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
@@ -487,7 +487,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
}
@@ -510,7 +510,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -562,7 +562,7 @@
config.refreshRate,
config.refreshRate,
config.refreshRate));
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
@@ -593,7 +593,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
}
@@ -626,7 +626,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -669,7 +669,7 @@
.WillOnce(Return(V2_1::Error::NONE));
}
- for (int i = 0; i < configs.size(); i++) {
+ for (size_t i = 0; i < configs.size(); i++) {
const auto& config = configs[i];
if (config.resolution.getWidth() == 800 && config.refreshRate == 1e9f / 11'111'111) {
EXPECT_EQ(NO_ERROR,
@@ -679,7 +679,7 @@
configs[i].refreshRate,
configs[i].refreshRate,
configs[i].refreshRate));
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
@@ -726,7 +726,7 @@
config.refreshRate,
config.refreshRate,
config.refreshRate));
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
@@ -773,7 +773,7 @@
config.refreshRate,
config.refreshRate,
config.refreshRate));
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
@@ -804,7 +804,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
}
@@ -815,7 +815,7 @@
mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(PRIMARY_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, false));
{
@@ -840,7 +840,7 @@
mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(PRIMARY_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, true));
@@ -856,6 +856,121 @@
}
}
+ void Test_SubsequentHotplugConnectUpdatesDisplay(Display hwcDisplayId) {
+ ALOGD("DisplayTest::Test_SubsequentHotplugConnectUpdatesDisplay");
+
+ // Send a hotplug connected event to set up the initial display modes.
+ // The primary display is already connected so this will update it.
+ // If we're running the test of an external display this will create it.
+ setExpectationsForConfigs(hwcDisplayId,
+ {{.id = 1,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 11'111'111,
+ .group = 1}},
+ /* activeConfig */ 1, 11'111'111);
+
+ mFakeComposerClient->hotplugDisplay(hwcDisplayId,
+ V2_1::IComposerCallback::Connection::CONNECTED);
+ waitForDisplayTransaction(hwcDisplayId);
+ EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true));
+
+ const auto displayId = physicalIdFromHwcDisplayId(hwcDisplayId);
+ const auto display = SurfaceComposerClient::getPhysicalDisplayToken(displayId);
+ EXPECT_FALSE(display == nullptr);
+
+ // Verify that the active mode and the supported moded are updated
+ {
+ DisplayConfig config;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+ EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+ EXPECT_EQ(1e9f / 11'111'111, config.refreshRate);
+
+ Vector<DisplayConfig> configs;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
+ EXPECT_EQ(configs.size(), 1);
+ }
+
+ // Send another hotplug connected event
+ setExpectationsForConfigs(hwcDisplayId,
+ {
+ {.id = 1,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 16'666'666,
+ .group = 1},
+ {.id = 2,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 11'111'111,
+ .group = 1},
+ {.id = 3,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 8'333'333,
+ .group = 1},
+ },
+ /* activeConfig */ 1, 16'666'666);
+
+ mFakeComposerClient->hotplugDisplay(hwcDisplayId,
+ V2_1::IComposerCallback::Connection::CONNECTED);
+ waitForDisplayTransaction(hwcDisplayId);
+ EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true));
+
+ // Verify that the active mode and the supported moded are updated
+ {
+ DisplayConfig config;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+ EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+ EXPECT_EQ(1e9f / 16'666'666, config.refreshRate);
+ }
+
+ Vector<DisplayConfig> configs;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
+ EXPECT_EQ(configs.size(), 3);
+
+ EXPECT_EQ(ui::Size(800, 1600), configs[0].resolution);
+ EXPECT_EQ(1e9f / 16'666'666, configs[0].refreshRate);
+
+ EXPECT_EQ(ui::Size(800, 1600), configs[1].resolution);
+ EXPECT_EQ(1e9f / 11'111'111, configs[1].refreshRate);
+
+ EXPECT_EQ(ui::Size(800, 1600), configs[2].resolution);
+ EXPECT_EQ(1e9f / 8'333'333, configs[2].refreshRate);
+
+ // Verify that we are able to switch to any of the modes
+ for (int i = configs.size() - 1; i >= 0; i--) {
+ const auto hwcId = i + 1;
+ // Set up HWC expectations for the mode change
+ if (mIs2_4Client) {
+ EXPECT_CALL(*mMockComposer,
+ setActiveConfigWithConstraints(hwcDisplayId, hwcId, _, _))
+ .WillOnce(Return(V2_4::Error::NONE));
+ } else {
+ EXPECT_CALL(*mMockComposer, setActiveConfig(hwcDisplayId, hwcId))
+ .WillOnce(Return(V2_1::Error::NONE));
+ }
+
+ EXPECT_EQ(NO_ERROR,
+ SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false,
+ configs[i].refreshRate,
+ configs[i].refreshRate,
+ configs[i].refreshRate,
+ configs[i].refreshRate));
+ // We need to refresh twice - once to apply the pending mode change request,
+ // and once to process the change.
+ waitForDisplayTransaction(hwcDisplayId);
+ waitForDisplayTransaction(hwcDisplayId);
+ EXPECT_TRUE(waitForConfigChangedEvent(hwcDisplayId, i))
+ << "Failure while switching to mode " << i;
+
+ DisplayConfig config;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+ EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+ EXPECT_EQ(configs[i].refreshRate, config.refreshRate);
+ }
+ }
+
sp<V2_1::IComposer> mFakeService;
sp<SurfaceComposerClient> mComposerClient;
@@ -911,6 +1026,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
using DisplayTest_2_2 = DisplayTest<FakeComposerService_2_2>;
TEST_F(DisplayTest_2_2, HotplugOneConfig) {
@@ -933,6 +1056,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
using DisplayTest_2_3 = DisplayTest<FakeComposerService_2_3>;
TEST_F(DisplayTest_2_3, HotplugOneConfig) {
@@ -955,6 +1086,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
using DisplayTest_2_4 = DisplayTest<FakeComposerService_2_4>;
TEST_F(DisplayTest_2_4, HotplugOneConfig) {
@@ -977,6 +1116,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
////////////////////////////////////////////////
template <typename FakeComposerService>
@@ -1639,82 +1786,6 @@
EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame()));
}
- void Test_DetachChildrenSameClient() {
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.show(mChild);
- ts.setPosition(mChild, 10, 10);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- }
-
- auto referenceFrame = Base::mBaseFrame;
- referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
- referenceFrame[CHILD_LAYER].mDisplayFrame =
- hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10};
- EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.setPosition(Base::mFGSurfaceControl, 0, 0);
- ts.detachChildren(Base::mFGSurfaceControl);
- }
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- ts.hide(mChild);
- }
-
- std::vector<RenderState> refFrame(2);
- refFrame[Base::BG_LAYER] = Base::mBaseFrame[Base::BG_LAYER];
- refFrame[Base::FG_LAYER] = Base::mBaseFrame[Base::FG_LAYER];
-
- EXPECT_TRUE(framesAreSame(refFrame, Base::sFakeComposer->getLatestFrame()));
- }
-
- void Test_DetachChildrenDifferentClient() {
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0,
- Base::mFGSurfaceControl->getHandle());
- ASSERT_TRUE(childNewClient != nullptr);
- ASSERT_TRUE(childNewClient->isValid());
- fillSurfaceRGBA8(childNewClient, LIGHT_GRAY);
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.hide(mChild);
- ts.show(childNewClient);
- ts.setPosition(childNewClient, 10, 10);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- }
-
- auto referenceFrame = Base::mBaseFrame;
- referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
- referenceFrame[CHILD_LAYER].mDisplayFrame =
- hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10};
- EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.detachChildren(Base::mFGSurfaceControl);
- ts.setPosition(Base::mFGSurfaceControl, 0, 0);
- }
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- ts.setPosition(childNewClient, 0, 0);
- ts.hide(childNewClient);
- }
-
- // Nothing should have changed. The child control becomes a no-op
- // zombie on detach. See comments for detachChildren in the
- // SurfaceControl.h file.
- EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
- }
-
// Regression test for b/37673612
void Test_ChildrenWithParentBufferTransform() {
{
@@ -1815,14 +1886,6 @@
Test_ReparentChildren();
}
-TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenSameClient) {
- Test_DetachChildrenSameClient();
-}
-
-TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenDifferentClient) {
- Test_DetachChildrenDifferentClient();
-}
-
// Regression test for b/37673612
TEST_F(ChildLayerTest_2_1, DISABLED_ChildrenWithParentBufferTransform) {
Test_ChildrenWithParentBufferTransform();
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index f2051d9..b696a6d 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -62,15 +62,9 @@
using testing::_;
using testing::AtLeast;
-using testing::Between;
-using testing::ByMove;
using testing::DoAll;
-using testing::Field;
-using testing::Invoke;
using testing::IsNull;
using testing::Mock;
-using testing::NotNull;
-using testing::Ref;
using testing::Return;
using testing::ReturnRef;
using testing::SetArgPointee;
@@ -86,7 +80,6 @@
constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
-constexpr int DEFAULT_CONFIG_ID = 0;
constexpr int DEFAULT_TEXTURE_ID = 6000;
constexpr int DEFAULT_LAYER_STACK = 7000;
@@ -147,7 +140,7 @@
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*vsyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
constexpr ISchedulerCallback* kCallback = nullptr;
@@ -548,12 +541,6 @@
setupLatchedBuffer(test, layer);
}
- static void setupBufferLayerPostFrameCallExpectations(CompositionTest* test) {
- // BufferLayer::onPostComposition(), when there is no present fence
- EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY, _))
- .WillOnce(DoAll(SetArgPointee<1>(DEFAULT_CONFIG_ID), Return(Error::NONE)));
- }
-
static void setupHwcSetGeometryCallExpectations(CompositionTest* test) {
if (!test->mDisplayOff) {
// TODO: Coverage of other values
@@ -632,8 +619,6 @@
.Times(1);
EXPECT_CALL(*test->mComposer, setLayerBuffer(HWC_DISPLAY, HWC_LAYER, _, _, _)).Times(1);
}
-
- setupBufferLayerPostFrameCallExpectations(test);
}
static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) {
@@ -793,7 +778,6 @@
static void setupInsecureREBufferCompositionCallExpectations(CompositionTest* test) {
setupInsecureREBufferCompositionCommonCallExpectations(test);
- Base::setupBufferLayerPostFrameCallExpectations(test);
}
static void setupInsecureREBufferScreenshotCompositionCallExpectations(CompositionTest* test) {
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index e2584e2..6e9f09b 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -14,9 +14,6 @@
* limitations under the License.
*/
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wextra"
#include "gmock/gmock-spec-builders.h"
#include "mock/MockTimeStats.h"
@@ -177,16 +174,17 @@
static constexpr const uid_t sUidOne = 0;
static constexpr pid_t sPidOne = 10;
static constexpr pid_t sPidTwo = 20;
+static constexpr int32_t sInputEventId = 5;
TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) {
int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
- EXPECT_EQ(getPredictions().size(), 1);
+ EXPECT_EQ(getPredictions().size(), 1u);
flushTokens(systemTime() + maxTokenRetentionTime);
int64_t token2 = mTokenManager->generateTokenForPredictions({10, 20, 30});
std::optional<TimelineItem> predictions = mTokenManager->getPredictionsForToken(token1);
// token1 should have expired
- EXPECT_EQ(getPredictions().size(), 1);
+ EXPECT_EQ(getPredictions().size(), 1u);
EXPECT_EQ(predictions.has_value(), false);
predictions = mTokenManager->getPredictionsForToken(token2);
@@ -194,16 +192,16 @@
}
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_getOwnerPidReturnsCorrectPid) {
- auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
+ auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne,
sLayerNameOne, sLayerNameOne);
- auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidTwo, sUidOne,
+ auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({}, sPidTwo, sUidOne,
sLayerNameOne, sLayerNameOne);
EXPECT_EQ(surfaceFrame1->getOwnerPid(), sPidOne);
EXPECT_EQ(surfaceFrame2->getOwnerPid(), sPidTwo);
}
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_noToken) {
- auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
+ auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne,
sLayerNameOne, sLayerNameOne);
EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::None);
}
@@ -211,21 +209,33 @@
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_expiredToken) {
int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
flushTokens(systemTime() + maxTokenRetentionTime);
- auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ auto surfaceFrame =
+ mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Expired);
}
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validToken) {
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
- auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ auto surfaceFrame =
+ mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Valid);
EXPECT_EQ(compareTimelineItems(surfaceFrame->getPredictions(), TimelineItem(10, 20, 30)), true);
}
+TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validInputEventId) {
+ int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
+ constexpr int32_t inputEventId = 1;
+ auto surfaceFrame =
+ mFrameTimeline->createSurfaceFrameForToken({token1, inputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
+
+ EXPECT_EQ(inputEventId, surfaceFrame->getInputEventId());
+}
+
TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) {
// Global increment
EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
@@ -234,8 +244,9 @@
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
- auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ auto surfaceFrame1 =
+ mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
// Set up the display frame
mFrameTimeline->setSfWakeUp(token1, 20, 11);
@@ -264,11 +275,11 @@
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 56, 60});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameTwo, sLayerNameTwo);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameTwo, sLayerNameTwo);
mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
@@ -288,8 +299,8 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto surfaceFrame3 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
surfaceFrame3->setPresentState(SurfaceFrame::PresentState::Dropped);
mFrameTimeline->addSurfaceFrame(surfaceFrame3);
@@ -320,8 +331,9 @@
int64_t sfToken = mTokenManager->generateTokenForPredictions(
{22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId},
+ sPidOne, sUidOne, sLayerNameOne,
+ sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -341,8 +353,8 @@
int64_t sfToken = mTokenManager->generateTokenForPredictions(
{22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -356,18 +368,18 @@
}
TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceAfterQueue) {
- auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, 0,
- "acquireFenceAfterQueue",
- "acquireFenceAfterQueue");
+ auto surfaceFrame =
+ mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue",
+ "acquireFenceAfterQueue");
surfaceFrame->setActualQueueTime(123);
surfaceFrame->setAcquireFenceTime(456);
EXPECT_EQ(surfaceFrame->getActuals().endTime, 456);
}
TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceBeforeQueue) {
- auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, 0,
- "acquireFenceAfterQueue",
- "acquireFenceAfterQueue");
+ auto surfaceFrame =
+ mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue",
+ "acquireFenceAfterQueue");
surfaceFrame->setActualQueueTime(456);
surfaceFrame->setAcquireFenceTime(123);
EXPECT_EQ(surfaceFrame->getActuals().endTime, 456);
@@ -383,8 +395,8 @@
// Size shouldn't exceed maxDisplayFrames - 64
for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
+ sLayerNameOne);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -395,15 +407,15 @@
// Increase the size to 256
mFrameTimeline->setMaxDisplayFrames(256);
- EXPECT_EQ(*maxDisplayFrames, 256);
+ EXPECT_EQ(*maxDisplayFrames, 256u);
// Global increment
EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_))
.Times(static_cast<int32_t>(*maxDisplayFrames + 10));
for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
+ sLayerNameOne);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -414,15 +426,15 @@
// Shrink the size to 128
mFrameTimeline->setMaxDisplayFrames(128);
- EXPECT_EQ(*maxDisplayFrames, 128);
+ EXPECT_EQ(*maxDisplayFrames, 128u);
// Global increment
EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_))
.Times(static_cast<int32_t>(*maxDisplayFrames + 10));
for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
+ sLayerNameOne);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -449,8 +461,8 @@
std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken1,
std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
11);
@@ -478,8 +490,8 @@
std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken1,
std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
30);
@@ -507,8 +519,8 @@
std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count()});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(
std::chrono::duration_cast<std::chrono::nanoseconds>(45ms).count());
mFrameTimeline->setSfWakeUp(sfToken1,
@@ -542,8 +554,9 @@
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
- auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ auto surfaceFrame1 =
+ mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
// Set up the display frame
mFrameTimeline->setSfWakeUp(token1, 20, 11);
@@ -558,7 +571,7 @@
mFrameTimeline->setSfPresent(55, presentFence2);
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
- EXPECT_EQ(packets.size(), 0);
+ EXPECT_EQ(packets.size(), 0u);
}
TEST_F(FrameTimelineTest, tracing_sanityTest) {
@@ -573,8 +586,9 @@
tracingSession->StartBlocking();
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
- auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ auto surfaceFrame1 =
+ mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
// Set up the display frame
mFrameTimeline->setSfWakeUp(token2, 20, 11);
@@ -594,7 +608,7 @@
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
// Display Frame 1 has 8 packets - 4 from DisplayFrame and 4 from SurfaceFrame.
- EXPECT_EQ(packets.size(), 8);
+ EXPECT_EQ(packets.size(), 8u);
}
TEST_F(FrameTimelineTest, traceDisplayFrame_invalidTokenDoesNotEmitTracePacket) {
@@ -622,7 +636,7 @@
tracingSession->StopBlocking();
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
- EXPECT_EQ(packets.size(), 0);
+ EXPECT_EQ(packets.size(), 0u);
}
TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) {
@@ -635,7 +649,7 @@
tracingSession->StartBlocking();
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
- auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
+ auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne,
sLayerNameOne, sLayerNameOne);
// Set up the display frame
@@ -657,7 +671,7 @@
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
// Display Frame 1 has 4 packets (SurfaceFrame shouldn't be traced since it has an invalid
// token).
- EXPECT_EQ(packets.size(), 4);
+ EXPECT_EQ(packets.size(), 4u);
}
void validateTraceEvent(const ProtoExpectedDisplayFrameStart& received,
@@ -791,12 +805,12 @@
tracingSession->StopBlocking();
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
- EXPECT_EQ(packets.size(), 4);
+ EXPECT_EQ(packets.size(), 4u);
// Packet - 0 : ExpectedDisplayFrameStart
const auto& packet0 = packets[0];
ASSERT_TRUE(packet0.has_timestamp());
- EXPECT_EQ(packet0.timestamp(), 10);
+ EXPECT_EQ(packet0.timestamp(), 10u);
ASSERT_TRUE(packet0.has_frame_timeline_event());
const auto& event0 = packet0.frame_timeline_event();
@@ -807,7 +821,7 @@
// Packet - 1 : FrameEnd (ExpectedDisplayFrame)
const auto& packet1 = packets[1];
ASSERT_TRUE(packet1.has_timestamp());
- EXPECT_EQ(packet1.timestamp(), 25);
+ EXPECT_EQ(packet1.timestamp(), 25u);
ASSERT_TRUE(packet1.has_frame_timeline_event());
const auto& event1 = packet1.frame_timeline_event();
@@ -818,7 +832,7 @@
// Packet - 2 : ActualDisplayFrameStart
const auto& packet2 = packets[2];
ASSERT_TRUE(packet2.has_timestamp());
- EXPECT_EQ(packet2.timestamp(), 20);
+ EXPECT_EQ(packet2.timestamp(), 20u);
ASSERT_TRUE(packet2.has_frame_timeline_event());
const auto& event2 = packet2.frame_timeline_event();
@@ -829,7 +843,7 @@
// Packet - 3 : FrameEnd (ActualDisplayFrame)
const auto& packet3 = packets[3];
ASSERT_TRUE(packet3.has_timestamp());
- EXPECT_EQ(packet3.timestamp(), 26);
+ EXPECT_EQ(packet3.timestamp(), 26u);
ASSERT_TRUE(packet3.has_frame_timeline_event());
const auto& event3 = packet3.frame_timeline_event();
@@ -853,8 +867,8 @@
int64_t displayFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setActualStartTime(0);
surfaceFrame1->setActualQueueTime(15);
surfaceFrame1->setAcquireFenceTime(20);
@@ -904,12 +918,12 @@
tracingSession->StopBlocking();
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
- EXPECT_EQ(packets.size(), 8);
+ EXPECT_EQ(packets.size(), 8u);
// Packet - 4 : ExpectedSurfaceFrameStart
const auto& packet4 = packets[4];
ASSERT_TRUE(packet4.has_timestamp());
- EXPECT_EQ(packet4.timestamp(), 10);
+ EXPECT_EQ(packet4.timestamp(), 10u);
ASSERT_TRUE(packet4.has_frame_timeline_event());
const auto& event4 = packet4.frame_timeline_event();
@@ -920,7 +934,7 @@
// Packet - 5 : FrameEnd (ExpectedSurfaceFrame)
const auto& packet5 = packets[5];
ASSERT_TRUE(packet5.has_timestamp());
- EXPECT_EQ(packet5.timestamp(), 25);
+ EXPECT_EQ(packet5.timestamp(), 25u);
ASSERT_TRUE(packet5.has_frame_timeline_event());
const auto& event5 = packet5.frame_timeline_event();
@@ -931,7 +945,7 @@
// Packet - 6 : ActualSurfaceFrameStart
const auto& packet6 = packets[6];
ASSERT_TRUE(packet6.has_timestamp());
- EXPECT_EQ(packet6.timestamp(), 10);
+ EXPECT_EQ(packet6.timestamp(), 10u);
ASSERT_TRUE(packet6.has_frame_timeline_event());
const auto& event6 = packet6.frame_timeline_event();
@@ -942,7 +956,7 @@
// Packet - 7 : FrameEnd (ActualSurfaceFrame)
const auto& packet7 = packets[7];
ASSERT_TRUE(packet7.has_timestamp());
- EXPECT_EQ(packet7.timestamp(), 20);
+ EXPECT_EQ(packet7.timestamp(), 20u);
ASSERT_TRUE(packet7.has_frame_timeline_event());
const auto& event7 = packet7.frame_timeline_event();
@@ -961,8 +975,8 @@
int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -1126,8 +1140,8 @@
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40});
int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(16);
mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1145,8 +1159,8 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(36);
mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1199,8 +1213,8 @@
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40});
int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(16);
mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1218,8 +1232,8 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(36);
mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1270,8 +1284,8 @@
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({42, 46, 50});
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 26, 60});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(40);
mFrameTimeline->setSfWakeUp(sfToken1, 42, 11);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1316,8 +1330,8 @@
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 30});
int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 50});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(26);
mFrameTimeline->setSfWakeUp(sfToken1, 32, 11);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1335,8 +1349,8 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(40);
mFrameTimeline->setSfWakeUp(sfToken2, 43, 11);
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1390,8 +1404,8 @@
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 56, 60});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({112, 116, 120});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(50);
mFrameTimeline->setSfWakeUp(sfToken1, 52, 30);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1409,8 +1423,8 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(84);
mFrameTimeline->setSfWakeUp(sfToken2, 112, 30);
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented, 54);
@@ -1456,6 +1470,3 @@
JankType::AppDeadlineMissed | JankType::BufferStuffing);
}
} // namespace android::frametimeline
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wextra"
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index 1e24c0a..6b82170 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -175,90 +175,5 @@
EXPECT_EQ(hal::Error::UNSUPPORTED, result);
}
-class HWComposerConfigsTest : public testing::Test {
-public:
- Hwc2::mock::Composer* mHal = new StrictMock<Hwc2::mock::Composer>();
- MockHWC2ComposerCallback mCallback;
-
- void setActiveConfig(Config config) {
- EXPECT_CALL(*mHal, getActiveConfig(_, _))
- .WillRepeatedly(DoAll(SetArgPointee<1>(config), Return(V2_1::Error::NONE)));
- }
-
- void setDisplayConfigs(std::vector<Config> configs) {
- EXPECT_CALL(*mHal, getDisplayConfigs(_, _))
- .WillOnce(DoAll(SetArgPointee<1>(configs), Return(V2_1::Error::NONE)));
- EXPECT_CALL(*mHal, getDisplayAttribute(_, _, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<3>(1), Return(V2_1::Error::NONE)));
- }
-
- void testSetActiveModeWithConstraintsCommon(bool isVsyncPeriodSwitchSupported);
-};
-
-void HWComposerConfigsTest::testSetActiveModeWithConstraintsCommon(
- bool isVsyncPeriodSwitchSupported) {
- EXPECT_CALL(*mHal, getMaxVirtualDisplayCount()).WillOnce(Return(0));
- EXPECT_CALL(*mHal, getCapabilities()).WillOnce(Return(std::vector<hal::Capability>{}));
- EXPECT_CALL(*mHal, getLayerGenericMetadataKeys(_)).WillOnce(Return(V2_4::Error::UNSUPPORTED));
- EXPECT_CALL(*mHal, registerCallback(_));
- EXPECT_CALL(*mHal, setVsyncEnabled(_, _)).WillRepeatedly(Return(V2_1::Error::NONE));
- EXPECT_CALL(*mHal, getDisplayIdentificationData(_, _, _))
- .WillRepeatedly(Return(V2_1::Error::UNSUPPORTED));
- EXPECT_CALL(*mHal, setClientTargetSlotCount(_)).WillRepeatedly(Return(V2_1::Error::NONE));
-
- EXPECT_CALL(*mHal, isVsyncPeriodSwitchSupported())
- .WillRepeatedly(Return(isVsyncPeriodSwitchSupported));
-
- if (isVsyncPeriodSwitchSupported) {
- EXPECT_CALL(*mHal, setActiveConfigWithConstraints(_, _, _, _))
- .WillRepeatedly(Return(V2_4::Error::NONE));
- } else {
- EXPECT_CALL(*mHal, setActiveConfig(_, _)).WillRepeatedly(Return(V2_1::Error::NONE));
- }
-
- impl::HWComposer hwc{std::unique_ptr<Hwc2::Composer>(mHal)};
- hwc.setConfiguration(&mCallback, 123);
-
- setDisplayConfigs({15});
- setActiveConfig(15);
-
- const auto physicalId = PhysicalDisplayId::fromPort(0);
- const hal::HWDisplayId hwcId = 0;
- hwc.allocatePhysicalDisplay(hwcId, physicalId);
-
- hal::VsyncPeriodChangeConstraints constraints;
- constraints.desiredTimeNanos = systemTime();
- constraints.seamlessRequired = false;
-
- hal::VsyncPeriodChangeTimeline timeline = {0, 0, 0};
- constexpr Config kConfigIndex = 0;
- const auto status =
- hwc.setActiveModeWithConstraints(physicalId, kConfigIndex, constraints, &timeline);
- EXPECT_EQ(NO_ERROR, status);
-
- const std::vector<Config> kConfigs{7, 8, 9, 10, 11};
- // Change the set of supported modes.
- setDisplayConfigs(kConfigs);
- setActiveConfig(11);
- hwc.onHotplug(hwcId, hal::Connection::CONNECTED);
- hwc.allocatePhysicalDisplay(hwcId, physicalId);
-
- for (size_t configIndex = 0; configIndex < kConfigs.size(); configIndex++) {
- const auto status =
- hwc.setActiveModeWithConstraints(physicalId,
- static_cast<hal::HWConfigId>(configIndex),
- constraints, &timeline);
- EXPECT_EQ(NO_ERROR, status) << "Error when switching to config " << configIndex;
- }
-}
-
-TEST_F(HWComposerConfigsTest, setActiveModeWithConstraintsWithVsyncSwitchingSupported) {
- testSetActiveModeWithConstraintsCommon(/*supported=*/true);
-}
-
-TEST_F(HWComposerConfigsTest, setActiveModeWithConstraintsWithVsyncSwitchingNotSupported) {
- testSetActiveModeWithConstraintsCommon(/*supported=*/false);
-}
-
} // namespace
} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index c5deb7c..abecd4b 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -144,7 +144,7 @@
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*vsyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
std::move(eventThread), std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index e060df2..a6d07d0 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -185,7 +185,7 @@
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*vsyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
std::move(eventThread), std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
index 8552e15..b713334 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
@@ -669,7 +669,7 @@
// --------------------------------------------------------------------
// Call Expectations
- EXPECT_CALL(*displaySurface, resizeBuffers(newWidth, oldHeight)).Times(1);
+ EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(newWidth, oldHeight))).Times(1);
// --------------------------------------------------------------------
// Invocation
@@ -714,7 +714,7 @@
// --------------------------------------------------------------------
// Call Expectations
- EXPECT_CALL(*displaySurface, resizeBuffers(oldWidth, newHeight)).Times(1);
+ EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(oldWidth, newHeight))).Times(1);
// --------------------------------------------------------------------
// Invocation
@@ -764,7 +764,7 @@
// --------------------------------------------------------------------
// Call Expectations
- EXPECT_CALL(*displaySurface, resizeBuffers(kNewWidth, kNewHeight)).Times(1);
+ EXPECT_CALL(*displaySurface, resizeBuffers(kNewSize.getSize())).Times(1);
// --------------------------------------------------------------------
// Invocation
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 2701f47..3787c43 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -41,6 +41,7 @@
#include "SurfaceFlingerDefaultFactory.h"
#include "SurfaceInterceptor.h"
#include "TestableScheduler.h"
+#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockDisplayIdGenerator.h"
#include "mock/MockFrameTimeline.h"
#include "mock/MockFrameTracer.h"
@@ -353,7 +354,8 @@
bool regionSampling) {
ScreenCaptureResults captureResults;
return mFlinger->renderScreenImplLocked(renderArea, traverseLayers, buffer, forSystem,
- regionSampling, captureResults);
+ regionSampling, false /* grayscale */,
+ captureResults);
}
auto traverseLayersInLayerStack(ui::LayerStack layerStack, int32_t uid,
@@ -366,18 +368,17 @@
return mFlinger->SurfaceFlinger::getDisplayNativePrimaries(displayToken, primaries);
}
- auto& getTransactionQueue() { return mFlinger->mTransactionQueues; }
+ auto& getTransactionQueue() { return mFlinger->mTransactionQueue; }
+ auto& getPendingTransactionQueue() { return mFlinger->mPendingTransactionQueues; }
- auto setTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
- const Vector<DisplayState>& displays, uint32_t flags,
- const sp<IBinder>& applyToken,
- const InputWindowCommands& inputWindowCommands,
- int64_t desiredPresentTime, bool isAutoTimestamp,
- const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
- std::vector<ListenerCallbacks>& listenerCallbacks,
- uint64_t transactionId) {
- return mFlinger->setTransactionState(frameTimelineVsyncId, states, displays, flags,
- applyToken, inputWindowCommands, desiredPresentTime,
+ auto setTransactionState(
+ const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states,
+ const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
+ bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+ std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
+ return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken,
+ inputWindowCommands, desiredPresentTime,
isAutoTimestamp, uncacheBuffer, hasListenerCallbacks,
listenerCallbacks, transactionId);
}
@@ -478,7 +479,7 @@
static constexpr hal::HWDisplayId DEFAULT_HWC_DISPLAY_ID = 1000;
static constexpr int32_t DEFAULT_WIDTH = 1920;
static constexpr int32_t DEFAULT_HEIGHT = 1280;
- static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666;
+ static constexpr int32_t DEFAULT_VSYNC_PERIOD = 16'666'666;
static constexpr int32_t DEFAULT_CONFIG_GROUP = 7;
static constexpr int32_t DEFAULT_DPI = 320;
static constexpr hal::HWConfigId DEFAULT_ACTIVE_CONFIG = 0;
@@ -503,8 +504,8 @@
return *this;
}
- auto& setRefreshRate(int32_t refreshRate) {
- mRefreshRate = refreshRate;
+ auto& setVsyncPeriod(int32_t vsyncPeriod) {
+ mVsyncPeriod = vsyncPeriod;
return *this;
}
@@ -533,7 +534,12 @@
return *this;
}
- void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) {
+ void inject(TestableSurfaceFlinger* flinger, Hwc2::mock::Composer* composer) {
+ using ::testing::_;
+ using ::testing::DoAll;
+ using ::testing::Return;
+ using ::testing::SetArgPointee;
+
static const std::unordered_set<hal::Capability> defaultCapabilities;
if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities;
@@ -548,15 +554,39 @@
display->setPowerMode(mPowerMode);
flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = std::move(display);
- auto config = DisplayMode::Builder(mActiveConfig)
- .setWidth(mWidth)
- .setHeight(mHeight)
- .setVsyncPeriod(mRefreshRate)
- .setDpiX(mDpiX)
- .setDpiY(mDpiY)
- .setConfigGroup(mConfigGroup)
- .build();
- flinger->mutableHwcDisplayData()[mDisplayId].modes.push_back(config);
+ EXPECT_CALL(*composer, getDisplayConfigs(mHwcDisplayId, _))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<1>(std::vector<hal::HWConfigId>{mActiveConfig}),
+ Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::WIDTH, _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mWidth), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::HEIGHT,
+ _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mHeight), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig,
+ hal::Attribute::VSYNC_PERIOD, _))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<3>(mVsyncPeriod), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::DPI_X, _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mDpiX), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::DPI_Y, _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mDpiY), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig,
+ hal::Attribute::CONFIG_GROUP, _))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<3>(mConfigGroup), Return(hal::Error::NONE)));
if (mHwcDisplayType == hal::DisplayType::PHYSICAL) {
const auto physicalId = PhysicalDisplayId::tryCast(mDisplayId);
@@ -582,10 +612,10 @@
hal::HWDisplayId mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID;
int32_t mWidth = DEFAULT_WIDTH;
int32_t mHeight = DEFAULT_HEIGHT;
- int32_t mRefreshRate = DEFAULT_REFRESH_RATE;
+ int32_t mVsyncPeriod = DEFAULT_VSYNC_PERIOD;
int32_t mDpiX = DEFAULT_DPI;
- int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
int32_t mDpiY = DEFAULT_DPI;
+ int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
hal::HWConfigId mActiveConfig = DEFAULT_ACTIVE_CONFIG;
hal::PowerMode mPowerMode = DEFAULT_POWER_MODE;
const std::unordered_set<hal::Capability>* mCapabilities = nullptr;
@@ -603,6 +633,21 @@
mHwcDisplayId(hwcDisplayId) {
mCreationArgs.connectionType = connectionType;
mCreationArgs.isPrimary = isPrimary;
+
+ mActiveModeId = DisplayModeId(0);
+ DisplayModePtr activeMode =
+ DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)
+ .setId(mActiveModeId)
+ .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH)
+ .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT)
+ .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)
+ .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI)
+ .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI)
+ .setConfigGroup(0)
+ .build();
+
+ DisplayModes modes{activeMode};
+ mCreationArgs.supportedModes = modes;
}
sp<IBinder> token() const { return mDisplayToken; }
@@ -625,6 +670,16 @@
auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; }
+ auto& setActiveMode(DisplayModeId mode) {
+ mActiveModeId = mode;
+ return *this;
+ }
+
+ auto& setSupportedModes(DisplayModes mode) {
+ mCreationArgs.supportedModes = mode;
+ return *this;
+ }
+
auto& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {
mCreationArgs.nativeWindow = nativeWindow;
return *this;
@@ -677,6 +732,9 @@
state.isSecure = mCreationArgs.isSecure;
sp<DisplayDevice> device = new DisplayDevice(mCreationArgs);
+ if (!device->isVirtual()) {
+ device->setActiveMode(mActiveModeId);
+ }
mFlinger.mutableDisplays().emplace(mDisplayToken, device);
mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);
@@ -693,6 +751,7 @@
sp<BBinder> mDisplayToken = new BBinder();
DisplayDeviceCreationArgs mCreationArgs;
const std::optional<hal::HWDisplayId> mHwcDisplayId;
+ DisplayModeId mActiveModeId;
};
private:
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 06275c6..eb2c1ba 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -14,10 +14,6 @@
* limitations under the License.
*/
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wextra"
#undef LOG_TAG
#define LOG_TAG "CompositionTest"
@@ -76,7 +72,7 @@
EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*mVSyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
mFlinger.setupScheduler(std::unique_ptr<mock::VsyncController>(mVsyncController),
std::unique_ptr<mock::VSyncTracker>(mVSyncTracker),
@@ -100,50 +96,50 @@
InputWindowCommands inputWindowCommands;
int64_t desiredPresentTime = 0;
bool isAutoTimestamp = true;
- int64_t frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+ FrameTimelineInfo frameTimelineInfo;
client_cache_t uncacheBuffer;
- int64_t id = -1;
+ uint64_t id = static_cast<uint64_t>(-1);
+ static_assert(0xffffffffffffffff == static_cast<uint64_t>(-1));
};
void checkEqual(TransactionInfo info, SurfaceFlinger::TransactionState state) {
- EXPECT_EQ(0, info.states.size());
- EXPECT_EQ(0, state.states.size());
+ EXPECT_EQ(0u, info.states.size());
+ EXPECT_EQ(0u, state.states.size());
- EXPECT_EQ(0, info.displays.size());
- EXPECT_EQ(0, state.displays.size());
+ EXPECT_EQ(0u, info.displays.size());
+ EXPECT_EQ(0u, state.displays.size());
EXPECT_EQ(info.flags, state.flags);
EXPECT_EQ(info.desiredPresentTime, state.desiredPresentTime);
}
void setupSingle(TransactionInfo& transaction, uint32_t flags, bool syncInputWindows,
int64_t desiredPresentTime, bool isAutoTimestamp,
- int64_t frameTimelineVsyncId) {
+ const FrameTimelineInfo& frameTimelineInfo) {
mTransactionNumber++;
transaction.flags |= flags; // ISurfaceComposer::eSynchronous;
transaction.inputWindowCommands.syncInputWindows = syncInputWindows;
transaction.desiredPresentTime = desiredPresentTime;
transaction.isAutoTimestamp = isAutoTimestamp;
- transaction.frameTimelineVsyncId = frameTimelineVsyncId;
+ transaction.frameTimelineInfo = frameTimelineInfo;
}
void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
- ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+ ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
// called in SurfaceFlinger::signalTransaction
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillOnce(Return(systemTime()));
TransactionInfo transaction;
setupSingle(transaction, flags, syncInputWindows,
/*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- ISurfaceComposer::INVALID_VSYNC_ID);
+ FrameTimelineInfo{});
nsecs_t applicationTime = systemTime();
- mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states,
+ mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
transaction.displays, transaction.flags,
transaction.applyToken, transaction.inputWindowCommands,
transaction.desiredPresentTime, transaction.isAutoTimestamp,
transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
transaction.id);
- // This transaction should not have been placed on the transaction queue.
// If transaction is synchronous or syncs input windows, SF
// applyTransactionState should time out (5s) wating for SF to commit
// the transaction or to receive a signal that syncInputWindows has
@@ -154,12 +150,13 @@
} else {
EXPECT_LE(returnedTime, applicationTime + s2ns(5));
}
+ // Each transaction should have been placed on the transaction queue
auto transactionQueue = mFlinger.getTransactionQueue();
- EXPECT_EQ(0, transactionQueue.size());
+ EXPECT_EQ(1u, transactionQueue.size());
}
void PlaceOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
- ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+ ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
// called in SurfaceFlinger::signalTransaction
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
@@ -170,10 +167,9 @@
.WillOnce(Return(time + nsecs_t(5 * 1e8)));
TransactionInfo transaction;
setupSingle(transaction, flags, syncInputWindows,
- /*desiredPresentTime*/ time + s2ns(1), false,
- ISurfaceComposer::INVALID_VSYNC_ID);
+ /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{});
nsecs_t applicationSentTime = systemTime();
- mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states,
+ mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
transaction.displays, transaction.flags,
transaction.applyToken, transaction.inputWindowCommands,
transaction.desiredPresentTime, transaction.isAutoTimestamp,
@@ -184,11 +180,11 @@
EXPECT_LE(returnedTime, applicationSentTime + s2ns(5));
// This transaction should have been placed on the transaction queue
auto transactionQueue = mFlinger.getTransactionQueue();
- EXPECT_EQ(1, transactionQueue.size());
+ EXPECT_EQ(1u, transactionQueue.size());
}
void BlockedByPriorTransaction(uint32_t flags, bool syncInputWindows) {
- ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+ ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
// called in SurfaceFlinger::signalTransaction
nsecs_t time = systemTime();
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
@@ -197,18 +193,17 @@
// transaction that should go on the pending thread
TransactionInfo transactionA;
setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false,
- /*desiredPresentTime*/ time + s2ns(1), false,
- ISurfaceComposer::INVALID_VSYNC_ID);
+ /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{});
// transaction that would not have gone on the pending thread if not
// blocked
TransactionInfo transactionB;
setupSingle(transactionB, flags, syncInputWindows,
/*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- ISurfaceComposer::INVALID_VSYNC_ID);
+ FrameTimelineInfo{});
nsecs_t applicationSentTime = systemTime();
- mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states,
+ mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
transactionA.displays, transactionA.flags,
transactionA.applyToken, transactionA.inputWindowCommands,
transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
@@ -219,9 +214,11 @@
// (5s is the timeout period that applyTransactionState waits for SF to
// commit the transaction)
EXPECT_LE(systemTime(), applicationSentTime + s2ns(5));
+ // transaction that would goes to pending transaciton queue.
+ mFlinger.flushTransactionQueues();
applicationSentTime = systemTime();
- mFlinger.setTransactionState(transactionB.frameTimelineVsyncId, transactionB.states,
+ mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
transactionB.displays, transactionB.flags,
transactionB.applyToken, transactionB.inputWindowCommands,
transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
@@ -238,12 +235,15 @@
EXPECT_LE(systemTime(), applicationSentTime + s2ns(5));
}
+ // transaction that would goes to pending transaciton queue.
+ mFlinger.flushTransactionQueues();
+
// check that there is one binder on the pending queue.
- auto transactionQueue = mFlinger.getTransactionQueue();
- EXPECT_EQ(1, transactionQueue.size());
+ auto transactionQueue = mFlinger.getPendingTransactionQueue();
+ EXPECT_EQ(1u, transactionQueue.size());
auto& [applyToken, transactionStates] = *(transactionQueue.begin());
- EXPECT_EQ(2, transactionStates.size());
+ EXPECT_EQ(2u, transactionStates.size());
auto& transactionStateA = transactionStates.front();
transactionStates.pop();
@@ -258,7 +258,7 @@
};
TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) {
- ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+ ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
// called in SurfaceFlinger::signalTransaction
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
@@ -268,20 +268,17 @@
.WillOnce(Return(s2ns(2)));
TransactionInfo transactionA; // transaction to go on pending queue
setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false,
- /*desiredPresentTime*/ s2ns(1), false, ISurfaceComposer::INVALID_VSYNC_ID);
- mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states,
+ /*desiredPresentTime*/ s2ns(1), false, FrameTimelineInfo{});
+ mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
transactionA.displays, transactionA.flags, transactionA.applyToken,
transactionA.inputWindowCommands, transactionA.desiredPresentTime,
transactionA.isAutoTimestamp, transactionA.uncacheBuffer,
mHasListenerCallbacks, mCallbacks, transactionA.id);
auto& transactionQueue = mFlinger.getTransactionQueue();
- ASSERT_EQ(1, transactionQueue.size());
+ ASSERT_EQ(1u, transactionQueue.size());
- auto& [applyToken, transactionStates] = *(transactionQueue.begin());
- ASSERT_EQ(1, transactionStates.size());
-
- auto& transactionState = transactionStates.front();
+ auto& transactionState = transactionQueue.front();
checkEqual(transactionA, transactionState);
// because flushing uses the cached expected present time, we send an empty
@@ -289,8 +286,8 @@
// different process) to re-query and reset the cached expected present time
TransactionInfo empty;
empty.applyToken = sp<IBinder>();
- mFlinger.setTransactionState(empty.frameTimelineVsyncId, empty.states, empty.displays,
- empty.flags, empty.applyToken, empty.inputWindowCommands,
+ mFlinger.setTransactionState(empty.frameTimelineInfo, empty.states, empty.displays, empty.flags,
+ empty.applyToken, empty.inputWindowCommands,
empty.desiredPresentTime, empty.isAutoTimestamp,
empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id);
@@ -298,7 +295,7 @@
// passed
mFlinger.flushTransactionQueues();
- EXPECT_EQ(0, transactionQueue.size());
+ EXPECT_EQ(0u, transactionQueue.size());
}
TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_Synchronous) {
@@ -343,6 +340,3 @@
EXPECT_EQ(nullptr, ret.promote().get());
}
} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index a13f93b..2fefa45 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -84,11 +84,13 @@
}
void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+ ASSERT_NE(nullptr, mOutBuffer);
ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
TransactionUtils::expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance);
}
void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+ ASSERT_NE(nullptr, mOutBuffer);
ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
const bool leftBorder = rect.left > 0;
const bool topBorder = rect.top > 0;
@@ -146,6 +148,7 @@
}
void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
+ ASSERT_NE(nullptr, mOutBuffer);
ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x));
if (r != pixel[0] || g != pixel[1] || b != pixel[2]) {
@@ -163,10 +166,14 @@
void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); }
explicit ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
- mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
+ if (mOutBuffer) {
+ mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
+ }
}
- ~ScreenCapture() { mOutBuffer->unlock(); }
+ ~ScreenCapture() {
+ if (mOutBuffer) mOutBuffer->unlock();
+ }
private:
sp<GraphicBuffer> mOutBuffer;