summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/android/display_luts.h165
-rw-r--r--include/android/looper.h26
-rw-r--r--include/android/performance_hint.h2
-rw-r--r--include/android/surface_control.h18
-rw-r--r--include/ftl/flags.h10
-rw-r--r--include/input/InputDevice.h10
-rw-r--r--include/private/display_luts_private.h65
-rw-r--r--libs/binder/Parcel.cpp4
-rw-r--r--libs/binder/TEST_MAPPING10
-rw-r--r--libs/binder/include/binder/Parcel.h6
-rw-r--r--libs/binder/rust/src/lib.rs2
-rw-r--r--libs/binder/rust/src/system_only.rs178
-rw-r--r--libs/binder/rust/tests/integration.rs60
-rw-r--r--libs/binder/tests/binderParcelUnitTest.cpp32
-rw-r--r--libs/ftl/flags_test.cpp14
-rw-r--r--libs/gui/Android.bp1
-rw-r--r--libs/gui/Flags.cpp73
-rw-r--r--libs/gui/SurfaceComposerClient.cpp5
-rw-r--r--libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl3
-rw-r--r--libs/gui/aidl/android/gui/LutProperties.aidl2
-rw-r--r--libs/gui/include/gui/Flags.h26
-rw-r--r--libs/gui/include/gui/view/Surface.h16
-rw-r--r--libs/gui/view/Surface.cpp4
-rw-r--r--libs/renderengine/include/renderengine/RenderEngine.h8
-rw-r--r--libs/renderengine/skia/SkiaRenderEngine.cpp1
-rw-r--r--libs/renderengine/skia/filters/LutShader.cpp59
-rw-r--r--libs/renderengine/skia/filters/LutShader.h5
-rw-r--r--libs/ui/include/ui/DynamicDisplayInfo.h3
-rw-r--r--services/automotive/display/Android.bp7
-rw-r--r--services/inputflinger/reader/mapper/SensorInputMapper.cpp2
-rw-r--r--services/inputflinger/reader/mapper/SensorInputMapper.h2
-rw-r--r--services/inputflinger/tests/SensorInputMapper_test.cpp4
-rw-r--r--services/powermanager/tests/PowerHalWrapperAidlTest.cpp20
-rw-r--r--services/surfaceflinger/PowerAdvisor/Android.bp54
-rw-r--r--services/surfaceflinger/PowerAdvisor/aidl/android/adpf/ISessionManager.aidl26
-rw-r--r--services/surfaceflinger/Scheduler/RefreshRateSelector.cpp13
-rw-r--r--services/surfaceflinger/Scheduler/RefreshRateSelector.h2
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp22
-rw-r--r--services/surfaceflinger/common/FlagManager.cpp279
-rw-r--r--services/surfaceflinger/common/include/common/FlagManager.h3
-rw-r--r--services/surfaceflinger/surfaceflinger_flags_new.aconfig7
-rw-r--r--services/surfaceflinger/tests/unittests/FlagManagerTest.cpp6
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();