Merge "Avoid calling into HWC in onFirstRef"
diff --git a/cmds/bugreportz/bugreportz.cpp b/cmds/bugreportz/bugreportz.cpp
index 75855cf..ded0ed3 100644
--- a/cmds/bugreportz/bugreportz.cpp
+++ b/cmds/bugreportz/bugreportz.cpp
@@ -55,7 +55,7 @@
errno = ETIMEDOUT;
}
printf("FAIL:Bugreport read terminated abnormally (%s)\n", strerror(errno));
- break;
+ return EXIT_FAILURE;
}
// Writes line by line.
@@ -71,8 +71,5 @@
// Process final line, in case it didn't finish with newline
write_line(line, show_progress);
- if (close(s) == -1) {
- fprintf(stderr, "WARNING: error closing socket: %s\n", strerror(errno));
- }
return EXIT_SUCCESS;
}
diff --git a/cmds/bugreportz/bugreportz.h b/cmds/bugreportz/bugreportz.h
index 304e4b3..7af289b 100644
--- a/cmds/bugreportz/bugreportz.h
+++ b/cmds/bugreportz/bugreportz.h
@@ -16,6 +16,7 @@
#define BUGREPORTZ_H
// Calls dumpstate using the given socket and output its result to stdout.
+// Ownership of the socket is not transferred.
int bugreportz(int s, bool show_progress);
#endif // BUGREPORTZ_H
diff --git a/cmds/bugreportz/main.cpp b/cmds/bugreportz/main.cpp
index a3ae1ff..74a95b0 100644
--- a/cmds/bugreportz/main.cpp
+++ b/cmds/bugreportz/main.cpp
@@ -82,7 +82,7 @@
if (s == -1) {
printf("FAIL:Failed to connect to dumpstatez service: %s\n", strerror(errno));
- return EXIT_SUCCESS;
+ return EXIT_FAILURE;
}
// Set a timeout so that if nothing is read in 10 minutes, we'll stop
@@ -92,8 +92,16 @@
tv.tv_sec = 10 * 60;
tv.tv_usec = 0;
if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
- fprintf(stderr, "WARNING: Cannot set socket timeout: %s\n", strerror(errno));
+ fprintf(stderr,
+ "WARNING: Cannot set socket timeout, bugreportz might hang indefinitely: %s\n",
+ strerror(errno));
}
- bugreportz(s, show_progress);
+ int ret = bugreportz(s, show_progress);
+
+ if (close(s) == -1) {
+ fprintf(stderr, "WARNING: error closing socket: %s\n", strerror(errno));
+ ret = EXIT_FAILURE;
+ }
+ return ret;
}
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 8d5f0d2..a6d7a78 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -498,7 +498,7 @@
}
}
out << "-->" << std::endl;
- out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlag::HALS_ONLY);
+ out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlags::HALS_ONLY);
}
std::string ListCommand::INIT_VINTF_NOTES{
diff --git a/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h b/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h
deleted file mode 100644
index 67abc68..0000000
--- a/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IARC_VIDEO_BRIDGE_H
-#define ANDROID_IARC_VIDEO_BRIDGE_H
-
-#include <arc/MojoBootstrapResult.h>
-#include <binder/IInterface.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-class IArcVideoBridge : public IInterface {
-public:
- DECLARE_META_INTERFACE(ArcVideoBridge);
-
- // Returns MojoBootstrapResult for creating mojo ipc channel of
- // VideoAcceleratorFactory.
- virtual ::arc::MojoBootstrapResult bootstrapVideoAcceleratorFactory() = 0;
-
- // Get the version of the remote VideoHost on Chromium side.
- virtual int32_t hostVersion() = 0;
-};
-
-class BnArcVideoBridge : public BnInterface<IArcVideoBridge> {
-public:
- virtual status_t onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IARC_VIDEO_BRIDGE_H
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 786b136..b2a304a 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -120,7 +120,6 @@
"liblog",
"libcutils",
"libutils",
- "libutilscallstack",
],
header_libs: [
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 7afec45..507ce53 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -31,7 +31,6 @@
#include <binder/Parcel.h>
#include <log/log.h>
-#include <utils/CallStack.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
@@ -264,7 +263,6 @@
if (VERBOSE) {
ALOGD("UNMAPPING binder=%p, heap=%p, size=%zu, fd=%d",
binder.get(), this, mSize, heapId);
- CallStack stack(LOG_TAG);
}
munmap(mBase, mSize);
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index d0ed31e..4ba6c2a 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -27,7 +27,6 @@
#include <cutils/properties.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
-#include <utils/CallStack.h>
#include <private/binder/Static.h>
@@ -161,12 +160,8 @@
int n = 0;
while (uptimeMillis() < timeout) {
n++;
- if (isVendorService) {
- ALOGI("Waiting for vendor service %s...", String8(name).string());
- CallStack stack(LOG_TAG);
- } else if (n%10 == 0) {
- ALOGI("Waiting for service %s...", String8(name).string());
- }
+ ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
+ ProcessState::self()->getDriverName().c_str());
usleep(1000*sleepTime);
sp<IBinder> svc = checkService(name);
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 8b2f842..0d224d8 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -46,6 +46,7 @@
"android.hardware.bluetooth@1.0::IBluetoothHci",
"android.hardware.camera.provider@2.4::ICameraProvider",
"android.hardware.drm@1.0::IDrmFactory",
+ "android.hardware.graphics.allocator@2.0::IAllocator",
"android.hardware.graphics.composer@2.1::IComposer",
"android.hardware.media.omx@1.0::IOmx",
"android.hardware.media.omx@1.0::IOmxStore",
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 19ad31b..3a6dfda 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -102,14 +102,14 @@
status_t SurfaceControl::clearLayerFrameStats() const {
status_t err = validate();
- if (err < 0) return err;
+ if (err != NO_ERROR) return err;
const sp<SurfaceComposerClient>& client(mClient);
return client->clearLayerFrameStats(mHandle);
}
status_t SurfaceControl::getLayerFrameStats(FrameStats* outStats) const {
status_t err = validate();
- if (err < 0) return err;
+ if (err != NO_ERROR) return err;
const sp<SurfaceComposerClient>& client(mClient);
return client->getLayerFrameStats(mHandle, outStats);
}
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e401572..98ec338 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -220,12 +220,12 @@
class BnSurfaceComposer: public BnInterface<ISurfaceComposer> {
public:
- enum {
+ enum ISurfaceComposerTag {
// Note: BOOT_FINISHED must remain this value, it is called from
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
CREATE_CONNECTION,
- UNUSED, // formerly CREATE_GRAPHIC_BUFFER_ALLOC
+ CREATE_GRAPHIC_BUFFER_ALLOC_UNUSED, // unused, fails permissions check
CREATE_DISPLAY_EVENT_CONNECTION,
CREATE_DISPLAY,
DESTROY_DISPLAY,
@@ -236,7 +236,7 @@
GET_DISPLAY_CONFIGS,
GET_ACTIVE_CONFIG,
SET_ACTIVE_CONFIG,
- CONNECT_DISPLAY,
+ CONNECT_DISPLAY_UNUSED, // unused, fails permissions check
CAPTURE_SCREEN,
CAPTURE_LAYERS,
CLEAR_ANIMATION_FRAME_STATS,
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 2a962b5..2ab5b65 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -968,8 +968,19 @@
ASSERT_TRUE(b2 != nullptr);
int b2_id = b2->id();
- // The duplicated buffer should inherit the same buffer id.
+ // These two buffer instances are based on the same physical buffer under the
+ // hood, so they should share the same id.
EXPECT_EQ(b1_id, b2_id);
+ // We use buffer_state_bit() to tell those two instances apart.
+ EXPECT_NE(b1->buffer_state_bit(), b2->buffer_state_bit());
+ EXPECT_NE(b1->buffer_state_bit(), 0ULL);
+ EXPECT_NE(b2->buffer_state_bit(), 0ULL);
+ EXPECT_NE(b1->buffer_state_bit(), kProducerStateBit);
+ EXPECT_NE(b2->buffer_state_bit(), kProducerStateBit);
+
+ // Both buffer instances should be in gained state.
+ EXPECT_TRUE(IsBufferGained(b1->buffer_state()));
+ EXPECT_TRUE(IsBufferGained(b2->buffer_state()));
// Promote the detached buffer should fail as b1 is no longer the exclusive
// owner of the buffer..
diff --git a/libs/vr/libbufferhub/detached_buffer.cpp b/libs/vr/libbufferhub/detached_buffer.cpp
index 60f11e2..02abd91 100644
--- a/libs/vr/libbufferhub/detached_buffer.cpp
+++ b/libs/vr/libbufferhub/detached_buffer.cpp
@@ -49,7 +49,7 @@
}
int DetachedBuffer::ImportGraphicBuffer() {
- ATRACE_NAME("DetachedBuffer::DetachedBuffer");
+ ATRACE_NAME("DetachedBuffer::ImportGraphicBuffer");
auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Import>();
if (!status) {
@@ -76,9 +76,53 @@
return ret;
}
+ // Import the metadata.
+ IonBuffer metadata_buffer;
+ if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
+ ALOGE("Failed to import metadata buffer, error=%d", ret);
+ return ret;
+ }
+ size_t metadata_buf_size = metadata_buffer.width();
+ if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
+ ALOGE("DetachedBuffer::ImportGraphicBuffer: metadata buffer too small: %zu",
+ metadata_buf_size);
+ return -EINVAL;
+ }
+
// If all imports succeed, replace the previous buffer and id.
id_ = buffer_id;
buffer_ = std::move(ion_buffer);
+ metadata_buffer_ = std::move(metadata_buffer);
+ user_metadata_size_ = metadata_buf_size - BufferHubDefs::kMetadataHeaderSize;
+
+ void* metadata_ptr = nullptr;
+ if (const int ret =
+ metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
+ /*y=*/0, metadata_buf_size,
+ /*height=*/1, &metadata_ptr)) {
+ ALOGE("DetachedBuffer::ImportGraphicBuffer: Failed to lock metadata.");
+ return ret;
+ }
+
+ // TODO(b/112012161) Set up shared fences.
+
+ // Note that here the buffer state is mapped from shared memory as an atomic
+ // object. The std::atomic's constructor will not be called so that the
+ // original value stored in the memory region can be preserved.
+ metadata_header_ = static_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
+ if (user_metadata_size_) {
+ user_metadata_ptr_ = static_cast<void*>(metadata_header_ + 1);
+ } else {
+ user_metadata_ptr_ = nullptr;
+ }
+
+ id_ = buffer_desc.id();
+ buffer_state_bit_ = buffer_desc.buffer_state_bit();
+
+ ALOGD_IF(TRACE,
+ "DetachedBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64
+ ".",
+ id(), metadata_header_->buffer_state.load());
return 0;
}
diff --git a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h b/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
index 376b53e..1fc011b 100644
--- a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
@@ -30,8 +30,17 @@
const sp<GraphicBuffer>& buffer() const { return buffer_.buffer(); }
+ // Gets ID of the buffer client. All DetachedBuffer clients derived from the
+ // same buffer in bufferhubd share the same buffer id.
int id() const { return id_; }
+ // Returns the current value of MetadataHeader::buffer_state.
+ uint64_t buffer_state() { return metadata_header_->buffer_state.load(); }
+
+ // A state mask which is unique to a buffer hub client among all its siblings
+ // sharing the same concrete graphic buffer.
+ uint64_t buffer_state_bit() const { return buffer_state_bit_; }
+
// Returns true if the buffer holds an open PDX channels towards bufferhubd.
bool IsConnected() const { return client_.IsValid(); }
@@ -75,7 +84,18 @@
// Global id for the buffer that is consistent across processes.
int id_;
+ uint64_t buffer_state_bit_;
+
+ // The concrete Ion buffers.
IonBuffer buffer_;
+ IonBuffer metadata_buffer_;
+
+ // buffer metadata.
+ size_t user_metadata_size_ = 0;
+ BufferHubDefs::MetadataHeader* metadata_header_ = nullptr;
+ void* user_metadata_ptr_ = nullptr;
+
+ // PDX backend.
BufferHubClient client_;
};
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 863e426..c805805 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -515,10 +515,9 @@
sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId,
int32_t x, int32_t y) {
// Traverse windows from front to back to find touched window.
- const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
- size_t numWindows = windowHandles.size();
+ size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
+ sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId == displayId) {
int32_t flags = windowInfo->layoutParamsFlags;
@@ -1248,10 +1247,9 @@
bool isTouchModal = false;
// Traverse windows from front to back to find touched window and outside targets.
- const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
- size_t numWindows = windowHandles.size();
+ size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
+ sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId != displayId) {
continue; // wrong display
@@ -1474,10 +1472,8 @@
sp<InputWindowHandle> foregroundWindowHandle =
mTempTouchState.getFirstForegroundWindowHandle();
if (foregroundWindowHandle->getInfo()->hasWallpaper) {
- const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
- size_t numWindows = windowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
+ for (size_t i = 0; i < mWindowHandles.size(); i++) {
+ sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
const InputWindowInfo* info = windowHandle->getInfo();
if (info->displayId == displayId
&& windowHandle->getInfo()->layoutParamsType
@@ -1662,10 +1658,9 @@
bool InputDispatcher::isWindowObscuredAtPointLocked(
const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
int32_t displayId = windowHandle->getInfo()->displayId;
- const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
- size_t numWindows = windowHandles.size();
+ size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> otherHandle = windowHandles.itemAt(i);
+ sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
if (otherHandle == windowHandle) {
break;
}
@@ -1683,11 +1678,10 @@
bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const {
int32_t displayId = windowHandle->getInfo()->displayId;
- const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
const InputWindowInfo* windowInfo = windowHandle->getInfo();
- size_t numWindows = windowHandles.size();
+ size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> otherHandle = windowHandles.itemAt(i);
+ sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
if (otherHandle == windowHandle) {
break;
}
@@ -2915,77 +2909,52 @@
}
}
-Vector<sp<InputWindowHandle>> InputDispatcher::getWindowHandlesLocked(int32_t displayId) const {
- std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>>::const_iterator it
- = mWindowHandlesByDisplay.find(displayId);
- if(it != mWindowHandlesByDisplay.end()) {
- return it->second;
- }
-
- // Return an empty one if nothing found.
- return Vector<sp<InputWindowHandle>>();
-}
-
sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
const sp<InputChannel>& inputChannel) const {
- for (auto& it : mWindowHandlesByDisplay) {
- const Vector<sp<InputWindowHandle>> windowHandles = it.second;
- size_t numWindows = windowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
- if (windowHandle->getInputChannel() == inputChannel) {
- return windowHandle;
- }
+ size_t numWindows = mWindowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+ if (windowHandle->getInputChannel() == inputChannel) {
+ return windowHandle;
}
}
return nullptr;
}
bool InputDispatcher::hasWindowHandleLocked(
- const sp<InputWindowHandle>& windowHandle, int32_t displayId) const {
-
- const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
- size_t numWindows = windowHandles.size();
+ const sp<InputWindowHandle>& windowHandle) const {
+ size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- if (windowHandles.itemAt(i) == windowHandle) {
+ if (mWindowHandles.itemAt(i) == windowHandle) {
return true;
}
}
return false;
}
-void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle>>& inputWindowHandles,
- int displayId) {
+void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
#if DEBUG_FOCUS
ALOGD("setInputWindows");
#endif
{ // acquire lock
AutoMutex _l(mLock);
- const Vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
- Vector<sp<InputWindowHandle>> windowHandles = inputWindowHandles;
- // Insert or replace
- mWindowHandlesByDisplay[displayId] = windowHandles;
+ Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
+ mWindowHandles = inputWindowHandles;
- // TODO(b/111361570): multi-display focus, one focus in all display in current.
- sp<InputWindowHandle> newFocusedWindowHandle = mFocusedWindowHandle;
+ sp<InputWindowHandle> newFocusedWindowHandle;
bool foundHoveredWindow = false;
-
- if (windowHandles.isEmpty()) {
- // Remove all handles on a display if there are no windows left.
- mWindowHandlesByDisplay.erase(displayId);
- } else {
- for (size_t i = 0; i < windowHandles.size(); i++) {
- const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
- if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == nullptr) {
- continue;
- }
- if (windowHandle->getInfo()->hasFocus) {
- newFocusedWindowHandle = windowHandle;
- }
- if (windowHandle == mLastHoverWindowHandle) {
- foundHoveredWindow = true;
- }
+ for (size_t i = 0; i < mWindowHandles.size(); i++) {
+ const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+ if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == nullptr) {
+ mWindowHandles.removeAt(i--);
+ continue;
+ }
+ if (windowHandle->getInfo()->hasFocus) {
+ newFocusedWindowHandle = windowHandle;
+ }
+ if (windowHandle == mLastHoverWindowHandle) {
+ foundHoveredWindow = true;
}
}
@@ -2993,7 +2962,6 @@
mLastHoverWindowHandle = nullptr;
}
- // TODO(b/111361570): multi-display focus, one focus in all display in current.
if (mFocusedWindowHandle != newFocusedWindowHandle) {
if (mFocusedWindowHandle != nullptr) {
#if DEBUG_FOCUS
@@ -3017,12 +2985,11 @@
mFocusedWindowHandle = newFocusedWindowHandle;
}
- ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
- if (stateIndex >= 0) {
- TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
+ for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
+ TouchState& state = mTouchStatesByDisplay.editValueAt(d);
for (size_t i = 0; i < state.windows.size(); ) {
TouchedWindow& touchedWindow = state.windows.editItemAt(i);
- if (!hasWindowHandleLocked(touchedWindow.windowHandle, displayId)) {
+ if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
#if DEBUG_FOCUS
ALOGD("Touched window was removed: %s",
touchedWindow.windowHandle->getName().c_str());
@@ -3048,7 +3015,7 @@
// which might not happen until the next GC.
for (size_t i = 0; i < oldWindowHandles.size(); i++) {
const sp<InputWindowHandle>& oldWindowHandle = oldWindowHandles.itemAt(i);
- if (!hasWindowHandleLocked(oldWindowHandle, displayId)) {
+ if (!hasWindowHandleLocked(oldWindowHandle)) {
#if DEBUG_FOCUS
ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
#endif
@@ -3299,44 +3266,36 @@
dump += INDENT "TouchStates: <no displays touched>\n";
}
- if (!mWindowHandlesByDisplay.empty()) {
- for (auto& it : mWindowHandlesByDisplay) {
- const Vector<sp<InputWindowHandle>> windowHandles = it.second;
- dump += StringPrintf(INDENT "Display: %d\n", it.first);
- if (!windowHandles.isEmpty()) {
- dump += INDENT "Windows:\n";
- for (size_t i = 0; i < windowHandles.size(); i++) {
- const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
+ if (!mWindowHandles.isEmpty()) {
+ dump += INDENT "Windows:\n";
+ for (size_t i = 0; i < mWindowHandles.size(); i++) {
+ const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
- dump += StringPrintf(INDENT2 "%zu: name='%s', displayId=%d, "
- "paused=%s, hasFocus=%s, hasWallpaper=%s, "
- "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
- "frame=[%d,%d][%d,%d], scale=%f, "
- "touchableRegion=",
- i, windowInfo->name.c_str(), windowInfo->displayId,
- toString(windowInfo->paused),
- toString(windowInfo->hasFocus),
- toString(windowInfo->hasWallpaper),
- toString(windowInfo->visible),
- toString(windowInfo->canReceiveKeys),
- windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
- windowInfo->layer,
- windowInfo->frameLeft, windowInfo->frameTop,
- windowInfo->frameRight, windowInfo->frameBottom,
- windowInfo->scaleFactor);
- dumpRegion(dump, windowInfo->touchableRegion);
- dump += StringPrintf(", inputFeatures=0x%08x", windowInfo->inputFeatures);
- dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
- windowInfo->ownerPid, windowInfo->ownerUid,
- windowInfo->dispatchingTimeout / 1000000.0);
- }
- } else {
- dump += INDENT "Windows: <none>\n";
- }
+ dump += StringPrintf(INDENT2 "%zu: name='%s', displayId=%d, "
+ "paused=%s, hasFocus=%s, hasWallpaper=%s, "
+ "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
+ "frame=[%d,%d][%d,%d], scale=%f, "
+ "touchableRegion=",
+ i, windowInfo->name.c_str(), windowInfo->displayId,
+ toString(windowInfo->paused),
+ toString(windowInfo->hasFocus),
+ toString(windowInfo->hasWallpaper),
+ toString(windowInfo->visible),
+ toString(windowInfo->canReceiveKeys),
+ windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
+ windowInfo->layer,
+ windowInfo->frameLeft, windowInfo->frameTop,
+ windowInfo->frameRight, windowInfo->frameBottom,
+ windowInfo->scaleFactor);
+ dumpRegion(dump, windowInfo->touchableRegion);
+ dump += StringPrintf(", inputFeatures=0x%08x", windowInfo->inputFeatures);
+ dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
+ windowInfo->ownerPid, windowInfo->ownerUid,
+ windowInfo->dispatchingTimeout / 1000000.0);
}
} else {
- dump += INDENT "Displays: <none>\n";
+ dump += INDENT "Windows: <none>\n";
}
if (!mMonitoringChannels.isEmpty()) {
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 5cb7fe1..31ab339 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -31,7 +31,6 @@
#include <stddef.h>
#include <unistd.h>
#include <limits.h>
-#include <unordered_map>
#include "InputWindow.h"
#include "InputApplication.h"
@@ -308,8 +307,7 @@
*
* This method may be called on any thread (usually by the input manager).
*/
- virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
- int displayId) = 0;
+ virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) = 0;
/* Sets the focused application.
*
@@ -389,8 +387,7 @@
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
uint32_t policyFlags);
- virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
- int displayId);
+ virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles);
virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
virtual void setInputDispatchMode(bool enabled, bool frozen);
virtual void setInputFilterEnabled(bool enabled);
@@ -959,11 +956,10 @@
bool mDispatchFrozen;
bool mInputFilterEnabled;
- std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay;
- // Get window handles by display, return an empty vector if not found.
- Vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const;
+ Vector<sp<InputWindowHandle> > mWindowHandles;
+
sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
- bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle, int32_t displayId) const;
+ bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
// Focus tracking for keys, trackball, etc.
sp<InputWindowHandle> mFocusedWindowHandle;
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 5adb75c..beda75a 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -3018,7 +3018,7 @@
if (!changes) {
mRotaryEncoderScrollAccumulator.configure(getDevice());
}
- if (!changes || (InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
DisplayViewport v;
if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, nullptr, &v)) {
mOrientation = v.orientation;
diff --git a/services/media/arcvideobridge/Android.bp b/services/media/arcvideobridge/Android.bp
deleted file mode 100644
index ca5b896..0000000
--- a/services/media/arcvideobridge/Android.bp
+++ /dev/null
@@ -1,28 +0,0 @@
-cc_library_shared {
- name: "libarcvideobridge",
- product_variables: {
- arc: {
- srcs: [
- "IArcVideoBridge.cpp",
- ],
- shared_libs: [
- "libarcbridge",
- "libarcbridgeservice",
- "libbinder",
- "libchrome",
- "liblog",
- "libmojo",
- "libutils",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wunused",
- "-Wunreachable-code",
- ],
- include_dirs: [
- "frameworks/native/include/media/arcvideobridge",
- ]
- }
- }
-}
diff --git a/services/media/arcvideobridge/IArcVideoBridge.cpp b/services/media/arcvideobridge/IArcVideoBridge.cpp
deleted file mode 100644
index 468b76b..0000000
--- a/services/media/arcvideobridge/IArcVideoBridge.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2016 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 "IArcVideoBridge"
-//#define LOG_NDEBUG 0
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "IArcVideoBridge.h"
-#include <binder/Parcel.h>
-#include <utils/Log.h>
-
-namespace android {
-
-enum {
- BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY = IBinder::FIRST_CALL_TRANSACTION,
- HOST_VERSION,
-};
-
-class BpArcVideoBridge : public BpInterface<IArcVideoBridge> {
-public:
- BpArcVideoBridge(const sp<IBinder>& impl) : BpInterface<IArcVideoBridge>(impl) { }
-
- virtual ::arc::MojoBootstrapResult bootstrapVideoAcceleratorFactory() {
- Parcel data, reply;
- ALOGV("bootstrapVideoAcceleratorFactory");
- data.writeInterfaceToken(IArcVideoBridge::getInterfaceDescriptor());
- status_t status = remote()->transact(
- BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY, data, &reply, 0);
- if (status != 0) {
- ALOGE("transact failed: %d", status);
- return arc::MojoBootstrapResult();
- }
- return arc::MojoBootstrapResult::createFromParcel(reply);
- }
-
- virtual int32_t hostVersion() {
- Parcel data, reply;
- ALOGV("hostVersion");
- data.writeInterfaceToken(IArcVideoBridge::getInterfaceDescriptor());
- status_t status = remote()->transact(HOST_VERSION, data, &reply, 0);
- if (status != 0) {
- ALOGE("transact failed: %d", status);
- return false;
- }
- return reply.readInt32();
- }
-};
-
-IMPLEMENT_META_INTERFACE(ArcVideoBridge, "android.os.IArcVideoBridge");
-
-status_t BnArcVideoBridge::onTransact(
- uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
- switch(code) {
- case BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY: {
- ALOGV("BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY");
- CHECK_INTERFACE(IArcVideoBridge, data, reply);
- arc::MojoBootstrapResult result = bootstrapVideoAcceleratorFactory();
- return result.writeToParcel(reply);
- }
- case HOST_VERSION: {
- ALOGV("HOST_VERSION");
- CHECK_INTERFACE(IArcVideoBridge, data, reply);
- reply->writeInt32(hostVersion());
- return OK;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 3fa1311..fa0141f 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -105,11 +105,8 @@
"DisplayHardware/HWComposerBufferCache.cpp",
"DisplayHardware/PowerAdvisor.cpp",
"DisplayHardware/VirtualDisplaySurface.cpp",
- "DispSync.cpp",
"Effects/Daltonizer.cpp",
- "EventControlThread.cpp",
"EventLog/EventLog.cpp",
- "EventThread.cpp",
"FrameTracker.cpp",
"GpuService.cpp",
"Layer.cpp",
@@ -118,7 +115,6 @@
"LayerRejecter.cpp",
"LayerStats.cpp",
"LayerVector.cpp",
- "MessageQueue.cpp",
"MonitoredProducer.cpp",
"RenderArea.cpp",
"RenderEngine/Description.cpp",
@@ -131,6 +127,11 @@
"RenderEngine/RenderEngine.cpp",
"RenderEngine/Surface.cpp",
"RenderEngine/Texture.cpp",
+ "Scheduler/DispSync.cpp",
+ "Scheduler/DispSyncSource.cpp",
+ "Scheduler/EventControlThread.cpp",
+ "Scheduler/EventThread.cpp",
+ "Scheduler/MessageQueue.cpp",
"StartPropertySetThread.cpp",
"SurfaceFlinger.cpp",
"SurfaceInterceptor.cpp",
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 8788d47..9096d4c 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -21,10 +21,10 @@
#include "BufferLayerConsumer.h"
-#include "DispSync.h"
#include "Layer.h"
#include "RenderEngine/Image.h"
#include "RenderEngine/RenderEngine.h"
+#include "Scheduler/DispSync.h"
#include <inttypes.h>
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 900b3d7..e0d6ecc 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -23,6 +23,7 @@
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
+#include <cutils/properties.h>
#include <gui/HdrMetadata.h>
#include <math/mat4.h>
#include <ui/GraphicTypes.h>
@@ -160,6 +161,8 @@
}
Builder& setVsyncPeriod(int32_t vsyncPeriod) {
mConfig->mVsyncPeriod = vsyncPeriod;
+ mConfig->mPeriodMultiplier = 1;
+ mConfig->mPeriodDivisor = 1;
return *this;
}
Builder& setDpiX(int32_t dpiX) {
@@ -189,7 +192,12 @@
int32_t getWidth() const { return mWidth; }
int32_t getHeight() const { return mHeight; }
- nsecs_t getVsyncPeriod() const { return mVsyncPeriod; }
+ nsecs_t getVsyncPeriod() const {
+ return mVsyncPeriod * mPeriodMultiplier / mPeriodDivisor; }
+ void scalePanelFrequency(int32_t multiplier, int32_t divisor) const {
+ mPeriodMultiplier = multiplier;
+ mPeriodDivisor = divisor;
+ }
float getDpiX() const { return mDpiX; }
float getDpiY() const { return mDpiY; }
@@ -202,6 +210,8 @@
int32_t mWidth;
int32_t mHeight;
nsecs_t mVsyncPeriod;
+ mutable int32_t mPeriodMultiplier;
+ mutable int32_t mPeriodDivisor;
float mDpiX;
float mDpiY;
};
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d9978b8..2a07074 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -215,7 +215,10 @@
bool Layer::createHwcLayer(HWComposer* hwc, int32_t displayId) {
LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0,
"Already have a layer for display %d", displayId);
- HWC2::Layer* layer = hwc->createLayer(displayId);
+ auto layer = std::shared_ptr<HWC2::Layer>(
+ hwc->createLayer(displayId),
+ [hwc, displayId](HWC2::Layer* layer) {
+ hwc->destroyLayer(displayId, layer); });
if (!layer) {
return false;
}
@@ -234,11 +237,8 @@
auto& hwcInfo = getBE().mHwcLayers[displayId];
LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer");
LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
- hwcInfo.hwc->destroyLayer(displayId, hwcInfo.layer);
- // The layer destroyed listener should have cleared the entry from
- // mHwcLayers. Verify that.
- LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0,
- "Stale layer entry in getBE().mHwcLayers");
+ hwcInfo.layer = nullptr;
+
return true;
}
@@ -701,7 +701,8 @@
auto position = displayTransform.transform(frame);
auto error =
- getBE().mHwcLayers[displayId].layer->setCursorPosition(position.left, position.top);
+ (getBE().mHwcLayers[displayId].layer)->setCursorPosition(
+ position.left, position.top);
ALOGE_IF(error != HWC2::Error::None,
"[%s] Failed to set cursor position "
"to (%d, %d): %s (%d)",
@@ -744,13 +745,13 @@
}
auto& hwcInfo = getBE().mHwcLayers[displayId];
auto& hwcLayer = hwcInfo.layer;
- ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(),
+ ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (hwcLayer)->getId(), to_string(type).c_str(),
static_cast<int>(callIntoHwc));
if (hwcInfo.compositionType != type) {
ALOGV(" actually setting");
hwcInfo.compositionType = type;
if (callIntoHwc) {
- auto error = hwcLayer->setCompositionType(type);
+ auto error = (hwcLayer)->setCompositionType(type);
ALOGE_IF(error != HWC2::Error::None,
"[%s] Failed to set "
"composition type %s: %s (%d)",
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 24a8bde..814adf7 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -510,7 +510,7 @@
if (getBE().mHwcLayers.count(displayId) == 0) {
return nullptr;
}
- return getBE().mHwcLayers[displayId].layer;
+ return getBE().mHwcLayers[displayId].layer.get();
}
// -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp
index 51b615b..b936b3f 100644
--- a/services/surfaceflinger/LayerBE.cpp
+++ b/services/surfaceflinger/LayerBE.cpp
@@ -26,16 +26,23 @@
LayerBE::LayerBE(Layer* layer, std::string layerName)
: mLayer(layer),
mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) {
- compositionInfo.layer = this;
+ compositionInfo.layer = std::make_shared<LayerBE>(*this);
compositionInfo.layerName = layerName;
}
+LayerBE::LayerBE(const LayerBE& layer)
+ : mLayer(layer.mLayer),
+ mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) {
+ compositionInfo.layer = layer.compositionInfo.layer;
+ compositionInfo.layerName = layer.mLayer->getName().string();
+}
+
void LayerBE::onLayerDisplayed(const sp<Fence>& releaseFence) {
mLayer->onLayerDisplayed(releaseFence);
}
void CompositionInfo::dumpHwc(const char* tag) const {
- ALOGV("[%s]\thwcLayer=%p", tag, hwc.hwcLayer);
+ ALOGV("[%s]\thwcLayer=%p", tag, hwc.hwcLayer.get());
ALOGV("[%s]\tfence=%p", tag, hwc.fence.get());
ALOGV("[%s]\ttransform=%d", tag, hwc.transform);
ALOGV("[%s]\tz=%d", tag, hwc.z);
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index b5aceba..3055621 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -37,9 +37,9 @@
HWC2::Composition compositionType;
sp<GraphicBuffer> mBuffer = nullptr;
int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
- LayerBE* layer = nullptr;
+ std::shared_ptr<LayerBE> layer;
struct {
- HWC2::Layer* hwcLayer;
+ std::shared_ptr<HWC2::Layer> hwcLayer;
sp<Fence> fence;
HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid;
Rect displayFrame;
@@ -54,6 +54,7 @@
sp<NativeHandle> sidebandStream;
ui::Dataspace dataspace;
hwc_color_t color;
+ bool clearClientTarget = false;
} hwc;
struct {
Mesh* mesh;
@@ -83,6 +84,7 @@
friend class SurfaceFlinger;
LayerBE(Layer* layer, std::string layerName);
+ explicit LayerBE(const LayerBE& layer);
void onLayerDisplayed(const sp<Fence>& releaseFence);
Mesh& getMesh() { return mMesh; }
@@ -103,7 +105,7 @@
transform(HWC2::Transform::None) {}
HWComposer* hwc;
- HWC2::Layer* layer;
+ std::shared_ptr<HWC2::Layer> layer;
bool forceClientComposition;
HWC2::Composition compositionType;
bool clearClientTarget;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 389fbd2..06e3d9c 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#include "MessageQueue.h"
#include "MonitoredProducer.h"
-#include "SurfaceFlinger.h"
#include "Layer.h"
+#include "SurfaceFlinger.h"
+
+#include "Scheduler/MessageQueue.h"
namespace android {
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 744a70c..4860f3c 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -30,7 +30,6 @@
#include <utils/Trace.h>
#include <cutils/compiler.h>
-#include <gui/ISurfaceComposer.h>
#include <math.h>
#include "Description.h"
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 40bc966..d2b218e 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -26,7 +26,6 @@
#include <EGL/eglext.h>
#include <Transform.h>
#include <android-base/unique_fd.h>
-#include <gui/SurfaceControl.h>
#include <math/mat4.h>
#define EGL_NO_CONFIG ((EGLConfig)0)
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
similarity index 97%
rename from services/surfaceflinger/DispSync.cpp
rename to services/surfaceflinger/Scheduler/DispSync.cpp
index cdfbba3..9d9acd3 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -515,12 +515,25 @@
void DispSync::setPeriod(nsecs_t period) {
Mutex::Autolock lock(mMutex);
- mPeriod = period;
+ mPeriodBase = mPeriod = period;
mPhase = 0;
mReferenceTime = 0;
mThread->updateModel(mPeriod, mPhase, mReferenceTime);
}
+void DispSync::scalePeriod(uint32_t multiplier, uint32_t divisor) {
+ Mutex::Autolock lock(mMutex);
+
+ // if only 1 of the properties is updated, we will get to this
+ // point "attempting" to set the scale to 1 when it is already
+ // 1. Check that special case so that we don't do a useless
+ // update of the model.
+ if ((multiplier == 1) && (divisor == 1) && (mPeriod == mPeriodBase)) return;
+
+ mPeriod = mPeriodBase * multiplier / divisor;
+ mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+}
+
nsecs_t DispSync::getPeriod() {
// lock mutex as mPeriod changes multiple times in updateModelLocked
Mutex::Autolock lock(mMutex);
@@ -545,7 +558,7 @@
// Exclude the min and max from the average
durationSum -= minDuration + maxDuration;
- mPeriod = durationSum / (mNumResyncSamples - 3);
+ mPeriodBase = mPeriod = durationSum / (mNumResyncSamples - 3);
ALOGV("[%s] mPeriod = %" PRId64, mName, ns2us(mPeriod));
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
similarity index 95%
rename from services/surfaceflinger/DispSync.h
rename to services/surfaceflinger/Scheduler/DispSync.h
index 1be131f..183966f 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -48,6 +48,7 @@
virtual bool addResyncSample(nsecs_t timestamp) = 0;
virtual void endResync() = 0;
virtual void setPeriod(nsecs_t period) = 0;
+ virtual void scalePeriod(const uint32_t multiplier, uint32_t divisor) = 0;
virtual nsecs_t getPeriod() = 0;
virtual void setRefreshSkipCount(int count) = 0;
virtual status_t addEventListener(const char* name, nsecs_t phase, Callback* callback) = 0;
@@ -117,6 +118,12 @@
// turned on. It should NOT be used after that.
void setPeriod(nsecs_t period) override;
+ // The scalePeriod method applies the multiplier and divisor to
+ // scale the vsync event model's period. The function is added
+ // for an experimental test mode and should not be used outside
+ // of that purpose.
+ void scalePeriod(const uint32_t multiplier, uint32_t divisor);
+
// The getPeriod method returns the current vsync period.
nsecs_t getPeriod() override;
@@ -176,6 +183,7 @@
// mPeriod is the computed period of the modeled vsync events in
// nanoseconds.
nsecs_t mPeriod;
+ nsecs_t mPeriodBase;
// mPhase is the phase offset of the modeled vsync events. It is the
// number of nanoseconds from time 0 to the first vsync event.
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
new file mode 100644
index 0000000..61f2ac8
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2018 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 "DispSyncSource.h"
+
+#include <android-base/stringprintf.h>
+#include <utils/Trace.h>
+#include <mutex>
+
+#include "DispSync.h"
+#include "EventThread.h"
+
+namespace android {
+
+DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
+ const char* name)
+ : mName(name),
+ mTraceVsync(traceVsync),
+ mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
+ mVsyncEventLabel(base::StringPrintf("VSYNC-%s", name)),
+ mDispSync(dispSync),
+ mPhaseOffset(phaseOffset) {}
+
+void DispSyncSource::setVSyncEnabled(bool enable) {
+ std::lock_guard lock(mVsyncMutex);
+ if (enable) {
+ status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
+ static_cast<DispSync::Callback*>(this));
+ if (err != NO_ERROR) {
+ ALOGE("error registering vsync callback: %s (%d)", strerror(-err), err);
+ }
+ // ATRACE_INT(mVsyncOnLabel.c_str(), 1);
+ } else {
+ status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this));
+ if (err != NO_ERROR) {
+ ALOGE("error unregistering vsync callback: %s (%d)", strerror(-err), err);
+ }
+ // ATRACE_INT(mVsyncOnLabel.c_str(), 0);
+ }
+ mEnabled = enable;
+}
+
+void DispSyncSource::setCallback(VSyncSource::Callback* callback) {
+ std::lock_guard lock(mCallbackMutex);
+ mCallback = callback;
+}
+
+void DispSyncSource::setPhaseOffset(nsecs_t phaseOffset) {
+ std::lock_guard lock(mVsyncMutex);
+
+ // Normalize phaseOffset to [0, period)
+ auto period = mDispSync->getPeriod();
+ phaseOffset %= period;
+ if (phaseOffset < 0) {
+ // If we're here, then phaseOffset is in (-period, 0). After this
+ // operation, it will be in (0, period)
+ phaseOffset += period;
+ }
+ mPhaseOffset = phaseOffset;
+
+ // If we're not enabled, we don't need to mess with the listeners
+ if (!mEnabled) {
+ return;
+ }
+
+ status_t err =
+ mDispSync->changePhaseOffset(static_cast<DispSync::Callback*>(this), mPhaseOffset);
+ if (err != NO_ERROR) {
+ ALOGE("error changing vsync offset: %s (%d)", strerror(-err), err);
+ }
+}
+
+void DispSyncSource::onDispSyncEvent(nsecs_t when) {
+ VSyncSource::Callback* callback;
+ {
+ std::lock_guard lock(mCallbackMutex);
+ callback = mCallback;
+
+ if (mTraceVsync) {
+ mValue = (mValue + 1) % 2;
+ ATRACE_INT(mVsyncEventLabel.c_str(), mValue);
+ }
+ }
+
+ if (callback != nullptr) {
+ callback->onVSyncEvent(when);
+ }
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
new file mode 100644
index 0000000..0fd84a2
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 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 <mutex>
+#include <string>
+
+#include "DispSync.h"
+#include "EventThread.h"
+
+namespace android {
+
+class DispSyncSource final : public VSyncSource, private DispSync::Callback {
+public:
+ DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* name);
+
+ ~DispSyncSource() override = default;
+
+ // The following methods are implementation of VSyncSource.
+ void setVSyncEnabled(bool enable) override;
+ void setCallback(VSyncSource::Callback* callback) override;
+ void setPhaseOffset(nsecs_t phaseOffset) override;
+
+private:
+ // The following method is the implementation of the DispSync::Callback.
+ virtual void onDispSyncEvent(nsecs_t when);
+
+ const char* const mName;
+ int mValue = 0;
+
+ const bool mTraceVsync;
+ const std::string mVsyncOnLabel;
+ const std::string mVsyncEventLabel;
+
+ DispSync* mDispSync;
+
+ std::mutex mCallbackMutex;
+ VSyncSource::Callback* mCallback GUARDED_BY(mCallbackMutex) = nullptr;
+
+ std::mutex mVsyncMutex;
+ nsecs_t mPhaseOffset GUARDED_BY(mVsyncMutex);
+ bool mEnabled GUARDED_BY(mVsyncMutex) = false;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/Scheduler/EventControlThread.cpp
similarity index 100%
rename from services/surfaceflinger/EventControlThread.cpp
rename to services/surfaceflinger/Scheduler/EventControlThread.cpp
diff --git a/services/surfaceflinger/EventControlThread.h b/services/surfaceflinger/Scheduler/EventControlThread.h
similarity index 100%
rename from services/surfaceflinger/EventControlThread.h
rename to services/surfaceflinger/Scheduler/EventControlThread.h
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
similarity index 98%
rename from services/surfaceflinger/EventThread.cpp
rename to services/surfaceflinger/Scheduler/EventThread.cpp
index 5a8fd25..b84177c 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -100,7 +100,8 @@
return NO_ERROR;
}
-void EventThread::removeDisplayEventConnectionLocked(const wp<EventThread::Connection>& connection) {
+void EventThread::removeDisplayEventConnectionLocked(
+ const wp<EventThread::Connection>& connection) {
mDisplayEventConnections.remove(connection);
}
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
similarity index 100%
rename from services/surfaceflinger/EventThread.h
rename to services/surfaceflinger/Scheduler/EventThread.h
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
similarity index 100%
rename from services/surfaceflinger/MessageQueue.cpp
rename to services/surfaceflinger/Scheduler/MessageQueue.cpp
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
similarity index 100%
rename from services/surfaceflinger/MessageQueue.h
rename to services/surfaceflinger/Scheduler/MessageQueue.h
diff --git a/services/surfaceflinger/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
similarity index 95%
rename from services/surfaceflinger/VSyncModulator.h
rename to services/surfaceflinger/Scheduler/VSyncModulator.h
index e071a59..7dfad43 100644
--- a/services/surfaceflinger/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -29,22 +29,17 @@
*/
class VSyncModulator {
private:
-
// Number of frames we'll keep the early phase offsets once they are activated. This acts as a
// low-pass filter in case the client isn't quick enough in sending new transactions.
const int MIN_EARLY_FRAME_COUNT = 2;
public:
-
struct Offsets {
nsecs_t sf;
nsecs_t app;
};
- enum TransactionStart {
- EARLY,
- NORMAL
- };
+ enum TransactionStart { EARLY, NORMAL };
// Sets the phase offsets
//
@@ -63,13 +58,9 @@
mOffsets = late;
}
- Offsets getEarlyOffsets() const {
- return mEarlyOffsets;
- }
+ Offsets getEarlyOffsets() const { return mEarlyOffsets; }
- Offsets getEarlyGlOffsets() const {
- return mEarlyGlOffsets;
- }
+ Offsets getEarlyGlOffsets() const { return mEarlyGlOffsets; }
void setEventThreads(EventThread* sfEventThread, EventThread* appEventThread) {
mSfEventThread = sfEventThread;
@@ -77,7 +68,6 @@
}
void setTransactionStart(TransactionStart transactionStart) {
-
if (transactionStart == TransactionStart::EARLY) {
mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT;
}
@@ -112,7 +102,6 @@
}
private:
-
void updateOffsets() {
const Offsets desired = getOffsets();
const Offsets current = mOffsets;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 31e4444..8ef15bd 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -70,10 +70,7 @@
#include "Colorizer.h"
#include "ContainerLayer.h"
#include "DdmConnection.h"
-#include "DispSync.h"
#include "DisplayDevice.h"
-#include "EventControlThread.h"
-#include "EventThread.h"
#include "Layer.h"
#include "LayerVector.h"
#include "MonitoredProducer.h"
@@ -85,10 +82,13 @@
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
-
#include "Effects/Daltonizer.h"
-
#include "RenderEngine/RenderEngine.h"
+#include "Scheduler/DispSync.h"
+#include "Scheduler/DispSyncSource.h"
+#include "Scheduler/EventControlThread.h"
+#include "Scheduler/EventThread.h"
+
#include <cutils/compiler.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
@@ -266,6 +266,7 @@
mForceFullDamage(false),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
+ mRefreshStartTime(0),
mHasPoweredOff(false),
mNumLayers(0),
mVrFlingerRequestsDisplay(false),
@@ -565,112 +566,6 @@
postMessageAsync(new LambdaMessage([=] { getRenderEngine().deleteTextures(1, &texture); }));
}
-class DispSyncSource final : public VSyncSource, private DispSync::Callback {
-public:
- DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
- const char* name) :
- mName(name),
- mValue(0),
- mTraceVsync(traceVsync),
- mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
- mVsyncEventLabel(String8::format("VSYNC-%s", name)),
- mDispSync(dispSync),
- mCallbackMutex(),
- mVsyncMutex(),
- mPhaseOffset(phaseOffset),
- mEnabled(false) {}
-
- ~DispSyncSource() override = default;
-
- void setVSyncEnabled(bool enable) override {
- Mutex::Autolock lock(mVsyncMutex);
- if (enable) {
- status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
- static_cast<DispSync::Callback*>(this));
- if (err != NO_ERROR) {
- ALOGE("error registering vsync callback: %s (%d)",
- strerror(-err), err);
- }
- //ATRACE_INT(mVsyncOnLabel.string(), 1);
- } else {
- status_t err = mDispSync->removeEventListener(
- static_cast<DispSync::Callback*>(this));
- if (err != NO_ERROR) {
- ALOGE("error unregistering vsync callback: %s (%d)",
- strerror(-err), err);
- }
- //ATRACE_INT(mVsyncOnLabel.string(), 0);
- }
- mEnabled = enable;
- }
-
- void setCallback(VSyncSource::Callback* callback) override{
- Mutex::Autolock lock(mCallbackMutex);
- mCallback = callback;
- }
-
- void setPhaseOffset(nsecs_t phaseOffset) override {
- Mutex::Autolock lock(mVsyncMutex);
-
- // Normalize phaseOffset to [0, period)
- auto period = mDispSync->getPeriod();
- phaseOffset %= period;
- if (phaseOffset < 0) {
- // If we're here, then phaseOffset is in (-period, 0). After this
- // operation, it will be in (0, period)
- phaseOffset += period;
- }
- mPhaseOffset = phaseOffset;
-
- // If we're not enabled, we don't need to mess with the listeners
- if (!mEnabled) {
- return;
- }
-
- status_t err = mDispSync->changePhaseOffset(static_cast<DispSync::Callback*>(this),
- mPhaseOffset);
- if (err != NO_ERROR) {
- ALOGE("error changing vsync offset: %s (%d)",
- strerror(-err), err);
- }
- }
-
-private:
- virtual void onDispSyncEvent(nsecs_t when) {
- VSyncSource::Callback* callback;
- {
- Mutex::Autolock lock(mCallbackMutex);
- callback = mCallback;
-
- if (mTraceVsync) {
- mValue = (mValue + 1) % 2;
- ATRACE_INT(mVsyncEventLabel.string(), mValue);
- }
- }
-
- if (callback != nullptr) {
- callback->onVSyncEvent(when);
- }
- }
-
- const char* const mName;
-
- int mValue;
-
- const bool mTraceVsync;
- const String8 mVsyncOnLabel;
- const String8 mVsyncEventLabel;
-
- DispSync* mDispSync;
-
- Mutex mCallbackMutex; // Protects the following
- VSyncSource::Callback* mCallback = nullptr;
-
- Mutex mVsyncMutex; // Protects the following
- nsecs_t mPhaseOffset;
- bool mEnabled;
-};
-
class InjectVSyncSource final : public VSyncSource {
public:
InjectVSyncSource() = default;
@@ -1221,15 +1116,6 @@
status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const
NO_THREAD_SAFETY_ANALYSIS {
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if ((uid != AID_SHELL) &&
- !PermissionCache::checkPermission(sDump, pid, uid)) {
- ALOGE("Layer debug info permission denied for pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
-
// Try to acquire a lock for 1s, fail gracefully
const status_t err = mStateLock.timedLock(s2ns(1));
const bool locked = (err == NO_ERROR);
@@ -1584,16 +1470,16 @@
mRefreshPending = false;
- nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
- preComposition(refreshStartTime);
+ preComposition();
rebuildLayerStacks();
- setUpHWComposer();
+ calculateWorkingSet();
+ beginFrame();
+ prepareFrame();
doDebugFlashRegions();
doTracing("handleRefresh");
logLayerStats();
doComposition();
- postComposition(refreshStartTime);
+ postComposition();
mHadClientComposition = false;
for (const auto& [token, display] : mDisplays) {
@@ -1605,6 +1491,84 @@
mLayersWithQueuedFrames.clear();
}
+void SurfaceFlinger::calculateWorkingSet() {
+ ATRACE_CALL();
+ ALOGV(__FUNCTION__);
+
+ // build the h/w work list
+ if (CC_UNLIKELY(mGeometryInvalid)) {
+ mGeometryInvalid = false;
+ for (const auto& [token, display] : mDisplays) {
+ const auto displayId = display->getId();
+ if (displayId >= 0) {
+ const Vector<sp<Layer>>& currentLayers(
+ display->getVisibleLayersSortedByZ());
+ for (size_t i = 0; i < currentLayers.size(); i++) {
+ const auto& layer = currentLayers[i];
+
+ if (!layer->hasHwcLayer(displayId)) {
+ if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) {
+ layer->forceClientComposition(displayId);
+ continue;
+ }
+ }
+
+ layer->setGeometry(display, i);
+ if (mDebugDisableHWC || mDebugRegion) {
+ layer->forceClientComposition(displayId);
+ }
+ }
+ }
+ }
+ }
+
+ // Set the per-frame data
+ for (const auto& [token, display] : mDisplays) {
+ const auto displayId = display->getId();
+ if (displayId < 0) {
+ continue;
+ }
+
+ if (mDrawingState.colorMatrixChanged) {
+ display->setColorTransform(mDrawingState.colorMatrix);
+ status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix);
+ ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
+ "display %d: %d", displayId, result);
+ }
+ for (auto& layer : display->getVisibleLayersSortedByZ()) {
+ if (layer->isHdrY410()) {
+ layer->forceClientComposition(displayId);
+ } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
+ layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
+ !display->hasHDR10Support()) {
+ layer->forceClientComposition(displayId);
+ } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
+ layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
+ !display->hasHLGSupport()) {
+ layer->forceClientComposition(displayId);
+ }
+
+ if (layer->getForceClientComposition(displayId)) {
+ ALOGV("[%s] Requesting Client composition", layer->getName().string());
+ layer->setCompositionType(displayId, HWC2::Composition::Client);
+ continue;
+ }
+
+ layer->setPerFrameData(display);
+ }
+
+ if (hasWideColorDisplay) {
+ ColorMode colorMode;
+ Dataspace dataSpace;
+ RenderIntent renderIntent;
+ pickColorMode(display, &colorMode, &dataSpace, &renderIntent);
+ setActiveColorModeInternal(display, colorMode, dataSpace, renderIntent);
+ }
+ }
+
+ mDrawingState.colorMatrixChanged = false;
+}
+
void SurfaceFlinger::doDebugFlashRegions()
{
// is debugging enabled
@@ -1669,14 +1633,16 @@
}
}
-void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
+void SurfaceFlinger::preComposition()
{
ATRACE_CALL();
ALOGV("preComposition");
+ mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
+
bool needExtraInvalidate = false;
mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (layer->onPreComposition(refreshStartTime)) {
+ if (layer->onPreComposition(mRefreshStartTime)) {
needExtraInvalidate = true;
}
});
@@ -1745,7 +1711,7 @@
getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}
-void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
+void SurfaceFlinger::postComposition()
{
ATRACE_CALL();
ALOGV("postComposition");
@@ -1778,11 +1744,11 @@
nsecs_t vsyncPhase = mPrimaryDispSync->computeNextRefresh(0);
nsecs_t vsyncInterval = mPrimaryDispSync->getPeriod();
- // We use the refreshStartTime which might be sampled a little later than
+ // We use the mRefreshStartTime which might be sampled a little later than
// when we started doing work for this frame, but that should be okay
// since updateCompositorTiming has snapping logic.
updateCompositorTiming(
- vsyncPhase, vsyncInterval, refreshStartTime, presentFenceTime);
+ vsyncPhase, vsyncInterval, mRefreshStartTime, presentFenceTime);
CompositorTiming compositorTiming;
{
std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
@@ -2004,10 +1970,8 @@
display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent);
}
-void SurfaceFlinger::setUpHWComposer() {
- ATRACE_CALL();
- ALOGV("setUpHWComposer");
-
+void SurfaceFlinger::beginFrame()
+{
for (const auto& [token, display] : mDisplays) {
bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty();
bool empty = display->getVisibleLayersSortedByZ().size() == 0;
@@ -2033,78 +1997,10 @@
display->lastCompositionHadVisibleLayers = !empty;
}
}
+}
- // build the h/w work list
- if (CC_UNLIKELY(mGeometryInvalid)) {
- mGeometryInvalid = false;
- for (const auto& [token, display] : mDisplays) {
- const auto displayId = display->getId();
- if (displayId >= 0) {
- const Vector<sp<Layer>>& currentLayers = display->getVisibleLayersSortedByZ();
- for (size_t i = 0; i < currentLayers.size(); i++) {
- const auto& layer = currentLayers[i];
- if (!layer->hasHwcLayer(displayId)) {
- if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) {
- layer->forceClientComposition(displayId);
- continue;
- }
- }
-
- layer->setGeometry(display, i);
- if (mDebugDisableHWC || mDebugRegion) {
- layer->forceClientComposition(displayId);
- }
- }
- }
- }
- }
-
- // Set the per-frame data
- for (const auto& [token, display] : mDisplays) {
- const auto displayId = display->getId();
- if (displayId < 0) {
- continue;
- }
-
- if (mDrawingState.colorMatrixChanged) {
- display->setColorTransform(mDrawingState.colorMatrix);
- status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix);
- ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %d: %d",
- displayId, result);
- }
- for (auto& layer : display->getVisibleLayersSortedByZ()) {
- if (layer->isHdrY410()) {
- layer->forceClientComposition(displayId);
- } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
- layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
- !display->hasHDR10Support()) {
- layer->forceClientComposition(displayId);
- } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
- layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
- !display->hasHLGSupport()) {
- layer->forceClientComposition(displayId);
- }
-
- if (layer->getForceClientComposition(displayId)) {
- ALOGV("[%s] Requesting Client composition", layer->getName().string());
- layer->setCompositionType(displayId, HWC2::Composition::Client);
- continue;
- }
-
- layer->setPerFrameData(display);
- }
-
- if (hasWideColorDisplay) {
- ColorMode colorMode;
- Dataspace dataSpace;
- RenderIntent renderIntent;
- pickColorMode(display, &colorMode, &dataSpace, &renderIntent);
- setActiveColorModeInternal(display, colorMode, dataSpace, renderIntent);
- }
- }
-
- mDrawingState.colorMatrixChanged = false;
-
+void SurfaceFlinger::prepareFrame()
+{
for (const auto& [token, display] : mDisplays) {
if (!display->isPoweredOn()) {
continue;
@@ -2329,7 +2225,9 @@
getHwComposer().getRenderIntents(displayId, colorMode);
hwcColorModes.emplace(colorMode, renderIntents);
}
+ }
+ if (displayId >= 0) {
getHwComposer().getHdrCapabilities(displayId, &hdrCapabilities);
supportedPerFrameMetadata = getHwComposer().getSupportedPerFrameMetadata(displayId);
}
@@ -3376,9 +3274,8 @@
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
-
if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
- !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
+ !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
return false;
}
return true;
@@ -4564,51 +4461,64 @@
}
status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {
- switch (code) {
- case CREATE_CONNECTION:
- case CREATE_DISPLAY:
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wswitch-enum"
+ switch (static_cast<ISurfaceComposerTag>(code)) {
+ // These methods should at minimum make sure that the client requested
+ // access to SF.
+ case AUTHENTICATE_SURFACE:
case BOOT_FINISHED:
case CLEAR_ANIMATION_FRAME_STATS:
- case GET_ANIMATION_FRAME_STATS:
- case SET_POWER_MODE:
- case GET_HDR_CAPABILITIES:
+ case CREATE_CONNECTION:
+ case CREATE_DISPLAY:
+ case DESTROY_DISPLAY:
case ENABLE_VSYNC_INJECTIONS:
+ case GET_ACTIVE_COLOR_MODE:
+ case GET_ANIMATION_FRAME_STATS:
+ case GET_HDR_CAPABILITIES:
+ case SET_ACTIVE_CONFIG:
+ case SET_ACTIVE_COLOR_MODE:
case INJECT_VSYNC:
- {
- // codes that require permission check
+ case SET_POWER_MODE: {
if (!callingThreadHasUnscopedSurfaceFlingerAccess()) {
IPCThreadState* ipc = IPCThreadState::self();
ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d",
ipc->getCallingPid(), ipc->getCallingUid());
return PERMISSION_DENIED;
}
- break;
- }
- /*
- * Calling setTransactionState is safe, because you need to have been
- * granted a reference to Client* and Handle* to do anything with it.
- *
- * Creating a scoped connection is safe, as per discussion in ISurfaceComposer.h
- */
- case SET_TRANSACTION_STATE:
- case CREATE_SCOPED_CONNECTION:
- {
return OK;
}
- case CAPTURE_SCREEN:
- {
- // codes that require permission check
+ case GET_LAYER_DEBUG_INFO: {
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
- if ((uid != AID_GRAPHICS) &&
- !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
- ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid);
+ if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) {
+ ALOGE("Layer debug info permission denied for pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
}
- break;
+ return OK;
}
- case CAPTURE_LAYERS: {
+ // Used by apps to hook Choreographer to SurfaceFlinger.
+ case CREATE_DISPLAY_EVENT_CONNECTION:
+ // The following calls are currently used by clients that do not
+ // request necessary permissions. However, they do not expose any secret
+ // information, so it is OK to pass them.
+ case GET_ACTIVE_CONFIG:
+ case GET_BUILT_IN_DISPLAY:
+ case GET_DISPLAY_COLOR_MODES:
+ case GET_DISPLAY_CONFIGS:
+ case GET_DISPLAY_STATS:
+ case GET_SUPPORTED_FRAME_TIMESTAMPS:
+ // Calling setTransactionState is safe, because you need to have been
+ // granted a reference to Client* and Handle* to do anything with it.
+ case SET_TRANSACTION_STATE:
+ // Creating a scoped connection is safe, as per discussion in ISurfaceComposer.h
+ case CREATE_SCOPED_CONNECTION: {
+ return OK;
+ }
+ case CAPTURE_LAYERS:
+ case CAPTURE_SCREEN: {
+ // codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
@@ -4617,15 +4527,37 @@
ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
}
- break;
+ return OK;
+ }
+ // The following codes are deprecated and should never be allowed to access SF.
+ case CONNECT_DISPLAY_UNUSED:
+ case CREATE_GRAPHIC_BUFFER_ALLOC_UNUSED: {
+ ALOGE("Attempting to access SurfaceFlinger with unused code: %u", code);
+ return PERMISSION_DENIED;
}
}
- return OK;
+
+ // These codes are used for the IBinder protocol to either interrogate the recipient
+ // side of the transaction for its canonical interface descriptor or to dump its state.
+ // We let them pass by default.
+ if (code == IBinder::INTERFACE_TRANSACTION || code == IBinder::DUMP_TRANSACTION ||
+ code == IBinder::PING_TRANSACTION || code == IBinder::SHELL_COMMAND_TRANSACTION ||
+ code == IBinder::SYSPROPS_TRANSACTION) {
+ return OK;
+ }
+ // Numbers from 1000 to 1029 are currently use for backdoors. The code
+ // in onTransact verifies that the user is root, and has access to use SF.
+ if (code >= 1000 && code <= 1029) {
+ ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
+ return OK;
+ }
+ ALOGE("Permission Denial: SurfaceFlinger did not recognize request code: %u", code);
+ return PERMISSION_DENIED;
+#pragma clang diagnostic pop
}
-status_t SurfaceFlinger::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
+status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
status_t credentialCheck = CheckTransactCodeCredentials(code);
if (credentialCheck != OK) {
return credentialCheck;
@@ -4855,6 +4787,33 @@
reply->writeBool(getBE().mHwc->isUsingVrComposer());
return NO_ERROR;
}
+ case 1029: {
+ // Code 1029 is an experimental feature that allows applications to
+ // simulate a high frequency panel by setting a multiplier and divisor
+ // on the VSYNC-sf clock. If either the multiplier or divisor are
+ // 0, then the code will set both to 1 to return the VSYNC-sf clock
+ // to it's normal frequency.
+ int multiplier = data.readInt32();
+ int divisor = data.readInt32();
+
+ if ((multiplier == 0) || (divisor == 0)) {
+ multiplier = 1;
+ divisor = 1;
+ }
+
+ if ((multiplier == 1) && (divisor == 1)) {
+ enableHardwareVsync();
+ } else {
+ disableHardwareVsync(true);
+ }
+ getBE().mHwc->getActiveConfig(DisplayDevice::DISPLAY_PRIMARY)
+ ->scalePanelFrequency(multiplier, divisor);
+ mPrimaryDispSync->scalePeriod(multiplier, divisor);
+
+ ATRACE_INT("PeriodMultiplier", multiplier);
+ ATRACE_INT("PeriodDivisor", divisor);
+ return NO_ERROR;
+ }
}
}
return err;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 12f4185..f5d8eb4 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -55,23 +55,22 @@
#include "Barrier.h"
#include "DisplayDevice.h"
-#include "DispSync.h"
-#include "EventThread.h"
#include "FrameTracker.h"
+#include "LayerBE.h"
#include "LayerStats.h"
#include "LayerVector.h"
-#include "MessageQueue.h"
+#include "StartPropertySetThread.h"
#include "SurfaceInterceptor.h"
#include "SurfaceTracing.h"
-#include "StartPropertySetThread.h"
-#include "TimeStats/TimeStats.h"
-#include "LayerBE.h"
-#include "VSyncModulator.h"
#include "DisplayHardware/HWC2.h"
#include "DisplayHardware/HWComposer.h"
-
#include "Effects/Daltonizer.h"
+#include "Scheduler/DispSync.h"
+#include "Scheduler/EventThread.h"
+#include "Scheduler/MessageQueue.h"
+#include "Scheduler/VSyncModulator.h"
+#include "TimeStats/TimeStats.h"
#include <map>
#include <mutex>
@@ -649,8 +648,8 @@
void computeVisibleRegions(const sp<const DisplayDevice>& display, Region& dirtyRegion,
Region& opaqueRegion);
- void preComposition(nsecs_t refreshStartTime);
- void postComposition(nsecs_t refreshStartTime);
+ void preComposition();
+ void postComposition();
void updateCompositorTiming(
nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
std::shared_ptr<FenceTime>& presentFenceTime);
@@ -668,7 +667,18 @@
void pickColorMode(const sp<DisplayDevice>& display, ui::ColorMode* outMode,
ui::Dataspace* outDataSpace, ui::RenderIntent* outRenderIntent) const;
- void setUpHWComposer();
+ void calculateWorkingSet();
+ /*
+ * beginFrame - This function handles any pre-frame processing that needs to be
+ * prior to any CompositionInfo handling and is not dependent on data in
+ * CompositionInfo
+ */
+ void beginFrame();
+ /* prepareFrame - This function will call into the DisplayDevice to prepare a
+ * frame after CompositionInfo has been programmed. This provides a mechanism
+ * to prepare the hardware composer
+ */
+ void prepareFrame();
void doComposition();
void doDebugFlashRegions();
void doTracing(const char* where);
@@ -864,6 +874,7 @@
Mutex mHWVsyncLock;
bool mPrimaryHWVsyncEnabled;
bool mHWVsyncAvailable;
+ nsecs_t mRefreshStartTime;
std::atomic<bool> mRefreshPending{false};
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index c511c5e..604aa7d 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -17,6 +17,7 @@
defaults: ["surfaceflinger_defaults"],
test_suites: ["device-tests"],
srcs: [
+ "Credentials_test.cpp",
"Stress_test.cpp",
"SurfaceInterceptor_test.cpp",
"Transaction_test.cpp",
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
new file mode 100644
index 0000000..cd57411
--- /dev/null
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -0,0 +1,322 @@
+#include <algorithm>
+#include <functional>
+#include <limits>
+#include <ostream>
+
+#include <gtest/gtest.h>
+
+#include <gui/ISurfaceComposer.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include <private/android_filesystem_config.h>
+#include <private/gui/ComposerService.h>
+
+#include <ui/DisplayInfo.h>
+#include <utils/String8.h>
+
+namespace android {
+
+using Transaction = SurfaceComposerClient::Transaction;
+
+namespace {
+const String8 DISPLAY_NAME("Credentials Display Test");
+const String8 SURFACE_NAME("Test Surface Name");
+const int32_t MIN_LAYER_Z = 0;
+const int32_t MAX_LAYER_Z = std::numeric_limits<int32_t>::max();
+const uint32_t ROTATION = 0;
+const float FRAME_SCALE = 1.0f;
+} // namespace
+
+/**
+ * This class tests the CheckCredentials method in SurfaceFlinger.
+ * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
+ * return anything meaningful.
+ */
+class CredentialsTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ // Start the tests as root.
+ seteuid(AID_ROOT);
+
+ ASSERT_NO_FATAL_FAILURE(initClient());
+ }
+
+ void TearDown() override {
+ mComposerClient->dispose();
+ mBGSurfaceControl.clear();
+ mComposerClient.clear();
+ // Finish the tests as root.
+ seteuid(AID_ROOT);
+ }
+
+ sp<IBinder> mDisplay;
+ sp<IBinder> mVirtualDisplay;
+ sp<SurfaceComposerClient> mComposerClient;
+ sp<SurfaceControl> mBGSurfaceControl;
+ sp<SurfaceControl> mVirtualSurfaceControl;
+
+ void initClient() {
+ mComposerClient = new SurfaceComposerClient;
+ ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
+ }
+
+ void setupBackgroundSurface() {
+ mDisplay = SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
+ DisplayInfo info;
+ SurfaceComposerClient::getDisplayInfo(mDisplay, &info);
+ const ssize_t displayWidth = info.w;
+ const ssize_t displayHeight = info.h;
+
+ // Background surface
+ mBGSurfaceControl =
+ mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
+ PIXEL_FORMAT_RGBA_8888, 0);
+ ASSERT_TRUE(mBGSurfaceControl != nullptr);
+ ASSERT_TRUE(mBGSurfaceControl->isValid());
+
+ Transaction t;
+ t.setDisplayLayerStack(mDisplay, 0);
+ ASSERT_EQ(NO_ERROR,
+ t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
+ }
+
+ void setupVirtualDisplay() {
+ mVirtualDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
+ const ssize_t displayWidth = 100;
+ const ssize_t displayHeight = 100;
+
+ // Background surface
+ mVirtualSurfaceControl =
+ mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
+ PIXEL_FORMAT_RGBA_8888, 0);
+ ASSERT_TRUE(mVirtualSurfaceControl != nullptr);
+ ASSERT_TRUE(mVirtualSurfaceControl->isValid());
+
+ Transaction t;
+ t.setDisplayLayerStack(mVirtualDisplay, 0);
+ ASSERT_EQ(NO_ERROR,
+ t.setLayer(mVirtualSurfaceControl, INT_MAX - 3)
+ .show(mVirtualSurfaceControl)
+ .apply());
+ }
+
+ /**
+ * Sets UID to imitate Graphic's process.
+ */
+ void setGraphicsUID() {
+ seteuid(AID_ROOT);
+ seteuid(AID_GRAPHICS);
+ }
+
+ /**
+ * Sets UID to imitate System's process.
+ */
+ void setSystemUID() {
+ seteuid(AID_ROOT);
+ seteuid(AID_SYSTEM);
+ }
+
+ /**
+ * Sets UID to imitate a process that doesn't have any special privileges in
+ * our code.
+ */
+ void setBinUID() {
+ seteuid(AID_ROOT);
+ seteuid(AID_BIN);
+ }
+
+ /**
+ * Template function the check a condition for different types of users: root
+ * graphics, system, and non-supported user. Root, graphics, and system should
+ * always equal privilegedValue, and non-supported user should equal unprivilegedValue.
+ */
+ template <typename T>
+ void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
+ // Check with root.
+ seteuid(AID_ROOT);
+ ASSERT_EQ(privilegedValue, condition());
+
+ // Check as a Graphics user.
+ setGraphicsUID();
+ ASSERT_EQ(privilegedValue, condition());
+
+ // Check as a system user.
+ setSystemUID();
+ ASSERT_EQ(privilegedValue, condition());
+
+ // Check as a non-supported user.
+ setBinUID();
+ ASSERT_EQ(unprivilegedValue, condition());
+ }
+};
+
+TEST_F(CredentialsTest, ClientInitTest) {
+ // Root can init can init the client.
+ ASSERT_NO_FATAL_FAILURE(initClient());
+
+ // Graphics can init the client.
+ setGraphicsUID();
+ ASSERT_NO_FATAL_FAILURE(initClient());
+
+ // System can init the client.
+ setSystemUID();
+ ASSERT_NO_FATAL_FAILURE(initClient());
+
+ // No one else can init the client.
+ setBinUID();
+ mComposerClient = new SurfaceComposerClient;
+ ASSERT_EQ(NO_INIT, mComposerClient->initCheck());
+}
+
+TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
+ std::function<bool()> condition = [=]() {
+ sp<IBinder> display(
+ SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+ return (display != nullptr);
+ };
+ // Anyone can access display information.
+ ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
+}
+
+TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
+ // The following methods are tested with a UID that is not root, graphics,
+ // or system, to show that anyone can access them.
+ setBinUID();
+ sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+ ASSERT_TRUE(display != nullptr);
+
+ DisplayInfo info;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
+
+ Vector<DisplayInfo> configs;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
+
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveConfig(display));
+
+ ASSERT_NE(static_cast<ui::ColorMode>(BAD_VALUE),
+ SurfaceComposerClient::getActiveColorMode(display));
+}
+
+TEST_F(CredentialsTest, GetDisplayColorModesTest) {
+ sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+ std::function<status_t()> condition = [=]() {
+ Vector<ui::ColorMode> outColorModes;
+ return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes);
+ };
+ ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
+}
+
+TEST_F(CredentialsTest, SetActiveConfigTest) {
+ sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+ std::function<status_t()> condition = [=]() {
+ return SurfaceComposerClient::setActiveConfig(display, 0);
+ };
+ ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
+}
+
+TEST_F(CredentialsTest, SetActiveColorModeTest) {
+ sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+ std::function<status_t()> condition = [=]() {
+ return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
+ };
+ ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
+}
+
+TEST_F(CredentialsTest, CreateSurfaceTest) {
+ sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+ DisplayInfo info;
+ SurfaceComposerClient::getDisplayInfo(display, &info);
+ const ssize_t displayWidth = info.w;
+ const ssize_t displayHeight = info.h;
+
+ std::function<bool()> condition = [=]() {
+ mBGSurfaceControl =
+ mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
+ PIXEL_FORMAT_RGBA_8888, 0);
+ return mBGSurfaceControl != nullptr && mBGSurfaceControl->isValid();
+ };
+ ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
+}
+
+TEST_F(CredentialsTest, CreateDisplayTest) {
+ std::function<bool()> condition = [=]() {
+ sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
+ return testDisplay.get() != nullptr;
+ };
+ ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
+
+ condition = [=]() {
+ sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
+ return testDisplay.get() != nullptr;
+ };
+ ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
+}
+
+TEST_F(CredentialsTest, DISABLED_DestroyDisplayTest) {
+ setupVirtualDisplay();
+
+ DisplayInfo info;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
+ SurfaceComposerClient::destroyDisplay(mVirtualDisplay);
+ // This test currently fails. TODO(b/112002626): Find a way to properly create
+ // a display in the test environment, so that destroy display can remove it.
+ ASSERT_EQ(NAME_NOT_FOUND, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
+}
+
+TEST_F(CredentialsTest, CaptureTest) {
+ sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+ std::function<status_t()> condition = [=]() {
+ sp<GraphicBuffer> outBuffer;
+ return ScreenshotClient::capture(display, Rect(), 0 /*reqWidth*/, 0 /*reqHeight*/,
+ MIN_LAYER_Z, MAX_LAYER_Z, false, ROTATION, &outBuffer);
+ };
+ ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
+}
+
+TEST_F(CredentialsTest, CaptureLayersTest) {
+ setupBackgroundSurface();
+ sp<GraphicBuffer> outBuffer;
+ std::function<status_t()> condition = [=]() {
+ sp<GraphicBuffer> outBuffer;
+ return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(), Rect(), FRAME_SCALE,
+ &outBuffer);
+ };
+ ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
+}
+
+/**
+ * Test for methods accessible directly through SurfaceFlinger:
+ */
+TEST_F(CredentialsTest, AuthenticateSurfaceTextureTest) {
+ setupBackgroundSurface();
+ sp<IGraphicBufferProducer> producer =
+ mBGSurfaceControl->getSurface()->getIGraphicBufferProducer();
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+
+ std::function<bool()> condition = [=]() { return sf->authenticateSurfaceTexture(producer); };
+ ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
+}
+
+TEST_F(CredentialsTest, GetLayerDebugInfo) {
+ setupBackgroundSurface();
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+
+ // Historically, only root and shell can access the getLayerDebugInfo which
+ // is called when we call dumpsys. I don't see a reason why we should change this.
+ std::vector<LayerDebugInfo> outLayers;
+ // Check with root.
+ seteuid(AID_ROOT);
+ ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+
+ // Check as a shell.
+ seteuid(AID_SHELL);
+ ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+
+ // Check as anyone else.
+ seteuid(AID_ROOT);
+ seteuid(AID_BIN);
+ ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
+}
+} // namespace android
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 731e628..1319e12 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
{
"presubmit": {
- "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*:-CropLatchingTest.FinalCropLatchingBufferOldSize"
+ "filter": "CredentialsTest.*:LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*:-CropLatchingTest.FinalCropLatchingBufferOldSize"
}
}
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index bde6614..4ab4fec 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -1422,6 +1422,19 @@
}
}
+TEST_P(LayerTypeTransactionTest, RefreshRateIsInitialized) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+
+ sp<IBinder> handle = layer->getHandle();
+ ASSERT_TRUE(handle != nullptr);
+
+ FrameStats frameStats;
+ mClient->getLayerFrameStats(handle, &frameStats);
+
+ ASSERT_GT(frameStats.refreshPeriodNano, static_cast<nsecs_t>(0));
+}
+
TEST_F(LayerTransactionTest, SetCropBasic_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 508875d..b4aec36 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -657,7 +657,8 @@
using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>;
using HwcVirtualDisplayCase =
Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant,
- NonHwcDisplayHdrSupportVariant, NonHwcPerFrameMetadataSupportVariant>;
+ HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>,
+ NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>;
using WideColorP3ColorimetricDisplayCase =
Case<PrimaryDisplayVariant, WideColorP3ColorimetricSupportedVariant<PrimaryDisplayVariant>,
HdrNotSupportedVariant<PrimaryDisplayVariant>,
diff --git a/services/surfaceflinger/tests/unittests/EventControlThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventControlThreadTest.cpp
index b346454..9dc4193 100644
--- a/services/surfaceflinger/tests/unittests/EventControlThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventControlThreadTest.cpp
@@ -23,7 +23,7 @@
#include <log/log.h>
#include "AsyncCallRecorder.h"
-#include "EventControlThread.h"
+#include "Scheduler/EventControlThread.h"
namespace android {
namespace {
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 19747bd..fb3b7a2 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -25,7 +25,7 @@
#include <utils/Errors.h>
#include "AsyncCallRecorder.h"
-#include "EventThread.h"
+#include "Scheduler/EventThread.h"
using namespace std::chrono_literals;
using namespace std::placeholders;
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
index 4a466ef..06a6b69 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
@@ -19,7 +19,7 @@
#include <gmock/gmock.h>
#include <utils/String8.h>
-#include "DispSync.h"
+#include "Scheduler/DispSync.h"
namespace android {
namespace mock {
@@ -35,6 +35,7 @@
MOCK_METHOD1(addResyncSample, bool(nsecs_t));
MOCK_METHOD0(endResync, void());
MOCK_METHOD1(setPeriod, void(nsecs_t));
+ MOCK_METHOD2(scalePeriod, void(uint32_t, uint32_t));
MOCK_METHOD0(getPeriod, nsecs_t());
MOCK_METHOD1(setRefreshSkipCount, void(int));
MOCK_METHOD3(addEventListener, status_t(const char*, nsecs_t, Callback*));
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventControlThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventControlThread.h
index 8ac09a9..6ef352a 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventControlThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventControlThread.h
@@ -18,7 +18,7 @@
#include <gmock/gmock.h>
-#include "EventControlThread.h"
+#include "Scheduler/EventControlThread.h"
namespace android {
namespace mock {
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index df9bfc6..ad2463d 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -18,7 +18,7 @@
#include <gmock/gmock.h>
-#include "EventThread.h"
+#include "Scheduler/EventThread.h"
namespace android {
namespace mock {
diff --git a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
index cf07cf7..8d503f4 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
@@ -18,7 +18,7 @@
#include <gmock/gmock.h>
-#include "MessageQueue.h"
+#include "Scheduler/MessageQueue.h"
namespace android {
namespace mock {
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
index a98bece..200f214 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
@@ -16,6 +16,8 @@
#include "mock/RenderEngine/MockRenderEngine.h"
+#include <ui/Region.h>
+
namespace android {
namespace RE {
namespace mock {