Merge "Allow GPU composition to occur at a lower resolution" into rvc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 3440116..e7029bd 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1477,6 +1477,8 @@
ds.AddDir(WMTRACE_DATA_DIR, false);
}
+ ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
+
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
/* Migrate the ril_dumpstate to a device specific dumpstate? */
@@ -1605,7 +1607,6 @@
ds.AddDir(RECOVERY_DATA_DIR, true);
ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
ds.AddDir(LOGPERSIST_DATA_DIR, false);
- ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
if (!PropertiesHelper::IsUserBuild()) {
ds.AddDir(PROFILE_DATA_DIR_CUR, true);
ds.AddDir(PROFILE_DATA_DIR_REF, true);
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index f426dbb..fb11cee 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -406,7 +406,7 @@
return false;
}
- if (fqInstance.getPackage() == gIBaseFqName.package()) {
+ if (fqInstance.getPackage() == "android.hidl.base") {
return true; // always remove IBase from manifest
}
diff --git a/include/ui/FatVector.h b/include/ui/FatVector.h
deleted file mode 120000
index c2047c0..0000000
--- a/include/ui/FatVector.h
+++ /dev/null
@@ -1 +0,0 @@
-../../libs/ui/include/ui/FatVector.h
\ No newline at end of file
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index aeca12b..43b0da3 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -30,24 +30,10 @@
namespace android {
-namespace {
-
-#if defined(__BRILLO__)
-// Because Brillo has no application model, security policy is managed
-// statically (at build time) with SELinux controls.
-// As a consequence, it also never runs the AppOpsManager service.
-const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_ALLOWED;
-#else
-const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_IGNORED;
-#endif // defined(__BRILLO__)
-
-} // namespace
-
-static String16 _appops("appops");
-static pthread_mutex_t gClientIdMutex = PTHREAD_MUTEX_INITIALIZER;
-static sp<IBinder> gClientId;
-
static const sp<IBinder>& getClientId() {
+ static pthread_mutex_t gClientIdMutex = PTHREAD_MUTEX_INITIALIZER;
+ static sp<IBinder> gClientId;
+
pthread_mutex_lock(&gClientIdMutex);
if (gClientId == nullptr) {
gClientId = new BBinder();
@@ -56,22 +42,13 @@
return gClientId;
}
-thread_local uint64_t notedAppOpsInThisBinderTransaction[2];
-thread_local int32_t uidOfThisBinderTransaction = -1;
-
-// Whether an appop should be collected: 0 == not initialized, 1 == don't note, 2 == note
-uint8_t appOpsToNote[AppOpsManager::_NUM_OP] = {0};
-
AppOpsManager::AppOpsManager()
{
}
-#if defined(__BRILLO__)
-// There is no AppOpsService on Brillo
-sp<IAppOpsService> AppOpsManager::getService() { return NULL; }
-#else
sp<IAppOpsService> AppOpsManager::getService()
{
+ static String16 _appops("appops");
std::lock_guard<Mutex> scoped_lock(mLock);
int64_t startTime = 0;
@@ -96,14 +73,13 @@
}
return service;
}
-#endif // defined(__BRILLO__)
int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
{
sp<IAppOpsService> service = getService();
return service != nullptr
? service->checkOperation(op, uid, callingPackage)
- : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+ : AppOpsManager::MODE_IGNORED;
}
int32_t AppOpsManager::checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
@@ -111,7 +87,7 @@
sp<IAppOpsService> service = getService();
return service != nullptr
? service->checkAudioOperation(op, usage, uid, callingPackage)
- : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+ : AppOpsManager::MODE_IGNORED;
}
int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
@@ -125,7 +101,7 @@
int32_t mode = service != nullptr
? service->noteOperation(op, uid, callingPackage, featureId, shouldCollectNotes(op),
message)
- : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+ : AppOpsManager::MODE_IGNORED;
return mode;
}
@@ -143,7 +119,7 @@
int32_t mode = service != nullptr
? service->startOperation(getClientId(), op, uid, callingPackage,
featureId, startIfModeDefault, shouldCollectNotes(op), message)
- : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+ : AppOpsManager::MODE_IGNORED;
return mode;
}
@@ -192,6 +168,9 @@
// check it the appops needs to be collected and cache result
bool AppOpsManager::shouldCollectNotes(int32_t opcode) {
+ // Whether an appop should be collected: 0 == not initialized, 1 == don't note, 2 == note
+ static uint8_t appOpsToNote[AppOpsManager::_NUM_OP] = {0};
+
if (appOpsToNote[opcode] == 0) {
if (getService()->shouldCollectNotes(opcode)) {
appOpsToNote[opcode] = 2;
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 2f6e9c3..e0fb543 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -141,7 +141,7 @@
// ---------------------------------------------------------------------------
-BBinder::BBinder() : mExtras(nullptr)
+BBinder::BBinder() : mExtras(nullptr), mStability(0)
{
}
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index f16c39c..d2b9b8f 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -138,6 +138,7 @@
BpBinder::BpBinder(int32_t handle, int32_t trackedUid)
: mHandle(handle)
+ , mStability(0)
, mAlive(1)
, mObitsSent(0)
, mObituaries(nullptr)
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
index 7ce5e36..e1565fa 100644
--- a/libs/binder/Stability.cpp
+++ b/libs/binder/Stability.cpp
@@ -15,6 +15,9 @@
*/
#include <binder/Stability.h>
+#include <binder/BpBinder.h>
+#include <binder/Binder.h>
+
namespace android {
namespace internal {
@@ -78,11 +81,12 @@
if (currentStability == stability) return OK;
- binder->attachObject(
- reinterpret_cast<void*>(&Stability::get),
- reinterpret_cast<void*>(stability),
- nullptr /*cleanupCookie*/,
- nullptr /*cleanup function*/);
+ BBinder* local = binder->localBinder();
+ if (local != nullptr) {
+ local->mStability = static_cast<int32_t>(stability);
+ } else {
+ binder->remoteBinder()->mStability = static_cast<int32_t>(stability);
+ }
return OK;
}
@@ -90,8 +94,12 @@
Stability::Level Stability::get(IBinder* binder) {
if (binder == nullptr) return UNDECLARED;
- return static_cast<Level>(reinterpret_cast<intptr_t>(
- binder->findObject(reinterpret_cast<void*>(&Stability::get))));
+ BBinder* local = binder->localBinder();
+ if (local != nullptr) {
+ return static_cast<Stability::Level>(local->mStability);
+ }
+
+ return static_cast<Stability::Level>(binder->remoteBinder()->mStability);
}
bool Stability::check(int32_t provided, Level required) {
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 3be61f9..74e52db 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -24,6 +24,10 @@
// ---------------------------------------------------------------------------
namespace android {
+namespace internal {
+class Stability;
+}
+
class BBinder : public IBinder
{
public:
@@ -88,7 +92,12 @@
Extras* getOrCreateExtras();
std::atomic<Extras*> mExtras;
- void* mReserved0;
+
+ friend ::android::internal::Stability;
+ union {
+ int32_t mStability;
+ void* mReserved0;
+ };
};
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 7dca733..8e871b8 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -27,6 +27,10 @@
// ---------------------------------------------------------------------------
namespace android {
+namespace internal {
+class Stability;
+};
+
using binder_proxy_limit_callback = void(*)(int);
class BpBinder : public IBinder
@@ -116,6 +120,9 @@
private:
const int32_t mHandle;
+ friend ::android::internal::Stability;
+ int32_t mStability;
+
struct Obituary {
wp<DeathRecipient> recipient;
void* cookie;
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 75dcdc8..649faa1 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -486,7 +486,6 @@
void AIBinder_incStrong(AIBinder* binder) {
if (binder == nullptr) {
- LOG(ERROR) << __func__ << ": on null binder";
return;
}
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 1b42b69..5b65c95 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -57,6 +57,7 @@
"android.hardware.audio@5.0::IDevicesFactory",
"android.hardware.audio@6.0::IDevicesFactory",
"android.hardware.biometrics.face@1.0::IBiometricsFace",
+ "android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprint",
"android.hardware.bluetooth@1.0::IBluetoothHci",
"android.hardware.camera.provider@2.4::ICameraProvider",
"android.hardware.drm@1.0::IDrmFactory",
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index a9c9b74..f7158d0 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -443,39 +443,18 @@
// ------------------------------- InputWindowCommands ----------------------------------------
void InputWindowCommands::merge(const InputWindowCommands& other) {
- transferTouchFocusCommands
- .insert(transferTouchFocusCommands.end(),
- std::make_move_iterator(other.transferTouchFocusCommands.begin()),
- std::make_move_iterator(other.transferTouchFocusCommands.end()));
-
syncInputWindows |= other.syncInputWindows;
}
void InputWindowCommands::clear() {
- transferTouchFocusCommands.clear();
syncInputWindows = false;
}
void InputWindowCommands::write(Parcel& output) const {
- output.writeUint32(static_cast<uint32_t>(transferTouchFocusCommands.size()));
- for (const auto& transferTouchFocusCommand : transferTouchFocusCommands) {
- output.writeStrongBinder(transferTouchFocusCommand.fromToken);
- output.writeStrongBinder(transferTouchFocusCommand.toToken);
- }
-
output.writeBool(syncInputWindows);
}
void InputWindowCommands::read(const Parcel& input) {
- size_t count = input.readUint32();
- transferTouchFocusCommands.clear();
- for (size_t i = 0; i < count; i++) {
- TransferTouchFocusCommand transferTouchFocusCommand;
- transferTouchFocusCommand.fromToken = input.readStrongBinder();
- transferTouchFocusCommand.toToken = input.readStrongBinder();
- transferTouchFocusCommands.emplace_back(transferTouchFocusCommand);
- }
-
syncInputWindows = input.readBool();
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index dc4860a..2307fbf 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1290,15 +1290,6 @@
return *this;
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::transferTouchFocus(
- const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
- InputWindowCommands::TransferTouchFocusCommand transferTouchFocusCommand;
- transferTouchFocusCommand.fromToken = fromToken;
- transferTouchFocusCommand.toToken = toToken;
- mInputWindowCommands.transferTouchFocusCommands.emplace_back(transferTouchFocusCommand);
- return *this;
-}
-
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::syncInputWindows() {
mInputWindowCommands.syncInputWindows = true;
return *this;
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 7e3d5d5..2b2f773 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -271,12 +271,6 @@
};
struct InputWindowCommands {
- struct TransferTouchFocusCommand {
- sp<IBinder> fromToken;
- sp<IBinder> toToken;
- };
-
- std::vector<TransferTouchFocusCommand> transferTouchFocusCommands;
bool syncInputWindows{false};
void merge(const InputWindowCommands& other);
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 0cf141d..2fb9538 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -507,7 +507,6 @@
#ifndef NO_INPUT
Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
- Transaction& transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
Transaction& syncInputWindows();
#endif
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 416ebfe..0d4305b 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -381,15 +381,6 @@
LOG_ALWAYS_FATAL_IF(!success, "can't make default context current");
}
- const uint16_t protTexData[] = {0};
- glGenTextures(1, &mProtectedTexName);
- glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
-
// mColorBlindnessCorrection = M;
if (mUseColorManagement) {
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 4cd0b3d..32dbad1 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -178,7 +178,6 @@
EGLSurface mDummySurface;
EGLContext mProtectedEGLContext;
EGLSurface mProtectedDummySurface;
- GLuint mProtectedTexName;
GLint mMaxViewportDims[2];
GLint mMaxTextureSize;
GLuint mVpWidth;
diff --git a/libs/ui/Gralloc4.cpp b/libs/ui/Gralloc4.cpp
index 6fd4b80..d8e4059 100644
--- a/libs/ui/Gralloc4.cpp
+++ b/libs/ui/Gralloc4.cpp
@@ -77,6 +77,7 @@
outDescriptorInfo->layerCount = layerCount;
outDescriptorInfo->format = static_cast<hardware::graphics::common::V1_2::PixelFormat>(format);
outDescriptorInfo->usage = usage;
+ outDescriptorInfo->reservedSize = 0;
}
} // anonymous namespace
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index cd2a448..bf487c4 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -67,20 +67,19 @@
// ----------------------------------------------------------------------------
Region::Region() {
- mStorage.push_back(Rect(0, 0));
+ mStorage.add(Rect(0,0));
}
Region::Region(const Region& rhs)
+ : mStorage(rhs.mStorage)
{
- mStorage.clear();
- mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
#if defined(VALIDATE_REGIONS)
validate(rhs, "rhs copy-ctor");
#endif
}
Region::Region(const Rect& rhs) {
- mStorage.push_back(rhs);
+ mStorage.add(rhs);
}
Region::~Region()
@@ -101,8 +100,8 @@
* final, correctly ordered region buffer. Each rectangle will be compared with the span directly
* above it, and subdivided to resolve any remaining T-junctions.
*/
-static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, FatVector<Rect>& dst,
- int spanDirection) {
+static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end,
+ Vector<Rect>& dst, int spanDirection) {
dst.clear();
const Rect* current = end - 1;
@@ -110,7 +109,7 @@
// add first span immediately
do {
- dst.push_back(*current);
+ dst.add(*current);
current--;
} while (current->top == lastTop && current >= begin);
@@ -148,12 +147,12 @@
if (prev.right <= left) break;
if (prev.right > left && prev.right < right) {
- dst.push_back(Rect(prev.right, top, right, bottom));
+ dst.add(Rect(prev.right, top, right, bottom));
right = prev.right;
}
if (prev.left > left && prev.left < right) {
- dst.push_back(Rect(prev.left, top, right, bottom));
+ dst.add(Rect(prev.left, top, right, bottom));
right = prev.left;
}
@@ -167,12 +166,12 @@
if (prev.left >= right) break;
if (prev.left > left && prev.left < right) {
- dst.push_back(Rect(left, top, prev.left, bottom));
+ dst.add(Rect(left, top, prev.left, bottom));
left = prev.left;
}
if (prev.right > left && prev.right < right) {
- dst.push_back(Rect(left, top, prev.right, bottom));
+ dst.add(Rect(left, top, prev.right, bottom));
left = prev.right;
}
// if an entry in the previous span is too far left, nothing further right in the
@@ -184,7 +183,7 @@
}
if (left < right) {
- dst.push_back(Rect(left, top, right, bottom));
+ dst.add(Rect(left, top, right, bottom));
}
current--;
@@ -202,14 +201,13 @@
if (r.isEmpty()) return r;
if (r.isRect()) return r;
- FatVector<Rect> reversed;
+ Vector<Rect> reversed;
reverseRectsResolvingJunctions(r.begin(), r.end(), reversed, direction_RTL);
Region outputRegion;
- reverseRectsResolvingJunctions(reversed.data(), reversed.data() + reversed.size(),
- outputRegion.mStorage, direction_LTR);
- outputRegion.mStorage.push_back(
- r.getBounds()); // to make region valid, mStorage must end with bounds
+ reverseRectsResolvingJunctions(reversed.begin(), reversed.end(),
+ outputRegion.mStorage, direction_LTR);
+ outputRegion.mStorage.add(r.getBounds()); // to make region valid, mStorage must end with bounds
#if defined(VALIDATE_REGIONS)
validate(outputRegion, "T-Junction free region");
@@ -224,8 +222,7 @@
validate(*this, "this->operator=");
validate(rhs, "rhs.operator=");
#endif
- mStorage.clear();
- mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
+ mStorage = rhs.mStorage;
return *this;
}
@@ -234,7 +231,7 @@
if (mStorage.size() >= 2) {
const Rect bounds(getBounds());
mStorage.clear();
- mStorage.push_back(bounds);
+ mStorage.add(bounds);
}
return *this;
}
@@ -258,25 +255,25 @@
void Region::clear()
{
mStorage.clear();
- mStorage.push_back(Rect(0, 0));
+ mStorage.add(Rect(0,0));
}
void Region::set(const Rect& r)
{
mStorage.clear();
- mStorage.push_back(r);
+ mStorage.add(r);
}
void Region::set(int32_t w, int32_t h)
{
mStorage.clear();
- mStorage.push_back(Rect(w, h));
+ mStorage.add(Rect(w, h));
}
void Region::set(uint32_t w, uint32_t h)
{
mStorage.clear();
- mStorage.push_back(Rect(w, h));
+ mStorage.add(Rect(w, h));
}
bool Region::isTriviallyEqual(const Region& region) const {
@@ -302,7 +299,8 @@
void Region::addRectUnchecked(int l, int t, int r, int b)
{
Rect rect(l,t,r,b);
- mStorage.insert(mStorage.end() - 1, rect);
+ size_t where = mStorage.size() - 1;
+ mStorage.insertAt(rect, where, 1);
}
// ----------------------------------------------------------------------------
@@ -352,7 +350,7 @@
Region& Region::scaleSelf(float sx, float sy) {
size_t count = mStorage.size();
- Rect* rects = mStorage.data();
+ Rect* rects = mStorage.editArray();
while (count) {
rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f);
rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f);
@@ -457,10 +455,10 @@
class Region::rasterizer : public region_operator<Rect>::region_rasterizer
{
Rect bounds;
- FatVector<Rect>& storage;
+ Vector<Rect>& storage;
Rect* head;
Rect* tail;
- FatVector<Rect> span;
+ Vector<Rect> span;
Rect* cur;
public:
explicit rasterizer(Region& reg)
@@ -487,8 +485,8 @@
flushSpan();
}
if (storage.size()) {
- bounds.top = storage.front().top;
- bounds.bottom = storage.back().bottom;
+ bounds.top = storage.itemAt(0).top;
+ bounds.bottom = storage.top().bottom;
if (storage.size() == 1) {
storage.clear();
}
@@ -496,7 +494,7 @@
bounds.left = 0;
bounds.right = 0;
}
- storage.push_back(bounds);
+ storage.add(bounds);
}
void Region::rasterizer::operator()(const Rect& rect)
@@ -511,15 +509,15 @@
return;
}
}
- span.push_back(rect);
- cur = span.data() + (span.size() - 1);
+ span.add(rect);
+ cur = span.editArray() + (span.size() - 1);
}
void Region::rasterizer::flushSpan()
{
bool merge = false;
if (tail-head == ssize_t(span.size())) {
- Rect const* p = span.data();
+ Rect const* p = span.editArray();
Rect const* q = head;
if (p->top == q->bottom) {
merge = true;
@@ -534,17 +532,17 @@
}
}
if (merge) {
- const int bottom = span.front().bottom;
+ const int bottom = span[0].bottom;
Rect* r = head;
while (r != tail) {
r->bottom = bottom;
r++;
}
} else {
- bounds.left = min(span.front().left, bounds.left);
- bounds.right = max(span.back().right, bounds.right);
- storage.insert(storage.end(), span.begin(), span.end());
- tail = storage.data() + storage.size();
+ bounds.left = min(span.itemAt(0).left, bounds.left);
+ bounds.right = max(span.top().right, bounds.right);
+ storage.appendVector(span);
+ tail = storage.editArray() + storage.size();
head = tail - span.size();
}
span.clear();
@@ -552,7 +550,7 @@
bool Region::validate(const Region& reg, const char* name, bool silent)
{
- if (reg.mStorage.empty()) {
+ if (reg.mStorage.isEmpty()) {
ALOGE_IF(!silent, "%s: mStorage is empty, which is never valid", name);
// return immediately as the code below assumes mStorage is non-empty
return false;
@@ -691,8 +689,9 @@
}
sk_dst.op(sk_lhs, sk_rhs, sk_op);
- if (sk_dst.empty() && dst.empty()) return;
-
+ if (sk_dst.isEmpty() && dst.isEmpty())
+ return;
+
bool same = true;
Region::const_iterator head = dst.begin();
Region::const_iterator const tail = dst.end();
@@ -787,7 +786,7 @@
validate(reg, "translate (before)");
#endif
size_t count = reg.mStorage.size();
- Rect* rects = reg.mStorage.data();
+ Rect* rects = reg.mStorage.editArray();
while (count) {
rects->offsetBy(dx, dy);
rects++;
@@ -867,25 +866,24 @@
ALOGE("Region::unflatten() failed, invalid region");
return BAD_VALUE;
}
- mStorage.clear();
- mStorage.insert(mStorage.begin(), result.mStorage.begin(), result.mStorage.end());
+ mStorage = result.mStorage;
return NO_ERROR;
}
// ----------------------------------------------------------------------------
Region::const_iterator Region::begin() const {
- return mStorage.data();
+ return mStorage.array();
}
Region::const_iterator Region::end() const {
// Workaround for b/77643177
// mStorage should never be empty, but somehow it is and it's causing
// an abort in ubsan
- if (mStorage.empty()) return mStorage.data();
+ if (mStorage.isEmpty()) return mStorage.array();
size_t numRects = isRect() ? 1 : mStorage.size() - 1;
- return mStorage.data() + numRects;
+ return mStorage.array() + numRects;
}
Rect const* Region::getArray(size_t* count) const {
diff --git a/libs/ui/include/ui/FatVector.h b/libs/ui/include/ui/FatVector.h
deleted file mode 100644
index 25fe3a0..0000000
--- a/libs/ui/include/ui/FatVector.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#ifndef ANDROID_REGION_FAT_VECTOR_H
-#define ANDROID_REGION_FAT_VECTOR_H
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <utils/Log.h>
-#include <type_traits>
-
-#include <vector>
-
-namespace android {
-
-template <typename T, size_t SIZE = 4>
-class InlineStdAllocator {
-public:
- struct Allocation {
- private:
- Allocation(const Allocation&) = delete;
- void operator=(const Allocation&) = delete;
-
- public:
- Allocation() {}
- // char array instead of T array, so memory is uninitialized, with no destructors run
- char array[sizeof(T) * SIZE];
- bool inUse = false;
- };
-
- typedef T value_type; // needed to implement std::allocator
- typedef T* pointer; // needed to implement std::allocator
-
- explicit InlineStdAllocator(Allocation& allocation) : mAllocation(allocation) {}
- InlineStdAllocator(const InlineStdAllocator& other) : mAllocation(other.mAllocation) {}
- ~InlineStdAllocator() {}
-
- T* allocate(size_t num, const void* = 0) {
- if (!mAllocation.inUse && num <= SIZE) {
- mAllocation.inUse = true;
- return static_cast<T*>(static_cast<void*>(mAllocation.array));
- } else {
- return static_cast<T*>(static_cast<void*>(malloc(num * sizeof(T))));
- }
- }
-
- void deallocate(pointer p, size_t) {
- if (p == static_cast<T*>(static_cast<void*>(mAllocation.array))) {
- mAllocation.inUse = false;
- } else {
- // 'free' instead of delete here - destruction handled separately
- free(p);
- }
- }
- Allocation& mAllocation;
-};
-
-/**
- * std::vector with SIZE elements preallocated into an internal buffer.
- *
- * Useful for avoiding the cost of malloc in cases where only SIZE or
- * fewer elements are needed in the common case.
- */
-template <typename T, size_t SIZE = 4>
-class FatVector : public std::vector<T, InlineStdAllocator<T, SIZE>> {
-public:
- FatVector()
- : std::vector<T, InlineStdAllocator<T, SIZE>>(InlineStdAllocator<T, SIZE>(mAllocation)) {
- this->reserve(SIZE);
- }
-
- explicit FatVector(size_t capacity) : FatVector() { this->resize(capacity); }
-
-private:
- typename InlineStdAllocator<T, SIZE>::Allocation mAllocation;
-};
-
-} // namespace android
-
-#endif // ANDROID_REGION_FAT_VECTOR_H
diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h
index 6bb7b8d..2db3b10 100644
--- a/libs/ui/include/ui/Region.h
+++ b/libs/ui/include/ui/Region.h
@@ -21,13 +21,13 @@
#include <sys/types.h>
#include <ostream>
+#include <utils/Vector.h>
+
#include <ui/Rect.h>
#include <utils/Flattenable.h>
#include <android-base/macros.h>
-#include "FatVector.h"
-
#include <string>
namespace android {
@@ -180,7 +180,7 @@
// with an extra Rect as the last element which is set to the
// bounds of the region. However, if the region is
// a simple Rect then mStorage contains only that rect.
- FatVector<Rect> mStorage;
+ Vector<Rect> mStorage;
};
@@ -235,3 +235,4 @@
}; // namespace android
#endif // ANDROID_UI_REGION_H
+
diff --git a/libs/ui/include_vndk/ui/FatVector.h b/libs/ui/include_vndk/ui/FatVector.h
deleted file mode 120000
index bf30166..0000000
--- a/libs/ui/include_vndk/ui/FatVector.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/ui/FatVector.h
\ No newline at end of file
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 67d69b4..a58e87c 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -158,13 +158,16 @@
// NOTE: This is only valid if the backend is OpenGL
attrs.push_back(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE);
attrs.push_back(vendorEGL);
+
+ // Context virtualization is only available on GL back-end.
+ // Needed to support threading with GL back-end
+ attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
+ attrs.push_back(EGL_FALSE);
break;
default:
- ALOGV("%s: Requesting Unknown (%d) ANGLE back-end", __FUNCTION__, cnx->angleBackend);
+ ALOGE("%s: Requesting Unknown (%d) ANGLE back-end", __FUNCTION__, cnx->angleBackend);
break;
}
- attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
- attrs.push_back(EGL_FALSE);
return true;
}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index d30c4f1..1f283b1 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -1445,7 +1445,6 @@
ASSERT_EQ(keyArgs.action, verifiedKey.action);
ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
- ASSERT_EQ(keyArgs.eventTime, verifiedKey.eventTimeNanos);
ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
@@ -1453,6 +1452,43 @@
ASSERT_EQ(0, verifiedKey.repeatCount);
}
+TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
+
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+
+ mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+
+ NotifyMotionArgs motionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&motionArgs);
+
+ InputEvent* event = window->consume();
+ ASSERT_NE(event, nullptr);
+
+ std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
+ ASSERT_NE(verified, nullptr);
+ ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
+
+ EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
+ EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
+ EXPECT_EQ(motionArgs.source, verified->source);
+ EXPECT_EQ(motionArgs.displayId, verified->displayId);
+
+ const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
+
+ EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
+ EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
+ EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
+ EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
+ EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
+ EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
+ EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
+}
+
class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
protected:
static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index 3e0f136..b0d3e3b 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -9,7 +9,7 @@
],
aidl: {
- local_include_dirs: ["."],
+ local_include_dirs: ["include"],
include_dirs: [
"frameworks/base/core/java/android/os",
],
@@ -28,6 +28,11 @@
"-Wunused",
"-Wunreachable-code",
],
+
+ local_include_dirs: ["include"],
+ export_include_dirs: [
+ "include",
+ ],
}
cc_test {
diff --git a/include/android/CoolingDevice.h b/services/powermanager/include/android/CoolingDevice.h
similarity index 100%
rename from include/android/CoolingDevice.h
rename to services/powermanager/include/android/CoolingDevice.h
diff --git a/include/android/Temperature.h b/services/powermanager/include/android/Temperature.h
similarity index 100%
rename from include/android/Temperature.h
rename to services/powermanager/include/android/Temperature.h
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d7ec868..e4d754c 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -485,6 +485,10 @@
}
}
+ if (recomputeVisibleRegions == true) {
+ maybeDirtyInput();
+ }
+
return true;
}
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 18f7f44..fac9024 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -441,7 +441,7 @@
mQueueItemCondition.broadcast();
}
- mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
+ mFlinger->mInterceptor->saveBufferUpdate(layerId, item.mGraphicBuffer->getWidth(),
item.mGraphicBuffer->getHeight(), item.mFrameNumber);
mFlinger->signalLayerUpdate();
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 64cfb3d..3765d0d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -993,6 +993,9 @@
commitTransaction(c);
mPendingStatesSnapshot = mPendingStates;
mCurrentState.callbackHandles = {};
+
+ maybeDirtyInput();
+
return flags;
}
@@ -2472,6 +2475,32 @@
}
}
+bool Layer::maybeDirtyInput() {
+ // No sense redirtying input.
+ if (mFlinger->inputDirty()) return true;
+
+ if (hasInput()) {
+ mFlinger->dirtyInput();
+ return true;
+ }
+
+ // If a child or relative dirties the input, no sense continuing to traverse
+ // so we return early and halt the recursion. We traverse ourselves instead
+ // of using traverse() so we can implement this early halt.
+ for (const sp<Layer>& child : mDrawingChildren) {
+ if (child->maybeDirtyInput()) {
+ return true;
+ }
+ }
+ for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) {
+ sp<Layer> relative = weakRelative.promote();
+ if (relative && relative->maybeDirtyInput()) {
+ return true;
+ }
+ }
+ return false;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 20d7232..e21a866 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -997,6 +997,10 @@
// Window types from WindowManager.LayoutParams
const int mWindowType;
+ // Called when mDrawingState has changed. If we or one of our children/relatives hasInput()
+ // then we will dirty the setInputWindows cache.
+ bool maybeDirtyInput();
+
private:
/**
* Returns an unsorted vector of all layers that are part of this tree.
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index d3364a0..e6c8654 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -120,7 +120,7 @@
// We latch the transparent region here, instead of above where we latch
// the rest of the geometry because it is only content but not necessarily
// resize dependent.
- if (!mFront.activeTransparentRegion_legacy.isTriviallyEqual(
+ if (!mFront.activeTransparentRegion_legacy.hasSameRects(
mFront.requestedTransparentRegion_legacy)) {
mFront.activeTransparentRegion_legacy = mFront.requestedTransparentRegion_legacy;
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 682679c..c675971 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -168,9 +168,9 @@
}
void RefreshRateOverlay::primeCache() {
- auto allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates();
+ auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates();
if (allRefreshRates.size() == 1) {
- auto fps = allRefreshRates.begin()->second.fps;
+ auto fps = allRefreshRates.begin()->second->fps;
half4 color = {LOW_FPS_COLOR, ALPHA};
mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
return;
@@ -178,8 +178,8 @@
std::vector<uint32_t> supportedFps;
supportedFps.reserve(allRefreshRates.size());
- for (auto [ignored, refreshRate] : allRefreshRates) {
- supportedFps.push_back(refreshRate.fps);
+ for (auto& [ignored, refreshRate] : allRefreshRates) {
+ supportedFps.push_back(refreshRate->fps);
}
std::sort(supportedFps.begin(), supportedFps.end());
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index 6ef6ce4..8a14572 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -212,7 +212,5 @@
for (const auto& [layer, info] : activeLayers()) {
info->clearHistory();
}
-
- mActiveLayersEnd = 0;
}
} // namespace android::scheduler::impl
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 63d9c4b..c04447d 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -71,10 +71,10 @@
std::unordered_map<float, Offsets> offsets;
for (const auto& [ignored, refreshRate] : refreshRateConfigs.getAllRefreshRates()) {
- if (refreshRate.fps > 65.0f) {
- offsets.emplace(refreshRate.fps, getHighFpsOffsets(refreshRate.vsyncPeriod));
+ if (refreshRate->fps > 65.0f) {
+ offsets.emplace(refreshRate->fps, getHighFpsOffsets(refreshRate->vsyncPeriod));
} else {
- offsets.emplace(refreshRate.fps, getDefaultOffsets(refreshRate.vsyncPeriod));
+ offsets.emplace(refreshRate->fps, getDefaultOffsets(refreshRate->vsyncPeriod));
}
}
return offsets;
@@ -238,7 +238,7 @@
refreshRates.reserve(allRefreshRates.size());
for (const auto& [ignored, refreshRate] : allRefreshRates) {
- refreshRates.emplace_back(refreshRate.fps);
+ refreshRates.emplace_back(refreshRate->fps);
}
return refreshRates;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 15b158d..02d0b53 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -23,6 +23,9 @@
#include <chrono>
#include <cmath>
+#undef LOG_TAG
+#define LOG_TAG "RefreshRateConfigs"
+
namespace android::scheduler {
using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType;
@@ -95,22 +98,19 @@
}
const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2(
- const std::vector<LayerRequirement>& layers, bool touchActive) const {
+ const std::vector<LayerRequirement>& layers, bool touchActive,
+ bool* touchConsidered) const {
ATRACE_CALL();
ALOGV("getRefreshRateForContent %zu layers", layers.size());
+ *touchConsidered = false;
std::lock_guard lock(mLock);
- // For now if the touch is active return the peak refresh rate
- // This should be optimized to consider other layers as well.
- if (touchActive) {
- return *mAvailableRefreshRates.back();
- }
-
// If there are not layers, there is not content detection, so return the current
// refresh rate.
if (layers.empty()) {
- return getCurrentRefreshRateByPolicyLocked();
+ *touchConsidered = touchActive;
+ return touchActive ? *mAvailableRefreshRates.back() : getCurrentRefreshRateByPolicyLocked();
}
int noVoteLayers = 0;
@@ -118,17 +118,30 @@
int maxVoteLayers = 0;
int explicitDefaultVoteLayers = 0;
int explicitExactOrMultipleVoteLayers = 0;
+ float maxExplicitWeight = 0;
for (const auto& layer : layers) {
- if (layer.vote == LayerVoteType::NoVote)
+ if (layer.vote == LayerVoteType::NoVote) {
noVoteLayers++;
- else if (layer.vote == LayerVoteType::Min)
+ } else if (layer.vote == LayerVoteType::Min) {
minVoteLayers++;
- else if (layer.vote == LayerVoteType::Max)
+ } else if (layer.vote == LayerVoteType::Max) {
maxVoteLayers++;
- else if (layer.vote == LayerVoteType::ExplicitDefault)
+ } else if (layer.vote == LayerVoteType::ExplicitDefault) {
explicitDefaultVoteLayers++;
- else if (layer.vote == LayerVoteType::ExplicitExactOrMultiple)
+ maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+ } else if (layer.vote == LayerVoteType::ExplicitExactOrMultiple) {
explicitExactOrMultipleVoteLayers++;
+ maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+ }
+ }
+
+ // Consider the touch event if there are no ExplicitDefault layers.
+ // ExplicitDefault are mostly interactive (as opposed to ExplicitExactOrMultiple)
+ // and therefore if those posted an explicit vote we should not change it
+ // if get get a touch event.
+ if (touchActive && explicitDefaultVoteLayers == 0) {
+ *touchConsidered = true;
+ return *mAvailableRefreshRates.back();
}
// Only if all layers want Min we should return Min
@@ -168,16 +181,17 @@
const auto layerPeriod = round<nsecs_t>(1e9f / layer.desiredRefreshRate);
if (layer.vote == LayerVoteType::ExplicitDefault) {
const auto layerScore = [&]() {
- const auto [displayFramesQuot, displayFramesRem] =
- getDisplayFrames(layerPeriod, displayPeriod);
- if (displayFramesQuot == 0) {
- // Layer desired refresh rate is higher the display rate.
- return static_cast<float>(layerPeriod) / static_cast<float>(displayPeriod);
+ // Find the actual rate the layer will render, assuming
+ // that layerPeriod is the minimal time to render a frame
+ auto actualLayerPeriod = displayPeriod;
+ int multiplier = 1;
+ while (layerPeriod > actualLayerPeriod + MARGIN_FOR_PERIOD_CALCULATION) {
+ multiplier++;
+ actualLayerPeriod = displayPeriod * multiplier;
}
-
- return 1.0f -
- (static_cast<float>(displayFramesRem) /
- static_cast<float>(layerPeriod));
+ return std::min(1.0f,
+ static_cast<float>(layerPeriod) /
+ static_cast<float>(actualLayerPeriod));
}();
ALOGV("%s (ExplicitDefault, weight %.2f) %.2fHz gives %s score of %.2f",
@@ -240,6 +254,7 @@
template <typename Iter>
const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) const {
+ constexpr auto EPSILON = 0.001f;
const RefreshRate* bestRefreshRate = begin->first;
float max = begin->second;
for (auto i = begin; i != end; ++i) {
@@ -248,7 +263,7 @@
ATRACE_INT(refreshRate->name.c_str(), round<int>(score * 100));
- if (score > max) {
+ if (score > max * (1 + EPSILON)) {
max = score;
bestRefreshRate = refreshRate;
}
@@ -286,12 +301,12 @@
mCurrentRefreshRate) != mAvailableRefreshRates.end()) {
return *mCurrentRefreshRate;
}
- return mRefreshRates.at(mDefaultConfig);
+ return *mRefreshRates.at(mDefaultConfig);
}
void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) {
std::lock_guard lock(mLock);
- mCurrentRefreshRate = &mRefreshRates.at(configId);
+ mCurrentRefreshRate = mRefreshRates.at(configId).get();
}
RefreshRateConfigs::RefreshRateConfigs(const std::vector<InputConfig>& configs,
@@ -326,7 +341,7 @@
if (mRefreshRates.count(defaultConfigId) == 0) {
return BAD_VALUE;
}
- const RefreshRate& refreshRate = mRefreshRates.at(defaultConfigId);
+ const RefreshRate& refreshRate = *mRefreshRates.at(defaultConfigId);
if (!refreshRate.inPolicy(minRefreshRate, maxRefreshRate)) {
return BAD_VALUE;
}
@@ -361,10 +376,10 @@
outRefreshRates->clear();
outRefreshRates->reserve(mRefreshRates.size());
for (const auto& [type, refreshRate] : mRefreshRates) {
- if (shouldAddRefreshRate(refreshRate)) {
+ if (shouldAddRefreshRate(*refreshRate)) {
ALOGV("getSortedRefreshRateList: config %d added to list policy",
- refreshRate.configId.value());
- outRefreshRates->push_back(&refreshRate);
+ refreshRate->configId.value());
+ outRefreshRates->push_back(refreshRate.get());
}
}
@@ -376,7 +391,7 @@
void RefreshRateConfigs::constructAvailableRefreshRates() {
// Filter configs based on current policy and sort based on vsync period
- HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig).configGroup;
+ HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig)->configGroup;
ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f",
mDefaultConfig.value(), group.value(), mMinRefreshRateFps, mMaxRefreshRateFps);
getSortedRefreshRateList(
@@ -403,16 +418,15 @@
LOG_ALWAYS_FATAL_IF(configs.empty());
LOG_ALWAYS_FATAL_IF(currentHwcConfig.value() >= configs.size());
- auto buildRefreshRate = [&](InputConfig config) -> RefreshRate {
- const float fps = 1e9f / config.vsyncPeriod;
- return RefreshRate(config.configId, config.vsyncPeriod, config.configGroup,
- base::StringPrintf("%2.ffps", fps), fps);
- };
-
for (const auto& config : configs) {
- mRefreshRates.emplace(config.configId, buildRefreshRate(config));
+ const float fps = 1e9f / config.vsyncPeriod;
+ mRefreshRates.emplace(config.configId,
+ std::make_unique<RefreshRate>(config.configId, config.vsyncPeriod,
+ config.configGroup,
+ base::StringPrintf("%2.ffps", fps),
+ fps));
if (config.configId == currentHwcConfig) {
- mCurrentRefreshRate = &mRefreshRates.at(config.configId);
+ mCurrentRefreshRate = mRefreshRates.at(config.configId).get();
}
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index c8aec86..87d4389 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -59,6 +59,8 @@
configGroup(configGroup),
name(std::move(name)),
fps(fps) {}
+
+ RefreshRate(const RefreshRate&) = delete;
// This config ID corresponds to the position of the config in the vector that is stored
// on the device.
const HwcConfigIndexType configId;
@@ -85,7 +87,8 @@
bool operator==(const RefreshRate& other) const { return !(*this != other); }
};
- using AllRefreshRatesMapType = std::unordered_map<HwcConfigIndexType, const RefreshRate>;
+ using AllRefreshRatesMapType =
+ std::unordered_map<HwcConfigIndexType, std::unique_ptr<const RefreshRate>>;
// Sets the current policy to choose refresh rates. Returns NO_ERROR if the requested policy is
// valid, or a negative error value otherwise. policyChanged, if non-null, will be set to true
@@ -134,9 +137,11 @@
// Returns the refresh rate that fits best to the given layers. This function also gets a
// boolean flag that indicates whether user touched the screen recently to be factored in when
- // choosing the refresh rate.
+ // choosing the refresh rate and returns whether the refresh rate was chosen as a result of
+ // a touch event.
const RefreshRate& getRefreshRateForContentV2(const std::vector<LayerRequirement>& layers,
- bool touchActive) const EXCLUDES(mLock);
+ bool touchActive, bool* touchConsidered) const
+ EXCLUDES(mLock);
// Returns all the refresh rates supported by the device. This won't change at runtime.
const AllRefreshRatesMapType& getAllRefreshRates() const EXCLUDES(mLock);
@@ -163,7 +168,7 @@
// Returns the refresh rate that corresponds to a HwcConfigIndexType. This won't change at
// runtime.
const RefreshRate& getRefreshRateFromConfigId(HwcConfigIndexType configId) const {
- return mRefreshRates.at(configId);
+ return *mRefreshRates.at(configId);
};
// Stores the current configId the device operates at
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 5444239..920f0ec 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -463,7 +463,7 @@
return;
}
mFeatures.configId = newConfigId;
- auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
+ auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
mSchedulerCallback.changeRefreshRate(newRefreshRate, ConfigEvent::Changed);
}
}
@@ -483,7 +483,7 @@
// that is currently on top. b/142507166 will give us this capability.
std::lock_guard<std::mutex> lock(mFeatureStateLock);
if (mLayerHistory) {
- mLayerHistory->clear();
+ // Layer History will be cleared based on RefreshRateConfigs::getRefreshRateForContentV2
mTouchTimer->reset();
@@ -515,7 +515,7 @@
// TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate
// magic number
- const auto refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
+ const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
constexpr float FPS_THRESHOLD_FOR_KERNEL_TIMER = 65.0f;
if (state == TimerState::Reset && refreshRate.fps > FPS_THRESHOLD_FOR_KERNEL_TIMER) {
// If we're not in performance mode then the kernel timer shouldn't do
@@ -620,10 +620,21 @@
return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements).configId;
}
- return mRefreshRateConfigs
- .getRefreshRateForContentV2(mFeatures.contentRequirements,
- mTouchTimer && mFeatures.touch == TouchState::Active)
- .configId;
+ bool touchConsidered;
+ const auto& ret =
+ mRefreshRateConfigs
+ .getRefreshRateForContentV2(mFeatures.contentRequirements,
+ mTouchTimer &&
+ mFeatures.touch == TouchState::Active,
+ &touchConsidered)
+ .configId;
+ if (touchConsidered) {
+ // Clear layer history if refresh rate was selected based on touch to allow
+ // the hueristic to pick up with the new rate.
+ mLayerHistory->clear();
+ }
+
+ return ret;
}
std::optional<HwcConfigIndexType> Scheduler::getPreferredConfigId() {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5a73727..224f093 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -908,7 +908,7 @@
void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) {
ATRACE_CALL();
- auto refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId);
+ auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId);
ALOGV("setDesiredActiveConfig(%s)", refreshRate.name.c_str());
std::lock_guard<std::mutex> lock(mActiveConfigLock);
@@ -989,7 +989,7 @@
mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
display->setActiveConfig(mUpcomingActiveConfig.configId);
- auto refreshRate =
+ auto& refreshRate =
mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId);
mPhaseConfiguration->setRefreshRateFps(refreshRate.fps);
mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets());
@@ -1009,7 +1009,7 @@
mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
mDesiredActiveConfigChanged = false;
- auto const refreshRate =
+ const auto& refreshRate =
mRefreshRateConfigs->getRefreshRateFromConfigId(mDesiredActiveConfig.configId);
mScheduler->resyncToHardwareVsync(true, refreshRate.vsyncPeriod);
mPhaseConfiguration->setRefreshRateFps(refreshRate.fps);
@@ -1042,7 +1042,7 @@
desiredActiveConfig = mDesiredActiveConfig;
}
- auto refreshRate =
+ auto& refreshRate =
mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig.configId);
ALOGV("performSetActiveConfig changing active config to %d(%s)", refreshRate.configId.value(),
refreshRate.name.c_str());
@@ -2785,6 +2785,19 @@
void SurfaceFlinger::updateInputWindowInfo() {
std::vector<InputWindowInfo> inputHandles;
+ // We use a simple caching algorithm here. mInputDirty begins as true,
+ // after we call setInputWindows we set it to false, so
+ // in the future we wont call it again.. We set input dirty to true again
+ // when any layer that hasInput() has a transaction performed on it
+ // or when any parent or relative parent of such a layer has a transaction
+ // performed on it. Not all of these transactions will really result in
+ // input changes but all input changes will spring from these transactions
+ // so the cache is safe but not optimal. It seems like it might be annoyingly
+ // costly to cache and comapre the actual InputWindowHandle vector though.
+ if (!mInputDirty) {
+ return;
+ }
+
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (layer->hasInput()) {
// When calculating the screen bounds we ignore the transparent region since it may
@@ -2796,10 +2809,12 @@
mInputFlinger->setInputWindows(inputHandles,
mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
: nullptr);
+
+ mInputDirty = false;
}
void SurfaceFlinger::commitInputWindowCommands() {
- mInputWindowCommands = mPendingInputWindowCommands;
+ mInputWindowCommands.merge(mPendingInputWindowCommands);
mPendingInputWindowCommands.clear();
}
@@ -3736,10 +3751,6 @@
uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) {
uint32_t flags = 0;
- if (!inputWindowCommands.transferTouchFocusCommands.empty()) {
- flags |= eTraversalNeeded;
- }
-
if (inputWindowCommands.syncInputWindows) {
flags |= eTraversalNeeded;
}
@@ -5144,7 +5155,7 @@
n = data.readInt32();
if (n == 1 && !mRefreshRateOverlay) {
mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this);
- auto current = mRefreshRateConfigs->getCurrentRefreshRate();
+ auto& current = mRefreshRateConfigs->getCurrentRefreshRate();
mRefreshRateOverlay->changeRefreshRate(current);
} else if (n == 0) {
mRefreshRateOverlay.reset();
@@ -5193,7 +5204,7 @@
if (mRefreshRateOverlay) {
const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false);
const bool timerExpired = kernelTimerEnabled && expired;
- const auto& current = [this]() {
+ const auto& current = [this]() -> const RefreshRate& {
std::lock_guard<std::mutex> lock(mActiveConfigLock);
if (mDesiredActiveConfigChanged) {
return mRefreshRateConfigs->getRefreshRateFromConfigId(
@@ -5774,6 +5785,7 @@
Mutex::Autolock _l(mStateLock);
mPendingSyncInputWindows = false;
+
mTransactionCV.broadcast();
}
@@ -5873,7 +5885,7 @@
display->getActiveConfig(), vsyncPeriod);
auto configId = mScheduler->getPreferredConfigId();
- auto preferredRefreshRate = configId
+ auto& preferredRefreshRate = configId
? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId)
// NOTE: Choose the default config ID, if Scheduler doesn't have one in mind.
: mRefreshRateConfigs->getRefreshRateFromConfigId(defaultConfig);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 7586793..e892faf 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1241,6 +1241,11 @@
// janky frames there are.
nsecs_t mMissedFrameJankStart = 0;
int32_t mMissedFrameJankCount = 0;
+
+ // See updateInputWindowInfo() for details
+ std::atomic<bool> mInputDirty = true;
+ void dirtyInput() { mInputDirty = true; }
+ bool inputDirty() { return mInputDirty; }
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 1f9d46c..5b3cd69 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -524,11 +524,11 @@
deletion->set_id(getLayerId(layer));
}
-void SurfaceInterceptor::addBufferUpdateLocked(Increment* increment, const sp<const Layer>& layer,
+void SurfaceInterceptor::addBufferUpdateLocked(Increment* increment, int32_t layerId,
uint32_t width, uint32_t height, uint64_t frameNumber)
{
BufferUpdate* update(increment->mutable_buffer_update());
- update->set_id(getLayerId(layer));
+ update->set_id(layerId);
update->set_w(width);
update->set_h(height);
update->set_frame_number(frameNumber);
@@ -644,15 +644,22 @@
addSurfaceDeletionLocked(createTraceIncrementLocked(), layer);
}
-void SurfaceInterceptor::saveBufferUpdate(const sp<const Layer>& layer, uint32_t width,
+/**
+ * Here we pass the layer by ID instead of by sp<> since this is called without
+ * holding the state-lock from a Binder thread. If we required the caller
+ * to pass 'this' by sp<> the temporary sp<> constructed could end up
+ * being the last reference and we might accidentally destroy the Layer
+ * from this binder thread.
+ */
+void SurfaceInterceptor::saveBufferUpdate(int32_t layerId, uint32_t width,
uint32_t height, uint64_t frameNumber)
{
- if (!mEnabled || layer == nullptr) {
+ if (!mEnabled) {
return;
}
ATRACE_CALL();
std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- addBufferUpdateLocked(createTraceIncrementLocked(), layer, width, height, frameNumber);
+ addBufferUpdateLocked(createTraceIncrementLocked(), layerId, width, height, frameNumber);
}
void SurfaceInterceptor::saveVSyncEvent(nsecs_t timestamp) {
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index a665f62..896bdcc 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -67,7 +67,7 @@
// Intercept surface data
virtual void saveSurfaceCreation(const sp<const Layer>& layer) = 0;
virtual void saveSurfaceDeletion(const sp<const Layer>& layer) = 0;
- virtual void saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height,
+ virtual void saveBufferUpdate(int32_t layerId, uint32_t width, uint32_t height,
uint64_t frameNumber) = 0;
// Intercept display data
@@ -102,7 +102,7 @@
// Intercept surface data
void saveSurfaceCreation(const sp<const Layer>& layer) override;
void saveSurfaceDeletion(const sp<const Layer>& layer) override;
- void saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height,
+ void saveBufferUpdate(int32_t layerId, uint32_t width, uint32_t height,
uint64_t frameNumber) override;
// Intercept display data
@@ -130,7 +130,7 @@
Increment* createTraceIncrementLocked();
void addSurfaceCreationLocked(Increment* increment, const sp<const Layer>& layer);
void addSurfaceDeletionLocked(Increment* increment, const sp<const Layer>& layer);
- void addBufferUpdateLocked(Increment* increment, const sp<const Layer>& layer, uint32_t width,
+ void addBufferUpdateLocked(Increment* increment, int32_t layerId, uint32_t width,
uint32_t height, uint64_t frameNumber);
void addVSyncUpdateLocked(Increment* increment, nsecs_t timestamp);
void addDisplayCreationLocked(Increment* increment, const DisplayDeviceState& info);
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index e7e7f66..dd04076 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -21,6 +21,7 @@
#include <log/log.h>
#include <thread>
+#include "../../Scheduler/RefreshRateConfigs.h"
#include "DisplayHardware/HWC2.h"
#include "Scheduler/RefreshRateConfigs.h"
@@ -93,8 +94,8 @@
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
- const auto minRate = refreshRateConfigs->getMinRefreshRate();
- const auto performanceRate = refreshRateConfigs->getMaxRefreshRate();
+ const auto& minRate = refreshRateConfigs->getMinRefreshRate();
+ const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate();
RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
ASSERT_EQ(expectedDefaultConfig, minRate);
@@ -102,8 +103,8 @@
90};
ASSERT_EQ(expectedPerformanceConfig, performanceRate);
- const auto minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy();
- const auto performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy();
+ const auto& minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy();
+ const auto& performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy();
ASSERT_EQ(minRateByPolicy, minRate);
ASSERT_EQ(performanceRateByPolicy, performanceRate);
}
@@ -115,10 +116,10 @@
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
- const auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
- const auto performanceRate = refreshRateConfigs->getMaxRefreshRate();
- const auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
- const auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
+ const auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
+ const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate();
+ const auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
+ const auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
ASSERT_EQ(expectedDefaultConfig, minRate);
@@ -128,8 +129,8 @@
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 60, 90, nullptr), 0);
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
- const auto minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy();
- const auto performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy();
+ const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy();
+ const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy();
RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_1, "90fps",
90};
@@ -145,8 +146,8 @@
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
- auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
- auto performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy();
+ auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
+ auto& performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy();
RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
ASSERT_EQ(expectedDefaultConfig, minRate);
@@ -156,8 +157,8 @@
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0);
- auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
- auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
+ auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
+ auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
ASSERT_EQ(expectedDefaultConfig, minRate60);
ASSERT_EQ(expectedDefaultConfig, performanceRate60);
}
@@ -169,19 +170,19 @@
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
{
- auto current = refreshRateConfigs->getCurrentRefreshRate();
+ auto& current = refreshRateConfigs->getCurrentRefreshRate();
EXPECT_EQ(current.configId, HWC_CONFIG_ID_60);
}
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
{
- auto current = refreshRateConfigs->getCurrentRefreshRate();
+ auto& current = refreshRateConfigs->getCurrentRefreshRate();
EXPECT_EQ(current.configId, HWC_CONFIG_ID_90);
}
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 0);
{
- auto current = refreshRateConfigs->getCurrentRefreshRate();
+ auto& current = refreshRateConfigs->getCurrentRefreshRate();
EXPECT_EQ(current.configId, HWC_CONFIG_ID_90);
}
}
@@ -248,6 +249,7 @@
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_noLayers) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
@@ -263,16 +265,17 @@
auto layers = std::vector<LayerRequirement>{};
EXPECT_EQ(expected72Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/
- false));
+ false, &ignored));
// Current refresh rate can always be changed.
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60);
EXPECT_EQ(expected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/
- false));
+ false, &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_90) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -288,134 +291,163 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
lr.name = "45Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
lr.name = "30Hz Heuristic";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
lr.name = "24Hz Heuristic";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.name = "";
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0);
lr.vote = LayerVoteType::Min;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 0);
lr.vote = LayerVoteType::Min;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 0, 120, nullptr), 0);
lr.vote = LayerVoteType::Min;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_72_90) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
@@ -432,35 +464,43 @@
lr.vote = LayerVoteType::Min;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90_120) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
@@ -486,24 +526,28 @@
lr2.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48.0f;
lr2.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48.0f;
lr2.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_DifferentTypes) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
@@ -531,7 +575,8 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -540,7 +585,8 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -549,7 +595,8 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "60Hz ExplicitDefault";
EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -558,7 +605,8 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -567,7 +615,8 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -576,7 +625,8 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
@@ -585,7 +635,8 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -594,7 +645,8 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -603,10 +655,12 @@
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.name = "90Hz ExplicitExactOrMultiple";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}}};
@@ -621,35 +675,43 @@
lr.vote = LayerVoteType::Min;
EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
@@ -669,57 +731,71 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
lr.name = "45Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
lr.name = "30Hz Heuristic";
EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
lr.name = "24Hz Heuristic";
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.name = "24Hz ExplicitExactOrMultiple";
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_PriorityTest) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
@@ -739,48 +815,56 @@
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Max;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 15.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 30.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_24FpsVideo) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -798,7 +882,8 @@
for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) {
lr.desiredRefreshRate = fps;
const auto& refreshRate =
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false);
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored);
printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str());
EXPECT_EQ(expected60Config, refreshRate);
}
@@ -833,6 +918,7 @@
}
TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Explicit) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -852,21 +938,24 @@
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 90.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, testInPolicy) {
@@ -880,6 +969,7 @@
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_75HzContent) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -897,13 +987,15 @@
for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) {
lr.desiredRefreshRate = fps;
const auto& refreshRate =
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false);
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored);
printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str());
EXPECT_EQ(expected90Config, refreshRate);
}
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -925,7 +1017,8 @@
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
@@ -934,7 +1027,8 @@
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz ExplicitDefault";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
@@ -942,7 +1036,8 @@
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30.0f;
@@ -951,7 +1046,8 @@
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30.0f;
@@ -959,10 +1055,12 @@
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -982,28 +1080,32 @@
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, false));
+ EXPECT_EQ(expected60Config,
+ refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, true));
+ EXPECT_EQ(expected90Config,
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, true));
+ EXPECT_EQ(expected90Config,
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, false));
+ EXPECT_EQ(expected90Config,
+ refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored));
// The other layer starts to provide buffers
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -1012,7 +1114,108 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, false));
+ EXPECT_EQ(expected90Config,
+ refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored));
+}
+
+TEST_F(RefreshRateConfigsTest, touchConsidered) {
+ bool touchConsidered;
+ std::vector<RefreshRateConfigs::InputConfig> configs{
+ {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
+ {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ refreshRateConfigs->getRefreshRateForContentV2({}, false, &touchConsidered);
+ EXPECT_EQ(false, touchConsidered);
+
+ refreshRateConfigs->getRefreshRateForContentV2({}, true, &touchConsidered);
+ EXPECT_EQ(true, touchConsidered);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
+ LayerRequirement{.weight = 1.0f}};
+ auto& lr1 = layers[0];
+ auto& lr2 = layers[1];
+
+ lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr1.desiredRefreshRate = 60.0f;
+ lr1.name = "60Hz ExplicitExactOrMultiple";
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "NoVote";
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ EXPECT_EQ(true, touchConsidered);
+
+ lr1.vote = LayerVoteType::ExplicitDefault;
+ lr1.desiredRefreshRate = 60.0f;
+ lr1.name = "60Hz ExplicitExactOrMultiple";
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "NoVote";
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ EXPECT_EQ(false, touchConsidered);
+
+ lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr1.desiredRefreshRate = 60.0f;
+ lr1.name = "60Hz ExplicitExactOrMultiple";
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "NoVote";
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ EXPECT_EQ(true, touchConsidered);
+
+ lr1.vote = LayerVoteType::ExplicitDefault;
+ lr1.desiredRefreshRate = 60.0f;
+ lr1.name = "60Hz ExplicitExactrMultiple";
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "NoVote";
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ EXPECT_EQ(false, touchConsidered);
+}
+
+TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_ExplicitDefault) {
+ bool ignored;
+ std::vector<RefreshRateConfigs::InputConfig> configs{
+ {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
+ {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
+ {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90},
+ {HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}};
+
+ auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/
+ HWC_CONFIG_ID_60);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ auto& lr = layers[0];
+
+ // Prepare a table with the vote and the expected refresh rate
+ const std::vector<std::pair<float, float>> testCases = {
+ {130, 120}, {120, 120}, {119, 120}, {110, 120},
+
+ {100, 90}, {90, 90}, {89, 90},
+
+ {80, 72}, {73, 72}, {72, 72}, {71, 72}, {70, 72},
+
+ {65, 60}, {60, 60}, {59, 60}, {58, 60},
+
+ {55, 90}, {50, 90}, {45, 90},
+
+ {42, 120}, {40, 120}, {39, 120},
+
+ {37, 72}, {36, 72}, {35, 72},
+
+ {30, 60},
+ };
+
+ for (const auto& test : testCases) {
+ lr.vote = LayerVoteType::ExplicitDefault;
+ lr.desiredRefreshRate = test.first;
+
+ std::stringstream ss;
+ ss << "ExplicitDefault " << test.first << " fps";
+ lr.name = ss.str();
+
+ const auto& refreshRate =
+ refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored);
+ EXPECT_FLOAT_EQ(refreshRate.fps, test.second)
+ << "Expecting " << test.first << "fps => " << test.second << "Hz";
+ }
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h b/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h
index 458b2f3..5beee1c 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h
@@ -39,7 +39,7 @@
const Vector<DisplayState>&, uint32_t));
MOCK_METHOD1(saveSurfaceCreation, void(const sp<const Layer>&));
MOCK_METHOD1(saveSurfaceDeletion, void(const sp<const Layer>&));
- MOCK_METHOD4(saveBufferUpdate, void(const sp<const Layer>&, uint32_t, uint32_t, uint64_t));
+ MOCK_METHOD4(saveBufferUpdate, void(int32_t, uint32_t, uint32_t, uint64_t));
MOCK_METHOD1(saveDisplayCreation, void(const DisplayDeviceState&));
MOCK_METHOD1(saveDisplayDeletion, void(int32_t));
MOCK_METHOD2(savePowerModeUpdate, void(int32_t, int32_t));