Merge "Add a config to allow touches while the display is off."
diff --git a/aidl/gui/android/view/Surface.aidl b/aidl/gui/android/view/Surface.aidl
index 7e89220..bb3faaf 100644
--- a/aidl/gui/android/view/Surface.aidl
+++ b/aidl/gui/android/view/Surface.aidl
@@ -17,4 +17,4 @@
package android.view;
-parcelable Surface cpp_header "gui/view/Surface.h";
+@JavaOnlyStableParcelable @NdkOnlyStableParcelable parcelable Surface cpp_header "gui/view/Surface.h" ndk_header "android/native_window_aidl.h";
diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp
index 3d81c32..6d1dfe8 100644
--- a/libs/gralloc/types/Android.bp
+++ b/libs/gralloc/types/Android.bp
@@ -58,7 +58,7 @@
],
export_shared_lib_headers: [
- "android.hardware.graphics.common-V3-ndk",
+ "android.hardware.graphics.common-V4-ndk",
"android.hardware.graphics.mapper@4.0",
"libhidlbase",
],
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 0021bd6..97e45c6 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -360,11 +360,12 @@
}
}
for (const auto& staleRelease : staleReleases) {
- BQA_LOGE("Faking releaseBufferCallback from transactionCompleteCallback");
- BBQ_TRACE("FakeReleaseCallback");
releaseBufferCallbackLocked(staleRelease,
- stat.previousReleaseFence ? stat.previousReleaseFence : Fence::NO_FENCE,
- stat.currentMaxAcquiredBufferCount);
+ stat.previousReleaseFence
+ ? stat.previousReleaseFence
+ : Fence::NO_FENCE,
+ stat.currentMaxAcquiredBufferCount,
+ true /* fakeRelease */);
}
} else {
BQA_LOGE("Failed to find matching SurfaceControl in transactionCallback");
@@ -408,11 +409,13 @@
BBQ_TRACE();
std::unique_lock _lock{mMutex};
- releaseBufferCallbackLocked(id, releaseFence, currentMaxAcquiredBufferCount);
+ releaseBufferCallbackLocked(id, releaseFence, currentMaxAcquiredBufferCount,
+ false /* fakeRelease */);
}
-void BLASTBufferQueue::releaseBufferCallbackLocked(const ReleaseCallbackId& id,
- const sp<Fence>& releaseFence, std::optional<uint32_t> currentMaxAcquiredBufferCount) {
+void BLASTBufferQueue::releaseBufferCallbackLocked(
+ const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
+ std::optional<uint32_t> currentMaxAcquiredBufferCount, bool fakeRelease) {
ATRACE_CALL();
BQA_LOGV("releaseBufferCallback %s", id.to_string().c_str());
@@ -435,6 +438,11 @@
auto rb = ReleasedBuffer{id, releaseFence};
if (std::find(mPendingRelease.begin(), mPendingRelease.end(), rb) == mPendingRelease.end()) {
mPendingRelease.emplace_back(rb);
+ if (fakeRelease) {
+ BQA_LOGE("Faking releaseBufferCallback from transactionCompleteCallback %" PRIu64,
+ id.framenumber);
+ BBQ_TRACE("FakeReleaseCallback");
+ }
}
// Release all buffers that are beyond the ones that we need to hold
diff --git a/libs/gui/fuzzer/Android.bp b/libs/gui/fuzzer/Android.bp
index cdc9376..1c61d6b 100644
--- a/libs/gui/fuzzer/Android.bp
+++ b/libs/gui/fuzzer/Android.bp
@@ -46,7 +46,7 @@
"android.hardware.configstore-utils",
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.bufferqueue@2.0",
- "android.hardware.power-V2-cpp",
+ "android.hardware.power-V4-cpp",
"android.hidl.token@1.0",
"libSurfaceFlingerProp",
"libgui",
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 957652e..47dcc42 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -93,7 +93,8 @@
void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
std::optional<uint32_t> currentMaxAcquiredBufferCount);
void releaseBufferCallbackLocked(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
- std::optional<uint32_t> currentMaxAcquiredBufferCount);
+ std::optional<uint32_t> currentMaxAcquiredBufferCount,
+ bool fakeRelease);
void syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback,
bool acquireSingleBuffer = true);
void stopContinuousSyncTransaction();
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 1f19f4e..7aec0bf 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -113,6 +113,24 @@
return surface != nullptr && surface->getIGraphicBufferProducer() != nullptr;
}
+ static sp<IGraphicBufferProducer> getIGraphicBufferProducer(ANativeWindow* window) {
+ int val;
+ if (window->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &val) >= 0 &&
+ val == NATIVE_WINDOW_SURFACE) {
+ return ((Surface*) window)->mGraphicBufferProducer;
+ }
+ return nullptr;
+ }
+
+ static sp<IBinder> getSurfaceControlHandle(ANativeWindow* window) {
+ int val;
+ if (window->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &val) >= 0 &&
+ val == NATIVE_WINDOW_SURFACE) {
+ return ((Surface*) window)->mSurfaceControlHandle;
+ }
+ return nullptr;
+ }
+
/* Attaches a sideband buffer stream to the Surface's IGraphicBufferProducer.
*
* A sideband stream is a device-specific mechanism for passing buffers
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrerrorcode.h b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrerrorcode.h
new file mode 100644
index 0000000..49ab34d
--- /dev/null
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrerrorcode.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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 <utils/Errors.h>
+
+namespace android::recoverymap {
+
+enum {
+ // status_t map for errors in the media framework
+ // OK or NO_ERROR or 0 represents no error.
+
+ // See system/core/include/utils/Errors.h
+ // System standard errors from -1 through (possibly) -133
+ //
+ // Errors with special meanings and side effects.
+ // INVALID_OPERATION: Operation attempted in an illegal state (will try to signal to app).
+ // DEAD_OBJECT: Signal from CodecBase to MediaCodec that MediaServer has died.
+ // NAME_NOT_FOUND: Signal from CodecBase to MediaCodec that the component was not found.
+
+ // JPEGR errors
+ JPEGR_IO_ERROR_BASE = -10000,
+ ERROR_JPEGR_INVALID_INPUT_TYPE = JPEGR_IO_ERROR_BASE,
+ ERROR_JPEGR_INVALID_OUTPUT_TYPE = JPEGR_IO_ERROR_BASE - 1,
+ ERROR_JPEGR_INVALID_NULL_PTR = JPEGR_IO_ERROR_BASE - 2,
+
+ JPEGR_RUNTIME_ERROR_BASE = -20000,
+ ERROR_JPEGR_ENCODE_ERROR = JPEGR_RUNTIME_ERROR_BASE - 1,
+ ERROR_JPEGR_DECODE_ERROR = JPEGR_RUNTIME_ERROR_BASE - 2,
+ ERROR_JPEGR_CALCULATION_ERROR = JPEGR_RUNTIME_ERROR_BASE - 3,
+ ERROR_JPEGR_METADATA_ERROR = JPEGR_RUNTIME_ERROR_BASE - 4,
+};
+
+} // namespace android::recoverymap
\ No newline at end of file
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
index 15eca1e..31f1872 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
@@ -14,7 +14,7 @@
* limitations under the License.
*/
- #include <utils/Errors.h>
+#include "jpegrerrorcode.h"
namespace android::recoverymap {
diff --git a/libs/jpegrecoverymap/recoverymap.cpp b/libs/jpegrecoverymap/recoverymap.cpp
index 5d25722..67c23e9 100644
--- a/libs/jpegrecoverymap/recoverymap.cpp
+++ b/libs/jpegrecoverymap/recoverymap.cpp
@@ -24,7 +24,7 @@
if (uncompressed_p010_image == nullptr
|| uncompressed_yuv_420_image == nullptr
|| dest == nullptr) {
- return BAD_VALUE;
+ return ERROR_JPEGR_INVALID_NULL_PTR;
}
// TBD
@@ -40,7 +40,7 @@
|| uncompressed_yuv_420_image == nullptr
|| compressed_jpeg_image == nullptr
|| dest == nullptr) {
- return BAD_VALUE;
+ return ERROR_JPEGR_INVALID_NULL_PTR;
}
// TBD
@@ -53,7 +53,7 @@
if (uncompressed_p010_image == nullptr
|| compressed_jpeg_image == nullptr
|| dest == nullptr) {
- return BAD_VALUE;
+ return ERROR_JPEGR_INVALID_NULL_PTR;
}
// TBD
@@ -62,7 +62,7 @@
status_t RecoveryMap::decodeJPEGR(void* compressed_jpegr_image, jr_uncompressed_ptr dest) {
if (compressed_jpegr_image == nullptr || dest == nullptr) {
- return BAD_VALUE;
+ return ERROR_JPEGR_INVALID_NULL_PTR;
}
// TBD
@@ -72,7 +72,7 @@
status_t RecoveryMap::decodeRecoveryMap(jr_compressed_ptr compressed_recovery_map,
jr_uncompressed_ptr dest) {
if (compressed_recovery_map == nullptr || dest == nullptr) {
- return BAD_VALUE;
+ return ERROR_JPEGR_INVALID_NULL_PTR;
}
// TBD
@@ -82,7 +82,7 @@
status_t RecoveryMap::encodeRecoveryMap(jr_uncompressed_ptr uncompressed_recovery_map,
jr_compressed_ptr dest) {
if (uncompressed_recovery_map == nullptr || dest == nullptr) {
- return BAD_VALUE;
+ return ERROR_JPEGR_INVALID_NULL_PTR;
}
// TBD
@@ -95,7 +95,7 @@
if (uncompressed_yuv_420_image == nullptr
|| uncompressed_p010_image == nullptr
|| dest == nullptr) {
- return BAD_VALUE;
+ return ERROR_JPEGR_INVALID_NULL_PTR;
}
// TBD
@@ -108,7 +108,7 @@
if (uncompressed_yuv_420_image == nullptr
|| uncompressed_recovery_map == nullptr
|| dest == nullptr) {
- return BAD_VALUE;
+ return ERROR_JPEGR_INVALID_NULL_PTR;
}
// TBD
@@ -117,7 +117,7 @@
status_t RecoveryMap::extractRecoveryMap(void* compressed_jpegr_image, jr_compressed_ptr dest) {
if (compressed_jpegr_image == nullptr || dest == nullptr) {
- return BAD_VALUE;
+ return ERROR_JPEGR_INVALID_NULL_PTR;
}
// TBD
@@ -130,7 +130,7 @@
if (compressed_jpeg_image == nullptr
|| compressed_recovery_map == nullptr
|| dest == nullptr) {
- return BAD_VALUE;
+ return ERROR_JPEGR_INVALID_NULL_PTR;
}
// TBD
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index b075080..c345385 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -20,10 +20,15 @@
// from nativewindow/includes/system/window.h
// (not to be confused with the compatibility-only window.h from system/core/includes)
#include <system/window.h>
+#include <android/native_window_aidl.h>
#include <private/android/AHardwareBufferHelpers.h>
+#include <log/log.h>
#include <ui/GraphicBuffer.h>
+#include <gui/Surface.h>
+#include <gui/view/Surface.h>
+#include <android/binder_libbinder.h>
using namespace android;
@@ -59,6 +64,13 @@
return false;
}
}
+static sp<IGraphicBufferProducer> IGraphicBufferProducer_from_ANativeWindow(ANativeWindow* window) {
+ return Surface::getIGraphicBufferProducer(window);
+}
+
+static sp<IBinder> SurfaceControlHandle_from_ANativeWindow(ANativeWindow* window) {
+ return Surface::getSurfaceControlHandle(window);
+}
/**************************************************************************************************
* NDK
@@ -350,6 +362,42 @@
return native_window_set_auto_prerotation(window, autoPrerotation);
}
+binder_status_t ANativeWindow_readFromParcel(
+ const AParcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow) {
+ const Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel);
+
+ // Use a android::view::Surface to unparcel the window
+ std::shared_ptr<android::view::Surface> shimSurface = std::shared_ptr<android::view::Surface>();
+ status_t ret = shimSurface->readFromParcel(nativeParcel);
+ if (ret != OK) {
+ ALOGE("%s: Error: Failed to create android::view::Surface from AParcel", __FUNCTION__);
+ return STATUS_BAD_VALUE;
+ }
+ sp<Surface> surface = sp<Surface>::make(
+ shimSurface->graphicBufferProducer, false, shimSurface->surfaceControlHandle);
+ ANativeWindow* anw = surface.get();
+ ANativeWindow_acquire(anw);
+ *outWindow = anw;
+ return STATUS_OK;
+}
+
+binder_status_t ANativeWindow_writeToParcel(
+ ANativeWindow* _Nonnull window, AParcel* _Nonnull parcel) {
+ int value;
+ int err = (*window->query)(window, NATIVE_WINDOW_CONCRETE_TYPE, &value);
+ if (err != OK || value != NATIVE_WINDOW_SURFACE) {
+ ALOGE("Error: ANativeWindow is not backed by Surface");
+ return STATUS_BAD_VALUE;
+ }
+ // Use a android::view::Surface to parcelize the window
+ std::shared_ptr<android::view::Surface> shimSurface = std::shared_ptr<android::view::Surface>();
+ shimSurface->graphicBufferProducer = IGraphicBufferProducer_from_ANativeWindow(window);
+ shimSurface->surfaceControlHandle = SurfaceControlHandle_from_ANativeWindow(window);
+
+ Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel);
+ return shimSurface->writeToParcel(nativeParcel);
+}
+
/**************************************************************************************************
* apex-stable
**************************************************************************************************/
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 3b58265..bc0bfc5 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -110,9 +110,11 @@
static_libs: [
"libarect",
"libgrallocusage",
+ "libgui_aidl_static",
],
header_libs: [
+ "libgui_headers",
"libarect_headers",
"libnativebase_headers",
"libnativewindow_headers",
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 281ec52..a27e3dd 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -376,7 +376,7 @@
__INTRODUCED_IN(__ANDROID_API_U__);
#ifdef __cplusplus
-};
+}
#endif
#endif // ANDROID_NATIVE_WINDOW_H
diff --git a/libs/nativewindow/include/android/native_window_aidl.h b/libs/nativewindow/include/android/native_window_aidl.h
new file mode 100644
index 0000000..a252245
--- /dev/null
+++ b/libs/nativewindow/include/android/native_window_aidl.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2022 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.
+ */
+
+/**
+ * @file native_window_aidl.h
+ * @brief NativeWindow NDK AIDL glue code
+ */
+
+/**
+ * @addtogroup ANativeWindow
+ *
+ * Parcelable support for ANativeWindow. Can be used with libbinder_ndk
+ *
+ * @{
+ */
+
+#ifndef ANDROID_NATIVE_WINDOW_AIDL_H
+#define ANDROID_NATIVE_WINDOW_AIDL_H
+
+#include <android/binder_parcel.h>
+#include <android/native_window.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/**
+ * Read an ANativeWindow from a AParcel. The output buffer will have an
+ * initial reference acquired and will need to be released with
+ * ANativeWindow_release.
+ *
+ * Available since API level 34.
+ *
+ * \return STATUS_OK on success
+ * STATUS_BAD_VALUE if the parcel or outBuffer is null, or if there's an
+ * issue deserializing (eg, corrupted parcel)
+ * STATUS_BAD_TYPE if the parcel's current data position is not that of
+ * an ANativeWindow type
+ * STATUS_NO_MEMORY if an allocation fails
+ */
+binder_status_t ANativeWindow_readFromParcel(const AParcel* _Nonnull parcel,
+ ANativeWindow* _Nullable* _Nonnull outWindow) __INTRODUCED_IN(__ANDROID_API_U__);
+
+/**
+ * Write an ANativeWindow to an AParcel.
+ *
+ * Available since API level 34.
+ *
+ * \return STATUS_OK on success.
+ * STATUS_BAD_VALUE if either buffer or parcel is null, or if the ANativeWindow*
+ * fails to serialize (eg, internally corrupted)
+ * STATUS_NO_MEMORY if the parcel runs out of space to store the buffer & is
+ * unable to allocate more
+ * STATUS_FDS_NOT_ALLOWED if the parcel does not allow storing FDs
+ */
+binder_status_t ANativeWindow_writeToParcel(ANativeWindow* _Nonnull window,
+ AParcel* _Nonnull parcel) __INTRODUCED_IN(__ANDROID_API_U__);
+
+__END_DECLS
+
+// Only enable the AIDL glue helper if this is C++
+#ifdef __cplusplus
+
+namespace aidl::android::hardware {
+
+/**
+ * Wrapper class that enables interop with AIDL NDK generation
+ * Takes ownership of the ANativeWindow* given to it in reset() and will automatically
+ * destroy it in the destructor, similar to a smart pointer container
+ */
+class NativeWindow {
+public:
+ NativeWindow() noexcept {}
+ explicit NativeWindow(ANativeWindow* _Nullable window) {
+ reset(window);
+ }
+
+ explicit NativeWindow(NativeWindow&& other) noexcept {
+ mWindow = other.release(); // steal ownership from r-value
+ }
+
+ ~NativeWindow() {
+ reset();
+ }
+
+ binder_status_t readFromParcel(const AParcel* _Nonnull parcel) {
+ reset();
+ return ANativeWindow_readFromParcel(parcel, &mWindow);
+ }
+
+ binder_status_t writeToParcel(AParcel* _Nonnull parcel) const {
+ if (!mWindow) {
+ return STATUS_BAD_VALUE;
+ }
+ return ANativeWindow_writeToParcel(mWindow, parcel);
+ }
+
+ /**
+ * Destroys any currently owned ANativeWindow* and takes ownership of the given
+ * ANativeWindow*
+ *
+ * @param buffer The buffer to take ownership of
+ */
+ void reset(ANativeWindow* _Nullable window = nullptr) noexcept {
+ if (mWindow) {
+ ANativeWindow_release(mWindow);
+ mWindow = nullptr;
+ }
+ if (window != nullptr) {
+ ANativeWindow_acquire(window);
+ }
+ mWindow = window;
+ }
+ inline ANativeWindow* _Nullable operator-> () const { return mWindow; }
+ inline ANativeWindow* _Nullable get() const { return mWindow; }
+ inline explicit operator bool () const { return mWindow != nullptr; }
+
+ NativeWindow& operator=(NativeWindow&& other) noexcept {
+ mWindow = other.release(); // steal ownership from r-value
+ return *this;
+ }
+
+ /**
+ * Stops managing any contained ANativeWindow*, returning it to the caller. Ownership
+ * is released.
+ * @return ANativeWindow* or null if this was empty
+ */
+ [[nodiscard]] ANativeWindow* _Nullable release() noexcept {
+ ANativeWindow* _Nullable ret = mWindow;
+ mWindow = nullptr;
+ return ret;
+ }
+private:
+ ANativeWindow* _Nullable mWindow = nullptr;
+ NativeWindow(const NativeWindow &other) = delete;
+ NativeWindow& operator=(const NativeWindow &other) = delete;
+};
+
+} // aidl::android::hardware
+ //
+namespace aidl::android::view {
+ using Surface = aidl::android::hardware::NativeWindow;
+}
+
+#endif // __cplusplus
+
+#endif // ANDROID_NATIVE_WINDOW_AIDL_H
+
+/** @} */
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index ce108b6..76d23fa 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -57,6 +57,8 @@
ANativeWindow_setUsage; # llndk
ANativeWindow_tryAllocateBuffers; # introduced=30
ANativeWindow_unlockAndPost;
+ ANativeWindow_readFromParcel; # introduced=UpsideDownCake
+ ANativeWindow_writeToParcel; # introduced=UpsideDownCake
local:
*;
};
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 63a2418..9a6ebaa 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2092,7 +2092,7 @@
}
bool isSplit = shouldSplitTouch(tempTouchState, entry);
- bool switchedDevice = tempTouchState.deviceId >= 0 && tempTouchState.displayId >= 0 &&
+ const bool switchedDevice = tempTouchState.deviceId >= 0 && tempTouchState.displayId >= 0 &&
(tempTouchState.deviceId != entry.deviceId || tempTouchState.source != entry.source ||
tempTouchState.displayId != displayId);
@@ -2102,7 +2102,6 @@
const bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction);
const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE);
- bool wrongDevice = false;
if (newGesture) {
bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
if (switchedDevice && tempTouchState.down && !down && !isHoverAction) {
@@ -2111,9 +2110,7 @@
displayId);
// TODO: test multiple simultaneous input streams.
outInjectionResult = InputEventInjectionResult::FAILED;
- switchedDevice = false;
- wrongDevice = true;
- return touchedWindows;
+ return touchedWindows; // wrong device
}
tempTouchState.reset();
tempTouchState.down = down;
@@ -2127,9 +2124,7 @@
displayId);
// TODO: test multiple simultaneous input streams.
outInjectionResult = InputEventInjectionResult::FAILED;
- switchedDevice = false;
- wrongDevice = true;
- return touchedWindows;
+ return touchedWindows; // wrong device
}
if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index eb31046..a3f45cf 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -138,14 +138,4 @@
return nullptr;
}
-sp<WindowInfoHandle> TouchState::getWindow(const sp<IBinder>& token) const {
- for (const TouchedWindow& touchedWindow : windows) {
- const auto& windowHandle = touchedWindow.windowHandle;
- if (windowHandle->getToken() == token) {
- return windowHandle;
- }
- }
- return nullptr;
-}
-
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index d324611..f6e9fb6 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -59,7 +59,6 @@
sp<android::gui::WindowInfoHandle> getFirstForegroundWindowHandle() const;
bool isSlippery() const;
sp<android::gui::WindowInfoHandle> getWallpaperWindow() const;
- sp<android::gui::WindowInfoHandle> getWindow(const sp<IBinder>&) const;
};
} // namespace inputdispatcher
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index d14b0f0..2110107 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -3562,6 +3562,8 @@
std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsecs_t readTime,
uint32_t policyFlags, bool down,
bool hovering) {
+ LOG_ALWAYS_FATAL_IF(mDeviceMode != DeviceMode::POINTER,
+ "%s cannot be used when the device is not in POINTER mode.", __func__);
std::list<NotifyArgs> out;
int32_t metaState = getContext()->getGlobalMetaState();
@@ -3688,6 +3690,10 @@
if (down || hovering) {
mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
+ mPointerSimple.displayId = displayId;
+ mPointerSimple.source = mSource;
+ mPointerSimple.lastCursorX = xCursorPosition;
+ mPointerSimple.lastCursorY = yCursorPosition;
} else {
mPointerSimple.reset();
}
@@ -3696,10 +3702,25 @@
std::list<NotifyArgs> TouchInputMapper::abortPointerSimple(nsecs_t when, nsecs_t readTime,
uint32_t policyFlags) {
- mPointerSimple.currentCoords.clear();
- mPointerSimple.currentProperties.clear();
-
- return dispatchPointerSimple(when, readTime, policyFlags, false, false);
+ std::list<NotifyArgs> out;
+ if (mPointerSimple.down || mPointerSimple.hovering) {
+ int32_t metaState = getContext()->getGlobalMetaState();
+ out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
+ mPointerSimple.source, mPointerSimple.displayId, policyFlags,
+ AMOTION_EVENT_ACTION_CANCEL, 0, AMOTION_EVENT_FLAG_CANCELED,
+ metaState, mLastRawState.buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+ &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.lastCursorX, mPointerSimple.lastCursorY,
+ mPointerSimple.downTime,
+ /* videoFrames */ {}));
+ if (mPointerController != nullptr) {
+ mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
+ }
+ }
+ mPointerSimple.reset();
+ return out;
}
NotifyMotionArgs TouchInputMapper::dispatchMotion(
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index bab15cc..d5e4d5a 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -681,6 +681,12 @@
// Time the pointer last went down.
nsecs_t downTime;
+ // Values reported for the last pointer event.
+ uint32_t source;
+ int32_t displayId;
+ float lastCursorX;
+ float lastCursorY;
+
void reset() {
currentCoords.clear();
currentProperties.clear();
@@ -689,6 +695,10 @@
down = false;
hovering = false;
downTime = 0;
+ source = 0;
+ displayId = ADISPLAY_ID_NONE;
+ lastCursorX = 0.f;
+ lastCursorY = 0.f;
}
} mPointerSimple;
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
index 5d5bee7..1891205 100644
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
@@ -108,13 +108,13 @@
}
void TouchButtonAccumulator::processMappedKey(int32_t scanCode, bool down) {
- int32_t outKeyCode, outMetaState;
- uint32_t outFlags;
+ int32_t keyCode, metaState;
+ uint32_t flags;
if (mDeviceContext.mapKey(scanCode, mHidUsageAccumulator.consumeCurrentHidUsage(),
- 0 /*metaState*/, &outKeyCode, &outMetaState, &outFlags) != OK) {
+ 0 /*metaState*/, &keyCode, &metaState, &flags) != OK) {
return;
}
- switch (outKeyCode) {
+ switch (keyCode) {
case AKEYCODE_STYLUS_BUTTON_PRIMARY:
mBtnStylus = down;
break;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 39f521b..0a5793d 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -10444,6 +10444,46 @@
ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0);
}
+TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
+ preparePointerMode(25 /*xResolution*/, 25 /*yResolution*/);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
+
+ // Start a stylus gesture.
+ processKey(mapper, BTN_TOOL_PEN, 1);
+ processId(mapper, FIRST_TRACKING_ID);
+ processPosition(mapper, 100, 200);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
+ WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
+ WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS))));
+ // TODO(b/257078296): Pointer mode generates extra event.
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
+ WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
+ WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS))));
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
+
+ // Make the viewport inactive. This will put the device in disabled mode, and the ongoing stylus
+ // gesture should be disabled.
+ auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
+ viewport->isActive = false;
+ mFakePolicy->updateViewport(*viewport);
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
+ WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
+ WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS))));
+ // TODO(b/257078296): Pointer mode generates extra event.
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
+ WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
+ WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS))));
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
+}
+
// --- JoystickInputMapperTest ---
class JoystickInputMapperTest : public InputMapperTest {
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 892c07d..999c03f 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -49,7 +49,7 @@
"android.hardware.graphics.composer@2.4",
"android.hardware.power@1.0",
"android.hardware.power@1.3",
- "android.hardware.power-V2-cpp",
+ "android.hardware.power-V4-cpp",
"libbase",
"libbinder",
"libbinder_ndk",
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 0ae8bf9..c1460cf 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -25,7 +25,7 @@
"android.hardware.graphics.composer@2.4",
"android.hardware.power@1.0",
"android.hardware.power@1.3",
- "android.hardware.power-V2-cpp",
+ "android.hardware.power-V4-cpp",
"libbase",
"libcutils",
"libgui",
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 499cee6..0e1b775 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -94,7 +94,7 @@
}
}
-void Scheduler::setRefreshRateSelector(std::shared_ptr<RefreshRateSelector> selectorPtr) {
+void Scheduler::setRefreshRateSelector(RefreshRateSelectorPtr selectorPtr) {
// The current RefreshRateSelector instance may outlive this call, so unbind its idle timer.
{
// mRefreshRateSelectorLock is not locked here to avoid the deadlock
@@ -126,13 +126,12 @@
mRefreshRateSelector->startIdleTimer();
}
-void Scheduler::registerDisplay(sp<const DisplayDevice> display) {
- if (display->isPrimary()) {
- mLeaderDisplayId = display->getPhysicalId();
+void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
+ if (!mLeaderDisplayId) {
+ mLeaderDisplayId = displayId;
}
- const bool ok = mDisplays.try_emplace(display->getPhysicalId(), std::move(display)).second;
- ALOGE_IF(!ok, "%s: Duplicate display", __func__);
+ mRefreshRateSelectors.emplace_or_replace(displayId, std::move(selectorPtr));
}
void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
@@ -140,7 +139,7 @@
mLeaderDisplayId.reset();
}
- mDisplays.erase(displayId);
+ mRefreshRateSelectors.erase(displayId);
}
void Scheduler::run() {
@@ -711,10 +710,9 @@
const auto globalSignals = makeGlobalSignals();
- for (const auto& [id, display] : mDisplays) {
+ for (const auto& [id, selectorPtr] : mRefreshRateSelectors) {
auto rankedRefreshRates =
- display->holdRefreshRateSelector()
- ->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals);
+ selectorPtr->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals);
for (const auto& [modePtr, score] : rankedRefreshRates.ranking) {
const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score);
@@ -733,7 +731,7 @@
// Find the first refresh rate common to all displays.
while (maxScoreIt != refreshRateTallies.cend() &&
- maxScoreIt->second.displayCount != mDisplays.size()) {
+ maxScoreIt->second.displayCount != mRefreshRateSelectors.size()) {
++maxScoreIt;
}
@@ -742,7 +740,8 @@
for (auto it = maxScoreIt + 1; it != refreshRateTallies.cend(); ++it) {
const auto [fps, tally] = *it;
- if (tally.displayCount == mDisplays.size() && tally.score > maxScoreIt->second.score) {
+ if (tally.displayCount == mRefreshRateSelectors.size() &&
+ tally.score > maxScoreIt->second.score) {
maxScoreIt = it;
}
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 39c41b9..901cf74 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -39,7 +39,6 @@
#include "Display/DisplayMap.h"
#include "Display/DisplayModeRequest.h"
-#include "DisplayDevice.h"
#include "EventThread.h"
#include "FrameRateOverrideMappings.h"
#include "LayerHistory.h"
@@ -107,10 +106,11 @@
virtual ~Scheduler();
void startTimers();
- void setRefreshRateSelector(std::shared_ptr<RefreshRateSelector>)
- EXCLUDES(mRefreshRateSelectorLock);
- void registerDisplay(sp<const DisplayDevice>);
+ using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>;
+ void setRefreshRateSelector(RefreshRateSelectorPtr) EXCLUDES(mRefreshRateSelectorLock);
+
+ void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr);
void unregisterDisplay(PhysicalDisplayId);
void run();
@@ -299,8 +299,7 @@
EXCLUDES(mRefreshRateSelectorLock);
android::impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const;
- std::shared_ptr<RefreshRateSelector> holdRefreshRateSelector() const
- EXCLUDES(mRefreshRateSelectorLock) {
+ RefreshRateSelectorPtr holdRefreshRateSelector() const EXCLUDES(mRefreshRateSelectorLock) {
std::scoped_lock lock(mRefreshRateSelectorLock);
return mRefreshRateSelector;
}
@@ -336,7 +335,7 @@
mutable std::mutex mPolicyLock;
- display::PhysicalDisplayMap<PhysicalDisplayId, sp<const DisplayDevice>> mDisplays;
+ display::PhysicalDisplayMap<PhysicalDisplayId, RefreshRateSelectorPtr> mRefreshRateSelectors;
std::optional<PhysicalDisplayId> mLeaderDisplayId;
struct Policy {
@@ -359,8 +358,9 @@
std::optional<ModeChangedParams> cachedModeChangedParams;
} mPolicy GUARDED_BY(mPolicyLock);
+ // TODO(b/255635821): Remove this by instead looking up the `mLeaderDisplayId` selector.
mutable std::mutex mRefreshRateSelectorLock;
- std::shared_ptr<RefreshRateSelector> mRefreshRateSelector GUARDED_BY(mRefreshRateSelectorLock);
+ RefreshRateSelectorPtr mRefreshRateSelector GUARDED_BY(mRefreshRateSelectorLock);
std::mutex mVsyncTimelineLock;
std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 89d905a..aa930bc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2937,11 +2937,15 @@
displaySurface, producer);
if (mScheduler && !display->isVirtual()) {
+ auto selectorPtr = display->holdRefreshRateSelector();
+
// Display modes are reloaded on hotplug reconnect.
if (display->isPrimary()) {
- mScheduler->setRefreshRateSelector(display->holdRefreshRateSelector());
+ mScheduler->setRefreshRateSelector(selectorPtr);
}
- mScheduler->registerDisplay(display);
+
+ const auto displayId = display->getPhysicalId();
+ mScheduler->registerDisplay(displayId, std::move(selectorPtr));
dispatchDisplayHotplugEvent(display->getPhysicalId(), true);
}
@@ -2994,8 +2998,6 @@
display->disconnect();
if (display->isVirtual()) {
releaseVirtualDisplay(display->getVirtualId());
- } else {
- mScheduler->unregisterDisplay(display->getPhysicalId());
}
}
@@ -3409,8 +3411,8 @@
}
mScheduler->createVsyncSchedule(features);
- mScheduler->setRefreshRateSelector(std::move(selectorPtr));
- mScheduler->registerDisplay(display);
+ mScheduler->setRefreshRateSelector(selectorPtr);
+ mScheduler->registerDisplay(display->getPhysicalId(), std::move(selectorPtr));
}
setVsyncEnabled(false);
mScheduler->startTimers();
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 5daa398..d88da4d 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -150,7 +150,7 @@
"android.hardware.power@1.1",
"android.hardware.power@1.2",
"android.hardware.power@1.3",
- "android.hardware.power-V2-cpp",
+ "android.hardware.power-V4-cpp",
"libaidlcommonsupport",
"libcompositionengine_mocks",
"libcompositionengine",
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 066083f..ea4666e 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -20,7 +20,6 @@
#include <mutex>
-#include "FakeDisplayInjector.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/RefreshRateSelector.h"
#include "TestableScheduler.h"
@@ -41,7 +40,6 @@
using MockEventThread = android::mock::EventThread;
using MockLayer = android::mock::MockLayer;
-using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
class SchedulerTest : public testing::Test {
protected:
@@ -90,10 +88,6 @@
sp<MockEventThreadConnection> mEventThreadConnection;
TestableSurfaceFlinger mFlinger;
- Hwc2::mock::PowerAdvisor mPowerAdvisor;
- sp<android::mock::NativeWindow> mNativeWindow = sp<android::mock::NativeWindow>::make();
-
- FakeDisplayInjector mFakeDisplayInjector{mFlinger, mPowerAdvisor, mNativeWindow};
};
SchedulerTest::SchedulerTest() {
@@ -240,14 +234,11 @@
}
TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
- const auto display = mFakeDisplayInjector.injectInternalDisplay(
- [&](FakeDisplayDeviceInjector& injector) {
- injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId());
- },
- {.displayId = kDisplayId1});
+ const auto selectorPtr =
+ std::make_shared<RefreshRateSelector>(kDisplay1Modes, kDisplay1Mode60->getId());
- mScheduler->registerDisplay(display);
- mScheduler->setRefreshRateSelector(display->holdRefreshRateSelector());
+ mScheduler->registerDisplay(kDisplayId1, selectorPtr);
+ mScheduler->setRefreshRateSelector(selectorPtr);
const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true));
@@ -269,13 +260,9 @@
}
TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) {
- const auto display = mFakeDisplayInjector.injectInternalDisplay(
- [&](FakeDisplayDeviceInjector& injector) {
- injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId());
- },
- {.displayId = kDisplayId1});
-
- mScheduler->registerDisplay(display);
+ mScheduler->registerDisplay(kDisplayId1,
+ std::make_shared<RefreshRateSelector>(kDisplay1Modes,
+ kDisplay1Mode60->getId()));
std::vector<RefreshRateSelector::LayerRequirement> layers =
std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
@@ -314,23 +301,16 @@
EXPECT_EQ(choice->get(), DisplayModeChoice(kDisplay1Mode120, globalSignals));
mScheduler->unregisterDisplay(kDisplayId1);
- EXPECT_TRUE(mScheduler->mutableDisplays().empty());
+ EXPECT_FALSE(mScheduler->hasRefreshRateSelectors());
}
TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) {
- const auto display1 = mFakeDisplayInjector.injectInternalDisplay(
- [&](FakeDisplayDeviceInjector& injector) {
- injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId());
- },
- {.displayId = kDisplayId1, .hwcDisplayId = 42, .isPrimary = true});
- const auto display2 = mFakeDisplayInjector.injectInternalDisplay(
- [&](FakeDisplayDeviceInjector& injector) {
- injector.setDisplayModes(kDisplay2Modes, kDisplay2Mode60->getId());
- },
- {.displayId = kDisplayId2, .hwcDisplayId = 41, .isPrimary = false});
-
- mScheduler->registerDisplay(display1);
- mScheduler->registerDisplay(display2);
+ mScheduler->registerDisplay(kDisplayId1,
+ std::make_shared<RefreshRateSelector>(kDisplay1Modes,
+ kDisplay1Mode60->getId()));
+ mScheduler->registerDisplay(kDisplayId2,
+ std::make_shared<RefreshRateSelector>(kDisplay2Modes,
+ kDisplay2Mode60->getId()));
using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
TestableScheduler::DisplayModeChoiceMap expectedChoices;
@@ -380,13 +360,10 @@
}
{
// This display does not support 120 Hz, so we should choose 60 Hz despite the touch signal.
- const auto display3 = mFakeDisplayInjector.injectInternalDisplay(
- [&](FakeDisplayDeviceInjector& injector) {
- injector.setDisplayModes(kDisplay3Modes, kDisplay3Mode60->getId());
- },
- {.displayId = kDisplayId3, .hwcDisplayId = 40, .isPrimary = false});
-
- mScheduler->registerDisplay(display3);
+ mScheduler
+ ->registerDisplay(kDisplayId3,
+ std::make_shared<RefreshRateSelector>(kDisplay3Modes,
+ kDisplay3Mode60->getId()));
const GlobalSignals globalSignals = {.touch = true};
mScheduler->replaceTouchTimer(10);
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 2814d38..95c9915 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -32,15 +32,13 @@
class TestableScheduler : public Scheduler, private ICompositor {
public:
- TestableScheduler(std::shared_ptr<RefreshRateSelector> selectorPtr,
- ISchedulerCallback& callback)
+ TestableScheduler(RefreshRateSelectorPtr selectorPtr, ISchedulerCallback& callback)
: TestableScheduler(std::make_unique<mock::VsyncController>(),
std::make_unique<mock::VSyncTracker>(), std::move(selectorPtr),
callback) {}
TestableScheduler(std::unique_ptr<VsyncController> controller,
- std::unique_ptr<VSyncTracker> tracker,
- std::shared_ptr<RefreshRateSelector> selectorPtr,
+ std::unique_ptr<VSyncTracker> tracker, RefreshRateSelectorPtr selectorPtr,
ISchedulerCallback& callback)
: Scheduler(*this, callback, Feature::kContentDetection) {
mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller)));
@@ -68,16 +66,15 @@
auto& mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; }
auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; }
- auto& mutableLayerHistory() { return mLayerHistory; }
+ auto refreshRateSelector() { return holdRefreshRateSelector(); }
+ bool hasRefreshRateSelectors() const { return !mRefreshRateSelectors.empty(); }
- auto& mutableDisplays() { return mDisplays; }
+ auto& mutableLayerHistory() { return mLayerHistory; }
size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS {
return mLayerHistory.mActiveLayerInfos.size() + mLayerHistory.mInactiveLayerInfos.size();
}
- auto refreshRateSelector() { return holdRefreshRateSelector(); }
-
size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS {
return mLayerHistory.mActiveLayerInfos.size();
}
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index ff79ce0..35c037c 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -842,7 +842,8 @@
sp<DisplayDevice> display = sp<DisplayDevice>::make(mCreationArgs);
mFlinger.mutableDisplays().emplace_or_replace(mDisplayToken, display);
if (mFlinger.scheduler()) {
- mFlinger.scheduler()->registerDisplay(display);
+ mFlinger.scheduler()->registerDisplay(display->getPhysicalId(),
+ display->holdRefreshRateSelector());
}
DisplayDeviceState state;
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.h
index 439f6f4..5f749df 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.h
@@ -23,6 +23,7 @@
using android::binder::Status;
using android::hardware::power::IPowerHintSession;
+using android::hardware::power::SessionHint;
using namespace android::hardware::power;
@@ -40,6 +41,7 @@
MOCK_METHOD(std::string, getInterfaceHash, (), (override));
MOCK_METHOD(Status, updateTargetWorkDuration, (int64_t), (override));
MOCK_METHOD(Status, reportActualWorkDuration, (const ::std::vector<WorkDuration>&), (override));
+ MOCK_METHOD(Status, sendHint, (SessionHint), (override));
};
} // namespace android::Hwc2::mock