Add compatibility param to setFrameRate() api

Add a compatiblity param to the setFrameRate() api, so the system has
more info to decide the device frame rate when there are multiple
competing preferences.

I also changed the plumbing for setFrameRate() to go directly to surface
flinger, instead of through buffer queue. We're trying to avoid changes
to buffer queue code, to avoid disturbing the prebuilts.

Bug: 137287430

Test: Added new cts tests to verify behavior of the compatibility param.
      cts-tradefed run commandAndExit cts-dev --module CtsGraphicsTestCases --test android.graphics.cts.SetFrameRateTest

Test: /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test --gtest_filter='SetFrameRateTest.*'

Change-Id: Ibe75a778fb459d4138a1446c1b38b44798b56a99
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 5547efc..a9c9b74 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -24,6 +24,8 @@
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/LayerState.h>
 
+#include <cmath>
+
 namespace android {
 
 status_t layer_state_t::write(Parcel& output) const
@@ -113,6 +115,7 @@
     output.writeFloat(shadowRadius);
     output.writeInt32(frameRateSelectionPriority);
     output.writeFloat(frameRate);
+    output.writeByte(frameRateCompatibility);
     return NO_ERROR;
 }
 
@@ -194,6 +197,7 @@
     shadowRadius = input.readFloat();
     frameRateSelectionPriority = input.readInt32();
     frameRate = input.readFloat();
+    frameRateCompatibility = input.readByte();
     return NO_ERROR;
 }
 
@@ -427,6 +431,7 @@
     if (other.what & eFrameRateChanged) {
         what |= eFrameRateChanged;
         frameRate = other.frameRate;
+        frameRateCompatibility = other.frameRateCompatibility;
     }
     if ((other.what & what) != other.what) {
         ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
@@ -474,4 +479,21 @@
     syncInputWindows = input.readBool();
 }
 
+bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName) {
+    const char* functionName = inFunctionName != nullptr ? inFunctionName : "call";
+    int floatClassification = std::fpclassify(frameRate);
+    if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) {
+        ALOGE("%s failed - invalid frame rate %f", functionName, frameRate);
+        return false;
+    }
+
+    if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT &&
+        compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) {
+        ALOGE("%s failed - invalid compatibility value %d", functionName, compatibility);
+        return false;
+    }
+
+    return true;
+}
+
 }; // namespace android