Merge "SF: Introduce new frontend logic"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index ecafcfc..a48313a 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -186,6 +186,7 @@
#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
#define CGROUPFS_DIR "/sys/fs/cgroup"
#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
+#define DROPBOX_DIR "/data/system/dropbox"
// TODO(narayan): Since this information has to be kept in sync
// with tombstoned, we should just put it in a common header.
@@ -526,6 +527,15 @@
return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
}
+static bool skip_wtf_strictmode(const char *path) {
+ if (strstr(path, "_wtf")) {
+ return true;
+ } else if (strstr(path, "_strictmode")) {
+ return true;
+ }
+ return false;
+}
+
static bool skip_none(const char* path __attribute__((unused))) {
return false;
}
@@ -1895,6 +1905,11 @@
DumpIpTablesAsRoot();
DumpDynamicPartitionInfo();
ds.AddDir(OTA_METADATA_DIR, true);
+ if (!PropertiesHelper::IsUserBuild()) {
+ // Include dropbox entry files inside ZIP, but exclude
+ // noisy WTF and StrictMode entries
+ dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
+ }
// Capture any IPSec policies in play. No keys are exposed here.
RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 87f9254..aa5219b 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -1051,7 +1051,8 @@
};
// Generate a quick LimitedOnly report redirected to a file, open it and verify entry exist.
-TEST_F(ZippedBugReportStreamTest, StreamLimitedOnlyReport) {
+// TODO: broken test tracked in b/249983726
+TEST_F(ZippedBugReportStreamTest, DISABLED_StreamLimitedOnlyReport) {
std::string out_path = kTestDataPath + "StreamLimitedOnlyReportOut.zip";
android::base::unique_fd out_fd;
CreateFd(out_path, &out_fd);
diff --git a/include/input/TfLiteMotionPredictor.h b/include/input/TfLiteMotionPredictor.h
index 704349c..54e2851 100644
--- a/include/input/TfLiteMotionPredictor.h
+++ b/include/input/TfLiteMotionPredictor.h
@@ -22,8 +22,8 @@
#include <memory>
#include <optional>
#include <span>
-#include <string>
+#include <android-base/mapped_file.h>
#include <input/RingBuffer.h>
#include <tensorflow/lite/core/api/error_reporter.h>
@@ -101,6 +101,8 @@
// Creates a model from an encoded Flatbuffer model.
static std::unique_ptr<TfLiteMotionPredictorModel> create(const char* modelPath);
+ ~TfLiteMotionPredictorModel();
+
// Returns the length of the model's input buffers.
size_t inputLength() const;
@@ -122,7 +124,7 @@
std::span<const float> outputPressure() const;
private:
- explicit TfLiteMotionPredictorModel(std::string model);
+ explicit TfLiteMotionPredictorModel(std::unique_ptr<android::base::MappedFile> model);
void allocateTensors();
void attachInputTensors();
@@ -138,7 +140,7 @@
const TfLiteTensor* mOutputPhi = nullptr;
const TfLiteTensor* mOutputPressure = nullptr;
- std::string mFlatBuffer;
+ std::unique_ptr<android::base::MappedFile> mFlatBuffer;
std::unique_ptr<tflite::ErrorReporter> mErrorReporter;
std::unique_ptr<tflite::FlatBufferModel> mModel;
std::unique_ptr<tflite::Interpreter> mInterpreter;
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
index afb73e9..38dd4fe 100644
--- a/libs/binder/rust/rpcbinder/Android.bp
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -23,7 +23,13 @@
"liblibc",
"liblog_rust",
],
+ visibility: [
+ "//device/google/cuttlefish/shared/minidroid/sample",
+ "//packages/modules/Uwb",
+ "//packages/modules/Virtualization:__subpackages__",
+ ],
apex_available: [
+ "//apex_available:platform",
"com.android.compos",
"com.android.uwb",
"com.android.virt",
@@ -51,6 +57,7 @@
"libutils",
],
apex_available: [
+ "//apex_available:platform",
"com.android.compos",
"com.android.uwb",
"com.android.virt",
@@ -84,6 +91,7 @@
"libutils",
],
apex_available: [
+ "//apex_available:platform",
"com.android.compos",
"com.android.uwb",
"com.android.virt",
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index cefb9a7..a77ca04 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -63,8 +63,7 @@
Vector<ComposerState>& state, const Vector<DisplayState>& displays,
uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& commands, int64_t desiredPresentTime,
- bool isAutoTimestamp,
- const std::vector<client_cache_t>& uncacheBuffers,
+ bool isAutoTimestamp, const client_cache_t& uncacheBuffer,
bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks,
uint64_t transactionId) override {
@@ -88,11 +87,8 @@
SAFE_PARCEL(commands.write, data);
SAFE_PARCEL(data.writeInt64, desiredPresentTime);
SAFE_PARCEL(data.writeBool, isAutoTimestamp);
- SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(uncacheBuffers.size()));
- for (const client_cache_t& uncacheBuffer : uncacheBuffers) {
- SAFE_PARCEL(data.writeStrongBinder, uncacheBuffer.token.promote());
- SAFE_PARCEL(data.writeUint64, uncacheBuffer.id);
- }
+ SAFE_PARCEL(data.writeStrongBinder, uncacheBuffer.token.promote());
+ SAFE_PARCEL(data.writeUint64, uncacheBuffer.id);
SAFE_PARCEL(data.writeBool, hasListenerCallbacks);
SAFE_PARCEL(data.writeVectorSize, listenerCallbacks);
@@ -162,14 +158,11 @@
SAFE_PARCEL(data.readInt64, &desiredPresentTime);
SAFE_PARCEL(data.readBool, &isAutoTimestamp);
- SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize());
- std::vector<client_cache_t> uncacheBuffers(count);
+ client_cache_t uncachedBuffer;
sp<IBinder> tmpBinder;
- for (size_t i = 0; i < count; i++) {
- SAFE_PARCEL(data.readNullableStrongBinder, &tmpBinder);
- uncacheBuffers[i].token = tmpBinder;
- SAFE_PARCEL(data.readUint64, &uncacheBuffers[i].id);
- }
+ SAFE_PARCEL(data.readNullableStrongBinder, &tmpBinder);
+ uncachedBuffer.token = tmpBinder;
+ SAFE_PARCEL(data.readUint64, &uncachedBuffer.id);
bool hasListenerCallbacks = false;
SAFE_PARCEL(data.readBool, &hasListenerCallbacks);
@@ -189,7 +182,7 @@
return setTransactionState(frameTimelineInfo, state, displays, stateFlags, applyToken,
inputWindowCommands, desiredPresentTime, isAutoTimestamp,
- uncacheBuffers, hasListenerCallbacks, listenerCallbacks,
+ uncachedBuffer, hasListenerCallbacks, listenerCallbacks,
transactionId);
}
default: {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 5088604..7498834 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -633,13 +633,11 @@
return NO_ERROR;
}
- uint64_t cache(const sp<GraphicBuffer>& buffer,
- std::optional<client_cache_t>& outUncacheBuffer) {
+ uint64_t cache(const sp<GraphicBuffer>& buffer) {
std::lock_guard<std::mutex> lock(mMutex);
if (mBuffers.size() >= BUFFER_CACHE_MAX_SIZE) {
- outUncacheBuffer = findLeastRecentlyUsedBuffer();
- mBuffers.erase(outUncacheBuffer->id);
+ evictLeastRecentlyUsedBuffer();
}
buffer->addDeathCallback(removeDeadBufferCallback, nullptr);
@@ -650,13 +648,16 @@
void uncache(uint64_t cacheId) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mBuffers.erase(cacheId)) {
- SurfaceComposerClient::doUncacheBufferTransaction(cacheId);
- }
+ uncacheLocked(cacheId);
+ }
+
+ void uncacheLocked(uint64_t cacheId) REQUIRES(mMutex) {
+ mBuffers.erase(cacheId);
+ SurfaceComposerClient::doUncacheBufferTransaction(cacheId);
}
private:
- client_cache_t findLeastRecentlyUsedBuffer() REQUIRES(mMutex) {
+ void evictLeastRecentlyUsedBuffer() REQUIRES(mMutex) {
auto itr = mBuffers.begin();
uint64_t minCounter = itr->second;
auto minBuffer = itr;
@@ -670,8 +671,7 @@
}
itr++;
}
-
- return {.token = getToken(), .id = minBuffer->first};
+ uncacheLocked(minBuffer->first);
}
uint64_t getCounter() REQUIRES(mMutex) {
@@ -809,18 +809,6 @@
InputWindowCommands inputWindowCommands;
inputWindowCommands.read(*parcel);
- count = static_cast<size_t>(parcel->readUint32());
- if (count > parcel->dataSize()) {
- return BAD_VALUE;
- }
- std::vector<client_cache_t> uncacheBuffers(count);
- for (size_t i = 0; i < count; i++) {
- sp<IBinder> tmpBinder;
- SAFE_PARCEL(parcel->readStrongBinder, &tmpBinder);
- uncacheBuffers[i].token = tmpBinder;
- SAFE_PARCEL(parcel->readUint64, &uncacheBuffers[i].id);
- }
-
// Parsing was successful. Update the object.
mId = transactionId;
mTransactionNestCount = transactionNestCount;
@@ -835,7 +823,6 @@
mComposerStates = composerStates;
mInputWindowCommands = inputWindowCommands;
mApplyToken = applyToken;
- mUncacheBuffers = std::move(uncacheBuffers);
return NO_ERROR;
}
@@ -887,13 +874,6 @@
}
mInputWindowCommands.write(*parcel);
-
- SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mUncacheBuffers.size()));
- for (const client_cache_t& uncacheBuffer : mUncacheBuffers) {
- SAFE_PARCEL(parcel->writeStrongBinder, uncacheBuffer.token.promote());
- SAFE_PARCEL(parcel->writeUint64, uncacheBuffer.id);
- }
-
return NO_ERROR;
}
@@ -960,10 +940,6 @@
}
}
- for (const auto& cacheId : other.mUncacheBuffers) {
- mUncacheBuffers.push_back(cacheId);
- }
-
mInputWindowCommands.merge(other.mInputWindowCommands);
mMayContainBuffer |= other.mMayContainBuffer;
@@ -982,7 +958,6 @@
mDisplayStates.clear();
mListenerCallbacks.clear();
mInputWindowCommands.clear();
- mUncacheBuffers.clear();
mMayContainBuffer = false;
mTransactionNestCount = 0;
mAnimation = false;
@@ -1005,10 +980,10 @@
uncacheBuffer.token = BufferCache::getInstance().getToken();
uncacheBuffer.id = cacheId;
Vector<ComposerState> composerStates;
- status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, {},
- ISurfaceComposer::eOneWay,
- Transaction::getDefaultApplyToken(), {}, systemTime(),
- true, {uncacheBuffer}, false, {}, generateId());
+ status_t status =
+ sf->setTransactionState(FrameTimelineInfo{}, composerStates, {},
+ ISurfaceComposer::eOneWay, Transaction::getDefaultApplyToken(),
+ {}, systemTime(), true, uncacheBuffer, false, {}, generateId());
if (status != NO_ERROR) {
ALOGE_AND_TRACE("SurfaceComposerClient::doUncacheBufferTransaction - %s",
strerror(-status));
@@ -1046,11 +1021,7 @@
s->bufferData->buffer = nullptr;
} else {
// Cache-miss. Include the buffer and send the new cacheId.
- std::optional<client_cache_t> uncacheBuffer;
- cacheId = BufferCache::getInstance().cache(s->bufferData->buffer, uncacheBuffer);
- if (uncacheBuffer) {
- mUncacheBuffers.push_back(*uncacheBuffer);
- }
+ cacheId = BufferCache::getInstance().cache(s->bufferData->buffer);
}
s->bufferData->flags |= BufferData::BufferDataChange::cachedBufferChanged;
s->bufferData->cachedBuffer.token = BufferCache::getInstance().getToken();
@@ -1183,7 +1154,8 @@
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken,
mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp,
- mUncacheBuffers, hasListenerCallbacks, listenerCallbacks, mId);
+ {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/,
+ hasListenerCallbacks, listenerCallbacks, mId);
mId = generateId();
// Clear the current states and flags
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index ae56f9f..045cc2a 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -113,9 +113,8 @@
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
- bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffer,
- bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
- uint64_t transactionId) = 0;
+ bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index ffd5af1..40c0d71 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -413,7 +413,6 @@
SortedVector<DisplayState> mDisplayStates;
std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash>
mListenerCallbacks;
- std::vector<client_cache_t> mUncacheBuffers;
uint64_t mId;
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index babc197..be1ef8e 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -701,7 +701,7 @@
const sp<IBinder>& /*applyToken*/,
const InputWindowCommands& /*inputWindowCommands*/,
int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/,
- const std::vector<client_cache_t>& /*cachedBuffer*/,
+ const client_cache_t& /*cachedBuffer*/,
bool /*hasListenerCallbacks*/,
const std::vector<ListenerCallbacks>& /*listenerCallbacks*/,
uint64_t /*transactionId*/) override {
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 83392ec..fd4fc16 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -73,11 +73,15 @@
"liblog",
"libPlatformProperties",
"libvintf",
- "libtflite",
+ ],
+
+ ldflags: [
+ "-Wl,--exclude-libs=libtflite_static.a",
],
static_libs: [
"libui-types",
+ "libtflite_static",
],
export_static_lib_headers: [
diff --git a/libs/input/TfLiteMotionPredictor.cpp b/libs/input/TfLiteMotionPredictor.cpp
index 40653d3..10510d6 100644
--- a/libs/input/TfLiteMotionPredictor.cpp
+++ b/libs/input/TfLiteMotionPredictor.cpp
@@ -17,27 +17,31 @@
#define LOG_TAG "TfLiteMotionPredictor"
#include <input/TfLiteMotionPredictor.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
-#include <fstream>
-#include <ios>
-#include <iterator>
#include <memory>
#include <span>
-#include <string>
#include <type_traits>
#include <utility>
+#include <android-base/logging.h>
+#include <android-base/mapped_file.h>
#define ATRACE_TAG ATRACE_TAG_INPUT
#include <cutils/trace.h>
#include <log/log.h>
#include "tensorflow/lite/core/api/error_reporter.h"
+#include "tensorflow/lite/core/api/op_resolver.h"
#include "tensorflow/lite/interpreter.h"
-#include "tensorflow/lite/kernels/register.h"
+#include "tensorflow/lite/kernels/builtin_op_kernels.h"
#include "tensorflow/lite/model.h"
+#include "tensorflow/lite/mutable_op_resolver.h"
namespace android {
namespace {
@@ -102,6 +106,15 @@
LOG_ALWAYS_FATAL_IF(buffer.empty(), "No buffer for tensor '%s'", tensor->name);
}
+std::unique_ptr<tflite::OpResolver> createOpResolver() {
+ auto resolver = std::make_unique<tflite::MutableOpResolver>();
+ resolver->AddBuiltin(::tflite::BuiltinOperator_CONCATENATION,
+ ::tflite::ops::builtin::Register_CONCATENATION());
+ resolver->AddBuiltin(::tflite::BuiltinOperator_FULLY_CONNECTED,
+ ::tflite::ops::builtin::Register_FULLY_CONNECTED());
+ return resolver;
+}
+
} // namespace
TfLiteMotionPredictorBuffers::TfLiteMotionPredictorBuffers(size_t inputLength)
@@ -195,27 +208,42 @@
std::unique_ptr<TfLiteMotionPredictorModel> TfLiteMotionPredictorModel::create(
const char* modelPath) {
- std::ifstream f(modelPath, std::ios::binary);
- LOG_ALWAYS_FATAL_IF(!f, "Could not read model from %s", modelPath);
+ const int fd = open(modelPath, O_RDONLY);
+ if (fd == -1) {
+ PLOG(FATAL) << "Could not read model from " << modelPath;
+ }
- std::string data;
- data.assign(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>());
+ const off_t fdSize = lseek(fd, 0, SEEK_END);
+ if (fdSize == -1) {
+ PLOG(FATAL) << "Failed to determine file size";
+ }
+
+ std::unique_ptr<android::base::MappedFile> modelBuffer =
+ android::base::MappedFile::FromFd(fd, /*offset=*/0, fdSize, PROT_READ);
+ if (!modelBuffer) {
+ PLOG(FATAL) << "Failed to mmap model";
+ }
+ if (close(fd) == -1) {
+ PLOG(FATAL) << "Failed to close model fd";
+ }
return std::unique_ptr<TfLiteMotionPredictorModel>(
- new TfLiteMotionPredictorModel(std::move(data)));
+ new TfLiteMotionPredictorModel(std::move(modelBuffer)));
}
-TfLiteMotionPredictorModel::TfLiteMotionPredictorModel(std::string model)
+TfLiteMotionPredictorModel::TfLiteMotionPredictorModel(
+ std::unique_ptr<android::base::MappedFile> model)
: mFlatBuffer(std::move(model)) {
+ CHECK(mFlatBuffer);
mErrorReporter = std::make_unique<LoggingErrorReporter>();
- mModel = tflite::FlatBufferModel::VerifyAndBuildFromBuffer(mFlatBuffer.data(),
- mFlatBuffer.length(),
+ mModel = tflite::FlatBufferModel::VerifyAndBuildFromBuffer(mFlatBuffer->data(),
+ mFlatBuffer->size(),
/*extra_verifier=*/nullptr,
mErrorReporter.get());
LOG_ALWAYS_FATAL_IF(!mModel);
- tflite::ops::builtin::BuiltinOpResolver resolver;
- tflite::InterpreterBuilder builder(*mModel, resolver);
+ auto resolver = createOpResolver();
+ tflite::InterpreterBuilder builder(*mModel, *resolver);
if (builder(&mInterpreter) != kTfLiteOk || !mInterpreter) {
LOG_ALWAYS_FATAL("Failed to build interpreter");
@@ -227,6 +255,8 @@
allocateTensors();
}
+TfLiteMotionPredictorModel::~TfLiteMotionPredictorModel() {}
+
void TfLiteMotionPredictorModel::allocateTensors() {
if (mRunner->AllocateTensors() != kTfLiteOk) {
LOG_ALWAYS_FATAL("Failed to allocate tensors");
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index f07164c..37faf91 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -34,6 +34,7 @@
"libgmock",
"libgui_window_info_static",
"libinput",
+ "libtflite_static",
"libui-types",
],
cflags: [
@@ -48,7 +49,6 @@
"libcutils",
"liblog",
"libPlatformProperties",
- "libtflite",
"libutils",
"libvintf",
],
diff --git a/libs/jpegrecoverymap/Android.bp b/libs/jpegrecoverymap/Android.bp
index 2c4b3bf..ee112e8 100644
--- a/libs/jpegrecoverymap/Android.bp
+++ b/libs/jpegrecoverymap/Android.bp
@@ -57,7 +57,7 @@
export_include_dirs: ["include"],
srcs: [
- "jpegencoder.cpp",
+ "jpegencoderhelper.cpp",
],
}
@@ -73,6 +73,6 @@
export_include_dirs: ["include"],
srcs: [
- "jpegdecoder.cpp",
+ "jpegdecoderhelper.cpp",
],
}
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoderhelper.h
similarity index 94%
rename from libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h
rename to libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoderhelper.h
index 419b63d..485869d 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoderhelper.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2022 The Android Open Source Project
*
@@ -15,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_JPEGRECOVERYMAP_JPEGDECODER_H
-#define ANDROID_JPEGRECOVERYMAP_JPEGDECODER_H
+#ifndef ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H
+#define ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H
// We must include cstdio before jpeglib.h. It is a requirement of libjpeg.
#include <cstdio>
@@ -31,10 +30,10 @@
* Encapsulates a converter from JPEG to raw image (YUV420planer or grey-scale) format.
* This class is not thread-safe.
*/
-class JpegDecoder {
+class JpegDecoderHelper {
public:
- JpegDecoder();
- ~JpegDecoder();
+ JpegDecoderHelper();
+ ~JpegDecoderHelper();
/*
* Decompresses JPEG image to raw image (YUV420planer, grey-scale or RGBA) format. After
* calling this method, call getDecompressedImage() to get the image.
@@ -118,4 +117,4 @@
};
} /* namespace android */
-#endif // ANDROID_JPEGRECOVERYMAP_JPEGDECODER_H
+#endif // ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoder.h b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoderhelper.h
similarity index 93%
rename from libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoder.h
rename to libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoderhelper.h
index 61aeb8a..f087b55 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoder.h
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoderhelper.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_JPEGRECOVERYMAP_JPEGENCODER_H
-#define ANDROID_JPEGRECOVERYMAP_JPEGENCODER_H
+#ifndef ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H
+#define ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H
// We must include cstdio before jpeglib.h. It is a requirement of libjpeg.
#include <cstdio>
@@ -34,10 +34,10 @@
* Encapsulates a converter from raw image (YUV420planer or grey-scale) to JPEG format.
* This class is not thread-safe.
*/
-class JpegEncoder {
+class JpegEncoderHelper {
public:
- JpegEncoder();
- ~JpegEncoder();
+ JpegEncoderHelper();
+ ~JpegEncoderHelper();
/*
* Compresses YUV420Planer image to JPEG format. After calling this method, call
@@ -92,4 +92,4 @@
} /* namespace android */
-#endif // ANDROID_JPEGRECOVERYMAP_JPEGENCODER_H
+#endif // ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H
diff --git a/libs/jpegrecoverymap/jpegdecoder.cpp b/libs/jpegrecoverymap/jpegdecoderhelper.cpp
similarity index 91%
rename from libs/jpegrecoverymap/jpegdecoder.cpp
rename to libs/jpegrecoverymap/jpegdecoderhelper.cpp
index 1bf609a..0754ec9 100644
--- a/libs/jpegrecoverymap/jpegdecoder.cpp
+++ b/libs/jpegrecoverymap/jpegdecoderhelper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <jpegrecoverymap/jpegdecoder.h>
+#include <jpegrecoverymap/jpegdecoderhelper.h>
#include <utils/Log.h>
@@ -90,14 +90,14 @@
longjmp(err->setjmp_buffer, 1);
}
-JpegDecoder::JpegDecoder() {
+JpegDecoderHelper::JpegDecoderHelper() {
mExifPos = 0;
}
-JpegDecoder::~JpegDecoder() {
+JpegDecoderHelper::~JpegDecoderHelper() {
}
-bool JpegDecoder::decompressImage(const void* image, int length, bool decodeToRGBA) {
+bool JpegDecoderHelper::decompressImage(const void* image, int length, bool decodeToRGBA) {
if (image == nullptr || length <= 0) {
ALOGE("Image size can not be handled: %d", length);
return false;
@@ -112,39 +112,39 @@
return true;
}
-void* JpegDecoder::getDecompressedImagePtr() {
+void* JpegDecoderHelper::getDecompressedImagePtr() {
return mResultBuffer.data();
}
-size_t JpegDecoder::getDecompressedImageSize() {
+size_t JpegDecoderHelper::getDecompressedImageSize() {
return mResultBuffer.size();
}
-void* JpegDecoder::getXMPPtr() {
+void* JpegDecoderHelper::getXMPPtr() {
return mXMPBuffer.data();
}
-size_t JpegDecoder::getXMPSize() {
+size_t JpegDecoderHelper::getXMPSize() {
return mXMPBuffer.size();
}
-void* JpegDecoder::getEXIFPtr() {
+void* JpegDecoderHelper::getEXIFPtr() {
return mEXIFBuffer.data();
}
-size_t JpegDecoder::getEXIFSize() {
+size_t JpegDecoderHelper::getEXIFSize() {
return mEXIFBuffer.size();
}
-size_t JpegDecoder::getDecompressedImageWidth() {
+size_t JpegDecoderHelper::getDecompressedImageWidth() {
return mWidth;
}
-size_t JpegDecoder::getDecompressedImageHeight() {
+size_t JpegDecoderHelper::getDecompressedImageHeight() {
return mHeight;
}
-bool JpegDecoder::decode(const void* image, int length, bool decodeToRGBA) {
+bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) {
jpeg_decompress_struct cinfo;
jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length);
jpegrerror_mgr myerr;
@@ -248,7 +248,7 @@
return true;
}
-bool JpegDecoder::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest,
+bool JpegDecoderHelper::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest,
bool isSingleChannel) {
if (isSingleChannel) {
return decompressSingleChannel(cinfo, dest);
@@ -259,7 +259,7 @@
return decompressYUV(cinfo, dest);
}
-bool JpegDecoder::getCompressedImageParameters(const void* image, int length,
+bool JpegDecoderHelper::getCompressedImageParameters(const void* image, int length,
size_t *pWidth, size_t *pHeight,
std::vector<uint8_t> *iccData , std::vector<uint8_t> *exifData) {
jpeg_decompress_struct cinfo;
@@ -326,7 +326,7 @@
return true;
}
-bool JpegDecoder::decompressRGBA(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
+bool JpegDecoderHelper::decompressRGBA(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
JSAMPLE* decodeDst = (JSAMPLE*) dest;
uint32_t lines = 0;
// TODO: use batches for more effectiveness
@@ -341,7 +341,7 @@
return lines == cinfo->image_height;
}
-bool JpegDecoder::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
+bool JpegDecoderHelper::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
JSAMPROW y[kCompressBatchSize];
JSAMPROW cb[kCompressBatchSize / 2];
@@ -386,7 +386,7 @@
return true;
}
-bool JpegDecoder::decompressSingleChannel(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
+bool JpegDecoderHelper::decompressSingleChannel(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
JSAMPROW y[kCompressBatchSize];
JSAMPARRAY planes[1] {y};
diff --git a/libs/jpegrecoverymap/jpegencoder.cpp b/libs/jpegrecoverymap/jpegencoderhelper.cpp
similarity index 86%
rename from libs/jpegrecoverymap/jpegencoder.cpp
rename to libs/jpegrecoverymap/jpegencoderhelper.cpp
index 627dcdf..54b184d 100644
--- a/libs/jpegrecoverymap/jpegencoder.cpp
+++ b/libs/jpegrecoverymap/jpegencoderhelper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <jpegrecoverymap/jpegencoder.h>
+#include <jpegrecoverymap/jpegencoderhelper.h>
#include <utils/Log.h>
@@ -22,20 +22,20 @@
namespace android::recoverymap {
-// The destination manager that can access |mResultBuffer| in JpegEncoder.
+// The destination manager that can access |mResultBuffer| in JpegEncoderHelper.
struct destination_mgr {
public:
struct jpeg_destination_mgr mgr;
- JpegEncoder* encoder;
+ JpegEncoderHelper* encoder;
};
-JpegEncoder::JpegEncoder() {
+JpegEncoderHelper::JpegEncoderHelper() {
}
-JpegEncoder::~JpegEncoder() {
+JpegEncoderHelper::~JpegEncoderHelper() {
}
-bool JpegEncoder::compressImage(const void* image, int width, int height, int quality,
+bool JpegEncoderHelper::compressImage(const void* image, int width, int height, int quality,
const void* iccBuffer, unsigned int iccSize,
bool isSingleChannel) {
if (width % 8 != 0 || height % 2 != 0) {
@@ -52,15 +52,15 @@
return true;
}
-void* JpegEncoder::getCompressedImagePtr() {
+void* JpegEncoderHelper::getCompressedImagePtr() {
return mResultBuffer.data();
}
-size_t JpegEncoder::getCompressedImageSize() {
+size_t JpegEncoderHelper::getCompressedImageSize() {
return mResultBuffer.size();
}
-void JpegEncoder::initDestination(j_compress_ptr cinfo) {
+void JpegEncoderHelper::initDestination(j_compress_ptr cinfo) {
destination_mgr* dest = reinterpret_cast<destination_mgr*>(cinfo->dest);
std::vector<JOCTET>& buffer = dest->encoder->mResultBuffer;
buffer.resize(kBlockSize);
@@ -68,7 +68,7 @@
dest->mgr.free_in_buffer = buffer.size();
}
-boolean JpegEncoder::emptyOutputBuffer(j_compress_ptr cinfo) {
+boolean JpegEncoderHelper::emptyOutputBuffer(j_compress_ptr cinfo) {
destination_mgr* dest = reinterpret_cast<destination_mgr*>(cinfo->dest);
std::vector<JOCTET>& buffer = dest->encoder->mResultBuffer;
size_t oldsize = buffer.size();
@@ -78,13 +78,13 @@
return true;
}
-void JpegEncoder::terminateDestination(j_compress_ptr cinfo) {
+void JpegEncoderHelper::terminateDestination(j_compress_ptr cinfo) {
destination_mgr* dest = reinterpret_cast<destination_mgr*>(cinfo->dest);
std::vector<JOCTET>& buffer = dest->encoder->mResultBuffer;
buffer.resize(buffer.size() - dest->mgr.free_in_buffer);
}
-void JpegEncoder::outputErrorMessage(j_common_ptr cinfo) {
+void JpegEncoderHelper::outputErrorMessage(j_common_ptr cinfo) {
char buffer[JMSG_LENGTH_MAX];
/* Create the message */
@@ -92,7 +92,7 @@
ALOGE("%s\n", buffer);
}
-bool JpegEncoder::encode(const void* image, int width, int height, int jpegQuality,
+bool JpegEncoderHelper::encode(const void* image, int width, int height, int jpegQuality,
const void* iccBuffer, unsigned int iccSize, bool isSingleChannel) {
jpeg_compress_struct cinfo;
jpeg_error_mgr jerr;
@@ -118,7 +118,7 @@
return true;
}
-void JpegEncoder::setJpegDestination(jpeg_compress_struct* cinfo) {
+void JpegEncoderHelper::setJpegDestination(jpeg_compress_struct* cinfo) {
destination_mgr* dest = static_cast<struct destination_mgr *>((*cinfo->mem->alloc_small) (
(j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(destination_mgr)));
dest->encoder = this;
@@ -128,7 +128,7 @@
cinfo->dest = reinterpret_cast<struct jpeg_destination_mgr*>(dest);
}
-void JpegEncoder::setJpegCompressStruct(int width, int height, int quality,
+void JpegEncoderHelper::setJpegCompressStruct(int width, int height, int quality,
jpeg_compress_struct* cinfo, bool isSingleChannel) {
cinfo->image_width = width;
cinfo->image_height = height;
@@ -158,7 +158,7 @@
}
}
-bool JpegEncoder::compress(
+bool JpegEncoderHelper::compress(
jpeg_compress_struct* cinfo, const uint8_t* image, bool isSingleChannel) {
if (isSingleChannel) {
return compressSingleChannel(cinfo, image);
@@ -166,7 +166,7 @@
return compressYuv(cinfo, image);
}
-bool JpegEncoder::compressYuv(jpeg_compress_struct* cinfo, const uint8_t* yuv) {
+bool JpegEncoderHelper::compressYuv(jpeg_compress_struct* cinfo, const uint8_t* yuv) {
JSAMPROW y[kCompressBatchSize];
JSAMPROW cb[kCompressBatchSize / 2];
JSAMPROW cr[kCompressBatchSize / 2];
@@ -210,7 +210,7 @@
return true;
}
-bool JpegEncoder::compressSingleChannel(jpeg_compress_struct* cinfo, const uint8_t* image) {
+bool JpegEncoderHelper::compressSingleChannel(jpeg_compress_struct* cinfo, const uint8_t* image) {
JSAMPROW y[kCompressBatchSize];
JSAMPARRAY planes[1] {y};
diff --git a/libs/jpegrecoverymap/recoverymap.cpp b/libs/jpegrecoverymap/recoverymap.cpp
index 8b8c2e7..218c430 100644
--- a/libs/jpegrecoverymap/recoverymap.cpp
+++ b/libs/jpegrecoverymap/recoverymap.cpp
@@ -15,8 +15,8 @@
*/
#include <jpegrecoverymap/recoverymap.h>
-#include <jpegrecoverymap/jpegencoder.h>
-#include <jpegrecoverymap/jpegdecoder.h>
+#include <jpegrecoverymap/jpegencoderhelper.h>
+#include <jpegrecoverymap/jpegdecoderhelper.h>
#include <jpegrecoverymap/recoverymapmath.h>
#include <jpegrecoverymap/recoverymaputils.h>
@@ -146,7 +146,7 @@
jrTransFunc_to_skTransFunc.at(JPEGR_TF_SRGB),
jrGamut_to_skGamut.at(uncompressed_yuv_420_image.colorGamut));
- JpegEncoder jpeg_encoder;
+ JpegEncoderHelper jpeg_encoder;
if (!jpeg_encoder.compressImage(uncompressed_yuv_420_image.data,
uncompressed_yuv_420_image.width,
uncompressed_yuv_420_image.height, quality,
@@ -210,7 +210,7 @@
jrTransFunc_to_skTransFunc.at(JPEGR_TF_SRGB),
jrGamut_to_skGamut.at(uncompressed_yuv_420_image->colorGamut));
- JpegEncoder jpeg_encoder;
+ JpegEncoderHelper jpeg_encoder;
if (!jpeg_encoder.compressImage(uncompressed_yuv_420_image->data,
uncompressed_yuv_420_image->width,
uncompressed_yuv_420_image->height, quality,
@@ -289,7 +289,7 @@
return ERROR_JPEGR_INVALID_INPUT_TYPE;
}
- JpegDecoder jpeg_decoder;
+ JpegDecoderHelper jpeg_decoder;
if (!jpeg_decoder.decompressImage(compressed_jpeg_image->data, compressed_jpeg_image->length)) {
return ERROR_JPEGR_DECODE_ERROR;
}
@@ -334,7 +334,7 @@
JPEGR_CHECK(extractPrimaryImageAndRecoveryMap(compressed_jpegr_image,
&primary_image, &recovery_map));
- JpegDecoder jpeg_decoder;
+ JpegDecoderHelper jpeg_decoder;
if (!jpeg_decoder.getCompressedImageParameters(primary_image.data, primary_image.length,
&jpegr_info->width, &jpegr_info->height,
jpegr_info->iccData, jpegr_info->exifData)) {
@@ -356,7 +356,7 @@
(void) exif;
if (request_sdr) {
- JpegDecoder jpeg_decoder;
+ JpegDecoderHelper jpeg_decoder;
if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length,
true)) {
return ERROR_JPEGR_DECODE_ERROR;
@@ -376,12 +376,12 @@
jpegr_metadata metadata;
JPEGR_CHECK(extractRecoveryMap(compressed_jpegr_image, &compressed_map));
- JpegDecoder jpeg_decoder;
+ JpegDecoderHelper jpeg_decoder;
if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length)) {
return ERROR_JPEGR_DECODE_ERROR;
}
- JpegDecoder recovery_map_decoder;
+ JpegDecoderHelper recovery_map_decoder;
if (!recovery_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) {
return ERROR_JPEGR_DECODE_ERROR;
}
@@ -411,7 +411,7 @@
return ERROR_JPEGR_INVALID_NULL_PTR;
}
- JpegEncoder jpeg_encoder;
+ JpegEncoderHelper jpeg_encoder;
if (!jpeg_encoder.compressImage(uncompressed_recovery_map->data,
uncompressed_recovery_map->width,
uncompressed_recovery_map->height,
diff --git a/libs/jpegrecoverymap/tests/Android.bp b/libs/jpegrecoverymap/tests/Android.bp
index e381caf..e416db9 100644
--- a/libs/jpegrecoverymap/tests/Android.bp
+++ b/libs/jpegrecoverymap/tests/Android.bp
@@ -44,10 +44,10 @@
}
cc_test {
- name: "libjpegencoder_test",
+ name: "libjpegencoderhelper_test",
test_suites: ["device-tests"],
srcs: [
- "jpegencoder_test.cpp",
+ "jpegencoderhelper_test.cpp",
],
shared_libs: [
"libjpeg",
@@ -60,10 +60,10 @@
}
cc_test {
- name: "libjpegdecoder_test",
+ name: "libjpegdecoderhelper_test",
test_suites: ["device-tests"],
srcs: [
- "jpegdecoder_test.cpp",
+ "jpegdecoderhelper_test.cpp",
],
shared_libs: [
"libjpeg",
diff --git a/libs/jpegrecoverymap/tests/jpegdecoder_test.cpp b/libs/jpegrecoverymap/tests/jpegdecoderhelper_test.cpp
similarity index 79%
rename from libs/jpegrecoverymap/tests/jpegdecoder_test.cpp
rename to libs/jpegrecoverymap/tests/jpegdecoderhelper_test.cpp
index 8e01351..278bf3b 100644
--- a/libs/jpegrecoverymap/tests/jpegdecoder_test.cpp
+++ b/libs/jpegrecoverymap/tests/jpegdecoderhelper_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <jpegrecoverymap/jpegdecoder.h>
+#include <jpegrecoverymap/jpegdecoderhelper.h>
#include <gtest/gtest.h>
#include <utils/Log.h>
@@ -27,14 +27,14 @@
#define GREY_IMAGE "/sdcard/Documents/minnie-320x240-y.jpg"
#define GREY_IMAGE_SIZE 20193
-class JpegDecoderTest : public testing::Test {
+class JpegDecoderHelperTest : public testing::Test {
public:
struct Image {
std::unique_ptr<uint8_t[]> buffer;
size_t size;
};
- JpegDecoderTest();
- ~JpegDecoderTest();
+ JpegDecoderHelperTest();
+ ~JpegDecoderHelperTest();
protected:
virtual void SetUp();
virtual void TearDown();
@@ -42,9 +42,9 @@
Image mYuvImage, mGreyImage;
};
-JpegDecoderTest::JpegDecoderTest() {}
+JpegDecoderHelperTest::JpegDecoderHelperTest() {}
-JpegDecoderTest::~JpegDecoderTest() {}
+JpegDecoderHelperTest::~JpegDecoderHelperTest() {}
static size_t getFileSize(int fd) {
struct stat st;
@@ -55,7 +55,7 @@
return st.st_size; // bytes
}
-static bool loadFile(const char filename[], JpegDecoderTest::Image* result) {
+static bool loadFile(const char filename[], JpegDecoderHelperTest::Image* result) {
int fd = open(filename, O_CLOEXEC);
if (fd < 0) {
return false;
@@ -74,7 +74,7 @@
return true;
}
-void JpegDecoderTest::SetUp() {
+void JpegDecoderHelperTest::SetUp() {
if (!loadFile(YUV_IMAGE, &mYuvImage)) {
FAIL() << "Load file " << YUV_IMAGE << " failed";
}
@@ -85,16 +85,16 @@
mGreyImage.size = GREY_IMAGE_SIZE;
}
-void JpegDecoderTest::TearDown() {}
+void JpegDecoderHelperTest::TearDown() {}
-TEST_F(JpegDecoderTest, decodeYuvImage) {
- JpegDecoder decoder;
+TEST_F(JpegDecoderHelperTest, decodeYuvImage) {
+ JpegDecoderHelper decoder;
EXPECT_TRUE(decoder.decompressImage(mYuvImage.buffer.get(), mYuvImage.size));
ASSERT_GT(decoder.getDecompressedImageSize(), static_cast<uint32_t>(0));
}
-TEST_F(JpegDecoderTest, decodeGreyImage) {
- JpegDecoder decoder;
+TEST_F(JpegDecoderHelperTest, decodeGreyImage) {
+ JpegDecoderHelper decoder;
EXPECT_TRUE(decoder.decompressImage(mGreyImage.buffer.get(), mGreyImage.size));
ASSERT_GT(decoder.getDecompressedImageSize(), static_cast<uint32_t>(0));
}
diff --git a/libs/jpegrecoverymap/tests/jpegencoder_test.cpp b/libs/jpegrecoverymap/tests/jpegencoderhelper_test.cpp
similarity index 83%
rename from libs/jpegrecoverymap/tests/jpegencoder_test.cpp
rename to libs/jpegrecoverymap/tests/jpegencoderhelper_test.cpp
index 4cd2a5e..532688d 100644
--- a/libs/jpegrecoverymap/tests/jpegencoder_test.cpp
+++ b/libs/jpegrecoverymap/tests/jpegencoderhelper_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <jpegrecoverymap/jpegencoder.h>
+#include <jpegrecoverymap/jpegencoderhelper.h>
#include <gtest/gtest.h>
#include <utils/Log.h>
@@ -33,15 +33,15 @@
#define INVALID_SIZE_IMAGE_HEIGHT 240
#define JPEG_QUALITY 90
-class JpegEncoderTest : public testing::Test {
+class JpegEncoderHelperTest : public testing::Test {
public:
struct Image {
std::unique_ptr<uint8_t[]> buffer;
size_t width;
size_t height;
};
- JpegEncoderTest();
- ~JpegEncoderTest();
+ JpegEncoderHelperTest();
+ ~JpegEncoderHelperTest();
protected:
virtual void SetUp();
virtual void TearDown();
@@ -49,9 +49,9 @@
Image mValidImage, mInvalidSizeImage, mSingleChannelImage;
};
-JpegEncoderTest::JpegEncoderTest() {}
+JpegEncoderHelperTest::JpegEncoderHelperTest() {}
-JpegEncoderTest::~JpegEncoderTest() {}
+JpegEncoderHelperTest::~JpegEncoderHelperTest() {}
static size_t getFileSize(int fd) {
struct stat st;
@@ -62,7 +62,7 @@
return st.st_size; // bytes
}
-static bool loadFile(const char filename[], JpegEncoderTest::Image* result) {
+static bool loadFile(const char filename[], JpegEncoderHelperTest::Image* result) {
int fd = open(filename, O_CLOEXEC);
if (fd < 0) {
return false;
@@ -81,7 +81,7 @@
return true;
}
-void JpegEncoderTest::SetUp() {
+void JpegEncoderHelperTest::SetUp() {
if (!loadFile(VALID_IMAGE, &mValidImage)) {
FAIL() << "Load file " << VALID_IMAGE << " failed";
}
@@ -99,23 +99,23 @@
mSingleChannelImage.height = SINGLE_CHANNEL_IMAGE_HEIGHT;
}
-void JpegEncoderTest::TearDown() {}
+void JpegEncoderHelperTest::TearDown() {}
-TEST_F(JpegEncoderTest, validImage) {
- JpegEncoder encoder;
+TEST_F(JpegEncoderHelperTest, validImage) {
+ JpegEncoderHelper encoder;
EXPECT_TRUE(encoder.compressImage(mValidImage.buffer.get(), mValidImage.width,
mValidImage.height, JPEG_QUALITY, NULL, 0));
ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
}
-TEST_F(JpegEncoderTest, invalidSizeImage) {
- JpegEncoder encoder;
+TEST_F(JpegEncoderHelperTest, invalidSizeImage) {
+ JpegEncoderHelper encoder;
EXPECT_FALSE(encoder.compressImage(mInvalidSizeImage.buffer.get(), mInvalidSizeImage.width,
mInvalidSizeImage.height, JPEG_QUALITY, NULL, 0));
}
-TEST_F(JpegEncoderTest, singleChannelImage) {
- JpegEncoder encoder;
+TEST_F(JpegEncoderHelperTest, singleChannelImage) {
+ JpegEncoderHelper encoder;
EXPECT_TRUE(encoder.compressImage(mSingleChannelImage.buffer.get(), mSingleChannelImage.width,
mSingleChannelImage.height, JPEG_QUALITY, NULL, 0, true));
ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
diff --git a/services/inputflinger/dispatcher/CancelationOptions.h b/services/inputflinger/dispatcher/CancelationOptions.h
index 48f9f2b..83e6a60 100644
--- a/services/inputflinger/dispatcher/CancelationOptions.h
+++ b/services/inputflinger/dispatcher/CancelationOptions.h
@@ -30,6 +30,7 @@
CANCEL_POINTER_EVENTS = 1,
CANCEL_NON_POINTER_EVENTS = 2,
CANCEL_FALLBACK_EVENTS = 3,
+ ftl_last = CANCEL_FALLBACK_EVENTS,
};
// The criterion to use to determine which events should be canceled.
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index d14a781..9d5bbbd 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2185,8 +2185,9 @@
const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE);
if (newGesture) {
- bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
- if (switchedDevice && tempTouchState.isDown() && !down && !isHoverAction) {
+ // If pointers are already down, let's finish the current gesture and ignore the new events
+ // from another device.
+ if (switchedDevice && wasDown) {
ALOGI("Dropping event because a pointer for a different device is already down "
"in display %" PRId32,
displayId);
@@ -3761,9 +3762,9 @@
}
if (DEBUG_OUTBOUND_EVENT_DETAILS) {
ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync "
- "with reality: %s, mode=%d.",
+ "with reality: %s, mode=%s.",
connection->getInputChannelName().c_str(), cancelationEvents.size(), options.reason,
- options.mode);
+ ftl::enum_string(options.mode).c_str());
}
std::string reason = std::string("reason=").append(options.reason);
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 3605be2..e71cdce 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -2461,6 +2461,86 @@
}
/**
+ * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
+ * While the touch is down, new hover events from the stylus device should be ignored. After the
+ * touch is gone, stylus hovering should start working again.
+ */
+TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+ window->setFrame(Rect(0, 0, 200, 200));
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+
+ const int32_t stylusDeviceId = 5;
+ const int32_t touchDeviceId = 4;
+ // Start hovering with stylus
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
+ AINPUT_SOURCE_STYLUS)
+ .deviceId(stylusDeviceId)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
+ .x(50)
+ .y(50))
+ .build()));
+ window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
+
+ // Finger down on the window
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(100)
+ .y(100))
+ .build()));
+ window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
+ window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
+
+ // Try to continue hovering with stylus. Since we are already down, injection should fail
+ ASSERT_EQ(InputEventInjectionResult::FAILED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
+ AINPUT_SOURCE_STYLUS)
+ .deviceId(stylusDeviceId)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
+ .x(50)
+ .y(50))
+ .build()));
+ // No event should be sent. This event should be ignored because a pointer from another device
+ // is already down.
+
+ // Lift up the finger
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
+ AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(100)
+ .y(100))
+ .build()));
+ window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
+
+ // Now that the touch is gone, stylus hovering should start working again
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
+ AINPUT_SOURCE_STYLUS)
+ .deviceId(stylusDeviceId)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
+ .x(50)
+ .y(50))
+ .build()));
+ window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
+ // No more events
+ window->assertNoEvents();
+}
+
+/**
* On the display, have a single window, and also an area where there's no window.
* First pointer touches the "no window" area of the screen. Second pointer touches the window.
* Make sure that the window receives the second pointer, and first pointer is simply ignored.
diff --git a/services/surfaceflinger/Scheduler/ISchedulerCallback.h b/services/surfaceflinger/Scheduler/ISchedulerCallback.h
new file mode 100644
index 0000000..c4de749
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/ISchedulerCallback.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include "Display/DisplayModeRequest.h"
+
+namespace android::scheduler {
+
+struct ISchedulerCallback {
+ virtual void setVsyncEnabled(bool) = 0;
+ virtual void requestDisplayModes(std::vector<display::DisplayModeRequest>) = 0;
+ virtual void kernelTimerChanged(bool expired) = 0;
+ virtual void triggerOnFrameRateOverridesChanged() = 0;
+
+protected:
+ ~ISchedulerCallback() = default;
+};
+
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 5fc250b..17cdff9 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -28,10 +28,10 @@
#include <ftl/enum.h>
#include <ftl/fake_guard.h>
#include <ftl/small_map.h>
+#include <gui/TraceUtils.h>
#include <gui/WindowInfo.h>
#include <system/window.h>
#include <utils/Timers.h>
-#include <utils/Trace.h>
#include <FrameTimeline/FrameTimeline.h>
#include <scheduler/interface/ICompositor.h>
@@ -155,7 +155,7 @@
}
void Scheduler::createVsyncSchedule(FeatureFlags features) {
- mVsyncSchedule.emplace(features);
+ mVsyncSchedule = std::make_unique<VsyncSchedule>(features);
}
std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
@@ -171,6 +171,7 @@
return true;
}
+ ATRACE_FORMAT("%s uid: %d frameRate: %s", __func__, uid, to_string(*frameRate).c_str());
return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp.ns(), *frameRate);
}
@@ -393,38 +394,17 @@
}
void Scheduler::enableHardwareVsync() {
- std::lock_guard<std::mutex> lock(mHWVsyncLock);
- if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
- mVsyncSchedule->getTracker().resetModel();
- mSchedulerCallback.setVsyncEnabled(true);
- mPrimaryHWVsyncEnabled = true;
- }
+ mVsyncSchedule->enableHardwareVsync(mSchedulerCallback);
}
-void Scheduler::disableHardwareVsync(bool makeUnavailable) {
- std::lock_guard<std::mutex> lock(mHWVsyncLock);
- if (mPrimaryHWVsyncEnabled) {
- mSchedulerCallback.setVsyncEnabled(false);
- mPrimaryHWVsyncEnabled = false;
- }
- if (makeUnavailable) {
- mHWVsyncAvailable = false;
- }
+void Scheduler::disableHardwareVsync(bool disallow) {
+ mVsyncSchedule->disableHardwareVsync(mSchedulerCallback, disallow);
}
-void Scheduler::resyncToHardwareVsync(bool makeAvailable, Fps refreshRate) {
- {
- std::lock_guard<std::mutex> lock(mHWVsyncLock);
- if (makeAvailable) {
- mHWVsyncAvailable = makeAvailable;
- } else if (!mHWVsyncAvailable) {
- // Hardware vsync is not currently available, so abort the resync
- // attempt for now
- return;
- }
+void Scheduler::resyncToHardwareVsync(bool allowToEnable, Fps refreshRate) {
+ if (mVsyncSchedule->isHardwareVsyncAllowed(allowToEnable) && refreshRate.isValid()) {
+ mVsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod());
}
-
- setVsyncPeriod(refreshRate.getPeriodNsecs());
}
void Scheduler::setRenderRate(Fps renderFrameRate) {
@@ -457,37 +437,12 @@
}
}
-void Scheduler::setVsyncPeriod(nsecs_t period) {
- if (period <= 0) return;
-
- std::lock_guard<std::mutex> lock(mHWVsyncLock);
- mVsyncSchedule->getController().startPeriodTransition(period);
-
- if (!mPrimaryHWVsyncEnabled) {
- mVsyncSchedule->getTracker().resetModel();
- mSchedulerCallback.setVsyncEnabled(true);
- mPrimaryHWVsyncEnabled = true;
- }
-}
-
-void Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
- bool* periodFlushed) {
- bool needsHwVsync = false;
- *periodFlushed = false;
- { // Scope for the lock
- std::lock_guard<std::mutex> lock(mHWVsyncLock);
- if (mPrimaryHWVsyncEnabled) {
- needsHwVsync =
- mVsyncSchedule->getController().addHwVsyncTimestamp(timestamp, hwcVsyncPeriod,
- periodFlushed);
- }
- }
-
- if (needsHwVsync) {
- enableHardwareVsync();
- } else {
- disableHardwareVsync(false);
- }
+bool Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriodIn) {
+ const auto hwcVsyncPeriod = ftl::Optional(hwcVsyncPeriodIn).transform([](nsecs_t nanos) {
+ return Period::fromNs(nanos);
+ });
+ return mVsyncSchedule->addResyncSample(mSchedulerCallback, TimePoint::fromNs(timestamp),
+ hwcVsyncPeriod);
}
void Scheduler::addPresentFence(std::shared_ptr<FenceTime> fence) {
@@ -635,14 +590,6 @@
mFrameRateOverrideMappings.dump(dumper);
dumper.eol();
-
- {
- utils::Dumper::Section section(dumper, "Hardware VSYNC"sv);
-
- std::lock_guard lock(mHWVsyncLock);
- dumper.dump("hwVsyncAvailable"sv, mHWVsyncAvailable);
- dumper.dump("hwVsyncEnabled"sv, mPrimaryHWVsyncEnabled);
- }
}
void Scheduler::dumpVsync(std::string& out) const {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index dae9546..a340919 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -43,6 +43,7 @@
#include "Display/DisplayModeRequest.h"
#include "EventThread.h"
#include "FrameRateOverrideMappings.h"
+#include "ISchedulerCallback.h"
#include "LayerHistory.h"
#include "MessageQueue.h"
#include "OneShotTimer.h"
@@ -92,16 +93,6 @@
using GlobalSignals = RefreshRateSelector::GlobalSignals;
-struct ISchedulerCallback {
- virtual void setVsyncEnabled(bool) = 0;
- virtual void requestDisplayModes(std::vector<display::DisplayModeRequest>) = 0;
- virtual void kernelTimerChanged(bool expired) = 0;
- virtual void triggerOnFrameRateOverridesChanged() = 0;
-
-protected:
- ~ISchedulerCallback() = default;
-};
-
class Scheduler : android::impl::MessageQueue {
using Impl = android::impl::MessageQueue;
@@ -192,20 +183,20 @@
void setRenderRate(Fps);
void enableHardwareVsync();
- void disableHardwareVsync(bool makeUnavailable);
+ void disableHardwareVsync(bool disallow);
// Resyncs the scheduler to hardware vsync.
- // If makeAvailable is true, then hardware vsync will be turned on.
+ // If allowToEnable is true, then hardware vsync will be turned on.
// Otherwise, if hardware vsync is not already enabled then this method will
// no-op.
- void resyncToHardwareVsync(bool makeAvailable, Fps refreshRate);
+ void resyncToHardwareVsync(bool allowToEnable, Fps refreshRate);
void resync() EXCLUDES(mDisplayLock);
void forceNextResync() { mLastResyncTime = 0; }
- // Passes a vsync sample to VsyncController. periodFlushed will be true if
- // VsyncController detected that the vsync period changed, and false otherwise.
- void addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
- bool* periodFlushed);
+ // Passes a vsync sample to VsyncController. Returns true if
+ // VsyncController detected that the vsync period changed and false
+ // otherwise.
+ bool addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod);
void addPresentFence(std::shared_ptr<FenceTime>);
// Layers are registered on creation, and unregistered when the weak reference expires.
@@ -297,7 +288,6 @@
void touchTimerCallback(TimerState);
void displayPowerTimerCallback(TimerState);
- void setVsyncPeriod(nsecs_t period);
void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod);
// Chooses a leader among the registered displays, unless `leaderIdOpt` is specified. The new
@@ -362,14 +352,10 @@
ConnectionHandle mAppConnectionHandle;
ConnectionHandle mSfConnectionHandle;
- mutable std::mutex mHWVsyncLock;
- bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock) = false;
- bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock) = false;
-
std::atomic<nsecs_t> mLastResyncTime = 0;
const FeatureFlags mFeatures;
- std::optional<VsyncSchedule> mVsyncSchedule;
+ std::unique_ptr<VsyncSchedule> mVsyncSchedule;
// Shifts the VSYNC phase during certain transactions and refresh rate changes.
const sp<VsyncModulator> mVsyncModulator;
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 02e12fd..f8cb323 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -31,8 +31,8 @@
#include <android-base/stringprintf.h>
#include <cutils/compiler.h>
#include <cutils/properties.h>
+#include <gui/TraceUtils.h>
#include <utils/Log.h>
-#include <utils/Trace.h>
#include "RefreshRateSelector.h"
#include "VSyncPredictor.h"
@@ -282,6 +282,13 @@
}
bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) const {
+ const TimePoint now = TimePoint::now();
+ const auto getTimePointIn = [](TimePoint now, nsecs_t timePoint) -> float {
+ return ticks<std::milli, float>(TimePoint::fromNs(timePoint) - now);
+ };
+ ATRACE_FORMAT("%s timePoint in: %.2f divisor: %zu", __func__, getTimePointIn(now, timePoint),
+ divisor);
+
struct VsyncError {
nsecs_t vsyncTimestamp;
float error;
@@ -304,6 +311,7 @@
if (knownTimestampIter == mRateDivisorKnownTimestampMap.end()) {
const auto vsync = nextAnticipatedVSyncTimeFromLocked(justBeforeTimePoint);
mRateDivisorKnownTimestampMap[dividedPeriod] = vsync;
+ ATRACE_FORMAT_INSTANT("(first) knownVsync in: %.2f", getTimePointIn(now, vsync));
return true;
}
@@ -323,6 +331,8 @@
const auto minVsyncError = std::min_element(vsyncs.begin(), vsyncs.end());
mRateDivisorKnownTimestampMap[dividedPeriod] = minVsyncError->vsyncTimestamp;
+ ATRACE_FORMAT_INSTANT("knownVsync in: %.2f",
+ getTimePointIn(now, minVsyncError->vsyncTimestamp));
return std::abs(minVsyncError->vsyncTimestamp - timePoint) < period / 2;
}
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
index 95bc31f..5245556 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
@@ -16,11 +16,14 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <ftl/fake_guard.h>
#include <scheduler/Fps.h>
#include <scheduler/Timer.h>
#include "VsyncSchedule.h"
+#include "ISchedulerCallback.h"
+#include "Utils/Dumper.h"
#include "VSyncDispatchTimerQueue.h"
#include "VSyncPredictor.h"
#include "VSyncReactor.h"
@@ -54,18 +57,16 @@
VsyncSchedule::VsyncSchedule(FeatureFlags features)
: mTracker(createTracker()),
mDispatch(createDispatch(*mTracker)),
- mController(createController(*mTracker, features)) {
- if (features.test(Feature::kTracePredictedVsync)) {
- mTracer = std::make_unique<PredictedVsyncTracer>(*mDispatch);
- }
-}
+ mController(createController(*mTracker, features)),
+ mTracer(features.test(Feature::kTracePredictedVsync)
+ ? std::make_unique<PredictedVsyncTracer>(*mDispatch)
+ : nullptr) {}
VsyncSchedule::VsyncSchedule(TrackerPtr tracker, DispatchPtr dispatch, ControllerPtr controller)
: mTracker(std::move(tracker)),
mDispatch(std::move(dispatch)),
mController(std::move(controller)) {}
-VsyncSchedule::VsyncSchedule(VsyncSchedule&&) = default;
VsyncSchedule::~VsyncSchedule() = default;
Period VsyncSchedule::period() const {
@@ -77,6 +78,16 @@
}
void VsyncSchedule::dump(std::string& out) const {
+ utils::Dumper dumper(out);
+ {
+ std::lock_guard<std::mutex> lock(mHwVsyncLock);
+ dumper.dump("hwVsyncState", ftl::enum_string(mHwVsyncState));
+
+ ftl::FakeGuard guard(kMainThreadContext);
+ dumper.dump("pendingHwVsyncState", ftl::enum_string(mPendingHwVsyncState));
+ dumper.eol();
+ }
+
out.append("VsyncController:\n");
mController->dump(out);
@@ -120,4 +131,67 @@
return reactor;
}
+void VsyncSchedule::startPeriodTransition(ISchedulerCallback& callback, Period period) {
+ std::lock_guard<std::mutex> lock(mHwVsyncLock);
+ mController->startPeriodTransition(period.ns());
+ enableHardwareVsyncLocked(callback);
+}
+
+bool VsyncSchedule::addResyncSample(ISchedulerCallback& callback, TimePoint timestamp,
+ ftl::Optional<Period> hwcVsyncPeriod) {
+ bool needsHwVsync = false;
+ bool periodFlushed = false;
+ {
+ std::lock_guard<std::mutex> lock(mHwVsyncLock);
+ if (mHwVsyncState == HwVsyncState::Enabled) {
+ needsHwVsync = mController->addHwVsyncTimestamp(timestamp.ns(),
+ hwcVsyncPeriod.transform(&Period::ns),
+ &periodFlushed);
+ }
+ }
+ if (needsHwVsync) {
+ enableHardwareVsync(callback);
+ } else {
+ disableHardwareVsync(callback, false /* disallow */);
+ }
+ return periodFlushed;
+}
+
+void VsyncSchedule::enableHardwareVsync(ISchedulerCallback& callback) {
+ std::lock_guard<std::mutex> lock(mHwVsyncLock);
+ enableHardwareVsyncLocked(callback);
+}
+
+void VsyncSchedule::enableHardwareVsyncLocked(ISchedulerCallback& callback) {
+ if (mHwVsyncState == HwVsyncState::Disabled) {
+ getTracker().resetModel();
+ callback.setVsyncEnabled(true);
+ mHwVsyncState = HwVsyncState::Enabled;
+ }
+}
+
+void VsyncSchedule::disableHardwareVsync(ISchedulerCallback& callback, bool disallow) {
+ std::lock_guard<std::mutex> lock(mHwVsyncLock);
+ if (mHwVsyncState == HwVsyncState::Enabled) {
+ callback.setVsyncEnabled(false);
+ }
+ mHwVsyncState = disallow ? HwVsyncState::Disallowed : HwVsyncState::Disabled;
+}
+
+bool VsyncSchedule::isHardwareVsyncAllowed(bool makeAllowed) {
+ std::lock_guard<std::mutex> lock(mHwVsyncLock);
+ if (makeAllowed && mHwVsyncState == HwVsyncState::Disallowed) {
+ mHwVsyncState = HwVsyncState::Disabled;
+ }
+ return mHwVsyncState != HwVsyncState::Disallowed;
+}
+
+void VsyncSchedule::setPendingHardwareVsyncState(bool enabled) {
+ mPendingHwVsyncState = enabled ? HwVsyncState::Enabled : HwVsyncState::Disabled;
+}
+
+bool VsyncSchedule::getPendingHardwareVsyncState() const {
+ return mPendingHwVsyncState == HwVsyncState::Enabled;
+}
+
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h
index 173b1d0..d88f1d1 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.h
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h
@@ -19,6 +19,9 @@
#include <memory>
#include <string>
+#include <ThreadContext.h>
+#include <ftl/enum.h>
+#include <ftl/optional.h>
#include <scheduler/Features.h>
#include <scheduler/Time.h>
@@ -32,6 +35,8 @@
namespace android::scheduler {
+struct ISchedulerCallback;
+
// TODO(b/185535769): Rename classes, and remove aliases.
class VSyncDispatch;
class VSyncTracker;
@@ -44,12 +49,24 @@
class VsyncSchedule {
public:
explicit VsyncSchedule(FeatureFlags);
- VsyncSchedule(VsyncSchedule&&);
~VsyncSchedule();
Period period() const;
TimePoint vsyncDeadlineAfter(TimePoint) const;
+ // Inform the schedule that the period is changing and the schedule needs to recalibrate
+ // itself. The schedule will end the period transition internally. This will
+ // enable hardware VSYNCs in order to calibrate.
+ //
+ // \param [in] period The period that the system is changing into.
+ void startPeriodTransition(ISchedulerCallback&, Period period);
+
+ // Pass a VSYNC sample to VsyncController. Return true if
+ // VsyncController detected that the VSYNC period changed. Enable or disable
+ // hardware VSYNCs depending on whether more samples are needed.
+ bool addResyncSample(ISchedulerCallback&, TimePoint timestamp,
+ ftl::Optional<Period> hwcVsyncPeriod);
+
// TODO(b/185535769): Hide behind API.
const VsyncTracker& getTracker() const { return *mTracker; }
VsyncTracker& getTracker() { return *mTracker; }
@@ -60,6 +77,22 @@
void dump(std::string&) const;
+ // Turn on hardware VSYNCs, unless mHwVsyncState is Disallowed, in which
+ // case this call is ignored.
+ void enableHardwareVsync(ISchedulerCallback&) EXCLUDES(mHwVsyncLock);
+
+ // Disable hardware VSYNCs. If `disallow` is true, future calls to
+ // enableHardwareVsync are ineffective until allowHardwareVsync is called.
+ void disableHardwareVsync(ISchedulerCallback&, bool disallow) EXCLUDES(mHwVsyncLock);
+
+ // If true, enableHardwareVsync can enable hardware VSYNC (if not already
+ // enabled). If false, enableHardwareVsync does nothing.
+ bool isHardwareVsyncAllowed(bool makeAllowed) EXCLUDES(mHwVsyncLock);
+
+ void setPendingHardwareVsyncState(bool enabled) REQUIRES(kMainThreadContext);
+
+ bool getPendingHardwareVsyncState() const REQUIRES(kMainThreadContext);
+
private:
friend class TestableScheduler;
friend class android::EventThreadTest;
@@ -76,14 +109,36 @@
static DispatchPtr createDispatch(VsyncTracker&);
static ControllerPtr createController(VsyncTracker&, FeatureFlags);
+ void enableHardwareVsyncLocked(ISchedulerCallback&) REQUIRES(mHwVsyncLock);
+
+ mutable std::mutex mHwVsyncLock;
+ enum class HwVsyncState {
+ // Hardware VSYNCs are currently enabled.
+ Enabled,
+
+ // Hardware VSYNCs are currently disabled. They can be enabled by a call
+ // to `enableHardwareVsync`.
+ Disabled,
+
+ // Hardware VSYNCs are not currently allowed (e.g. because the display
+ // is off).
+ Disallowed,
+
+ ftl_last = Disallowed,
+ };
+ HwVsyncState mHwVsyncState GUARDED_BY(mHwVsyncLock) = HwVsyncState::Disallowed;
+
+ // Pending state, in case an attempt is made to set the state while the
+ // device is off.
+ HwVsyncState mPendingHwVsyncState GUARDED_BY(kMainThreadContext) = HwVsyncState::Disabled;
+
class PredictedVsyncTracer;
using TracerPtr = std::unique_ptr<PredictedVsyncTracer>;
- // Effectively const except in move constructor.
- TrackerPtr mTracker;
- DispatchPtr mDispatch;
- ControllerPtr mController;
- TracerPtr mTracer;
+ const TrackerPtr mTracker;
+ const DispatchPtr mDispatch;
+ const ControllerPtr mController;
+ const TracerPtr mTracer;
};
} // namespace android::scheduler
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index c88757a..c76e41f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2037,8 +2037,7 @@
return;
}
- bool periodFlushed = false;
- mScheduler->addResyncSample(timestamp, vsyncPeriod, &periodFlushed);
+ const bool periodFlushed = mScheduler->addResyncSample(timestamp, vsyncPeriod);
if (periodFlushed) {
mScheduler->modulateVsync(&VsyncModulator::onRefreshRateChangeCompleted);
}
@@ -2086,11 +2085,14 @@
// On main thread to avoid race conditions with display power state.
static_cast<void>(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
- mHWCVsyncPendingState = enabled ? hal::Vsync::ENABLE : hal::Vsync::DISABLE;
+ {
+ ftl::FakeGuard guard(kMainThreadContext);
+ mScheduler->getVsyncSchedule().setPendingHardwareVsyncState(enabled);
+ }
if (const auto display = getDefaultDisplayDeviceLocked();
display && display->isPoweredOn()) {
- setHWCVsyncEnabled(display->getPhysicalId(), mHWCVsyncPendingState);
+ setHWCVsyncEnabled(display->getPhysicalId(), enabled);
}
}));
}
@@ -4161,7 +4163,7 @@
transaction.displays, transaction.flags,
transaction.inputWindowCommands,
transaction.desiredPresentTime, transaction.isAutoTimestamp,
- std::move(transaction.uncacheBufferIds), transaction.postTime,
+ transaction.buffer, transaction.postTime,
transaction.permissions, transaction.hasListenerCallbacks,
transaction.listenerCallbacks, transaction.originPid,
transaction.originUid, transaction.id);
@@ -4249,9 +4251,8 @@
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states,
const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
- bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers,
- bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
- uint64_t transactionId) {
+ bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
ATRACE_CALL();
uint32_t permissions =
@@ -4285,15 +4286,6 @@
const int originPid = ipc->getCallingPid();
const int originUid = ipc->getCallingUid();
- std::vector<uint64_t> uncacheBufferIds;
- uncacheBufferIds.reserve(uncacheBuffers.size());
- for (const auto& uncacheBuffer : uncacheBuffers) {
- sp<GraphicBuffer> buffer = ClientCache::getInstance().erase(uncacheBuffer);
- if (buffer != nullptr) {
- uncacheBufferIds.push_back(buffer->getId());
- }
- }
-
std::vector<ResolvedComposerState> resolvedStates;
resolvedStates.reserve(states.size());
for (auto& state : states) {
@@ -4311,22 +4303,14 @@
}
}
- TransactionState state{frameTimelineInfo,
- resolvedStates,
- displays,
- flags,
- applyToken,
- inputWindowCommands,
- desiredPresentTime,
- isAutoTimestamp,
- std::move(uncacheBufferIds),
- postTime,
- permissions,
- hasListenerCallbacks,
- listenerCallbacks,
- originPid,
- originUid,
- transactionId};
+ TransactionState state{frameTimelineInfo, resolvedStates,
+ displays, flags,
+ applyToken, inputWindowCommands,
+ desiredPresentTime, isAutoTimestamp,
+ uncacheBuffer, postTime,
+ permissions, hasListenerCallbacks,
+ listenerCallbacks, originPid,
+ originUid, transactionId};
if (mTransactionTracing) {
mTransactionTracing->addQueuedTransaction(state);
@@ -4349,7 +4333,7 @@
Vector<DisplayState>& displays, uint32_t flags,
const InputWindowCommands& inputWindowCommands,
const int64_t desiredPresentTime, bool isAutoTimestamp,
- const std::vector<uint64_t>& uncacheBufferIds,
+ const client_cache_t& uncacheBuffer,
const int64_t postTime, uint32_t permissions,
bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks,
@@ -4399,8 +4383,11 @@
ALOGE("Only privileged callers are allowed to send input commands.");
}
- for (uint64_t uncacheBufferId : uncacheBufferIds) {
- mBufferIdsToUncache.push_back(uncacheBufferId);
+ if (uncacheBuffer.isValid()) {
+ sp<GraphicBuffer> buffer = ClientCache::getInstance().erase(uncacheBuffer);
+ if (buffer != nullptr) {
+ mBufferIdsToUncache.push_back(buffer->getId());
+ }
}
// If a synchronous transaction is explicitly requested without any changes, force a transaction
@@ -5243,7 +5230,8 @@
}
getHwComposer().setPowerMode(displayId, mode);
if (isActiveDisplay && mode != hal::PowerMode::DOZE_SUSPEND) {
- setHWCVsyncEnabled(displayId, mHWCVsyncPendingState);
+ setHWCVsyncEnabled(displayId,
+ mScheduler->getVsyncSchedule().getPendingHardwareVsyncState());
mScheduler->onScreenAcquired(mAppConnectionHandle);
mScheduler->resyncToHardwareVsync(true, refreshRate);
}
@@ -5264,7 +5252,7 @@
}
// Make sure HWVsync is disabled before turning off the display
- setHWCVsyncEnabled(displayId, hal::Vsync::DISABLE);
+ setHWCVsyncEnabled(displayId, false);
getHwComposer().setPowerMode(displayId, mode);
mVisibleRegionsDirty = true;
@@ -5473,14 +5461,6 @@
mScheduler->dump(dumper);
- // TODO(b/241286146): Move to Scheduler.
- {
- utils::Dumper::Indent indent(dumper);
- dumper.dump("lastHwcVsyncState"sv, mLastHWCVsyncState);
- dumper.dump("pendingHwcVsyncState"sv, mHWCVsyncPendingState);
- }
- dumper.eol();
-
// TODO(b/241285876): Move to DisplayModeController.
dumper.dump("debugDisplayModeSetByBackdoor"sv, mDebugDisplayModeSetByBackdoor);
dumper.eol();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5b8038b..8866a6d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -76,6 +76,7 @@
#include "FrontEnd/LayerSnapshotBuilder.h"
#include "FrontEnd/TransactionHandler.h"
#include "LayerVector.h"
+#include "Scheduler/ISchedulerCallback.h"
#include "Scheduler/RefreshRateSelector.h"
#include "Scheduler/RefreshRateStats.h"
#include "Scheduler/Scheduler.h"
@@ -521,8 +522,7 @@
uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
int64_t desiredPresentTime, bool isAutoTimestamp,
- const std::vector<client_cache_t>& uncacheBuffers,
- bool hasListenerCallbacks,
+ const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks,
uint64_t transactionId) override;
void bootFinished();
@@ -735,14 +735,16 @@
/*
* Transactions
*/
- bool applyTransactionState(
- const FrameTimelineInfo& info, std::vector<ResolvedComposerState>& state,
- Vector<DisplayState>& displays, uint32_t flags,
- const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
- bool isAutoTimestamp, const std::vector<uint64_t>& uncacheBufferIds,
- const int64_t postTime, uint32_t permissions, bool hasListenerCallbacks,
- const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid,
- uint64_t transactionId) REQUIRES(mStateLock);
+ bool applyTransactionState(const FrameTimelineInfo& info,
+ std::vector<ResolvedComposerState>& state,
+ Vector<DisplayState>& displays, uint32_t flags,
+ const InputWindowCommands& inputWindowCommands,
+ const int64_t desiredPresentTime, bool isAutoTimestamp,
+ const client_cache_t& uncacheBuffer, const int64_t postTime,
+ uint32_t permissions, bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks,
+ int originPid, int originUid, uint64_t transactionId)
+ REQUIRES(mStateLock);
// Flush pending transactions that were presented after desiredPresentTime.
// For test only
bool flushTransactionQueues(VsyncId) REQUIRES(kMainThreadContext);
@@ -992,9 +994,9 @@
*/
nsecs_t getVsyncPeriodFromHWC() const REQUIRES(mStateLock);
- void setHWCVsyncEnabled(PhysicalDisplayId id, hal::Vsync enabled) {
- mLastHWCVsyncState = enabled;
- getHwComposer().setVsyncEnabled(id, enabled);
+ void setHWCVsyncEnabled(PhysicalDisplayId id, bool enabled) {
+ hal::Vsync halState = enabled ? hal::Vsync::ENABLE : hal::Vsync::DISABLE;
+ getHwComposer().setVsyncEnabled(id, halState);
}
using FenceTimePtr = std::shared_ptr<FenceTime>;
@@ -1321,9 +1323,6 @@
TimePoint mScheduledPresentTime GUARDED_BY(kMainThreadContext);
TimePoint mExpectedPresentTime GUARDED_BY(kMainThreadContext);
- hal::Vsync mHWCVsyncPendingState = hal::Vsync::DISABLE;
- hal::Vsync mLastHWCVsyncState = hal::Vsync::DISABLE;
-
// below flags are set by main thread only
bool mSetActiveModePending = false;
diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h
index 6c5a8b2..aeca56e 100644
--- a/services/surfaceflinger/TransactionState.h
+++ b/services/surfaceflinger/TransactionState.h
@@ -49,7 +49,7 @@
const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands,
int64_t desiredPresentTime, bool isAutoTimestamp,
- std::vector<uint64_t> uncacheBufferIds, int64_t postTime, uint32_t permissions,
+ const client_cache_t& uncacheBuffer, int64_t postTime, uint32_t permissions,
bool hasListenerCallbacks, std::vector<ListenerCallbacks> listenerCallbacks,
int originPid, int originUid, uint64_t transactionId)
: frameTimelineInfo(frameTimelineInfo),
@@ -60,7 +60,7 @@
inputWindowCommands(inputWindowCommands),
desiredPresentTime(desiredPresentTime),
isAutoTimestamp(isAutoTimestamp),
- uncacheBufferIds(std::move(uncacheBufferIds)),
+ buffer(uncacheBuffer),
postTime(postTime),
permissions(permissions),
hasListenerCallbacks(hasListenerCallbacks),
@@ -121,7 +121,7 @@
InputWindowCommands inputWindowCommands;
int64_t desiredPresentTime;
bool isAutoTimestamp;
- std::vector<uint64_t> uncacheBufferIds;
+ client_cache_t buffer;
int64_t postTime;
uint32_t permissions;
bool hasListenerCallbacks;
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index cdffbb4..7695459 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -234,7 +234,8 @@
std::shared_ptr<RefreshRateSelector> selectorPtr,
sp<VsyncModulator> modulatorPtr, ISchedulerCallback& callback)
: Scheduler(*this, callback, Feature::kContentDetection, std::move(modulatorPtr)) {
- mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller)));
+ mVsyncSchedule = std::unique_ptr<VsyncSchedule>(
+ new VsyncSchedule(std::move(tracker), nullptr, std::move(controller)));
const auto displayId = selectorPtr->getActiveMode().modePtr->getPhysicalDisplayId();
registerDisplay(displayId, std::move(selectorPtr));
@@ -244,9 +245,6 @@
return Scheduler::createConnection(std::move(eventThread));
}
- auto &mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; }
- auto &mutableHWVsyncAvailable() { return mHWVsyncAvailable; }
-
auto &mutableLayerHistory() { return mLayerHistory; }
auto refreshRateSelector() { return leaderSelectorPtr(); }
@@ -739,18 +737,17 @@
return mFlinger->mTransactionHandler.mPendingTransactionQueues;
}
- auto setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
- Vector<ComposerState>& states, const Vector<DisplayState>& displays,
- uint32_t flags, const sp<IBinder>& applyToken,
- const InputWindowCommands& inputWindowCommands,
+ auto setTransactionState(const FrameTimelineInfo &frameTimelineInfo,
+ Vector<ComposerState> &states, const Vector<DisplayState> &displays,
+ uint32_t flags, const sp<IBinder> &applyToken,
+ const InputWindowCommands &inputWindowCommands,
int64_t desiredPresentTime, bool isAutoTimestamp,
- const std::vector<client_cache_t>& uncacheBuffers,
- bool hasListenerCallbacks,
- std::vector<ListenerCallbacks>& listenerCallbacks,
+ const client_cache_t &uncacheBuffer, bool hasListenerCallbacks,
+ std::vector<ListenerCallbacks> &listenerCallbacks,
uint64_t transactionId) {
return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken,
inputWindowCommands, desiredPresentTime,
- isAutoTimestamp, uncacheBuffers, hasListenerCallbacks,
+ isAutoTimestamp, uncacheBuffer, hasListenerCallbacks,
listenerCallbacks, transactionId);
}
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index 44805db..61fb29a 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -76,7 +76,7 @@
FuzzedDataProvider mFdp;
- std::optional<scheduler::VsyncSchedule> mVsyncSchedule;
+ std::unique_ptr<scheduler::VsyncSchedule> mVsyncSchedule;
};
PhysicalDisplayId SchedulerFuzzer::getPhysicalDisplayId() {
@@ -90,9 +90,9 @@
}
void SchedulerFuzzer::fuzzEventThread() {
- mVsyncSchedule.emplace(scheduler::VsyncSchedule(std::make_unique<mock::VSyncTracker>(),
- std::make_unique<mock::VSyncDispatch>(),
- nullptr));
+ mVsyncSchedule = std::unique_ptr<scheduler::VsyncSchedule>(
+ new scheduler::VsyncSchedule(std::make_unique<mock::VSyncTracker>(),
+ std::make_unique<mock::VSyncDispatch>(), nullptr));
const auto getVsyncPeriod = [](uid_t /* uid */) { return kSyncPeriod.count(); };
std::unique_ptr<android::impl::EventThread> thread = std::make_unique<
android::impl::EventThread>("fuzzer", *mVsyncSchedule, nullptr, nullptr, getVsyncPeriod,
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index fedd71e..0495678 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -139,11 +139,6 @@
set_sched_policy(0, SP_FOREGROUND);
- // Put most SurfaceFlinger threads in the system-background cpuset
- // Keeps us from unnecessarily using big cores
- // Do this after the binder thread pool init
- if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);
-
// initialize before clients can connect
flinger->init();
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index b3aba37..f6bcadc 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -125,7 +125,7 @@
ConnectionEventRecorder mConnectionEventCallRecorder{0};
ConnectionEventRecorder mThrottledConnectionEventCallRecorder{0};
- std::optional<scheduler::VsyncSchedule> mVsyncSchedule;
+ std::unique_ptr<scheduler::VsyncSchedule> mVsyncSchedule;
std::unique_ptr<impl::EventThread> mThread;
sp<MockEventThreadConnection> mConnection;
sp<MockEventThreadConnection> mThrottledConnection;
@@ -140,9 +140,9 @@
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
- mVsyncSchedule.emplace(scheduler::VsyncSchedule(std::make_unique<mock::VSyncTracker>(),
- std::make_unique<mock::VSyncDispatch>(),
- nullptr));
+ mVsyncSchedule = std::unique_ptr<scheduler::VsyncSchedule>(
+ new scheduler::VsyncSchedule(std::make_unique<mock::VSyncTracker>(),
+ std::make_unique<mock::VSyncDispatch>(), nullptr));
mock::VSyncDispatch& mockDispatch =
*static_cast<mock::VSyncDispatch*>(&mVsyncSchedule->getDispatch());
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
index ab732ed..88ddb0f 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
@@ -262,8 +262,8 @@
return display;
}
- static void setInitialPrimaryHWVsyncEnabled(DisplayTransactionTest* test, bool enabled) {
- test->mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled() = enabled;
+ static void setInitialHwVsyncEnabled(DisplayTransactionTest* test, bool enabled) {
+ test->mFlinger.scheduler()->setInitialHwVsyncEnabled(enabled);
}
static void setupRepaintEverythingCallExpectations(DisplayTransactionTest* test) {
@@ -329,9 +329,9 @@
Case::Doze::setupComposerCallExpectations(this);
auto display =
Case::injectDisplayWithInitialPowerMode(this, Case::Transition::INITIAL_POWER_MODE);
- Case::setInitialPrimaryHWVsyncEnabled(this,
- PowerModeInitialVSyncEnabled<
- Case::Transition::INITIAL_POWER_MODE>::value);
+ Case::setInitialHwVsyncEnabled(this,
+ PowerModeInitialVSyncEnabled<
+ Case::Transition::INITIAL_POWER_MODE>::value);
// --------------------------------------------------------------------
// Call Expectations
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 6cf6141..bd3f3ca 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -44,9 +44,9 @@
std::unique_ptr<VSyncTracker> tracker, RefreshRateSelectorPtr selectorPtr,
sp<VsyncModulator> modulatorPtr, ISchedulerCallback& callback)
: Scheduler(*this, callback, Feature::kContentDetection, std::move(modulatorPtr)) {
- mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker),
- std::make_unique<mock::VSyncDispatch>(),
- std::move(controller)));
+ mVsyncSchedule = std::unique_ptr<VsyncSchedule>(
+ new VsyncSchedule(std::move(tracker), std::make_unique<mock::VSyncDispatch>(),
+ std::move(controller)));
const auto displayId = selectorPtr->getActiveMode().modePtr->getPhysicalDisplayId();
registerDisplay(displayId, std::move(selectorPtr));
@@ -66,13 +66,6 @@
return Scheduler::createConnection(std::move(eventThread));
}
- /* ------------------------------------------------------------------------
- * Read-write access to private data to set up preconditions and assert
- * post-conditions.
- */
- auto& mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; }
- auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; }
-
auto refreshRateSelector() { return leaderSelectorPtr(); }
const auto& refreshRateSelectors() const NO_THREAD_SAFETY_ANALYSIS {
@@ -157,6 +150,12 @@
Scheduler::onNonPrimaryDisplayModeChanged(handle, mode);
}
+ void setInitialHwVsyncEnabled(bool enabled) {
+ std::lock_guard<std::mutex> lock(mVsyncSchedule->mHwVsyncLock);
+ mVsyncSchedule->mHwVsyncState = enabled ? VsyncSchedule::HwVsyncState::Enabled
+ : VsyncSchedule::HwVsyncState::Disabled;
+ }
+
private:
// ICompositor overrides:
void configure() override {}
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 68c738f..e03f6cc 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -440,13 +440,12 @@
uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
int64_t desiredPresentTime, bool isAutoTimestamp,
- const std::vector<client_cache_t>& uncacheBuffers,
- bool hasListenerCallbacks,
+ const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
std::vector<ListenerCallbacks>& listenerCallbacks,
uint64_t transactionId) {
return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken,
inputWindowCommands, desiredPresentTime,
- isAutoTimestamp, uncacheBuffers, hasListenerCallbacks,
+ isAutoTimestamp, uncacheBuffer, hasListenerCallbacks,
listenerCallbacks, transactionId);
}
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 859f702..981e9d2 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -102,7 +102,7 @@
int64_t desiredPresentTime = 0;
bool isAutoTimestamp = true;
FrameTimelineInfo frameTimelineInfo;
- std::vector<client_cache_t> uncacheBuffers;
+ client_cache_t uncacheBuffer;
uint64_t id = static_cast<uint64_t>(-1);
static_assert(0xffffffffffffffff == static_cast<uint64_t>(-1));
};
@@ -138,7 +138,7 @@
transaction.displays, transaction.flags,
transaction.applyToken, transaction.inputWindowCommands,
transaction.desiredPresentTime, transaction.isAutoTimestamp,
- transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
+ transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
transaction.id);
// If transaction is synchronous, SF applyTransactionState should time out (5s) wating for
@@ -165,7 +165,7 @@
transaction.displays, transaction.flags,
transaction.applyToken, transaction.inputWindowCommands,
transaction.desiredPresentTime, transaction.isAutoTimestamp,
- transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
+ transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
transaction.id);
nsecs_t returnedTime = systemTime();
@@ -196,7 +196,7 @@
transactionA.displays, transactionA.flags,
transactionA.applyToken, transactionA.inputWindowCommands,
transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
- transactionA.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
+ transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
transactionA.id);
// This thread should not have been blocked by the above transaction
@@ -211,7 +211,7 @@
transactionB.displays, transactionB.flags,
transactionB.applyToken, transactionB.inputWindowCommands,
transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
- transactionB.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
+ transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
transactionB.id);
// this thread should have been blocked by the above transaction
@@ -248,7 +248,7 @@
mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
transactionA.displays, transactionA.flags, transactionA.applyToken,
transactionA.inputWindowCommands, transactionA.desiredPresentTime,
- transactionA.isAutoTimestamp, transactionA.uncacheBuffers,
+ transactionA.isAutoTimestamp, transactionA.uncacheBuffer,
mHasListenerCallbacks, mCallbacks, transactionA.id);
auto& transactionQueue = mFlinger.getTransactionQueue();
@@ -268,7 +268,7 @@
mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
transactionA.displays, transactionA.flags, transactionA.applyToken,
transactionA.inputWindowCommands, transactionA.desiredPresentTime,
- transactionA.isAutoTimestamp, transactionA.uncacheBuffers,
+ transactionA.isAutoTimestamp, transactionA.uncacheBuffer,
mHasListenerCallbacks, mCallbacks, transactionA.id);
auto& transactionQueue = mFlinger.getTransactionQueue();
@@ -282,7 +282,7 @@
mFlinger.setTransactionState(empty.frameTimelineInfo, empty.states, empty.displays, empty.flags,
empty.applyToken, empty.inputWindowCommands,
empty.desiredPresentTime, empty.isAutoTimestamp,
- empty.uncacheBuffers, mHasListenerCallbacks, mCallbacks, empty.id);
+ empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id);
// flush transaction queue should flush as desiredPresentTime has
// passed
@@ -379,7 +379,8 @@
transaction.applyToken,
transaction.inputWindowCommands,
transaction.desiredPresentTime,
- transaction.isAutoTimestamp, {}, systemTime(), 0,
+ transaction.isAutoTimestamp,
+ transaction.uncacheBuffer, systemTime(), 0,
mHasListenerCallbacks, mCallbacks, getpid(),
static_cast<int>(getuid()), transaction.id);
mFlinger.setTransactionStateInternal(transactionState);