Merge "Create EGLImages during buffer allocation"
diff --git a/data/etc/android.hardware.nfc.ese.xml b/data/etc/android.hardware.nfc.ese.xml
new file mode 100644
index 0000000..6642bb2
--- /dev/null
+++ b/data/etc/android.hardware.nfc.ese.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+
+<!-- This feature indicates that the device supports eSE-based NFC card
+ emulation -->
+<permissions>
+ <feature name="android.hardware.nfc.ese" />
+</permissions>
diff --git a/data/etc/android.hardware.nfc.uicc.xml b/data/etc/android.hardware.nfc.uicc.xml
new file mode 100644
index 0000000..4f12de4
--- /dev/null
+++ b/data/etc/android.hardware.nfc.uicc.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+
+<!-- This feature indicates that the device supports uicc-based NFC card
+ emulation -->
+<permissions>
+ <feature name="android.hardware.nfc.uicc" />
+</permissions>
diff --git a/libs/android_runtime_lazy/Android.bp b/libs/android_runtime_lazy/Android.bp
index b200314..9284acb 100644
--- a/libs/android_runtime_lazy/Android.bp
+++ b/libs/android_runtime_lazy/Android.bp
@@ -33,6 +33,7 @@
cc_library {
name: "libandroid_runtime_lazy",
vendor_available: true,
+ double_loadable: true,
cflags: [
"-Wall",
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index ccde12a..b1c577e 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -59,4 +59,22 @@
* Unknown packages are mapped to false.
*/
boolean[] isAudioPlaybackCaptureAllowed(in @utf8InCpp String[] packageNames);
+
+ /* ApplicationInfo.isSystemApp() == true */
+ const int LOCATION_SYSTEM = 0x1;
+ /* ApplicationInfo.isVendor() == true */
+ const int LOCATION_VENDOR = 0x2;
+ /* ApplicationInfo.isProduct() == true */
+ const int LOCATION_PRODUCT = 0x4;
+ /* ApplicationInfo.isProductServices() == true */
+ const int LOCATION_PRODUCT_SERVICES = 0x8;
+
+ /**
+ * Returns a set of bitflags about package location.
+ * LOCATION_SYSTEM: getApplicationInfo(packageName).isSystemApp()
+ * LOCATION_VENDOR: getApplicationInfo(packageName).isVendor()
+ * LOCATION_PRODUCT: getApplicationInfo(packageName).isProduct()
+ * LOCATION_PRODUCT_SERVICES: getApplicationInfo(packageName).isProductService()
+ */
+ int getLocationFlags(in @utf8InCpp String packageName);
}
diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp
index 0571dcc..56521bf 100644
--- a/libs/graphicsenv/Android.bp
+++ b/libs/graphicsenv/Android.bp
@@ -27,6 +27,7 @@
"libbase",
"libbinder",
"libcutils",
+ "libdl_android",
"liblog",
"libutils",
],
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index bc63d31..b74d675 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -69,7 +69,8 @@
const sp<IBinder>& applyToken,
const InputWindowCommands& commands,
int64_t desiredPresentTime,
- const cached_buffer_t& uncacheBuffer) {
+ const cached_buffer_t& uncacheBuffer,
+ const std::vector<ListenerCallbacks>& listenerCallbacks) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -89,6 +90,14 @@
data.writeInt64(desiredPresentTime);
data.writeStrongBinder(uncacheBuffer.token);
data.writeUint64(uncacheBuffer.cacheId);
+
+ if (data.writeVectorSize(listenerCallbacks) == NO_ERROR) {
+ for (const auto& [listener, callbackIds] : listenerCallbacks) {
+ data.writeStrongBinder(IInterface::asBinder(listener));
+ data.writeInt64Vector(callbackIds);
+ }
+ }
+
remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
}
@@ -978,8 +987,18 @@
uncachedBuffer.token = data.readStrongBinder();
uncachedBuffer.cacheId = data.readUint64();
+ std::vector<ListenerCallbacks> listenerCallbacks;
+ int32_t listenersSize = data.readInt32();
+ for (int32_t i = 0; i < listenersSize; i++) {
+ auto listener =
+ interface_cast<ITransactionCompletedListener>(data.readStrongBinder());
+ std::vector<CallbackId> callbackIds;
+ data.readInt64Vector(&callbackIds);
+ listenerCallbacks.emplace_back(listener, callbackIds);
+ }
+
setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands,
- desiredPresentTime, uncachedBuffer);
+ desiredPresentTime, uncachedBuffer, listenerCallbacks);
return NO_ERROR;
}
case BOOT_FINISHED: {
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index ce88d7b..74cd4f1 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -76,7 +76,11 @@
}
status_t TransactionStats::writeToParcel(Parcel* output) const {
- status_t err = output->writeInt64(latchTime);
+ status_t err = output->writeInt64Vector(callbackIds);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ err = output->writeInt64(latchTime);
if (err != NO_ERROR) {
return err;
}
@@ -96,7 +100,11 @@
}
status_t TransactionStats::readFromParcel(const Parcel* input) {
- status_t err = input->readInt64(&latchTime);
+ status_t err = input->readInt64Vector(&callbackIds);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ err = input->readInt64(&latchTime);
if (err != NO_ERROR) {
return err;
}
@@ -120,16 +128,11 @@
if (err != NO_ERROR) {
return err;
}
-
- for (const auto& [callbackIds, stats] : transactionStats) {
+ for (const auto& stats : transactionStats) {
err = output->writeParcelable(stats);
if (err != NO_ERROR) {
return err;
}
- err = output->writeInt64Vector(callbackIds);
- if (err != NO_ERROR) {
- return err;
- }
}
return NO_ERROR;
}
@@ -139,18 +142,11 @@
for (int i = 0; i < transactionStats_size; i++) {
TransactionStats stats;
- std::vector<CallbackId> callbackIds;
-
status_t err = input->readParcelable(&stats);
if (err != NO_ERROR) {
return err;
}
- err = input->readInt64Vector(&callbackIds);
- if (err != NO_ERROR) {
- return err;
- }
-
- transactionStats.emplace(callbackIds, stats);
+ transactionStats.push_back(stats);
}
return NO_ERROR;
}
@@ -159,11 +155,8 @@
const std::unordered_set<CallbackId>& callbackIds) {
ListenerStats listenerStats;
listenerStats.listener = listener;
- TransactionStats transactionStats;
- listenerStats.transactionStats.emplace(std::piecewise_construct,
- std::forward_as_tuple(callbackIds.begin(),
- callbackIds.end()),
- std::forward_as_tuple(transactionStats));
+ listenerStats.transactionStats.emplace_back(callbackIds);
+
return listenerStats;
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index f6ca9e8..3077b21 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -86,14 +86,7 @@
memcpy(output.writeInplace(16 * sizeof(float)),
colorTransform.asArray(), 16 * sizeof(float));
output.writeFloat(cornerRadius);
-
- if (output.writeVectorSize(listenerCallbacks) == NO_ERROR) {
- for (const auto& [listener, callbackIds] : listenerCallbacks) {
- output.writeStrongBinder(IInterface::asBinder(listener));
- output.writeInt64Vector(callbackIds);
- }
- }
-
+ output.writeBool(hasListenerCallbacks);
output.writeStrongBinder(cachedBuffer.token);
output.writeUint64(cachedBuffer.cacheId);
output.writeParcelable(metadata);
@@ -163,15 +156,7 @@
colorTransform = mat4(static_cast<const float*>(input.readInplace(16 * sizeof(float))));
cornerRadius = input.readFloat();
-
- int32_t listenersSize = input.readInt32();
- for (int32_t i = 0; i < listenersSize; i++) {
- auto listener = interface_cast<ITransactionCompletedListener>(input.readStrongBinder());
- std::vector<CallbackId> callbackIds;
- input.readInt64Vector(&callbackIds);
- listenerCallbacks.emplace_back(listener, callbackIds);
- }
-
+ hasListenerCallbacks = input.readBool();
cachedBuffer.token = input.readStrongBinder();
cachedBuffer.cacheId = input.readUint64();
input.readParcelable(&metadata);
@@ -376,9 +361,9 @@
what |= eColorTransformChanged;
colorTransform = other.colorTransform;
}
- if (other.what & eListenerCallbacksChanged) {
- what |= eListenerCallbacksChanged;
- listenerCallbacks = other.listenerCallbacks;
+ if (other.what & eHasListenerCallbacksChanged) {
+ what |= eHasListenerCallbacksChanged;
+ hasListenerCallbacks = other.hasListenerCallbacks;
}
#ifndef NO_INPUT
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 39cd62f..83cf40c 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -203,15 +203,15 @@
* that could possibly exist for the callbacks.
*/
std::unordered_map<sp<IBinder>, sp<SurfaceControl>, IBinderHash> surfaceControls;
- for (const auto& [callbackIds, transactionStats] : listenerStats.transactionStats) {
- for (auto callbackId : callbackIds) {
+ for (const auto& transactionStats : listenerStats.transactionStats) {
+ for (auto callbackId : transactionStats.callbackIds) {
auto& [callbackFunction, callbackSurfaceControls] = mCallbacks[callbackId];
surfaceControls.insert(callbackSurfaceControls.begin(), callbackSurfaceControls.end());
}
}
- for (const auto& [callbackIds, transactionStats] : listenerStats.transactionStats) {
- for (auto callbackId : callbackIds) {
+ for (const auto& transactionStats : listenerStats.transactionStats) {
+ for (auto callbackId : transactionStats.callbackIds) {
auto& [callbackFunction, callbackSurfaceControls] = mCallbacks[callbackId];
if (!callbackFunction) {
ALOGE("cannot call null callback function, skipping");
@@ -381,7 +381,7 @@
s.state.parentHandleForChild = nullptr;
composerStates.add(s);
- sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1, {});
+ sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1, {}, {});
}
void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) {
@@ -391,7 +391,7 @@
uncacheBuffer.token = BufferCache::getInstance().getToken();
uncacheBuffer.cacheId = cacheId;
- sf->setTransactionState({}, {}, 0, nullptr, {}, -1, uncacheBuffer);
+ sf->setTransactionState({}, {}, 0, nullptr, {}, -1, uncacheBuffer, {});
}
void SurfaceComposerClient::Transaction::cacheBuffers() {
@@ -406,10 +406,16 @@
continue;
}
+ // Don't try to cache a null buffer. Sending null buffers is cheap so we shouldn't waste
+ // time trying to cache them.
+ if (!s->buffer) {
+ continue;
+ }
+
uint64_t cacheId = 0;
status_t ret = BufferCache::getInstance().getCacheId(s->buffer, &cacheId);
if (ret == NO_ERROR) {
- s->what &= ~static_cast<uint32_t>(layer_state_t::eBufferChanged);
+ s->what &= ~static_cast<uint64_t>(layer_state_t::eBufferChanged);
s->buffer = nullptr;
} else {
cacheId = BufferCache::getInstance().cache(s->buffer);
@@ -434,6 +440,8 @@
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ std::vector<ListenerCallbacks> listenerCallbacks;
+
// For every listener with registered callbacks
for (const auto& [listener, callbackInfo] : mListenerCallbacks) {
auto& [callbackIds, surfaceControls] = callbackInfo;
@@ -441,11 +449,7 @@
continue;
}
- // If the listener does not have any SurfaceControls set on this Transaction, send the
- // callback now
- if (surfaceControls.empty()) {
- listener->onTransactionCompleted(ListenerStats::createEmpty(listener, callbackIds));
- }
+ listenerCallbacks.emplace_back(listener, std::move(callbackIds));
// If the listener has any SurfaceControls set on this Transaction update the surface state
for (const auto& surfaceControl : surfaceControls) {
@@ -454,8 +458,8 @@
ALOGE("failed to get layer state");
continue;
}
- s->what |= layer_state_t::eListenerCallbacksChanged;
- s->listenerCallbacks.emplace_back(listener, std::move(callbackIds));
+ s->what |= layer_state_t::eHasListenerCallbacksChanged;
+ s->hasListenerCallbacks = true;
}
}
mListenerCallbacks.clear();
@@ -494,7 +498,8 @@
sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands,
mDesiredPresentTime,
- {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/);
+ {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/,
+ listenerCallbacks);
mInputWindowCommands.clear();
mStatus = NO_ERROR;
return NO_ERROR;
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 0ef5b39..fe85fdf 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -20,13 +20,10 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <utils/Timers.h>
-#include <utils/Vector.h>
-
#include <binder/IInterface.h>
+#include <gui/ITransactionCompletedListener.h>
+
#include <ui/ConfigStoreTypes.h>
#include <ui/DisplayedFrameStats.h>
#include <ui/FrameStats.h>
@@ -34,6 +31,11 @@
#include <ui/GraphicTypes.h>
#include <ui/PixelFormat.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/Vector.h>
+
#include <optional>
#include <vector>
@@ -133,7 +135,8 @@
const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
int64_t desiredPresentTime,
- const cached_buffer_t& uncacheBuffer) = 0;
+ const cached_buffer_t& uncacheBuffer,
+ const std::vector<ListenerCallbacks>& listenerCallbacks) = 0;
/* signal that we're done booting.
* Requires ACCESS_SURFACE_FLINGER permission
diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h
index 29ab026..774ad46 100644
--- a/libs/gui/include/gui/ITransactionCompletedListener.h
+++ b/libs/gui/include/gui/ITransactionCompletedListener.h
@@ -34,18 +34,6 @@
using CallbackId = int64_t;
-struct CallbackIdsHash {
- // CallbackId vectors have several properties that let us get away with this simple hash.
- // 1) CallbackIds are never 0 so if something has gone wrong and our CallbackId vector is
- // empty we can still hash 0.
- // 2) CallbackId vectors for the same listener either are identical or contain none of the
- // same members. It is sufficient to just check the first CallbackId in the vectors. If
- // they match, they are the same. If they do not match, they are not the same.
- std::size_t operator()(const std::vector<CallbackId> callbackIds) const {
- return std::hash<CallbackId>{}((callbackIds.size() == 0) ? 0 : callbackIds.front());
- }
-};
-
class SurfaceStats : public Parcelable {
public:
status_t writeToParcel(Parcel* output) const override;
@@ -65,6 +53,15 @@
status_t writeToParcel(Parcel* output) const override;
status_t readFromParcel(const Parcel* input) override;
+ TransactionStats() = default;
+ TransactionStats(const std::vector<CallbackId>& ids) : callbackIds(ids) {}
+ TransactionStats(const std::unordered_set<CallbackId>& ids)
+ : callbackIds(ids.begin(), ids.end()) {}
+ TransactionStats(const std::vector<CallbackId>& ids, nsecs_t latch, const sp<Fence>& present,
+ const std::vector<SurfaceStats>& surfaces)
+ : callbackIds(ids), latchTime(latch), presentFence(present), surfaceStats(surfaces) {}
+
+ std::vector<CallbackId> callbackIds;
nsecs_t latchTime = -1;
sp<Fence> presentFence = nullptr;
std::vector<SurfaceStats> surfaceStats;
@@ -79,7 +76,7 @@
const std::unordered_set<CallbackId>& callbackIds);
sp<ITransactionCompletedListener> listener;
- std::unordered_map<std::vector<CallbackId>, TransactionStats, CallbackIdsHash> transactionStats;
+ std::vector<TransactionStats> transactionStats;
};
class ITransactionCompletedListener : public IInterface {
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 77bf8f1..2256497 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -23,7 +23,6 @@
#include <utils/Errors.h>
#include <gui/IGraphicBufferProducer.h>
-#include <gui/ITransactionCompletedListener.h>
#include <math/mat4.h>
#ifndef NO_INPUT
@@ -86,7 +85,7 @@
eApiChanged = 0x04000000,
eSidebandStreamChanged = 0x08000000,
eColorTransformChanged = 0x10000000,
- eListenerCallbacksChanged = 0x20000000,
+ eHasListenerCallbacksChanged = 0x20000000,
eInputInfoChanged = 0x40000000,
eCornerRadiusChanged = 0x80000000,
eFrameChanged = 0x1'00000000,
@@ -120,6 +119,7 @@
surfaceDamageRegion(),
api(-1),
colorTransform(mat4()),
+ hasListenerCallbacks(false),
bgColorAlpha(0),
bgColorDataspace(ui::Dataspace::UNKNOWN),
colorSpaceAgnostic(false) {
@@ -182,7 +182,7 @@
sp<NativeHandle> sidebandStream;
mat4 colorTransform;
- std::vector<ListenerCallbacks> listenerCallbacks;
+ bool hasListenerCallbacks;
#ifndef NO_INPUT
InputWindowInfo inputInfo;
#endif
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 94b669d..0ee9bff 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -561,7 +561,9 @@
const sp<IBinder>& /*applyToken*/,
const InputWindowCommands& /*inputWindowCommands*/,
int64_t /*desiredPresentTime*/,
- const cached_buffer_t& /*cachedBuffer*/) override {}
+ const cached_buffer_t& /*cachedBuffer*/,
+ const std::vector<ListenerCallbacks>& /*listenerCallbacks*/) override {
+ }
void bootFinished() override {}
bool authenticateSurfaceTexture(
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index fb71ce5..d0127b8 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -831,12 +831,14 @@
return success;
}
EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer,
- bool isProtected) {
+ bool isProtected,
+ bool useFramebufferCache) {
sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(nativeBuffer);
- uint64_t bufferId = graphicBuffer->getId();
- for (const auto& image : mFramebufferImageCache) {
- if (image.first == bufferId) {
- return image.second;
+ if (useFramebufferCache) {
+ for (const auto& image : mFramebufferImageCache) {
+ if (image.first == graphicBuffer->getId()) {
+ return image.second;
+ }
}
}
EGLint attributes[] = {
@@ -846,13 +848,15 @@
};
EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
nativeBuffer, attributes);
- if (image != EGL_NO_IMAGE_KHR) {
- if (mFramebufferImageCache.size() >= mFramebufferImageCacheSize) {
- EGLImageKHR expired = mFramebufferImageCache.front().second;
- mFramebufferImageCache.pop_front();
- eglDestroyImageKHR(mEGLDisplay, expired);
+ if (useFramebufferCache) {
+ if (image != EGL_NO_IMAGE_KHR) {
+ if (mFramebufferImageCache.size() >= mFramebufferImageCacheSize) {
+ EGLImageKHR expired = mFramebufferImageCache.front().second;
+ mFramebufferImageCache.pop_front();
+ eglDestroyImageKHR(mEGLDisplay, expired);
+ }
+ mFramebufferImageCache.push_back({graphicBuffer->getId(), image});
}
- mFramebufferImageCache.push_back({bufferId, image});
}
return image;
}
@@ -860,7 +864,8 @@
status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
const std::vector<LayerSettings>& layers,
ANativeWindowBuffer* const buffer,
- base::unique_fd&& bufferFence, base::unique_fd* drawFence) {
+ const bool useFramebufferCache, base::unique_fd&& bufferFence,
+ base::unique_fd* drawFence) {
ATRACE_CALL();
if (layers.empty()) {
ALOGV("Drawing empty layer stack");
@@ -880,7 +885,7 @@
{
std::lock_guard<std::mutex> lock(mRenderingMutex);
- BindNativeBufferAsFramebuffer fbo(*this, buffer);
+ BindNativeBufferAsFramebuffer fbo(*this, buffer, useFramebufferCache);
if (fbo.getStatus() != NO_ERROR) {
ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 613629e..de793c2 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -84,14 +84,16 @@
bool supportsProtectedContent() const override;
bool useProtectedContext(bool useProtectedContext) override;
status_t drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers,
- ANativeWindowBuffer* buffer, base::unique_fd&& bufferFence,
- base::unique_fd* drawFence) EXCLUDES(mRenderingMutex) override;
+ ANativeWindowBuffer* buffer, const bool useFramebufferCache,
+ base::unique_fd&& bufferFence, base::unique_fd* drawFence)
+ EXCLUDES(mRenderingMutex) override;
// internal to RenderEngine
EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
EGLConfig getEGLConfig() const { return mEGLConfig; }
// Creates an output image for rendering to
- EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected);
+ EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected,
+ bool useFramebufferCache);
// Test-only methods
// Returns true iff mImageCache contains an image keyed by bufferId
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index c45598c..dacf8d3 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -41,19 +41,25 @@
glDeleteTextures(1, &mTextureName);
}
-bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) {
+bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected,
+ const bool useFramebufferCache) {
ATRACE_CALL();
if (mEGLImage != EGL_NO_IMAGE_KHR) {
+ if (!usingFramebufferCache) {
+ eglDestroyImageKHR(mEGLDisplay, mEGLImage);
+ }
mEGLImage = EGL_NO_IMAGE_KHR;
mBufferWidth = 0;
mBufferHeight = 0;
}
if (nativeBuffer) {
- mEGLImage = mEngine.createFramebufferImageIfNeeded(nativeBuffer, isProtected);
+ mEGLImage = mEngine.createFramebufferImageIfNeeded(nativeBuffer, isProtected,
+ useFramebufferCache);
if (mEGLImage == EGL_NO_IMAGE_KHR) {
return false;
}
+ usingFramebufferCache = useFramebufferCache;
mBufferWidth = nativeBuffer->width;
mBufferHeight = nativeBuffer->height;
}
diff --git a/libs/renderengine/gl/GLFramebuffer.h b/libs/renderengine/gl/GLFramebuffer.h
index 1289fbf..b7650bb 100644
--- a/libs/renderengine/gl/GLFramebuffer.h
+++ b/libs/renderengine/gl/GLFramebuffer.h
@@ -35,7 +35,8 @@
explicit GLFramebuffer(GLESRenderEngine& engine);
~GLFramebuffer() override;
- bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) override;
+ bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected,
+ const bool useFramebufferCache) override;
EGLImageKHR getEGLImage() const { return mEGLImage; }
uint32_t getTextureName() const { return mTextureName; }
uint32_t getFramebufferName() const { return mFramebufferName; }
@@ -46,6 +47,7 @@
GLESRenderEngine& mEngine;
EGLDisplay mEGLDisplay;
EGLImageKHR mEGLImage;
+ bool usingFramebufferCache = false;
uint32_t mTextureName, mFramebufferName;
int32_t mBufferHeight = 0;
diff --git a/libs/renderengine/include/renderengine/Framebuffer.h b/libs/renderengine/include/renderengine/Framebuffer.h
index 66eb9ef..6511127 100644
--- a/libs/renderengine/include/renderengine/Framebuffer.h
+++ b/libs/renderengine/include/renderengine/Framebuffer.h
@@ -27,7 +27,8 @@
public:
virtual ~Framebuffer() = default;
- virtual bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) = 0;
+ virtual bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected,
+ const bool useFramebufferCache) = 0;
};
} // namespace renderengine
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 6773859..bf614fd 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -176,6 +176,9 @@
// @param layers The layers to draw onto the display, in Z-order.
// @param buffer The buffer which will be drawn to. This buffer will be
// ready once drawFence fires.
+ // @param useFramebufferCache True if the framebuffer cache should be used.
+ // If an implementation does not cache output framebuffers, then this
+ // parameter does nothing.
// @param bufferFence Fence signalling that the buffer is ready to be drawn
// to.
// @param drawFence A pointer to a fence, which will fire when the buffer
@@ -186,8 +189,8 @@
// now, this always returns NO_ERROR.
virtual status_t drawLayers(const DisplaySettings& display,
const std::vector<LayerSettings>& layers,
- ANativeWindowBuffer* buffer, base::unique_fd&& bufferFence,
- base::unique_fd* drawFence) = 0;
+ ANativeWindowBuffer* buffer, const bool useFramebufferCache,
+ base::unique_fd&& bufferFence, base::unique_fd* drawFence) = 0;
protected:
// Gets a framebuffer to render to. This framebuffer may or may not be
@@ -201,14 +204,16 @@
class BindNativeBufferAsFramebuffer {
public:
- BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer)
+ BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer,
+ const bool useFramebufferCache)
: mEngine(engine), mFramebuffer(mEngine.getFramebufferForDrawing()), mStatus(NO_ERROR) {
- mStatus = mFramebuffer->setNativeWindowBuffer(buffer, mEngine.isProtected())
+ mStatus = mFramebuffer->setNativeWindowBuffer(buffer, mEngine.isProtected(),
+ useFramebufferCache)
? mEngine.bindFrameBuffer(mFramebuffer)
: NO_MEMORY;
}
~BindNativeBufferAsFramebuffer() {
- mFramebuffer->setNativeWindowBuffer(nullptr, false);
+ mFramebuffer->setNativeWindowBuffer(nullptr, false, /*arbitrary*/ true);
mEngine.unbindFrameBuffer(mFramebuffer);
}
status_t getStatus() const { return mStatus; }
diff --git a/libs/renderengine/include/renderengine/mock/Framebuffer.h b/libs/renderengine/include/renderengine/mock/Framebuffer.h
index 7695885..dfb6a4e 100644
--- a/libs/renderengine/include/renderengine/mock/Framebuffer.h
+++ b/libs/renderengine/include/renderengine/mock/Framebuffer.h
@@ -28,7 +28,7 @@
Framebuffer();
~Framebuffer() override;
- MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer*, bool));
+ MOCK_METHOD3(setNativeWindowBuffer, bool(ANativeWindowBuffer*, bool, const bool));
};
} // namespace mock
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index 4f7d9f4..e33bcfd 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -79,9 +79,9 @@
MOCK_CONST_METHOD0(isProtected, bool());
MOCK_CONST_METHOD0(supportsProtectedContent, bool());
MOCK_METHOD1(useProtectedContext, bool(bool));
- MOCK_METHOD5(drawLayers,
+ MOCK_METHOD6(drawLayers,
status_t(const DisplaySettings&, const std::vector<LayerSettings>&,
- ANativeWindowBuffer*, base::unique_fd&&, base::unique_fd*));
+ ANativeWindowBuffer*, const bool, base::unique_fd&&, base::unique_fd*));
};
} // namespace mock
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 24904cf..7acaecf 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -118,7 +118,7 @@
void invokeDraw(renderengine::DisplaySettings settings,
std::vector<renderengine::LayerSettings> layers, sp<GraphicBuffer> buffer) {
base::unique_fd fence;
- status_t status = sRE->drawLayers(settings, layers, buffer->getNativeBuffer(),
+ status_t status = sRE->drawLayers(settings, layers, buffer->getNativeBuffer(), true,
base::unique_fd(), &fence);
sCurrentBuffer = buffer;
@@ -770,7 +770,7 @@
BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
layers.push_back(layer);
base::unique_fd fence;
- status_t status = sRE->drawLayers(settings, layers, nullptr, base::unique_fd(), &fence);
+ status_t status = sRE->drawLayers(settings, layers, nullptr, true, base::unique_fd(), &fence);
ASSERT_EQ(BAD_VALUE, status);
}
@@ -787,13 +787,33 @@
layer.alpha = 1.0;
layers.push_back(layer);
- status_t status = sRE->drawLayers(settings, layers, mBuffer->getNativeBuffer(),
+ status_t status = sRE->drawLayers(settings, layers, mBuffer->getNativeBuffer(), true,
base::unique_fd(), nullptr);
sCurrentBuffer = mBuffer;
ASSERT_EQ(NO_ERROR, status);
expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
}
+TEST_F(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) {
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ settings.clip = fullscreenRect();
+
+ std::vector<renderengine::LayerSettings> layers;
+ renderengine::LayerSettings layer;
+ layer.geometry.boundaries = fullscreenRect().toFloatRect();
+ BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
+ layer.alpha = 1.0;
+ layers.push_back(layer);
+
+ status_t status = sRE->drawLayers(settings, layers, mBuffer->getNativeBuffer(), false,
+ base::unique_fd(), nullptr);
+ sCurrentBuffer = mBuffer;
+ ASSERT_EQ(NO_ERROR, status);
+ ASSERT_FALSE(sRE->isFramebufferImageCachedForTesting(mBuffer->getId()));
+ expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
+}
+
TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_colorSource) {
fillRedBuffer<ColorSourceVariant>();
}
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index fa92830..6d202ae 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -59,9 +59,6 @@
"libbufferhub_headers",
"libnativebase_headers",
],
-
- // TODO(b/117568153): Temporarily opt out using libcrt.
- no_libcrt: true,
}
cc_test {
@@ -70,7 +67,4 @@
shared_libs: sharedLibraries,
header_libs: headerLibraries,
name: "buffer_hub-test",
-
- // TODO(b/117568153): Temporarily opt out using libcrt.
- no_libcrt: true,
}
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 20894e3..9f72c05 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -59,9 +59,6 @@
static_libs: staticLibraries,
shared_libs: sharedLibraries,
header_libs: headerLibraries,
-
- // TODO(b/117568153): Temporarily opt out using libcrt.
- no_libcrt: true,
}
subdirs = ["benchmarks", "tests"]
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
index 357dffe..3260447 100644
--- a/libs/vr/libdvr/tests/Android.bp
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -49,9 +49,6 @@
"-g",
],
name: "dvr_api-test",
-
- // TODO(b/117568153): Temporarily opt out using libcrt.
- no_libcrt: true,
}
cc_test {
diff --git a/libs/vr/libvrflinger/tests/Android.bp b/libs/vr/libvrflinger/tests/Android.bp
index c884cb3..410e234 100644
--- a/libs/vr/libvrflinger/tests/Android.bp
+++ b/libs/vr/libvrflinger/tests/Android.bp
@@ -33,7 +33,4 @@
"-Werror",
],
name: "vrflinger_test",
-
- // TODO(b/117568153): Temporarily opt out using libcrt.
- no_libcrt: true,
}
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index ac1d492..52c68df 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -47,7 +47,7 @@
"libhwbinder",
"liblayers_proto",
"liblog",
- "libnativewindow",
+ "libnativewindow",
"libpdx_default_transport",
"libprocessgroup",
"libprotobuf-cpp-lite",
@@ -56,7 +56,7 @@
"libui",
"libinput",
"libutils",
- "libSurfaceFlingerProperties",
+ "libSurfaceFlingerProp",
],
static_libs: [
"libcompositionengine",
@@ -138,8 +138,9 @@
"LayerVector.cpp",
"MonitoredProducer.cpp",
"NativeWindowSurface.cpp",
- "RenderArea.cpp",
+ "RefreshRateOverlay.cpp",
"RegionSamplingThread.cpp",
+ "RenderArea.cpp",
"Scheduler/DispSync.cpp",
"Scheduler/DispSyncSource.cpp",
"Scheduler/EventControlThread.cpp",
@@ -221,7 +222,7 @@
srcs: [":surfaceflinger_binary_sources"],
shared_libs: [
"libsurfaceflinger",
- "libSurfaceFlingerProperties",
+ "libSurfaceFlingerProp",
],
}
@@ -232,10 +233,9 @@
]
cc_library_shared {
- name: "libSurfaceFlingerProperties",
+ name: "libSurfaceFlingerProp",
srcs: [
"SurfaceFlingerProperties.cpp",
- "sysprop/*.sysprop",
],
shared_libs: [
"android.hardware.configstore-utils",
@@ -247,6 +247,10 @@
"libhwbinder",
"libui",
"libutils",
+ "liblog",
+ ],
+ static_libs: [
+ "SurfaceFlingerProperties",
],
export_shared_lib_headers: [
"android.hardware.graphics.common@1.2",
@@ -254,4 +258,7 @@
"libhidltransport",
"libhwbinder",
],
+ export_static_lib_headers: [
+ "SurfaceFlingerProperties",
+ ],
}
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
new file mode 100644
index 0000000..e70bfe4
--- /dev/null
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019 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 "RefreshRateOverlay.h"
+#include "Client.h"
+#include "Layer.h"
+
+namespace android {
+
+using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+
+RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger)
+ : mFlinger(flinger), mClient(new Client(&mFlinger)) {
+ createLayer();
+}
+
+bool RefreshRateOverlay::createLayer() {
+ const status_t ret =
+ mFlinger.createLayer(String8("RefreshRateOverlay"), mClient, 0, 0,
+ PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor,
+ LayerMetadata(), &mIBinder, &mGbp, &mLayer);
+ if (ret) {
+ ALOGE("failed to color layer");
+ return false;
+ }
+
+ mLayer = mClient->getLayerUser(mIBinder);
+ mLayer->setCrop_legacy(Rect(0, 0, 200, 100), true);
+ mLayer->setLayer(INT32_MAX - 2);
+
+ return true;
+}
+
+void RefreshRateOverlay::changeRefreshRate(RefreshRateType type) {
+ const half3& color = (type == RefreshRateType::PERFORMANCE) ? GREEN : RED;
+ mLayer->setColor(color);
+ mFlinger.setTransactionFlags(eTransactionMask);
+}
+
+}; // namespace android
diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h
new file mode 100644
index 0000000..ce29bc3
--- /dev/null
+++ b/services/surfaceflinger/RefreshRateOverlay.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019 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 "SurfaceFlinger.h"
+
+namespace android {
+
+using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+
+class RefreshRateOverlay {
+public:
+ RefreshRateOverlay(SurfaceFlinger& flinger);
+
+ void changeRefreshRate(RefreshRateType type);
+
+private:
+ bool createLayer();
+
+ SurfaceFlinger& mFlinger;
+ sp<Client> mClient;
+ sp<Layer> mLayer;
+ sp<IBinder> mIBinder;
+ sp<IGraphicBufferProducer> mGbp;
+
+ const half3 RED = half3(1.0f, 0.0f, 0.0f);
+ const half3 GREEN = half3(0.0f, 1.0f, 0.0f);
+};
+
+}; // namespace android
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index a2a6bd8..f72aef1 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -333,7 +333,6 @@
if (t < now) {
if (isShorterThanPeriod(now - eventListener.mLastCallbackTime)) {
eventListener.mLastEventTime = t;
- eventListener.mLastCallbackTime = now;
ALOGV("[%s] [%s] Skipping event due to model error", mName,
eventListener.mName);
continue;
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 78bf7c5..a760079 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -97,7 +97,7 @@
return event;
}
-DisplayEventReceiver::Event makeConfigChanged(uint32_t displayId, int32_t configId) {
+DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, int32_t configId) {
DisplayEventReceiver::Event event;
event.header = {DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, displayId, systemTime()};
event.config.configId = configId;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 9e95f95..1aa6ade 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -57,7 +57,7 @@
}
~RefreshRateConfigs() = default;
- const std::unordered_map<RefreshRateType, std::shared_ptr<RefreshRate>>& getRefreshRates() {
+ const std::map<RefreshRateType, std::shared_ptr<RefreshRate>>& getRefreshRates() {
return mRefreshRates;
}
std::shared_ptr<RefreshRate> getRefreshRate(RefreshRateType type) {
@@ -120,7 +120,7 @@
}
}
- std::unordered_map<RefreshRateType, std::shared_ptr<RefreshRate>> mRefreshRates;
+ std::map<RefreshRateType, std::shared_ptr<RefreshRate>> mRefreshRates;
};
} // namespace scheduler
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a5f025d..0345baf 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -84,6 +84,7 @@
#include "LayerVector.h"
#include "MonitoredProducer.h"
#include "NativeWindowSurface.h"
+#include "RefreshRateOverlay.h"
#include "StartPropertySetThread.h"
#include "SurfaceFlinger.h"
#include "SurfaceInterceptor.h"
@@ -128,8 +129,6 @@
using ui::Hdr;
using ui::RenderIntent;
-using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
-
namespace {
#pragma clang diagnostic push
@@ -281,6 +280,7 @@
mFactory(factory),
mTransactionPending(false),
mAnimTransactionPending(false),
+ mTraversalNeededMainThread(false),
mLayersRemoved(false),
mLayersAdded(false),
mBootTime(systemTime()),
@@ -942,24 +942,18 @@
return display->getActiveConfig();
}
-void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int mode,
- Scheduler::ConfigEvent event) {
+void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) {
ATRACE_CALL();
// Lock is acquired by setRefreshRateTo.
- const auto display = getDisplayDeviceLocked(displayToken);
+ const auto display = getDisplayDeviceLocked(info.displayToken);
if (!display) {
- ALOGE("Attempt to set active config %d for invalid display token %p", mode,
- displayToken.get());
+ ALOGE("Attempt to set active config %d for invalid display token %p", info.configId,
+ info.displayToken.get());
return;
}
if (display->isVirtual()) {
- ALOGW("Attempt to set active config %d for virtual display", mode);
- return;
- }
- int currentDisplayPowerMode = display->getPowerMode();
- if (currentDisplayPowerMode != HWC_POWER_MODE_NORMAL) {
- // Don't change active config when in AoD.
+ ALOGW("Attempt to set active config %d for virtual display", info.configId);
return;
}
@@ -967,8 +961,9 @@
// config twice. However event generation config might have changed so we need to update it
// accordingly
std::lock_guard<std::mutex> lock(mActiveConfigLock);
- const Scheduler::ConfigEvent desiredConfig = mDesiredActiveConfig.event | event;
- mDesiredActiveConfig = ActiveConfigInfo{mode, displayToken, desiredConfig};
+ const Scheduler::ConfigEvent prevConfig = mDesiredActiveConfig.event;
+ mDesiredActiveConfig = info;
+ mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig;
if (!mDesiredActiveConfigChanged) {
// This is the first time we set the desired
@@ -979,6 +974,10 @@
}
mDesiredActiveConfigChanged = true;
ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
+
+ if (mRefreshRateOverlay) {
+ mRefreshRateOverlay->changeRefreshRate(mDesiredActiveConfig.type);
+ }
}
status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
@@ -1041,6 +1040,7 @@
// on both cases there is nothing left to do
std::lock_guard<std::mutex> lock(mActiveConfigLock);
mScheduler->pauseVsyncCallback(mAppConnectionHandle, false);
+ mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
mDesiredActiveConfigChanged = false;
ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
return false;
@@ -1491,7 +1491,7 @@
}
mPhaseOffsets->setRefreshRateType(refreshRate);
- setDesiredActiveConfig(getInternalDisplayTokenLocked(), desiredConfigId, event);
+ setDesiredActiveConfig({refreshRate, desiredConfigId, getInternalDisplayTokenLocked(), event});
}
void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
@@ -2778,7 +2778,7 @@
* (perform the transaction for each of them if needed)
*/
- if (transactionFlags & eTraversalNeeded) {
+ if ((transactionFlags & eTraversalNeeded) || mTraversalNeededMainThread) {
mCurrentState.traverseInZOrder([&](Layer* layer) {
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
if (!trFlags) return;
@@ -2791,6 +2791,7 @@
mInputInfoChanged = true;
}
});
+ mTraversalNeededMainThread = false;
}
/*
@@ -3436,7 +3437,8 @@
}
}
renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
- buf->getNativeBuffer(), std::move(fd), readyFence);
+ buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
+ readyFence);
if (expensiveRenderingExpected && displayId) {
mPowerAdvisor.setExpensiveRenderingExpected(*displayId, false);
}
@@ -3522,14 +3524,14 @@
while (!transactionQueue.empty()) {
const auto&
- [states, displays, flags, desiredPresentTime, uncacheBuffer, postTime,
- privileged] = transactionQueue.front();
+ [states, displays, flags, desiredPresentTime, uncacheBuffer, listenerCallbacks,
+ postTime, privileged] = transactionQueue.front();
if (!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
break;
}
applyTransactionState(states, displays, flags, mPendingInputWindowCommands,
- desiredPresentTime, uncacheBuffer, postTime, privileged,
- /*isMainThread*/ true);
+ desiredPresentTime, uncacheBuffer, listenerCallbacks, postTime,
+ privileged, /*isMainThread*/ true);
transactionQueue.pop();
}
@@ -3587,7 +3589,8 @@
const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
int64_t desiredPresentTime,
- const cached_buffer_t& uncacheBuffer) {
+ const cached_buffer_t& uncacheBuffer,
+ const std::vector<ListenerCallbacks>& listenerCallbacks) {
ATRACE_CALL();
const int64_t postTime = systemTime();
@@ -3604,13 +3607,14 @@
if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() ||
!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime,
- uncacheBuffer, postTime, privileged);
+ uncacheBuffer, listenerCallbacks, postTime,
+ privileged);
setTransactionFlags(eTransactionNeeded);
return;
}
applyTransactionState(states, displays, flags, inputWindowCommands, desiredPresentTime,
- uncacheBuffer, postTime, privileged);
+ uncacheBuffer, listenerCallbacks, postTime, privileged);
}
void SurfaceFlinger::applyTransactionState(const Vector<ComposerState>& states,
@@ -3618,6 +3622,7 @@
const InputWindowCommands& inputWindowCommands,
const int64_t desiredPresentTime,
const cached_buffer_t& uncacheBuffer,
+ const std::vector<ListenerCallbacks>& listenerCallbacks,
const int64_t postTime, bool privileged,
bool isMainThread) {
uint32_t transactionFlags = 0;
@@ -3642,10 +3647,22 @@
transactionFlags |= setDisplayStateLocked(display);
}
+ // In case the client has sent a Transaction that should receive callbacks but without any
+ // SurfaceControls that should be included in the callback, send the listener and callbackIds
+ // to the callback thread so it can send an empty callback
+ if (!listenerCallbacks.empty()) {
+ mTransactionCompletedThread.run();
+ }
+ for (const auto& [listener, callbackIds] : listenerCallbacks) {
+ mTransactionCompletedThread.addCallback(listener, callbackIds);
+ }
+
uint32_t clientStateFlags = 0;
for (const ComposerState& state : states) {
- clientStateFlags |= setClientStateLocked(state, desiredPresentTime, postTime, privileged);
+ clientStateFlags |= setClientStateLocked(state, desiredPresentTime, listenerCallbacks,
+ postTime, privileged);
}
+
// If the state doesn't require a traversal and there are callbacks, send them now
if (!(clientStateFlags & eTraversalNeeded)) {
mTransactionCompletedThread.sendCallbacks();
@@ -3667,6 +3684,13 @@
transactionFlags = eTransactionNeeded;
}
+ // If we are on the main thread, we are about to preform a traversal. Clear the traversal bit
+ // so we don't have to wake up again next frame to preform an uneeded traversal.
+ if (isMainThread && (transactionFlags & eTraversalNeeded)) {
+ transactionFlags = transactionFlags & (~eTraversalNeeded);
+ mTraversalNeededMainThread = true;
+ }
+
if (transactionFlags) {
if (mInterceptor->isEnabled()) {
mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags);
@@ -3765,9 +3789,10 @@
return true;
}
-uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState,
- int64_t desiredPresentTime, int64_t postTime,
- bool privileged) {
+uint32_t SurfaceFlinger::setClientStateLocked(
+ const ComposerState& composerState, int64_t desiredPresentTime,
+ const std::vector<ListenerCallbacks>& listenerCallbacks, int64_t postTime,
+ bool privileged) {
const layer_state_t& s = composerState.state;
sp<Client> client(static_cast<Client*>(composerState.client.get()));
@@ -3993,9 +4018,8 @@
}
}
std::vector<sp<CallbackHandle>> callbackHandles;
- if ((what & layer_state_t::eListenerCallbacksChanged) && (!s.listenerCallbacks.empty())) {
- mTransactionCompletedThread.run();
- for (const auto& [listener, callbackIds] : s.listenerCallbacks) {
+ if ((what & layer_state_t::eHasListenerCallbacksChanged) && (!listenerCallbacks.empty())) {
+ for (const auto& [listener, callbackIds] : listenerCallbacks) {
callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface));
}
}
@@ -4256,7 +4280,7 @@
d.width = 0;
d.height = 0;
displays.add(d);
- setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1, {});
+ setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1, {}, {});
setPowerModeInternal(display, HWC_POWER_MODE_NORMAL);
@@ -5020,9 +5044,9 @@
code == IBinder::SYSPROPS_TRANSACTION) {
return OK;
}
- // Numbers from 1000 to 1033 are currently used for backdoors. The code
+ // Numbers from 1000 to 1034 are currently used for backdoors. The code
// in onTransact verifies that the user is root, and has access to use SF.
- if (code >= 1000 && code <= 1033) {
+ if (code >= 1000 && code <= 1034) {
ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
return OK;
}
@@ -5338,6 +5362,18 @@
reply->writeInt32(NO_ERROR);
return NO_ERROR;
}
+ case 1034: {
+ // TODO(b/129297325): expose this via developer menu option
+ n = data.readInt32();
+ if (n && !mRefreshRateOverlay) {
+ std::lock_guard<std::mutex> lock(mActiveConfigLock);
+ mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this);
+ mRefreshRateOverlay->changeRefreshRate(mDesiredActiveConfig.type);
+ } else if (!n) {
+ mRefreshRateOverlay.reset();
+ }
+ return NO_ERROR;
+ }
}
}
return err;
@@ -5722,7 +5758,7 @@
base::unique_fd drawFence;
getRenderEngine().useProtectedContext(false);
getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayers, buffer,
- std::move(bufferFence), &drawFence);
+ /*useFramebufferCache=*/false, std::move(bufferFence), &drawFence);
*outSyncFd = drawFence.release();
}
@@ -5805,30 +5841,14 @@
mAllowedConfigs[*displayId] = std::move(allowedConfigs);
}
- // make sure that the current config is still allowed
- int currentConfigIndex = getHwComposer().getActiveConfigIndex(*displayId);
- if (!isConfigAllowed(*displayId, currentConfigIndex)) {
- for (const auto& [type, config] : mRefreshRateConfigs[*displayId]->getRefreshRates()) {
- if (config && isConfigAllowed(*displayId, config->configId)) {
- // TODO: we switch to the first allowed config. In the future
- // we may want to enhance this logic to pick a similar config
- // to the current one
- ALOGV("Old config is not allowed - switching to config %d", config->configId);
- setDesiredActiveConfig(displayToken, config->configId,
- Scheduler::ConfigEvent::Changed);
- break;
- }
- }
- }
-
- // If idle timer and fps detection are disabled and we are in RefreshRateType::DEFAULT,
- // there is no trigger to move to RefreshRateType::PERFORMANCE, even if it is an allowed.
- if (!mScheduler->isIdleTimerEnabled() && !mUseSmart90ForVideo) {
- const auto& performanceRefreshRate =
- mRefreshRateConfigs[*displayId]->getRefreshRate(RefreshRateType::PERFORMANCE);
- if (performanceRefreshRate &&
- isConfigAllowed(*displayId, performanceRefreshRate->configId)) {
- setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::Changed);
+ // Set the highest allowed config by iterating backwards on available refresh rates
+ const auto& refreshRates = mRefreshRateConfigs[*displayId]->getRefreshRates();
+ for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) {
+ if (iter->second && isConfigAllowed(*displayId, iter->second->configId)) {
+ ALOGV("switching to config %d", iter->second->configId);
+ setDesiredActiveConfig({iter->first, iter->second->configId, displayToken,
+ Scheduler::ConfigEvent::Changed});
+ break;
}
}
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 26d0cd1..3d8b6b7 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -90,6 +90,8 @@
namespace android {
+using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+
// ---------------------------------------------------------------------------
class Client;
@@ -102,6 +104,7 @@
class IInputFlinger;
class InjectVSyncSource;
class Layer;
+class RefreshRateOverlay;
class Surface;
class SurfaceFlingerBE;
class TimeStats;
@@ -366,6 +369,7 @@
friend class BufferQueueLayer;
friend class BufferStateLayer;
friend class MonitoredProducer;
+ friend class RefreshRateOverlay;
friend class RegionSamplingThread;
friend class SurfaceTracing;
@@ -431,8 +435,8 @@
const Vector<DisplayState>& displays, uint32_t flags,
const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
- int64_t desiredPresentTime,
- const cached_buffer_t& uncacheBuffer) override;
+ int64_t desiredPresentTime, const cached_buffer_t& uncacheBuffer,
+ const std::vector<ListenerCallbacks>& listenerCallbacks) override;
void bootFinished() override;
bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) const override;
@@ -528,11 +532,30 @@
void signalLayerUpdate();
void signalRefresh();
+ struct ActiveConfigInfo {
+ RefreshRateType type;
+ int configId;
+ sp<IBinder> displayToken;
+ Scheduler::ConfigEvent event;
+
+ bool operator!=(const ActiveConfigInfo& other) const {
+ if (type != other.type) {
+ return true;
+ }
+ if (configId != other.configId) {
+ return true;
+ }
+ if (displayToken != other.displayToken) {
+ return true;
+ }
+ return (event != other.event);
+ }
+ };
+
// called on the main thread in response to initializeDisplays()
void onInitializeDisplays() REQUIRES(mStateLock);
// Sets the desired active config bit. It obtains the lock, and sets mDesiredActiveConfig.
- void setDesiredActiveConfig(const sp<IBinder>& displayToken, int mode,
- Scheduler::ConfigEvent event) REQUIRES(mStateLock);
+ void setDesiredActiveConfig(const ActiveConfigInfo& info) REQUIRES(mStateLock);
// Once HWC has returned the present fence, this sets the active config and a new refresh
// rate in SF. It also triggers HWC vsync.
void setActiveConfigInternal() REQUIRES(mStateLock);
@@ -579,8 +602,10 @@
const Vector<DisplayState>& displays, uint32_t flags,
const InputWindowCommands& inputWindowCommands,
const int64_t desiredPresentTime,
- const cached_buffer_t& uncacheBuffer, const int64_t postTime,
- bool privileged, bool isMainThread = false) REQUIRES(mStateLock);
+ const cached_buffer_t& uncacheBuffer,
+ const std::vector<ListenerCallbacks>& listenerCallbacks,
+ const int64_t postTime, bool privileged, bool isMainThread = false)
+ REQUIRES(mStateLock);
bool flushTransactionQueues();
uint32_t getTransactionFlags(uint32_t flags);
uint32_t peekTransactionFlags();
@@ -593,6 +618,7 @@
bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
const Vector<ComposerState>& states);
uint32_t setClientStateLocked(const ComposerState& composerState, int64_t desiredPresentTime,
+ const std::vector<ListenerCallbacks>& listenerCallbacks,
int64_t postTime, bool privileged) REQUIRES(mStateLock);
uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
@@ -815,8 +841,7 @@
// Sets the refresh rate by switching active configs, if they are available for
// the desired refresh rate.
- void setRefreshRateTo(scheduler::RefreshRateConfigs::RefreshRateType,
- Scheduler::ConfigEvent event) REQUIRES(mStateLock);
+ void setRefreshRateTo(RefreshRateType, Scheduler::ConfigEvent event) REQUIRES(mStateLock);
bool isConfigAllowed(const DisplayId& displayId, int32_t config);
@@ -938,6 +963,7 @@
bool mTransactionPending;
bool mAnimTransactionPending;
SortedVector< sp<Layer> > mLayersPendingRemoval;
+ bool mTraversalNeededMainThread;
// guards access to the mDrawing state if tracing is enabled.
mutable std::mutex mDrawingStateLock;
@@ -1062,12 +1088,14 @@
TransactionState(const Vector<ComposerState>& composerStates,
const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
int64_t desiredPresentTime, const cached_buffer_t& uncacheBuffer,
- int64_t postTime, bool privileged)
+ const std::vector<ListenerCallbacks>& listenerCallbacks, int64_t postTime,
+ bool privileged)
: states(composerStates),
displays(displayStates),
flags(transactionFlags),
desiredPresentTime(desiredPresentTime),
buffer(uncacheBuffer),
+ callback(listenerCallbacks),
postTime(postTime),
privileged(privileged) {}
@@ -1076,6 +1104,7 @@
uint32_t flags;
const int64_t desiredPresentTime;
cached_buffer_t buffer;
+ std::vector<ListenerCallbacks> callback;
const int64_t postTime;
bool privileged;
};
@@ -1134,18 +1163,6 @@
std::unordered_map<DisplayId, std::unique_ptr<const AllowedDisplayConfigs>> mAllowedConfigs
GUARDED_BY(mAllowedConfigsLock);
- struct ActiveConfigInfo {
- int configId;
- sp<IBinder> displayToken;
- Scheduler::ConfigEvent event;
-
- bool operator!=(const ActiveConfigInfo& other) const {
- if (configId != other.configId) {
- return true;
- }
- return (displayToken != other.displayToken);
- }
- };
std::mutex mActiveConfigLock;
// This bit is set once we start setting the config. We read from this bit during the
// process. If at the end, this bit is different than mDesiredActiveConfig, we restart
@@ -1172,6 +1189,8 @@
sp<SetInputWindowsListener> mSetInputWindowsListener;
bool mPendingSyncInputWindows GUARDED_BY(mStateLock);
Hwc2::impl::PowerAdvisor mPowerAdvisor;
+
+ std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay;
};
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index e130511..09b793a 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -1,6 +1,4 @@
-#include <sysprop/SurfaceFlingerProperties.sysprop.h>
-
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.1/types.h>
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index 6f90117..b2fafdd 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -2,9 +2,9 @@
#ifndef SURFACEFLINGERPROPERTIES_H_
#define SURFACEFLINGERPROPERTIES_H_
+#include <SurfaceFlingerProperties.sysprop.h>
#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
#include <android/hardware/graphics/common/1.2/types.h>
-#include <sysprop/SurfaceFlingerProperties.sysprop.h>
#include <ui/ConfigStoreTypes.h>
#include <cstdint>
diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
index d2b7fe0..1d2217d 100644
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ b/services/surfaceflinger/TransactionCompletedThread.cpp
@@ -29,6 +29,18 @@
namespace android {
+// Returns 0 if they are equal
+// <0 if the first id that doesn't match is lower in c2 or all ids match but c2 is shorter
+// >0 if the first id that doesn't match is greater in c2 or all ids match but c2 is longer
+//
+// See CallbackIdsHash for a explaniation of why this works
+static int compareCallbackIds(const std::vector<CallbackId>& c1, const std::vector<CallbackId> c2) {
+ if (c1.empty()) {
+ return !c2.empty();
+ }
+ return c1.front() - c2.front();
+}
+
TransactionCompletedThread::~TransactionCompletedThread() {
std::lock_guard lockThread(mThreadMutex);
@@ -44,8 +56,8 @@
{
std::lock_guard lock(mMutex);
- for (const auto& [listener, listenerStats] : mListenerStats) {
- listener->unlinkToDeath(mDeathRecipient);
+ for (const auto& [listener, transactionStats] : mCompletedTransactions) {
+ IInterface::asBinder(listener)->unlinkToDeath(mDeathRecipient);
}
}
}
@@ -62,64 +74,128 @@
mThread = std::thread(&TransactionCompletedThread::threadMain, this);
}
-void TransactionCompletedThread::registerPendingCallbackHandle(const sp<CallbackHandle>& handle) {
+status_t TransactionCompletedThread::addCallback(const sp<ITransactionCompletedListener>& listener,
+ const std::vector<CallbackId>& callbackIds) {
std::lock_guard lock(mMutex);
+ if (!mRunning) {
+ ALOGE("cannot add callback because the callback thread isn't running");
+ return BAD_VALUE;
+ }
- sp<IBinder> listener = IInterface::asBinder(handle->listener);
- const auto& callbackIds = handle->callbackIds;
+ if (mCompletedTransactions.count(listener) == 0) {
+ status_t err = IInterface::asBinder(listener)->linkToDeath(mDeathRecipient);
+ if (err != NO_ERROR) {
+ ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
+ return err;
+ }
+ }
- mPendingTransactions[listener][callbackIds]++;
+ auto& transactionStatsDeque = mCompletedTransactions[listener];
+ transactionStatsDeque.emplace_back(callbackIds);
+ return NO_ERROR;
}
-void TransactionCompletedThread::addPresentedCallbackHandles(
+status_t TransactionCompletedThread::registerPendingCallbackHandle(
+ const sp<CallbackHandle>& handle) {
+ std::lock_guard lock(mMutex);
+ if (!mRunning) {
+ ALOGE("cannot register callback handle because the callback thread isn't running");
+ return BAD_VALUE;
+ }
+
+ // If we can't find the transaction stats something has gone wrong. The client should call
+ // addCallback before trying to register a pending callback handle.
+ TransactionStats* transactionStats;
+ status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
+ if (err != NO_ERROR) {
+ ALOGE("cannot find transaction stats");
+ return err;
+ }
+
+ mPendingTransactions[handle->listener][handle->callbackIds]++;
+ return NO_ERROR;
+}
+
+status_t TransactionCompletedThread::addPresentedCallbackHandles(
const std::deque<sp<CallbackHandle>>& handles) {
std::lock_guard lock(mMutex);
+ if (!mRunning) {
+ ALOGE("cannot add presented callback handle because the callback thread isn't running");
+ return BAD_VALUE;
+ }
for (const auto& handle : handles) {
- auto listener = mPendingTransactions.find(IInterface::asBinder(handle->listener));
- auto& pendingCallbacks = listener->second;
- auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
+ auto listener = mPendingTransactions.find(handle->listener);
+ if (listener != mPendingTransactions.end()) {
+ auto& pendingCallbacks = listener->second;
+ auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
- if (pendingCallback != pendingCallbacks.end()) {
- auto& pendingCount = pendingCallback->second;
+ if (pendingCallback != pendingCallbacks.end()) {
+ auto& pendingCount = pendingCallback->second;
- // Decrease the pending count for this listener
- if (--pendingCount == 0) {
- pendingCallbacks.erase(pendingCallback);
+ // Decrease the pending count for this listener
+ if (--pendingCount == 0) {
+ pendingCallbacks.erase(pendingCallback);
+ }
+ } else {
+ ALOGW("there are more latched callbacks than there were registered callbacks");
}
} else {
- ALOGE("there are more latched callbacks than there were registered callbacks");
+ ALOGW("cannot find listener in mPendingTransactions");
}
- addCallbackHandle(handle);
+ status_t err = addCallbackHandle(handle);
+ if (err != NO_ERROR) {
+ ALOGE("could not add callback handle");
+ return err;
+ }
}
+
+ return NO_ERROR;
}
-void TransactionCompletedThread::addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle) {
+status_t TransactionCompletedThread::addUnpresentedCallbackHandle(
+ const sp<CallbackHandle>& handle) {
std::lock_guard lock(mMutex);
- addCallbackHandle(handle);
+ if (!mRunning) {
+ ALOGE("cannot add unpresented callback handle because the callback thread isn't running");
+ return BAD_VALUE;
+ }
+
+ return addCallbackHandle(handle);
}
-void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
- const sp<IBinder> listener = IInterface::asBinder(handle->listener);
+status_t TransactionCompletedThread::findTransactionStats(
+ const sp<ITransactionCompletedListener>& listener,
+ const std::vector<CallbackId>& callbackIds, TransactionStats** outTransactionStats) {
+ auto& transactionStatsDeque = mCompletedTransactions[listener];
- // If we don't already have a reference to this listener, linkToDeath so we get a notification
- // if it dies.
- if (mListenerStats.count(listener) == 0) {
- status_t error = listener->linkToDeath(mDeathRecipient);
- if (error != NO_ERROR) {
- ALOGE("cannot add callback handle because linkToDeath failed, err: %d", error);
- return;
+ // Search back to front because the most recent transactions are at the back of the deque
+ auto itr = transactionStatsDeque.rbegin();
+ for (; itr != transactionStatsDeque.rend(); itr++) {
+ if (compareCallbackIds(itr->callbackIds, callbackIds) == 0) {
+ *outTransactionStats = &(*itr);
+ return NO_ERROR;
}
}
- auto& listenerStats = mListenerStats[listener];
- listenerStats.listener = handle->listener;
+ ALOGE("could not find transaction stats");
+ return BAD_VALUE;
+}
- auto& transactionStats = listenerStats.transactionStats[handle->callbackIds];
- transactionStats.latchTime = handle->latchTime;
- transactionStats.surfaceStats.emplace_back(handle->surfaceControl, handle->acquireTime,
- handle->previousReleaseFence);
+status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
+ // If we can't find the transaction stats something has gone wrong. The client should call
+ // addCallback before trying to add a presnted callback handle.
+ TransactionStats* transactionStats;
+ status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ transactionStats->latchTime = handle->latchTime;
+ transactionStats->surfaceStats.emplace_back(handle->surfaceControl, handle->acquireTime,
+ handle->previousReleaseFence);
+ return NO_ERROR;
}
void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) {
@@ -141,40 +217,46 @@
mConditionVariable.wait(mMutex);
// For each listener
- auto it = mListenerStats.begin();
- while (it != mListenerStats.end()) {
- auto& [listener, listenerStats] = *it;
+ auto completedTransactionsItr = mCompletedTransactions.begin();
+ while (completedTransactionsItr != mCompletedTransactions.end()) {
+ auto& [listener, transactionStatsDeque] = *completedTransactionsItr;
+ ListenerStats listenerStats;
+ listenerStats.listener = listener;
// For each transaction
- bool sendCallback = true;
- for (auto& [callbackIds, transactionStats] : listenerStats.transactionStats) {
- // If we are still waiting on the callback handles for this transaction, skip it
- if (mPendingTransactions[listener].count(callbackIds) != 0) {
- sendCallback = false;
+ auto transactionStatsItr = transactionStatsDeque.begin();
+ while (transactionStatsItr != transactionStatsDeque.end()) {
+ auto& transactionStats = *transactionStatsItr;
+
+ // If we are still waiting on the callback handles for this transaction, stop
+ // here because all transaction callbacks for the same listener must come in order
+ if (mPendingTransactions[listener].count(transactionStats.callbackIds) != 0) {
break;
}
// If the transaction has been latched
if (transactionStats.latchTime >= 0) {
if (!mPresentFence) {
- sendCallback = false;
break;
}
transactionStats.presentFence = mPresentFence;
}
+
+ // Remove the transaction from completed to the callback
+ listenerStats.transactionStats.push_back(std::move(transactionStats));
+ transactionStatsItr = transactionStatsDeque.erase(transactionStatsItr);
}
- // If the listener has no pending transactions and all latched transactions have been
- // presented
- if (sendCallback) {
+ // If the listener has completed transactions
+ if (!listenerStats.transactionStats.empty()) {
// If the listener is still alive
- if (listener->isBinderAlive()) {
+ if (IInterface::asBinder(listener)->isBinderAlive()) {
// Send callback
listenerStats.listener->onTransactionCompleted(listenerStats);
- listener->unlinkToDeath(mDeathRecipient);
+ IInterface::asBinder(listener)->unlinkToDeath(mDeathRecipient);
}
- it = mListenerStats.erase(it);
+ completedTransactionsItr = mCompletedTransactions.erase(completedTransactionsItr);
} else {
- it++;
+ completedTransactionsItr++;
}
}
diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h
index f49306d..09feb75 100644
--- a/services/surfaceflinger/TransactionCompletedThread.h
+++ b/services/surfaceflinger/TransactionCompletedThread.h
@@ -30,6 +30,18 @@
namespace android {
+struct CallbackIdsHash {
+ // CallbackId vectors have several properties that let us get away with this simple hash.
+ // 1) CallbackIds are never 0 so if something has gone wrong and our CallbackId vector is
+ // empty we can still hash 0.
+ // 2) CallbackId vectors for the same listener either are identical or contain none of the
+ // same members. It is sufficient to just check the first CallbackId in the vectors. If
+ // they match, they are the same. If they do not match, they are not the same.
+ std::size_t operator()(const std::vector<CallbackId> callbackIds) const {
+ return std::hash<CallbackId>{}((callbackIds.empty()) ? 0 : callbackIds.front());
+ }
+};
+
class CallbackHandle : public RefBase {
public:
CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
@@ -51,18 +63,24 @@
void run();
+ // Adds listener and callbackIds in case there are no SurfaceControls that are supposed
+ // to be included in the callback. This functions should be call before attempting to add any
+ // callback handles.
+ status_t addCallback(const sp<ITransactionCompletedListener>& transactionListener,
+ const std::vector<CallbackId>& callbackIds);
+
// Informs the TransactionCompletedThread that there is a Transaction with a CallbackHandle
// that needs to be latched and presented this frame. This function should be called once the
// layer has received the CallbackHandle so the TransactionCompletedThread knows not to send
// a callback for that Listener/Transaction pair until that CallbackHandle has been latched and
// presented.
- void registerPendingCallbackHandle(const sp<CallbackHandle>& handle);
+ status_t registerPendingCallbackHandle(const sp<CallbackHandle>& handle);
// Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented.
- void addPresentedCallbackHandles(const std::deque<sp<CallbackHandle>>& handles);
+ status_t addPresentedCallbackHandles(const std::deque<sp<CallbackHandle>>& handles);
// Adds the Transaction CallbackHandle from a layer that does not need to be relatched and
// presented this frame.
- void addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle);
+ status_t addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle);
void addPresentFence(const sp<Fence>& presentFence);
@@ -71,7 +89,11 @@
private:
void threadMain();
- void addCallbackHandle(const sp<CallbackHandle>& handle) REQUIRES(mMutex);
+ status_t findTransactionStats(const sp<ITransactionCompletedListener>& listener,
+ const std::vector<CallbackId>& callbackIds,
+ TransactionStats** outTransactionStats) REQUIRES(mMutex);
+
+ status_t addCallbackHandle(const sp<CallbackHandle>& handle) REQUIRES(mMutex);
class ThreadDeathRecipient : public IBinder::DeathRecipient {
public:
@@ -84,9 +106,10 @@
};
sp<ThreadDeathRecipient> mDeathRecipient;
- struct IBinderHash {
- std::size_t operator()(const sp<IBinder>& strongPointer) const {
- return std::hash<IBinder*>{}(strongPointer.get());
+ struct ITransactionCompletedListenerHash {
+ std::size_t operator()(const sp<ITransactionCompletedListener>& listener) const {
+ return std::hash<IBinder*>{}((listener) ? IInterface::asBinder(listener).get()
+ : nullptr);
}
};
@@ -99,12 +122,13 @@
std::condition_variable_any mConditionVariable;
std::unordered_map<
- sp<IBinder /*listener*/>,
+ sp<ITransactionCompletedListener>,
std::unordered_map<std::vector<CallbackId>, uint32_t /*count*/, CallbackIdsHash>,
- IBinderHash>
+ ITransactionCompletedListenerHash>
mPendingTransactions GUARDED_BY(mMutex);
- std::unordered_map<sp<IBinder /*listener*/>, ListenerStats, IBinderHash> mListenerStats
- GUARDED_BY(mMutex);
+ std::unordered_map<sp<ITransactionCompletedListener>, std::deque<TransactionStats>,
+ ITransactionCompletedListenerHash>
+ mCompletedTransactions GUARDED_BY(mMutex);
bool mRunning GUARDED_BY(mMutex) = false;
bool mKeepRunning GUARDED_BY(mMutex) = true;
diff --git a/services/surfaceflinger/sysprop/Android.bp b/services/surfaceflinger/sysprop/Android.bp
new file mode 100644
index 0000000..7721d7d2
--- /dev/null
+++ b/services/surfaceflinger/sysprop/Android.bp
@@ -0,0 +1,6 @@
+sysprop_library {
+ name: "SurfaceFlingerProperties",
+ srcs: ["*.sysprop"],
+ api_packages: ["android.sysprop"],
+ property_owner: "Platform",
+}
diff --git a/services/surfaceflinger/sysprop/api/current.txt b/services/surfaceflinger/sysprop/api/current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/removed.txt b/services/surfaceflinger/sysprop/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/system-current.txt b/services/surfaceflinger/sysprop/api/system-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/system-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/system-removed.txt b/services/surfaceflinger/sysprop/api/system-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/test-current.txt b/services/surfaceflinger/sysprop/api/test-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/test-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/test-removed.txt b/services/surfaceflinger/sysprop/api/test-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/test-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index ea2818d..ef3dfef 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -175,7 +175,6 @@
renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
mock::DispSync* mPrimaryDispSync = new mock::DispSync();
- renderengine::mock::Framebuffer* mReFrameBuffer = new renderengine::mock::Framebuffer();
sp<Fence> mClientTargetAcquireFence = Fence::NO_FENCE;
@@ -312,8 +311,8 @@
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillRepeatedly(
[](const renderengine::DisplaySettings& displaySettings,
- const std::vector<renderengine::LayerSettings>& /*layerSettings*/,
- ANativeWindowBuffer*, base::unique_fd&&, base::unique_fd*) -> status_t {
+ const std::vector<renderengine::LayerSettings>&, ANativeWindowBuffer*,
+ const bool, base::unique_fd&&, base::unique_fd*) -> status_t {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -351,8 +350,8 @@
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillRepeatedly(
[](const renderengine::DisplaySettings& displaySettings,
- const std::vector<renderengine::LayerSettings>& /*layerSettings*/,
- ANativeWindowBuffer*, base::unique_fd&&, base::unique_fd*) -> status_t {
+ const std::vector<renderengine::LayerSettings>&, ANativeWindowBuffer*,
+ const bool, base::unique_fd&&, base::unique_fd*) -> status_t {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -581,7 +580,7 @@
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillOnce([](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>& layerSettings,
- ANativeWindowBuffer*, base::unique_fd&&,
+ ANativeWindowBuffer*, const bool, base::unique_fd&&,
base::unique_fd*) -> status_t {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
@@ -624,7 +623,7 @@
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillOnce([](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>& layerSettings,
- ANativeWindowBuffer*, base::unique_fd&&,
+ ANativeWindowBuffer*, const bool, base::unique_fd&&,
base::unique_fd*) -> status_t {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
@@ -694,7 +693,7 @@
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillOnce([](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>& layerSettings,
- ANativeWindowBuffer*, base::unique_fd&&,
+ ANativeWindowBuffer*, const bool, base::unique_fd&&,
base::unique_fd*) -> status_t {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 406ec81..249c78f 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -38,6 +38,7 @@
constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID = 111;
constexpr PhysicalDisplayId EXTERNAL_DISPLAY_ID = 222;
+constexpr PhysicalDisplayId DISPLAY_ID_64BIT = 0xabcd12349876fedcULL;
class MockVSyncSource : public VSyncSource {
public:
@@ -470,5 +471,10 @@
expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5);
}
+TEST_F(EventThreadTest, postConfigChangedPrimary64bit) {
+ mThread->onConfigChanged(DISPLAY_ID_64BIT, 7);
+ expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7);
+}
+
} // namespace
} // namespace android
diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp
index 4e24a64..afb3004 100644
--- a/services/vr/bufferhubd/Android.bp
+++ b/services/vr/bufferhubd/Android.bp
@@ -44,9 +44,6 @@
static_libs: [
"libbufferhub",
],
-
- // TODO(b/117568153): Temporarily opt out using libcrt.
- no_libcrt: true,
}
cc_binary {
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 206c8eb..71a120a 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -76,6 +76,7 @@
"libhardware",
"libsync",
"libbase",
+ "libdl_android",
"libhidlbase",
"libhidltransport",
"liblog",