Merge "Fix inverted logic in isOperationRestricted"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 21de4db..ea266e5 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -54,7 +54,9 @@
#include <android/os/IIncidentCompanion.h>
#include <cutils/native_handle.h>
#include <cutils/properties.h>
+#include <debuggerd/client.h>
#include <dumpsys.h>
+#include <dumputils/dump_utils.h>
#include <hidl/ServiceManagement.h>
#include <openssl/sha.h>
#include <private/android_filesystem_config.h>
@@ -1450,7 +1452,7 @@
RunDumpsysCritical();
/* collect stack traces from Dalvik and native processes (needs root) */
- dump_traces_path = dump_traces();
+ dump_traces_path = ds.DumpTraces();
/* Run some operations that require root. */
ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
@@ -1587,6 +1589,114 @@
printf("========================================================\n");
}
+const char* Dumpstate::DumpTraces() {
+ DurationReporter duration_reporter("DUMP TRACES");
+
+ const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
+ const size_t buf_size = temp_file_pattern.length() + 1;
+ std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
+ memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
+
+ // Create a new, empty file to receive all trace dumps.
+ //
+ // TODO: This can be simplified once we remove support for the old style
+ // dumps. We can have a file descriptor passed in to dump_traces instead
+ // of creating a file, closing it and then reopening it again.
+ android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
+ if (fd < 0) {
+ MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
+ return nullptr;
+ }
+
+ // Nobody should have access to this temporary file except dumpstate, but we
+ // temporarily grant 'read' to 'others' here because this file is created
+ // when tombstoned is still running as root, but dumped after dropping. This
+ // can go away once support for old style dumping has.
+ const int chmod_ret = fchmod(fd, 0666);
+ if (chmod_ret < 0) {
+ MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
+ return nullptr;
+ }
+
+ std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
+ if (proc.get() == nullptr) {
+ MYLOGE("opendir /proc failed: %s\n", strerror(errno));
+ return nullptr;
+ }
+
+ // Number of times process dumping has timed out. If we encounter too many
+ // failures, we'll give up.
+ int timeout_failures = 0;
+ bool dalvik_found = false;
+
+ const std::set<int> hal_pids = get_interesting_hal_pids();
+
+ struct dirent* d;
+ while ((d = readdir(proc.get()))) {
+ int pid = atoi(d->d_name);
+ if (pid <= 0) {
+ continue;
+ }
+
+ const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
+ std::string exe;
+ if (!android::base::Readlink(link_name, &exe)) {
+ continue;
+ }
+
+ bool is_java_process;
+ if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
+ // Don't bother dumping backtraces for the zygote.
+ if (IsZygote(pid)) {
+ continue;
+ }
+
+ dalvik_found = true;
+ is_java_process = true;
+ } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
+ is_java_process = false;
+ } else {
+ // Probably a native process we don't care about, continue.
+ continue;
+ }
+
+ // If 3 backtrace dumps fail in a row, consider debuggerd dead.
+ if (timeout_failures == 3) {
+ dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
+ break;
+ }
+
+ const uint64_t start = Nanotime();
+ const int ret = dump_backtrace_to_file_timeout(
+ pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
+ is_java_process ? 5 : 20, fd);
+
+ if (ret == -1) {
+ // For consistency, the header and footer to this message match those
+ // dumped by debuggerd in the success case.
+ dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
+ dprintf(fd, "Dump failed, likely due to a timeout.\n");
+ dprintf(fd, "---- end %d ----", pid);
+ timeout_failures++;
+ continue;
+ }
+
+ // We've successfully dumped stack traces, reset the failure count
+ // and write a summary of the elapsed time to the file and continue with the
+ // next process.
+ timeout_failures = 0;
+
+ dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
+ pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
+ }
+
+ if (!dalvik_found) {
+ MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
+ }
+
+ return file_name_buf.release();
+}
+
void Dumpstate::DumpstateBoard() {
DurationReporter duration_reporter("dumpstate_board()");
printf("========================================================\n");
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index c326bb6..603af71 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -73,13 +73,13 @@
*/
class DurationReporter {
public:
- explicit DurationReporter(const std::string& title, bool log_only = false);
+ explicit DurationReporter(const std::string& title, bool logcat_only = false);
~DurationReporter();
private:
std::string title_;
- bool log_only_;
+ bool logcat_only_;
uint64_t started_;
DISALLOW_COPY_AND_ASSIGN(DurationReporter);
@@ -291,6 +291,9 @@
// TODO: temporary method until Dumpstate object is properly set
void SetProgress(std::unique_ptr<Progress> progress);
+ // Dumps Dalvik and native stack traces, return the trace file location (nullptr if none).
+ const char* DumpTraces();
+
void DumpstateBoard();
/*
@@ -543,9 +546,6 @@
/* create leading directories, if necessary */
void create_parent_dirs(const char *path);
-/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
-const char *dump_traces();
-
/* for each process in the system, run the specified function */
void for_each_pid(for_each_pid_func func, const char *header);
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 2a5516d..8b92988 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -50,8 +50,6 @@
#include <android-base/unique_fd.h>
#include <cutils/properties.h>
#include <cutils/sockets.h>
-#include <debuggerd/client.h>
-#include <dumputils/dump_utils.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
@@ -95,8 +93,8 @@
return singleton_;
}
-DurationReporter::DurationReporter(const std::string& title, bool log_only)
- : title_(title), log_only_(log_only) {
+DurationReporter::DurationReporter(const std::string& title, bool logcat_only)
+ : title_(title), logcat_only_(logcat_only) {
if (!title_.empty()) {
started_ = Nanotime();
}
@@ -105,15 +103,13 @@
DurationReporter::~DurationReporter() {
if (!title_.empty()) {
uint64_t elapsed = Nanotime() - started_;
- if (log_only_) {
- MYLOGD("Duration of '%s': %.3fs\n", title_.c_str(), (float)elapsed / NANOS_PER_SEC);
- } else {
- // TODO(124089395): Remove or rewrite when bugreport latency is fixed.
- MYLOGD("Duration of '%s': %.3fs\n", title_.c_str(), (float)elapsed / NANOS_PER_SEC);
- // Use "Yoda grammar" to make it easier to grep|sort sections.
- printf("------ %.3fs was the duration of '%s' ------\n", (float)elapsed / NANOS_PER_SEC,
- title_.c_str());
+ MYLOGD("Duration of '%s': %.3fs\n", title_.c_str(), (float)elapsed / NANOS_PER_SEC);
+ if (logcat_only_) {
+ return;
}
+ // Use "Yoda grammar" to make it easier to grep|sort sections.
+ printf("------ %.3fs was the duration of '%s' ------\n", (float)elapsed / NANOS_PER_SEC,
+ title_.c_str());
}
}
@@ -795,115 +791,6 @@
return _redirect_to_file(redirect, path, O_APPEND);
}
-// Dump Dalvik and native stack traces, return the trace file location (nullptr if none).
-const char* dump_traces() {
- DurationReporter duration_reporter("DUMP TRACES");
-
- const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
- const size_t buf_size = temp_file_pattern.length() + 1;
- std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
- memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
-
- // Create a new, empty file to receive all trace dumps.
- //
- // TODO: This can be simplified once we remove support for the old style
- // dumps. We can have a file descriptor passed in to dump_traces instead
- // of creating a file, closing it and then reopening it again.
- android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
- if (fd < 0) {
- MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
- return nullptr;
- }
-
- // Nobody should have access to this temporary file except dumpstate, but we
- // temporarily grant 'read' to 'others' here because this file is created
- // when tombstoned is still running as root, but dumped after dropping. This
- // can go away once support for old style dumping has.
- const int chmod_ret = fchmod(fd, 0666);
- if (chmod_ret < 0) {
- MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
- return nullptr;
- }
-
- std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
- if (proc.get() == nullptr) {
- MYLOGE("opendir /proc failed: %s\n", strerror(errno));
- return nullptr;
- }
-
- // Number of times process dumping has timed out. If we encounter too many
- // failures, we'll give up.
- int timeout_failures = 0;
- bool dalvik_found = false;
-
- const std::set<int> hal_pids = get_interesting_hal_pids();
-
- struct dirent* d;
- while ((d = readdir(proc.get()))) {
- int pid = atoi(d->d_name);
- if (pid <= 0) {
- continue;
- }
-
- const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
- std::string exe;
- if (!android::base::Readlink(link_name, &exe)) {
- continue;
- }
-
- bool is_java_process;
- if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
- // Don't bother dumping backtraces for the zygote.
- if (IsZygote(pid)) {
- continue;
- }
-
- dalvik_found = true;
- is_java_process = true;
- } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
- is_java_process = false;
- } else {
- // Probably a native process we don't care about, continue.
- continue;
- }
-
- // If 3 backtrace dumps fail in a row, consider debuggerd dead.
- if (timeout_failures == 3) {
- dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
- break;
- }
-
- const uint64_t start = Nanotime();
- const int ret = dump_backtrace_to_file_timeout(
- pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
- is_java_process ? 5 : 20, fd);
-
- if (ret == -1) {
- // For consistency, the header and footer to this message match those
- // dumped by debuggerd in the success case.
- dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
- dprintf(fd, "Dump failed, likely due to a timeout.\n");
- dprintf(fd, "---- end %d ----", pid);
- timeout_failures++;
- continue;
- }
-
- // We've successfully dumped stack traces, reset the failure count
- // and write a summary of the elapsed time to the file and continue with the
- // next process.
- timeout_failures = 0;
-
- dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
- pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
- }
-
- if (!dalvik_found) {
- MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
- }
-
- return file_name_buf.release();
-}
-
void dump_route_tables() {
DurationReporter duration_reporter("DUMP ROUTE TABLES");
if (PropertiesHelper::IsDryRun()) return;
diff --git a/cmds/installd/globals.cpp b/cmds/installd/globals.cpp
index f52c2e7..1394701 100644
--- a/cmds/installd/globals.cpp
+++ b/cmds/installd/globals.cpp
@@ -44,7 +44,7 @@
static constexpr const char* PRIVATE_APP_SUBDIR = "app-private/"; // sub-directory under
// ANDROID_DATA
-static constexpr const char* STAGING_SUBDIR = "pkg_staging/"; // sub-directory under ANDROID_DATA
+static constexpr const char* STAGING_SUBDIR = "app-staging/"; // sub-directory under ANDROID_DATA
std::string android_app_dir;
std::string android_app_ephemeral_dir;
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 0e79239..ef2ad99 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -40,9 +40,9 @@
struct ASurfaceControl;
/**
- * The SurfaceControl API can be used to provide a heirarchy of surfaces for
+ * The SurfaceControl API can be used to provide a hierarchy of surfaces for
* composition to the system compositor. ASurfaceControl represents a content node in
- * this heirarchy.
+ * this hierarchy.
*/
typedef struct ASurfaceControl ASurfaceControl;
@@ -112,7 +112,7 @@
* the callback.
*
* |stats| is an opaque handle that can be passed to ASurfaceTransactionStats functions to query
- * information about the transaction. The handle is only valid during the the callback.
+ * information about the transaction. The handle is only valid during the callback.
*
* THREADING
* The transaction completed callback can be invoked on any thread.
diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
index b82141c..83a1048 100644
--- a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -106,28 +106,37 @@
virtual bool isRemote() = 0;
/**
- * Dumps information about the interface.
+ * Dumps information about the interface. By default, dumps nothing.
*/
- virtual binder_status_t dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/) {
- return STATUS_OK;
- }
+ virtual inline binder_status_t dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/);
+
+ /**
+ * Interprets this binder as this underlying interface if this has stored an ICInterface in the
+ * binder's user data.
+ *
+ * This does not do type checking and should only be used when the binder is known to originate
+ * from ICInterface. Most likely, you want to use I*::fromBinder.
+ */
+ static inline std::shared_ptr<ICInterface> asInterface(AIBinder* binder);
/**
* Helper method to create a class
*/
- static AIBinder_Class* defineClass(const char* interfaceDescriptor,
- AIBinder_Class_onCreate onCreate,
- AIBinder_Class_onDestroy onDestroy,
- AIBinder_Class_onTransact onTransact,
- AIBinder_onDump onDump = nullptr) {
- AIBinder_Class* clazz =
- AIBinder_Class_define(interfaceDescriptor, onCreate, onDestroy, onTransact);
- if (clazz == nullptr) {
- return nullptr;
- }
- AIBinder_Class_setOnDump(clazz, onDump);
- return clazz;
- }
+ static inline AIBinder_Class* defineClass(const char* interfaceDescriptor,
+ AIBinder_Class_onTransact onTransact);
+
+ private:
+ class ICInterfaceData {
+ public:
+ std::shared_ptr<ICInterface> interface;
+
+ static inline std::shared_ptr<ICInterface> getInterface(AIBinder* binder);
+
+ static inline void* onCreate(void* args);
+ static inline void onDestroy(void* userData);
+ static inline binder_status_t onDump(AIBinder* binder, int fd, const char** args,
+ uint32_t numArgs);
+ };
};
/**
@@ -141,7 +150,7 @@
SpAIBinder asBinder() override;
- bool isRemote() override { return true; }
+ bool isRemote() override { return false; }
protected:
/**
@@ -176,6 +185,55 @@
SpAIBinder mBinder;
};
+// END OF CLASS DECLARATIONS
+
+binder_status_t ICInterface::dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/) {
+ return STATUS_OK;
+}
+
+std::shared_ptr<ICInterface> ICInterface::asInterface(AIBinder* binder) {
+ return ICInterfaceData::getInterface(binder);
+}
+
+AIBinder_Class* ICInterface::defineClass(const char* interfaceDescriptor,
+ AIBinder_Class_onTransact onTransact) {
+ AIBinder_Class* clazz = AIBinder_Class_define(interfaceDescriptor, ICInterfaceData::onCreate,
+ ICInterfaceData::onDestroy, onTransact);
+ if (clazz == nullptr) {
+ return nullptr;
+ }
+
+ // We can't know if this method is overriden by a subclass interface, so we must register
+ // ourselves. The default (nothing to dump) is harmless.
+ AIBinder_Class_setOnDump(clazz, ICInterfaceData::onDump);
+ return clazz;
+}
+
+std::shared_ptr<ICInterface> ICInterface::ICInterfaceData::getInterface(AIBinder* binder) {
+ if (binder == nullptr) return nullptr;
+
+ void* userData = AIBinder_getUserData(binder);
+ if (userData == nullptr) return nullptr;
+
+ return static_cast<ICInterfaceData*>(userData)->interface;
+}
+
+void* ICInterface::ICInterfaceData::onCreate(void* args) {
+ std::shared_ptr<ICInterface> interface = static_cast<ICInterface*>(args)->ref<ICInterface>();
+ ICInterfaceData* data = new ICInterfaceData{interface};
+ return static_cast<void*>(data);
+}
+
+void ICInterface::ICInterfaceData::onDestroy(void* userData) {
+ delete static_cast<ICInterfaceData*>(userData);
+}
+
+binder_status_t ICInterface::ICInterfaceData::onDump(AIBinder* binder, int fd, const char** args,
+ uint32_t numArgs) {
+ std::shared_ptr<ICInterface> interface = getInterface(binder);
+ return interface->dump(fd, args, numArgs);
+}
+
template <typename INTERFACE>
SpAIBinder BnCInterface<INTERFACE>::asBinder() {
std::lock_guard<std::mutex> l(mMutex);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 3affa23..6460325 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -20,6 +20,11 @@
#include <gui/Surface.h>
+#include <condition_variable>
+#include <deque>
+#include <mutex>
+#include <thread>
+
#include <inttypes.h>
#include <android/native_window.h>
@@ -450,6 +455,82 @@
return NO_ERROR;
}
+class FenceMonitor {
+public:
+ explicit FenceMonitor(const char* name) : mName(name), mFencesQueued(0), mFencesSignaled(0) {
+ std::thread thread(&FenceMonitor::loop, this);
+ pthread_setname_np(thread.native_handle(), mName);
+ thread.detach();
+ }
+
+ void queueFence(const sp<Fence>& fence) {
+ char message[64];
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
+ snprintf(message, sizeof(message), "%s fence %u has signaled", mName, mFencesQueued);
+ ATRACE_NAME(message);
+ // Need an increment on both to make the trace number correct.
+ mFencesQueued++;
+ mFencesSignaled++;
+ return;
+ }
+ snprintf(message, sizeof(message), "Trace %s fence %u", mName, mFencesQueued);
+ ATRACE_NAME(message);
+
+ mQueue.push_back(fence);
+ mCondition.notify_one();
+ mFencesQueued++;
+ ATRACE_INT(mName, int32_t(mQueue.size()));
+ }
+
+private:
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+ void loop() {
+ while (true) {
+ threadLoop();
+ }
+ }
+#pragma clang diagnostic pop
+
+ void threadLoop() {
+ sp<Fence> fence;
+ uint32_t fenceNum;
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+ while (mQueue.empty()) {
+ mCondition.wait(lock);
+ }
+ fence = mQueue[0];
+ fenceNum = mFencesSignaled;
+ }
+ {
+ char message[64];
+ snprintf(message, sizeof(message), "waiting for %s %u", mName, fenceNum);
+ ATRACE_NAME(message);
+
+ status_t result = fence->waitForever(message);
+ if (result != OK) {
+ ALOGE("Error waiting for fence: %d", result);
+ }
+ }
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mQueue.pop_front();
+ mFencesSignaled++;
+ ATRACE_INT(mName, int32_t(mQueue.size()));
+ }
+ }
+
+ const char* mName;
+ uint32_t mFencesQueued;
+ uint32_t mFencesSignaled;
+ std::deque<sp<Fence>> mQueue;
+ std::condition_variable mCondition;
+ std::mutex mMutex;
+};
+
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
ATRACE_CALL();
ALOGV("Surface::dequeueBuffer");
@@ -519,6 +600,11 @@
// this should never happen
ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
+ if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
+ static FenceMonitor hwcReleaseThread("HWC release");
+ hwcReleaseThread.queueFence(fence);
+ }
+
if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
freeAllBuffers();
}
@@ -761,6 +847,11 @@
mQueueBufferCondition.broadcast();
+ if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
+ static FenceMonitor gpuCompletionThread("GPU completion");
+ gpuCompletionThread.queueFence(fence);
+ }
+
return err;
}
diff --git a/services/bufferhub/tests/Android.bp b/services/bufferhub/tests/Android.bp
index 8d29923..3033e70 100644
--- a/services/bufferhub/tests/Android.bp
+++ b/services/bufferhub/tests/Android.bp
@@ -11,6 +11,7 @@
"-Wall",
"-Werror",
],
+ compile_multilib: "first",
header_libs: [
"libdvr_headers",
"libnativewindow_headers",
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index c7c0867..96292a8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3873,7 +3873,7 @@
if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded;
}
if (what & layer_state_t::eInputInfoChanged) {
- if (callingThreadHasUnscopedSurfaceFlingerAccess()) {
+ if (privileged) {
layer->setInputInfo(s.inputInfo);
flags |= eTraversalNeeded;
} else {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1181886..96a21cc 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -584,8 +584,9 @@
bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
const Vector<ComposerState>& states);
- uint32_t setClientStateLocked(const ComposerState& composerState, bool privileged);
- uint32_t setDisplayStateLocked(const DisplayState& s);
+ uint32_t setClientStateLocked(const ComposerState& composerState, bool privileged)
+ REQUIRES(mStateLock);
+ uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
REQUIRES(mStateLock);
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 13059e8..46fd964 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -257,7 +257,10 @@
return mFlinger->onHotplugReceived(sequenceId, display, connection);
}
- auto setDisplayStateLocked(const DisplayState& s) { return mFlinger->setDisplayStateLocked(s); }
+ auto setDisplayStateLocked(const DisplayState& s) {
+ Mutex::Autolock _l(mFlinger->mStateLock);
+ return mFlinger->setDisplayStateLocked(s);
+ }
// Allow reading display state without locking, as if called on the SF main thread.
auto onInitializeDisplays() NO_THREAD_SAFETY_ANALYSIS {