1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_MEDIA_ECO_DATA_H_
18 #define ANDROID_MEDIA_ECO_DATA_H_
19 
20 #include <android/binder_auto_utils.h>
21 #include <android/binder_parcel.h>
22 #include <android/binder_status.h>
23 
24 #include <string>
25 #include <unordered_map>
26 #include <variant>
27 
28 namespace aidl {
29 namespace android {
30 namespace media {
31 namespace eco {
32 
33 enum class ECODataStatus {
34     OK,
35     FAIL_TO_INSERT,
36     INVALID_ECODATA_TYPE,
37     KEY_NOT_EXIST,
38     INVALID_VALUE_TYPE,
39     INVALID_ARGUMENT,
40 };
41 
42 /**
43 * ECOData is the container for all messages passed between different components in ECOService.
44 * All messages in ECOServices are represented by a list of key-value pairs.
45 * For example:
46 *     "bit-rate" -> 22000000
47 *     "Provider-Name" -> "QCOM-Video-Encoder".
48 *     "avg-frame-qp" -> 40
49 * ECOData follows the same design pattern of AMessage and Metadata in Media Framework. The key
50 * must be non-empty string. Below are the supported data types:
51 *
52 *    //   Item types      set/find function suffixes
53 *    //   ==========================================
54 *    //     int32_t                Int32
55 *    //     int64_t                Int64
56 *    //     size_t                 Size
57 *    //     float                  Float
58 *    //     double                 Double
59 *    //     String                 String
60 *
61 * ECOData does not support duplicate keys with different values. When inserting a key-value pair,
62 * a new entry will be created if the key does not exist. Othewise, they key's value will be
63 * overwritten with the new value.
64 *
65 *  Sample usage:
66 *
67 *   // Create the ECOData
68 *   std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
69 *
70 *   // Set the encoder name.
71 *   data->setString("stats-encoder-type", "google-avc");
72 *
73 *   // Set encoding bitrate.
74 *   data->setInt32("stats-encoder-target-bitrate-bps", 22000000);
75 */
76 class ECOData {
77 public:
78     using ECODataValueType =
79             std::variant<int32_t, int64_t, size_t, float, double, std::string, int8_t>;
80     using ECODataKeyValuePair = std::pair<std::string, ECODataValueType>;
81 
ECOData()82     ECOData() : mDataType(0), mDataTimeUs(-1) {}
ECOData(int32_t type)83     ECOData(int32_t type) : mDataType(type), mDataTimeUs(-1) {}
ECOData(int32_t type,int64_t timeUs)84     ECOData(int32_t type, int64_t timeUs) : mDataType(type), mDataTimeUs(timeUs) {}
85 
86     // Constants for mDataType.
87     typedef enum {
88         DATA_TYPE_UNKNOWN = 0,
89         /* Data sent from the ECOServiceStatsProvider to ECOService. */
90         DATA_TYPE_STATS = 1,
91         /* Data sent from the ECOService to ECOServiceInfoListener. */
92         DATA_TYPE_INFO = 2,
93         /* Configuration data sent by ECOServiceStatsProvider when connects with ECOService. */
94         DATA_TYPE_STATS_PROVIDER_CONFIG = 3,
95         /* Configuration data sent by ECOServiceInfoListener when connects with ECOService. */
96         DATA_TYPE_INFO_LISTENER_CONFIG = 4,
97     } ECODatatype;
98 
99     // set/find functions that could be used for all the value types.
100     ECODataStatus set(const std::string& key, const ECODataValueType& value);
101     ECODataStatus find(const std::string& key, ECODataValueType* out) const;
102 
103     // Convenient set/find functions for string value type.
104     ECODataStatus setString(const std::string& key, const std::string& value);
105     ECODataStatus findString(const std::string& key, std::string* out) const;
106 
107     // Convenient set/find functions for int32_t value type.
108     ECODataStatus setInt32(const std::string& key, int32_t value);
109     ECODataStatus findInt32(const std::string& key, int32_t* out) const;
110 
111     // Convenient set/find functions for int64_t value type.
112     ECODataStatus setInt64(const std::string& key, int64_t value);
113     ECODataStatus findInt64(const std::string& key, int64_t* out) const;
114 
115     // Convenient set/find functions for float value type.
116     ECODataStatus setFloat(const std::string& key, float value);
117     ECODataStatus findFloat(const std::string& key, float* out) const;
118 
119     // Convenient set/find functions for double value type.
120     ECODataStatus setDouble(const std::string& key, double value);
121     ECODataStatus findDouble(const std::string& key, double* out) const;
122 
123     // Convenient set/find functions for size_t value type.
124     ECODataStatus setSize(const std::string& key, size_t value);
125     ECODataStatus findSize(const std::string& key, size_t* out) const;
126 
127     // Convenient set/find functions for int8_t value type.
128     // TODO(hkuang): Add unit test.
129     ECODataStatus setInt8(const std::string& key, int8_t value);
130     ECODataStatus findInt8(const std::string& key, int8_t* out) const;
131 
132     /**
133     * Serialization over Binder
134     */
135     binder_status_t readFromParcel(const AParcel* parcel);
136     binder_status_t writeToParcel(AParcel* parcel) const;
137 
138     /* Returns the type of the data. */
139     int32_t getDataType() const;
140 
141     /* Returns the type of the data in string. */
142     std::string getDataTypeString() const;
143 
144     /* Returns the timestamp associated with the data. */
145     int64_t getDataTimeUs() const;
146 
147     /* Sets the type of the data. */
148     void setDataType(int32_t type);
149 
150     /* Sets the timestamp associated with the data. */
151     void setDataTimeUs();
152 
153     /* Gets the number of keys in the ECOData. */
getNumOfEntries()154     size_t getNumOfEntries() const { return mKeyValueStore.size(); }
155 
156     /* Whether the ECOData is empty. */
isEmpty()157     size_t isEmpty() const { return mKeyValueStore.size() == 0; }
158 
159     friend class ECODataKeyValueIterator;
160 
161     friend bool copyKeyValue(const ECOData& src, ECOData* dst);
162 
163     // Dump the ECOData as a string.
164     std::string debugString() const;
165 
166     std::string toString() const;
167 
168 protected:
169     // ValueType. This must match the index in ECODataValueType.
170     enum ValueType {
171         kTypeInt32 = 0,
172         kTypeInt64 = 1,
173         kTypeSize = 2,
174         kTypeFloat = 3,
175         kTypeDouble = 4,
176         kTypeString = 5,
177         kTypeInt8 = 6,
178     };
179 
180     /* The type of the data */
181     int32_t mDataType;
182 
183     // The timestamp time associated with the data in microseconds. The timestamp should be in
184     // boottime time base. This is only used when the data type is stats or info. -1 means
185     // unavailable.
186     int64_t mDataTimeUs;
187 
188     // Internal store for the key value pairs.
189     std::unordered_map<std::string, ECODataValueType> mKeyValueStore;
190 
191     template <typename T>
192     ECODataStatus setValue(const std::string& key, T value);
193 
194     template <typename T>
195     ECODataStatus findValue(const std::string& key, T* out) const;
196 
copyKeyValue(const ECOData & src,ECOData * dst)197     static bool copyKeyValue(const ECOData& src, ECOData* dst) {
198         if (src.isEmpty() || dst == nullptr) return false;
199         dst->mKeyValueStore = src.mKeyValueStore;
200         return true;
201     }
202 };
203 
204 // A simple ECOData iterator that will iterate over all the key value paris in ECOData.
205 // To be used like:
206 // while (it.hasNext()) {
207 //   entry = it.next();
208 // }
209 class ECODataKeyValueIterator {
210 public:
ECODataKeyValueIterator(const ECOData & data)211     ECODataKeyValueIterator(const ECOData& data)
212           : mKeyValueStore(data.mKeyValueStore), mBeginReturned(false) {
213         mIterator = mKeyValueStore.begin();
214     }
215     ~ECODataKeyValueIterator() = default;
216     bool hasNext();
217     ECOData::ECODataKeyValuePair next() const;
218 
219 private:
220     const std::unordered_map<std::string, ECOData::ECODataValueType>& mKeyValueStore;
221     std::unordered_map<std::string, ECOData::ECODataValueType>::const_iterator mIterator;
222     bool mBeginReturned;
223 };
224 
225 }  // namespace eco
226 }  // namespace media
227 }  // namespace android
228 }  // namespace aidl
229 
230 #endif  // ANDROID_MEDIA_ECO_DATA_H_
231