Merge "Add support for EGL_EXT_gl_colorspace_bt2020_hlg to libEGL" into udc-dev
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index d73a30b..fb69513 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -93,9 +93,22 @@
libfuzzer_options: [
"max_len=50000",
],
- cc: [
- "smoreland@google.com",
- "waghpawan@google.com",
+ },
+}
+
+// Adding this new fuzzer to test the corpus generated by record_binder
+cc_fuzz {
+ name: "servicemanager_test_fuzzer",
+ defaults: [
+ "servicemanager_defaults",
+ "service_fuzzer_defaults",
+ ],
+ host_supported: true,
+ srcs: ["fuzzers/ServiceManagerTestFuzzer.cpp"],
+ fuzz_config: {
+ libfuzzer_options: [
+ "max_len=50000",
],
},
+ corpus: ["fuzzers/servicemamanager_fuzzer_corpus/*"],
}
diff --git a/cmds/servicemanager/fuzzers/ServiceManagerTestFuzzer.cpp b/cmds/servicemanager/fuzzers/ServiceManagerTestFuzzer.cpp
new file mode 100644
index 0000000..e19b6eb
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/ServiceManagerTestFuzzer.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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 <fuzzbinder/libbinder_driver.h>
+#include <utils/StrongPointer.h>
+
+#include "Access.h"
+#include "ServiceManager.h"
+
+using ::android::Access;
+using ::android::Parcel;
+using ::android::ServiceManager;
+using ::android::sp;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider provider(data, size);
+ auto accessPtr = std::make_unique<Access>();
+ auto serviceManager = sp<ServiceManager>::make(std::move(accessPtr));
+
+ // Reserved bytes
+ provider.ConsumeBytes<uint8_t>(8);
+ uint32_t code = provider.ConsumeIntegral<uint32_t>();
+ uint32_t flag = provider.ConsumeIntegral<uint32_t>();
+ std::vector<uint8_t> parcelData = provider.ConsumeRemainingBytes<uint8_t>();
+
+ Parcel inputParcel;
+ inputParcel.setData(parcelData.data(), parcelData.size());
+
+ Parcel reply;
+ serviceManager->transact(code, inputParcel, &reply, flag);
+
+ serviceManager->clear();
+
+ return 0;
+}
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_1 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_1
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_1
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_10 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_10
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_10
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_11 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_11
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_11
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_12 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_12
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_12
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_13 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_13
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_13
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_14 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_14
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_14
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_15 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_15
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_15
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_16 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_16
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_16
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_17 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_17
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_17
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_18 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_18
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_18
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_19 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_19
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_19
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_2 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_2
new file mode 100644
index 0000000..e69ab49
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_2
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_20 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_20
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_20
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_21 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_21
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_21
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_22 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_22
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_22
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_23 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_23
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_23
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_24 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_24
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_24
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_25 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_25
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_25
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_26 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_26
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_26
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_27 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_27
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_27
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_28 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_28
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_28
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_29 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_29
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_29
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_3 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_3
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_3
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_30 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_30
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_30
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_31 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_31
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_31
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_32 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_32
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_32
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_33 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_33
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_33
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_34 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_34
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_34
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_35 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_35
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_35
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_36 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_36
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_36
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_37 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_37
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_37
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_38 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_38
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_38
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_39 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_39
new file mode 100644
index 0000000..b326907
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_39
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_4 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_4
new file mode 100644
index 0000000..05b27bf
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_4
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_40 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_40
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_40
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_41 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_41
new file mode 100644
index 0000000..b326907
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_41
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_42 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_42
new file mode 100644
index 0000000..cdaa1f0
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_42
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_43 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_43
new file mode 100644
index 0000000..ff0941b
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_43
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_44 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_44
new file mode 100644
index 0000000..cdaa1f0
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_44
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_45 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_45
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_45
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_46 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_46
new file mode 100644
index 0000000..7e5f948
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_46
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_5 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_5
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_5
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_6 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_6
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_6
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_7 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_7
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_7
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_8 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_8
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_8
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_9 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_9
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_9
Binary files differ
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index daeebec..e4ba58a 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -548,11 +548,15 @@
* to the max display brightness. The system may not be able to, or may choose
* not to, deliver the requested range.
*
- * If unspecified, the system will attempt to provide the best range it can
- * for the given ambient conditions & device state. However, voluntarily
- * reducing the requested range can help improve battery life as well as can
- * improve quality by ensuring greater bit depth is allocated to the luminance
- * range in use.
+ * While requesting a large desired ratio will result in the most
+ * dynamic range, voluntarily reducing the requested range can help
+ * improve battery life as well as can improve quality by ensuring
+ * greater bit depth is allocated to the luminance range in use.
+ *
+ * Default value is 1.0f and indicates that extended range brightness
+ * is not being used, so the resulting SDR or HDR behavior will be
+ * determined entirely by the dataspace being used (ie, typically SDR
+ * however PQ or HLG transfer functions will still result in HDR)
*
* Must be finite && >= 1.0f
*
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 46dd62d..c480056 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -689,4 +689,13 @@
return mAngleNamespace;
}
+void GraphicsEnv::nativeToggleAngleAsSystemDriver(bool enabled) {
+ const sp<IGpuService> gpuService = getGpuService();
+ if (!gpuService) {
+ ALOGE("No GPU service");
+ return;
+ }
+ gpuService->toggleAngleAsSystemDriver(enabled);
+}
+
} // namespace android
diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp
index ceb52f7..4c070ae 100644
--- a/libs/graphicsenv/IGpuService.cpp
+++ b/libs/graphicsenv/IGpuService.cpp
@@ -78,6 +78,15 @@
IBinder::FLAG_ONEWAY);
}
+ void toggleAngleAsSystemDriver(bool enabled) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
+ data.writeBool(enabled);
+
+ remote()->transact(BnGpuService::TOGGLE_ANGLE_AS_SYSTEM_DRIVER, data, &reply,
+ IBinder::FLAG_ONEWAY);
+ }
+
std::string getUpdatableDriverPath() override {
Parcel data, reply;
data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
@@ -189,6 +198,15 @@
return OK;
}
+ case TOGGLE_ANGLE_AS_SYSTEM_DRIVER: {
+ CHECK_INTERFACE(IGpuService, data, reply);
+
+ bool enableAngleAsSystemDriver;
+ if ((status = data.readBool(&enableAngleAsSystemDriver)) != OK) return status;
+
+ toggleAngleAsSystemDriver(enableAngleAsSystemDriver);
+ return OK;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index b58a6d9..1274c46 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -142,6 +142,8 @@
const std::string& getDebugLayers();
// Get the debug layers to load.
const std::string& getDebugLayersGLES();
+ // Set the persist.graphics.egl system property value.
+ void nativeToggleAngleAsSystemDriver(bool enabled);
private:
enum UseAngle { UNKNOWN, YES, NO };
diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h
index b708b0f..e3857d2 100644
--- a/libs/graphicsenv/include/graphicsenv/IGpuService.h
+++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h
@@ -50,6 +50,9 @@
// setter and getter for updatable driver path.
virtual void setUpdatableDriverPath(const std::string& driverPath) = 0;
virtual std::string getUpdatableDriverPath() = 0;
+
+ // sets ANGLE as system GLES driver if enabled==true by setting persist.graphics.egl to true.
+ virtual void toggleAngleAsSystemDriver(bool enabled) = 0;
};
class BnGpuService : public BnInterface<IGpuService> {
@@ -59,6 +62,7 @@
SET_TARGET_STATS,
SET_UPDATABLE_DRIVER_PATH,
GET_UPDATABLE_DRIVER_PATH,
+ TOGGLE_ANGLE_AS_SYSTEM_DRIVER,
// Always append new enum to the end.
};
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 7700aa4..eb5cc4f 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -898,7 +898,7 @@
}
void SurfaceComposerClient::Transaction::releaseBufferIfOverwriting(const layer_state_t& state) {
- if (!(state.what & layer_state_t::eBufferChanged)) {
+ if (!(state.what & layer_state_t::eBufferChanged) || !state.bufferData->hasBuffer()) {
return;
}
@@ -1642,28 +1642,25 @@
releaseBufferIfOverwriting(*s);
- if (buffer == nullptr) {
- s->what &= ~layer_state_t::eBufferChanged;
- s->bufferData = nullptr;
- return *this;
- }
-
std::shared_ptr<BufferData> bufferData = std::make_shared<BufferData>();
bufferData->buffer = buffer;
- uint64_t frameNumber = sc->resolveFrameNumber(optFrameNumber);
- bufferData->frameNumber = frameNumber;
- bufferData->producerId = producerId;
- bufferData->flags |= BufferData::BufferDataChange::frameNumberChanged;
- if (fence) {
- bufferData->acquireFence = *fence;
- bufferData->flags |= BufferData::BufferDataChange::fenceChanged;
+ if (buffer) {
+ uint64_t frameNumber = sc->resolveFrameNumber(optFrameNumber);
+ bufferData->frameNumber = frameNumber;
+ bufferData->producerId = producerId;
+ bufferData->flags |= BufferData::BufferDataChange::frameNumberChanged;
+ if (fence) {
+ bufferData->acquireFence = *fence;
+ bufferData->flags |= BufferData::BufferDataChange::fenceChanged;
+ }
+ bufferData->releaseBufferEndpoint =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ setReleaseBufferCallback(bufferData.get(), callback);
}
- bufferData->releaseBufferEndpoint =
- IInterface::asBinder(TransactionCompletedListener::getIInstance());
+
if (mIsAutoTimestamp) {
mDesiredPresentTime = systemTime();
}
- setReleaseBufferCallback(bufferData.get(), callback);
s->what |= layer_state_t::eBufferChanged;
s->bufferData = std::move(bufferData);
registerSurfaceControlForCallback(sc);
@@ -1684,6 +1681,25 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::unsetBuffer(
+ const sp<SurfaceControl>& sc) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+
+ if (!(s->what & layer_state_t::eBufferChanged)) {
+ return *this;
+ }
+
+ releaseBufferIfOverwriting(*s);
+
+ s->what &= ~layer_state_t::eBufferChanged;
+ s->bufferData = nullptr;
+ return *this;
+}
+
void SurfaceComposerClient::Transaction::setReleaseBufferCallback(BufferData* bufferData,
ReleaseBufferCallback callback) {
if (!callback) {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index d431b43..945b164 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -541,6 +541,7 @@
const std::optional<sp<Fence>>& fence = std::nullopt,
const std::optional<uint64_t>& frameNumber = std::nullopt,
uint32_t producerId = 0, ReleaseBufferCallback callback = nullptr);
+ Transaction& unsetBuffer(const sp<SurfaceControl>& sc);
std::shared_ptr<BufferData> getAndClearBuffer(const sp<SurfaceControl>& sc);
/**
diff --git a/libs/gui/include/gui/test/CallbackUtils.h b/libs/gui/include/gui/test/CallbackUtils.h
index 08785b4..1c900e9 100644
--- a/libs/gui/include/gui/test/CallbackUtils.h
+++ b/libs/gui/include/gui/test/CallbackUtils.h
@@ -51,6 +51,7 @@
enum Buffer {
NOT_ACQUIRED = 0,
ACQUIRED,
+ ACQUIRED_NULL,
};
enum PreviousBuffer {
@@ -133,17 +134,28 @@
: mBufferResult(bufferResult), mPreviousBufferResult(previousBufferResult) {}
void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats,
- nsecs_t latchTime) const {
+ nsecs_t /* latchTime */) const {
const auto& [surfaceControl, latch, acquireTimeOrFence, presentFence,
previousReleaseFence, transformHint, frameEvents, ignore] =
- surfaceControlStats;
+ surfaceControlStats;
- ASSERT_TRUE(std::holds_alternative<nsecs_t>(acquireTimeOrFence));
- ASSERT_EQ(std::get<nsecs_t>(acquireTimeOrFence) > 0,
- mBufferResult == ExpectedResult::Buffer::ACQUIRED)
- << "bad acquire time";
- ASSERT_LE(std::get<nsecs_t>(acquireTimeOrFence), latchTime)
- << "acquire time should be <= latch time";
+ nsecs_t acquireTime = -1;
+ if (std::holds_alternative<nsecs_t>(acquireTimeOrFence)) {
+ acquireTime = std::get<nsecs_t>(acquireTimeOrFence);
+ } else {
+ auto fence = std::get<sp<Fence>>(acquireTimeOrFence);
+ if (fence) {
+ ASSERT_EQ(fence->wait(3000), NO_ERROR);
+ acquireTime = fence->getSignalTime();
+ }
+ }
+
+ if (mBufferResult == ExpectedResult::Buffer::ACQUIRED) {
+ ASSERT_GT(acquireTime, 0) << "acquire time should be valid";
+ } else {
+ ASSERT_LE(acquireTime, 0) << "acquire time should not be valid";
+ }
+ ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED);
if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::RELEASED) {
ASSERT_NE(previousReleaseFence, nullptr)
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index aaa8c18..5e7b2e8 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -19,6 +19,7 @@
#include "GpuService.h"
#include <android-base/stringprintf.h>
+#include <android-base/properties.h>
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
#include <binder/Parcel.h>
@@ -46,6 +47,8 @@
} // namespace
const String16 sDump("android.permission.DUMP");
+const String16 sAccessGpuServicePermission("android.permission.ACCESS_GPU_SERVICE");
+const std::string sAngleGlesDriverSuffix = "angle";
const char* const GpuService::SERVICE_NAME = "gpu";
@@ -88,6 +91,29 @@
mGpuStats->insertTargetStatsArray(appPackageName, driverVersionCode, stats, values, valueCount);
}
+void GpuService::toggleAngleAsSystemDriver(bool enabled) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+
+ // only system_server with the ACCESS_GPU_SERVICE permission is allowed to set
+ // persist.graphics.egl
+ if (uid != AID_SYSTEM ||
+ !PermissionCache::checkPermission(sAccessGpuServicePermission, pid, uid)) {
+ ALOGE("Permission Denial: can't set persist.graphics.egl from setAngleAsSystemDriver() "
+ "pid=%d, uid=%d\n", pid, uid);
+ return;
+ }
+
+ std::lock_guard<std::mutex> lock(mLock);
+ if (enabled) {
+ android::base::SetProperty("persist.graphics.egl", sAngleGlesDriverSuffix);
+ } else {
+ android::base::SetProperty("persist.graphics.egl", "");
+ }
+}
+
+
void GpuService::setUpdatableDriverPath(const std::string& driverPath) {
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index e7e0cba..0e559f2 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -61,6 +61,7 @@
const uint64_t* values, const uint32_t valueCount) override;
void setUpdatableDriverPath(const std::string& driverPath) override;
std::string getUpdatableDriverPath() override;
+ void toggleAngleAsSystemDriver(bool enabled) override;
/*
* IBinder interface
diff --git a/services/inputflinger/dispatcher/Connection.cpp b/services/inputflinger/dispatcher/Connection.cpp
index b4497fd..ed95de7 100644
--- a/services/inputflinger/dispatcher/Connection.cpp
+++ b/services/inputflinger/dispatcher/Connection.cpp
@@ -28,8 +28,6 @@
inputPublisher(inputChannel),
inputState(idGenerator) {}
-Connection::~Connection() {}
-
const std::string Connection::getWindowName() const {
if (inputChannel != nullptr) {
return inputChannel->getName();
diff --git a/services/inputflinger/dispatcher/Connection.h b/services/inputflinger/dispatcher/Connection.h
index 6040e9b..2929d61 100644
--- a/services/inputflinger/dispatcher/Connection.h
+++ b/services/inputflinger/dispatcher/Connection.h
@@ -27,10 +27,7 @@
struct DispatchEntry;
/* Manages the dispatch state associated with a single input channel. */
-class Connection : public RefBase {
-protected:
- virtual ~Connection();
-
+class Connection {
public:
enum class Status {
// Everything is peachy.
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index a6d1810..6b9ad44 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -688,7 +688,7 @@
mCommandQueue.clear();
while (!mConnectionsByToken.empty()) {
- sp<Connection> connection = mConnectionsByToken.begin()->second;
+ std::shared_ptr<Connection> connection = mConnectionsByToken.begin()->second;
removeInputChannelLocked(connection->inputChannel->getConnectionToken(), /*notify=*/false);
}
}
@@ -802,7 +802,7 @@
}
// If we reached here, we have an unresponsive connection.
- sp<Connection> connection = getConnectionLocked(mAnrTracker.firstToken());
+ std::shared_ptr<Connection> connection = getConnectionLocked(mAnrTracker.firstToken());
if (connection == nullptr) {
ALOGE("Could not find connection for entry %" PRId64, mAnrTracker.firstTimeout());
return nextAnrCheck;
@@ -815,7 +815,7 @@
}
std::chrono::nanoseconds InputDispatcher::getDispatchingTimeoutLocked(
- const sp<Connection>& connection) {
+ const std::shared_ptr<Connection>& connection) {
if (connection->monitor) {
return mMonitorDispatchingTimeout;
}
@@ -1058,7 +1058,8 @@
const std::vector<sp<WindowInfoHandle>> touchedSpies =
findTouchedSpyWindowsAtLocked(displayId, x, y, isStylus);
for (const auto& windowHandle : touchedSpies) {
- const sp<Connection> connection = getConnectionLocked(windowHandle->getToken());
+ const std::shared_ptr<Connection> connection =
+ getConnectionLocked(windowHandle->getToken());
if (connection != nullptr && connection->responsive) {
// This spy window could take more input. Drop all events preceding this
// event, so that the spy window can get a chance to receive the stream.
@@ -1895,7 +1896,7 @@
pokeUserActivityLocked(*eventEntry);
for (const InputTarget& inputTarget : inputTargets) {
- sp<Connection> connection =
+ std::shared_ptr<Connection> connection =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
@@ -1909,7 +1910,7 @@
}
}
-void InputDispatcher::cancelEventsForAnrLocked(const sp<Connection>& connection) {
+void InputDispatcher::cancelEventsForAnrLocked(const std::shared_ptr<Connection>& connection) {
// We will not be breaking any connections here, even if the policy wants us to abort dispatch.
// If the policy decides to close the app, we will get a channel removal event via
// unregisterInputChannel, and will clean up the connection that way. We are already not
@@ -2101,7 +2102,7 @@
std::vector<Monitor> responsiveMonitors;
std::copy_if(monitors.begin(), monitors.end(), std::back_inserter(responsiveMonitors),
[this](const Monitor& monitor) REQUIRES(mLock) {
- sp<Connection> connection =
+ std::shared_ptr<Connection> connection =
getConnectionLocked(monitor.inputChannel->getConnectionToken());
if (connection == nullptr) {
ALOGE("Could not find connection for monitor %s",
@@ -3027,7 +3028,7 @@
}
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection,
+ const std::shared_ptr<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
if (ATRACE_ENABLED()) {
@@ -3097,7 +3098,7 @@
}
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
- const sp<Connection>& connection,
+ const std::shared_ptr<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
if (ATRACE_ENABLED()) {
@@ -3131,7 +3132,7 @@
}
}
-void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
+void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget,
ftl::Flags<InputTarget::Flags> dispatchMode) {
@@ -3316,14 +3317,14 @@
}
std::unordered_set<sp<IBinder>, StrongPointerHash<IBinder>> newConnectionTokens;
- std::vector<sp<Connection>> newConnections;
+ std::vector<std::shared_ptr<Connection>> newConnections;
for (const InputTarget& target : targets) {
if (target.flags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
continue; // Skip windows that receive ACTION_OUTSIDE
}
sp<IBinder> token = target.inputChannel->getConnectionToken();
- sp<Connection> connection = getConnectionLocked(token);
+ std::shared_ptr<Connection> connection = getConnectionLocked(token);
if (connection == nullptr) {
continue;
}
@@ -3336,7 +3337,7 @@
mInteractionConnectionTokens = newConnectionTokens;
std::string targetList;
- for (const sp<Connection>& connection : newConnections) {
+ for (const std::shared_ptr<Connection>& connection : newConnections) {
targetList += connection->getWindowName() + ", ";
}
std::string message = "Interaction with: " + targetList;
@@ -3416,7 +3417,7 @@
}
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection) {
+ const std::shared_ptr<Connection>& connection) {
if (ATRACE_ENABLED()) {
std::string message = StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
connection->getInputChannelName().c_str());
@@ -3596,8 +3597,8 @@
}
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection, uint32_t seq,
- bool handled, nsecs_t consumeTime) {
+ const std::shared_ptr<Connection>& connection,
+ uint32_t seq, bool handled, nsecs_t consumeTime) {
if (DEBUG_DISPATCH_CYCLE) {
ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
connection->getInputChannelName().c_str(), seq, toString(handled));
@@ -3616,7 +3617,7 @@
}
void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection,
+ const std::shared_ptr<Connection>& connection,
bool notify) {
if (DEBUG_DISPATCH_CYCLE) {
LOG(DEBUG) << "channel '" << connection->getInputChannelName() << "'~ " << __func__
@@ -3665,7 +3666,7 @@
int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) {
std::scoped_lock _l(mLock);
- sp<Connection> connection = getConnectionLocked(connectionToken);
+ std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
if (connection == nullptr) {
ALOGW("Received looper callback for unknown input channel token %p. events=0x%x",
connectionToken.get(), events);
@@ -3757,7 +3758,7 @@
void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
const std::shared_ptr<InputChannel>& channel, const CancelationOptions& options) {
- sp<Connection> connection = getConnectionLocked(channel->getConnectionToken());
+ std::shared_ptr<Connection> connection = getConnectionLocked(channel->getConnectionToken());
if (connection == nullptr) {
return;
}
@@ -3766,7 +3767,7 @@
}
void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
- const sp<Connection>& connection, const CancelationOptions& options) {
+ const std::shared_ptr<Connection>& connection, const CancelationOptions& options) {
if (connection->status == Connection::Status::BROKEN) {
return;
}
@@ -3844,7 +3845,7 @@
}
void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(
- const nsecs_t downTime, const sp<Connection>& connection,
+ const nsecs_t downTime, const std::shared_ptr<Connection>& connection,
ftl::Flags<InputTarget::Flags> targetFlags) {
if (connection->status == Connection::Status::BROKEN) {
return;
@@ -3909,7 +3910,8 @@
void InputDispatcher::synthesizeCancelationEventsForWindowLocked(
const sp<WindowInfoHandle>& windowHandle, const CancelationOptions& options) {
if (windowHandle != nullptr) {
- sp<Connection> wallpaperConnection = getConnectionLocked(windowHandle->getToken());
+ std::shared_ptr<Connection> wallpaperConnection =
+ getConnectionLocked(windowHandle->getToken());
if (wallpaperConnection != nullptr) {
synthesizeCancelationEventsForConnectionLocked(wallpaperConnection, options);
}
@@ -4796,7 +4798,7 @@
return false;
}
- sp<Connection> connection = getConnectionLocked(window->getToken());
+ std::shared_ptr<Connection> connection = getConnectionLocked(window->getToken());
if (connection == nullptr) {
ALOGW("Not sending touch to %s because there's no corresponding connection",
window->getName().c_str());
@@ -5318,8 +5320,8 @@
}
// Synthesize cancel for old window and down for new window.
- sp<Connection> fromConnection = getConnectionLocked(fromToken);
- sp<Connection> toConnection = getConnectionLocked(toToken);
+ std::shared_ptr<Connection> fromConnection = getConnectionLocked(fromToken);
+ std::shared_ptr<Connection> toConnection = getConnectionLocked(toToken);
if (fromConnection != nullptr && toConnection != nullptr) {
fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
CancelationOptions
@@ -5685,8 +5687,9 @@
std::scoped_lock _l(mLock);
const sp<IBinder>& token = serverChannel->getConnectionToken();
int fd = serverChannel->getFd();
- sp<Connection> connection =
- sp<Connection>::make(std::move(serverChannel), /*monitor=*/false, mIdGenerator);
+ std::shared_ptr<Connection> connection =
+ std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/false,
+ mIdGenerator);
if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) {
ALOGE("Created a new connection, but the token %p is already known", token.get());
@@ -5723,8 +5726,8 @@
<< " without a specified display.";
}
- sp<Connection> connection =
- sp<Connection>::make(serverChannel, /*monitor=*/true, mIdGenerator);
+ std::shared_ptr<Connection> connection =
+ std::make_shared<Connection>(serverChannel, /*monitor=*/true, mIdGenerator);
const sp<IBinder>& token = serverChannel->getConnectionToken();
const int fd = serverChannel->getFd();
@@ -5764,7 +5767,7 @@
status_t InputDispatcher::removeInputChannelLocked(const sp<IBinder>& connectionToken,
bool notify) {
- sp<Connection> connection = getConnectionLocked(connectionToken);
+ std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
if (connection == nullptr) {
// Connection can be removed via socket hang up or an explicit call to 'removeInputChannel'
return BAD_VALUE;
@@ -5910,7 +5913,8 @@
return std::nullopt;
}
-sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const {
+std::shared_ptr<Connection> InputDispatcher::getConnectionLocked(
+ const sp<IBinder>& inputConnectionToken) const {
if (inputConnectionToken == nullptr) {
return nullptr;
}
@@ -5925,21 +5929,22 @@
}
std::string InputDispatcher::getConnectionNameLocked(const sp<IBinder>& connectionToken) const {
- sp<Connection> connection = getConnectionLocked(connectionToken);
+ std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
if (connection == nullptr) {
return "<nullptr>";
}
return connection->getInputChannelName();
}
-void InputDispatcher::removeConnectionLocked(const sp<Connection>& connection) {
+void InputDispatcher::removeConnectionLocked(const std::shared_ptr<Connection>& connection) {
mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken());
mConnectionsByToken.erase(connection->inputChannel->getConnectionToken());
}
void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime,
- const sp<Connection>& connection, uint32_t seq,
- bool handled, nsecs_t consumeTime) {
+ const std::shared_ptr<Connection>& connection,
+ uint32_t seq, bool handled,
+ nsecs_t consumeTime) {
// Handle post-event policy actions.
std::deque<DispatchEntry*>::iterator dispatchEntryIt = connection->findWaitQueueEntry(seq);
if (dispatchEntryIt == connection->waitQueue.end()) {
@@ -6017,7 +6022,7 @@
postCommandLocked(std::move(command));
}
-void InputDispatcher::onAnrLocked(const sp<Connection>& connection) {
+void InputDispatcher::onAnrLocked(const std::shared_ptr<Connection>& connection) {
if (connection == nullptr) {
LOG_ALWAYS_FATAL("Caller must check for nullness");
}
@@ -6179,9 +6184,9 @@
sendWindowResponsiveCommandLocked(connectionToken, pid);
}
-bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry,
- KeyEntry& keyEntry, bool handled) {
+bool InputDispatcher::afterKeyEventLockedInterruptable(
+ const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry,
+ KeyEntry& keyEntry, bool handled) {
if (keyEntry.flags & AKEY_EVENT_FLAG_FALLBACK) {
if (!handled) {
// Report the key as unhandled, since the fallback was not handled.
@@ -6356,9 +6361,9 @@
return false;
}
-bool InputDispatcher::afterMotionEventLockedInterruptable(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry,
- MotionEntry& motionEntry, bool handled) {
+bool InputDispatcher::afterMotionEventLockedInterruptable(
+ const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry,
+ MotionEntry& motionEntry, bool handled) {
return false;
}
@@ -6680,9 +6685,11 @@
wallpaperFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED |
InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
state.addOrUpdateWindow(newWallpaper, wallpaperFlags, pointerIds, downTimeInTarget);
- sp<Connection> wallpaperConnection = getConnectionLocked(newWallpaper->getToken());
+ std::shared_ptr<Connection> wallpaperConnection =
+ getConnectionLocked(newWallpaper->getToken());
if (wallpaperConnection != nullptr) {
- sp<Connection> toConnection = getConnectionLocked(toWindowHandle->getToken());
+ std::shared_ptr<Connection> toConnection =
+ getConnectionLocked(toWindowHandle->getToken());
toConnection->inputState.mergePointerStateTo(wallpaperConnection->inputState);
synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, wallpaperConnection,
wallpaperFlags);
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 76b15e2..7aa1a2d 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -249,12 +249,12 @@
sp<android::gui::WindowInfoHandle> findTouchedForegroundWindowLocked(int32_t displayId) const
REQUIRES(mLock);
- sp<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const
+ std::shared_ptr<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const
REQUIRES(mLock);
std::string getConnectionNameLocked(const sp<IBinder>& connectionToken) const REQUIRES(mLock);
- void removeConnectionLocked(const sp<Connection>& connection) REQUIRES(mLock);
+ void removeConnectionLocked(const std::shared_ptr<Connection>& connection) REQUIRES(mLock);
status_t pilferPointersLocked(const sp<IBinder>& token) REQUIRES(mLock);
@@ -264,8 +264,8 @@
};
// All registered connections mapped by input channel token.
- std::unordered_map<sp<IBinder>, sp<Connection>, StrongPointerHash<IBinder>> mConnectionsByToken
- GUARDED_BY(mLock);
+ std::unordered_map<sp<IBinder>, std::shared_ptr<Connection>, StrongPointerHash<IBinder>>
+ mConnectionsByToken GUARDED_BY(mLock);
// Find a monitor pid by the provided token.
std::optional<int32_t> findMonitorPidByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock);
@@ -328,8 +328,8 @@
std::chrono::nanoseconds mMonitorDispatchingTimeout GUARDED_BY(mLock);
nsecs_t processAnrsLocked() REQUIRES(mLock);
- std::chrono::nanoseconds getDispatchingTimeoutLocked(const sp<Connection>& connection)
- REQUIRES(mLock);
+ std::chrono::nanoseconds getDispatchingTimeoutLocked(
+ const std::shared_ptr<Connection>& connection) REQUIRES(mLock);
// Input filter processing.
bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs& args) REQUIRES(mLock);
@@ -533,7 +533,7 @@
// prevent unneeded wakeups.
AnrTracker mAnrTracker GUARDED_BY(mLock);
- void cancelEventsForAnrLocked(const sp<Connection>& connection) REQUIRES(mLock);
+ void cancelEventsForAnrLocked(const std::shared_ptr<Connection>& connection) REQUIRES(mLock);
// If a focused application changes, we should stop counting down the "no focused window" time,
// because we will have no way of knowing when the previous application actually added a window.
// This also means that we will miss cases like pulling down notification shade when the
@@ -594,22 +594,26 @@
// These methods are deliberately not Interruptible because doing all of the work
// with the mutex held makes it easier to ensure that connection invariants are maintained.
// If needed, the methods post commands to run later once the critical bits are done.
- void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
+ void prepareDispatchCycleLocked(nsecs_t currentTime,
+ const std::shared_ptr<Connection>& connection,
std::shared_ptr<EventEntry>, const InputTarget& inputTarget)
REQUIRES(mLock);
- void enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection,
+ void enqueueDispatchEntriesLocked(nsecs_t currentTime,
+ const std::shared_ptr<Connection>& connection,
std::shared_ptr<EventEntry>, const InputTarget& inputTarget)
REQUIRES(mLock);
- void enqueueDispatchEntryLocked(const sp<Connection>& connection, std::shared_ptr<EventEntry>,
- const InputTarget& inputTarget,
+ void enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
+ std::shared_ptr<EventEntry>, const InputTarget& inputTarget,
ftl::Flags<InputTarget::Flags> dispatchMode) REQUIRES(mLock);
status_t publishMotionEvent(Connection& connection, DispatchEntry& dispatchEntry) const;
- void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection)
+ void startDispatchCycleLocked(nsecs_t currentTime,
+ const std::shared_ptr<Connection>& connection) REQUIRES(mLock);
+ void finishDispatchCycleLocked(nsecs_t currentTime,
+ const std::shared_ptr<Connection>& connection, uint32_t seq,
+ bool handled, nsecs_t consumeTime) REQUIRES(mLock);
+ void abortBrokenDispatchCycleLocked(nsecs_t currentTime,
+ const std::shared_ptr<Connection>& connection, bool notify)
REQUIRES(mLock);
- void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
- uint32_t seq, bool handled, nsecs_t consumeTime) REQUIRES(mLock);
- void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
- bool notify) REQUIRES(mLock);
void drainDispatchQueue(std::deque<DispatchEntry*>& queue);
void releaseDispatchEntry(DispatchEntry* dispatchEntry);
int handleReceiveCallback(int events, sp<IBinder> connectionToken);
@@ -624,14 +628,13 @@
void synthesizeCancelationEventsForInputChannelLocked(
const std::shared_ptr<InputChannel>& channel, const CancelationOptions& options)
REQUIRES(mLock);
- void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
- const CancelationOptions& options)
+ void synthesizeCancelationEventsForConnectionLocked(
+ const std::shared_ptr<Connection>& connection, const CancelationOptions& options)
REQUIRES(mLock);
- void synthesizePointerDownEventsForConnectionLocked(const nsecs_t downTime,
- const sp<Connection>& connection,
- ftl::Flags<InputTarget::Flags> targetFlags)
- REQUIRES(mLock);
+ void synthesizePointerDownEventsForConnectionLocked(
+ const nsecs_t downTime, const std::shared_ptr<Connection>& connection,
+ ftl::Flags<InputTarget::Flags> targetFlags) REQUIRES(mLock);
void synthesizeCancelationEventsForWindowLocked(
const sp<android::gui::WindowInfoHandle>& windowHandle,
@@ -658,16 +661,16 @@
REQUIRES(mLock);
// Interesting events that we might like to log or tell the framework about.
- void doDispatchCycleFinishedCommand(nsecs_t finishTime, const sp<Connection>& connection,
- uint32_t seq, bool handled, nsecs_t consumeTime)
- REQUIRES(mLock);
+ void doDispatchCycleFinishedCommand(nsecs_t finishTime,
+ const std::shared_ptr<Connection>& connection, uint32_t seq,
+ bool handled, nsecs_t consumeTime) REQUIRES(mLock);
void doInterceptKeyBeforeDispatchingCommand(const sp<IBinder>& focusedWindowToken,
KeyEntry& entry) REQUIRES(mLock);
void onFocusChangedLocked(const FocusResolver::FocusChanges& changes) REQUIRES(mLock);
void sendFocusChangedCommandLocked(const sp<IBinder>& oldToken, const sp<IBinder>& newToken)
REQUIRES(mLock);
void sendDropWindowCommandLocked(const sp<IBinder>& token, float x, float y) REQUIRES(mLock);
- void onAnrLocked(const sp<Connection>& connection) REQUIRES(mLock);
+ void onAnrLocked(const std::shared_ptr<Connection>& connection) REQUIRES(mLock);
void onAnrLocked(std::shared_ptr<InputApplicationHandle> application) REQUIRES(mLock);
void updateLastAnrStateLocked(const sp<android::gui::WindowInfoHandle>& window,
const std::string& reason) REQUIRES(mLock);
@@ -675,10 +678,10 @@
const std::string& reason) REQUIRES(mLock);
void updateLastAnrStateLocked(const std::string& windowLabel, const std::string& reason)
REQUIRES(mLock);
- bool afterKeyEventLockedInterruptable(const sp<Connection>& connection,
+ bool afterKeyEventLockedInterruptable(const std::shared_ptr<Connection>& connection,
DispatchEntry* dispatchEntry, KeyEntry& keyEntry,
bool handled) REQUIRES(mLock);
- bool afterMotionEventLockedInterruptable(const sp<Connection>& connection,
+ bool afterMotionEventLockedInterruptable(const std::shared_ptr<Connection>& connection,
DispatchEntry* dispatchEntry, MotionEntry& motionEntry,
bool handled) REQUIRES(mLock);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
index 608c53a..ccff1ec 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -19,6 +19,7 @@
#include <optional>
#include <ostream>
#include <unordered_set>
+#include "ui/LayerStack.h"
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
@@ -140,7 +141,7 @@
ClientCompositionTargetSettings&) const = 0;
// Called after the layer is displayed to update the presentation fence
- virtual void onLayerDisplayed(ftl::SharedFuture<FenceResult>) = 0;
+ virtual void onLayerDisplayed(ftl::SharedFuture<FenceResult>, ui::LayerStack layerStack) = 0;
// Gets some kind of identifier for the layer for debug purposes.
virtual const char* getDebugName() const = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
index 12e063b..15e4577 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
@@ -49,7 +49,8 @@
std::optional<compositionengine::LayerFE::LayerSettings>(
compositionengine::LayerFE::ClientCompositionTargetSettings&));
- MOCK_METHOD(void, onLayerDisplayed, (ftl::SharedFuture<FenceResult>), (override));
+ MOCK_METHOD(void, onLayerDisplayed, (ftl::SharedFuture<FenceResult>, ui::LayerStack),
+ (override));
MOCK_CONST_METHOD0(getDebugName, const char*());
MOCK_CONST_METHOD0(getSequence, int32_t());
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index d64231f..793959c 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -1556,8 +1556,9 @@
releaseFence =
Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
}
- layer->getLayerFE().onLayerDisplayed(
- ftl::yield<FenceResult>(std::move(releaseFence)).share());
+ layer->getLayerFE()
+ .onLayerDisplayed(ftl::yield<FenceResult>(std::move(releaseFence)).share(),
+ outputState.layerFilter.layerStack);
}
// We've got a list of layers needing fences, that are disjoint with
@@ -1565,7 +1566,8 @@
// supply them with the present fence.
for (auto& weakLayer : mReleasedLayers) {
if (const auto layer = weakLayer.promote()) {
- layer->onLayerDisplayed(ftl::yield<FenceResult>(frame.presentFence).share());
+ layer->onLayerDisplayed(ftl::yield<FenceResult>(frame.presentFence).share(),
+ outputState.layerFilter.layerStack);
}
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index aaf0f06..9e0e7b5 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -3220,16 +3220,19 @@
// are passed. This happens to work with the current implementation, but
// would not survive certain calls like Fence::merge() which would return a
// new instance.
- EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_))
- .WillOnce([&layer1Fence](ftl::SharedFuture<FenceResult> futureFenceResult) {
+ EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_, _))
+ .WillOnce([&layer1Fence](ftl::SharedFuture<FenceResult> futureFenceResult,
+ ui::LayerStack) {
EXPECT_EQ(FenceResult(layer1Fence), futureFenceResult.get());
});
- EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_))
- .WillOnce([&layer2Fence](ftl::SharedFuture<FenceResult> futureFenceResult) {
+ EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_, _))
+ .WillOnce([&layer2Fence](ftl::SharedFuture<FenceResult> futureFenceResult,
+ ui::LayerStack) {
EXPECT_EQ(FenceResult(layer2Fence), futureFenceResult.get());
});
- EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_))
- .WillOnce([&layer3Fence](ftl::SharedFuture<FenceResult> futureFenceResult) {
+ EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_, _))
+ .WillOnce([&layer3Fence](ftl::SharedFuture<FenceResult> futureFenceResult,
+ ui::LayerStack) {
EXPECT_EQ(FenceResult(layer3Fence), futureFenceResult.get());
});
@@ -3285,16 +3288,19 @@
EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
// Each released layer should be given the presentFence.
- EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_))
- .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult) {
+ EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_, _))
+ .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult,
+ ui::LayerStack) {
EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get());
});
- EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_))
- .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult) {
+ EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_, _))
+ .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult,
+ ui::LayerStack) {
EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get());
});
- EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_))
- .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult) {
+ EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_, _))
+ .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult,
+ ui::LayerStack) {
EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get());
});
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index b397b82..23bb54c 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -130,7 +130,8 @@
void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerState) {
const uint32_t oldFlags = flags;
const half oldAlpha = color.a;
- const bool hadBufferOrSideStream = hasValidBuffer() || sidebandStream != nullptr;
+ const bool hadBuffer = externalTexture != nullptr;
+ const bool hadSideStream = sidebandStream != nullptr;
const layer_state_t& clientState = resolvedComposerState.state;
const bool hadBlur = hasBlur();
uint64_t clientChanges = what | layer_state_t::diff(clientState);
@@ -146,23 +147,32 @@
changes |= RequestedLayerState::Changes::Geometry;
}
}
- if (clientState.what &
- (layer_state_t::eBufferChanged | layer_state_t::eSidebandStreamChanged)) {
- const bool hasBufferOrSideStream = hasValidBuffer() || sidebandStream != nullptr;
- if (hadBufferOrSideStream != hasBufferOrSideStream) {
+ if (clientState.what & layer_state_t::eBufferChanged) {
+ externalTexture = resolvedComposerState.externalTexture;
+ barrierProducerId = std::max(bufferData->producerId, barrierProducerId);
+ barrierFrameNumber = std::max(bufferData->frameNumber, barrierFrameNumber);
+ // TODO(b/277265947) log and flush transaction trace when we detect out of order updates
+
+ const bool hasBuffer = externalTexture != nullptr;
+ if (hasBuffer || hasBuffer != hadBuffer) {
+ changes |= RequestedLayerState::Changes::Buffer;
+ }
+
+ if (hasBuffer != hadBuffer) {
changes |= RequestedLayerState::Changes::Geometry |
RequestedLayerState::Changes::VisibleRegion |
RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Input;
}
}
- if (clientState.what & layer_state_t::eBufferChanged) {
- barrierProducerId = std::max(bufferData->producerId, barrierProducerId);
- barrierFrameNumber = std::max(bufferData->frameNumber, barrierFrameNumber);
- // TODO(b/277265947) log and flush transaction trace when we detect out of order updates
- changes |= RequestedLayerState::Changes::Buffer;
- }
+
if (clientState.what & layer_state_t::eSidebandStreamChanged) {
changes |= RequestedLayerState::Changes::SidebandStream;
+ const bool hasSideStream = sidebandStream != nullptr;
+ if (hasSideStream != hadSideStream) {
+ changes |= RequestedLayerState::Changes::Geometry |
+ RequestedLayerState::Changes::VisibleRegion |
+ RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Input;
+ }
}
if (what & (layer_state_t::eAlphaChanged)) {
if (oldAlpha == 0 || color.a == 0) {
@@ -236,10 +246,6 @@
// TODO(b/238781169) handle callbacks
}
- if (clientState.what & layer_state_t::eBufferChanged) {
- externalTexture = resolvedComposerState.externalTexture;
- }
-
if (clientState.what & layer_state_t::ePositionChanged) {
requestedTransform.set(x, y);
}
@@ -465,6 +471,10 @@
return hasFrameUpdate() && sidebandStream.get();
}
+bool RequestedLayerState::willReleaseBufferOnLatch() const {
+ return changes.test(Changes::Buffer) && !externalTexture;
+}
+
void RequestedLayerState::clearChanges() {
what = 0;
changes.clear();
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index f15f023..0ef50bc 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -79,6 +79,7 @@
bool hasFrameUpdate() const;
bool hasReadyFrame() const;
bool hasSidebandStreamFrame() const;
+ bool willReleaseBufferOnLatch() const;
// Layer serial number. This gives layers an explicit ordering, so we
// have a stable sort order when their layer stack and Z-order are
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 9c232b1..9e40d7f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2795,7 +2795,8 @@
currentMaxAcquiredBufferCount);
}
-void Layer::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult) {
+void Layer::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,
+ ui::LayerStack layerStack) {
// If we are displayed on multiple displays in a single composition cycle then we would
// need to do careful tracking to enable the use of the mLastClientCompositionFence.
// For example we can only use it if all the displays are client comp, and we need
@@ -2825,8 +2826,7 @@
// transaction doesn't need a previous release fence.
sp<CallbackHandle> ch;
for (auto& handle : mDrawingState.callbackHandles) {
- if (handle->releasePreviousBuffer &&
- mDrawingState.releaseBufferEndpoint == handle->listener) {
+ if (handle->releasePreviousBuffer && mPreviousReleaseBufferEndpoint == handle->listener) {
ch = handle;
break;
}
@@ -2842,6 +2842,7 @@
ch->previousReleaseFences.emplace_back(std::move(futureFenceResult));
ch->name = mName;
}
+ mPreviouslyPresentedLayerStacks.push_back(layerStack);
}
void Layer::onSurfaceFrameCreated(
@@ -2880,8 +2881,7 @@
}
for (auto& handle : mDrawingState.callbackHandles) {
- if (handle->releasePreviousBuffer &&
- mDrawingState.releaseBufferEndpoint == handle->listener) {
+ if (handle->releasePreviousBuffer && mPreviousReleaseBufferEndpoint == handle->listener) {
handle->previousReleaseCallbackId = mPreviousReleaseCallbackId;
break;
}
@@ -3018,14 +3018,22 @@
return true;
}
+void Layer::resetDrawingStateBufferInfo() {
+ mDrawingState.producerId = 0;
+ mDrawingState.frameNumber = 0;
+ mDrawingState.releaseBufferListener = nullptr;
+ mDrawingState.buffer = nullptr;
+ mDrawingState.acquireFence = sp<Fence>::make(-1);
+ mDrawingState.acquireFenceTime = std::make_unique<FenceTime>(mDrawingState.acquireFence);
+ mCallbackHandleAcquireTimeOrFence = mDrawingState.acquireFenceTime->getSignalTime();
+ mDrawingState.releaseBufferEndpoint = nullptr;
+}
+
bool Layer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime,
bool isAutoTimestamp, std::optional<nsecs_t> dequeueTime,
const FrameTimelineInfo& info) {
ATRACE_FORMAT("setBuffer %s - hasBuffer=%s", getDebugName(), (buffer ? "true" : "false"));
- if (!buffer) {
- return false;
- }
const bool frameNumberChanged =
bufferData.flags.test(BufferData::BufferDataChange::frameNumberChanged);
@@ -3057,12 +3065,24 @@
mLastClientCompositionFence);
mLastClientCompositionFence = nullptr;
}
- } else {
+ } else if (buffer) {
// if we are latching a buffer for the first time then clear the mLastLatchTime since
// we don't want to incorrectly classify a frame if we miss the desired present time.
updateLastLatchTime(0);
}
+ mDrawingState.desiredPresentTime = desiredPresentTime;
+ mDrawingState.isAutoTimestamp = isAutoTimestamp;
+ mDrawingState.latchedVsyncId = info.vsyncId;
+ mDrawingState.modified = true;
+ if (!buffer) {
+ resetDrawingStateBufferInfo();
+ setTransactionFlags(eTransactionNeeded);
+ mDrawingState.bufferSurfaceFrameTX = nullptr;
+ setFrameTimelineVsyncForBufferlessTransaction(info, postTime);
+ return true;
+ }
+
mDrawingState.producerId = bufferData.producerId;
mDrawingState.barrierProducerId =
std::max(mDrawingState.producerId, mDrawingState.barrierProducerId);
@@ -3073,7 +3093,6 @@
// TODO(b/277265947) log and flush transaction trace when we detect out of order updates
mDrawingState.releaseBufferListener = bufferData.releaseBufferListener;
mDrawingState.buffer = std::move(buffer);
- mDrawingState.clientCacheId = bufferData.cachedBuffer;
mDrawingState.acquireFence = bufferData.flags.test(BufferData::BufferDataChange::fenceChanged)
? bufferData.acquireFence
: Fence::NO_FENCE;
@@ -3086,15 +3105,11 @@
} else {
mCallbackHandleAcquireTimeOrFence = mDrawingState.acquireFenceTime->getSignalTime();
}
- mDrawingState.latchedVsyncId = info.vsyncId;
- mDrawingState.modified = true;
setTransactionFlags(eTransactionNeeded);
const int32_t layerId = getSequence();
mFlinger->mTimeStats->setPostTime(layerId, mDrawingState.frameNumber, getName().c_str(),
mOwnerUid, postTime, getGameMode());
- mDrawingState.desiredPresentTime = desiredPresentTime;
- mDrawingState.isAutoTimestamp = isAutoTimestamp;
if (mFlinger->mLegacyFrontEndEnabled) {
recordLayerHistoryBufferUpdate(getLayerProps());
@@ -3342,7 +3357,7 @@
const State& s(getDrawingState());
if (!s.buffer) {
- if (bgColorOnly) {
+ if (bgColorOnly || mBufferInfo.mBuffer) {
for (auto& handle : mDrawingState.callbackHandles) {
handle->latchTime = latchTime;
}
@@ -3389,12 +3404,19 @@
}
void Layer::gatherBufferInfo() {
- if (!mBufferInfo.mBuffer || !mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer)) {
+ mPreviousReleaseCallbackId = {getCurrentBufferId(), mBufferInfo.mFrameNumber};
+ mPreviousReleaseBufferEndpoint = mBufferInfo.mReleaseBufferEndpoint;
+ if (!mDrawingState.buffer) {
+ mBufferInfo = {};
+ return;
+ }
+
+ if ((!mBufferInfo.mBuffer || !mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer))) {
decrementPendingBufferCount();
}
- mPreviousReleaseCallbackId = {getCurrentBufferId(), mBufferInfo.mFrameNumber};
mBufferInfo.mBuffer = mDrawingState.buffer;
+ mBufferInfo.mReleaseBufferEndpoint = mDrawingState.releaseBufferEndpoint;
mBufferInfo.mFence = mDrawingState.acquireFence;
mBufferInfo.mFrameNumber = mDrawingState.frameNumber;
mBufferInfo.mPixelFormat =
@@ -3924,6 +3946,10 @@
mBufferInfo.mFrameLatencyNeeded = false;
}
+bool Layer::willReleaseBufferOnLatch() const {
+ return !mDrawingState.buffer && mBufferInfo.mBuffer;
+}
+
bool Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
const bool bgColorOnly = mDrawingState.bgColorLayer != nullptr;
return latchBufferImpl(recomputeVisibleRegions, latchTime, bgColorOnly);
@@ -3947,9 +3973,6 @@
return false;
}
updateTexImage(latchTime, bgColorOnly);
- if (mDrawingState.buffer == nullptr) {
- return false;
- }
// Capture the old state of the layer for comparisons later
BufferInfo oldBufferInfo = mBufferInfo;
@@ -3958,6 +3981,18 @@
mCurrentFrameNumber = mDrawingState.frameNumber;
gatherBufferInfo();
+ if (mBufferInfo.mBuffer) {
+ // We latched a buffer that will be presented soon. Clear the previously presented layer
+ // stack list.
+ mPreviouslyPresentedLayerStacks.clear();
+ }
+
+ if (mDrawingState.buffer == nullptr) {
+ const bool bufferReleased = oldBufferInfo.mBuffer != nullptr;
+ recomputeVisibleRegions = bufferReleased;
+ return bufferReleased;
+ }
+
if (oldBufferInfo.mBuffer == nullptr) {
// the first time we receive a buffer, we need to trigger a
// geometry invalidation.
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8d7c362..b37fa15 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -153,7 +153,6 @@
bool transformToDisplayInverse;
Region transparentRegionHint;
std::shared_ptr<renderengine::ExternalTexture> buffer;
- client_cache_t clientCacheId;
sp<Fence> acquireFence;
std::shared_ptr<FenceTime> acquireFenceTime;
HdrMetadata hdrMetadata;
@@ -455,6 +454,12 @@
bool bgColorOnly);
/*
+ * Returns true if the currently presented buffer will be released when this layer state
+ * is latched. This will return false if there is no buffer currently presented.
+ */
+ bool willReleaseBufferOnLatch() const;
+
+ /*
* Calls latchBuffer if the buffer has a frame queued and then releases the buffer.
* This is used if the buffer is just latched and releases to free up the buffer
* and will not be shown on screen.
@@ -536,6 +541,7 @@
std::shared_ptr<renderengine::ExternalTexture> mBuffer;
uint64_t mFrameNumber;
+ sp<IBinder> mReleaseBufferEndpoint;
bool mFrameLatencyNeeded{false};
float mDesiredHdrSdrRatio = 1.f;
@@ -547,7 +553,7 @@
const compositionengine::LayerFECompositionState* getCompositionState() const;
bool fenceHasSignaled() const;
void onPreComposition(nsecs_t refreshStartTime);
- void onLayerDisplayed(ftl::SharedFuture<FenceResult>);
+ void onLayerDisplayed(ftl::SharedFuture<FenceResult>, ui::LayerStack layerStack);
void setWasClientComposed(const sp<Fence>& fence) {
mLastClientCompositionFence = fence;
@@ -900,7 +906,10 @@
void setTransformHint(std::optional<ui::Transform::RotationFlags> transformHint) {
mTransformHint = transformHint;
}
-
+ // Keeps track of the previously presented layer stacks. This is used to get
+ // the release fences from the correct displays when we release the last buffer
+ // from the layer.
+ std::vector<ui::LayerStack> mPreviouslyPresentedLayerStacks;
// Exposed so SurfaceFlinger can assert that it's held
const sp<SurfaceFlinger> mFlinger;
@@ -1177,6 +1186,7 @@
half4 mBorderColor;
void setTransformHintLegacy(ui::Transform::RotationFlags);
+ void resetDrawingStateBufferInfo();
const uint32_t mTextureName;
@@ -1187,6 +1197,7 @@
std::optional<ui::Transform::RotationFlags> mTransformHint = std::nullopt;
ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
+ sp<IBinder> mPreviousReleaseBufferEndpoint;
uint64_t mPreviousReleasedFrameNumber = 0;
uint64_t mPreviousBarrierFrameNumber = 0;
diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp
index b9c8b78..e713263 100644
--- a/services/surfaceflinger/LayerFE.cpp
+++ b/services/surfaceflinger/LayerFE.cpp
@@ -325,8 +325,9 @@
caster.shadow = state;
}
-void LayerFE::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult) {
- mCompositionResult.releaseFences.emplace_back(std::move(futureFenceResult));
+void LayerFE::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,
+ ui::LayerStack layerStack) {
+ mCompositionResult.releaseFences.emplace_back(std::move(futureFenceResult), layerStack);
}
CompositionResult&& LayerFE::stealCompositionResult() {
diff --git a/services/surfaceflinger/LayerFE.h b/services/surfaceflinger/LayerFE.h
index c23bd31..d584fb7 100644
--- a/services/surfaceflinger/LayerFE.h
+++ b/services/surfaceflinger/LayerFE.h
@@ -29,7 +29,7 @@
// TODO(b/238781169) update CE to no longer pass refreshStartTime to LayerFE::onPreComposition
// and remove this field.
nsecs_t refreshStartTime = 0;
- std::vector<ftl::SharedFuture<FenceResult>> releaseFences;
+ std::vector<std::pair<ftl::SharedFuture<FenceResult>, ui::LayerStack>> releaseFences;
sp<Fence> lastClientCompositionFence = nullptr;
};
@@ -40,7 +40,7 @@
// compositionengine::LayerFE overrides
const compositionengine::LayerFECompositionState* getCompositionState() const override;
bool onPreComposition(nsecs_t refreshStartTime, bool updatingOutputGeometryThisFrame) override;
- void onLayerDisplayed(ftl::SharedFuture<FenceResult>) override;
+ void onLayerDisplayed(ftl::SharedFuture<FenceResult>, ui::LayerStack) override;
const char* getDebugName() const override;
int32_t getSequence() const override;
bool hasRoundedCorners() const override;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 3e12db6..63a0173 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -50,8 +50,9 @@
#include "FrontEnd/LayerHandle.h"
#include "OneShotTimer.h"
#include "SurfaceFlingerProperties.h"
-#include "VSyncPredictor.h"
-#include "VSyncReactor.h"
+#include "VSyncTracker.h"
+#include "VsyncController.h"
+#include "VsyncSchedule.h"
#define RETURN_IF_INVALID_HANDLE(handle, ...) \
do { \
@@ -119,14 +120,13 @@
void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
RefreshRateSelectorPtr selectorPtr,
- std::shared_ptr<VsyncSchedule> vsyncSchedule) {
+ VsyncSchedulePtr schedulePtr) {
demotePacesetterDisplay();
std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
{
std::scoped_lock lock(mDisplayLock);
- mRefreshRateSelectors.emplace_or_replace(displayId, std::move(selectorPtr));
- mVsyncSchedules.emplace_or_replace(displayId, std::move(vsyncSchedule));
+ mDisplays.emplace_or_replace(displayId, std::move(selectorPtr), std::move(schedulePtr));
pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
}
@@ -139,13 +139,12 @@
std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
{
std::scoped_lock lock(mDisplayLock);
- mRefreshRateSelectors.erase(displayId);
- mVsyncSchedules.erase(displayId);
+ mDisplays.erase(displayId);
// Do not allow removing the final display. Code in the scheduler expects
// there to be at least one display. (This may be relaxed in the future with
// headless virtual display.)
- LOG_ALWAYS_FATAL_IF(mRefreshRateSelectors.empty(), "Cannot unregister all displays!");
+ LOG_ALWAYS_FATAL_IF(mDisplays.empty(), "Cannot unregister all displays!");
pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
}
@@ -199,20 +198,27 @@
impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
return [this](uid_t uid) {
- const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().fps;
- const nsecs_t currentPeriod =
- getVsyncSchedule()->period().ns() ?: refreshRate.getPeriodNsecs();
+ const auto [refreshRate, period] = [this] {
+ std::scoped_lock lock(mDisplayLock);
+ const auto pacesetterOpt = pacesetterDisplayLocked();
+ LOG_ALWAYS_FATAL_IF(!pacesetterOpt);
+ const Display& pacesetter = *pacesetterOpt;
+ return std::make_pair(pacesetter.selectorPtr->getActiveMode().fps,
+ pacesetter.schedulePtr->period());
+ }();
+
+ const Period currentPeriod = period != Period::zero() ? period : refreshRate.getPeriod();
const auto frameRate = getFrameRateOverride(uid);
if (!frameRate.has_value()) {
- return currentPeriod;
+ return currentPeriod.ns();
}
const auto divisor = RefreshRateSelector::getFrameRateDivisor(refreshRate, *frameRate);
if (divisor <= 1) {
- return currentPeriod;
+ return currentPeriod.ns();
}
- return currentPeriod * divisor;
+ return currentPeriod.ns() * divisor;
};
}
@@ -413,23 +419,24 @@
std::scoped_lock lock(mDisplayLock);
ftl::FakeGuard guard(kMainThreadContext);
- for (const auto& [id, _] : mRefreshRateSelectors) {
+ for (const auto& [id, _] : mDisplays) {
resyncToHardwareVsyncLocked(id, allowToEnable);
}
}
void Scheduler::resyncToHardwareVsyncLocked(PhysicalDisplayId id, bool allowToEnable,
std::optional<Fps> refreshRate) {
- auto schedule = getVsyncScheduleLocked(id);
- if (schedule->isHardwareVsyncAllowed(allowToEnable)) {
+ const auto displayOpt = mDisplays.get(id);
+ LOG_ALWAYS_FATAL_IF(!displayOpt);
+ const Display& display = *displayOpt;
+
+ if (display.schedulePtr->isHardwareVsyncAllowed(allowToEnable)) {
if (!refreshRate) {
- auto selectorPtr = mRefreshRateSelectors.get(id);
- LOG_ALWAYS_FATAL_IF(!selectorPtr);
- refreshRate = selectorPtr->get()->getActiveMode().modePtr->getFps();
+ refreshRate = display.selectorPtr->getActiveMode().modePtr->getFps();
}
if (refreshRate->isValid()) {
- schedule->startPeriodTransition(mSchedulerCallback, refreshRate->getPeriod(),
- false /* force */);
+ display.schedulePtr->startPeriodTransition(mSchedulerCallback, refreshRate->getPeriod(),
+ false /* force */);
}
}
}
@@ -438,9 +445,10 @@
std::scoped_lock lock(mDisplayLock);
ftl::FakeGuard guard(kMainThreadContext);
- auto selectorPtr = mRefreshRateSelectors.get(id);
- LOG_ALWAYS_FATAL_IF(!selectorPtr);
- const auto mode = selectorPtr->get()->getActiveMode();
+ const auto displayOpt = mDisplays.get(id);
+ LOG_ALWAYS_FATAL_IF(!displayOpt);
+ const Display& display = *displayOpt;
+ const auto mode = display.selectorPtr->getActiveMode();
using fps_approx_ops::operator!=;
LOG_ALWAYS_FATAL_IF(renderFrameRate != mode.fps,
@@ -451,7 +459,7 @@
ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(),
to_string(mode.modePtr->getFps()).c_str());
- getVsyncScheduleLocked(id)->getTracker().setRenderRate(renderFrameRate);
+ display.schedulePtr->getTracker().setRenderRate(renderFrameRate);
}
void Scheduler::resync() {
@@ -558,22 +566,24 @@
mLayerHistory.clear();
}
-std::shared_ptr<const VsyncSchedule> Scheduler::getVsyncSchedule(
- std::optional<PhysicalDisplayId> idOpt) const {
+auto Scheduler::getVsyncSchedule(std::optional<PhysicalDisplayId> idOpt) const
+ -> ConstVsyncSchedulePtr {
std::scoped_lock lock(mDisplayLock);
return getVsyncScheduleLocked(idOpt);
}
-std::shared_ptr<const VsyncSchedule> Scheduler::getVsyncScheduleLocked(
- std::optional<PhysicalDisplayId> idOpt) const {
+auto Scheduler::getVsyncScheduleLocked(std::optional<PhysicalDisplayId> idOpt) const
+ -> ConstVsyncSchedulePtr {
ftl::FakeGuard guard(kMainThreadContext);
+
if (!idOpt) {
LOG_ALWAYS_FATAL_IF(!mPacesetterDisplayId, "Missing a pacesetter!");
idOpt = mPacesetterDisplayId;
}
- auto scheduleOpt = mVsyncSchedules.get(*idOpt);
- LOG_ALWAYS_FATAL_IF(!scheduleOpt);
- return std::const_pointer_cast<const VsyncSchedule>(scheduleOpt->get());
+
+ const auto displayOpt = mDisplays.get(*idOpt);
+ LOG_ALWAYS_FATAL_IF(!displayOpt);
+ return displayOpt->get().schedulePtr;
}
void Scheduler::kernelIdleTimerCallback(TimerState state) {
@@ -597,9 +607,9 @@
// need to update the VsyncController model anyway.
std::scoped_lock lock(mDisplayLock);
ftl::FakeGuard guard(kMainThreadContext);
- constexpr bool disallow = false;
- for (auto& [_, schedule] : mVsyncSchedules) {
- schedule->disableHardwareVsync(mSchedulerCallback, disallow);
+ for (const auto& [_, display] : mDisplays) {
+ constexpr bool kDisallow = false;
+ display.schedulePtr->disableHardwareVsync(mSchedulerCallback, kDisallow);
}
}
@@ -664,12 +674,12 @@
to_string(*mPacesetterDisplayId).c_str());
getVsyncScheduleLocked()->dump(out);
}
- for (auto& [id, vsyncSchedule] : mVsyncSchedules) {
+ for (auto& [id, display] : mDisplays) {
if (id == mPacesetterDisplayId) {
continue;
}
base::StringAppendF(&out, "VsyncSchedule for follower %s:\n", to_string(id).c_str());
- vsyncSchedule->dump(out);
+ display.schedulePtr->dump(out);
}
}
@@ -699,25 +709,29 @@
std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked(
std::optional<PhysicalDisplayId> pacesetterIdOpt) {
// TODO(b/241286431): Choose the pacesetter display.
- mPacesetterDisplayId = pacesetterIdOpt.value_or(mRefreshRateSelectors.begin()->first);
+ mPacesetterDisplayId = pacesetterIdOpt.value_or(mDisplays.begin()->first);
ALOGI("Display %s is the pacesetter", to_string(*mPacesetterDisplayId).c_str());
- auto vsyncSchedule = getVsyncScheduleLocked(*mPacesetterDisplayId);
- if (const auto pacesetterPtr = pacesetterSelectorPtrLocked()) {
- pacesetterPtr->setIdleTimerCallbacks(
+ std::shared_ptr<VsyncSchedule> newVsyncSchedulePtr;
+ if (const auto pacesetterOpt = pacesetterDisplayLocked()) {
+ const Display& pacesetter = *pacesetterOpt;
+
+ pacesetter.selectorPtr->setIdleTimerCallbacks(
{.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
.onExpired = [this] { idleTimerCallback(TimerState::Expired); }},
.kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); },
.onExpired =
[this] { kernelIdleTimerCallback(TimerState::Expired); }}});
- pacesetterPtr->startIdleTimer();
+ pacesetter.selectorPtr->startIdleTimer();
- const Fps refreshRate = pacesetterPtr->getActiveMode().modePtr->getFps();
- vsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(),
- true /* force */);
+ newVsyncSchedulePtr = pacesetter.schedulePtr;
+
+ const Fps refreshRate = pacesetter.selectorPtr->getActiveMode().modePtr->getFps();
+ newVsyncSchedulePtr->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(),
+ true /* force */);
}
- return vsyncSchedule;
+ return newVsyncSchedulePtr;
}
void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule) {
@@ -831,9 +845,10 @@
const auto globalSignals = makeGlobalSignals();
- for (const auto& [id, selectorPtr] : mRefreshRateSelectors) {
+ for (const auto& [id, display] : mDisplays) {
auto rankedFrameRates =
- selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals);
+ display.selectorPtr->getRankedFrameRates(mPolicy.contentRequirements,
+ globalSignals);
for (const auto& [frameRateMode, score] : rankedFrameRates.ranking) {
const auto [it, inserted] = refreshRateTallies.try_emplace(frameRateMode.fps, score);
@@ -852,7 +867,7 @@
// Find the first refresh rate common to all displays.
while (maxScoreIt != refreshRateTallies.cend() &&
- maxScoreIt->second.displayCount != mRefreshRateSelectors.size()) {
+ maxScoreIt->second.displayCount != mDisplays.size()) {
++maxScoreIt;
}
@@ -861,8 +876,7 @@
for (auto it = maxScoreIt + 1; it != refreshRateTallies.cend(); ++it) {
const auto [fps, tally] = *it;
- if (tally.displayCount == mRefreshRateSelectors.size() &&
- tally.score > maxScoreIt->second.score) {
+ if (tally.displayCount == mDisplays.size() && tally.score > maxScoreIt->second.score) {
maxScoreIt = it;
}
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 1f6d378..43aab2d 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -32,7 +32,6 @@
#include <ui/GraphicTypes.h>
#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
-#include <ftl/algorithm.h>
#include <ftl/fake_guard.h>
#include <ftl/optional.h>
#include <scheduler/Features.h>
@@ -51,7 +50,6 @@
#include "RefreshRateSelector.h"
#include "Utils/Dumper.h"
#include "VsyncModulator.h"
-#include "VsyncSchedule.h"
namespace android::scheduler {
@@ -94,6 +92,8 @@
using GlobalSignals = RefreshRateSelector::GlobalSignals;
+class VsyncSchedule;
+
class Scheduler : android::impl::MessageQueue {
using Impl = android::impl::MessageQueue;
@@ -109,6 +109,9 @@
using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>;
+ using ConstVsyncSchedulePtr = std::shared_ptr<const VsyncSchedule>;
+ using VsyncSchedulePtr = std::shared_ptr<VsyncSchedule>;
+
void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr) REQUIRES(kMainThreadContext)
EXCLUDES(mDisplayLock);
void unregisterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
@@ -237,12 +240,12 @@
void setDisplayPowerMode(PhysicalDisplayId, hal::PowerMode powerMode)
REQUIRES(kMainThreadContext);
- std::shared_ptr<const VsyncSchedule> getVsyncSchedule(
- std::optional<PhysicalDisplayId> idOpt = std::nullopt) const EXCLUDES(mDisplayLock);
- std::shared_ptr<VsyncSchedule> getVsyncSchedule(
- std::optional<PhysicalDisplayId> idOpt = std::nullopt) EXCLUDES(mDisplayLock) {
- return std::const_pointer_cast<VsyncSchedule>(
- static_cast<const Scheduler*>(this)->getVsyncSchedule(idOpt));
+ ConstVsyncSchedulePtr getVsyncSchedule(std::optional<PhysicalDisplayId> = std::nullopt) const
+ EXCLUDES(mDisplayLock);
+
+ VsyncSchedulePtr getVsyncSchedule(std::optional<PhysicalDisplayId> idOpt = std::nullopt)
+ EXCLUDES(mDisplayLock) {
+ return std::const_pointer_cast<VsyncSchedule>(std::as_const(*this).getVsyncSchedule(idOpt));
}
// Returns true if a given vsync timestamp is considered valid vsync
@@ -339,9 +342,8 @@
// the caller on the main thread to avoid deadlock, since the timer thread locks it before exit.
void demotePacesetterDisplay() REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock, mPolicyLock);
- void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr,
- std::shared_ptr<VsyncSchedule>) REQUIRES(kMainThreadContext)
- EXCLUDES(mDisplayLock);
+ void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr, VsyncSchedulePtr)
+ REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
struct Policy;
@@ -420,16 +422,37 @@
// must lock for writes but not reads. See also mPolicyLock for locking order.
mutable std::mutex mDisplayLock;
- display::PhysicalDisplayMap<PhysicalDisplayId, RefreshRateSelectorPtr> mRefreshRateSelectors
- GUARDED_BY(mDisplayLock) GUARDED_BY(kMainThreadContext);
+ struct Display {
+ Display(RefreshRateSelectorPtr selectorPtr, VsyncSchedulePtr schedulePtr)
+ : selectorPtr(std::move(selectorPtr)), schedulePtr(std::move(schedulePtr)) {}
- // TODO (b/266715559): Store in the same map as mRefreshRateSelectors.
- display::PhysicalDisplayMap<PhysicalDisplayId, std::shared_ptr<VsyncSchedule>> mVsyncSchedules
- GUARDED_BY(mDisplayLock) GUARDED_BY(kMainThreadContext);
+ // Effectively const except in move constructor.
+ RefreshRateSelectorPtr selectorPtr;
+ VsyncSchedulePtr schedulePtr;
+ };
+
+ using DisplayRef = std::reference_wrapper<Display>;
+ using ConstDisplayRef = std::reference_wrapper<const Display>;
+
+ display::PhysicalDisplayMap<PhysicalDisplayId, Display> mDisplays GUARDED_BY(mDisplayLock)
+ GUARDED_BY(kMainThreadContext);
ftl::Optional<PhysicalDisplayId> mPacesetterDisplayId GUARDED_BY(mDisplayLock)
GUARDED_BY(kMainThreadContext);
+ ftl::Optional<DisplayRef> pacesetterDisplayLocked() REQUIRES(mDisplayLock) {
+ return static_cast<const Scheduler*>(this)->pacesetterDisplayLocked().transform(
+ [](const Display& display) { return std::ref(const_cast<Display&>(display)); });
+ }
+
+ ftl::Optional<ConstDisplayRef> pacesetterDisplayLocked() const REQUIRES(mDisplayLock) {
+ ftl::FakeGuard guard(kMainThreadContext);
+ return mPacesetterDisplayId.and_then([this](PhysicalDisplayId pacesetterId)
+ REQUIRES(mDisplayLock, kMainThreadContext) {
+ return mDisplays.get(pacesetterId);
+ });
+ }
+
RefreshRateSelectorPtr pacesetterSelectorPtr() const EXCLUDES(mDisplayLock) {
std::scoped_lock lock(mDisplayLock);
return pacesetterSelectorPtrLocked();
@@ -437,19 +460,17 @@
RefreshRateSelectorPtr pacesetterSelectorPtrLocked() const REQUIRES(mDisplayLock) {
ftl::FakeGuard guard(kMainThreadContext);
- return mPacesetterDisplayId
- .and_then([this](PhysicalDisplayId pacesetterId)
- REQUIRES(mDisplayLock, kMainThreadContext) {
- return mRefreshRateSelectors.get(pacesetterId);
- })
- .or_else(ftl::static_ref<RefreshRateSelectorPtr>([] { return nullptr; }))
+ return pacesetterDisplayLocked()
+ .transform([](const Display& display) { return display.selectorPtr; })
+ .or_else([] { return std::optional<RefreshRateSelectorPtr>(nullptr); })
.value();
}
- std::shared_ptr<const VsyncSchedule> getVsyncScheduleLocked(
- std::optional<PhysicalDisplayId> idOpt = std::nullopt) const REQUIRES(mDisplayLock);
- std::shared_ptr<VsyncSchedule> getVsyncScheduleLocked(
- std::optional<PhysicalDisplayId> idOpt = std::nullopt) REQUIRES(mDisplayLock) {
+ ConstVsyncSchedulePtr getVsyncScheduleLocked(
+ std::optional<PhysicalDisplayId> = std::nullopt) const REQUIRES(mDisplayLock);
+
+ VsyncSchedulePtr getVsyncScheduleLocked(std::optional<PhysicalDisplayId> idOpt = std::nullopt)
+ REQUIRES(mDisplayLock) {
return std::const_pointer_cast<VsyncSchedule>(
static_cast<const Scheduler*>(this)->getVsyncScheduleLocked(idOpt));
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a6f4630..48b4144 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2303,13 +2303,17 @@
std::make_optional(layer->parentId), true));
mLegacyLayers[bgColorLayer->sequence] = bgColorLayer;
}
- if (!layer->hasReadyFrame()) continue;
+ const bool willReleaseBufferOnLatch = layer->willReleaseBufferOnLatch();
+ if (!layer->hasReadyFrame() && !willReleaseBufferOnLatch) continue;
auto it = mLegacyLayers.find(layer->id);
LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), "Couldnt find layer object for %s",
layer->getDebugString().c_str());
const bool bgColorOnly =
!layer->externalTexture && (layer->bgColorLayerId != UNASSIGNED_LAYER_ID);
+ if (willReleaseBufferOnLatch) {
+ mLayersWithBuffersRemoved.emplace(it->second);
+ }
it->second->latchBufferImpl(unused, latchTime, bgColorOnly);
mLayersWithQueuedFrames.emplace(it->second);
}
@@ -2644,10 +2648,10 @@
for (auto [layer, layerFE] : layers) {
CompositionResult compositionResult{layerFE->stealCompositionResult()};
layer->onPreComposition(compositionResult.refreshStartTime);
- for (auto releaseFence : compositionResult.releaseFences) {
+ for (auto& [releaseFence, layerStack] : compositionResult.releaseFences) {
Layer* clonedFrom = layer->getClonedFrom().get();
auto owningLayer = clonedFrom ? clonedFrom : layer;
- owningLayer->onLayerDisplayed(releaseFence);
+ owningLayer->onLayerDisplayed(std::move(releaseFence), layerStack);
}
if (compositionResult.lastClientCompositionFence) {
layer->setWasClientComposed(compositionResult.lastClientCompositionFence);
@@ -2858,6 +2862,29 @@
const CompositorTiming compositorTiming(vsyncDeadline.ns(), vsyncPeriod.ns(), vsyncPhase,
presentLatency.ns());
+ display::DisplayMap<ui::LayerStack, const DisplayDevice*> layerStackToDisplay;
+ {
+ if (!mLayersWithBuffersRemoved.empty() || mNumTrustedPresentationListeners > 0) {
+ Mutex::Autolock lock(mStateLock);
+ for (const auto& [token, display] : mDisplays) {
+ layerStackToDisplay.emplace_or_replace(display->getLayerStack(), display.get());
+ }
+ }
+ }
+
+ for (auto layer : mLayersWithBuffersRemoved) {
+ for (auto layerStack : layer->mPreviouslyPresentedLayerStacks) {
+ auto optDisplay = layerStackToDisplay.get(layerStack);
+ if (optDisplay && !optDisplay->get()->isVirtual()) {
+ auto fence = getHwComposer().getPresentFence(optDisplay->get()->getPhysicalId());
+ layer->onLayerDisplayed(ftl::yield<FenceResult>(fence).share(),
+ ui::INVALID_LAYER_STACK);
+ }
+ }
+ layer->releasePendingBuffer(presentTime.ns());
+ }
+ mLayersWithBuffersRemoved.clear();
+
for (const auto& layer: mLayersWithQueuedFrames) {
layer->onPostComposition(defaultDisplay, glCompositionDoneFenceTime, presentFenceTime,
compositorTiming);
@@ -2984,14 +3011,6 @@
}
if (mNumTrustedPresentationListeners > 0) {
- display::DisplayMap<ui::LayerStack, const DisplayDevice*> layerStackToDisplay;
- {
- Mutex::Autolock lock(mStateLock);
- for (const auto& [token, display] : mDisplays) {
- layerStackToDisplay.emplace_or_replace(display->getLayerStack(), display.get());
- }
- }
-
// We avoid any reverse traversal upwards so this shouldn't be too expensive
traverseLegacyLayers([&](Layer* layer) {
if (!layer->hasTrustedPresentationListener()) {
@@ -4039,7 +4058,7 @@
}
}
- if (layer->hasReadyFrame()) {
+ if (layer->hasReadyFrame() || layer->willReleaseBufferOnLatch()) {
frameQueued = true;
mLayersWithQueuedFrames.emplace(sp<Layer>::fromExisting(layer));
} else {
@@ -4070,6 +4089,9 @@
Mutex::Autolock lock(mStateLock);
for (const auto& layer : mLayersWithQueuedFrames) {
+ if (layer->willReleaseBufferOnLatch()) {
+ mLayersWithBuffersRemoved.emplace(layer);
+ }
if (layer->latchBuffer(visibleRegions, latchTime)) {
mLayersPendingRefresh.push_back(layer);
newDataLatched = true;
@@ -5069,7 +5091,8 @@
}
if (layer->setTransactionCompletedListeners(callbackHandles,
- layer->willPresentCurrentTransaction())) {
+ layer->willPresentCurrentTransaction() ||
+ layer->willReleaseBufferOnLatch())) {
flags |= eTraversalNeeded;
}
@@ -5183,8 +5206,9 @@
}
const auto& requestedLayerState = mLayerLifecycleManager.getLayerFromId(layer->getSequence());
- bool willPresentCurrentTransaction =
- requestedLayerState && requestedLayerState->hasReadyFrame();
+ bool willPresentCurrentTransaction = requestedLayerState &&
+ (requestedLayerState->hasReadyFrame() ||
+ requestedLayerState->willReleaseBufferOnLatch());
if (layer->setTransactionCompletedListeners(callbackHandles, willPresentCurrentTransaction))
flags |= eTraversalNeeded;
@@ -5847,8 +5871,8 @@
return layersProto;
}
- return LayerProtoFromSnapshotGenerator(mLayerSnapshotBuilder, mFrontEndDisplayInfos, {},
- traceFlags)
+ return LayerProtoFromSnapshotGenerator(mLayerSnapshotBuilder, mFrontEndDisplayInfos,
+ mLegacyLayers, traceFlags)
.generate(mLayerHierarchyBuilder.getHierarchy());
}
@@ -7380,12 +7404,14 @@
: ftl::yield(present()).share();
for (auto& [layer, layerFE] : layers) {
- layer->onLayerDisplayed(
- ftl::Future(presentFuture)
- .then([layerFE = std::move(layerFE)](FenceResult) {
- return layerFE->stealCompositionResult().releaseFences.back().get();
- })
- .share());
+ layer->onLayerDisplayed(ftl::Future(presentFuture)
+ .then([layerFE = std::move(layerFE)](FenceResult) {
+ return layerFE->stealCompositionResult()
+ .releaseFences.back()
+ .first.get();
+ })
+ .share(),
+ ui::INVALID_LAYER_STACK);
}
return presentFuture;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 04fcfb9..fffd63a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1193,6 +1193,7 @@
// Tracks layers that have pending frames which are candidates for being
// latched.
std::unordered_set<sp<Layer>, SpHash<Layer>> mLayersWithQueuedFrames;
+ std::unordered_set<sp<Layer>, SpHash<Layer>> mLayersWithBuffersRemoved;
// Tracks layers that need to update a display's dirty region.
std::vector<sp<Layer>> mLayersPendingRefresh;
diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h
index 2daea25..35c8b6c 100644
--- a/services/surfaceflinger/TransactionState.h
+++ b/services/surfaceflinger/TransactionState.h
@@ -78,8 +78,7 @@
template <typename Visitor>
void traverseStatesWithBuffers(Visitor&& visitor) const {
for (const auto& state : states) {
- if (state.state.hasBufferChanges() && state.state.hasValidBuffer() &&
- state.state.surface) {
+ if (state.state.hasBufferChanges() && state.externalTexture && state.state.surface) {
visitor(state.state);
}
}
@@ -88,8 +87,7 @@
template <typename Visitor>
void traverseStatesWithBuffersWhileTrue(Visitor&& visitor) {
for (auto state = states.begin(); state != states.end();) {
- if (state->state.hasBufferChanges() && state->state.hasValidBuffer() &&
- state->state.surface) {
+ if (state->state.hasBufferChanges() && state->externalTexture && state->state.surface) {
int result = visitor(state->state, state->externalTexture);
if (result == STOP_TRAVERSAL) return;
if (result == DELETE_AND_CONTINUE_TRAVERSAL) {
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
index 4304259..c3dcb85 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
@@ -125,9 +125,12 @@
mFdp.ConsumeIntegral<int64_t>(),
mFdp.ConsumeIntegral<int64_t>());
- layer->onLayerDisplayed(ftl::yield<FenceResult>(fence).share());
- layer->onLayerDisplayed(
- ftl::yield<FenceResult>(base::unexpected(mFdp.ConsumeIntegral<status_t>())).share());
+ layer->onLayerDisplayed(ftl::yield<FenceResult>(fence).share(),
+ ui::LayerStack::fromValue(mFdp.ConsumeIntegral<uint32_t>()));
+ layer->onLayerDisplayed(ftl::yield<FenceResult>(
+ base::unexpected(mFdp.ConsumeIntegral<status_t>()))
+ .share(),
+ ui::LayerStack::fromValue(mFdp.ConsumeIntegral<uint32_t>()));
layer->releasePendingBuffer(mFdp.ConsumeIntegral<int64_t>());
layer->onPostComposition(nullptr, fenceTime, fenceTime, compositorTiming);
diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp
index 26dbc76..79886bd 100644
--- a/services/surfaceflinger/tests/LayerCallback_test.cpp
+++ b/services/surfaceflinger/tests/LayerCallback_test.cpp
@@ -1224,4 +1224,75 @@
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
}
+TEST_F(LayerCallbackTest, SetNullBuffer) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer, /*setBuffer=*/true,
+ /*setBackgroundColor=*/false);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ transaction.apply();
+
+ {
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+ ExpectedResult::Buffer::ACQUIRED,
+ ExpectedResult::PreviousBuffer::NOT_RELEASED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+ }
+
+ transaction.setBuffer(layer, nullptr);
+ transaction.addTransactionCompletedCallback(callback.function, callback.getContext());
+ transaction.apply();
+
+ {
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+ ExpectedResult::Buffer::ACQUIRED_NULL,
+ ExpectedResult::PreviousBuffer::RELEASED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+ }
+
+ err = fillTransaction(transaction, &callback, layer, /*setBuffer=*/true,
+ /*setBackgroundColor=*/false);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.apply();
+
+ {
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+ ExpectedResult::Buffer::ACQUIRED,
+ ExpectedResult::PreviousBuffer::NOT_RELEASED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+ }
+}
+
+TEST_F(LayerCallbackTest, SetNullBufferOnLayerWithoutBuffer) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
+
+ Transaction transaction;
+ transaction.setBuffer(layer, nullptr);
+ CallbackHelper callback;
+ transaction.addTransactionCompletedCallback(callback.function, callback.getContext());
+ transaction.apply();
+
+ {
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
+ ExpectedResult::Buffer::NOT_ACQUIRED,
+ ExpectedResult::PreviousBuffer::NOT_RELEASED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+ }
+}
+
} // namespace android
diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
index 0b8c51e..b8068f7 100644
--- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
@@ -1636,6 +1636,65 @@
getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance);
}
}
+
+TEST_P(LayerRenderTypeTransactionTest, SetNullBuffer) {
+ const Rect bounds(0, 0, 32, 32);
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ sp<GraphicBuffer>::make(32u, 32u, PIXEL_FORMAT_RGBA_8888, 1u, kUsageFlags, "test");
+
+ ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, bounds, Color::GREEN));
+ Transaction().setBuffer(layer, buffer).apply();
+ {
+ SCOPED_TRACE("before null buffer");
+ auto shot = getScreenCapture();
+ shot->expectColor(bounds, Color::GREEN);
+ }
+
+ Transaction().setBuffer(layer, nullptr).apply();
+ {
+ SCOPED_TRACE("null buffer removes buffer");
+ auto shot = getScreenCapture();
+ shot->expectColor(bounds, Color::BLACK);
+ }
+
+ Transaction().setBuffer(layer, buffer).apply();
+ {
+ SCOPED_TRACE("after null buffer");
+ auto shot = getScreenCapture();
+ shot->expectColor(bounds, Color::GREEN);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetNullBufferOnLayerWithoutBuffer) {
+ const Rect bounds(0, 0, 32, 32);
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ {
+ SCOPED_TRACE("starting state");
+ auto shot = getScreenCapture();
+ shot->expectColor(bounds, Color::BLACK);
+ }
+
+ Transaction().setBuffer(layer, nullptr).apply();
+ {
+ SCOPED_TRACE("null buffer has no effect");
+ auto shot = getScreenCapture();
+ shot->expectColor(bounds, Color::BLACK);
+ }
+
+ Transaction().setBuffer(layer, nullptr).apply();
+ {
+ SCOPED_TRACE("null buffer has no effect");
+ auto shot = getScreenCapture();
+ shot->expectColor(bounds, Color::BLACK);
+ }
+}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index f1a5fc4..3b6a987 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -65,10 +65,6 @@
auto refreshRateSelector() { return pacesetterSelectorPtr(); }
- const auto& refreshRateSelectors() const NO_THREAD_SAFETY_ANALYSIS {
- return mRefreshRateSelectors;
- }
-
void registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
registerDisplay(displayId, std::move(selectorPtr),
std::make_unique<mock::VsyncController>(),
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 03c4e71..dbb7c6c 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -274,6 +274,34 @@
EXPECT_EQ(nullptr, ret.get());
}
+class FakeExternalTexture : public renderengine::ExternalTexture {
+ const sp<GraphicBuffer> mEmptyBuffer = nullptr;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint64_t mId;
+ PixelFormat mPixelFormat;
+ uint64_t mUsage;
+
+public:
+ FakeExternalTexture(BufferData& bufferData)
+ : mWidth(bufferData.getWidth()),
+ mHeight(bufferData.getHeight()),
+ mId(bufferData.getId()),
+ mPixelFormat(bufferData.getPixelFormat()),
+ mUsage(bufferData.getUsage()) {}
+ const sp<GraphicBuffer>& getBuffer() const { return mEmptyBuffer; }
+ bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
+ return getId() == other.getId();
+ }
+ uint32_t getWidth() const override { return mWidth; }
+ uint32_t getHeight() const override { return mHeight; }
+ uint64_t getId() const override { return mId; }
+ PixelFormat getPixelFormat() const override { return mPixelFormat; }
+ uint64_t getUsage() const override { return mUsage; }
+ void remapBuffer() override {}
+ ~FakeExternalTexture() = default;
+};
+
class LatchUnsignaledTest : public TransactionApplicationTest {
public:
void TearDown() override {
@@ -346,7 +374,11 @@
std::vector<ResolvedComposerState> resolvedStates;
resolvedStates.reserve(transaction.states.size());
for (auto& state : transaction.states) {
- resolvedStates.emplace_back(std::move(state));
+ ResolvedComposerState resolvedState;
+ resolvedState.state = std::move(state.state);
+ resolvedState.externalTexture =
+ std::make_shared<FakeExternalTexture>(*resolvedState.state.bufferData);
+ resolvedStates.emplace_back(resolvedState);
}
TransactionState transactionState(transaction.frameTimelineInfo, resolvedStates,