diff options
42 files changed, 1028 insertions, 227 deletions
diff --git a/include/android/display_luts.h b/include/android/display_luts.h new file mode 100644 index 0000000000..08dfb12d6c --- /dev/null +++ b/include/android/display_luts.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2024 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 display_luts.h + */ +#pragma once + +#include <inttypes.h> + +__BEGIN_DECLS + +/** + * The dimension of the lut + */ +enum ADisplayLuts_Dimension : int32_t { + ADISPLAYLUTS_ONE_DIMENSION = 1, + ADISPLAYLUTS_THREE_DIMENSION = 3, +}; +typedef enum ADisplayLuts_Dimension ADisplayLuts_Dimension; + +/** + * The sampling key used by the lut + */ +enum ADisplayLuts_SamplingKey : int32_t { + ADISPLAYLUTS_SAMPLINGKEY_RGB = 0, + ADISPLAYLUTS_SAMPLINGKEY_MAX_RGB = 1, +}; +typedef enum ADisplayLuts_SamplingKey ADisplayLuts_SamplingKey; + +/** + * Used to get and set display luts entry + */ +typedef struct ADisplayLutsEntry ADisplayLutsEntry; + +/** + * Used to get and set display luts + */ +typedef struct ADisplayLuts ADisplayLuts; + +/** + * Creates a \a ADisplayLutsEntry entry. + * + * You are responsible for mamanging the memory of the returned object. + * Always call \a ADisplayLutsEntry_destroy to release it after use. + * + * Functions like \a ADisplayLuts_set create their own copies of entries, + * therefore they don't take the ownership of the instance created by + * \a ADisplayLutsEntry_create. + * + * @param buffer The lut raw buffer. The function creates a copy of it and does not need to + * outlive the life of the ADisplayLutsEntry. + * @param length The length of lut raw buffer + * @param dimension The dimension of the lut. see \a ADisplayLuts_Dimension + * @param key The sampling key used by the lut. see \a ADisplayLuts_SamplingKey + * @return a new \a ADisplayLutsEntry instance. + */ +ADisplayLutsEntry* _Nonnull ADisplayLutsEntry_createEntry(float* _Nonnull buffer, + int32_t length, int32_t dimension, int32_t key) __INTRODUCED_IN(36); + +/** + * Destroy the \a ADisplayLutsEntry instance. + * + * @param entry The entry to be destroyed + */ +void ADisplayLutsEntry_destroy(ADisplayLutsEntry* _Nullable entry) __INTRODUCED_IN(36); + +/** + * Gets the dimension of the entry. + * + * The function is only valid for the lifetime of the `entry`. + * + * @param entry The entry to query + * @return the dimension of the lut + */ +ADisplayLuts_Dimension ADisplayLutsEntry_getDimension(const ADisplayLutsEntry* _Nonnull entry) + __INTRODUCED_IN(36); + +/** + * Gets the size for each dimension of the entry. + * + * The function is only valid for the lifetime of the `entry`. + * + * @param entry The entry to query + * @return the size of each dimension of the lut + */ +int32_t ADisplayLutsEntry_getSize(const ADisplayLutsEntry* _Nonnull entry) + __INTRODUCED_IN(36); + +/** + * Gets the sampling key used by the entry. + * + * The function is only valid for the lifetime of the `entry`. + * + * @param entry The entry to query + * @return the sampling key used by the lut + */ +ADisplayLuts_SamplingKey ADisplayLutsEntry_getSamplingKey(const ADisplayLutsEntry* _Nonnull entry) + __INTRODUCED_IN(36); + +/** + * Gets the lut buffer of the entry. + * + * The function is only valid for the lifetime of the `entry`. + * + * @param entry The entry to query + * @return a pointer to the raw lut buffer + */ +const float* _Nonnull ADisplayLutsEntry_getBuffer(const ADisplayLutsEntry* _Nonnull entry) + __INTRODUCED_IN(36); + +/** + * Creates a \a ADisplayLuts instance. + * + * You are responsible for mamanging the memory of the returned object. + * Always call \a ADisplayLuts_destroy to release it after use. E.g., after calling + * the function \a ASurfaceTransaction_setLuts. + * + * @return a new \a ADisplayLuts instance + */ +ADisplayLuts* _Nonnull ADisplayLuts_create() __INTRODUCED_IN(36); + +/** + * Sets Luts in order to be applied. + * + * The function accepts a single 1D Lut, or a single 3D Lut or both 1D and 3D Lut in order. + * And the function will replace any previously set lut(s). + * If you want to clear the previously set lut(s), set `entries` to be nullptr, + * and `numEntries` will be internally ignored. + * + * @param luts the pointer of the \a ADisplayLuts instance + * @param entries the pointer of the array of lut entries to be applied + * @param numEntries the number of lut entries. The value should be either 1 or 2. + */ +void ADisplayLuts_setEntries(ADisplayLuts* _Nonnull luts, + ADisplayLutsEntry* _Nullable *_Nullable entries, int32_t numEntries) __INTRODUCED_IN(36); + +/** + * Deletes the \a ADisplayLuts instance. + * + * @param luts The luts to be destroyed + */ +void ADisplayLuts_destroy(ADisplayLuts* _Nullable luts) __INTRODUCED_IN(36); + +__END_DECLS + +/** @} */
\ No newline at end of file diff --git a/include/android/looper.h b/include/android/looper.h index d80a3660a6..8cf13965bb 100644 --- a/include/android/looper.h +++ b/include/android/looper.h @@ -90,20 +90,23 @@ enum { ALOOPER_POLL_WAKE = -1, /** - * Result from ALooper_pollOnce() and ALooper_pollAll(): - * One or more callbacks were executed. + * Result from ALooper_pollOnce(): + * One or more callbacks were executed. The poll may also have been + * explicitly woken by ALooper_wake(). */ ALOOPER_POLL_CALLBACK = -2, /** * Result from ALooper_pollOnce() and ALooper_pollAll(): - * The timeout expired. + * The timeout expired. The poll may also have been explicitly woken by + * ALooper_wake(). */ ALOOPER_POLL_TIMEOUT = -3, /** * Result from ALooper_pollOnce() and ALooper_pollAll(): - * An error occurred. + * An error occurred. The poll may also have been explicitly woken by + * ALooper_wake(()). */ ALOOPER_POLL_ERROR = -4, }; @@ -182,10 +185,13 @@ typedef int (*ALooper_callbackFunc)(int fd, int events, void* data); * If the timeout is zero, returns immediately without blocking. * If the timeout is negative, waits indefinitely until an event appears. * + * **All return values may also imply ALOOPER_POLL_WAKE.** If you call this in a + * loop, you must treat all return values as if they also indicated + * ALOOPER_POLL_WAKE. + * * Returns ALOOPER_POLL_WAKE if the poll was awoken using ALooper_wake() before * the timeout expired and no callbacks were invoked and no other file - * descriptors were ready. **All return values may also imply - * ALOOPER_POLL_WAKE.** + * descriptors were ready. * * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked. The poll * may also have been explicitly woken by ALooper_wake. @@ -214,9 +220,9 @@ int ALooper_pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outDa * data has been consumed or a file descriptor is available with no callback. * This function will never return ALOOPER_POLL_CALLBACK. * - * This API cannot be used safely, but a safe alternative exists (see below). As - * such, new builds will not be able to call this API and must migrate to the - * safe API. Binary compatibility is preserved to support already-compiled apps. + * This API will not reliably respond to ALooper_wake. As such, this API is + * hidden and callers should migrate to ALooper_pollOnce. Binary compatibility + * is preserved to support already-compiled apps. * * \bug ALooper_pollAll will not wake in response to ALooper_wake calls if it * also handles another event at the same time. @@ -235,6 +241,8 @@ int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outDat * * This method can be called on any thread. * This method returns immediately. + * + * \bug ALooper_pollAll will not reliably wake in response to ALooper_wake. */ void ALooper_wake(ALooper* looper); diff --git a/include/android/performance_hint.h b/include/android/performance_hint.h index 37d320a662..fba063db69 100644 --- a/include/android/performance_hint.h +++ b/include/android/performance_hint.h @@ -518,7 +518,7 @@ int ASessionCreationConfig_setPreferPowerEfficiency( pipeline is reached. */ int ASessionCreationConfig_setGraphicsPipeline( - ASessionCreationConfig* _Nonnull confi, bool enabled) __INTRODUCED_IN(36); + ASessionCreationConfig* _Nonnull config, bool enabled) __INTRODUCED_IN(36); __END_DECLS diff --git a/include/android/surface_control.h b/include/android/surface_control.h index fe38e86015..95540153b3 100644 --- a/include/android/surface_control.h +++ b/include/android/surface_control.h @@ -28,6 +28,7 @@ #include <sys/cdefs.h> +#include <android/display_luts.h> #include <android/choreographer.h> #include <android/data_space.h> #include <android/hardware_buffer.h> @@ -713,6 +714,23 @@ void ASurfaceTransaction_setDesiredHdrHeadroom(ASurfaceTransaction* _Nonnull tra __INTRODUCED_IN(__ANDROID_API_V__); /** + * Sets the Lut(s) to be applied for the layer. + * + * The function makes a deep copy of the provided `luts`. + * Any modifications made to the `luts` object after calling this function + * will not affect the Lut(s) applied to the layer. + * + * @param surface_control The layer where Lut(s) is being applied + * @param luts The Lut(s) to be applied + * + * Available since API level 36. + */ +void ASurfaceTransaction_setLuts(ASurfaceTransaction* _Nonnull transaction, + ASurfaceControl* _Nonnull surface_control, + const struct ADisplayLuts* _Nullable luts) + __INTRODUCED_IN(36); + +/** * Same as ASurfaceTransaction_setFrameRateWithChangeStrategy(transaction, surface_control, * frameRate, compatibility, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS). * diff --git a/include/ftl/flags.h b/include/ftl/flags.h index dbe3148fc5..a2a22ebebe 100644 --- a/include/ftl/flags.h +++ b/include/ftl/flags.h @@ -22,6 +22,7 @@ #include <bitset> #include <cstdint> #include <iterator> +#include <initializer_list> #include <string> #include <type_traits> @@ -40,6 +41,7 @@ class Flags { public: constexpr Flags(F f) : mFlags(static_cast<U>(f)) {} + constexpr Flags(std::initializer_list<F> fs) : mFlags(combine(fs)) {} constexpr Flags() : mFlags(0) {} constexpr Flags(const Flags<F>& f) : mFlags(f.mFlags) {} @@ -197,6 +199,14 @@ public: private: U mFlags; + static constexpr U combine(std::initializer_list<F> fs) { + U result = 0; + for (const F f : fs) { + result |= static_cast<U>(f); + } + return result; + } + static void appendFlag(std::string& str, const std::string_view& flag, bool& first) { if (first) { first = false; diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 6b45dd39dc..ea1e4aee01 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -111,12 +111,12 @@ enum class InputDeviceSensorType : int32_t { }; enum class InputDeviceSensorAccuracy : int32_t { - ACCURACY_NONE = 0, - ACCURACY_LOW = 1, - ACCURACY_MEDIUM = 2, - ACCURACY_HIGH = 3, + NONE = 0, + LOW = 1, + MEDIUM = 2, + HIGH = 3, - ftl_last = ACCURACY_HIGH, + ftl_last = HIGH, }; enum class InputDeviceSensorReportingMode : int32_t { diff --git a/include/private/display_luts_private.h b/include/private/display_luts_private.h new file mode 100644 index 0000000000..240e1f98cf --- /dev/null +++ b/include/private/display_luts_private.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <stdint.h> +#include <vector> +#include <utils/RefBase.h> + +using namespace android; + +__BEGIN_DECLS + +struct ADisplayLutsEntry_buffer { + std::vector<float> data; +}; + +struct ADisplayLutsEntry_properties { + int32_t dimension; + int32_t size; + int32_t samplingKey; +}; + +struct ADisplayLutsEntry: public RefBase { + struct ADisplayLutsEntry_buffer buffer; + struct ADisplayLutsEntry_properties properties; + ADisplayLutsEntry() {} + + // copy constructor + ADisplayLutsEntry(const ADisplayLutsEntry& other) : + buffer(other.buffer), + properties(other.properties) {} + + // copy operator + ADisplayLutsEntry& operator=(const ADisplayLutsEntry& other) { + if (this != &other) { // Protect against self-assignment + buffer = other.buffer; + properties = other.properties; + } + return *this; + } +}; + +struct ADisplayLuts: public RefBase { + int32_t totalBufferSize; + std::vector<int32_t> offsets; + std::vector<sp<ADisplayLutsEntry>> entries; + + ADisplayLuts() : totalBufferSize(0) {} +}; + +__END_DECLS
\ No newline at end of file diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 96d821e196..a5f416f1ba 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -2223,9 +2223,7 @@ const char* Parcel::readCString() const const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail)); if (eos) { const size_t len = eos - str; - mDataPos += pad_size(len+1); - ALOGV("readCString Setting data pos of %p to %zu", this, mDataPos); - return str; + return static_cast<const char*>(readInplace(len + 1)); } } return nullptr; diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING index ab449572d6..99a9c911bf 100644 --- a/libs/binder/TEST_MAPPING +++ b/libs/binder/TEST_MAPPING @@ -67,15 +67,7 @@ "name": "fuzz_service_test" }, { - "name": "CtsOsTestCases", - "options": [ - { - "include-filter": "android.os.cts.BinderTest" - }, - { - "include-filter": "android.os.cts.ParcelTest" - } - ] + "name": "CtsOsTestCases_ParcelAndBinderTests" }, { "name": "libbinder_rs-internal_test" diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index ceab20a275..0c7366e683 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -178,7 +178,8 @@ public: LIBBINDER_EXPORTED status_t writeUint64(uint64_t val); LIBBINDER_EXPORTED status_t writeFloat(float val); LIBBINDER_EXPORTED status_t writeDouble(double val); - LIBBINDER_EXPORTED status_t writeCString(const char* str); + LIBBINDER_EXPORTED status_t writeCString(const char* str) + __attribute__((deprecated("use AIDL, writeString* instead"))); LIBBINDER_EXPORTED status_t writeString8(const String8& str); LIBBINDER_EXPORTED status_t writeString8(const char* str, size_t len); LIBBINDER_EXPORTED status_t writeString16(const String16& str); @@ -434,7 +435,8 @@ public: LIBBINDER_EXPORTED status_t readUtf8FromUtf16(std::unique_ptr<std::string>* str) const __attribute__((deprecated("use std::optional version instead"))); - LIBBINDER_EXPORTED const char* readCString() const; + LIBBINDER_EXPORTED const char* readCString() const + __attribute__((deprecated("use AIDL, use readString*"))); LIBBINDER_EXPORTED String8 readString8() const; LIBBINDER_EXPORTED status_t readString8(String8* pArg) const; LIBBINDER_EXPORTED const char* readString8Inplace(size_t* outLen) const; diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs index 14493db262..1b24b0a1e1 100644 --- a/libs/binder/rust/src/lib.rs +++ b/libs/binder/rust/src/lib.rs @@ -126,7 +126,7 @@ pub use service::{get_interface, get_service}; #[cfg(not(any(trusty, android_ndk)))] pub use state::{ProcessState, ThreadState}; #[cfg(not(any(android_vendor, android_vndk, android_ndk)))] -pub use system_only::{delegate_accessor, Accessor, ConnectionInfo}; +pub use system_only::{delegate_accessor, Accessor, AccessorProvider, ConnectionInfo}; /// Binder result containing a [`Status`] on error. pub type Result<T> = std::result::Result<T, Status>; diff --git a/libs/binder/rust/src/system_only.rs b/libs/binder/rust/src/system_only.rs index 9833cbe4e2..3da59ab811 100644 --- a/libs/binder/rust/src/system_only.rs +++ b/libs/binder/rust/src/system_only.rs @@ -100,17 +100,36 @@ impl Accessor { unsafe { SpIBinder::from_raw(sys::ABinderRpc_Accessor_asBinder(self.accessor)) } } + /// Release the underlying ABinderRpc_Accessor pointer for use with the ndk API + /// This gives up ownership of the ABinderRpc_Accessor and it is the responsibility of + /// the caller to delete it with ABinderRpc_Accessor_delete + /// + /// # Safety + /// + /// - The returned `ABinderRpc_Accessor` pointer is now owned by the caller, who must + /// call `ABinderRpc_Accessor_delete` to delete the object. + /// - This `Accessor` object is now useless after `release` so it can be dropped. + unsafe fn release(mut self) -> *mut sys::ABinderRpc_Accessor { + if self.accessor.is_null() { + log::error!("Attempting to release an Accessor that was already released"); + return ptr::null_mut(); + } + let ptr = self.accessor; + self.accessor = ptr::null_mut(); + ptr + } + /// Callback invoked from C++ when the connection info is needed. /// /// # Safety /// - /// The `instance` parameter must be a non-null pointer to a valid C string for - /// CStr::from_ptr. The memory must contain a valid null terminator at the end of - /// the string within isize::MAX from the pointer. The memory must not be mutated for - /// the duration of this function call and must be valid for reads from the pointer - /// to the null terminator. - /// The `cookie` parameter must be the cookie for an `Arc<F>` and - /// the caller must hold a ref-count to it. + /// - The `instance` parameter must be a non-null pointer to a valid C string for + /// CStr::from_ptr. The memory must contain a valid null terminator at the end of + /// the string within isize::MAX from the pointer. The memory must not be mutated for + /// the duration of this function call and must be valid for reads from the pointer + /// to the null terminator. + /// - The `cookie` parameter must be the cookie for an `Arc<F>` and + /// the caller must hold a ref-count to it. unsafe extern "C" fn connection_info<F>( instance: *const c_char, cookie: *mut c_void, @@ -172,8 +191,8 @@ impl Accessor { /// /// # Safety /// - /// The `cookie` parameter must be the cookie for an `Arc<F>` and - /// the owner must give up a ref-count to it. + /// - The `cookie` parameter must be the cookie for an `Arc<F>` and + /// the owner must give up a ref-count to it. unsafe extern "C" fn cookie_decr_refcount<F>(cookie: *mut c_void) where F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static, @@ -185,6 +204,10 @@ impl Accessor { impl Drop for Accessor { fn drop(&mut self) { + if self.accessor.is_null() { + // This Accessor was already released. + return; + } // Safety: `self.accessor` is always a valid, owned // `ABinderRpc_Accessor` pointer returned by // `ABinderRpc_Accessor_new` when `self` was created. This delete @@ -218,3 +241,140 @@ pub fn delegate_accessor(name: &str, mut binder: SpIBinder) -> Result<SpIBinder> // point, so can be safely passed to `SpIBinder::from_raw`. Ok(unsafe { SpIBinder::from_raw(delegator).expect("Expected valid binder at this point") }) } + +/// Rust wrapper around ABinderRpc_AccessorProvider objects for RPC binder service management. +/// +/// Dropping the `AccessorProvider` will drop/unregister the underlying object. +#[derive(Debug)] +pub struct AccessorProvider { + accessor_provider: *mut sys::ABinderRpc_AccessorProvider, +} + +/// Safety: A `AccessorProvider` is a wrapper around `ABinderRpc_AccessorProvider` which is +/// `Sync` and `Send`. As +/// `ABinderRpc_AccessorProvider` is threadsafe, this structure is too. +/// The Fn owned the AccessorProvider has `Sync` and `Send` properties +unsafe impl Send for AccessorProvider {} + +/// Safety: A `AccessorProvider` is a wrapper around `ABinderRpc_AccessorProvider` which is +/// `Sync` and `Send`. As `ABinderRpc_AccessorProvider` is threadsafe, this structure is too. +/// The Fn owned the AccessorProvider has `Sync` and `Send` properties +unsafe impl Sync for AccessorProvider {} + +impl AccessorProvider { + /// Create a new `AccessorProvider` that will give libbinder `Accessors` in order to + /// connect to binder services over sockets. + /// + /// `instances` is a list of all instances that this `AccessorProvider` is responsible for. + /// It is declaring these instances as available to this process and will return + /// `Accessor` objects for them when libbinder calls the `provider` callback. + /// `provider` is the callback that libbinder will call when a service is being requested. + /// The callback takes a `&str` argument representing the service that is being requested. + /// See the `ABinderRpc_AccessorProvider_getAccessorCallback` for the C++ equivalent. + pub fn new<F>(instances: &[String], provider: F) -> Option<AccessorProvider> + where + F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static, + { + let callback: *mut c_void = Arc::into_raw(Arc::new(provider)) as *mut c_void; + let c_str_instances: Vec<CString> = + instances.iter().map(|s| CString::new(s.as_bytes()).unwrap()).collect(); + let mut c_instances: Vec<*const c_char> = + c_str_instances.iter().map(|s| s.as_ptr()).collect(); + let num_instances: usize = c_instances.len(); + // Safety: + // - The function pointer for the first argument is a valid `get_accessor` callback. + // - This call returns an owned `ABinderRpc_AccessorProvider` pointer which + // must be destroyed via `ABinderRpc_unregisterAccessorProvider` when no longer + // needed. + // - When the underlying ABinderRpc_AccessorProvider is deleted, it will call + // the `cookie_decr_refcount` callback on the `callback` pointer to release its + // strong ref. + // - The `c_instances` vector is not modified by the function + let accessor_provider = unsafe { + sys::ABinderRpc_registerAccessorProvider( + Some(Self::get_accessor::<F>), + c_instances.as_mut_ptr(), + num_instances, + callback, + Some(Self::accessor_cookie_decr_refcount::<F>), + ) + }; + + if accessor_provider.is_null() { + return None; + } + Some(AccessorProvider { accessor_provider }) + } + + /// Callback invoked from C++ when an Accessor is needed. + /// + /// # Safety + /// + /// - libbinder guarantees the `instance` argument is a valid C string if it's not null. + /// - The `cookie` pointer is same pointer that we pass to ABinderRpc_registerAccessorProvider + /// in AccessorProvider.new() which is the closure that we will delete with + /// self.accessor_cookie_decr_refcount when unregistering the AccessorProvider. + unsafe extern "C" fn get_accessor<F>( + instance: *const c_char, + cookie: *mut c_void, + ) -> *mut binder_ndk_sys::ABinderRpc_Accessor + where + F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static, + { + if cookie.is_null() || instance.is_null() { + log::error!("Cookie({cookie:p}) or instance({instance:p}) is null!"); + return ptr::null_mut(); + } + // Safety: The caller promises that `cookie` is for an Arc<F>. + let callback = unsafe { (cookie as *const F).as_ref().unwrap() }; + + let inst = { + // Safety: The caller in libbinder_ndk will have already verified this is a valid + // C string + match unsafe { CStr::from_ptr(instance) }.to_str() { + Ok(s) => s, + Err(err) => { + log::error!("Failed to get a valid C string! {err:?}"); + return ptr::null_mut(); + } + } + }; + + match callback(inst) { + Some(a) => { + // Safety: This is giving up ownership of this ABinderRpc_Accessor + // to the caller of this function (libbinder) and it is responsible + // for deleting it. + unsafe { a.release() } + } + None => ptr::null_mut(), + } + } + + /// Callback that decrements the ref-count. + /// This is invoked from C++ when the provider is unregistered. + /// + /// # Safety + /// + /// - The `cookie` parameter must be the cookie for an `Arc<F>` and + /// the owner must give up a ref-count to it. + unsafe extern "C" fn accessor_cookie_decr_refcount<F>(cookie: *mut c_void) + where + F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static, + { + // Safety: The caller promises that `cookie` is for an Arc<F>. + unsafe { Arc::decrement_strong_count(cookie as *const F) }; + } +} + +impl Drop for AccessorProvider { + fn drop(&mut self) { + // Safety: `self.accessor_provider` is always a valid, owned + // `ABinderRpc_AccessorProvider` pointer returned by + // `ABinderRpc_registerAccessorProvider` when `self` was created. This delete + // method can only be called once when `self` is dropped. + unsafe { + sys::ABinderRpc_unregisterAccessorProvider(self.accessor_provider); + } + } +} diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs index 489fa0aa69..0e793e5761 100644 --- a/libs/binder/rust/tests/integration.rs +++ b/libs/binder/rust/tests/integration.rs @@ -384,8 +384,8 @@ mod tests { use std::time::Duration; use binder::{ - Accessor, BinderFeatures, DeathRecipient, FromIBinder, IBinder, Interface, SpIBinder, - StatusCode, Strong, + Accessor, AccessorProvider, BinderFeatures, DeathRecipient, FromIBinder, IBinder, + Interface, SpIBinder, StatusCode, Strong, }; // Import from impl API for testing only, should not be necessary as long as // you are using AIDL. @@ -982,6 +982,62 @@ mod tests { assert_eq!(delegator_binder, Err(StatusCode::NAME_NOT_FOUND)); } + #[test] + fn test_accessor_provider_simple() { + let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()]; + let accessor = AccessorProvider::new(&instances, move |_inst: &str| None); + assert!(accessor.is_some()); + } + + #[test] + fn test_accessor_provider_no_instance() { + let instances: Vec<String> = vec![]; + let accessor = AccessorProvider::new(&instances, move |_inst: &str| None); + assert!(accessor.is_none()); + } + + #[test] + fn test_accessor_provider_double_register() { + let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()]; + let accessor = AccessorProvider::new(&instances, move |_inst: &str| None); + assert!(accessor.is_some()); + let accessor2 = AccessorProvider::new(&instances, move |_inst: &str| None); + assert!(accessor2.is_none()); + } + + #[test] + fn test_accessor_provider_register_drop_register() { + let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()]; + { + let accessor = AccessorProvider::new(&instances, move |_inst: &str| None); + assert!(accessor.is_some()); + // accessor drops and unregisters the provider + } + { + let accessor = AccessorProvider::new(&instances, move |_inst: &str| None); + assert!(accessor.is_some()); + } + } + + #[test] + fn test_accessor_provider_callback_destruction() { + let deleted: Arc<AtomicBool> = Arc::new(AtomicBool::new(false)); + let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()]; + { + let accessor: Option<AccessorProvider>; + { + let helper = ToBeDeleted { deleted: deleted.clone() }; + accessor = AccessorProvider::new(&instances, move |_inst: &str| { + let _ = &helper; + None + }); + } + assert!(accessor.is_some()); + assert!(!deleted.load(Ordering::Relaxed)); + } + assert!(deleted.load(Ordering::Relaxed)); + } + #[tokio::test] async fn reassociate_rust_binder_async() { let service_name = "testing_service"; diff --git a/libs/binder/tests/binderParcelUnitTest.cpp b/libs/binder/tests/binderParcelUnitTest.cpp index 32a70e5b11..6259d9d2d2 100644 --- a/libs/binder/tests/binderParcelUnitTest.cpp +++ b/libs/binder/tests/binderParcelUnitTest.cpp @@ -33,6 +33,38 @@ using android::String8; using android::binder::Status; using android::binder::unique_fd; +static void checkCString(const char* str) { + for (size_t i = 0; i < 3; i++) { + Parcel p; + + for (size_t j = 0; j < i; j++) p.writeInt32(3); + + p.writeCString(str); + int32_t pos = p.dataPosition(); + + p.setDataPosition(0); + + for (size_t j = 0; j < i; j++) p.readInt32(); + const char* str2 = p.readCString(); + + ASSERT_EQ(std::string(str), str2); + ASSERT_EQ(pos, p.dataPosition()); + } +} + +TEST(Parcel, TestReadCString) { + // we should remove the *CString APIs, but testing them until + // they are deleted. + checkCString(""); + checkCString("a"); + checkCString("\n"); + checkCString("32"); + checkCString("321"); + checkCString("3210"); + checkCString("3210b"); + checkCString("123434"); +} + TEST(Parcel, NonNullTerminatedString8) { String8 kTestString = String8("test-is-good"); diff --git a/libs/ftl/flags_test.cpp b/libs/ftl/flags_test.cpp index 1279d1147d..bb43e8d2a3 100644 --- a/libs/ftl/flags_test.cpp +++ b/libs/ftl/flags_test.cpp @@ -17,7 +17,7 @@ #include <ftl/flags.h> #include <gtest/gtest.h> -#include <type_traits> +#include <initializer_list> namespace android::test { @@ -59,6 +59,18 @@ TEST(Flags, All) { ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); } +TEST(Flags, ImplicitConstructionAndAssignmentFromInitializerList) { + Flags<TestFlags> flags = {TestFlags::ONE, TestFlags::THREE}; + ASSERT_TRUE(flags.test(TestFlags::ONE)); + ASSERT_FALSE(flags.test(TestFlags::TWO)); + ASSERT_TRUE(flags.test(TestFlags::THREE)); + + flags = {}; + ASSERT_FALSE(flags.test(TestFlags::ONE)); + ASSERT_FALSE(flags.test(TestFlags::TWO)); + ASSERT_FALSE(flags.test(TestFlags::THREE)); +} + TEST(Flags, DefaultConstructor_hasNoFlagsSet) { Flags<TestFlags> flags; ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 1e33abbdea..052b519db6 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -264,6 +264,7 @@ filegroup { "DisplayEventDispatcher.cpp", "DisplayEventReceiver.cpp", "FenceMonitor.cpp", + "Flags.cpp", "GLConsumer.cpp", "IConsumerListener.cpp", "IGraphicBufferConsumer.cpp", diff --git a/libs/gui/Flags.cpp b/libs/gui/Flags.cpp new file mode 100644 index 0000000000..85ee2cddad --- /dev/null +++ b/libs/gui/Flags.cpp @@ -0,0 +1,73 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gui/Flags.h> +#include <gui/IGraphicBufferProducer.h> +#include <gui/Surface.h> +#include <gui/view/Surface.h> + +namespace android { +namespace flagtools { +sp<SurfaceType> surfaceToSurfaceType(const sp<Surface>& surface) { +#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES + return surface; +#else + return surface->getIGraphicBufferProducer(); +#endif +} + +sp<IGraphicBufferProducer> surfaceTypeToIGBP(const sp<SurfaceType>& surface) { +#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES + return surface->getIGraphicBufferProducer(); +#else + return surface; +#endif +} + +bool isSurfaceTypeValid(const sp<SurfaceType>& surface) { +#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES + return Surface::isValid(surface); +#else + return surface != nullptr; +#endif +} + +ParcelableSurfaceType toParcelableSurfaceType(const view::Surface& surface) { +#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES + return surface; +#else + return surface.graphicBufferProducer; +#endif +} + +ParcelableSurfaceType convertSurfaceTypeToParcelable(sp<SurfaceType> surface) { +#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES + return view::Surface::fromSurface(surface); +#else + return surface; +#endif +} + +sp<SurfaceType> convertParcelableSurfaceTypeToSurface(const ParcelableSurfaceType& surface) { +#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES + return surface.toSurface(); +#else + return surface; +#endif +} + +} // namespace flagtools +} // namespace android
\ No newline at end of file diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 793377668c..be88b11b9c 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -2873,6 +2873,11 @@ void SurfaceComposerClient::getDynamicDisplayInfoInternal(gui::DynamicDisplayInf outInfo->hasArrSupport = ginfo.hasArrSupport; outInfo->frameRateCategoryRate = ui::FrameRateCategoryRate(ginfo.frameRateCategoryRate.normal, ginfo.frameRateCategoryRate.high); + outInfo->supportedRefreshRates.clear(); + outInfo->supportedRefreshRates.reserve(ginfo.supportedRefreshRates.size()); + for (const auto rate : ginfo.supportedRefreshRates) { + outInfo->supportedRefreshRates.push_back(static_cast<float>(rate)); + } } status_t SurfaceComposerClient::getDynamicDisplayInfoFromId(int64_t displayId, diff --git a/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl b/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl index 67cc273fce..26c12c56f3 100644 --- a/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl +++ b/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl @@ -50,4 +50,7 @@ parcelable DynamicDisplayInfo { // Represents frame rate for FrameRateCategory Normal and High. FrameRateCategoryRate frameRateCategoryRate; + + // All the refresh rates supported for the default display mode. + float[] supportedRefreshRates; } diff --git a/libs/gui/aidl/android/gui/LutProperties.aidl b/libs/gui/aidl/android/gui/LutProperties.aidl index 87b878c1ca..84c7013cda 100644 --- a/libs/gui/aidl/android/gui/LutProperties.aidl +++ b/libs/gui/aidl/android/gui/LutProperties.aidl @@ -27,6 +27,6 @@ parcelable LutProperties { int size; @Backing(type="int") - enum SamplingKey { RGB, MAX_RGB } + enum SamplingKey { RGB, MAX_RGB, CIE_Y } SamplingKey[] samplingKeys; }
\ No newline at end of file diff --git a/libs/gui/include/gui/Flags.h b/libs/gui/include/gui/Flags.h index 34350d2c91..845bc54c71 100644 --- a/libs/gui/include/gui/Flags.h +++ b/libs/gui/include/gui/Flags.h @@ -17,8 +17,15 @@ #pragma once #include <com_android_graphics_libgui_flags.h> -#include <gui/IGraphicBufferProducer.h> -#include <gui/Surface.h> +#include <utils/StrongPointer.h> + +namespace android { + +class IGraphicBufferProducer; +class Surface; +namespace view { +class Surface; +} #define WB_CAMERA3_AND_PROCESSORS_WITH_DEPENDENCIES \ (COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CAMERA3_AND_PROCESSORS) && \ @@ -31,6 +38,19 @@ #if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES typedef android::Surface SurfaceType; +typedef android::view::Surface ParcelableSurfaceType; #else typedef android::IGraphicBufferProducer SurfaceType; -#endif
\ No newline at end of file +typedef android::sp<android::IGraphicBufferProducer> ParcelableSurfaceType; +#endif + +namespace flagtools { +sp<SurfaceType> surfaceToSurfaceType(const sp<Surface>& surface); +ParcelableSurfaceType toParcelableSurfaceType(const view::Surface& surface); +sp<IGraphicBufferProducer> surfaceTypeToIGBP(const sp<SurfaceType>& surface); +bool isSurfaceTypeValid(const sp<SurfaceType>& surface); +ParcelableSurfaceType convertSurfaceTypeToParcelable(sp<SurfaceType> surface); +sp<SurfaceType> convertParcelableSurfaceTypeToSurface(const ParcelableSurfaceType& surface); +} // namespace flagtools + +} // namespace android diff --git a/libs/gui/include/gui/view/Surface.h b/libs/gui/include/gui/view/Surface.h index 7c762d3869..bd8704ddc7 100644 --- a/libs/gui/include/gui/view/Surface.h +++ b/libs/gui/include/gui/view/Surface.h @@ -54,6 +54,22 @@ class Surface : public Parcelable { sp<android::Surface> toSurface() const; status_t getUniqueId(/* out */ uint64_t* id) const; + + bool isEmpty() const; + + bool operator==(const Surface& other) const { + return graphicBufferProducer == other.graphicBufferProducer; + } + bool operator!=(const Surface& other) const { return !(*this == other); } + bool operator==(const sp<android::Surface> other) const { + if (other == nullptr) return graphicBufferProducer == nullptr; + return graphicBufferProducer == other->getIGraphicBufferProducer(); + } + bool operator!=(const sp<android::Surface> other) const { return !(*this == other); } + bool operator<(const Surface& other) const { + return graphicBufferProducer < other.graphicBufferProducer; + } + bool operator>(const Surface& other) const { return other < *this; } #endif virtual status_t writeToParcel(Parcel* parcel) const override; diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp index 9f57923886..2cf7081ede 100644 --- a/libs/gui/view/Surface.cpp +++ b/libs/gui/view/Surface.cpp @@ -151,6 +151,10 @@ status_t Surface::getUniqueId(uint64_t* out_id) const { } return OK; } + +bool Surface::isEmpty() const { + return graphicBufferProducer == nullptr; +} #endif std::string Surface::toString() const { diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 0fd982e812..95c4d033e2 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -38,6 +38,14 @@ #define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.renderengine.backend" /** + * Allows opting particular devices into an initial preview rollout of RenderEngine on Graphite. + * + * Only applicable within SurfaceFlinger, and if relevant aconfig flags are enabled. + */ +#define PROPERTY_DEBUG_RENDERENGINE_GRAPHITE_PREVIEW_OPTIN \ + "debug.renderengine.graphite_preview_optin" + +/** * Turns on recording of skia commands in SkiaGL version of the RE. This property * defines number of milliseconds for the recording to take place. A non zero value * turns on the recording. diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index 8f232492e9..b3284e48c5 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -545,6 +545,7 @@ sk_sp<SkShader> SkiaRenderEngine::createRuntimeEffectShader( if (graphicBuffer && parameters.layer.luts) { shader = mLutShader.lutShader(shader, parameters.layer.luts, + parameters.layer.sourceDataspace, toSkColorSpace(parameters.outputDataSpace)); } diff --git a/libs/renderengine/skia/filters/LutShader.cpp b/libs/renderengine/skia/filters/LutShader.cpp index 1e43ff3cd3..5e9dfbba3e 100644 --- a/libs/renderengine/skia/filters/LutShader.cpp +++ b/libs/renderengine/skia/filters/LutShader.cpp @@ -15,11 +15,13 @@ */ #include "LutShader.h" +#include <SkM44.h> #include <SkTileMode.h> #include <common/trace.h> #include <cutils/ashmem.h> #include <math/half.h> #include <sys/mman.h> +#include <ui/ColorSpace.h> #include "include/core/SkColorSpace.h" #include "src/core/SkColorFilterPriv.h" @@ -36,6 +38,8 @@ static const SkString kShader = SkString(R"( uniform int size; uniform int key; uniform int dimension; + uniform vec3 luminanceCoefficients; // for CIE_Y + vec4 main(vec2 xy) { float4 rgba = image.eval(xy); float3 linear = toLinearSrgb(rgba.rgb); @@ -51,12 +55,16 @@ static const SkString kShader = SkString(R"( return float4(linear.r * gainR, linear.g * gainG, linear.b * gainB, rgba.a); // MAX_RGB } else if (key == 1) { - float4 rgba = image.eval(xy); - float3 linear = toLinearSrgb(rgba.rgb); float maxRGB = max(linear.r, max(linear.g, linear.b)); float index = maxRGB * float(size - 1); float gain = lut.eval(vec2(index, 0.0) + 0.5).r; return float4(linear * gain, rgba.a); + // CIE_Y + } else if (key == 2) { + float y = dot(linear, luminanceCoefficients) / 3.0; + float index = y * float(size - 1); + float gain = lut.eval(vec2(index, 0.0) + 0.5).r; + return float4(linear * gain, rgba.a); } } else if (dimension == 3) { if (key == 0) { @@ -110,11 +118,37 @@ static const SkString kShader = SkString(R"( return rgba; })"); +// same as shader::toColorSpace function +// TODO: put this function in a general place +static ColorSpace toColorSpace(ui::Dataspace dataspace) { + switch (dataspace & HAL_DATASPACE_STANDARD_MASK) { + case HAL_DATASPACE_STANDARD_BT709: + return ColorSpace::sRGB(); + case HAL_DATASPACE_STANDARD_DCI_P3: + return ColorSpace::DisplayP3(); + case HAL_DATASPACE_STANDARD_BT2020: + case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE: + return ColorSpace::BT2020(); + case HAL_DATASPACE_STANDARD_ADOBE_RGB: + return ColorSpace::AdobeRGB(); + case HAL_DATASPACE_STANDARD_BT601_625: + case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED: + case HAL_DATASPACE_STANDARD_BT601_525: + case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED: + case HAL_DATASPACE_STANDARD_BT470M: + case HAL_DATASPACE_STANDARD_FILM: + case HAL_DATASPACE_STANDARD_UNSPECIFIED: + default: + return ColorSpace::sRGB(); + } +} + sk_sp<SkShader> LutShader::generateLutShader(sk_sp<SkShader> input, const std::vector<float>& buffers, const int32_t offset, const int32_t length, const int32_t dimension, const int32_t size, - const int32_t samplingKey) { + const int32_t samplingKey, + ui::Dataspace srcDataspace) { SFTRACE_NAME("lut shader"); std::vector<half> buffer(length * 4); // 4 is for RGBA auto d = static_cast<LutProperties::Dimension>(dimension); @@ -133,12 +167,16 @@ sk_sp<SkShader> LutShader::generateLutShader(sk_sp<SkShader> input, } } /** - * 1D Lut(rgba) + * 1D Lut RGB/MAX_RGB * (R0, 0, 0, 0) * (R1, 0, 0, 0) + * + * 1D Lut CIE_Y + * (Y0, 0, 0, 0) + * (Y1, 0, 0, 0) * ... * - * 3D Lut + * 3D Lut MAX_RGB * (R0, G0, B0, 0) * (R1, G1, B1, 0) * ... @@ -162,6 +200,14 @@ sk_sp<SkShader> LutShader::generateLutShader(sk_sp<SkShader> input, const int uSize = static_cast<int>(size); const int uKey = static_cast<int>(samplingKey); const int uDimension = static_cast<int>(dimension); + if (static_cast<LutProperties::SamplingKey>(samplingKey) == LutProperties::SamplingKey::CIE_Y) { + // Use predefined colorspaces of input dataspace so that we can get D65 illuminant + mat3 toXYZMatrix(toColorSpace(srcDataspace).getRGBtoXYZ()); + mBuilder->uniform("luminanceCoefficients") = + SkV3{toXYZMatrix[0][1], toXYZMatrix[1][1], toXYZMatrix[2][1]}; + } else { + mBuilder->uniform("luminanceCoefficients") = SkV3{1.f, 1.f, 1.f}; + } mBuilder->uniform("size") = uSize; mBuilder->uniform("key") = uKey; mBuilder->uniform("dimension") = uDimension; @@ -170,6 +216,7 @@ sk_sp<SkShader> LutShader::generateLutShader(sk_sp<SkShader> input, sk_sp<SkShader> LutShader::lutShader(sk_sp<SkShader>& input, std::shared_ptr<gui::DisplayLuts> displayLuts, + ui::Dataspace srcDataspace, sk_sp<SkColorSpace> outColorSpace) { if (mBuilder == nullptr) { const static SkRuntimeEffect::Result instance = SkRuntimeEffect::MakeForShader(kShader); @@ -218,7 +265,7 @@ sk_sp<SkShader> LutShader::lutShader(sk_sp<SkShader>& input, } input = generateLutShader(input, buffers, offsets[i], bufferSizePerLut, lutProperties[i].dimension, lutProperties[i].size, - lutProperties[i].samplingKey); + lutProperties[i].samplingKey, srcDataspace); } auto colorXformLutToDst = diff --git a/libs/renderengine/skia/filters/LutShader.h b/libs/renderengine/skia/filters/LutShader.h index ce3e0592a1..7c62fcae08 100644 --- a/libs/renderengine/skia/filters/LutShader.h +++ b/libs/renderengine/skia/filters/LutShader.h @@ -21,6 +21,7 @@ #include <aidl/android/hardware/graphics/composer3/LutProperties.h> #include <gui/DisplayLuts.h> +#include <ui/GraphicTypes.h> namespace android { namespace renderengine { @@ -29,13 +30,13 @@ namespace skia { class LutShader { public: sk_sp<SkShader> lutShader(sk_sp<SkShader>& input, std::shared_ptr<gui::DisplayLuts> displayLuts, - sk_sp<SkColorSpace> outColorSpace); + ui::Dataspace srcDataspace, sk_sp<SkColorSpace> outColorSpace); private: sk_sp<SkShader> generateLutShader(sk_sp<SkShader> input, const std::vector<float>& buffers, const int32_t offset, const int32_t length, const int32_t dimension, const int32_t size, - const int32_t samplingKey); + const int32_t samplingKey, ui::Dataspace srcDataspace); std::unique_ptr<SkRuntimeShaderBuilder> mBuilder; }; diff --git a/libs/ui/include/ui/DynamicDisplayInfo.h b/libs/ui/include/ui/DynamicDisplayInfo.h index af494dcf39..9d97151155 100644 --- a/libs/ui/include/ui/DynamicDisplayInfo.h +++ b/libs/ui/include/ui/DynamicDisplayInfo.h @@ -59,6 +59,9 @@ struct DynamicDisplayInfo { // Represents frame rate for FrameRateCategory Normal and High. ui::FrameRateCategoryRate frameRateCategoryRate; + + // All the refresh rates supported for the default display mode. + std::vector<float> supportedRefreshRates; }; } // namespace android::ui diff --git a/services/automotive/display/Android.bp b/services/automotive/display/Android.bp index 72bd29254d..b63e919504 100644 --- a/services/automotive/display/Android.bp +++ b/services/automotive/display/Android.bp @@ -23,6 +23,11 @@ package { default_applicable_licenses: ["frameworks_native_license"], } +vintf_fragment { + name: "manifest_android.frameworks.automotive.display@1.0.xml", + src: "manifest_android.frameworks.automotive.display@1.0.xml", +} + cc_binary { name: "android.frameworks.automotive.display@1.0-service", defaults: ["hidl_defaults"], @@ -50,7 +55,7 @@ cc_binary { "-DLOG_TAG=\"AutomotiveDisplayService\"" ], - vintf_fragments: [ + vintf_fragment_modules: [ "manifest_android.frameworks.automotive.display@1.0.xml", ], } diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp index 4233f789d6..1f6600d3f6 100644 --- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp @@ -212,7 +212,7 @@ SensorInputMapper::Sensor SensorInputMapper::createSensor(InputDeviceSensorType // One input device can only have 1 sensor for each sensor Type. InputDeviceSensorInfo sensorInfo(identifier.name, std::to_string(identifier.vendor), identifier.version, sensorType, - InputDeviceSensorAccuracy::ACCURACY_HIGH, + InputDeviceSensorAccuracy::HIGH, /*maxRange=*/axis.max, /*resolution=*/axis.scale, /*power=*/config.getFloat(prefix + ".power").value_or(0.0f), /*minDelay=*/config.getInt(prefix + ".minDelay").value_or(0), diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.h b/services/inputflinger/reader/mapper/SensorInputMapper.h index 63bc151ac1..7974efe172 100644 --- a/services/inputflinger/reader/mapper/SensorInputMapper.h +++ b/services/inputflinger/reader/mapper/SensorInputMapper.h @@ -101,7 +101,7 @@ private: std::array<int32_t, SENSOR_VEC_LEN> dataVec; void resetValue() { this->enabled = false; - this->accuracy = InputDeviceSensorAccuracy::ACCURACY_NONE; + this->accuracy = InputDeviceSensorAccuracy::NONE; this->samplingPeriod = std::chrono::nanoseconds(0); this->maxBatchReportLatency = std::chrono::nanoseconds(0); this->lastSampleTimeNs = std::nullopt; diff --git a/services/inputflinger/tests/SensorInputMapper_test.cpp b/services/inputflinger/tests/SensorInputMapper_test.cpp index 2c1265378a..ac2e99e7b5 100644 --- a/services/inputflinger/tests/SensorInputMapper_test.cpp +++ b/services/inputflinger/tests/SensorInputMapper_test.cpp @@ -125,7 +125,7 @@ TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) { ASSERT_EQ(arg.source, AINPUT_SOURCE_SENSOR); ASSERT_EQ(arg.deviceId, DEVICE_ID); ASSERT_EQ(arg.sensorType, InputDeviceSensorType::ACCELEROMETER); - ASSERT_EQ(arg.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH); + ASSERT_EQ(arg.accuracy, InputDeviceSensorAccuracy::HIGH); ASSERT_EQ(arg.hwTimestamp, ARBITRARY_TIME); ASSERT_EQ(arg.values, values); mMapper->flushSensor(InputDeviceSensorType::ACCELEROMETER); @@ -170,7 +170,7 @@ TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) { ASSERT_EQ(arg.source, AINPUT_SOURCE_SENSOR); ASSERT_EQ(arg.deviceId, DEVICE_ID); ASSERT_EQ(arg.sensorType, InputDeviceSensorType::GYROSCOPE); - ASSERT_EQ(arg.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH); + ASSERT_EQ(arg.accuracy, InputDeviceSensorAccuracy::HIGH); ASSERT_EQ(arg.hwTimestamp, ARBITRARY_TIME); ASSERT_EQ(arg.values, values); mMapper->flushSensor(InputDeviceSensorType::GYROSCOPE); diff --git a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp index ae84d7b133..71d3d1f571 100644 --- a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp +++ b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp @@ -28,18 +28,10 @@ #include <unistd.h> #include <thread> -using aidl::android::hardware::power::Boost; -using aidl::android::hardware::power::ChannelConfig; -using aidl::android::hardware::power::CpuHeadroomParams; -using aidl::android::hardware::power::GpuHeadroomParams; -using aidl::android::hardware::power::IPower; -using aidl::android::hardware::power::IPowerHintSession; -using aidl::android::hardware::power::Mode; -using aidl::android::hardware::power::SessionConfig; -using aidl::android::hardware::power::SessionTag; -using aidl::android::hardware::power::SupportInfo; + using android::binder::Status; +using namespace aidl::android::hardware::power; using namespace android; using namespace android::power; using namespace std::chrono_literals; @@ -74,13 +66,17 @@ public: MOCK_METHOD(ndk::SpAIBinder, asBinder, (), (override)); MOCK_METHOD(bool, isRemote, (), (override)); MOCK_METHOD(ndk::ScopedAStatus, getCpuHeadroom, - (const CpuHeadroomParams& params, std::vector<float>* headroom), (override)); + (const CpuHeadroomParams& params, CpuHeadroomResult* headroom), (override)); MOCK_METHOD(ndk::ScopedAStatus, getGpuHeadroom, - (const GpuHeadroomParams& params, float* headroom), (override)); + (const GpuHeadroomParams& params, GpuHeadroomResult* headroom), (override)); MOCK_METHOD(ndk::ScopedAStatus, getCpuHeadroomMinIntervalMillis, (int64_t* interval), (override)); MOCK_METHOD(ndk::ScopedAStatus, getGpuHeadroomMinIntervalMillis, (int64_t* interval), (override)); + MOCK_METHOD(ndk::ScopedAStatus, sendCompositionData, + (const std::vector<CompositionData>& in_data), (override)); + MOCK_METHOD(ndk::ScopedAStatus, sendCompositionUpdate, + (const CompositionUpdate& in_update), (override)); }; // ------------------------------------------------------------------------------------------------- diff --git a/services/surfaceflinger/PowerAdvisor/Android.bp b/services/surfaceflinger/PowerAdvisor/Android.bp new file mode 100644 index 0000000000..7352f7a80e --- /dev/null +++ b/services/surfaceflinger/PowerAdvisor/Android.bp @@ -0,0 +1,54 @@ +/* + * Copyright 2024 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. + */ + +// ADPF uses FMQ which can't build to CPP backend, and is thus not +// compatible with the rest of SF aidl for this reason + +aidl_interface { + name: "android.adpf.sessionmanager_aidl", + defaults: [ + "android.hardware.power-aidl", + ], + srcs: [ + "aidl/android/adpf/*.aidl", + ], + local_include_dir: "aidl", + unstable: true, + backend: { + java: { + sdk_version: "module_current", + enabled: true, + }, + cpp: { + enabled: false, + }, + ndk: { + enabled: true, + }, + }, + imports: [ + "android.hardware.common.fmq-V1", + "android.hardware.common-V2", + ], +} + +cc_defaults { + name: "poweradvisor_deps", + shared_libs: [ + "libpowermanager", + "android.adpf.sessionmanager_aidl-ndk", + ], +} diff --git a/services/surfaceflinger/PowerAdvisor/aidl/android/adpf/ISessionManager.aidl b/services/surfaceflinger/PowerAdvisor/aidl/android/adpf/ISessionManager.aidl new file mode 100644 index 0000000000..c1a6a9e63c --- /dev/null +++ b/services/surfaceflinger/PowerAdvisor/aidl/android/adpf/ISessionManager.aidl @@ -0,0 +1,26 @@ +/* + * Copyright 2024 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. + */ + +package android.adpf; + +/** + * Private service for SessionManager to use. Ideally this will + * eventually take the role of HintManagerService. + */ +interface ISessionManager { + oneway void associateSessionToLayers(in int sessionId, in int ownerUid, in IBinder[] layers); + oneway void trackedSessionsDied(in int[] sessionId); +} diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index e4069dd691..668fa549bb 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -1557,6 +1557,19 @@ Fps RefreshRateSelector::findClosestKnownFrameRate(Fps frameRate) const { return distance1 < distance2 ? *lowerBound : *std::prev(lowerBound); } +std::vector<float> RefreshRateSelector::getSupportedFrameRates() const { + std::scoped_lock lock(mLock); + // TODO(b/356986687) Remove the limit once we have the anchor list implementation. + const size_t frameRatesSize = std::min<size_t>(11, mPrimaryFrameRates.size()); + std::vector<float> supportedFrameRates; + supportedFrameRates.reserve(frameRatesSize); + std::transform(mPrimaryFrameRates.rbegin(), + mPrimaryFrameRates.rbegin() + static_cast<int>(frameRatesSize), + std::back_inserter(supportedFrameRates), + [](FrameRateMode mode) { return mode.fps.getValue(); }); + return supportedFrameRates; +} + auto RefreshRateSelector::getIdleTimerAction() const -> KernelIdleTimerAction { std::lock_guard lock(mLock); diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h index ee3a4f7bdc..508f9d72ea 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h @@ -441,6 +441,8 @@ public: std::pair<Fps, Fps> getFrameRateCategoryRates() const { return kFrameRateCategoryRates; } + std::vector<float> getSupportedFrameRates() const EXCLUDES(mLock); + private: friend struct TestableRefreshRateSelector; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7ce050b18d..2c4fcf546b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -797,6 +797,12 @@ void SurfaceFlinger::bootFinished() { })); } +bool shouldUseGraphiteIfCompiledAndSupported() { + return FlagManager::getInstance().graphite_renderengine() || + (FlagManager::getInstance().graphite_renderengine_preview_rollout() && + base::GetBoolProperty(PROPERTY_DEBUG_RENDERENGINE_GRAPHITE_PREVIEW_OPTIN, false)); +} + void chooseRenderEngineType(renderengine::RenderEngineCreationArgs::Builder& builder) { char prop[PROPERTY_VALUE_MAX]; property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, ""); @@ -825,14 +831,13 @@ void chooseRenderEngineType(renderengine::RenderEngineCreationArgs::Builder& bui // is used by layertracegenerator (which also needs SurfaceFlinger.cpp). :) #if COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS_GRAPHITE_RENDERENGINE || \ COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS_FORCE_COMPILE_GRAPHITE_RENDERENGINE - const bool useGraphite = FlagManager::getInstance().graphite_renderengine() && + const bool useGraphite = shouldUseGraphiteIfCompiledAndSupported() && renderengine::RenderEngine::canSupport(kVulkan); #else const bool useGraphite = false; - if (FlagManager::getInstance().graphite_renderengine()) { - ALOGE("RenderEngine's Graphite Skia backend was requested with the " - "debug.renderengine.graphite system property, but it is not compiled in this " - "build! Falling back to Ganesh backend selection logic."); + if (shouldUseGraphiteIfCompiledAndSupported()) { + ALOGE("RenderEngine's Graphite Skia backend was requested, but it is not compiled in " + "this build! Falling back to Ganesh backend selection logic."); } #endif const bool useVulkan = useGraphite || @@ -1231,6 +1236,8 @@ void SurfaceFlinger::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo*& info const auto [normal, high] = display->refreshRateSelector().getFrameRateCategoryRates(); ui::FrameRateCategoryRate frameRateCategoryRate(normal.getValue(), high.getValue()); info->frameRateCategoryRate = frameRateCategoryRate; + + info->supportedRefreshRates = display->refreshRateSelector().getSupportedFrameRates(); info->activeColorMode = display->getCompositionDisplay()->getState().colorMode; info->hdrCapabilities = filterOut4k30(display->getHdrCapabilities()); @@ -8643,6 +8650,11 @@ void SurfaceComposerAIDL::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo& gui::FrameRateCategoryRate& frameRateCategoryRate = outInfo->frameRateCategoryRate; frameRateCategoryRate.normal = info.frameRateCategoryRate.getNormal(); frameRateCategoryRate.high = info.frameRateCategoryRate.getHigh(); + outInfo->supportedRefreshRates.clear(); + outInfo->supportedRefreshRates.reserve(info.supportedRefreshRates.size()); + for (float supportedRefreshRate : info.supportedRefreshRates) { + outInfo->supportedRefreshRates.push_back(supportedRefreshRate); + } outInfo->supportedColorModes.clear(); outInfo->supportedColorModes.reserve(info.supportedColorModes.size()); diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp index 659a919909..f257c7cf10 100644 --- a/services/surfaceflinger/common/FlagManager.cpp +++ b/services/surfaceflinger/common/FlagManager.cpp @@ -89,9 +89,9 @@ void FlagManager::setUnitTestMode() { mBootCompleted = true; } -void FlagManager::dumpFlag(std::string& result, bool readonly, const char* name, +void FlagManager::dumpFlag(std::string& result, bool aconfig, const char* name, std::function<bool()> getter) const { - if (readonly || mBootCompleted) { + if (aconfig || mBootCompleted) { base::StringAppendF(&result, "%s: %s\n", name, getter() ? "true" : "false"); } else { base::StringAppendF(&result, "%s: in progress (still booting)\n", name); @@ -99,72 +99,73 @@ void FlagManager::dumpFlag(std::string& result, bool readonly, const char* name, } void FlagManager::dump(std::string& result) const { -#define DUMP_FLAG_INTERVAL(name, readonly) \ - dumpFlag(result, (readonly), #name, std::bind(&FlagManager::name, this)) -#define DUMP_SERVER_FLAG(name) DUMP_FLAG_INTERVAL(name, false) -#define DUMP_READ_ONLY_FLAG(name) DUMP_FLAG_INTERVAL(name, true) +#define DUMP_FLAG_INTERNAL(name, aconfig) \ + dumpFlag(result, (aconfig), #name, std::bind(&FlagManager::name, this)) +#define DUMP_LEGACY_SERVER_FLAG(name) DUMP_FLAG_INTERNAL(name, false) +#define DUMP_ACONFIG_FLAG(name) DUMP_FLAG_INTERNAL(name, true) base::StringAppendF(&result, "FlagManager values: \n"); /// Legacy server flags /// - DUMP_SERVER_FLAG(use_adpf_cpu_hint); - DUMP_SERVER_FLAG(use_skia_tracing); + DUMP_LEGACY_SERVER_FLAG(use_adpf_cpu_hint); + DUMP_LEGACY_SERVER_FLAG(use_skia_tracing); - /// Trunk stable server flags /// - DUMP_SERVER_FLAG(refresh_rate_overlay_on_external_display); - DUMP_SERVER_FLAG(adpf_gpu_sf); - DUMP_SERVER_FLAG(adpf_native_session_manager); - DUMP_SERVER_FLAG(adpf_use_fmq_channel); + /// Trunk stable server (R/W) flags /// + DUMP_ACONFIG_FLAG(refresh_rate_overlay_on_external_display); + DUMP_ACONFIG_FLAG(adpf_gpu_sf); + DUMP_ACONFIG_FLAG(adpf_native_session_manager); + DUMP_ACONFIG_FLAG(adpf_use_fmq_channel); + DUMP_ACONFIG_FLAG(graphite_renderengine_preview_rollout); /// Trunk stable readonly flags /// - DUMP_READ_ONLY_FLAG(adpf_fmq_sf); - DUMP_READ_ONLY_FLAG(connected_display); - DUMP_READ_ONLY_FLAG(enable_small_area_detection); - DUMP_READ_ONLY_FLAG(stable_edid_ids); - DUMP_READ_ONLY_FLAG(frame_rate_category_mrr); - DUMP_READ_ONLY_FLAG(misc1); - DUMP_READ_ONLY_FLAG(vrr_config); - DUMP_READ_ONLY_FLAG(hdcp_level_hal); - DUMP_READ_ONLY_FLAG(multithreaded_present); - DUMP_READ_ONLY_FLAG(add_sf_skipped_frames_to_trace); - DUMP_READ_ONLY_FLAG(use_known_refresh_rate_for_fps_consistency); - DUMP_READ_ONLY_FLAG(cache_when_source_crop_layer_only_moved); - DUMP_READ_ONLY_FLAG(enable_fro_dependent_features); - DUMP_READ_ONLY_FLAG(display_protected); - DUMP_READ_ONLY_FLAG(fp16_client_target); - DUMP_READ_ONLY_FLAG(game_default_frame_rate); - DUMP_READ_ONLY_FLAG(enable_layer_command_batching); - DUMP_READ_ONLY_FLAG(vulkan_renderengine); - DUMP_READ_ONLY_FLAG(renderable_buffer_usage); - DUMP_READ_ONLY_FLAG(vrr_bugfix_24q4); - DUMP_READ_ONLY_FLAG(vrr_bugfix_dropped_frame); - DUMP_READ_ONLY_FLAG(restore_blur_step); - DUMP_READ_ONLY_FLAG(dont_skip_on_early_ro); - DUMP_READ_ONLY_FLAG(no_vsyncs_on_screen_off); - DUMP_READ_ONLY_FLAG(protected_if_client); - DUMP_READ_ONLY_FLAG(idle_screen_refresh_rate_timeout); - DUMP_READ_ONLY_FLAG(graphite_renderengine); - DUMP_READ_ONLY_FLAG(filter_frames_before_trace_starts); - DUMP_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed); - DUMP_READ_ONLY_FLAG(deprecate_vsync_sf); - DUMP_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter); - DUMP_READ_ONLY_FLAG(detached_mirror); - DUMP_READ_ONLY_FLAG(commit_not_composited); - DUMP_READ_ONLY_FLAG(correct_dpi_with_display_size); - DUMP_READ_ONLY_FLAG(local_tonemap_screenshots); - DUMP_READ_ONLY_FLAG(override_trusted_overlay); - DUMP_READ_ONLY_FLAG(flush_buffer_slots_to_uncache); - DUMP_READ_ONLY_FLAG(force_compile_graphite_renderengine); - DUMP_READ_ONLY_FLAG(trace_frame_rate_override); - DUMP_READ_ONLY_FLAG(true_hdr_screenshots); - DUMP_READ_ONLY_FLAG(display_config_error_hal); - DUMP_READ_ONLY_FLAG(connected_display_hdr); - DUMP_READ_ONLY_FLAG(deprecate_frame_tracker); - DUMP_READ_ONLY_FLAG(skip_invisible_windows_in_input); - DUMP_READ_ONLY_FLAG(begone_bright_hlg); - -#undef DUMP_READ_ONLY_FLAG -#undef DUMP_SERVER_FLAG + DUMP_ACONFIG_FLAG(adpf_fmq_sf); + DUMP_ACONFIG_FLAG(connected_display); + DUMP_ACONFIG_FLAG(enable_small_area_detection); + DUMP_ACONFIG_FLAG(stable_edid_ids); + DUMP_ACONFIG_FLAG(frame_rate_category_mrr); + DUMP_ACONFIG_FLAG(misc1); + DUMP_ACONFIG_FLAG(vrr_config); + DUMP_ACONFIG_FLAG(hdcp_level_hal); + DUMP_ACONFIG_FLAG(multithreaded_present); + DUMP_ACONFIG_FLAG(add_sf_skipped_frames_to_trace); + DUMP_ACONFIG_FLAG(use_known_refresh_rate_for_fps_consistency); + DUMP_ACONFIG_FLAG(cache_when_source_crop_layer_only_moved); + DUMP_ACONFIG_FLAG(enable_fro_dependent_features); + DUMP_ACONFIG_FLAG(display_protected); + DUMP_ACONFIG_FLAG(fp16_client_target); + DUMP_ACONFIG_FLAG(game_default_frame_rate); + DUMP_ACONFIG_FLAG(enable_layer_command_batching); + DUMP_ACONFIG_FLAG(vulkan_renderengine); + DUMP_ACONFIG_FLAG(renderable_buffer_usage); + DUMP_ACONFIG_FLAG(vrr_bugfix_24q4); + DUMP_ACONFIG_FLAG(vrr_bugfix_dropped_frame); + DUMP_ACONFIG_FLAG(restore_blur_step); + DUMP_ACONFIG_FLAG(dont_skip_on_early_ro); + DUMP_ACONFIG_FLAG(no_vsyncs_on_screen_off); + DUMP_ACONFIG_FLAG(protected_if_client); + DUMP_ACONFIG_FLAG(idle_screen_refresh_rate_timeout); + DUMP_ACONFIG_FLAG(graphite_renderengine); + DUMP_ACONFIG_FLAG(filter_frames_before_trace_starts); + DUMP_ACONFIG_FLAG(latch_unsignaled_with_auto_refresh_changed); + DUMP_ACONFIG_FLAG(deprecate_vsync_sf); + DUMP_ACONFIG_FLAG(allow_n_vsyncs_in_targeter); + DUMP_ACONFIG_FLAG(detached_mirror); + DUMP_ACONFIG_FLAG(commit_not_composited); + DUMP_ACONFIG_FLAG(correct_dpi_with_display_size); + DUMP_ACONFIG_FLAG(local_tonemap_screenshots); + DUMP_ACONFIG_FLAG(override_trusted_overlay); + DUMP_ACONFIG_FLAG(flush_buffer_slots_to_uncache); + DUMP_ACONFIG_FLAG(force_compile_graphite_renderengine); + DUMP_ACONFIG_FLAG(trace_frame_rate_override); + DUMP_ACONFIG_FLAG(true_hdr_screenshots); + DUMP_ACONFIG_FLAG(display_config_error_hal); + DUMP_ACONFIG_FLAG(connected_display_hdr); + DUMP_ACONFIG_FLAG(deprecate_frame_tracker); + DUMP_ACONFIG_FLAG(skip_invisible_windows_in_input); + DUMP_ACONFIG_FLAG(begone_bright_hlg); + +#undef DUMP_ACONFIG_FLAG +#undef DUMP_LEGACY_SERVER_FLAG #undef DUMP_FLAG_INTERVAL } @@ -189,35 +190,24 @@ bool FlagManager::getServerConfigurableFlag(const char* experimentFlagName) cons return getServerConfigurableFlag(serverFlagName); \ } -#define FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, checkForBootCompleted, owner) \ - bool FlagManager::name() const { \ - if (checkForBootCompleted) { \ - LOG_ALWAYS_FATAL_IF(!mBootCompleted, \ - "Can't read %s before boot completed as it is server writable", \ - __func__); \ - } \ - static const std::optional<bool> debugOverride = getBoolProperty(syspropOverride); \ - static const bool value = getFlagValue([] { return owner ::name(); }, debugOverride); \ - if (mUnitTestMode) { \ - /* \ - * When testing, we don't want to rely on the cached `value` or the debugOverride. \ - */ \ - return owner ::name(); \ - } \ - return value; \ +#define FLAG_MANAGER_ACONFIG_INTERNAL(name, syspropOverride, owner) \ + bool FlagManager::name() const { \ + static const std::optional<bool> debugOverride = getBoolProperty(syspropOverride); \ + static const bool value = getFlagValue([] { return owner ::name(); }, debugOverride); \ + if (mUnitTestMode) { \ + /* \ + * When testing, we don't want to rely on the cached `value` or the debugOverride. \ + */ \ + return owner ::name(); \ + } \ + return value; \ } -#define FLAG_MANAGER_SERVER_FLAG(name, syspropOverride) \ - FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true, flags) +#define FLAG_MANAGER_ACONFIG_FLAG(name, syspropOverride) \ + FLAG_MANAGER_ACONFIG_INTERNAL(name, syspropOverride, flags) -#define FLAG_MANAGER_READ_ONLY_FLAG(name, syspropOverride) \ - FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, false, flags) - -#define FLAG_MANAGER_SERVER_FLAG_IMPORTED(name, syspropOverride, owner) \ - FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true, owner) - -#define FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(name, syspropOverride, owner) \ - FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, false, owner) +#define FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(name, syspropOverride, owner) \ + FLAG_MANAGER_ACONFIG_INTERNAL(name, syspropOverride, owner) /// Legacy server flags /// FLAG_MANAGER_LEGACY_SERVER_FLAG(test_flag, "", "") @@ -227,64 +217,65 @@ FLAG_MANAGER_LEGACY_SERVER_FLAG(use_skia_tracing, PROPERTY_SKIA_ATRACE_ENABLED, "SkiaTracingFeature__use_skia_tracing") /// Trunk stable readonly flags /// -FLAG_MANAGER_READ_ONLY_FLAG(adpf_fmq_sf, "") -FLAG_MANAGER_READ_ONLY_FLAG(connected_display, "") -FLAG_MANAGER_READ_ONLY_FLAG(enable_small_area_detection, "") -FLAG_MANAGER_READ_ONLY_FLAG(stable_edid_ids, "debug.sf.stable_edid_ids") -FLAG_MANAGER_READ_ONLY_FLAG(frame_rate_category_mrr, "debug.sf.frame_rate_category_mrr") -FLAG_MANAGER_READ_ONLY_FLAG(misc1, "") -FLAG_MANAGER_READ_ONLY_FLAG(vrr_config, "debug.sf.enable_vrr_config") -FLAG_MANAGER_READ_ONLY_FLAG(hdcp_level_hal, "") -FLAG_MANAGER_READ_ONLY_FLAG(multithreaded_present, "debug.sf.multithreaded_present") -FLAG_MANAGER_READ_ONLY_FLAG(add_sf_skipped_frames_to_trace, "") -FLAG_MANAGER_READ_ONLY_FLAG(use_known_refresh_rate_for_fps_consistency, "") -FLAG_MANAGER_READ_ONLY_FLAG(cache_when_source_crop_layer_only_moved, - "debug.sf.cache_source_crop_only_moved") -FLAG_MANAGER_READ_ONLY_FLAG(enable_fro_dependent_features, "") -FLAG_MANAGER_READ_ONLY_FLAG(display_protected, "") -FLAG_MANAGER_READ_ONLY_FLAG(fp16_client_target, "debug.sf.fp16_client_target") -FLAG_MANAGER_READ_ONLY_FLAG(game_default_frame_rate, "") -FLAG_MANAGER_READ_ONLY_FLAG(enable_layer_command_batching, "debug.sf.enable_layer_command_batching") -FLAG_MANAGER_READ_ONLY_FLAG(vulkan_renderengine, "debug.renderengine.vulkan") -FLAG_MANAGER_READ_ONLY_FLAG(renderable_buffer_usage, "") -FLAG_MANAGER_READ_ONLY_FLAG(restore_blur_step, "debug.renderengine.restore_blur_step") -FLAG_MANAGER_READ_ONLY_FLAG(dont_skip_on_early_ro, "") -FLAG_MANAGER_READ_ONLY_FLAG(no_vsyncs_on_screen_off, "debug.sf.no_vsyncs_on_screen_off") -FLAG_MANAGER_READ_ONLY_FLAG(protected_if_client, "") -FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_24q4, ""); -FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_dropped_frame, "") -FLAG_MANAGER_READ_ONLY_FLAG(graphite_renderengine, "debug.renderengine.graphite") -FLAG_MANAGER_READ_ONLY_FLAG(filter_frames_before_trace_starts, "") -FLAG_MANAGER_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed, ""); -FLAG_MANAGER_READ_ONLY_FLAG(deprecate_vsync_sf, ""); -FLAG_MANAGER_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter, ""); -FLAG_MANAGER_READ_ONLY_FLAG(detached_mirror, ""); -FLAG_MANAGER_READ_ONLY_FLAG(commit_not_composited, ""); -FLAG_MANAGER_READ_ONLY_FLAG(correct_dpi_with_display_size, ""); -FLAG_MANAGER_READ_ONLY_FLAG(local_tonemap_screenshots, "debug.sf.local_tonemap_screenshots"); -FLAG_MANAGER_READ_ONLY_FLAG(override_trusted_overlay, ""); -FLAG_MANAGER_READ_ONLY_FLAG(flush_buffer_slots_to_uncache, ""); -FLAG_MANAGER_READ_ONLY_FLAG(force_compile_graphite_renderengine, ""); -FLAG_MANAGER_READ_ONLY_FLAG(true_hdr_screenshots, "debug.sf.true_hdr_screenshots"); -FLAG_MANAGER_READ_ONLY_FLAG(display_config_error_hal, ""); -FLAG_MANAGER_READ_ONLY_FLAG(connected_display_hdr, ""); -FLAG_MANAGER_READ_ONLY_FLAG(deprecate_frame_tracker, ""); -FLAG_MANAGER_READ_ONLY_FLAG(skip_invisible_windows_in_input, ""); -FLAG_MANAGER_READ_ONLY_FLAG(begone_bright_hlg, "debug.sf.begone_bright_hlg"); - -/// Trunk stable server flags /// -FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "") -FLAG_MANAGER_SERVER_FLAG(adpf_gpu_sf, "") -FLAG_MANAGER_SERVER_FLAG(adpf_native_session_manager, ""); - -/// Trunk stable server flags from outside SurfaceFlinger /// -FLAG_MANAGER_SERVER_FLAG_IMPORTED(adpf_use_fmq_channel, "", android::os) +FLAG_MANAGER_ACONFIG_FLAG(adpf_fmq_sf, "") +FLAG_MANAGER_ACONFIG_FLAG(connected_display, "") +FLAG_MANAGER_ACONFIG_FLAG(enable_small_area_detection, "") +FLAG_MANAGER_ACONFIG_FLAG(stable_edid_ids, "debug.sf.stable_edid_ids") +FLAG_MANAGER_ACONFIG_FLAG(frame_rate_category_mrr, "debug.sf.frame_rate_category_mrr") +FLAG_MANAGER_ACONFIG_FLAG(misc1, "") +FLAG_MANAGER_ACONFIG_FLAG(vrr_config, "debug.sf.enable_vrr_config") +FLAG_MANAGER_ACONFIG_FLAG(hdcp_level_hal, "") +FLAG_MANAGER_ACONFIG_FLAG(multithreaded_present, "debug.sf.multithreaded_present") +FLAG_MANAGER_ACONFIG_FLAG(add_sf_skipped_frames_to_trace, "") +FLAG_MANAGER_ACONFIG_FLAG(use_known_refresh_rate_for_fps_consistency, "") +FLAG_MANAGER_ACONFIG_FLAG(cache_when_source_crop_layer_only_moved, + "debug.sf.cache_source_crop_only_moved") +FLAG_MANAGER_ACONFIG_FLAG(enable_fro_dependent_features, "") +FLAG_MANAGER_ACONFIG_FLAG(display_protected, "") +FLAG_MANAGER_ACONFIG_FLAG(fp16_client_target, "debug.sf.fp16_client_target") +FLAG_MANAGER_ACONFIG_FLAG(game_default_frame_rate, "") +FLAG_MANAGER_ACONFIG_FLAG(enable_layer_command_batching, "debug.sf.enable_layer_command_batching") +FLAG_MANAGER_ACONFIG_FLAG(vulkan_renderengine, "debug.renderengine.vulkan") +FLAG_MANAGER_ACONFIG_FLAG(renderable_buffer_usage, "") +FLAG_MANAGER_ACONFIG_FLAG(restore_blur_step, "debug.renderengine.restore_blur_step") +FLAG_MANAGER_ACONFIG_FLAG(dont_skip_on_early_ro, "") +FLAG_MANAGER_ACONFIG_FLAG(no_vsyncs_on_screen_off, "debug.sf.no_vsyncs_on_screen_off") +FLAG_MANAGER_ACONFIG_FLAG(protected_if_client, "") +FLAG_MANAGER_ACONFIG_FLAG(vrr_bugfix_24q4, ""); +FLAG_MANAGER_ACONFIG_FLAG(vrr_bugfix_dropped_frame, "") +FLAG_MANAGER_ACONFIG_FLAG(graphite_renderengine, "debug.renderengine.graphite") +FLAG_MANAGER_ACONFIG_FLAG(filter_frames_before_trace_starts, "") +FLAG_MANAGER_ACONFIG_FLAG(latch_unsignaled_with_auto_refresh_changed, ""); +FLAG_MANAGER_ACONFIG_FLAG(deprecate_vsync_sf, ""); +FLAG_MANAGER_ACONFIG_FLAG(allow_n_vsyncs_in_targeter, ""); +FLAG_MANAGER_ACONFIG_FLAG(detached_mirror, ""); +FLAG_MANAGER_ACONFIG_FLAG(commit_not_composited, ""); +FLAG_MANAGER_ACONFIG_FLAG(correct_dpi_with_display_size, ""); +FLAG_MANAGER_ACONFIG_FLAG(local_tonemap_screenshots, "debug.sf.local_tonemap_screenshots"); +FLAG_MANAGER_ACONFIG_FLAG(override_trusted_overlay, ""); +FLAG_MANAGER_ACONFIG_FLAG(flush_buffer_slots_to_uncache, ""); +FLAG_MANAGER_ACONFIG_FLAG(force_compile_graphite_renderengine, ""); +FLAG_MANAGER_ACONFIG_FLAG(true_hdr_screenshots, "debug.sf.true_hdr_screenshots"); +FLAG_MANAGER_ACONFIG_FLAG(display_config_error_hal, ""); +FLAG_MANAGER_ACONFIG_FLAG(connected_display_hdr, ""); +FLAG_MANAGER_ACONFIG_FLAG(deprecate_frame_tracker, ""); +FLAG_MANAGER_ACONFIG_FLAG(skip_invisible_windows_in_input, ""); +FLAG_MANAGER_ACONFIG_FLAG(begone_bright_hlg, "debug.sf.begone_bright_hlg"); + +/// Trunk stable server (R/W) flags /// +FLAG_MANAGER_ACONFIG_FLAG(refresh_rate_overlay_on_external_display, "") +FLAG_MANAGER_ACONFIG_FLAG(adpf_gpu_sf, "") +FLAG_MANAGER_ACONFIG_FLAG(adpf_native_session_manager, ""); +FLAG_MANAGER_ACONFIG_FLAG(graphite_renderengine_preview_rollout, ""); + +/// Trunk stable server (R/W) flags from outside SurfaceFlinger /// +FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(adpf_use_fmq_channel, "", android::os) /// Trunk stable readonly flags from outside SurfaceFlinger /// -FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(idle_screen_refresh_rate_timeout, "", - com::android::server::display::feature::flags) -FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(adpf_use_fmq_channel_fixed, "", android::os) -FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(trace_frame_rate_override, "", - com::android::graphics::libgui::flags); +FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(idle_screen_refresh_rate_timeout, "", + com::android::server::display::feature::flags) +FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(adpf_use_fmq_channel_fixed, "", android::os) +FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(trace_frame_rate_override, "", + com::android::graphics::libgui::flags); } // namespace android diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h index d46947f555..a461627eef 100644 --- a/services/surfaceflinger/common/include/common/FlagManager.h +++ b/services/surfaceflinger/common/include/common/FlagManager.h @@ -47,12 +47,13 @@ public: bool use_adpf_cpu_hint() const; bool use_skia_tracing() const; - /// Trunk stable server flags /// + /// Trunk stable server (R/W) flags /// bool refresh_rate_overlay_on_external_display() const; bool adpf_gpu_sf() const; bool adpf_use_fmq_channel() const; bool adpf_native_session_manager() const; bool adpf_use_fmq_channel_fixed() const; + bool graphite_renderengine_preview_rollout() const; /// Trunk stable readonly flags /// bool adpf_fmq_sf() const; diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig index 34a935a223..2c44e4ce0d 100644 --- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig +++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig @@ -173,6 +173,13 @@ flag { } # frame_rate_category_mrr flag { + name: "graphite_renderengine_preview_rollout" + namespace: "core_graphics" + description: "R/W flag to enable Skia's Graphite Vulkan backend in RenderEngine, IF it is already compiled with force_compile_graphite_renderengine, AND the debug.renderengine.graphite_preview_optin sysprop is set to true." + bug: "293371537" +} # graphite_renderengine_preview_rollout + +flag { name: "latch_unsignaled_with_auto_refresh_changed" namespace: "core_graphics" description: "Ignore eAutoRefreshChanged with latch unsignaled" diff --git a/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp b/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp index 51b5f40a52..a5b347a43c 100644 --- a/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp +++ b/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp @@ -85,12 +85,6 @@ TEST_F(FlagManagerTest, legacyReturnsValue) { EXPECT_EQ(false, mFlagManager.test_flag()); } -TEST_F(FlagManagerTest, crashesIfQueriedBeforeBoot) { - mFlagManager.markBootIncomplete(); - EXPECT_DEATH(FlagManager::getInstance() - .refresh_rate_overlay_on_external_display(), ""); -} - TEST_F(FlagManagerTest, returnsOverrideTrue) { mFlagManager.markBootCompleted(); |