Merge "Add frame rate flexibility token" into rvc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index b475c90..c85c7cf 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2677,15 +2677,6 @@
MYLOGI("User denied consent. Returning\n");
return status;
}
- if (options_->do_screenshot &&
- options_->screenshot_fd.get() != -1 &&
- !options_->is_screenshot_copied) {
- bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
- options_->screenshot_fd.get());
- if (copy_succeeded) {
- android::os::UnlinkAndLogOnError(screenshot_path_);
- }
- }
if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
MYLOGI(
"Did not receive user consent yet."
@@ -2815,6 +2806,16 @@
bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
if (copy_succeeded) {
android::os::UnlinkAndLogOnError(path_);
+ if (options_->do_screenshot &&
+ options_->screenshot_fd.get() != -1 &&
+ !options_->is_screenshot_copied) {
+ copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
+ options_->screenshot_fd.get());
+ options_->is_screenshot_copied = copy_succeeded;
+ if (copy_succeeded) {
+ android::os::UnlinkAndLogOnError(screenshot_path_);
+ }
+ }
}
return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
} else if (consent_result == UserConsentResult::UNAVAILABLE) {
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 1af6edd..5ee6a9f 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -374,6 +374,14 @@
bool skip_compilation = vold_decrypt == "trigger_restart_min_framework" ||
vold_decrypt == "1";
+ std::string updatable_bcp_packages =
+ MapPropertyToArg("dalvik.vm.dex2oat-updatable-bcp-packages-file",
+ "--updatable-bcp-packages-file=%s");
+ if (updatable_bcp_packages.empty()) {
+ // Make dex2oat fail by providing non-existent file name.
+ updatable_bcp_packages = "--updatable-bcp-packages-file=/nonx/updatable-bcp-packages.txt";
+ }
+
std::string resolve_startup_string_arg =
MapPropertyToArg("persist.device_config.runtime.dex2oat_resolve_startup_strings",
"--resolve-startup-const-strings=%s");
@@ -520,6 +528,7 @@
AddRuntimeArg(dex2oat_Xms_arg);
AddRuntimeArg(dex2oat_Xmx_arg);
+ AddArg(updatable_bcp_packages);
AddArg(resolve_startup_string_arg);
AddArg(image_block_size_arg);
AddArg(dex2oat_compiler_filter_arg);
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 3ee8187..c7b7551 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -40,7 +40,7 @@
},
srcs: ["binderDriverInterfaceTest.cpp"],
- test_suites: ["device-tests", "vts-core"],
+ test_suites: ["device-tests", "vts"],
}
cc_test {
@@ -69,7 +69,7 @@
"libbinder",
"libutils",
],
- test_suites: ["device-tests", "vts-core"],
+ test_suites: ["device-tests", "vts"],
require_root: true,
}
@@ -131,7 +131,7 @@
"liblog",
"libutils",
],
- test_suites: ["device-tests", "vts-core"],
+ test_suites: ["device-tests", "vts"],
require_root: true,
}
diff --git a/services/inputflinger/tests/EventHub_test.cpp b/services/inputflinger/tests/EventHub_test.cpp
index be2e19e..71731b0 100644
--- a/services/inputflinger/tests/EventHub_test.cpp
+++ b/services/inputflinger/tests/EventHub_test.cpp
@@ -34,6 +34,7 @@
using android::sp;
using android::UinputHomeKey;
using std::chrono_literals::operator""ms;
+using std::chrono_literals::operator""s;
static constexpr bool DEBUG = false;
@@ -70,11 +71,12 @@
mEventHub = std::make_unique<EventHub>();
consumeInitialDeviceAddedEvents();
mKeyboard = createUinputDevice<UinputHomeKey>();
- mDeviceId = waitForDeviceCreation();
+ ASSERT_NO_FATAL_FAILURE(mDeviceId = waitForDeviceCreation());
}
virtual void TearDown() override {
mKeyboard.reset();
waitForDeviceClose(mDeviceId);
+ assertNoMoreEvents();
}
/**
@@ -83,21 +85,38 @@
int32_t waitForDeviceCreation();
void waitForDeviceClose(int32_t deviceId);
void consumeInitialDeviceAddedEvents();
- std::vector<RawEvent> getEvents(std::chrono::milliseconds timeout = 5ms);
+ void assertNoMoreEvents();
+ /**
+ * Read events from the EventHub.
+ *
+ * If expectedEvents is set, wait for a significant period of time to try and ensure that
+ * the expected number of events has been read. The number of returned events
+ * may be smaller (if timeout has been reached) or larger than expectedEvents.
+ *
+ * If expectedEvents is not set, return all of the immediately available events.
+ */
+ std::vector<RawEvent> getEvents(std::optional<size_t> expectedEvents = std::nullopt);
};
-std::vector<RawEvent> EventHubTest::getEvents(std::chrono::milliseconds timeout) {
+std::vector<RawEvent> EventHubTest::getEvents(std::optional<size_t> expectedEvents) {
static constexpr size_t EVENT_BUFFER_SIZE = 256;
std::array<RawEvent, EVENT_BUFFER_SIZE> eventBuffer;
std::vector<RawEvent> events;
while (true) {
- size_t count =
+ std::chrono::milliseconds timeout = 0s;
+ if (expectedEvents) {
+ timeout = 2s;
+ }
+ const size_t count =
mEventHub->getEvents(timeout.count(), eventBuffer.data(), eventBuffer.size());
if (count == 0) {
break;
}
events.insert(events.end(), eventBuffer.begin(), eventBuffer.begin() + count);
+ if (expectedEvents && events.size() >= *expectedEvents) {
+ break;
+ }
}
if (DEBUG) {
dumpEvents(events);
@@ -111,7 +130,7 @@
* it will return a lot of "device added" type of events.
*/
void EventHubTest::consumeInitialDeviceAddedEvents() {
- std::vector<RawEvent> events = getEvents(0ms);
+ std::vector<RawEvent> events = getEvents();
std::set<int32_t /*deviceId*/> existingDevices;
// All of the events should be DEVICE_ADDED type, except the last one.
for (size_t i = 0; i < events.size() - 1; i++) {
@@ -128,8 +147,11 @@
int32_t EventHubTest::waitForDeviceCreation() {
// Wait a little longer than usual, to ensure input device has time to be created
- std::vector<RawEvent> events = getEvents(20ms);
- EXPECT_EQ(2U, events.size()); // Using "expect" because the function is non-void.
+ std::vector<RawEvent> events = getEvents(2);
+ if (events.size() != 2) {
+ ADD_FAILURE() << "Instead of 2 events, received " << events.size();
+ return 0; // this value is unused
+ }
const RawEvent& deviceAddedEvent = events[0];
EXPECT_EQ(static_cast<int32_t>(EventHubInterface::DEVICE_ADDED), deviceAddedEvent.type);
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceAddedEvent.deviceId);
@@ -142,7 +164,7 @@
}
void EventHubTest::waitForDeviceClose(int32_t deviceId) {
- std::vector<RawEvent> events = getEvents(20ms);
+ std::vector<RawEvent> events = getEvents(2);
ASSERT_EQ(2U, events.size());
const RawEvent& deviceRemovedEvent = events[0];
EXPECT_EQ(static_cast<int32_t>(EventHubInterface::DEVICE_REMOVED), deviceRemovedEvent.type);
@@ -152,6 +174,11 @@
finishedDeviceScanEvent.type);
}
+void EventHubTest::assertNoMoreEvents() {
+ std::vector<RawEvent> events = getEvents();
+ ASSERT_TRUE(events.empty());
+}
+
/**
* Ensure that input_events are generated with monotonic clock.
* That means input_event should receive a timestamp that is in the future of the time
@@ -162,7 +189,7 @@
nsecs_t lastEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
ASSERT_NO_FATAL_FAILURE(mKeyboard->pressAndReleaseHomeKey());
- std::vector<RawEvent> events = getEvents();
+ std::vector<RawEvent> events = getEvents(4);
ASSERT_EQ(4U, events.size()) << "Expected to receive 2 keys and 2 syncs, total of 4 events";
for (const RawEvent& event : events) {
// Cannot use strict comparison because the events may happen too quickly
diff --git a/services/inputflinger/tests/UinputDevice.cpp b/services/inputflinger/tests/UinputDevice.cpp
index 99480b7..10e7293 100644
--- a/services/inputflinger/tests/UinputDevice.cpp
+++ b/services/inputflinger/tests/UinputDevice.cpp
@@ -44,9 +44,7 @@
device.id.product = 0x01;
device.id.version = 1;
- // Using EXPECT instead of ASSERT to allow the device creation to continue even when
- // some failures are reported when configuring the device.
- EXPECT_NO_FATAL_FAILURE(configureDevice(mDeviceFd, &device));
+ ASSERT_NO_FATAL_FAILURE(configureDevice(mDeviceFd, &device));
if (write(mDeviceFd, &device, sizeof(device)) < 0) {
FAIL() << "Could not write uinput_user_dev struct into uinput file descriptor: "
@@ -70,7 +68,7 @@
" with value %" PRId32 " : %s",
type, code, value, strerror(errno));
ALOGE("%s", msg.c_str());
- ADD_FAILURE() << msg.c_str();
+ FAIL() << msg.c_str();
}
}
@@ -82,41 +80,41 @@
void UinputKeyboard::configureDevice(int fd, uinput_user_dev* device) {
// enable key press/release event
if (ioctl(fd, UI_SET_EVBIT, EV_KEY)) {
- ADD_FAILURE() << "Error in ioctl : UI_SET_EVBIT : EV_KEY: " << strerror(errno);
+ FAIL() << "Error in ioctl : UI_SET_EVBIT : EV_KEY: " << strerror(errno);
}
// enable set of KEY events
std::for_each(mKeys.begin(), mKeys.end(), [fd](int key) {
if (ioctl(fd, UI_SET_KEYBIT, key)) {
- ADD_FAILURE() << "Error in ioctl : UI_SET_KEYBIT : " << key << " : " << strerror(errno);
+ FAIL() << "Error in ioctl : UI_SET_KEYBIT : " << key << " : " << strerror(errno);
}
});
// enable synchronization event
if (ioctl(fd, UI_SET_EVBIT, EV_SYN)) {
- ADD_FAILURE() << "Error in ioctl : UI_SET_EVBIT : EV_SYN: " << strerror(errno);
+ FAIL() << "Error in ioctl : UI_SET_EVBIT : EV_SYN: " << strerror(errno);
}
}
void UinputKeyboard::pressKey(int key) {
if (mKeys.find(key) == mKeys.end()) {
- ADD_FAILURE() << mName << ": Cannot inject key press: Key not found: " << key;
+ FAIL() << mName << ": Cannot inject key press: Key not found: " << key;
}
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_KEY, key, 1));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_KEY, key, 1);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
void UinputKeyboard::releaseKey(int key) {
if (mKeys.find(key) == mKeys.end()) {
- ADD_FAILURE() << mName << ": Cannot inject key release: Key not found: " << key;
+ FAIL() << mName << ": Cannot inject key release: Key not found: " << key;
}
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_KEY, key, 0));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_KEY, key, 0);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
void UinputKeyboard::pressAndReleaseKey(int key) {
- EXPECT_NO_FATAL_FAILURE(pressKey(key));
- EXPECT_NO_FATAL_FAILURE(releaseKey(key));
+ pressKey(key);
+ releaseKey(key);
}
// --- UinputHomeKey ---
@@ -124,7 +122,7 @@
UinputHomeKey::UinputHomeKey() : UinputKeyboard({KEY_HOME}) {}
void UinputHomeKey::pressAndReleaseHomeKey() {
- EXPECT_NO_FATAL_FAILURE(pressAndReleaseKey(KEY_HOME));
+ pressAndReleaseKey(KEY_HOME);
}
// --- UinputTouchScreen ---
@@ -158,35 +156,35 @@
}
void UinputTouchScreen::sendSlot(int32_t slot) {
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_SLOT, slot));
+ injectEvent(EV_ABS, ABS_MT_SLOT, slot);
}
void UinputTouchScreen::sendTrackingId(int32_t trackingId) {
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_TRACKING_ID, trackingId));
+ injectEvent(EV_ABS, ABS_MT_TRACKING_ID, trackingId);
}
void UinputTouchScreen::sendDown(const Point& point) {
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_KEY, BTN_TOUCH, 1));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_X, point.x));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_KEY, BTN_TOUCH, 1);
+ injectEvent(EV_ABS, ABS_MT_POSITION_X, point.x);
+ injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
void UinputTouchScreen::sendMove(const Point& point) {
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_X, point.x));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_ABS, ABS_MT_POSITION_X, point.x);
+ injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
void UinputTouchScreen::sendUp() {
sendTrackingId(0xffffffff);
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_KEY, BTN_TOUCH, 0));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_KEY, BTN_TOUCH, 0);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
void UinputTouchScreen::sendToolType(int32_t toolType) {
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_TOOL_TYPE, toolType));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_ABS, ABS_MT_TOOL_TYPE, toolType);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
// Get the center x, y base on the range definition.
diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp
index 106efd6..1622e77 100644
--- a/services/sensorservice/SensorDirectConnection.cpp
+++ b/services/sensorservice/SensorDirectConnection.cpp
@@ -93,6 +93,23 @@
return nullptr;
}
+void SensorService::SensorDirectConnection::updateSensorSubscriptions() {
+ if (!hasSensorAccess()) {
+ stopAll(true /* backupRecord */);
+ } else {
+ recoverAll();
+ }
+}
+
+void SensorService::SensorDirectConnection::setSensorAccess(bool hasAccess) {
+ mHasSensorAccess = hasAccess;
+ updateSensorSubscriptions();
+}
+
+bool SensorService::SensorDirectConnection::hasSensorAccess() const {
+ return mHasSensorAccess && !mService->mSensorPrivacyPolicy->isSensorPrivacyEnabled();
+}
+
status_t SensorService::SensorDirectConnection::enableDisable(
int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,
int reservedFlags) {
diff --git a/services/sensorservice/SensorDirectConnection.h b/services/sensorservice/SensorDirectConnection.h
index ead08d3..fa88fbc 100644
--- a/services/sensorservice/SensorDirectConnection.h
+++ b/services/sensorservice/SensorDirectConnection.h
@@ -54,6 +54,9 @@
// called by SensorService when return to NORMAL mode.
void recoverAll();
+ void updateSensorSubscriptions();
+
+ void setSensorAccess(bool hasAccess);
protected:
virtual ~SensorDirectConnection();
// ISensorEventConnection functions
@@ -66,6 +69,7 @@
virtual int32_t configureChannel(int handle, int rateLevel);
virtual void destroy();
private:
+ bool hasSensorAccess() const;
const sp<SensorService> mService;
const uid_t mUid;
const sensors_direct_mem_t mMem;
@@ -76,6 +80,8 @@
std::unordered_map<int, int> mActivated;
std::unordered_map<int, int> mActivatedBackup;
+ std::atomic_bool mHasSensorAccess = true;
+
mutable Mutex mDestroyLock;
bool mDestroyed;
};
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 77d8c11..5be4ccd 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -70,17 +70,16 @@
}
bool SensorService::SensorEventConnection::needsWakeLock() {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
return !mDead && mWakeLockRefCount > 0;
}
void SensorService::SensorEventConnection::resetWakeLockRefCount() {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
mWakeLockRefCount = 0;
}
void SensorService::SensorEventConnection::dump(String8& result) {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
result.appendFormat("\tOperating Mode: ");
if (!mService->isWhiteListedPackage(getPackageName())) {
result.append("RESTRICTED\n");
@@ -92,6 +91,8 @@
result.appendFormat("\t %s | WakeLockRefCount %d | uid %d | cache size %d | "
"max cache size %d\n", mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize,
mMaxCacheSize);
+
+ std::lock_guard<std::mutex> _l(mConnectionLock);
for (auto& it : mSensorInfo) {
const FlushInfo& flushInfo = it.second.flushInfo;
result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n",
@@ -122,7 +123,7 @@
*/
void SensorService::SensorEventConnection::dump(util::ProtoOutputStream* proto) const {
using namespace service::SensorEventConnectionProto;
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
if (!mService->isWhiteListedPackage(getPackageName())) {
proto->write(OPERATING_MODE, OP_MODE_RESTRICTED);
@@ -160,7 +161,7 @@
bool SensorService::SensorEventConnection::addSensor(
int32_t handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags) {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
if (si == nullptr ||
!canAccessSensor(si->getSensor(), "Tried adding", mOpPackageName) ||
@@ -179,12 +180,12 @@
}
bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
return mSensorInfo.erase(handle) > 0;
}
std::vector<int32_t> SensorService::SensorEventConnection::getActiveSensorHandles() const {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
std::vector<int32_t> list;
for (auto& it : mSensorInfo) {
list.push_back(it.first);
@@ -193,17 +194,19 @@
}
bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::recursive_mutex> _backlock(mBackupLock);
+ std::lock_guard<std::mutex> _lock(mConnectionLock);
return mSensorInfo.count(handle) + mSensorInfoBackup.count(handle) > 0;
}
bool SensorService::SensorEventConnection::hasAnySensor() const {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::recursive_mutex> _backlock(mBackupLock);
+ std::lock_guard<std::mutex> _lock(mConnectionLock);
return mSensorInfo.size() + mSensorInfoBackup.size() ? true : false;
}
bool SensorService::SensorEventConnection::hasOneShotSensors() const {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
for (auto &it : mSensorInfo) {
const int handle = it.first;
sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
@@ -220,7 +223,7 @@
void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
bool value) {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
if (mSensorInfo.count(handle) > 0) {
FlushInfo& flushInfo = mSensorInfo[handle].flushInfo;
flushInfo.mFirstFlushPending = value;
@@ -228,7 +231,7 @@
}
void SensorService::SensorEventConnection::updateLooperRegistration(const sp<Looper>& looper) {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
updateLooperRegistrationLocked(looper);
}
@@ -279,7 +282,7 @@
}
void SensorService::SensorEventConnection::incrementPendingFlushCount(int32_t handle) {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
if (mSensorInfo.count(handle) > 0) {
FlushInfo& flushInfo = mSensorInfo[handle].flushInfo;
flushInfo.mPendingFlushEventsToSend++;
@@ -295,7 +298,7 @@
std::unique_ptr<sensors_event_t[]> sanitizedBuffer;
int count = 0;
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
if (scratch) {
size_t i=0;
while (i<numEvents) {
@@ -453,11 +456,18 @@
}
void SensorService::SensorEventConnection::stopAll() {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
- if (!mSensorInfo.empty()) {
- mSensorInfoBackup = mSensorInfo;
- mSensorInfo.clear();
+ bool backupPerformed = false;
+ std::lock_guard<std::recursive_mutex> _backlock(mBackupLock);
+ {
+ std::lock_guard<std::mutex> _lock(mConnectionLock);
+ if (!mSensorInfo.empty()) {
+ mSensorInfoBackup = mSensorInfo;
+ mSensorInfo.clear();
+ backupPerformed = true;
+ }
+ }
+ if (backupPerformed) {
for (auto& it : mSensorInfoBackup) {
int32_t handle = it.first;
@@ -471,7 +481,7 @@
}
void SensorService::SensorEventConnection::recoverAll() {
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::recursive_mutex> _l(mBackupLock);
for (auto& it : mSensorInfoBackup) {
int32_t handle = it.first;
SensorRequest &request = it.second;
@@ -612,7 +622,7 @@
// half the size of the socket buffer allocated in BitTube whichever is smaller.
const int maxWriteSize = helpers::min(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2,
int(mService->mSocketBufferSize/(sizeof(sensors_event_t)*2)));
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
// Send pending flush complete events (if any)
sendPendingFlushEventsLocked();
for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
@@ -724,7 +734,7 @@
{
status_t err = mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
if (err == NO_ERROR && mSensorInfo.count(handle) > 0) {
mSensorInfo[handle].samplingPeriodNs = samplingPeriodNs;
}
@@ -750,7 +760,7 @@
// and remove the fd from Looper. Call checkWakeLockState to know if SensorService
// can release the wake-lock.
ALOGD_IF(DEBUG_CONNECTIONS, "%p Looper error %d", this, fd);
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
mDead = true;
mWakeLockRefCount = 0;
updateLooperRegistrationLocked(mService->getLooper());
@@ -769,7 +779,7 @@
unsigned char buf[sizeof(sensors_event_t)];
ssize_t numBytesRead = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
{
- std::lock_guard<std::recursive_mutex> _l(mConnectionLock);
+ std::lock_guard<std::mutex> _l(mConnectionLock);
if (numBytesRead == sizeof(sensors_event_t)) {
if (!mDataInjectionMode) {
ALOGE("Data injected in normal mode, dropping event"
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 3ba5c07..80e7431 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -146,7 +146,13 @@
sp<SensorService> const mService;
sp<BitTube> mChannel;
uid_t mUid;
- mutable std::recursive_mutex mConnectionLock;
+
+ // A lock that should be used when modifying mSensorInfo
+ mutable std::mutex mConnectionLock;
+
+ // A lock that should be used when modifying mSensorInfoBackup
+ mutable std::recursive_mutex mBackupLock;
+
// Number of events from wake up sensors which are still pending and haven't been delivered to
// the corresponding application. It is incremented by one unit for each write to the socket.
uint32_t mWakeLockRefCount;
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 5ae7c51..29df825 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -302,6 +302,7 @@
void SensorService::setSensorAccess(uid_t uid, bool hasAccess) {
ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
const auto& connections = connLock.getActiveConnections();
+ const auto& directConnections = connLock.getDirectConnections();
mLock.unlock();
for (const sp<SensorEventConnection>& conn : connections) {
@@ -309,6 +310,15 @@
conn->setSensorAccess(hasAccess);
}
}
+
+ for (const sp<SensorDirectConnection>& conn : directConnections) {
+ if (conn->getUid() == uid) {
+ conn->setSensorAccess(hasAccess);
+ }
+ }
+
+ // Lock the mutex again for clean shutdown
+ mLock.lock();
}
const Sensor& SensorService::registerSensor(SensorInterface* s, bool isDebug, bool isVirtual) {
@@ -645,7 +655,7 @@
connection->updateSensorSubscriptions();
}
for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
- connection->stopAll(true /* backupRecord */);
+ connection->updateSensorSubscriptions();
}
dev.disableAllSensors();
// Clear all pending flush connections for all active sensors. If one of the active
@@ -676,7 +686,7 @@
connection->updateSensorSubscriptions();
}
for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
- connection->recoverAll();
+ connection->updateSensorSubscriptions();
}
}
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
index f24f314..b6d904f 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
@@ -35,6 +35,7 @@
using byte_view = std::basic_string_view<uint8_t>;
+constexpr size_t kEdidBlockSize = 128;
constexpr size_t kEdidHeaderLength = 5;
constexpr uint16_t kFallbackEdidManufacturerId = 0;
@@ -98,6 +99,57 @@
return info;
}
+Cea861ExtensionBlock parseCea861Block(const byte_view& block) {
+ Cea861ExtensionBlock cea861Block;
+
+ constexpr size_t kRevisionNumberOffset = 1;
+ cea861Block.revisionNumber = block[kRevisionNumberOffset];
+
+ constexpr size_t kDetailedTimingDescriptorsOffset = 2;
+ const size_t dtdStart =
+ std::min(kEdidBlockSize, static_cast<size_t>(block[kDetailedTimingDescriptorsOffset]));
+
+ // Parse data blocks.
+ for (size_t dataBlockOffset = 4; dataBlockOffset < dtdStart;) {
+ const uint8_t header = block[dataBlockOffset];
+ const uint8_t tag = header >> 5;
+ const size_t bodyLength = header & 0b11111;
+ constexpr size_t kDataBlockHeaderSize = 1;
+ const size_t dataBlockSize = bodyLength + kDataBlockHeaderSize;
+
+ if (block.size() < dataBlockOffset + dataBlockSize) {
+ ALOGW("Invalid EDID: CEA 861 data block is truncated.");
+ break;
+ }
+
+ const byte_view dataBlock(block.data() + dataBlockOffset, dataBlockSize);
+ constexpr uint8_t kVendorSpecificDataBlockTag = 0x3;
+
+ if (tag == kVendorSpecificDataBlockTag) {
+ const uint32_t ieeeRegistrationId =
+ dataBlock[1] | (dataBlock[2] << 8) | (dataBlock[3] << 16);
+ constexpr uint32_t kHdmiIeeeRegistrationId = 0xc03;
+
+ if (ieeeRegistrationId == kHdmiIeeeRegistrationId) {
+ const uint8_t a = dataBlock[4] >> 4;
+ const uint8_t b = dataBlock[4] & 0b1111;
+ const uint8_t c = dataBlock[5] >> 4;
+ const uint8_t d = dataBlock[5] & 0b1111;
+ cea861Block.hdmiVendorDataBlock =
+ HdmiVendorDataBlock{.physicalAddress = HdmiPhysicalAddress{a, b, c, d}};
+ } else {
+ ALOGV("Ignoring vendor specific data block for vendor with IEEE OUI %x",
+ ieeeRegistrationId);
+ }
+ } else {
+ ALOGV("Ignoring CEA-861 data block with tag %x", tag);
+ }
+ dataBlockOffset += bodyLength + kDataBlockHeaderSize;
+ }
+
+ return cea861Block;
+}
+
} // namespace
uint16_t DisplayId::manufacturerId() const {
@@ -115,13 +167,12 @@
}
std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) {
- constexpr size_t kMinLength = 128;
- if (edid.size() < kMinLength) {
+ if (edid.size() < kEdidBlockSize) {
ALOGW("Invalid EDID: structure is truncated.");
// Attempt parsing even if EDID is malformed.
} else {
- ALOGW_IF(edid[126] != 0, "EDID extensions are currently unsupported.");
- ALOGW_IF(std::accumulate(edid.begin(), edid.begin() + kMinLength, static_cast<uint8_t>(0)),
+ ALOGW_IF(std::accumulate(edid.begin(), edid.begin() + kEdidBlockSize,
+ static_cast<uint8_t>(0)),
"Invalid EDID: structure does not checksum.");
}
@@ -227,13 +278,43 @@
// have been observed to change on some displays with multiple inputs.
const auto modelHash = static_cast<uint32_t>(std::hash<std::string_view>()(modelString));
+ // Parse extension blocks.
+ std::optional<Cea861ExtensionBlock> cea861Block;
+ if (edid.size() < kEdidBlockSize) {
+ ALOGW("Invalid EDID: block 0 is truncated.");
+ } else {
+ constexpr size_t kNumExtensionsOffset = 126;
+ const size_t numExtensions = edid[kNumExtensionsOffset];
+ view = byte_view(edid.data(), edid.size());
+ for (size_t blockNumber = 1; blockNumber <= numExtensions; blockNumber++) {
+ view.remove_prefix(kEdidBlockSize);
+ if (view.size() < kEdidBlockSize) {
+ ALOGW("Invalid EDID: block %zu is truncated.", blockNumber);
+ break;
+ }
+
+ const byte_view block(view.data(), kEdidBlockSize);
+ ALOGW_IF(std::accumulate(block.begin(), block.end(), static_cast<uint8_t>(0)),
+ "Invalid EDID: block %zu does not checksum.", blockNumber);
+ const uint8_t tag = block[0];
+
+ constexpr uint8_t kCea861BlockTag = 0x2;
+ if (tag == kCea861BlockTag) {
+ cea861Block = parseCea861Block(block);
+ } else {
+ ALOGV("Ignoring block number %zu with tag %x.", blockNumber, tag);
+ }
+ }
+ }
+
return Edid{.manufacturerId = manufacturerId,
.productId = productId,
.pnpId = *pnpId,
.modelHash = modelHash,
.displayName = displayName,
+ .manufactureOrModelYear = manufactureOrModelYear,
.manufactureWeek = manufactureWeek,
- .manufactureOrModelYear = manufactureOrModelYear};
+ .cea861Block = cea861Block};
}
std::optional<PnpId> getPnpId(uint16_t manufacturerId) {
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
index d91b957..fc2f72e 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
@@ -57,6 +57,26 @@
std::optional<DeviceProductInfo> deviceProductInfo;
};
+struct ExtensionBlock {
+ uint8_t tag;
+ uint8_t revisionNumber;
+};
+
+struct HdmiPhysicalAddress {
+ // The address describes the path from the display sink in the network of connected HDMI
+ // devices. The format of the address is "a.b.c.d". For example, address 2.1.0.0 means we are
+ // connected to port 1 of a device which is connected to port 2 of the sink.
+ uint8_t a, b, c, d;
+};
+
+struct HdmiVendorDataBlock {
+ std::optional<HdmiPhysicalAddress> physicalAddress;
+};
+
+struct Cea861ExtensionBlock : ExtensionBlock {
+ std::optional<HdmiVendorDataBlock> hdmiVendorDataBlock;
+};
+
struct Edid {
uint16_t manufacturerId;
uint16_t productId;
@@ -65,6 +85,7 @@
std::string_view displayName;
uint8_t manufactureOrModelYear;
uint8_t manufactureWeek;
+ std::optional<Cea861ExtensionBlock> cea861Block;
};
bool isEdid(const DisplayIdentificationData&);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3d67a6b..5039761 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2134,10 +2134,12 @@
writeToProtoDrawingState(layerProto, traceFlags);
writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
- // Only populate for the primary display.
- if (device) {
- const Hwc2::IComposerClient::Composition compositionType = getCompositionType(device);
- layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
+ if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) {
+ // Only populate for the primary display.
+ if (device) {
+ const Hwc2::IComposerClient::Composition compositionType = getCompositionType(device);
+ layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
+ }
}
for (const sp<Layer>& layer : mDrawingChildren) {
@@ -2180,8 +2182,10 @@
LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
[&]() { return layerInfo->mutable_position(); });
LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
- LayerProtoHelper::writeToProto(debugGetVisibleRegionOnDefaultDisplay(),
- [&]() { return layerInfo->mutable_visible_region(); });
+ if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) {
+ LayerProtoHelper::writeToProto(debugGetVisibleRegionOnDefaultDisplay(),
+ [&]() { return layerInfo->mutable_visible_region(); });
+ }
LayerProtoHelper::writeToProto(surfaceDamageRegion,
[&]() { return layerInfo->mutable_damage_region(); });
@@ -2191,15 +2195,13 @@
}
}
- if (traceFlags & SurfaceTracing::TRACE_EXTRA) {
- LayerProtoHelper::writeToProto(mSourceBounds,
- [&]() { return layerInfo->mutable_source_bounds(); });
- LayerProtoHelper::writeToProto(mScreenBounds,
- [&]() { return layerInfo->mutable_screen_bounds(); });
- LayerProtoHelper::writeToProto(getRoundedCornerState().cropRect,
- [&]() { return layerInfo->mutable_corner_radius_crop(); });
- layerInfo->set_shadow_radius(mEffectiveShadowRadius);
- }
+ LayerProtoHelper::writeToProto(mSourceBounds,
+ [&]() { return layerInfo->mutable_source_bounds(); });
+ LayerProtoHelper::writeToProto(mScreenBounds,
+ [&]() { return layerInfo->mutable_screen_bounds(); });
+ LayerProtoHelper::writeToProto(getRoundedCornerState().cropRect,
+ [&]() { return layerInfo->mutable_corner_radius_crop(); });
+ layerInfo->set_shadow_radius(mEffectiveShadowRadius);
}
void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index c47bf94..4ceac4e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1947,8 +1947,18 @@
// potentially trigger a display handoff.
updateVrFlinger();
- bool refreshNeeded = handleMessageTransaction();
- refreshNeeded |= handleMessageInvalidate();
+ bool refreshNeeded;
+ withTracingLock([&]() {
+ refreshNeeded = handleMessageTransaction();
+ refreshNeeded |= handleMessageInvalidate();
+ if (mTracingEnabled) {
+ mAddCompositionStateToTrace =
+ mTracing.flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION);
+ if (mVisibleRegionsDirty && !mAddCompositionStateToTrace) {
+ mTracing.notifyLocked("visibleRegionsDirty");
+ }
+ }
+ });
// Layers need to get updated (in the previous line) before we can use them for
// choosing the refresh rate.
@@ -2092,7 +2102,7 @@
mLayersWithQueuedFrames.clear();
if (mVisibleRegionsDirty) {
mVisibleRegionsDirty = false;
- if (mTracingEnabled) {
+ if (mTracingEnabled && mAddCompositionStateToTrace) {
mTracing.notify("visibleRegionsDirty");
}
}
@@ -2974,8 +2984,7 @@
void SurfaceFlinger::commitTransaction()
{
- withTracingLock([this]() { commitTransactionLocked(); });
-
+ commitTransactionLocked();
mTransactionPending = false;
mAnimTransactionPending = false;
mTransactionCV.broadcast();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3997633..12efca1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1077,6 +1077,7 @@
std::unique_ptr<SurfaceInterceptor> mInterceptor;
SurfaceTracing mTracing{*this};
bool mTracingEnabled = false;
+ bool mAddCompositionStateToTrace = false;
bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false;
const std::shared_ptr<TimeStats> mTimeStats;
const std::unique_ptr<FrameTracer> mFrameTracer;
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index a9c3332..0b1251e 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -60,6 +60,8 @@
mCanStartTrace.wait(lock);
android::base::ScopedLockAssertion assumeLock(mSfLock);
LayersTraceProto entry = traceLayersLocked(mWhere, displayDevice);
+ mTracingInProgress = false;
+ mMissedTraceEntries = 0;
lock.unlock();
return entry;
}
@@ -76,7 +78,15 @@
void SurfaceTracing::notify(const char* where) {
std::scoped_lock lock(mSfLock);
+ notifyLocked(where);
+}
+
+void SurfaceTracing::notifyLocked(const char* where) {
mWhere = where;
+ if (mTracingInProgress) {
+ mMissedTraceEntries++;
+ }
+ mTracingInProgress = true;
mCanStartTrace.notify_one();
}
@@ -175,7 +185,10 @@
entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
entry.set_where(where);
LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags, displayDevice));
- mFlinger.dumpOffscreenLayersProto(layers);
+
+ if (flagIsSetLocked(SurfaceTracing::TRACE_EXTRA)) {
+ mFlinger.dumpOffscreenLayersProto(layers);
+ }
entry.mutable_layers()->Swap(&layers);
if (mTraceFlags & SurfaceTracing::TRACE_HWC) {
@@ -183,6 +196,10 @@
mFlinger.dumpHwc(hwcDump);
entry.set_hwc_blob(hwcDump);
}
+ if (!flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION)) {
+ entry.set_excludes_composition_state(true);
+ }
+ entry.set_missed_entries(mMissedTraceEntries);
return entry;
}
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 83872ed..a00e5d6 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -49,6 +49,7 @@
status_t writeToFile();
bool isEnabled() const;
void notify(const char* where);
+ void notifyLocked(const char* where) NO_THREAD_SAFETY_ANALYSIS /* REQUIRES(mSfLock) */;
void setBufferSize(size_t bufferSizeInByte);
void writeToFileAsync();
@@ -57,11 +58,15 @@
enum : uint32_t {
TRACE_CRITICAL = 1 << 0,
TRACE_INPUT = 1 << 1,
- TRACE_EXTRA = 1 << 2,
- TRACE_HWC = 1 << 3,
+ TRACE_COMPOSITION = 1 << 2,
+ TRACE_EXTRA = 1 << 3,
+ TRACE_HWC = 1 << 4,
TRACE_ALL = 0xffffffff
};
void setTraceFlags(uint32_t flags);
+ bool flagIsSetLocked(uint32_t flags) NO_THREAD_SAFETY_ANALYSIS /* REQUIRES(mSfLock) */ {
+ return (mTraceFlags & flags) == flags;
+ }
private:
static constexpr auto kDefaultBufferCapInByte = 5_MB;
@@ -103,6 +108,8 @@
std::mutex& mSfLock;
uint32_t mTraceFlags GUARDED_BY(mSfLock) = TRACE_CRITICAL | TRACE_INPUT;
const char* mWhere GUARDED_BY(mSfLock) = "";
+ uint32_t mMissedTraceEntries GUARDED_BY(mSfLock) = 0;
+ bool mTracingInProgress GUARDED_BY(mSfLock) = false;
mutable std::mutex mTraceLock;
LayersTraceBuffer mBuffer GUARDED_BY(mTraceLock);
diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto
index ac33a0e..acf621e 100644
--- a/services/surfaceflinger/layerproto/layerstrace.proto
+++ b/services/surfaceflinger/layerproto/layerstrace.proto
@@ -51,4 +51,10 @@
// Blob for the current HWC information for all layers, reported by dumpsys.
optional string hwc_blob = 4;
+
+ /* Includes state sent during composition like visible region and composition type. */
+ optional bool excludes_composition_state = 5;
+
+ /* Number of missed entries since the last entry was recorded. */
+ optional int32 missed_entries = 6;
}
diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
index c2ddfce..cc11aa9 100644
--- a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
@@ -96,7 +96,7 @@
"\x0a\x20\x20\x20\x20\x20\x01\x47\x02\x03\x2d\x71\x50\x90\x05"
"\x04\x03\x07\x02\x06\x01\x1f\x14\x13\x12\x16\x11\x15\x20\x2c"
"\x09\x07\x03\x15\x07\x50\x57\x07\x00\x39\x07\xbb\x66\x03\x0c"
- "\x00\x20\x00\x00\x83\x01\x00\x00\x01\x1d\x00\x72\x51\xd0\x1e"
+ "\x00\x12\x34\x00\x83\x01\x00\x00\x01\x1d\x00\x72\x51\xd0\x1e"
"\x20\x6e\x28\x55\x00\xc4\x8e\x21\x00\x00\x1e\x01\x1d\x80\x18"
"\x71\x1c\x16\x20\x58\x2c\x25\x00\xc4\x8e\x21\x00\x00\x9e\x8c"
"\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\x13\x8e\x21\x00"
@@ -185,6 +185,7 @@
EXPECT_EQ(12610, edid->productId);
EXPECT_EQ(21, edid->manufactureOrModelYear);
EXPECT_EQ(0, edid->manufactureWeek);
+ EXPECT_FALSE(edid->cea861Block);
edid = parseEdid(getExternalEdid());
ASSERT_TRUE(edid);
@@ -195,6 +196,7 @@
EXPECT_EQ(10348, edid->productId);
EXPECT_EQ(22, edid->manufactureOrModelYear);
EXPECT_EQ(2, edid->manufactureWeek);
+ EXPECT_FALSE(edid->cea861Block);
edid = parseEdid(getExternalEedid());
ASSERT_TRUE(edid);
@@ -205,6 +207,14 @@
EXPECT_EQ(2302, edid->productId);
EXPECT_EQ(21, edid->manufactureOrModelYear);
EXPECT_EQ(41, edid->manufactureWeek);
+ ASSERT_TRUE(edid->cea861Block);
+ ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
+ ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock->physicalAddress);
+ auto physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress;
+ EXPECT_EQ(2, physicalAddress->a);
+ EXPECT_EQ(0, physicalAddress->b);
+ EXPECT_EQ(0, physicalAddress->c);
+ EXPECT_EQ(0, physicalAddress->d);
edid = parseEdid(getPanasonicTvEdid());
ASSERT_TRUE(edid);
@@ -215,6 +225,14 @@
EXPECT_EQ(41622, edid->productId);
EXPECT_EQ(29, edid->manufactureOrModelYear);
EXPECT_EQ(0, edid->manufactureWeek);
+ ASSERT_TRUE(edid->cea861Block);
+ ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
+ ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock->physicalAddress);
+ physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress;
+ EXPECT_EQ(2, physicalAddress->a);
+ EXPECT_EQ(0, physicalAddress->b);
+ EXPECT_EQ(0, physicalAddress->c);
+ EXPECT_EQ(0, physicalAddress->d);
edid = parseEdid(getHisenseTvEdid());
ASSERT_TRUE(edid);
@@ -225,6 +243,14 @@
EXPECT_EQ(0, edid->productId);
EXPECT_EQ(29, edid->manufactureOrModelYear);
EXPECT_EQ(18, edid->manufactureWeek);
+ ASSERT_TRUE(edid->cea861Block);
+ ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
+ ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock->physicalAddress);
+ physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress;
+ EXPECT_EQ(1, physicalAddress->a);
+ EXPECT_EQ(2, physicalAddress->b);
+ EXPECT_EQ(3, physicalAddress->c);
+ EXPECT_EQ(4, physicalAddress->d);
edid = parseEdid(getCtlDisplayEdid());
ASSERT_TRUE(edid);
@@ -235,6 +261,8 @@
EXPECT_EQ(9373, edid->productId);
EXPECT_EQ(23, edid->manufactureOrModelYear);
EXPECT_EQ(0xff, edid->manufactureWeek);
+ ASSERT_TRUE(edid->cea861Block);
+ EXPECT_FALSE(edid->cea861Block->hdmiVendorDataBlock);
}
TEST(DisplayIdentificationTest, parseInvalidEdid) {