SF: Adding statistical mode

- Adding statistical mode for timestamp intervals.
- Moving math calculations into util class, and adding a unit test.

See go/surface-flinger-scheduler for more info and systrace links.

Test: SF tests pass. Adding new test class.
Bug: 113612090
Change-Id: I3c3a73e3d8719e47326d8a48d27683037b7beb47
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 58f1e9c..28f3ef2 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -31,6 +31,7 @@
         "EventThreadTest.cpp",
         "LayerHistoryTest.cpp",
         "SchedulerTest.cpp",
+        "SchedulerUtilsTest.cpp",
         "mock/DisplayHardware/MockComposer.cpp",
         "mock/DisplayHardware/MockDisplaySurface.cpp",
         "mock/DisplayHardware/MockPowerAdvisor.cpp",
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index e967742..d0cf1b7 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -59,8 +59,6 @@
     SchedulerTest();
     ~SchedulerTest() override;
 
-    int64_t calculateMedian(std::vector<int64_t>* v);
-
     sp<Scheduler::ConnectionHandle> mConnectionHandle;
     mock::DispSync* mPrimaryDispSync = new mock::DispSync();
     mock::EventThread* mEventThread;
@@ -97,10 +95,6 @@
     ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
 }
 
-int64_t SchedulerTest::calculateMedian(std::vector<int64_t>* v) {
-    return mScheduler->calculateMedian(v);
-}
-
 namespace {
 /* ------------------------------------------------------------------------
  * Test cases
@@ -190,38 +184,5 @@
     EXPECT_CALL(*mEventThread, setPhaseOffset(10)).Times(1);
     ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(mConnectionHandle, 10));
 }
-
-TEST_F(SchedulerTest, calculateMedian) {
-    std::vector<int64_t> testVector;
-    // Calling the function on empty vector returns 0.
-    EXPECT_EQ(0, calculateMedian(&testVector));
-
-    testVector.push_back(33);
-    EXPECT_EQ(33, calculateMedian(&testVector));
-    testVector.push_back(33);
-    testVector.push_back(33);
-    EXPECT_EQ(33, calculateMedian(&testVector));
-    testVector.push_back(42);
-    EXPECT_EQ(33, calculateMedian(&testVector));
-    testVector.push_back(33);
-    EXPECT_EQ(33, calculateMedian(&testVector));
-    testVector.push_back(42);
-    EXPECT_EQ(33, calculateMedian(&testVector));
-    testVector.push_back(42);
-    EXPECT_EQ(33, calculateMedian(&testVector));
-    testVector.push_back(42);
-    EXPECT_EQ(42, calculateMedian(&testVector));
-    testVector.push_back(60);
-    EXPECT_EQ(42, calculateMedian(&testVector));
-    testVector.push_back(60);
-    EXPECT_EQ(42, calculateMedian(&testVector));
-    testVector.push_back(33);
-    EXPECT_EQ(42, calculateMedian(&testVector));
-    testVector.push_back(33);
-    EXPECT_EQ(42, calculateMedian(&testVector));
-    testVector.push_back(33);
-    EXPECT_EQ(33, calculateMedian(&testVector));
-}
-
 } // namespace
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp
new file mode 100644
index 0000000..5865579
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "SchedulerUnittests"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <array>
+
+#include "Scheduler/SchedulerUtils.h"
+
+namespace android {
+namespace scheduler {
+
+class SchedulerUtilsTest : public testing::Test {
+public:
+    SchedulerUtilsTest() = default;
+    ~SchedulerUtilsTest() override = default;
+};
+
+namespace {
+TEST_F(SchedulerUtilsTest, calculate_mean) {
+    std::array<int64_t, 30> testArray{};
+    // Calling the function on empty array returns 0.
+    EXPECT_EQ(0, calculate_mean(testArray));
+
+    testArray[0] = 33;
+    EXPECT_EQ(1, calculate_mean(testArray));
+    testArray[1] = 33;
+    testArray[2] = 33;
+    EXPECT_EQ(3, calculate_mean(testArray));
+    testArray[3] = 42;
+    EXPECT_EQ(4, calculate_mean(testArray));
+    testArray[4] = 33;
+    EXPECT_EQ(5, calculate_mean(testArray));
+    testArray[5] = 42;
+    EXPECT_EQ(7, calculate_mean(testArray));
+    for (int i = 6; i < 30; i++) {
+        testArray[i] = 33;
+    }
+    EXPECT_EQ(33, calculate_mean(testArray));
+}
+
+TEST_F(SchedulerUtilsTest, calculate_median) {
+    std::vector<int64_t> testVector;
+    // Calling the function on empty vector returns 0.
+    EXPECT_EQ(0, calculate_median(&testVector));
+
+    testVector.push_back(33);
+    EXPECT_EQ(33, calculate_median(&testVector));
+    testVector.push_back(33);
+    testVector.push_back(33);
+    EXPECT_EQ(33, calculate_median(&testVector));
+    testVector.push_back(42);
+    EXPECT_EQ(33, calculate_median(&testVector));
+    testVector.push_back(33);
+    EXPECT_EQ(33, calculate_median(&testVector));
+    testVector.push_back(42);
+    EXPECT_EQ(33, calculate_median(&testVector));
+    testVector.push_back(42);
+    EXPECT_EQ(33, calculate_median(&testVector));
+    testVector.push_back(42);
+    EXPECT_EQ(42, calculate_median(&testVector));
+    testVector.push_back(60);
+    EXPECT_EQ(42, calculate_median(&testVector));
+    testVector.push_back(60);
+    EXPECT_EQ(42, calculate_median(&testVector));
+    testVector.push_back(33);
+    EXPECT_EQ(42, calculate_median(&testVector));
+    testVector.push_back(33);
+    EXPECT_EQ(42, calculate_median(&testVector));
+    testVector.push_back(33);
+    EXPECT_EQ(33, calculate_median(&testVector));
+}
+
+TEST_F(SchedulerUtilsTest, calculate_mode) {
+    std::vector<int64_t> testVector;
+    // Calling the function on empty vector returns 0.
+    EXPECT_EQ(0, calculate_mode(testVector));
+
+    testVector.push_back(33);
+    EXPECT_EQ(33, calculate_mode(testVector));
+    testVector.push_back(33);
+    testVector.push_back(33);
+    EXPECT_EQ(33, calculate_mode(testVector));
+    testVector.push_back(42);
+    EXPECT_EQ(33, calculate_mode(testVector));
+    testVector.push_back(33);
+    EXPECT_EQ(33, calculate_mode(testVector));
+    testVector.push_back(42);
+    EXPECT_EQ(33, calculate_mode(testVector));
+    testVector.push_back(42);
+    EXPECT_EQ(33, calculate_mode(testVector));
+    testVector.push_back(42);
+    EXPECT_EQ(33, calculate_mode(testVector));
+    testVector.push_back(60);
+    EXPECT_EQ(33, calculate_mode(testVector));
+    testVector.push_back(60);
+    EXPECT_EQ(33, calculate_mode(testVector));
+    testVector.push_back(33);
+    // 5 occurences of 33.
+    EXPECT_EQ(33, calculate_mode(testVector));
+    testVector.push_back(42);
+    // 5 occurences of 33, 5 occurences of 42. We choose the first one.
+    EXPECT_EQ(33, calculate_mode(testVector));
+    testVector.push_back(42);
+    // 5 occurences of 33, 6 occurences of 42.
+    EXPECT_EQ(42, calculate_mode(testVector));
+    testVector.push_back(42);
+    // 5 occurences of 33, 7 occurences of 42.
+    EXPECT_EQ(42, calculate_mode(testVector));
+}
+
+} // namespace
+} // namespace scheduler
+} // namespace android
\ No newline at end of file