summaryrefslogtreecommitdiff
path: root/media/eco
diff options
context:
space:
mode:
authorHangyu Kuang <hkuang@google.com>2019-03-14 17:54:26 -0700
committerHangyu Kuang <hkuang@google.com>2019-03-21 10:30:55 -0700
commit8d28536351da76ec5a769aeda0b7c614217dfa41 (patch)
tree7fd9bbec84c3bc53f2c48afd21879442a926bbf8 /media/eco
parent52cc6a407e54af6f9dd0123f82fbbe4892fef176 (diff)
downloadav-8d28536351da76ec5a769aeda0b7c614217dfa41.tar.gz
ECOService: Add implementation for ECOData part 1.
Add the following operation for ECOdata and also unit test for them. setString findString setInt32 findInt32 setInt64 findInt64 setFloat findFLoat setDouble findDouble setSize findSize Bug: 117877984 Test: Unit test. Change-Id: I1f5ddb76572f559d7775acdac63d2bb8bed639da
Diffstat (limited to 'media/eco')
-rw-r--r--media/eco/ECOData.cpp138
-rw-r--r--media/eco/include/eco/ECOData.h102
-rw-r--r--media/eco/include/eco/ECODataKey.h6
-rw-r--r--media/eco/tests/Android.bp19
-rw-r--r--media/eco/tests/EcoDataTest.cpp303
-rw-r--r--media/eco/tests/run_all_unit_tests.sh10
6 files changed, 573 insertions, 5 deletions
diff --git a/media/eco/ECOData.cpp b/media/eco/ECOData.cpp
index bb3fe1a..0f32e53 100644
--- a/media/eco/ECOData.cpp
+++ b/media/eco/ECOData.cpp
@@ -19,10 +19,12 @@
#include <utils/Errors.h>
#include <utils/Log.h>
+#include <string>
#include <binder/Parcel.h>
#include "eco/ECOData.h"
+#include "eco/ECODataKey.h"
namespace android {
namespace media {
@@ -33,15 +35,151 @@ using namespace ::android;
status_t ECOData::readFromParcel(const Parcel* parcel) {
parcel->readInt32(&mDataType);
parcel->readInt64(&mDataTimeUs);
+ // TODO(hkuang): Add the implenmentation of reading all keys.
return NO_ERROR;
}
status_t ECOData::writeToParcel(Parcel* parcel) const {
parcel->writeInt32(mDataType);
parcel->writeInt64(mDataTimeUs);
+ // TODO(hkuang): Add the implenmentation of writing all keys.
return NO_ERROR;
}
+void ECOData::init() {
+ mKeyValueStore[ECO_DATA_KEY_TYPE] = mDataType;
+ mKeyValueStore[ECO_DATA_KEY_TIME_US] = mDataTimeUs;
+}
+
+int32_t ECOData::getDataType() {
+ return mDataType;
+}
+
+int64_t ECOData::getDataTimeUs() {
+ return mDataTimeUs;
+}
+
+// Inserts a new key into store if the key does not exist yet. Otherwise, this will override the
+// existing key's value.
+ECODataStatus ECOData::setString(const std::string& key, const std::string& value) {
+ if (key.empty() || value.empty()) {
+ return ECODataStatus::INVALID_ARGUMENT;
+ }
+
+ mKeyValueStore[key] = value;
+
+ // TODO(hkuang): Check the valueType is valid for the key.
+ return ECODataStatus::OK;
+}
+
+ECODataStatus ECOData::findString(const std::string& key, std::string* value) const {
+ if (key.empty()) {
+ return ECODataStatus::INVALID_ARGUMENT;
+ }
+
+ // Check if the key exists.
+ if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
+ return ECODataStatus::KEY_NOT_EXIST;
+ }
+
+ // Safely access the value.
+ const std::string& entryValue = std::get<std::string>(mKeyValueStore.at(key));
+ value->assign(entryValue);
+
+ return ECODataStatus::OK;
+}
+
+// Inserts a new key into store if the key does not exist yet. Otherwise, this will override the
+// existing key's value.
+template <typename T>
+ECODataStatus ECOData::setValue(const std::string& key, T value) {
+ if (key.empty()) {
+ return ECODataStatus::INVALID_ARGUMENT;
+ }
+
+ mKeyValueStore[key] = value;
+ return ECODataStatus::OK;
+}
+
+template <typename T>
+ECODataStatus ECOData::findValue(const std::string& key, T* out) const {
+ if (key.empty() || out == nullptr) {
+ return ECODataStatus::INVALID_ARGUMENT;
+ }
+
+ if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
+ return ECODataStatus::KEY_NOT_EXIST;
+ }
+
+ // Safely access the value.
+ *out = std::get<T>(mKeyValueStore.at(key));
+
+ return ECODataStatus::OK;
+}
+
+ECODataStatus ECOData::setInt32(const std::string& key, int32_t value) {
+ return setValue<int32_t>(key, value);
+}
+
+ECODataStatus ECOData::findInt32(const std::string& key, int32_t* out) const {
+ return findValue<int32_t>(key, out);
+}
+
+ECODataStatus ECOData::setInt64(const std::string& key, int64_t value) {
+ return setValue<int64_t>(key, value);
+}
+
+ECODataStatus ECOData::findInt64(const std::string& key, int64_t* out) const {
+ return findValue<int64_t>(key, out);
+}
+
+ECODataStatus ECOData::setDouble(const std::string& key, double value) {
+ return setValue<double>(key, value);
+}
+
+ECODataStatus ECOData::findDouble(const std::string& key, double* out) const {
+ return findValue<double>(key, out);
+}
+
+ECODataStatus ECOData::setSize(const std::string& key, size_t value) {
+ return setValue<size_t>(key, value);
+}
+
+ECODataStatus ECOData::findSize(const std::string& key, size_t* out) const {
+ return findValue<size_t>(key, out);
+}
+
+ECODataStatus ECOData::setFloat(const std::string& key, float value) {
+ return setValue<float>(key, value);
+}
+
+ECODataStatus ECOData::findFloat(const std::string& key, float* out) const {
+ return findValue<float>(key, out);
+}
+
+ECODataStatus ECOData::set(const std::string& key, const ECOData::ECODataValueType& value) {
+ if (key.empty()) {
+ return ECODataStatus::INVALID_ARGUMENT;
+ }
+ mKeyValueStore[key] = value;
+ return ECODataStatus::OK;
+}
+
+ECODataStatus ECOData::find(const std::string& key, ECOData::ECODataValueType* out) const {
+ if (key.empty() || out == nullptr) {
+ return ECODataStatus::INVALID_ARGUMENT;
+ }
+
+ if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
+ return ECODataStatus::KEY_NOT_EXIST;
+ }
+
+ // Safely access the value.
+ *out = mKeyValueStore.at(key);
+
+ return ECODataStatus::OK;
+}
+
} // namespace eco
} // namespace media
} // namespace android \ No newline at end of file
diff --git a/media/eco/include/eco/ECOData.h b/media/eco/include/eco/ECOData.h
index 9c17320..37b048c 100644
--- a/media/eco/include/eco/ECOData.h
+++ b/media/eco/include/eco/ECOData.h
@@ -19,11 +19,23 @@
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
+#include <string>
+#include <unordered_map>
+#include <variant>
namespace android {
namespace media {
namespace eco {
+enum class ECODataStatus {
+ OK,
+ FAIL_TO_INSERT,
+ INVALID_ECODATA_TYPE,
+ KEY_NOT_EXIST,
+ INVALID_VALUE_TYPE,
+ INVALID_ARGUMENT,
+};
+
/**
* ECOData is the container for all messages passed between different components in ECOService.
* All messages in ECOServices are represented by a list of key-value pairs.
@@ -31,14 +43,40 @@ namespace eco {
* "bit-rate" -> 22000000
* "Provider-Name" -> "QCOM-Video-Encoder".
* "avg-frame-qp" -> 40
-* ECOData follows the same design pattern of AMessage and Metadata in Media Framework.
-* TODO(hkuang): Add the implementation and sample usage.
+* ECOData follows the same design pattern of AMessage and Metadata in Media Framework. The key
+* must be non-empty string. Below are the supported data types:
+*
+* // Item types set/find function suffixes
+* // ==========================================
+* // int32_t Int32
+* // int64_t Int64
+* // size_t Size
+* // float Float
+* // double Double
+* // String String
+*
+* ECOData does not support duplicate keys with different values. When inserting a key-value pair,
+* a new entry will be created if the key does not exist. Othewise, they key's value will be
+* overwritten with the new value.
+*
+* Sample usage:
+*
+* // Create the ECOData
+* std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+*
+* // Set the encoder name.
+* data->setString("stats-encoder-type", "google-avc");
+*
+* // Set encoding bitrate.
+* data->setInt32("stats-encoder-target-bitrate-bps", 22000000);
*/
class ECOData : public Parcelable {
public:
- ECOData() : mDataType(0), mDataTimeUs(-1) {}
- ECOData(int32_t type) : mDataType(type), mDataTimeUs(-1) {}
- ECOData(int32_t type, int64_t timeUs) : mDataType(type), mDataTimeUs(timeUs) {}
+ using ECODataValueType = std::variant<int32_t, int64_t, size_t, float, double, std::string>;
+
+ ECOData() : mDataType(0), mDataTimeUs(-1) { init(); }
+ ECOData(int32_t type) : mDataType(type), mDataTimeUs(-1) { init(); }
+ ECOData(int32_t type, int64_t timeUs) : mDataType(type), mDataTimeUs(timeUs) { init(); }
// Constants for mDataType.
enum {
@@ -53,13 +91,58 @@ public:
DATA_TYPE_INFO_LISTENER_OPTON = 4,
};
+ // set/find functions that could be used for all the value types.
+ ECODataStatus set(const std::string& key, const ECODataValueType& value);
+ ECODataStatus find(const std::string& key, ECODataValueType* out) const;
+
+ // Convenient set/find functions for string value type.
+ ECODataStatus setString(const std::string& key, const std::string& value);
+ ECODataStatus findString(const std::string& key, std::string* out) const;
+
+ // Convenient set/find functions for int32_t value type.
+ ECODataStatus setInt32(const std::string& key, int32_t value);
+ ECODataStatus findInt32(const std::string& key, int32_t* out) const;
+
+ // Convenient set/find functions for int64_t value type.
+ ECODataStatus setInt64(const std::string& key, int64_t value);
+ ECODataStatus findInt64(const std::string& key, int64_t* out) const;
+
+ // Convenient set/find functions for float value type.
+ ECODataStatus setFloat(const std::string& key, float value);
+ ECODataStatus findFloat(const std::string& key, float* out) const;
+
+ // Convenient set/find functions for double value type.
+ ECODataStatus setDouble(const std::string& key, double value);
+ ECODataStatus findDouble(const std::string& key, double* out) const;
+
+ // Convenient set/find functions for size_t value type.
+ ECODataStatus setSize(const std::string& key, size_t value);
+ ECODataStatus findSize(const std::string& key, size_t* out) const;
+
/**
* Serialization over Binder
*/
status_t readFromParcel(const Parcel* parcel) override;
status_t writeToParcel(Parcel* parcel) const override;
+ /* Returns the type of the data. */
+ int32_t getDataType();
+
+ /* Returns the timestamp associated with the data. */
+ int64_t getDataTimeUs();
+
+ /* Sets the type of the data. */
+ void setDataType(int32_t type);
+
+ /* Sets the timestamp associated with the data. */
+ void setDataTimeUs();
+
+ /* Gets the number of keys in the ECOData. */
+ size_t getNumOfEntries() { return mKeyValueStore.size(); }
+
private:
+ void init();
+
/* The type of the data */
int32_t mDataType;
@@ -67,6 +150,15 @@ private:
// boottime time base. This is only used when the data type is stats or info. -1 means
// unavailable.
int64_t mDataTimeUs;
+
+ // Internal store for the key value pairs.
+ std::unordered_map<std::string, ECODataValueType> mKeyValueStore;
+
+ template <typename T>
+ ECODataStatus setValue(const std::string& key, T value);
+
+ template <typename T>
+ ECODataStatus findValue(const std::string& key, T* out) const;
};
} // namespace eco
diff --git a/media/eco/include/eco/ECODataKey.h b/media/eco/include/eco/ECODataKey.h
index 7945ea0..0856e01 100644
--- a/media/eco/include/eco/ECODataKey.h
+++ b/media/eco/include/eco/ECODataKey.h
@@ -86,6 +86,12 @@ constexpr char INFO_KEY_FRAME_TYPE[] = "info-frame-type";
constexpr char INFO_KEY_FRAME_SIZE_BYTES[] = "info-frame-size-bytes";
constexpr char INFO_KEY_CURRENT_BITRATE_BPS[] = "info-current-bitrate-bps";
+// ================================================================================================
+// Standard ECOData keys.
+// ================================================================================================
+constexpr char ECO_DATA_KEY_TYPE[] = "eco-data-type";
+constexpr char ECO_DATA_KEY_TIME_US[] = "eco-data-time-us";
+
} // namespace eco
} // namespace media
} // namespace android
diff --git a/media/eco/tests/Android.bp b/media/eco/tests/Android.bp
new file mode 100644
index 0000000..543885c
--- /dev/null
+++ b/media/eco/tests/Android.bp
@@ -0,0 +1,19 @@
+cc_defaults{
+ name : "libmedia_ecoservice_tests_defaults",
+ cflags : [
+ "-Wall",
+ "-Werror",
+ ],
+}
+
+cc_test {
+ name: "EcoDataTest",
+ defaults: ["libmedia_ecoservice_tests_defaults"],
+ srcs: ["EcoDataTest.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "libutils",
+ "libmedia_ecoservice",
+ ],
+}
diff --git a/media/eco/tests/EcoDataTest.cpp b/media/eco/tests/EcoDataTest.cpp
new file mode 100644
index 0000000..fb9e2a1
--- /dev/null
+++ b/media/eco/tests/EcoDataTest.cpp
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 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.
+ */
+
+// Unit Test for EcoData.
+
+#include <math.h>
+#include <stdlib.h>
+
+#include <android-base/unique_fd.h>
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <cutils/ashmem.h>
+#include <gtest/gtest.h>
+#include <sys/mman.h>
+
+#include "eco/ECOData.h"
+#include "eco/ECODataKey.h"
+
+namespace android {
+namespace media {
+namespace eco {
+
+TEST(EcoDataTest, TestConstructor1) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>();
+ EXPECT_EQ(data->getDataType(), ECOData::DATA_TYPE_UNKNOWN);
+ EXPECT_EQ(data->getDataTimeUs(), -1);
+
+ int32_t type;
+ EXPECT_TRUE(data->findInt32(ECO_DATA_KEY_TYPE, &type) == ECODataStatus::OK);
+ EXPECT_EQ(type, ECOData::DATA_TYPE_UNKNOWN);
+
+ int64_t time;
+ EXPECT_TRUE(data->findInt64(ECO_DATA_KEY_TIME_US, &time) == ECODataStatus::OK);
+ EXPECT_EQ(time, -1);
+}
+
+TEST(EcoDataTest, TestConstructor2) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS);
+ EXPECT_EQ(data->getDataType(), ECOData::DATA_TYPE_STATS);
+ EXPECT_EQ(data->getDataTimeUs(), -1);
+}
+
+TEST(EcoDataTest, TestConstructor3) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+ EXPECT_EQ(data->getDataType(), ECOData::DATA_TYPE_STATS);
+ EXPECT_EQ(data->getDataTimeUs(), 1000);
+}
+
+TEST(EcoDataTest, TestNormalSetAndFindString) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ data->setString(STATS_KEY_ENCODER_TYPE, "avc");
+ std::string testValue;
+ EXPECT_TRUE(data->findString(STATS_KEY_ENCODER_TYPE, &testValue) == ECODataStatus::OK);
+ EXPECT_EQ(testValue, "avc");
+
+ // Override existing key.
+ data->setString(STATS_KEY_ENCODER_TYPE, "hevc");
+ EXPECT_EQ(data->findString(STATS_KEY_ENCODER_TYPE, &testValue), ECODataStatus::OK);
+ EXPECT_EQ(testValue, "hevc");
+}
+
+TEST(EcoDataTest, TestSetAndFindMultipleString) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ std::unordered_map<std::string, std::string> inputEntries = {
+ {"name1", "avc"}, {"name2", "avc2"}, {"name3", "avc3"}, {"name4", "avc4"},
+ {"name5", "avc5"}, {"name6", "avc6"}, {"name7", "avc7"}, {"name8", "avc8"},
+ {"name9", "avc9"}, {"name10", "avc10"}, {"name11", "avc11"}, {"name12", "avc12"}};
+ for (auto it = inputEntries.begin(); it != inputEntries.end(); ++it) {
+ data->setString(it->first, it->second);
+ }
+
+ // Checks if the string exist in the ECOData.
+ for (auto it = inputEntries.begin(); it != inputEntries.end(); ++it) {
+ std::string testValue;
+ EXPECT_TRUE(data->findString(it->first, &testValue) == ECODataStatus::OK);
+ EXPECT_EQ(testValue, it->second);
+ }
+}
+
+TEST(EcoDataTest, TestSetAndFindInvalidString) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ // Test read to null ptr and expect failure
+ EXPECT_TRUE(data->findString("encoder-name", nullptr) != ECODataStatus::OK);
+
+ // Test find non-existing key and expect failure.
+ std::string testValue;
+ EXPECT_TRUE(data->findString("encoder-name", &testValue) != ECODataStatus::OK);
+
+ // Test set empty key and expect failure
+ EXPECT_TRUE(data->setString("", "avc") != ECODataStatus::OK);
+
+ // Test read empty key and expect failure
+ EXPECT_TRUE(data->findString("", &testValue) != ECODataStatus::OK);
+}
+
+TEST(EcoDataTest, TestNormalSetAndFindInt32) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ data->setInt32(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, 2000000);
+ int32_t testValue;
+ EXPECT_TRUE(data->findInt32(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, &testValue) ==
+ ECODataStatus::OK);
+ EXPECT_EQ(testValue, 2000000);
+
+ // Override existing key.
+ data->setInt32(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, 2200000);
+ EXPECT_EQ(data->findInt32(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, &testValue), ECODataStatus::OK);
+ EXPECT_EQ(testValue, 2200000);
+}
+
+TEST(EcoDataTest, TestSetAndFindMultipleInt32) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ std::unordered_map<std::string, int32_t> inputEntries = {
+ {"name1", 100}, {"name2", 200}, {"name3", 300}, {"name4", 400},
+ {"name5", 500}, {"name6", 600}, {"name7", 700}, {"name8", 800},
+ {"name9", 900}, {"name10", 10000}, {"name11", 110000}, {"name12", 120000}};
+ for (auto it = inputEntries.begin(); it != inputEntries.end(); ++it) {
+ data->setInt32(it->first, it->second);
+ }
+
+ // Checks if the string exist in the ECOData.
+ for (auto it = inputEntries.begin(); it != inputEntries.end(); ++it) {
+ int32_t testValue;
+ EXPECT_TRUE(data->findInt32(it->first, &testValue) == ECODataStatus::OK);
+ EXPECT_EQ(testValue, it->second);
+ }
+}
+
+TEST(EcoDataTest, TestSetAndFindInvalidInt32) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ // Test read to null ptr and expect failure
+ EXPECT_TRUE(data->findInt32("encoder-name", nullptr) != ECODataStatus::OK);
+
+ // Test find non-existing key and expect failure.
+ int32_t testValue;
+ EXPECT_TRUE(data->findInt32("encoder-name", &testValue) != ECODataStatus::OK);
+
+ // Test set empty key and expect failure
+ EXPECT_TRUE(data->setInt32("", 1000) != ECODataStatus::OK);
+
+ // Test read empty key and expect failure
+ EXPECT_TRUE(data->findInt32("", &testValue) != ECODataStatus::OK);
+}
+
+TEST(EcoDataTest, TestNormalSetAndFindInt64) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ data->setInt64(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, 2000000);
+ int64_t testValue;
+ EXPECT_TRUE(data->findInt64(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, &testValue) ==
+ ECODataStatus::OK);
+ EXPECT_EQ(testValue, 2000000);
+
+ // Override existing key.
+ data->setInt64(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, 2200000);
+ EXPECT_EQ(data->findInt64(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, &testValue), ECODataStatus::OK);
+ EXPECT_EQ(testValue, 2200000);
+}
+
+TEST(EcoDataTest, TestNormalSetAndFindMultipleInt64) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ std::unordered_map<std::string, int64_t> inputEntries = {
+ {"name1", 100}, {"name2", 200}, {"name3", 300}, {"name4", 400},
+ {"name5", 500}, {"name6", 600}, {"name7", 700}, {"name8", 800},
+ {"name9", 900}, {"name10", 10000}, {"name11", 110000}, {"name12", 120000}};
+ for (auto it = inputEntries.begin(); it != inputEntries.end(); ++it) {
+ data->setInt64(it->first, it->second);
+ }
+
+ // Checks if the string exist in the ECOData.
+ for (auto it = inputEntries.begin(); it != inputEntries.end(); ++it) {
+ int64_t testValue;
+ EXPECT_TRUE(data->findInt64(it->first, &testValue) == ECODataStatus::OK);
+ EXPECT_EQ(testValue, it->second);
+ }
+}
+
+TEST(EcoDataTest, TestSetAndFindInvalidInt64) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ // Test read to null ptr and expect failure
+ EXPECT_TRUE(data->findInt64("encoder-name", nullptr) != ECODataStatus::OK);
+
+ // Test find non-existing key and expect failure.
+ int64_t testValue;
+ EXPECT_TRUE(data->findInt64("encoder-name", &testValue) != ECODataStatus::OK);
+
+ // Test set empty key and expect failure
+ EXPECT_TRUE(data->setInt64("", 1000) != ECODataStatus::OK);
+
+ // Test read empty key and expect failure
+ EXPECT_TRUE(data->findInt64("", &testValue) != ECODataStatus::OK);
+}
+
+TEST(EcoDataTest, TestNormalSetAndFindFloat) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ data->setFloat(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, 2000000.0);
+ float testValue;
+ EXPECT_TRUE(data->findFloat(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, &testValue) ==
+ ECODataStatus::OK);
+ EXPECT_FLOAT_EQ(testValue, 2000000.0);
+
+ // Override existing key.
+ data->setFloat(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, 2200000.0);
+ EXPECT_TRUE(data->findFloat(STATS_KEY_ENCODER_TARGET_BITRATE_BPS, &testValue) ==
+ ECODataStatus::OK);
+ EXPECT_FLOAT_EQ(testValue, 2200000.0);
+}
+
+TEST(EcoDataTest, TestNormalSetAndFindMultipleFloat) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ std::unordered_map<std::string, float> inputEntries = {
+ {"name1", 100.0}, {"name2", 200.0}, {"name3", 300.0}, {"name4", 400.0},
+ {"name5", 500.0}, {"name6", 600.0}, {"name7", 700.0}, {"name8", 800.0},
+ {"name9", 900.0}, {"name10", 10000.0}, {"name11", 110000.0}, {"name12", 120000.0}};
+ for (auto it = inputEntries.begin(); it != inputEntries.end(); ++it) {
+ data->setFloat(it->first, it->second);
+ }
+
+ // Checks if the string exist in the ECOData.
+ for (auto it = inputEntries.begin(); it != inputEntries.end(); ++it) {
+ float testValue;
+ EXPECT_TRUE(data->findFloat(it->first, &testValue) == ECODataStatus::OK);
+ EXPECT_FLOAT_EQ(testValue, it->second);
+ }
+}
+
+TEST(EcoDataTest, TestSetAndFindInvalidFloat) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ // Test read to null ptr and expect failure
+ EXPECT_TRUE(data->findFloat("encoder-name", nullptr) != ECODataStatus::OK);
+
+ // Test find non-existing key and expect failure.
+ float testValue;
+ EXPECT_TRUE(data->findFloat("encoder-name", &testValue) != ECODataStatus::OK);
+
+ // Test set empty key and expect failure
+ EXPECT_TRUE(data->setFloat("", 1000.0) != ECODataStatus::OK);
+
+ // Test read empty key and expect failure
+ EXPECT_TRUE(data->findFloat("", &testValue) != ECODataStatus::OK);
+}
+
+TEST(EcoDataTest, TestNormalSetAndFindMixedDataType) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ std::unordered_map<std::string, ECOData::ECODataValueType> inputEntries = {
+ {"name1", "google-encoder"}, {"name2", "avc"}, {"profile", 1}, {"level", 2},
+ {"framerate", 4.1}, {"kfi", 30}};
+ for (auto it = inputEntries.begin(); it != inputEntries.end(); ++it) {
+ data->set(it->first, it->second);
+ }
+
+ // Checks if the string exist in the ECOData.
+ for (auto it = inputEntries.begin(); it != inputEntries.end(); ++it) {
+ ECOData::ECODataValueType testValue;
+ EXPECT_TRUE(data->find(it->first, &testValue) == ECODataStatus::OK);
+ EXPECT_EQ(testValue, it->second);
+ }
+}
+
+TEST(EcoDataTest, TestSetAndFindInvalidDataType) {
+ std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
+
+ // Test read to null ptr and expect failure
+ EXPECT_TRUE(data->find("encoder-name", nullptr) != ECODataStatus::OK);
+
+ // Test find non-existing key and expect failure.
+ ECOData::ECODataValueType testValue;
+ EXPECT_TRUE(data->find("encoder-name2", &testValue) != ECODataStatus::OK);
+
+ // Test set empty key and expect failure
+ EXPECT_TRUE(data->set("", 1000) != ECODataStatus::OK);
+
+ // Test read empty key and expect failure
+ EXPECT_TRUE(data->find("", &testValue) != ECODataStatus::OK);
+}
+
+} // namespace eco
+} // namespace media
+} // namespace android \ No newline at end of file
diff --git a/media/eco/tests/run_all_unit_tests.sh b/media/eco/tests/run_all_unit_tests.sh
new file mode 100644
index 0000000..0b5fee0
--- /dev/null
+++ b/media/eco/tests/run_all_unit_tests.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+ echo "Android build environment not set"
+ exit -1
+fi
+
+echo "waiting for device"
+adb root && adb wait-for-device remount && adb sync
+
+adb shell /data/nativetest/EcoDataTest/EcoDataTest