Merge "Move to C API of libnativeloader."
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index 5c28c9d..6c86c21 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -5,6 +5,12 @@
# Access control to these files is now entirely in selinux policy.
on post-fs
+ # On userdebug allow to enable any event via the generic
+ # set_event interface:
+ # echo sched/foo > set_event == echo 1 > events/sched/foo/enable.
+ chmod 0666 /sys/kernel/tracing/set_event
+ chmod 0666 /sys/kernel/debug/tracing/set_event
+
chmod 0666 /sys/kernel/tracing/events/workqueue/enable
chmod 0666 /sys/kernel/debug/tracing/events/workqueue/enable
chmod 0666 /sys/kernel/tracing/events/regulator/enable
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 909bdd7..6596fa2 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -98,11 +98,10 @@
return binder::Status::ok();
}
-binder::Status DumpstateService::startBugreport(const android::base::unique_fd& /* bugreportFd */,
- const android::base::unique_fd& /* screenshotFd */,
+binder::Status DumpstateService::startBugreport(const android::base::unique_fd& bugreport_fd,
+ const android::base::unique_fd& screenshot_fd,
int bugreport_mode,
- const sp<IDumpstateListener>& /* listener */) {
- // TODO(b/111441001): Pass in fds & other arguments to DumpOptions.
+ const sp<IDumpstateListener>& listener) {
MYLOGI("startBugreport() with mode: %d\n", bugreport_mode);
if (bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_FULL &&
@@ -116,9 +115,20 @@
StringPrintf("Invalid bugreport mode: %d", bugreport_mode));
}
+ if (bugreport_fd.get() == -1 || screenshot_fd.get() == -1) {
+ return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Invalid file descriptor");
+ }
+
std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
- options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode));
+ options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
+ screenshot_fd);
+
+ std::lock_guard<std::mutex> lock(lock_);
+ // TODO(b/111441001): Disallow multiple simultaneous bugreports.
ds_.SetOptions(std::move(options));
+ if (listener != nullptr) {
+ ds_.listener_ = listener;
+ }
pthread_t thread;
status_t err = pthread_create(&thread, nullptr, callAndNotify, &ds_);
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 1736ae8..1705317 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -42,8 +42,8 @@
bool getSectionDetails,
sp<IDumpstateToken>* returned_token) override;
- binder::Status startBugreport(const android::base::unique_fd& bugreportFd,
- const android::base::unique_fd& screenshotFd, int bugreport_mode,
+ binder::Status startBugreport(const android::base::unique_fd& bugreport_fd,
+ const android::base::unique_fd& screenshot_fd, int bugreport_mode,
const sp<IDumpstateListener>& listener) override;
private:
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index ba3e290..d24c953 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -25,8 +25,6 @@
* {@hide}
*/
interface IDumpstate {
-
-
// TODO: remove method once startBugReport is used by Shell.
/*
* Sets the listener for this dumpstate progress.
@@ -69,6 +67,6 @@
* @param bugreportMode the mode that specifies other run time options; must be one of above
* @param listener callback for updates; optional
*/
- void startBugreport(FileDescriptor bugreportFd, FileDescriptor screenshotFd, int bugreportMode,
- IDumpstateListener listener);
+ void startBugreport(FileDescriptor bugreportFd, FileDescriptor screenshotFd, int bugreportMode,
+ IDumpstateListener listener);
}
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index 030d69d..2966c86 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -22,18 +22,48 @@
* {@hide}
*/
interface IDumpstateListener {
+ /**
+ * Called when there is a progress update.
+ *
+ * @param progress the progress in [0, 100]
+ */
+ oneway void onProgress(int progress);
+
+ /* Options specified are invalid or incompatible */
+ const int BUGREPORT_ERROR_INVALID_INPUT = 1;
+
+ /* Bugreport encountered a runtime error */
+ const int BUGREPORT_ERROR_RUNTIME_ERROR = 2;
+
+ /**
+ * Called on an error condition with one of the error codes listed above.
+ */
+ oneway void onError(int errorCode);
+
+ /**
+ * Called when taking bugreport finishes successfully
+ *
+ * @param durationMs time capturing bugreport took in milliseconds
+ * @param title title for the bugreport; helpful in reminding the user why they took it
+ * @param description detailed description for the bugreport
+ */
+ oneway void onFinished(long durationMs, @utf8InCpp String title,
+ @utf8InCpp String description);
+
+ // TODO(b/111441001): Remove old methods when not used anymore.
void onProgressUpdated(int progress);
void onMaxProgressUpdated(int maxProgress);
/**
- * Called after every section is complete.
- * @param name section name
- * @param status values from status_t
- * {@code OK} section completed successfully
- * {@code TIMEOUT} dump timed out
- * {@code != OK} error
- * @param size size in bytes, may be invalid if status != OK
- * @param durationMs duration in ms
- */
+ * Called after every section is complete.
+ *
+ * @param name section name
+ * @param status values from status_t
+ * {@code OK} section completed successfully
+ * {@code TIMEOUT} dump timed out
+ * {@code != OK} error
+ * @param size size in bytes, may be invalid if status != OK
+ * @param durationMs duration in ms
+ */
void onSectionComplete(@utf8InCpp String name, int status, int size, int durationMs);
}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 47c4f62..4e5d68d 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1881,8 +1881,9 @@
ds.tmp_path_ = ds.GetPath(".tmp");
ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
- std::string destination = ds.options_->fd != -1 ? StringPrintf("[fd:%d]", ds.options_->fd)
- : ds.bugreport_dir_.c_str();
+ std::string destination = ds.options_->bugreport_fd.get() != -1
+ ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
+ : ds.bugreport_dir_.c_str();
MYLOGD(
"Bugreport dir: %s\n"
"Internal Bugreport dir: %s\n"
@@ -1960,8 +1961,8 @@
}
// The zip file lives in an internal directory. Copy it over to output.
bool copy_succeeded = false;
- if (ds.options_->fd != -1) {
- copy_succeeded = android::os::CopyFileToFd(ds.path_, ds.options_->fd);
+ if (ds.options_->bugreport_fd.get() != -1) {
+ copy_succeeded = android::os::CopyFileToFd(ds.path_, ds.options_->bugreport_fd.get());
} else {
ds.final_path_ = ds.GetPath(ds.bugreport_dir_, ".zip");
copy_succeeded = android::os::CopyFileToFile(ds.path_, ds.final_path_);
@@ -2164,7 +2165,7 @@
MYLOGI("telephony_only: %d\n", options.telephony_only);
MYLOGI("wifi_only: %d\n", options.wifi_only);
MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
- MYLOGI("fd: %d\n", options.fd);
+ MYLOGI("fd: %d\n", options.bugreport_fd.get());
MYLOGI("use_outfile: %s\n", options.use_outfile.c_str());
MYLOGI("extra_options: %s\n", options.extra_options.c_str());
MYLOGI("args: %s\n", options.args.c_str());
@@ -2172,14 +2173,17 @@
MYLOGI("notification_description: %s\n", options.notification_description.c_str());
}
-void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode) {
+void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
+ const android::base::unique_fd& bugreport_fd_in,
+ const android::base::unique_fd& screenshot_fd_in) {
// In the new API world, date is always added; output is always a zip file.
// TODO(111441001): remove these options once they are obsolete.
do_add_date = true;
do_zip_file = true;
- // STOPSHIP b/111441001: Remove hardcoded output file path; accept fd.
- use_outfile = "/data/user_de/0/com.android.shell/files/bugreports/bugreport";
+ // Duplicate the fds because the passed in fds don't outlive the binder transaction.
+ bugreport_fd.reset(dup(bugreport_fd_in.get()));
+ screenshot_fd.reset(dup(screenshot_fd_in.get()));
extra_options = ModeToString(bugreport_mode);
SetOptionsFromMode(bugreport_mode, this);
@@ -2230,11 +2234,11 @@
}
bool Dumpstate::DumpOptions::ValidateOptions() const {
- if (fd != -1 && !do_zip_file) {
+ if (bugreport_fd.get() != -1 && !do_zip_file) {
return false;
}
- bool has_out_file_options = !use_outfile.empty() || fd != -1;
+ bool has_out_file_options = !use_outfile.empty() || bugreport_fd.get() != -1;
if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) &&
!has_out_file_options) {
return false;
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 7ac25e4..529111e 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -342,9 +342,11 @@
bool wifi_only = false;
// Whether progress updates should be published.
bool do_progress_updates = false;
- // File descriptor to output zip file. -1 indicates not set. Takes precedence over
- // use_outfile.
- int fd = -1;
+ // File descriptor to output zip file. Takes precedence over use_outfile.
+ android::base::unique_fd bugreport_fd;
+ // File descriptor to screenshot file.
+ // TODO(b/111441001): Use this fd.
+ android::base::unique_fd screenshot_fd;
// Partial path to output file.
std::string use_outfile;
// TODO: rename to MODE.
@@ -360,7 +362,8 @@
RunStatus Initialize(int argc, char* argv[]);
/* Initializes options from the requested mode. */
- void Initialize(BugreportMode bugreport_mode);
+ void Initialize(BugreportMode bugreport_mode, const android::base::unique_fd& bugreport_fd,
+ const android::base::unique_fd& screenshot_fd);
/* Returns true if the options set so far are consistent. */
bool ValidateOptions() const;
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 61a5ef5..c57775f 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -53,6 +53,19 @@
DumpstateListener(int fd, std::shared_ptr<std::vector<SectionInfo>> sections)
: outFd_(fd), max_progress_(5000), sections_(sections) {
}
+ binder::Status onProgress(int32_t progress) override {
+ dprintf(outFd_, "\rIn progress %d", progress);
+ return binder::Status::ok();
+ }
+ binder::Status onError(int32_t error_code) override {
+ dprintf(outFd_, "\rError %d", error_code);
+ return binder::Status::ok();
+ }
+ binder::Status onFinished(int64_t duration_ms, const ::std::string&,
+ const ::std::string&) override {
+ dprintf(outFd_, "\rFinished in %lld", (long long) duration_ms);
+ return binder::Status::ok();
+ }
binder::Status onProgressUpdated(int32_t progress) override {
dprintf(outFd_, "\rIn progress %d/%d", progress, max_progress_);
return binder::Status::ok();
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index fcf9371..98ee1b0 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -59,6 +59,10 @@
class DumpstateListenerMock : public IDumpstateListener {
public:
+ MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
+ MOCK_METHOD1(onError, binder::Status(int32_t error_code));
+ MOCK_METHOD3(onFinished, binder::Status(int64_t duration_ms, const ::std::string& title,
+ const ::std::string& description));
MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status,
diff --git a/cmds/surfacereplayer/OWNERS b/cmds/surfacereplayer/OWNERS
new file mode 100644
index 0000000..cc4c842
--- /dev/null
+++ b/cmds/surfacereplayer/OWNERS
@@ -0,0 +1,2 @@
+mathias@google.com
+racarr@google.com
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index 05d96ff..d31d1f1 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -112,15 +112,25 @@
#if __ANDROID_API__ >= 29
+/**
+ * Possible values of the flags argument to android_res_nsend and android_res_nquery.
+ * Values are ORed together.
+ */
enum ResNsendFlags : uint32_t {
- // Send a single request to a single resolver and fail on timeout or network errors
+ /**
+ * Send a single request to a single resolver and fail on timeout or network errors
+ */
ANDROID_RESOLV_NO_RETRY = 1 << 0,
- // Do not cache the result of the lookup. The lookup may return a result that is already
- // in the cache, unless the ANDROID_RESOLV_NO_CACHE_LOOKUP flag is also specified.
+ /**
+ * Do not cache the result of the lookup. The lookup may return a result that is already
+ * in the cache, unless the ANDROID_RESOLV_NO_CACHE_LOOKUP flag is also specified.
+ */
ANDROID_RESOLV_NO_CACHE_STORE = 1 << 1,
- // Don't lookup the request in cache, do not write back the response into the cache
+ /**
+ * Don't lookup the request in cache.
+ */
ANDROID_RESOLV_NO_CACHE_LOOKUP = 1 << 2,
};
@@ -136,8 +146,7 @@
* POSIX error code (see errno.h) if an immediate error occurs.
*/
int android_res_nquery(net_handle_t network,
- const char *dname, int ns_class, int ns_type,
- enum ResNsendFlags flags) __INTRODUCED_IN(29);
+ const char *dname, int ns_class, int ns_type, uint32_t flags) __INTRODUCED_IN(29);
/**
* Issue the query |msg| on the given |network|.
@@ -148,10 +157,11 @@
* POSIX error code (see errno.h) if an immediate error occurs.
*/
int android_res_nsend(net_handle_t network,
- const uint8_t *msg, size_t msglen, enum ResNsendFlags flags) __INTRODUCED_IN(29);
+ const uint8_t *msg, size_t msglen, uint32_t flags) __INTRODUCED_IN(29);
/**
* Read a result for the query associated with the |fd| descriptor.
+ * Closes |fd| before returning.
*
* Returns:
* < 0: negative POSIX error code (see errno.h for possible values). |rcode| is not set.
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
new file mode 100644
index 0000000..13b630b
--- /dev/null
+++ b/include/android/surface_control.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2018 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.
+ */
+
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file surface_control.h
+ */
+
+#ifndef ANDROID_SURFACE_CONTROL_H
+#define ANDROID_SURFACE_CONTROL_H
+
+#include <sys/cdefs.h>
+
+#include <android/hardware_buffer.h>
+#include <android/native_window.h>
+
+__BEGIN_DECLS
+
+#if __ANDROID_API__ >= 29
+
+struct ASurfaceControl;
+
+/**
+ * The SurfaceControl API can be used to provide a heirarchy of surfaces for
+ * composition to the system compositor. ASurfaceControl represents a content node in
+ * this heirarchy.
+ */
+typedef struct ASurfaceControl ASurfaceControl;
+
+/*
+ * Creates an ASurfaceControl with either ANativeWindow or an ASurfaceControl as its parent.
+ * |debug_name| is a debug name associated with this surface. It can be used to
+ * identify this surface in the SurfaceFlinger's layer tree. It must not be
+ * null.
+ *
+ * The caller takes ownership of the ASurfaceControl returned and must release it
+ * using ASurfaceControl_release below.
+ */
+ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* parent, const char* debug_name)
+ __INTRODUCED_IN(29);
+
+ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* debug_name)
+ __INTRODUCED_IN(29);
+
+/**
+ * Destroys the |surface_control| object. After releasing the ASurfaceControl the caller no longer
+ * has ownership of the AsurfaceControl.
+ */
+void ASurfaceControl_destroy(ASurfaceControl* surface_control) __INTRODUCED_IN(29);
+
+struct ASurfaceTransaction;
+
+/**
+ * ASurfaceTransaction is a collection of updates to the surface tree that must
+ * be applied atomically.
+ */
+typedef struct ASurfaceTransaction ASurfaceTransaction;
+
+/**
+ * The caller takes ownership of the transaction and must release it using
+ * ASurfaceControl_delete below.
+ */
+ASurfaceTransaction* ASurfaceTransaction_create() __INTRODUCED_IN(29);
+
+/**
+ * Destroys the |transaction| object.
+ */
+void ASurfaceTransaction_delete(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
+
+/**
+ * Applies the updates accumulated in |transaction|.
+ *
+ * Note that the transaction is guaranteed to be applied atomically. The
+ * transactions which are applied on the same thread are also guaranteed to be
+ * applied in order.
+ */
+void ASurfaceTransaction_apply(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
+
+/**
+ * Since the transactions are applied asynchronously, the
+ * ASurfaceTransaction_OnComplete callback can be used to be notified when a frame
+ * including the updates in a transaction was presented.
+ *
+ * |context| is the optional context provided by the client that is passed into
+ * the callback.
+ * |present_fence| is the sync fence that signals when the transaction has been presented.
+ * The recipient of the callback takes ownership of the present_fence and is responsible for closing
+ * it.
+ *
+ * It is safe to assume that once the present fence singals, that reads for all buffers,
+ * submitted in previous transactions, which are not in the surface tree after a transaction is
+ * applied, are finished and the buffers may be reused.
+ *
+ * THREADING
+ * The transaction completed callback can be invoked on any thread.
+ */
+typedef void (*ASurfaceTransaction_OnComplete)(void* context, int32_t present_fence);
+
+/**
+ * Sets the callback that will be invoked when the updates from this transaction
+ * are presented. For details on the callback semantics and data, see the
+ * comments on the ASurfaceTransaction_OnComplete declaration above.
+ */
+void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* transaction, void* context,
+ ASurfaceTransaction_OnComplete func) __INTRODUCED_IN(29);
+
+/* Parameter for ASurfaceTransaction_setVisibility */
+enum {
+ ASURFACE_TRANSACTION_VISIBILITY_HIDE = 0,
+ ASURFACE_TRANSACTION_VISIBILITY_SHOW = 1,
+};
+/**
+ * Updates the visibility of |surface_control|. If show is set to
+ * ASURFACE_TRANSACTION_VISIBILITY_HIDE, the |surface_control| and all surfaces in its subtree will
+ * be hidden.
+ */
+void ASurfaceTransaction_setVisibility(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, int8_t visibility)
+ __INTRODUCED_IN(29);
+
+/**
+ * Updates the z order index for |surface_control|. Note that the z order for a surface
+ * is relative to other surfaces which are siblings of this surface. The behavior of sibilings with
+ * the same z order is undefined.
+ *
+ * Z orders may be from MIN_INT32 to MAX_INT32. A layer's default z order index is 0.
+ */
+void ASurfaceTransaction_setZOrder(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, int32_t z_order)
+ __INTRODUCED_IN(29);
+
+/**
+ * Updates the AHardwareBuffer displayed for |surface_control|. If not -1, the
+ * fence_fd should be a file descriptor that is signaled when all pending work
+ * for the buffer is complete and the buffer can be safely read.
+ *
+ * The frameworks takes ownership of the |fence_fd| passed and is responsible
+ * for closing it.
+ */
+void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, AHardwareBuffer* buffer,
+ int fence_fd = -1) __INTRODUCED_IN(29);
+
+/**
+ * |source| the sub-rect within the buffer's content to be rendered inside the surface's area
+ * The surface's source rect is clipped by the bounds of its current buffer. The source rect's width
+ * and height must be > 0.
+ *
+ * |destination| specifies the rect in the parent's space where this surface will be drawn. The post
+ * source rect bounds are scaled to fit the destination rect. The surface's destination rect is
+ * clipped by the bounds of its parent. The destination rect's width and height must be > 0.
+ *
+ * |transform| the transform applied after the source rect is applied to the buffer. This parameter
+ * should be set to 0 for no transform. To specify a transfrom use the NATIVE_WINDOW_TRANSFORM_*
+ * enum.
+ */
+void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, const ARect& source,
+ const ARect& destination, int32_t transform)
+ __INTRODUCED_IN(29);
+
+
+/* Parameter for ASurfaceTransaction_setBufferTransparency */
+enum {
+ ASURFACE_TRANSACTION_TRANSPARENCY_TRANSPARENT = 0,
+ ASURFACE_TRANSACTION_TRANSPARENCY_TRANSLUCENT = 1,
+ ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE = 2,
+};
+/**
+ * Updates whether the content for the buffer associated with this surface is
+ * completely opaque. If true, every pixel of content inside the buffer must be
+ * opaque or visual errors can occur.
+ */
+void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, int8_t transparency)
+ __INTRODUCED_IN(29);
+
+/**
+ * Updates the region for the content on this surface updated in this
+ * transaction. If unspecified, the complete surface is assumed to be damaged.
+ */
+void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, const ARect rects[],
+ uint32_t count) __INTRODUCED_IN(29);
+
+#endif // __ANDROID_API__ >= 29
+
+__END_DECLS
+
+#endif // ANDROID_SURFACE_CONTROL_H
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a481e81..7357ba9 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -681,6 +681,18 @@
result = reply.readUint64Vector(&outStats->component_3_sample);
return result;
}
+
+ virtual status_t getProtectedContentSupport(bool* outSupported) const {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ remote()->transact(BnSurfaceComposer::GET_PROTECTED_CONTENT_SUPPORT, data, &reply);
+ bool result;
+ status_t err = reply.readBool(&result);
+ if (err == NO_ERROR) {
+ *outSupported = result;
+ }
+ return err;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -1017,7 +1029,7 @@
reply->writeInt32(static_cast<int32_t>(wideColorGamutDataspace));
reply->writeInt32(static_cast<int32_t>(wideColorGamutPixelFormat));
}
- return NO_ERROR;
+ return error;
}
case GET_COLOR_MANAGEMENT: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
@@ -1026,7 +1038,7 @@
if (error == NO_ERROR) {
reply->writeBool(result);
}
- return result;
+ return error;
}
case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
@@ -1110,6 +1122,15 @@
}
return result;
}
+ case GET_PROTECTED_CONTENT_SUPPORT: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ bool result;
+ status_t error = getProtectedContentSupport(&result);
+ if (error == NO_ERROR) {
+ reply->writeBool(result);
+ }
+ return error;
+ }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
index a7c7e79..73150dc 100644
--- a/libs/gui/OWNERS
+++ b/libs/gui/OWNERS
@@ -1,8 +1,7 @@
-brianderson@google.com
jessehall@google.com
jwcai@google.com
+lpy@google.com
+marissaw@google.com
mathias@google.com
-olv@google.com
-pceballos@google.com
racarr@google.com
stoza@google.com
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 1534fca..9812e1c 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -309,6 +309,12 @@
virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
uint64_t timestamp,
DisplayedFrameStats* outStats) const = 0;
+
+ /*
+ * Gets whether SurfaceFlinger can support protected content in GPU composition.
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ virtual status_t getProtectedContentSupport(bool* outSupported) const = 0;
};
// ----------------------------------------------------------------------------
@@ -350,6 +356,7 @@
GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
SET_DISPLAY_CONTENT_SAMPLING_ENABLED,
GET_DISPLAYED_CONTENT_SAMPLE,
+ GET_PROTECTED_CONTENT_SUPPORT,
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 60173dc..2d773f2 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -655,7 +655,8 @@
return NO_ERROR;
}
- virtual status_t getColorManagement(bool* /*outGetColorManagement*/) const { return NO_ERROR; }
+ status_t getColorManagement(bool* /*outGetColorManagement*/) const override { return NO_ERROR; }
+ status_t getProtectedContentSupport(bool* /*outSupported*/) const override { return NO_ERROR; }
protected:
IBinder* onAsBinder() override { return nullptr; }
diff --git a/libs/math/OWNERS b/libs/math/OWNERS
new file mode 100644
index 0000000..6fb149a
--- /dev/null
+++ b/libs/math/OWNERS
@@ -0,0 +1,6 @@
+jaesoo@google.com
+jiyong@google.com
+mathias@google.com
+pawin@google.com
+randolphs@google.com
+romainguy@google.com
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index 052e650..6310f29 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -319,11 +319,6 @@
mMetadata.IsValid() && mBufferClient != nullptr;
}
-// TODO(b/68770788): implement Poll() once we have event fd
-int BufferHubBuffer::Poll(int /* timeoutMs */) {
- return -ENOSYS;
-}
-
native_handle_t* BufferHubBuffer::Duplicate() {
if (mBufferClient == nullptr) {
ALOGE("%s: missing BufferClient!", __FUNCTION__);
diff --git a/libs/ui/OWNERS b/libs/ui/OWNERS
new file mode 100644
index 0000000..3938e4f
--- /dev/null
+++ b/libs/ui/OWNERS
@@ -0,0 +1,5 @@
+jiyong@google.com
+mathias@google.com
+olv@google.com
+romainguy@google.com
+stoza@google.com
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
index 44dfa95..c6a4a23 100644
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -94,9 +94,6 @@
// current cycle of the usage of the buffer.
int Release();
- // Polls the fd for |timeoutMs| milliseconds (-1 for infinity).
- int Poll(int timeoutMs);
-
// Creates a token that stands for this BufferHubBuffer client and could be used for Import to
// create another BufferHubBuffer. The new BufferHubBuffer will share the same underlying
// gralloc buffer and ashmem region for metadata. Note that the caller owns the token and
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
index ad49cd6..a40443d 100644
--- a/services/bufferhub/BufferHubService.cpp
+++ b/services/bufferhub/BufferHubService.cpp
@@ -216,7 +216,7 @@
stream << " ";
stream << std::setw(10) << "State";
stream << " ";
- stream << std::setw(10) << "Index";
+ stream << std::setw(8) << "Index";
stream << std::endl;
for (auto iter = clientCount.begin(); iter != clientCount.end(); ++iter) {
@@ -251,6 +251,7 @@
stream << " ";
stream << "0x" << std::hex << std::setfill('0');
stream << std::setw(8) << /*State=*/state;
+ stream << std::dec << std::setfill(' ');
stream << " ";
stream << std::setw(8) << /*Index=*/index;
stream << std::endl;
diff --git a/services/displayservice/OWNERS b/services/displayservice/OWNERS
new file mode 100644
index 0000000..7a3e4c2
--- /dev/null
+++ b/services/displayservice/OWNERS
@@ -0,0 +1,2 @@
+smoreland@google.com
+lpy@google.com
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index bf925b2..7b25adb 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -43,8 +43,12 @@
// ---------------------------------------------------------------------------
-EventThreadConnection::EventThreadConnection(EventThread* eventThread)
- : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {}
+EventThreadConnection::EventThreadConnection(EventThread* eventThread,
+ ResyncCallback resyncCallback)
+ : resyncCallback(std::move(resyncCallback)),
+ count(-1),
+ mEventThread(eventThread),
+ mChannel(gui::BitTube::DefaultSize) {}
EventThreadConnection::~EventThreadConnection() {
// do nothing here -- clean-up will happen automatically
@@ -88,26 +92,21 @@
namespace impl {
EventThread::EventThread(std::unique_ptr<VSyncSource> src,
- const ResyncWithRateLimitCallback& resyncWithRateLimitCallback,
const InterceptVSyncsCallback& interceptVSyncsCallback,
const ResetIdleTimerCallback& resetIdleTimerCallback,
const char* threadName)
- : EventThread(nullptr, std::move(src), resyncWithRateLimitCallback, interceptVSyncsCallback,
- threadName) {
+ : EventThread(nullptr, std::move(src), interceptVSyncsCallback, threadName) {
mResetIdleTimer = resetIdleTimerCallback;
}
-EventThread::EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback,
- InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
- : EventThread(src, nullptr, resyncWithRateLimitCallback, interceptVSyncsCallback,
- threadName) {}
+EventThread::EventThread(VSyncSource* src, InterceptVSyncsCallback interceptVSyncsCallback,
+ const char* threadName)
+ : EventThread(src, nullptr, interceptVSyncsCallback, threadName) {}
EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
- ResyncWithRateLimitCallback resyncWithRateLimitCallback,
InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
: mVSyncSource(src),
mVSyncSourceUnique(std::move(uniqueSrc)),
- mResyncWithRateLimitCallback(resyncWithRateLimitCallback),
mInterceptVSyncsCallback(interceptVSyncsCallback) {
if (src == nullptr) {
mVSyncSource = mVSyncSourceUnique.get();
@@ -150,8 +149,8 @@
mVSyncSource->setPhaseOffset(phaseOffset);
}
-sp<EventThreadConnection> EventThread::createEventConnection() const {
- return new EventThreadConnection(const_cast<EventThread*>(this));
+sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const {
+ return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback));
}
status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
@@ -195,8 +194,9 @@
ATRACE_NAME("resetIdleTimer");
mResetIdleTimer();
}
- if (mResyncWithRateLimitCallback) {
- mResyncWithRateLimitCallback();
+
+ if (connection->resyncCallback) {
+ connection->resyncCallback();
}
std::lock_guard<std::mutex> lock(mMutex);
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index e110488..a411885 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -44,6 +44,8 @@
// ---------------------------------------------------------------------------
+using ResyncCallback = std::function<void()>;
+
class VSyncSource {
public:
class Callback {
@@ -60,7 +62,7 @@
class EventThreadConnection : public BnDisplayEventConnection {
public:
- explicit EventThreadConnection(EventThread* eventThread);
+ EventThreadConnection(EventThread* eventThread, ResyncCallback resyncCallback);
virtual ~EventThreadConnection();
virtual status_t postEvent(const DisplayEventReceiver::Event& event);
@@ -72,6 +74,9 @@
// in order to update the configs.
void requestNextVsyncForHWC();
+ // Called in response to requestNextVsync.
+ const ResyncCallback resyncCallback;
+
// count >= 1 : continuous event. count is the vsync rate
// count == 0 : one-shot event that has not fired
// count ==-1 : one-shot event that fired this round / disabled
@@ -90,7 +95,8 @@
virtual ~EventThread();
- virtual sp<EventThreadConnection> createEventConnection() const = 0;
+ virtual sp<EventThreadConnection> createEventConnection(
+ ResyncCallback resyncCallback) const = 0;
// called before the screen is turned off from main thread
virtual void onScreenReleased() = 0;
@@ -117,20 +123,18 @@
class EventThread : public android::EventThread, private VSyncSource::Callback {
public:
- using ResyncWithRateLimitCallback = std::function<void()>;
using InterceptVSyncsCallback = std::function<void(nsecs_t)>;
using ResetIdleTimerCallback = std::function<void()>;
// TODO(b/113612090): Once the Scheduler is complete this constructor will become obsolete.
- EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback,
- InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName);
+ EventThread(VSyncSource* src, InterceptVSyncsCallback interceptVSyncsCallback,
+ const char* threadName);
EventThread(std::unique_ptr<VSyncSource> src,
- const ResyncWithRateLimitCallback& resyncWithRateLimitCallback,
const InterceptVSyncsCallback& interceptVSyncsCallback,
const ResetIdleTimerCallback& resetIdleTimerCallback, const char* threadName);
~EventThread();
- sp<EventThreadConnection> createEventConnection() const override;
+ sp<EventThreadConnection> createEventConnection(ResyncCallback resyncCallback) const override;
status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
void setVsyncRate(uint32_t count, const sp<EventThreadConnection>& connection) override;
@@ -155,7 +159,6 @@
// TODO(b/113612090): Once the Scheduler is complete this constructor will become obsolete.
EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
- ResyncWithRateLimitCallback resyncWithRateLimitCallback,
InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName);
@@ -179,7 +182,6 @@
VSyncSource* mVSyncSource GUARDED_BY(mMutex) = nullptr;
std::unique_ptr<VSyncSource> mVSyncSourceUnique GUARDED_BY(mMutex) = nullptr;
// constants
- const ResyncWithRateLimitCallback mResyncWithRateLimitCallback;
const InterceptVSyncsCallback mInterceptVSyncsCallback;
std::thread mThread;
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 66f42bb..75a410b 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -85,7 +85,8 @@
mHandler = new Handler(*this);
}
-void MessageQueue::setEventThread(android::EventThread* eventThread) {
+void MessageQueue::setEventThread(android::EventThread* eventThread,
+ ResyncCallback resyncCallback) {
if (mEventThread == eventThread) {
return;
}
@@ -95,7 +96,7 @@
}
mEventThread = eventThread;
- mEvents = eventThread->createEventConnection();
+ mEvents = eventThread->createEventConnection(std::move(resyncCallback));
mEvents->stealReceiveChannel(&mEventTube);
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
this);
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
index 0bf00b0..56a00c0 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.h
+++ b/services/surfaceflinger/Scheduler/MessageQueue.h
@@ -29,12 +29,12 @@
#include <private/gui/BitTube.h>
#include "Barrier.h"
+#include "EventThread.h"
#include <functional>
namespace android {
-class EventThread;
class SurfaceFlinger;
// ---------------------------------------------------------------------------
@@ -86,7 +86,7 @@
virtual void init(const sp<SurfaceFlinger>& flinger) = 0;
// TODO(akrulec): Remove this function once everything is migrated to Scheduler.
- virtual void setEventThread(EventThread* events) = 0;
+ virtual void setEventThread(EventThread* events, ResyncCallback resyncCallback) = 0;
virtual void setEventConnection(const sp<EventThreadConnection>& connection) = 0;
virtual void waitMessage() = 0;
virtual status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) = 0;
@@ -127,7 +127,7 @@
public:
~MessageQueue() override = default;
void init(const sp<SurfaceFlinger>& flinger) override;
- void setEventThread(android::EventThread* events) override;
+ void setEventThread(android::EventThread* events, ResyncCallback resyncCallback) override;
void setEventConnection(const sp<EventThreadConnection>& connection) override;
void waitMessage() override;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index fec53af..0d587dd 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -86,39 +86,38 @@
Scheduler::~Scheduler() = default;
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
- const std::string& connectionName, int64_t phaseOffsetNs,
- impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
+ const std::string& connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
const int64_t id = sNextId++;
ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
std::unique_ptr<EventThread> eventThread =
- makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs, resyncCallback,
+ makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
interceptCallback);
auto connection = std::make_unique<Connection>(new ConnectionHandle(id),
- eventThread->createEventConnection(),
+ eventThread->createEventConnection(
+ std::move(resyncCallback)),
std::move(eventThread));
+
mConnections.insert(std::make_pair(id, std::move(connection)));
return mConnections[id]->handle;
}
std::unique_ptr<EventThread> Scheduler::makeEventThread(
const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
- impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
const std::string sourceName = connectionName + "Source";
std::unique_ptr<VSyncSource> eventThreadSource =
std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, sourceName.c_str());
const std::string threadName = connectionName + "Thread";
- return std::make_unique<impl::EventThread>(std::move(eventThreadSource), resyncCallback,
- interceptCallback, [this] { resetIdleTimer(); },
- threadName.c_str());
+ return std::make_unique<impl::EventThread>(std::move(eventThreadSource), interceptCallback,
+ [this] { resetIdleTimer(); }, threadName.c_str());
}
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
- const sp<Scheduler::ConnectionHandle>& handle) {
+ const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) {
RETURN_VALUE_IF_INVALID(nullptr);
- return mConnections[handle->id]->thread->createEventConnection();
+ return mConnections[handle->id]->thread->createEventConnection(std::move(resyncCallback));
}
EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 3538f31..ba18d21 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -73,11 +73,11 @@
/** Creates an EventThread connection. */
sp<ConnectionHandle> createConnection(
- const std::string& connectionName, int64_t phaseOffsetNs,
- impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
+ const std::string& connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback);
- sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle);
+ sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle,
+ ResyncCallback resyncCallback);
// Getter methods.
EventThread* getEventThread(const sp<ConnectionHandle>& handle);
@@ -122,7 +122,6 @@
protected:
virtual std::unique_ptr<EventThread> makeEventThread(
const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
- impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback);
private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9eff3c6..1af1112 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -17,15 +17,16 @@
// #define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <stdint.h>
#include <sys/types.h>
-#include <algorithm>
#include <errno.h>
-#include <math.h>
-#include <mutex>
#include <dlfcn.h>
-#include <inttypes.h>
-#include <stdatomic.h>
+
+#include <algorithm>
+#include <cinttypes>
+#include <cmath>
+#include <cstdint>
+#include <functional>
+#include <mutex>
#include <optional>
#include <cutils/properties.h>
@@ -618,6 +619,8 @@
Mutex::Autolock _l(mStateLock);
+ auto resyncCallback = makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
+
// start the EventThread
if (mUseScheduler) {
mScheduler = getFactory().createScheduler([this](bool enabled) {
@@ -626,12 +629,11 @@
mAppConnectionHandle =
mScheduler->createConnection("appConnection", SurfaceFlinger::vsyncPhaseOffsetNs,
- [this] { resyncWithRateLimit(); },
+ resyncCallback,
impl::EventThread::InterceptVSyncsCallback());
mSfConnectionHandle =
mScheduler->createConnection("sfConnection", SurfaceFlinger::sfVsyncPhaseOffsetNs,
- [this] { resyncWithRateLimit(); },
- [this](nsecs_t timestamp) {
+ resyncCallback, [this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
});
@@ -644,7 +646,6 @@
SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
mEventThread =
std::make_unique<impl::EventThread>(mEventThreadSource.get(),
- [this] { resyncWithRateLimit(); },
impl::EventThread::InterceptVSyncsCallback(),
"appEventThread");
mSfEventThreadSource =
@@ -653,12 +654,11 @@
mSFEventThread =
std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),
- [this] { resyncWithRateLimit(); },
[this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
},
"sfEventThread");
- mEventQueue->setEventThread(mSFEventThread.get());
+ mEventQueue->setEventThread(mSFEventThread.get(), std::move(resyncCallback));
mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get());
}
@@ -942,13 +942,15 @@
status_t SurfaceFlinger::setActiveConfigAsync(const sp<IBinder>& displayToken, int mode) {
ATRACE_NAME("setActiveConfigAsync");
- postMessageAsync(new LambdaMessage([=] { setActiveConfigInternal(displayToken, mode); }));
+ postMessageAsync(new LambdaMessage(
+ [=]() NO_THREAD_SAFETY_ANALYSIS { setActiveConfigInternal(displayToken, mode); }));
return NO_ERROR;
}
status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
ATRACE_NAME("setActiveConfigSync");
- postMessageSync(new LambdaMessage([&] { setActiveConfigInternal(displayToken, mode); }));
+ postMessageSync(new LambdaMessage(
+ [&]() NO_THREAD_SAFETY_ANALYSIS { setActiveConfigInternal(displayToken, mode); }));
return NO_ERROR;
}
@@ -989,7 +991,7 @@
getHwComposer().setActiveConfig(*displayId, mode);
ATRACE_INT("ActiveConfigMode", mode);
- resyncToHardwareVsync(true);
+ resyncToHardwareVsync(true, getVsyncPeriod());
}
status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken,
@@ -1153,6 +1155,14 @@
outStats);
}
+status_t SurfaceFlinger::getProtectedContentSupport(bool* outSupported) const {
+ if (!outSupported) {
+ return BAD_VALUE;
+ }
+ *outSupported = getRenderEngine().supportsProtectedContent();
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
postMessageSync(new LambdaMessage([&] {
Mutex::Autolock _l(mStateLock);
@@ -1161,6 +1171,8 @@
return;
}
+ auto resyncCallback = makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
+
// TODO(akrulec): Part of the Injector should be refactored, so that it
// can be passed to Scheduler.
if (enable) {
@@ -1168,14 +1180,14 @@
if (mVSyncInjector.get() == nullptr) {
mVSyncInjector = std::make_unique<InjectVSyncSource>();
mInjectorEventThread = std::make_unique<
- impl::EventThread>(mVSyncInjector.get(), [this] { resyncWithRateLimit(); },
+ impl::EventThread>(mVSyncInjector.get(),
impl::EventThread::InterceptVSyncsCallback(),
"injEventThread");
}
- mEventQueue->setEventThread(mInjectorEventThread.get());
+ mEventQueue->setEventThread(mInjectorEventThread.get(), std::move(resyncCallback));
} else {
ALOGV("VSync Injections disabled");
- mEventQueue->setEventThread(mSFEventThread.get());
+ mEventQueue->setEventThread(mSFEventThread.get(), std::move(resyncCallback));
}
mInjectVSyncs = enable;
@@ -1232,17 +1244,22 @@
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource) {
+ auto resyncCallback = makeResyncCallback([this] {
+ Mutex::Autolock lock(mStateLock);
+ return getVsyncPeriod();
+ });
+
if (mUseScheduler) {
if (vsyncSource == eVsyncSourceSurfaceFlinger) {
- return mScheduler->createDisplayEventConnection(mSfConnectionHandle);
+ return mScheduler->createDisplayEventConnection(mSfConnectionHandle, resyncCallback);
} else {
- return mScheduler->createDisplayEventConnection(mAppConnectionHandle);
+ return mScheduler->createDisplayEventConnection(mAppConnectionHandle, resyncCallback);
}
} else {
if (vsyncSource == eVsyncSourceSurfaceFlinger) {
- return mSFEventThread->createEventConnection();
+ return mSFEventThread->createEventConnection(resyncCallback);
} else {
- return mEventThread->createEventConnection();
+ return mEventThread->createEventConnection(resyncCallback);
}
}
}
@@ -1286,6 +1303,16 @@
} while (true);
}
+nsecs_t SurfaceFlinger::getVsyncPeriod() const {
+ const auto displayId = getInternalDisplayId();
+ if (!displayId || !getHwComposer().isConnected(*displayId)) {
+ return 0;
+ }
+
+ const auto config = getHwComposer().getActiveConfig(*displayId);
+ return config ? config->getVsyncPeriod() : 0;
+}
+
void SurfaceFlinger::enableHardwareVsync() {
Mutex::Autolock _l(mHWVsyncLock);
if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
@@ -1295,7 +1322,7 @@
}
}
-void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
+void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable, nsecs_t period) {
Mutex::Autolock _l(mHWVsyncLock);
if (makeAvailable) {
@@ -1310,14 +1337,10 @@
return;
}
- const auto displayId = getInternalDisplayId();
- if (!displayId || !getHwComposer().isConnected(*displayId)) {
+ if (period <= 0) {
return;
}
- const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
- const nsecs_t period = activeConfig->getVsyncPeriod();
-
if (mUseScheduler) {
mScheduler->setVsyncPeriod(period);
} else {
@@ -1344,16 +1367,15 @@
}
}
-void SurfaceFlinger::resyncWithRateLimit() {
+void SurfaceFlinger::VsyncState::resync(const GetVsyncPeriod& getVsyncPeriod) {
static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
- // No explicit locking is needed here since EventThread holds a lock while calling this method
- static nsecs_t sLastResyncAttempted = 0;
const nsecs_t now = systemTime();
- if (now - sLastResyncAttempted > kIgnoreDelay) {
- resyncToHardwareVsync(false);
+ const nsecs_t last = lastResyncTime.exchange(now);
+
+ if (now - last > kIgnoreDelay) {
+ flinger.resyncToHardwareVsync(false, getVsyncPeriod());
}
- sLastResyncAttempted = now;
}
void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
@@ -1553,9 +1575,8 @@
setPowerModeInternal(display, currentDisplayPowerMode);
// Reset the timing values to account for the period of the swapped in HWC
- const auto activeConfig = getHwComposer().getActiveConfig(*display->getId());
- const nsecs_t period = activeConfig->getVsyncPeriod();
- mAnimFrameTracker.setDisplayRefreshPeriod(period);
+ const nsecs_t vsyncPeriod = getVsyncPeriod();
+ mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
// The present fences returned from vr_hwc are not an accurate
// representation of vsync times.
@@ -1569,10 +1590,10 @@
// Use phase of 0 since phase is not known.
// Use latency of 0, which will snap to the ideal latency.
- DisplayStatInfo stats{0 /* vsyncTime */, period /* vsyncPeriod */};
+ DisplayStatInfo stats{0 /* vsyncTime */, vsyncPeriod};
setCompositorTimingSnapped(stats, 0);
- resyncToHardwareVsync(false);
+ resyncToHardwareVsync(false, vsyncPeriod);
mRepaintEverything = true;
setTransactionFlags(eDisplayTransactionNeeded);
@@ -4120,8 +4141,11 @@
// ---------------------------------------------------------------------------
void SurfaceFlinger::onInitializeDisplays() {
- const auto displayToken = getInternalDisplayToken();
- if (!displayToken) return;
+ const auto display = getDefaultDisplayDeviceLocked();
+ if (!display) return;
+
+ const sp<IBinder> token = display->getDisplayToken().promote();
+ LOG_ALWAYS_FATAL_IF(token == nullptr);
// reset screen orientation and use primary layer stack
Vector<ComposerState> state;
@@ -4129,7 +4153,7 @@
DisplayState d;
d.what = DisplayState::eDisplayProjectionChanged |
DisplayState::eLayerStackChanged;
- d.token = displayToken;
+ d.token = token;
d.layerStack = 0;
d.orientation = DisplayState::eOrientationDefault;
d.frame.makeInvalid();
@@ -4139,24 +4163,21 @@
displays.add(d);
setTransactionState(state, displays, 0, nullptr, mInputWindowCommands);
- const auto display = getDisplayDevice(displayToken);
- if (!display) return;
-
setPowerModeInternal(display, HWC_POWER_MODE_NORMAL);
- const auto activeConfig = getHwComposer().getActiveConfig(*display->getId());
- const nsecs_t period = activeConfig->getVsyncPeriod();
- mAnimFrameTracker.setDisplayRefreshPeriod(period);
+ const nsecs_t vsyncPeriod = getVsyncPeriod();
+ mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
// Use phase of 0 since phase is not known.
// Use latency of 0, which will snap to the ideal latency.
- DisplayStatInfo stats{0 /* vsyncTime */, period /* vsyncPeriod */};
+ DisplayStatInfo stats{0 /* vsyncTime */, vsyncPeriod};
setCompositorTimingSnapped(stats, 0);
}
void SurfaceFlinger::initializeDisplays() {
// Async since we may be called from the main thread.
- postMessageAsync(new LambdaMessage([this] { onInitializeDisplays(); }));
+ postMessageAsync(
+ new LambdaMessage([this]() NO_THREAD_SAFETY_ANALYSIS { onInitializeDisplays(); }));
}
void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int mode) {
@@ -4190,7 +4211,7 @@
} else {
mEventThread->onScreenAcquired();
}
- resyncToHardwareVsync(true);
+ resyncToHardwareVsync(true, getVsyncPeriod());
}
mVisibleRegionsDirty = true;
@@ -4235,7 +4256,7 @@
} else {
mEventThread->onScreenAcquired();
}
- resyncToHardwareVsync(true);
+ resyncToHardwareVsync(true, getVsyncPeriod());
}
} else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
// Leave display going to doze
@@ -4265,7 +4286,7 @@
}
void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
- postMessageSync(new LambdaMessage([&] {
+ postMessageSync(new LambdaMessage([&]() NO_THREAD_SAFETY_ANALYSIS {
const auto display = getDisplayDevice(displayToken);
if (!display) {
ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
@@ -4438,12 +4459,7 @@
index++;
}
- if (const auto displayId = getInternalDisplayId();
- displayId && getHwComposer().isConnected(*displayId)) {
- const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
- const nsecs_t period = activeConfig->getVsyncPeriod();
- StringAppendF(&result, "%" PRId64 "\n", period);
- }
+ StringAppendF(&result, "%" PRId64 "\n", getVsyncPeriod());
if (name.isEmpty()) {
mAnimFrameTracker.dumpStats(result);
@@ -4744,22 +4760,16 @@
const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets();
const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets();
- if (const auto displayId = getInternalDisplayId();
- displayId && getHwComposer().isConnected(*displayId)) {
- const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
- StringAppendF(&result,
- "Display %s: app phase %" PRId64 " ns, "
- "sf phase %" PRId64 " ns, "
- "early app phase %" PRId64 " ns, "
- "early sf phase %" PRId64 " ns, "
- "early app gl phase %" PRId64 " ns, "
- "early sf gl phase %" PRId64 " ns, "
- "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
- to_string(*displayId).c_str(), vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs,
- appEarlyOffset, sfEarlyOffset, appEarlyGlOffset, sfEarlyGlOffset,
- dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
- }
- result.append("\n");
+ StringAppendF(&result,
+ "app phase %" PRId64 " ns, "
+ "sf phase %" PRId64 " ns, "
+ "early app phase %" PRId64 " ns, "
+ "early sf phase %" PRId64 " ns, "
+ "early app gl phase %" PRId64 " ns, "
+ "early sf gl phase %" PRId64 " ns, "
+ "present offset %" PRId64 " ns (refresh %" PRId64 " ns)\n",
+ vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, appEarlyOffset, sfEarlyOffset,
+ appEarlyGlOffset, sfEarlyGlOffset, dispSyncPresentTimeOffset, getVsyncPeriod());
// Dump static screen stats
result.append("\n");
@@ -5004,7 +5014,8 @@
case SET_TRANSACTION_STATE:
case CREATE_CONNECTION:
case GET_COLOR_MANAGEMENT:
- case GET_COMPOSITION_PREFERENCE: {
+ case GET_COMPOSITION_PREFERENCE:
+ case GET_PROTECTED_CONTENT_SUPPORT: {
return OK;
}
case CAPTURE_LAYERS:
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index eb7127e..a4bd3e9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -17,63 +17,58 @@
#ifndef ANDROID_SURFACE_FLINGER_H
#define ANDROID_SURFACE_FLINGER_H
-#include <memory>
-#include <stdint.h>
#include <sys/types.h>
/*
* NOTE: Make sure this file doesn't include anything from <gl/ > or <gl2/ >
*/
-#include <cutils/compiler.h>
+#include <android-base/thread_annotations.h>
#include <cutils/atomic.h>
-
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-#include <utils/SortedVector.h>
-#include <utils/threads.h>
-#include <utils/Trace.h>
-
-#include <ui/FenceTime.h>
-#include <ui/PixelFormat.h>
-#include <math/mat4.h>
-
+#include <cutils/compiler.h>
+#include <gui/BufferQueue.h>
#include <gui/FrameTimestamps.h>
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
#include <gui/LayerState.h>
-
#include <gui/OccupancyTracker.h>
-#include <gui/BufferQueue.h>
-
#include <hardware/hwcomposer_defs.h>
-
+#include <layerproto/LayerProtoHeader.h>
+#include <math/mat4.h>
#include <serviceutils/PriorityDumper.h>
-
#include <system/graphics.h>
+#include <ui/FenceTime.h>
+#include <ui/PixelFormat.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/Trace.h>
+#include <utils/threads.h>
#include "Barrier.h"
#include "DisplayDevice.h"
+#include "DisplayHardware/HWC2.h"
+#include "DisplayHardware/HWComposer.h"
+#include "Effects/Daltonizer.h"
#include "FrameTracker.h"
#include "LayerBE.h"
#include "LayerStats.h"
#include "LayerVector.h"
-#include "SurfaceFlingerFactory.h"
-#include "SurfaceInterceptor.h"
-#include "SurfaceTracing.h"
-#include "TransactionCompletedThread.h"
-
-#include "DisplayHardware/HWC2.h"
-#include "DisplayHardware/HWComposer.h"
-#include "Effects/Daltonizer.h"
#include "Scheduler/DispSync.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/MessageQueue.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/VSyncModulator.h"
+#include "SurfaceFlingerFactory.h"
+#include "SurfaceInterceptor.h"
+#include "SurfaceTracing.h"
+#include "TransactionCompletedThread.h"
+#include <atomic>
+#include <cstdint>
#include <map>
+#include <memory>
#include <mutex>
#include <queue>
#include <set>
@@ -82,8 +77,6 @@
#include <unordered_map>
#include <utility>
-#include <layerproto/LayerProtoHeader.h>
-
using namespace android::surfaceflinger;
namespace android {
@@ -148,10 +141,6 @@
const std::string mHwcServiceName; // "default" for real use, something else for testing.
- // constant members (no synchronization needed for access)
- EGLContext mEGLContext;
- EGLDisplay mEGLDisplay;
-
FenceTimeline mGlCompositionDoneTimeline;
FenceTimeline mDisplayTimeline;
@@ -412,77 +401,75 @@
/* ------------------------------------------------------------------------
* IBinder interface
*/
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags);
- virtual status_t dump(int fd, const Vector<String16>& args) { return priorityDump(fd, args); }
+ status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
+ status_t dump(int fd, const Vector<String16>& args) override { return priorityDump(fd, args); }
/* ------------------------------------------------------------------------
* ISurfaceComposer interface
*/
- virtual sp<ISurfaceComposerClient> createConnection();
- virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
- virtual void destroyDisplay(const sp<IBinder>& displayToken);
- virtual sp<IBinder> getBuiltInDisplay(int32_t id);
- virtual void setTransactionState(const Vector<ComposerState>& state,
- const Vector<DisplayState>& displays, uint32_t flags,
- const sp<IBinder>& applyToken,
- const InputWindowCommands& inputWindowCommands);
- virtual void bootFinished();
- virtual bool authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& bufferProducer) const;
- virtual status_t getSupportedFrameTimestamps(
- std::vector<FrameEvent>* outSupported) const;
- virtual sp<IDisplayEventConnection> createDisplayEventConnection(
- ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp);
- virtual status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
- const ui::Dataspace reqDataspace,
- const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
- ISurfaceComposer::Rotation rotation);
- virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
- const ui::Dataspace reqDataspace,
- const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- float frameScale, bool childrenOnly);
- virtual status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
- virtual status_t getDisplayConfigs(const sp<IBinder>& displayToken,
- Vector<DisplayInfo>* configs);
- virtual int getActiveConfig(const sp<IBinder>& displayToken);
- virtual status_t getDisplayColorModes(const sp<IBinder>& displayToken,
- Vector<ui::ColorMode>* configs);
- virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken);
- virtual status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode);
- virtual void setPowerMode(const sp<IBinder>& displayToken, int mode);
- virtual status_t setActiveConfig(const sp<IBinder>& displayToken, int id);
- virtual status_t clearAnimationFrameStats();
- virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
- virtual status_t getHdrCapabilities(const sp<IBinder>& displayToken,
- HdrCapabilities* outCapabilities) const;
- virtual status_t enableVSyncInjections(bool enable);
- virtual status_t injectVSync(nsecs_t when);
- virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const;
- virtual status_t getColorManagement(bool* outGetColorManagement) const;
+ sp<ISurfaceComposerClient> createConnection() override;
+ sp<IBinder> createDisplay(const String8& displayName, bool secure) override;
+ void destroyDisplay(const sp<IBinder>& displayToken) override;
+ sp<IBinder> getBuiltInDisplay(int32_t id) override;
+ void setTransactionState(const Vector<ComposerState>& state,
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const sp<IBinder>& applyToken,
+ const InputWindowCommands& inputWindowCommands) override;
+ void bootFinished() override;
+ bool authenticateSurfaceTexture(
+ const sp<IGraphicBufferProducer>& bufferProducer) const override;
+ status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override;
+ sp<IDisplayEventConnection> createDisplayEventConnection(
+ ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp) override;
+ status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
+ const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ bool useIdentityTransform, ISurfaceComposer::Rotation rotation) override;
+ status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
+ const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
+ const Rect& sourceCrop, float frameScale, bool childrenOnly) override;
+ status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
+ status_t getDisplayConfigs(const sp<IBinder>& displayToken,
+ Vector<DisplayInfo>* configs) override;
+ int getActiveConfig(const sp<IBinder>& displayToken) override;
+ status_t getDisplayColorModes(const sp<IBinder>& displayToken,
+ Vector<ui::ColorMode>* configs) override;
+ ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken) override;
+ status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override;
+ void setPowerMode(const sp<IBinder>& displayToken, int mode) override;
+ status_t setActiveConfig(const sp<IBinder>& displayToken, int id) override;
+ status_t clearAnimationFrameStats() override;
+ status_t getAnimationFrameStats(FrameStats* outStats) const override;
+ status_t getHdrCapabilities(const sp<IBinder>& displayToken,
+ HdrCapabilities* outCapabilities) const override;
+ status_t enableVSyncInjections(bool enable) override;
+ status_t injectVSync(nsecs_t when) override;
+ status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const override;
+ status_t getColorManagement(bool* outGetColorManagement) const override;
status_t getCompositionPreference(ui::Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
ui::Dataspace* outWideColorGamutDataspace,
ui::PixelFormat* outWideColorGamutPixelFormat) const override;
- virtual status_t getDisplayedContentSamplingAttributes(
- const sp<IBinder>& display, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const override;
- virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
- uint8_t componentMask,
- uint64_t maxFrames) const override;
- virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
- uint64_t timestamp,
- DisplayedFrameStats* outStats) const override;
+ status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
+ ui::PixelFormat* outFormat,
+ ui::Dataspace* outDataspace,
+ uint8_t* outComponentMask) const override;
+ status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+ uint8_t componentMask,
+ uint64_t maxFrames) const override;
+ status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
+ uint64_t timestamp,
+ DisplayedFrameStats* outStats) const override;
+ status_t getProtectedContentSupport(bool* outSupported) const override;
/* ------------------------------------------------------------------------
* DeathRecipient interface
*/
- virtual void binderDied(const wp<IBinder>& who);
+ void binderDied(const wp<IBinder>& who) override;
/* ------------------------------------------------------------------------
* RefBase interface
*/
- virtual void onFirstRef();
+ void onFirstRef() override;
/* ------------------------------------------------------------------------
* HWC2::ComposerCallback / HWComposer::EventHandler interface
@@ -504,13 +491,13 @@
void signalRefresh();
// called on the main thread in response to initializeDisplays()
- void onInitializeDisplays();
+ void onInitializeDisplays() REQUIRES(mStateLock);
// setActiveConfigInternal() posted on a main thread for async execution
status_t setActiveConfigAsync(const sp<IBinder>& displayToken, int mode);
// called on the main thread in response to setActiveConfig()
- void setActiveConfigInternal(const sp<IBinder>& displayToken, int mode);
+ void setActiveConfigInternal(const sp<IBinder>& displayToken, int mode) REQUIRES(mStateLock);
// called on the main thread in response to setPowerMode()
- void setPowerModeInternal(const sp<DisplayDevice>& display, int mode);
+ void setPowerModeInternal(const sp<DisplayDevice>& display, int mode) REQUIRES(mStateLock);
// Called on the main thread in response to setActiveColorMode()
void setActiveColorModeInternal(const sp<DisplayDevice>& display, ui::ColorMode colorMode,
@@ -706,6 +693,7 @@
void preComposition();
void postComposition();
+ void getCompositorTiming(CompositorTiming* compositorTiming);
void updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
std::shared_ptr<FenceTime>& presentFenceTime);
void setCompositorTimingSnapped(const DisplayStatInfo& stats,
@@ -760,18 +748,38 @@
/* ------------------------------------------------------------------------
* VSync
*/
+ nsecs_t getVsyncPeriod() const REQUIRES(mStateLock);
void enableHardwareVsync();
- void resyncToHardwareVsync(bool makeAvailable);
+ void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
void disableHardwareVsync(bool makeUnavailable);
-public:
- void resyncWithRateLimit();
- void getCompositorTiming(CompositorTiming* compositorTiming);
-private:
// Sets the refresh rate to newFps by switching active configs, if they are available for
// the desired refresh rate.
void setRefreshRateTo(float newFps);
+ using GetVsyncPeriod = std::function<nsecs_t()>;
+
+ // Stores per-display state about VSYNC.
+ struct VsyncState {
+ explicit VsyncState(SurfaceFlinger& flinger) : flinger(flinger) {}
+
+ void resync(const GetVsyncPeriod&);
+
+ SurfaceFlinger& flinger;
+ std::atomic<nsecs_t> lastResyncTime = 0;
+ };
+
+ const std::shared_ptr<VsyncState> mPrimaryVsyncState{std::make_shared<VsyncState>(*this)};
+
+ auto makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod) {
+ std::weak_ptr<VsyncState> ptr = mPrimaryVsyncState;
+ return [ptr, getVsyncPeriod = std::move(getVsyncPeriod)]() {
+ if (const auto vsync = ptr.lock()) {
+ vsync->resync(getVsyncPeriod);
+ }
+ };
+ }
+
/* ------------------------------------------------------------------------
* Debugging & dumpsys
*/
@@ -817,9 +825,11 @@
}
void listLayersLocked(const Vector<String16>& args, size_t& index, std::string& result) const;
- void dumpStatsLocked(const Vector<String16>& args, size_t& index, std::string& result) const;
+ void dumpStatsLocked(const Vector<String16>& args, size_t& index, std::string& result) const
+ REQUIRES(mStateLock);
void clearStatsLocked(const Vector<String16>& args, size_t& index, std::string& result);
- void dumpAllLocked(const Vector<String16>& args, size_t& index, std::string& result) const;
+ void dumpAllLocked(const Vector<String16>& args, size_t& index, std::string& result) const
+ REQUIRES(mStateLock);
bool startDdmConnection();
void appendSfConfigString(std::string& result) const;
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index a5b522e..a2c0611 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -11,6 +11,7 @@
shared_libs: [
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"android.hardware.power@1.3",
"libbase",
"libbinder",
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 2d26bb3..c18068f 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -47,10 +47,11 @@
class EventThreadTest : public testing::Test {
protected:
- class MockEventThreadConnection : public android::EventThreadConnection {
+ class MockEventThreadConnection : public EventThreadConnection {
public:
- explicit MockEventThreadConnection(android::impl::EventThread* eventThread)
- : android::EventThreadConnection(eventThread) {}
+ MockEventThreadConnection(android::impl::EventThread* eventThread,
+ ResyncCallback&& resyncCallback)
+ : EventThreadConnection(eventThread, std::move(resyncCallback)) {}
MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
};
@@ -113,14 +114,14 @@
void EventThreadTest::createThread() {
mThread =
std::make_unique<android::impl::EventThread>(&mVSyncSource,
- mResyncCallRecorder.getInvocable(),
mInterceptVSyncCallRecorder.getInvocable(),
"unit-test-event-thread");
}
sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
ConnectionEventRecorder& recorder) {
- sp<MockEventThreadConnection> connection = new MockEventThreadConnection(mThread.get());
+ sp<MockEventThreadConnection> connection =
+ new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable());
EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
return connection;
}
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 4253ad8..3dd5143 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -8,12 +8,9 @@
#include <mutex>
-#include "AsyncCallRecorder.h"
-#include "Scheduler/DispSync.h"
#include "Scheduler/EventControlThread.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/Scheduler.h"
-#include "mock/MockDispSync.h"
#include "mock/MockEventThread.h"
using testing::_;
@@ -26,7 +23,7 @@
class MockEventThreadConnection : public android::EventThreadConnection {
public:
explicit MockEventThreadConnection(EventThread* eventThread)
- : EventThreadConnection(eventThread) {}
+ : EventThreadConnection(eventThread, ResyncCallback()) {}
~MockEventThreadConnection() = default;
MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
@@ -46,7 +43,6 @@
std::unique_ptr<EventThread> makeEventThread(
const std::string& /* connectionName */, DispSync* /* dispSync */,
nsecs_t /* phaseOffsetNs */,
- impl::EventThread::ResyncWithRateLimitCallback /* resyncCallback */,
impl::EventThread::InterceptVSyncsCallback /* interceptCallback */) override {
return std::move(mEventThread);
}
@@ -61,13 +57,9 @@
~SchedulerTest() override;
sp<Scheduler::ConnectionHandle> mConnectionHandle;
- mock::DispSync* mPrimaryDispSync = new mock::DispSync();
mock::EventThread* mEventThread;
std::unique_ptr<MockScheduler> mScheduler;
sp<MockEventThreadConnection> mEventThreadConnection;
-
- AsyncCallRecorder<void (*)()> mResyncCallRecorder;
- AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
};
SchedulerTest::SchedulerTest() {
@@ -84,12 +76,12 @@
// createConnection call to scheduler makes a createEventConnection call to EventThread. Make
// sure that call gets executed and returns an EventThread::Connection object.
- EXPECT_CALL(*mEventThread, createEventConnection())
+ EXPECT_CALL(*mEventThread, createEventConnection(_))
.WillRepeatedly(Return(mEventThreadConnection));
- mConnectionHandle =
- mScheduler->createConnection("appConnection", 16, mResyncCallRecorder.getInvocable(),
- mInterceptVSyncCallRecorder.getInvocable());
+ mConnectionHandle = mScheduler->createConnection("appConnection", 16, ResyncCallback(),
+ impl::EventThread::InterceptVSyncsCallback());
+ EXPECT_TRUE(mConnectionHandle != nullptr);
}
SchedulerTest::~SchedulerTest() {
@@ -102,17 +94,13 @@
/* ------------------------------------------------------------------------
* Test cases
*/
-TEST_F(SchedulerTest, canCreateAndDestroyTest) {
- EXPECT_FALSE(mResyncCallRecorder.waitForCall().has_value());
- EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall().has_value());
- EXPECT_EQ(0, mConnectionHandle->id);
-}
TEST_F(SchedulerTest, testNullPtr) {
// Passing a null pointer for ConnectionHandle is a valid argument. The code doesn't throw any
// exceptions, just gracefully continues.
sp<IDisplayEventConnection> returnedValue;
- ASSERT_NO_FATAL_FAILURE(returnedValue = mScheduler->createDisplayEventConnection(nullptr));
+ ASSERT_NO_FATAL_FAILURE(
+ returnedValue = mScheduler->createDisplayEventConnection(nullptr, ResyncCallback()));
EXPECT_TRUE(returnedValue == nullptr);
EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
@@ -132,8 +120,9 @@
sp<Scheduler::ConnectionHandle> connectionHandle = new Scheduler::ConnectionHandle(20);
sp<IDisplayEventConnection> returnedValue;
- ASSERT_NO_FATAL_FAILURE(returnedValue =
- mScheduler->createDisplayEventConnection(connectionHandle));
+ ASSERT_NO_FATAL_FAILURE(
+ returnedValue =
+ mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback()));
EXPECT_TRUE(returnedValue == nullptr);
EXPECT_TRUE(mScheduler->getEventThread(connectionHandle) == nullptr);
EXPECT_TRUE(mScheduler->getEventConnection(connectionHandle) == nullptr);
@@ -160,8 +149,9 @@
TEST_F(SchedulerTest, validConnectionHandle) {
sp<IDisplayEventConnection> returnedValue;
- ASSERT_NO_FATAL_FAILURE(returnedValue =
- mScheduler->createDisplayEventConnection(mConnectionHandle));
+ ASSERT_NO_FATAL_FAILURE(
+ returnedValue =
+ mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback()));
EXPECT_TRUE(returnedValue != nullptr);
ASSERT_EQ(returnedValue, mEventThreadConnection);
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 9ff5e8d..15a8c5a 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -235,9 +235,14 @@
auto setDisplayStateLocked(const DisplayState& s) { return mFlinger->setDisplayStateLocked(s); }
- auto onInitializeDisplays() { return mFlinger->onInitializeDisplays(); }
+ // Allow reading display state without locking, as if called on the SF main thread.
+ auto onInitializeDisplays() NO_THREAD_SAFETY_ANALYSIS {
+ return mFlinger->onInitializeDisplays();
+ }
- auto setPowerModeInternal(const sp<DisplayDevice>& display, int mode) {
+ // Allow reading display state without locking, as if called on the SF main thread.
+ auto setPowerModeInternal(const sp<DisplayDevice>& display,
+ int mode) NO_THREAD_SAFETY_ANALYSIS {
return mFlinger->setPowerModeInternal(display, mode);
}
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index 48d45fa..3242ef1 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -28,7 +28,7 @@
EventThread();
~EventThread() override;
- MOCK_CONST_METHOD0(createEventConnection, sp<EventThreadConnection>());
+ MOCK_CONST_METHOD1(createEventConnection, sp<EventThreadConnection>(ResyncCallback));
MOCK_METHOD0(onScreenReleased, void());
MOCK_METHOD0(onScreenAcquired, void());
MOCK_METHOD2(onHotplugReceived, void(DisplayType, bool));
diff --git a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
index 8c113e2..e22d3e8 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
@@ -30,8 +30,8 @@
~MessageQueue() override;
MOCK_METHOD1(init, void(const sp<SurfaceFlinger>&));
- MOCK_METHOD1(setEventThread, void(android::EventThread*));
- MOCK_METHOD1(setEventConnection, void(const sp<android::EventThreadConnection>& connection));
+ MOCK_METHOD2(setEventThread, void(android::EventThread*, ResyncCallback));
+ MOCK_METHOD1(setEventConnection, void(const sp<EventThreadConnection>& connection));
MOCK_METHOD0(waitMessage, void());
MOCK_METHOD2(postMessage, status_t(const sp<MessageBase>&, nsecs_t));
MOCK_METHOD0(invalidate, void());
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 258b45b..d9df204 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -15,6 +15,7 @@
"android.frameworks.vr.composer@1.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"libbase",
"libbufferhubqueue",
"libbinder",