Merge "Include carrier services in user builds' connectivity bug reports."
diff --git a/cmds/installd/CrateManager.cpp b/cmds/installd/CrateManager.cpp
index 344aefb..6e079eb 100644
--- a/cmds/installd/CrateManager.cpp
+++ b/cmds/installd/CrateManager.cpp
@@ -16,6 +16,8 @@
#include "CrateManager.h"
+#ifdef ENABLE_STORAGE_CRATES
+
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android/log.h>
@@ -127,3 +129,5 @@
} // namespace installd
} // namespace android
+
+#endif // ENABLE_STORAGE_CRATES
\ No newline at end of file
diff --git a/cmds/installd/CrateManager.h b/cmds/installd/CrateManager.h
index 1776622..4332d4c 100644
--- a/cmds/installd/CrateManager.h
+++ b/cmds/installd/CrateManager.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_INSTALLD_CRATE_INFO_MANAGER_H
#define ANDROID_INSTALLD_CRATE_INFO_MANAGER_H
+#ifdef ENABLE_STORAGE_CRATES
+
#include <android/os/storage/CrateMetadata.h>
#include <cutils/multiuser.h>
#include <fts.h>
@@ -79,4 +81,9 @@
} // namespace installd
} // namespace android
+#else // ENABLE_STORAGE_CRATES
+#include <android/os/storage/CrateMetadata.h>
+using android::os::storage::CrateMetadata;
+#endif // ENABLE_STORAGE_CRATES
+
#endif // ANDROID_INSTALLD_CRATE_INFO_MANAGER_H
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 4288735..3713e87 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -2054,6 +2054,7 @@
for (const auto& packageName : packageNames) {
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
}
+#ifdef ENABLE_STORAGE_CRATES
std::lock_guard<std::recursive_mutex> lock(mLock);
auto retVector = std::make_unique<std::vector<std::unique_ptr<CrateMetadata>>>();
@@ -2083,6 +2084,14 @@
#endif
*_aidl_return = std::move(retVector);
+#else // ENABLE_STORAGE_CRATES
+ *_aidl_return = nullptr;
+
+ /* prevent compile warning fail */
+ if (userId < 0) {
+ return error();
+ }
+#endif // ENABLE_STORAGE_CRATES
return ok();
}
@@ -2091,6 +2100,7 @@
std::unique_ptr<std::vector<std::unique_ptr<CrateMetadata>>>* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
+#ifdef ENABLE_STORAGE_CRATES
std::lock_guard<std::recursive_mutex> lock(mLock);
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
@@ -2118,6 +2128,14 @@
#endif
*_aidl_return = std::move(retVector);
+#else // ENABLE_STORAGE_CRATES
+ *_aidl_return = nullptr;
+
+ /* prevent compile warning fail */
+ if (userId < 0) {
+ return error();
+ }
+#endif // ENABLE_STORAGE_CRATES
return ok();
}
diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
index 7331ba2..e6b743b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -86,9 +86,15 @@
return t->template ref<T>();
}
+ static void operator delete(void* p) { std::free(p); }
+
private:
std::once_flag mFlagThis;
std::weak_ptr<SharedRefBase> mThis;
+
+ // Use 'SharedRefBase::make<T>(...)' to make. SharedRefBase has implicit
+ // ownership. Making this operator private to avoid double-ownership.
+ static void* operator new(size_t s) { return std::malloc(s); }
};
/**
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index f18e118..f0ea237 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -242,23 +242,18 @@
}
binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) {
- std::unique_ptr<ParcelFileDescriptor> parcelFd;
-
if (fd < 0) {
if (fd != -1) {
return STATUS_UNKNOWN_ERROR;
}
- // parcelFd = nullptr
- } else { // fd >= 0
- parcelFd = std::make_unique<ParcelFileDescriptor>(unique_fd(fd));
+ return parcel->get()->writeInt32(0); // null
}
- status_t status = parcel->get()->writeNullableParcelable(parcelFd);
+ ParcelFileDescriptor parcelFd = ParcelFileDescriptor(unique_fd(fd));
+ status_t status = parcel->get()->writeParcelable(parcelFd);
// ownership is retained by caller
- if (parcelFd != nullptr) {
- (void)parcelFd->release().release();
- }
+ (void)parcelFd.release().release();
return PruneStatusT(status);
}
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 99d3856..7f57f5d 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -189,6 +189,10 @@
},
},
+ whole_static_libs: [
+ "LibGuiProperties",
+ ],
+
shared_libs: [
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.bufferqueue@2.0",
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index f6493bf..02416e4 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -19,6 +19,8 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <cutils/properties.h>
+
#include <gui/BLASTBufferQueue.h>
#include <gui/BufferItemConsumer.h>
#include <gui/GLConsumer.h>
@@ -99,7 +101,11 @@
mHeight(height),
mNextTransaction(nullptr) {
BufferQueue::createBufferQueue(&mProducer, &mConsumer);
- mConsumer->setMaxAcquiredBufferCount(MAX_ACQUIRED_BUFFERS);
+
+ int8_t disableTripleBuffer = property_get_bool("ro.sf.disable_triple_buffer", 0);
+ if (!disableTripleBuffer) {
+ mProducer->setMaxDequeuedBufferCount(2);
+ }
mBufferItemConsumer =
new BLASTBufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);
static int32_t id = 0;
@@ -183,7 +189,7 @@
void BLASTBufferQueue::processNextBufferLocked() {
ATRACE_CALL();
- if (mNumFrameAvailable == 0 || mNumAcquired == MAX_ACQUIRED_BUFFERS) {
+ if (mNumFrameAvailable == 0 || mNumAcquired == MAX_ACQUIRED_BUFFERS + 1) {
return;
}
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index 6749c3c..e2ea3f9 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "FrameEvents"
+#include <LibGuiProperties.sysprop.h>
#include <android-base/stringprintf.h>
#include <cutils/compiler.h> // For CC_[UN]LIKELY
#include <inttypes.h>
@@ -167,6 +168,11 @@
} // namespace
+const size_t FrameEventHistory::MAX_FRAME_HISTORY =
+ sysprop::LibGuiProperties::frame_event_history_size().value_or(8);
+
+FrameEventHistory::FrameEventHistory() : mFrames(std::vector<FrameEvents>(MAX_FRAME_HISTORY)) {}
+
FrameEventHistory::~FrameEventHistory() = default;
FrameEvents* FrameEventHistory::getFrame(uint64_t frameNumber) {
@@ -348,6 +354,9 @@
// ConsumerFrameEventHistory
// ============================================================================
+ConsumerFrameEventHistory::ConsumerFrameEventHistory()
+ : mFramesDirty(std::vector<FrameEventDirtyFields>(MAX_FRAME_HISTORY)) {}
+
ConsumerFrameEventHistory::~ConsumerFrameEventHistory() = default;
void ConsumerFrameEventHistory::onDisconnect() {
@@ -447,9 +456,8 @@
mFramesDirty[mReleaseOffset].setDirty<FrameEvent::RELEASE>();
}
-void ConsumerFrameEventHistory::getFrameDelta(
- FrameEventHistoryDelta* delta,
- const std::array<FrameEvents, MAX_FRAME_HISTORY>::iterator& frame) {
+void ConsumerFrameEventHistory::getFrameDelta(FrameEventHistoryDelta* delta,
+ const std::vector<FrameEvents>::iterator& frame) {
mProducerWantsEvents = true;
size_t i = static_cast<size_t>(std::distance(mFrames.begin(), frame));
if (mFramesDirty[i].anyDirty()) {
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index d72eb5a..1b22df2 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -98,7 +98,9 @@
std::mutex mMutex;
std::condition_variable mCallbackCV;
- static const int MAX_ACQUIRED_BUFFERS = 2;
+ // BufferQueue internally allows 1 more than
+ // the max to be acquired
+ static const int MAX_ACQUIRED_BUFFERS = 1;
int32_t mNumFrameAvailable GUARDED_BY(mMutex);
int32_t mNumAcquired GUARDED_BY(mMutex);
diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
index 4af8659..0750080 100644
--- a/libs/gui/include/gui/FrameTimestamps.h
+++ b/libs/gui/include/gui/FrameTimestamps.h
@@ -106,6 +106,7 @@
// producer via deltas.
class FrameEventHistory {
public:
+ FrameEventHistory();
virtual ~FrameEventHistory();
FrameEvents* getFrame(uint64_t frameNumber);
@@ -113,10 +114,10 @@
void checkFencesForCompletion();
void dump(std::string& outString) const;
- static constexpr size_t MAX_FRAME_HISTORY = 8;
+ static const size_t MAX_FRAME_HISTORY;
protected:
- std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames;
+ std::vector<FrameEvents> mFrames;
CompositorTiming mCompositorTiming;
};
@@ -203,6 +204,7 @@
// The consumer's interface to FrameEventHistory
class ConsumerFrameEventHistory : public FrameEventHistory {
public:
+ ConsumerFrameEventHistory();
~ConsumerFrameEventHistory() override;
void onDisconnect();
@@ -224,9 +226,9 @@
private:
void getFrameDelta(FrameEventHistoryDelta* delta,
- const std::array<FrameEvents, MAX_FRAME_HISTORY>::iterator& frame);
+ const std::vector<FrameEvents>::iterator& frame);
- std::array<FrameEventDirtyFields, MAX_FRAME_HISTORY> mFramesDirty;
+ std::vector<FrameEventDirtyFields> mFramesDirty;
size_t mQueueOffset{0};
size_t mCompositionOffset{0};
diff --git a/libs/gui/sysprop/Android.bp b/libs/gui/sysprop/Android.bp
new file mode 100644
index 0000000..e7f7c1f
--- /dev/null
+++ b/libs/gui/sysprop/Android.bp
@@ -0,0 +1,7 @@
+sysprop_library {
+ name: "LibGuiProperties",
+ srcs: ["*.sysprop"],
+ api_packages: ["android.sysprop"],
+ property_owner: "Platform",
+ vendor_available: true,
+}
diff --git a/libs/gui/sysprop/LibGuiProperties.sysprop b/libs/gui/sysprop/LibGuiProperties.sysprop
new file mode 100644
index 0000000..0d54711
--- /dev/null
+++ b/libs/gui/sysprop/LibGuiProperties.sysprop
@@ -0,0 +1,25 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the License);
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an AS IS BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module: "android.sysprop.LibGuiProperties"
+owner: Platform
+
+# Indicates how many elements should be present in the frame event histories.
+prop {
+ api_name: "frame_event_history_size"
+ type: Integer
+ scope: Public
+ access: Readonly
+ prop_name: "ro.lib_gui.frame_event_history_size"
+}
diff --git a/libs/gui/sysprop/api/LibGuiProperties-current.txt b/libs/gui/sysprop/api/LibGuiProperties-current.txt
new file mode 100644
index 0000000..5b7f74e
--- /dev/null
+++ b/libs/gui/sysprop/api/LibGuiProperties-current.txt
@@ -0,0 +1,8 @@
+props {
+ module: "android.sysprop.LibGuiProperties"
+ prop {
+ api_name: "frame_event_history_size"
+ type: Integer
+ prop_name: "ro.lib_gui.frame_event_history_size"
+ }
+}
diff --git a/libs/gui/sysprop/api/LibGuiProperties-latest.txt b/libs/gui/sysprop/api/LibGuiProperties-latest.txt
new file mode 100644
index 0000000..5b7f74e
--- /dev/null
+++ b/libs/gui/sysprop/api/LibGuiProperties-latest.txt
@@ -0,0 +1,8 @@
+props {
+ module: "android.sysprop.LibGuiProperties"
+ prop {
+ api_name: "frame_event_history_size"
+ type: Integer
+ prop_name: "ro.lib_gui.frame_event_history_size"
+ }
+}
diff --git a/libs/renderengine/gl/filters/KawaseBlurFilter.cpp b/libs/renderengine/gl/filters/KawaseBlurFilter.cpp
index fc26bcc..7524c6d 100644
--- a/libs/renderengine/gl/filters/KawaseBlurFilter.cpp
+++ b/libs/renderengine/gl/filters/KawaseBlurFilter.cpp
@@ -106,21 +106,19 @@
precision mediump float;
uniform sampler2D uTexture;
- highp uniform vec2 uOffset;
+ uniform vec2 uOffset;
highp in vec2 vUV;
out vec4 fragColor;
- vec4 kawaseBlur() {
- return (texture(uTexture, vec2(-1.0, 1.0) * uOffset + vUV, 0.0)
- + texture(uTexture, uOffset + vUV, 0.0)
- + texture(uTexture, vec2(1.0, -1.0) * uOffset + vUV, 0.0)
- + texture(uTexture, vec2(-1.0) * uOffset + vUV, 0.0))
- * 0.25;
- }
-
void main() {
- fragColor = kawaseBlur();
+ fragColor = texture(uTexture, vUV, 0.0);
+ fragColor += texture(uTexture, vUV + vec2( uOffset.x, uOffset.y), 0.0);
+ fragColor += texture(uTexture, vUV + vec2( uOffset.x, -uOffset.y), 0.0);
+ fragColor += texture(uTexture, vUV + vec2(-uOffset.x, uOffset.y), 0.0);
+ fragColor += texture(uTexture, vUV + vec2(-uOffset.x, -uOffset.y), 0.0);
+
+ fragColor = vec4(fragColor.rgb * 0.2, 1.0);
}
)SHADER";
}
diff --git a/libs/renderengine/gl/filters/KawaseBlurFilter.h b/libs/renderengine/gl/filters/KawaseBlurFilter.h
index ec81f81..20009cf 100644
--- a/libs/renderengine/gl/filters/KawaseBlurFilter.h
+++ b/libs/renderengine/gl/filters/KawaseBlurFilter.h
@@ -30,7 +30,7 @@
class KawaseBlurFilter : public BlurFilter {
public:
- static constexpr uint32_t kMaxPasses = 8;
+ static constexpr uint32_t kMaxPasses = 6;
explicit KawaseBlurFilter(GLESRenderEngine& engine);
status_t prepare() override;
diff --git a/libs/ui/include/ui/DisplayInfo.h b/libs/ui/include/ui/DisplayInfo.h
index 7773319..69f86d3 100644
--- a/libs/ui/include/ui/DisplayInfo.h
+++ b/libs/ui/include/ui/DisplayInfo.h
@@ -20,8 +20,11 @@
namespace android {
+enum class DisplayConnectionType { Internal, External };
+
// Immutable information about physical display.
struct DisplayInfo {
+ DisplayConnectionType connectionType = DisplayConnectionType::Internal;
float density = 0.f;
bool secure = false;
};
diff --git a/services/automotive/display/Android.bp b/services/automotive/display/Android.bp
index d94fb27..8ff0711 100644
--- a/services/automotive/display/Android.bp
+++ b/services/automotive/display/Android.bp
@@ -36,4 +36,8 @@
local_include_dirs: [
"include",
],
+
+ cflags: [
+ "-DLOG_TAG=\"AutomotiveDisplayService\""
+ ],
}
diff --git a/services/automotive/display/AutomotiveDisplayProxyService.cpp b/services/automotive/display/AutomotiveDisplayProxyService.cpp
index 3cd8e39..4767406 100644
--- a/services/automotive/display/AutomotiveDisplayProxyService.cpp
+++ b/services/automotive/display/AutomotiveDisplayProxyService.cpp
@@ -27,97 +27,163 @@
namespace V1_0 {
namespace implementation {
-Return<sp<IGraphicBufferProducer>>
-AutomotiveDisplayProxyService::getIGraphicBufferProducer() {
- if (mSurface == nullptr) {
- status_t err;
- mSurfaceComposerClient = new SurfaceComposerClient();
- err = mSurfaceComposerClient->initCheck();
+Return<sp<IGraphicBufferProducer>>
+AutomotiveDisplayProxyService::getIGraphicBufferProducer(uint64_t id) {
+ auto it = mDisplays.find(id);
+ sp<IBinder> displayToken = nullptr;
+ sp<SurfaceControl> surfaceControl = nullptr;
+ if (it == mDisplays.end()) {
+ displayToken = SurfaceComposerClient::getPhysicalDisplayToken(id);
+ if (displayToken == nullptr) {
+ ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id);
+ return nullptr;
+ }
+
+ // Get the resolution from stored display state.
+ DisplayConfig displayConfig = {};
+ auto err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig);
+ if (err != NO_ERROR) {
+ ALOGE("Failed to get display configuration of %lX. "
+ "This display will be ignored.", (unsigned long)id);
+ return nullptr;
+ }
+
+ ui::DisplayState displayState = {};
+ err = SurfaceComposerClient::getDisplayState(displayToken, &displayState);
+ if (err != NO_ERROR) {
+ ALOGE("Failed to get current display status of %lX. "
+ "This display will be ignored.", (unsigned long)id);
+ return nullptr;
+ }
+
+ auto displayWidth = displayConfig.resolution.getWidth();
+ auto displayHeight = displayConfig.resolution.getHeight();
+ if ((displayState.orientation != ui::ROTATION_0) &&
+ (displayState.orientation != ui::ROTATION_180)) {
+ std::swap(displayWidth, displayHeight);
+ }
+
+ sp<android::SurfaceComposerClient> surfaceClient = new SurfaceComposerClient();
+ err = surfaceClient->initCheck();
if (err != NO_ERROR) {
ALOGE("SurfaceComposerClient::initCheck error: %#x", err);
- mSurfaceComposerClient = nullptr;
return nullptr;
}
- const auto displayToken = SurfaceComposerClient::getInternalDisplayToken();
- if (displayToken == nullptr) {
- ALOGE("Failed to get internal display ");
- return nullptr;
- }
-
- err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &mDpyConfig);
- if (err != NO_ERROR) {
- ALOGE("Failed to get active display config");
- return nullptr;
- }
-
- err = SurfaceComposerClient::getDisplayState(displayToken, &mDpyState);
- if (err != NO_ERROR) {
- ALOGE("Failed to get display state");
- return nullptr;
- }
-
- const ui::Size& resolution = mDpyConfig.resolution;
- auto width = resolution.getWidth();
- auto height = resolution.getHeight();
-
- if (mDpyState.orientation == ui::ROTATION_90 ||
- mDpyState.orientation == ui::ROTATION_270) {
- std::swap(width, height);
- }
-
- mSurfaceControl = mSurfaceComposerClient->createSurface(
- String8("Automotive Display"), width, height,
+ // Create a SurfaceControl instance
+ surfaceControl = surfaceClient->createSurface(
+ String8::format("AutomotiveDisplay::%lX", (unsigned long)id),
+ displayWidth, displayHeight,
PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque);
- if (mSurfaceControl == nullptr || !mSurfaceControl->isValid()) {
- ALOGE("Failed to create SurfaceControl");
- mSurfaceComposerClient = nullptr;
- mSurfaceControl = nullptr;
+ if (surfaceControl == nullptr || !surfaceControl->isValid()) {
+ ALOGE("Failed to create SurfaceControl.");
return nullptr;
}
- // SurfaceControl::getSurface is guaranteed to be not null.
- mSurface = mSurfaceControl->getSurface();
+ // Store
+ DisplayDesc descriptor = {displayToken, surfaceControl};
+ mDisplays.insert_or_assign(id, std::move(descriptor));
+ } else {
+ displayToken = it->second.token;
+ surfaceControl = it->second.surfaceControl;
}
+ // SurfaceControl::getSurface is guaranteed to be not null.
+ auto targetSurface = surfaceControl->getSurface();
return new ::android::hardware::graphics::bufferqueue::V2_0::utils::
- B2HGraphicBufferProducer(
- mSurface->getIGraphicBufferProducer());
+ B2HGraphicBufferProducer(targetSurface->getIGraphicBufferProducer());
}
-Return<bool> AutomotiveDisplayProxyService::showWindow() {
- status_t status = NO_ERROR;
- if (mSurfaceControl != nullptr) {
- status = SurfaceComposerClient::Transaction{}
- .setLayer(
- mSurfaceControl, 0x7FFFFFFF) // always on top
- .show(mSurfaceControl)
- .apply();
- } else {
- ALOGE("showWindow: Failed to get a valid SurfaceControl!");
+Return<bool> AutomotiveDisplayProxyService::showWindow(uint64_t id) {
+ auto it = mDisplays.find(id);
+ if (it == mDisplays.end()) {
+ ALOGE("Given display token is invalid or unknown.");
return false;
}
+ ui::DisplayState displayState;
+ auto err = SurfaceComposerClient::getDisplayState(it->second.token, &displayState);
+ if (err != NO_ERROR) {
+ ALOGE("Failed to get current state of the display 0x%lX", (unsigned long)id);
+ return false;
+ }
+
+ SurfaceComposerClient::Transaction t;
+ t.setDisplayLayerStack(it->second.token, displayState.layerStack);
+ t.setLayerStack(it->second.surfaceControl, displayState.layerStack);
+
+ status_t status = t.setLayer(it->second.surfaceControl, 0x7FFFFFFF)
+ .show(it->second.surfaceControl)
+ .apply();
+
return status == NO_ERROR;
}
-Return<bool> AutomotiveDisplayProxyService::hideWindow() {
- status_t status = NO_ERROR;
- if (mSurfaceControl != nullptr) {
- status = SurfaceComposerClient::Transaction{}
- .hide(mSurfaceControl)
- .apply();
- } else {
- ALOGE("hideWindow: Failed to get a valid SurfaceControl!");
+Return<bool> AutomotiveDisplayProxyService::hideWindow(uint64_t id) {
+ auto it = mDisplays.find(id);
+ if (it == mDisplays.end()) {
+ ALOGE("Given display token is invalid or unknown.");
return false;
}
+ status_t status = SurfaceComposerClient::Transaction{}
+ .hide(it->second.surfaceControl)
+ .apply();
+
return status == NO_ERROR;
}
+
+Return<void> AutomotiveDisplayProxyService::getDisplayIdList(getDisplayIdList_cb _cb) {
+ hardware::hidl_vec<uint64_t> ids;
+
+ // Get stable IDs of all available displays and get their tokens and
+ // descriptors.
+ auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
+ ids.resize(displayIds.size());
+ for (auto i = 0; i < displayIds.size(); ++i) {
+ ids[i] = displayIds[i];
+ }
+
+ _cb(ids);
+ return hardware::Void();
+}
+
+
+Return<void> AutomotiveDisplayProxyService::getDisplayInfo(uint64_t id, getDisplayInfo_cb _cb) {
+ HwDisplayConfig activeConfig;
+ HwDisplayState activeState;
+
+ auto displayToken = SurfaceComposerClient::getPhysicalDisplayToken(id);
+ if (displayToken == nullptr) {
+ ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id);
+ } else {
+ DisplayConfig displayConfig = {};
+ auto err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig);
+ if (err != NO_ERROR) {
+ ALOGW("Failed to get display configuration of %lX. "
+ "This display will be ignored.", (unsigned long)id);
+ }
+
+ ui::DisplayState displayState = {};
+ err = SurfaceComposerClient::getDisplayState(displayToken, &displayState);
+ if (err != NO_ERROR) {
+ ALOGW("Failed to get current display status of %lX. "
+ "This display will be ignored.", (unsigned long)id);
+ }
+
+ activeConfig.setToExternal((uint8_t*)&displayConfig, sizeof(DisplayConfig));
+ activeState.setToExternal((uint8_t*)&displayState, sizeof(DisplayState));
+ }
+
+ _cb(activeConfig, activeState);
+ return hardware::Void();
+}
+
+
} // namespace implementation
} // namespace V1_0
} // namespace display
diff --git a/services/automotive/display/include/AutomotiveDisplayProxyService.h b/services/automotive/display/include/AutomotiveDisplayProxyService.h
index 3956602..e2fc0d2 100644
--- a/services/automotive/display/include/AutomotiveDisplayProxyService.h
+++ b/services/automotive/display/include/AutomotiveDisplayProxyService.h
@@ -16,12 +16,14 @@
#pragma once
#include <android/frameworks/automotive/display/1.0/IAutomotiveDisplayProxyService.h>
-#include <gui/ISurfaceComposer.h>
#include <gui/IGraphicBufferProducer.h>
+#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <ui/DisplayConfig.h>
#include <ui/DisplayState.h>
+#include <tuple>
+#include <vector>
namespace android {
namespace frameworks {
@@ -31,32 +33,30 @@
namespace implementation {
using ::android::hardware::Return;
-using ::android::sp;
using ::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer;
+using ::android::sp;
+
+
+typedef struct DisplayDesc {
+ sp<IBinder> token;
+ sp<SurfaceControl> surfaceControl;
+} DisplayDesc;
+
class AutomotiveDisplayProxyService : public IAutomotiveDisplayProxyService {
public:
- Return<sp<IGraphicBufferProducer>> getIGraphicBufferProducer() override;
- Return<bool> showWindow() override;
- Return<bool> hideWindow() override;
- Return<void> getDisplayInfo(getDisplayInfo_cb _info_cb) override {
- HwDisplayConfig cfg;
- cfg.setToExternal((uint8_t*)&mDpyConfig, sizeof(DisplayConfig));
-
- HwDisplayState state;
- state.setToExternal((uint8_t*)&mDpyState, sizeof(DisplayState));
-
- _info_cb(cfg, state);
- return hardware::Void();
- }
+ Return<sp<IGraphicBufferProducer>> getIGraphicBufferProducer(uint64_t id) override;
+ Return<bool> showWindow(uint64_t id) override;
+ Return<bool> hideWindow(uint64_t id) override;
+ Return<void> getDisplayIdList(getDisplayIdList_cb _cb) override;
+ Return<void> getDisplayInfo(uint64_t, getDisplayInfo_cb _cb) override;
private:
- sp<android::Surface> mSurface;
- sp<android::SurfaceComposerClient> mSurfaceComposerClient;
- sp<android::SurfaceControl> mSurfaceControl;
- DisplayConfig mDpyConfig;
- ui::DisplayState mDpyState;
+ uint8_t getDisplayPort(const uint64_t id) { return (id & 0xF); }
+
+ std::unordered_map<uint64_t, DisplayDesc> mDisplays;
};
+
} // namespace implementation
} // namespace V1_0
} // namespace display
diff --git a/services/automotive/display/main_automotivedisplayproxy.cpp b/services/automotive/display/main_automotivedisplayproxy.cpp
index 626c185..59b584c 100644
--- a/services/automotive/display/main_automotivedisplayproxy.cpp
+++ b/services/automotive/display/main_automotivedisplayproxy.cpp
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#define LOG_TAG "AutomotiveDisplayService"
-
#include <unistd.h>
#include <hidl/HidlTransportSupport.h>
@@ -39,9 +37,10 @@
const static char kServiceName[] = "default";
int main() {
- ALOGI("Car Window Service is starting");
+ ALOGI("Automotive Display Proxy Service is starting");
- android::sp<IAutomotiveDisplayProxyService> service = new AutomotiveDisplayProxyService();
+ android::sp<IAutomotiveDisplayProxyService> service =
+ new AutomotiveDisplayProxyService();
configureRpcThreadpool(1, true /* callerWillJoin */);
@@ -56,7 +55,7 @@
}
// In normal operation, we don't expect the thread pool to exit
- ALOGE("Car Window Service is shutting down");
+ ALOGE("Automotive Window Service is shutting down");
return 1;
}
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 5a955f7..d7ec868 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -325,6 +325,7 @@
Mutex::Autolock lock(mFrameEventHistoryMutex);
mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, presentFence,
compositorTiming);
+ finalizeFrameEventHistory(glDoneFence, compositorTiming);
}
// Update mFrameTracker.
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 0487e38..f678910 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -203,12 +203,12 @@
void updateCloneBufferInfo() override;
uint64_t mPreviousFrameNumber = 0;
+ virtual uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
+
private:
// Returns true if this layer requires filtering
bool needsFiltering(const sp<const DisplayDevice>& displayDevice) const override;
- uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
-
// BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame
// and its parent layer is not bounded
Rect getBufferSize(const State& s) const override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 1188dfe..de5429b 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -468,6 +468,32 @@
return mDrawingState.frameNumber;
}
+/**
+ * This is the frameNumber used for deferred transaction signalling. We need to use this because
+ * of cases where we defer a transaction for a surface to itself. In the BLAST world this
+ * may not make a huge amount of sense (Why not just merge the Buffer transaction with the
+ * deferred transaction?) but this is an important legacy use case, for example moving
+ * a window at the same time it draws makes use of this kind of technique. So anyway
+ * imagine we have something like this:
+ *
+ * Transaction { // containing
+ * Buffer -> frameNumber = 2
+ * DeferTransactionUntil -> frameNumber = 2
+ * Random other stuff
+ * }
+ * Now imagine getHeadFrameNumber returned mDrawingState.mFrameNumber (or mCurrentFrameNumber).
+ * Prior to doTransaction SurfaceFlinger will call notifyAvailableFrames, but because we
+ * haven't swapped mCurrentState to mDrawingState yet we will think the sync point
+ * is not ready. So we will return false from applyPendingState and not swap
+ * current state to drawing state. But because we don't swap current state
+ * to drawing state the number will never update and we will be stuck. This way
+ * we can see we need to return the frame number for the buffer we are about
+ * to apply.
+ */
+uint64_t BufferStateLayer::getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const {
+ return mCurrentState.frameNumber;
+}
+
bool BufferStateLayer::getAutoRefresh() const {
// TODO(marissaw): support shared buffer mode
return false;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 539442a..753a742 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -116,6 +116,7 @@
protected:
void gatherBufferInfo() override;
+ uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
private:
bool updateFrameEventHistory(const sp<Fence>& acquireFence, nsecs_t postedTime,
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 9995ce1..02226ab 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -88,6 +88,7 @@
MOCK_CONST_METHOD1(getColorModes, std::vector<ui::ColorMode>(DisplayId));
MOCK_METHOD3(setActiveColorMode, status_t(DisplayId, ui::ColorMode, ui::RenderIntent));
MOCK_CONST_METHOD0(isUsingVrComposer, bool());
+ MOCK_CONST_METHOD1(getDisplayConnectionType, DisplayConnectionType(DisplayId));
MOCK_CONST_METHOD1(isVsyncPeriodSwitchSupported, bool(DisplayId));
MOCK_CONST_METHOD1(getDisplayVsyncPeriod, nsecs_t(DisplayId));
MOCK_METHOD4(setActiveConfigWithConstraints,
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 6ff39b4..cd6bbd1 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -49,16 +49,16 @@
DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(const sp<SurfaceFlinger>& flinger,
const wp<IBinder>& displayToken,
- const std::optional<DisplayId>& displayId)
+ std::optional<DisplayId> displayId)
: flinger(flinger), displayToken(displayToken), displayId(displayId) {}
DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args)
: mFlinger(args.flinger),
mDisplayToken(args.displayToken),
mSequenceId(args.sequenceId),
- mIsVirtual(args.isVirtual),
+ mConnectionType(args.connectionType),
mCompositionDisplay{mFlinger->getCompositionEngine().createDisplay(
- compositionengine::DisplayCreationArgs{args.isVirtual, args.displayId,
+ compositionengine::DisplayCreationArgs{args.isVirtual(), args.displayId,
args.powerAdvisor})},
mPhysicalOrientation(args.physicalOrientation),
mIsPrimary(args.isPrimary) {
@@ -248,10 +248,18 @@
}
std::string DisplayDevice::getDebugName() const {
- const auto id = getId() ? to_string(*getId()) + ", " : std::string();
- return base::StringPrintf("DisplayDevice{%s%s%s\"%s\"}", id.c_str(),
- isPrimary() ? "primary, " : "", isVirtual() ? "virtual, " : "",
- mDisplayName.c_str());
+ std::string displayId;
+ if (const auto id = getId()) {
+ displayId = to_string(*id) + ", ";
+ }
+
+ const char* type = "virtual";
+ if (mConnectionType) {
+ type = *mConnectionType == DisplayConnectionType::Internal ? "internal" : "external";
+ }
+
+ return base::StringPrintf("DisplayDevice{%s%s%s, \"%s\"}", displayId.c_str(), type,
+ isPrimary() ? ", primary" : "", mDisplayName.c_str());
}
void DisplayDevice::dump(std::string& result) const {
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index f45feae..d970b82 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -28,6 +28,7 @@
#include <math/mat4.h>
#include <renderengine/RenderEngine.h>
#include <system/window.h>
+#include <ui/DisplayInfo.h>
#include <ui/DisplayState.h>
#include <ui/GraphicTypes.h>
#include <ui/HdrCapabilities.h>
@@ -52,7 +53,6 @@
struct CompositionInfo;
struct DisplayDeviceCreationArgs;
-struct DisplayInfo;
namespace compositionengine {
class Display;
@@ -71,7 +71,9 @@
return mCompositionDisplay;
}
- bool isVirtual() const { return mIsVirtual; }
+ std::optional<DisplayConnectionType> getConnectionType() const { return mConnectionType; }
+
+ bool isVirtual() const { return !mConnectionType; }
bool isPrimary() const { return mIsPrimary; }
// isSecure indicates whether this display can be trusted to display
@@ -159,7 +161,7 @@
const sp<SurfaceFlinger> mFlinger;
const wp<IBinder> mDisplayToken;
const int32_t mSequenceId;
- const bool mIsVirtual;
+ const std::optional<DisplayConnectionType> mConnectionType;
const std::shared_ptr<compositionengine::Display> mCompositionDisplay;
@@ -178,10 +180,19 @@
};
struct DisplayDeviceState {
- bool isVirtual() const { return !displayId.has_value(); }
+ struct Physical {
+ DisplayId id;
+ DisplayConnectionType type;
+
+ bool operator==(const Physical& other) const {
+ return id == other.id && type == other.type;
+ }
+ };
+
+ bool isVirtual() const { return !physical; }
int32_t sequenceId = sNextSequenceId++;
- std::optional<DisplayId> displayId;
+ std::optional<Physical> physical;
sp<IGraphicBufferProducer> surface;
ui::LayerStack layerStack = ui::NO_LAYER_STACK;
Rect viewport;
@@ -199,15 +210,17 @@
struct DisplayDeviceCreationArgs {
// We use a constructor to ensure some of the values are set, without
// assuming a default value.
- DisplayDeviceCreationArgs(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& displayToken,
- const std::optional<DisplayId>& displayId);
+ DisplayDeviceCreationArgs(const sp<SurfaceFlinger>&, const wp<IBinder>& displayToken,
+ std::optional<DisplayId>);
+
+ bool isVirtual() const { return !connectionType; }
const sp<SurfaceFlinger> flinger;
const wp<IBinder> displayToken;
const std::optional<DisplayId> displayId;
int32_t sequenceId{0};
- bool isVirtual{false};
+ std::optional<DisplayConnectionType> connectionType;
bool isSecure{false};
sp<ANativeWindow> nativeWindow;
sp<compositionengine::DisplaySurface> displaySurface;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index e8bf2d8..fc5d441 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -95,13 +95,13 @@
}
namespace impl {
+
Display::Display(android::Hwc2::Composer& composer,
const std::unordered_set<Capability>& capabilities, hwc2_display_t id,
DisplayType type)
: mComposer(composer),
mCapabilities(capabilities),
mId(id),
- mIsConnected(false),
mType(type) {
ALOGV("Created display %" PRIu64, id);
}
@@ -109,20 +109,27 @@
Display::~Display() {
mLayers.clear();
- if (mType == DisplayType::Virtual) {
- ALOGV("Destroying virtual display");
- auto intError = mComposer.destroyVirtualDisplay(mId);
- auto error = static_cast<Error>(intError);
- ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64
- ") failed: %s (%d)", mId, to_string(error).c_str(), intError);
- } else if (mType == DisplayType::Physical) {
- auto error = setVsyncEnabled(HWC2::Vsync::Disable);
- if (error != Error::None) {
- ALOGE("~Display: Failed to disable vsync for display %" PRIu64
- ": %s (%d)", mId, to_string(error).c_str(),
- static_cast<int32_t>(error));
- }
+ Error error = Error::None;
+ const char* msg;
+ switch (mType) {
+ case DisplayType::Physical:
+ error = setVsyncEnabled(HWC2::Vsync::Disable);
+ msg = "disable VSYNC for";
+ break;
+
+ case DisplayType::Virtual:
+ error = static_cast<Error>(mComposer.destroyVirtualDisplay(mId));
+ msg = "destroy virtual";
+ break;
+
+ case DisplayType::Invalid: // Used in unit tests.
+ break;
}
+
+ ALOGE_IF(error != Error::None, "%s: Failed to %s display %" PRIu64 ": %s (%d)", __FUNCTION__,
+ msg, mId, to_string(error).c_str(), static_cast<int32_t>(error));
+
+ ALOGV("Destroyed display %" PRIu64, mId);
}
// Required by HWC2 display
@@ -372,9 +379,19 @@
return Error::None;
}
-Error Display::getType(DisplayType* outType) const
-{
- *outType = mType;
+Error Display::getConnectionType(android::DisplayConnectionType* outType) const {
+ if (mType != DisplayType::Physical) return Error::BadDisplay;
+
+ using ConnectionType = Hwc2::IComposerClient::DisplayConnectionType;
+ ConnectionType connectionType;
+ const auto error = static_cast<Error>(mComposer.getDisplayConnectionType(mId, &connectionType));
+ if (error != Error::None) {
+ return error;
+ }
+
+ *outType = connectionType == ConnectionType::INTERNAL
+ ? android::DisplayConnectionType::Internal
+ : android::DisplayConnectionType::External;
return Error::None;
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 5804903..6549525 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -25,6 +25,7 @@
#include <gui/HdrMetadata.h>
#include <math/mat4.h>
+#include <ui/DisplayInfo.h>
#include <ui/GraphicTypes.h>
#include <ui/HdrCapabilities.h>
#include <ui/Region.h>
@@ -191,7 +192,8 @@
[[clang::warn_unused_result]] virtual Error getRequests(
DisplayRequest* outDisplayRequests,
std::unordered_map<Layer*, LayerRequest>* outLayerRequests) = 0;
- [[clang::warn_unused_result]] virtual Error getType(DisplayType* outType) const = 0;
+ [[clang::warn_unused_result]] virtual Error getConnectionType(
+ android::DisplayConnectionType*) const = 0;
[[clang::warn_unused_result]] virtual Error supportsDoze(bool* outSupport) const = 0;
[[clang::warn_unused_result]] virtual Error getHdrCapabilities(
android::HdrCapabilities* outCapabilities) const = 0;
@@ -268,7 +270,7 @@
Error getName(std::string* outName) const override;
Error getRequests(DisplayRequest* outDisplayRequests,
std::unordered_map<Layer*, LayerRequest>* outLayerRequests) override;
- Error getType(DisplayType* outType) const override;
+ Error getConnectionType(android::DisplayConnectionType*) const override;
Error supportsDoze(bool* outSupport) const override;
Error getHdrCapabilities(android::HdrCapabilities* outCapabilities) const override;
Error getDisplayedContentSamplingAttributes(android::ui::PixelFormat* outFormat,
@@ -332,16 +334,17 @@
android::Hwc2::Composer& mComposer;
const std::unordered_set<Capability>& mCapabilities;
- hwc2_display_t mId;
- bool mIsConnected;
+ const hwc2_display_t mId;
DisplayType mType;
- std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
+ bool mIsConnected = false;
+ std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
std::once_flag mDisplayCapabilityQueryFlag;
std::unordered_set<DisplayCapability> mDisplayCapabilities;
};
+
} // namespace impl
class Layer {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index bb6f696..784fa74 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -405,18 +405,32 @@
// Composer 2.4
+DisplayConnectionType HWComposer::getDisplayConnectionType(DisplayId displayId) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, DisplayConnectionType::Internal);
+ const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
+
+ DisplayConnectionType type;
+ const auto error = hwcDisplay->getConnectionType(&type);
+
+ const auto FALLBACK_TYPE = hwcDisplay->getId() == mInternalHwcDisplayId
+ ? DisplayConnectionType::Internal
+ : DisplayConnectionType::External;
+
+ RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE);
+ return type;
+}
+
bool HWComposer::isVsyncPeriodSwitchSupported(DisplayId displayId) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, false);
return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
}
nsecs_t HWComposer::getDisplayVsyncPeriod(DisplayId displayId) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, 0);
+
nsecs_t vsyncPeriodNanos;
auto error = mDisplayData.at(displayId).hwcDisplay->getDisplayVsyncPeriod(&vsyncPeriodNanos);
- if (error != HWC2::Error::None) {
- LOG_DISPLAY_ERROR(displayId, "Failed to get Vsync Period");
- return 0;
- }
-
+ RETURN_IF_HWC_ERROR(error, displayId, 0);
return vsyncPeriodNanos;
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 76e831b..41db501 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -189,6 +189,7 @@
virtual bool isUsingVrComposer() const = 0;
// Composer 2.4
+ virtual DisplayConnectionType getDisplayConnectionType(DisplayId) const = 0;
virtual bool isVsyncPeriodSwitchSupported(DisplayId displayId) const = 0;
virtual nsecs_t getDisplayVsyncPeriod(DisplayId displayId) const = 0;
virtual status_t setActiveConfigWithConstraints(
@@ -326,6 +327,7 @@
bool isUsingVrComposer() const override;
// Composer 2.4
+ DisplayConnectionType getDisplayConnectionType(DisplayId) const override;
bool isVsyncPeriodSwitchSupported(DisplayId displayId) const override;
nsecs_t getDisplayVsyncPeriod(DisplayId displayId) const override;
status_t setActiveConfigWithConstraints(DisplayId displayId, size_t configId,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 745736f..a98ff4f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -783,14 +783,18 @@
return NAME_NOT_FOUND;
}
- if (display->isVirtual()) {
+ if (const auto connectionType = display->getConnectionType())
+ info->connectionType = *connectionType;
+ else {
return INVALID_OPERATION;
}
if (mEmulatedDisplayDensity) {
info->density = mEmulatedDisplayDensity;
} else {
- info->density = display->isPrimary() ? mInternalDisplayDensity : FALLBACK_DENSITY;
+ info->density = info->connectionType == DisplayConnectionType::Internal
+ ? mInternalDisplayDensity
+ : FALLBACK_DENSITY;
}
info->secure = display->isSecure();
@@ -2242,30 +2246,38 @@
continue;
}
+ const DisplayId displayId = info->id;
+ const auto it = mPhysicalDisplayTokens.find(displayId);
+
if (event.connection == HWC2::Connection::Connected) {
- if (!mPhysicalDisplayTokens.count(info->id)) {
- ALOGV("Creating display %s", to_string(info->id).c_str());
+ if (it == mPhysicalDisplayTokens.end()) {
+ ALOGV("Creating display %s", to_string(displayId).c_str());
+
if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
- initScheduler(info->id);
+ initScheduler(displayId);
}
- mPhysicalDisplayTokens[info->id] = new BBinder();
+
DisplayDeviceState state;
- state.displayId = info->id;
+ state.physical = {displayId, getHwComposer().getDisplayConnectionType(displayId)};
state.isSecure = true; // All physical displays are currently considered secure.
state.displayName = info->name;
- mCurrentState.displays.add(mPhysicalDisplayTokens[info->id], state);
+
+ sp<IBinder> token = new BBinder();
+ mCurrentState.displays.add(token, state);
+ mPhysicalDisplayTokens.emplace(displayId, std::move(token));
+
mInterceptor->saveDisplayCreation(state);
}
} else {
- ALOGV("Removing display %s", to_string(info->id).c_str());
+ ALOGV("Removing display %s", to_string(displayId).c_str());
- ssize_t index = mCurrentState.displays.indexOfKey(mPhysicalDisplayTokens[info->id]);
+ const ssize_t index = mCurrentState.displays.indexOfKey(it->second);
if (index >= 0) {
const DisplayDeviceState& state = mCurrentState.displays.valueAt(index);
mInterceptor->saveDisplayDeletion(state.sequenceId);
mCurrentState.displays.removeItemsAt(index);
}
- mPhysicalDisplayTokens.erase(info->id);
+ mPhysicalDisplayTokens.erase(it);
}
processDisplayChangesLocked();
@@ -2285,13 +2297,16 @@
const sp<IGraphicBufferProducer>& producer) {
DisplayDeviceCreationArgs creationArgs(this, displayToken, displayId);
creationArgs.sequenceId = state.sequenceId;
- creationArgs.isVirtual = state.isVirtual();
creationArgs.isSecure = state.isSecure;
creationArgs.displaySurface = dispSurface;
creationArgs.hasWideColorGamut = false;
creationArgs.supportedPerFrameMetadata = 0;
creationArgs.powerAdvisor = displayId ? &mPowerAdvisor : nullptr;
+ if (const auto& physical = state.physical) {
+ creationArgs.connectionType = physical->type;
+ }
+
const bool isInternalDisplay = displayId && displayId == getInternalDisplayIdLocked();
creationArgs.isPrimary = isInternalDisplay;
@@ -2482,8 +2497,8 @@
"surface is provided (%p), ignoring it",
state.surface.get());
- displayId = state.displayId;
- LOG_ALWAYS_FATAL_IF(!displayId);
+ LOG_FATAL_IF(!state.physical);
+ displayId = state.physical->id;
dispSurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer);
producer = bqProducer;
}
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 6884b4c..1f9d46c 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -595,8 +595,8 @@
creation->set_id(info.sequenceId);
creation->set_name(info.displayName);
creation->set_is_secure(info.isSecure);
- if (info.displayId) {
- creation->set_display_id(info.displayId->value);
+ if (info.physical) {
+ creation->set_display_id(info.physical->id.value);
}
}
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 0e7eba8..8d97f27 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -145,6 +145,7 @@
mBGSurfaceControl.clear();
mFGSurfaceControl.clear();
mComposerClient.clear();
+ system("setenforce 1");
}
sp<SurfaceComposerClient> mComposerClient;
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp
index 2f89696..96a7541 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp
@@ -183,6 +183,7 @@
// Wait for mock call signaling teardown?
property_set("debug.sf.nobootanimation", "0");
property_set("debug.sf.hwc_service_name", "default");
+ system("setenforce 1");
ALOGI("Test env tear down - done");
}
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 1dfb6ba..06ef8e7 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -284,13 +284,14 @@
EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
- test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, DEFAULT_DISPLAY_ID,
- false /* isVirtual */, true /* isPrimary */)
- .setDisplaySurface(test->mDisplaySurface)
- .setNativeWindow(test->mNativeWindow)
- .setSecure(Derived::IS_SECURE)
- .setPowerMode(Derived::INIT_POWER_MODE)
- .inject();
+ test->mDisplay =
+ FakeDisplayDeviceInjector(test->mFlinger, DEFAULT_DISPLAY_ID,
+ DisplayConnectionType::Internal, true /* isPrimary */)
+ .setDisplaySurface(test->mDisplaySurface)
+ .setNativeWindow(test->mNativeWindow)
+ .setSecure(Derived::IS_SECURE)
+ .setPowerMode(Derived::INIT_POWER_MODE)
+ .inject();
Mock::VerifyAndClear(test->mNativeWindow);
test->mDisplay->setLayerStack(DEFAULT_LAYER_STACK);
}
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 232255f..4da0647 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -310,6 +310,16 @@
static std::optional<DisplayId> get() { return {}; }
};
+template <typename>
+struct DisplayConnectionTypeGetter {
+ static constexpr std::optional<DisplayConnectionType> value;
+};
+
+template <typename PhysicalDisplay>
+struct DisplayConnectionTypeGetter<PhysicalDisplayId<PhysicalDisplay>> {
+ static constexpr std::optional<DisplayConnectionType> value = PhysicalDisplay::CONNECTION_TYPE;
+};
+
// DisplayIdType can be:
// 1) PhysicalDisplayId<...> for generated ID of physical display backed by HWC.
// 2) VirtualDisplayId<...> for hard-coded ID of virtual display backed by HWC.
@@ -318,6 +328,7 @@
Secure secure, Primary primary, int grallocUsage>
struct DisplayVariant {
using DISPLAY_ID = DisplayIdGetter<DisplayIdType>;
+ using CONNECTION_TYPE = DisplayConnectionTypeGetter<DisplayIdType>;
// The display width and height
static constexpr int WIDTH = width;
@@ -343,8 +354,8 @@
static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) {
auto injector =
- FakeDisplayDeviceInjector(test->mFlinger, DISPLAY_ID::get(),
- static_cast<bool>(VIRTUAL), static_cast<bool>(PRIMARY));
+ FakeDisplayDeviceInjector(test->mFlinger, DISPLAY_ID::get(), CONNECTION_TYPE::value,
+ static_cast<bool>(PRIMARY));
injector.setSecure(static_cast<bool>(SECURE));
injector.setNativeWindow(test->mNativeWindow);
@@ -448,6 +459,15 @@
}
static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) {
+ constexpr auto CONNECTION_TYPE =
+ PhysicalDisplay::CONNECTION_TYPE == DisplayConnectionType::Internal
+ ? IComposerClient::DisplayConnectionType::INTERNAL
+ : IComposerClient::DisplayConnectionType::EXTERNAL;
+
+ EXPECT_CALL(*test->mComposer, getDisplayConnectionType(HWC_DISPLAY_ID, _))
+ .WillOnce(
+ DoAll(SetArgPointee<1>(CONNECTION_TYPE), Return(Hwc2::V2_4::Error::NONE)));
+
EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
EXPECT_CALL(*test->mComposer, getDisplayConfigs(HWC_DISPLAY_ID, _))
.WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{HWC_ACTIVE_CONFIG_ID}),
@@ -512,6 +532,7 @@
template <bool hasIdentificationData>
struct PrimaryDisplay {
+ static constexpr auto CONNECTION_TYPE = DisplayConnectionType::Internal;
static constexpr Primary PRIMARY = Primary::TRUE;
static constexpr uint8_t PORT = 255;
static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
@@ -520,6 +541,7 @@
template <bool hasIdentificationData>
struct ExternalDisplay {
+ static constexpr auto CONNECTION_TYPE = DisplayConnectionType::External;
static constexpr Primary PRIMARY = Primary::FALSE;
static constexpr uint8_t PORT = 254;
static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
@@ -1181,7 +1203,8 @@
GetBestColorModeTest()
: DisplayTransactionTest(),
- mInjector(FakeDisplayDeviceInjector(mFlinger, DEFAULT_DISPLAY_ID, false /* isVirtual */,
+ mInjector(FakeDisplayDeviceInjector(mFlinger, DEFAULT_DISPLAY_ID,
+ DisplayConnectionType::Internal,
true /* isPrimary */)) {}
void setHasWideColorGamut(bool hasWideColorGamut) { mHasWideColorGamut = hasWideColorGamut; }
@@ -1283,8 +1306,6 @@
class DisplayDeviceSetProjectionTest : public DisplayTransactionTest {
public:
static constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{777};
- static constexpr bool DEFAULT_DISPLAY_IS_VIRTUAL = false;
- static constexpr bool DEFAULT_DISPLAY_IS_PRIMARY = true;
static constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1080; // arbitrary
static constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1920; // arbitrary
@@ -1314,8 +1335,8 @@
EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64));
EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT));
- return FakeDisplayDeviceInjector(mFlinger, DEFAULT_DISPLAY_ID, DEFAULT_DISPLAY_IS_VIRTUAL,
- DEFAULT_DISPLAY_IS_PRIMARY)
+ return FakeDisplayDeviceInjector(mFlinger, DEFAULT_DISPLAY_ID,
+ DisplayConnectionType::Internal, true /* isPrimary */)
.setNativeWindow(mNativeWindow)
.setPhysicalOrientation(mPhysicalOrientation)
.inject();
@@ -1645,8 +1666,12 @@
// Invocation
DisplayDeviceState state;
- state.displayId = static_cast<bool>(Case::Display::VIRTUAL) ? std::nullopt
- : Case::Display::DISPLAY_ID::get();
+ if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) {
+ const auto displayId = Case::Display::DISPLAY_ID::get();
+ ASSERT_TRUE(displayId);
+ state.physical = {*displayId, *connectionType};
+ }
+
state.isSecure = static_cast<bool>(Case::Display::SECURE);
auto device =
@@ -1658,6 +1683,7 @@
ASSERT_TRUE(device != nullptr);
EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getId());
+ EXPECT_EQ(Case::Display::CONNECTION_TYPE::value, device->getConnectionType());
EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), device->isVirtual());
EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure());
EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary());
@@ -1821,21 +1847,24 @@
EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure());
EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary());
+ std::optional<DisplayDeviceState::Physical> expectedPhysical;
+ if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) {
+ const auto displayId = Case::Display::DISPLAY_ID::get();
+ ASSERT_TRUE(displayId);
+ expectedPhysical = {*displayId, *connectionType};
+ }
+
// The display should have been set up in the current display state
ASSERT_TRUE(hasCurrentDisplayState(displayToken));
const auto& current = getCurrentDisplayState(displayToken);
EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), current.isVirtual());
- EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL) ? std::nullopt
- : Case::Display::DISPLAY_ID::get(),
- current.displayId);
+ EXPECT_EQ(expectedPhysical, current.physical);
// The display should have been set up in the drawing display state
ASSERT_TRUE(hasDrawingDisplayState(displayToken));
const auto& draw = getDrawingDisplayState(displayToken);
EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), draw.isVirtual());
- EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL) ? std::nullopt
- : Case::Display::DISPLAY_ID::get(),
- draw.displayId);
+ EXPECT_EQ(expectedPhysical, draw.physical);
}
template <typename Case>
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 685cfaf..3a4f349 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -543,10 +543,11 @@
class FakeDisplayDeviceInjector {
public:
FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger,
- const std::optional<DisplayId>& displayId, bool isVirtual,
+ std::optional<DisplayId> displayId,
+ std::optional<DisplayConnectionType> connectionType,
bool isPrimary)
: mFlinger(flinger), mCreationArgs(flinger.mFlinger.get(), mDisplayToken, displayId) {
- mCreationArgs.isVirtual = isVirtual;
+ mCreationArgs.connectionType = connectionType;
mCreationArgs.isPrimary = isPrimary;
}
@@ -609,7 +610,12 @@
sp<DisplayDevice> inject() {
DisplayDeviceState state;
- state.displayId = mCreationArgs.isVirtual ? std::nullopt : mCreationArgs.displayId;
+ if (const auto type = mCreationArgs.connectionType) {
+ const auto id = mCreationArgs.displayId;
+ LOG_ALWAYS_FATAL_IF(!id);
+ state.physical = {*id, *type};
+ }
+
state.isSecure = mCreationArgs.isSecure;
sp<DisplayDevice> device = new DisplayDevice(std::move(mCreationArgs));
@@ -617,9 +623,8 @@
mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);
- if (!mCreationArgs.isVirtual) {
- LOG_ALWAYS_FATAL_IF(!state.displayId);
- mFlinger.mutablePhysicalDisplayTokens()[*state.displayId] = mDisplayToken;
+ if (const auto& physical = state.physical) {
+ mFlinger.mutablePhysicalDisplayTokens()[physical->id] = mDisplayToken;
}
return device;