1 /*
2  * Copyright (C) 2021 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "NativeMediaFormatUnitTest"
19 #include <log/log.h>
20 
21 #include <jni.h>
22 #include <media/NdkMediaFormat.h>
23 
24 #include <cinttypes>
25 #include <map>
26 #include <string>
27 
28 static const char story[] = {"What if after you die, God asks you: 'so how was heaven'"};
29 static const char dragon[] = {"e4 c5 Nf3 d6 d4 cxd4 Nxd4 Nf6 Nc3 g6"};
30 
31 class Rect {
32 public:
33     int left;
34     int top;
35     int right;
36     int bottom;
37 
Rect(int a,int b,int c,int d)38     Rect(int a, int b, int c, int d) : left{a}, top{b}, right{c}, bottom{d} {};
39 };
40 
41 class Buffer {
42 public:
43     char* buffer;
44     size_t size;
45 
Buffer(char * buffer=nullptr,size_t size=0)46     explicit Buffer(char* buffer = nullptr, size_t size = 0) : buffer{buffer}, size{size} {};
47 };
48 
49 class NativeMediaFormatUnitTest {
50 private:
51     std::map<int32_t, const char*> mInt32KeyValuePairs;
52     std::map<int64_t, const char*> mInt64KeyValuePairs;
53     std::map<float, const char*> mFloatKeyValuePairs;
54     std::map<double, const char*> mDoubleKeyValuePairs;
55     std::map<size_t, const char*> mSizeKeyValuePairs;
56     std::map<const char*, const char*> mStringKeyValuePairs;
57     std::map<Rect*, const char*> mWindowKeyValuePairs;
58     std::map<Buffer*, const char*> mBufferKeyValuePairs;
59 
60 public:
61     NativeMediaFormatUnitTest();
62     ~NativeMediaFormatUnitTest();
63 
64     bool validateFormatInt32(AMediaFormat* fmt, int offset = 0, bool isClear = false);
65     bool validateFormatInt64(AMediaFormat* fmt, int offset = 0, bool isClear = false);
66     bool validateFormatFloat(AMediaFormat* fmt, float offset = 0.0f, bool isClear = false);
67     bool validateFormatDouble(AMediaFormat* fmt, double offset = 0.0, bool isClear = false);
68     bool validateFormatSize(AMediaFormat* fmt, size_t offset = 0, bool isClear = false);
69     bool validateFormatString(AMediaFormat* fmt, int offset = 0, bool isClear = false);
70     bool validateFormatRect(AMediaFormat* fmt, int offset = 0, bool isClear = false);
71     bool validateFormatBuffer(AMediaFormat* fmt, int offset = 0, bool isClear = false);
72     bool validateFormat(AMediaFormat* fmt, int offset = 0, bool isClear = false);
73 
74     void configureFormatInt32(AMediaFormat* fmt, int offset = 0);
75     void configureFormatInt64(AMediaFormat* fmt, int offset = 0);
76     void configureFormatFloat(AMediaFormat* fmt, float offset = 0.0f);
77     void configureFormatDouble(AMediaFormat* fmt, double offset = 0.0);
78     void configureFormatSize(AMediaFormat* fmt, size_t offset = 0);
79     void configureFormatString(AMediaFormat* fmt, int offset = 0);
80     void configureFormatRect(AMediaFormat* fmt, int offset = 0);
81     void configureFormatBuffer(AMediaFormat* fmt, int offset = 0);
82     void configureFormat(AMediaFormat* fmt, int offset = 0);
83 };
84 
NativeMediaFormatUnitTest()85 NativeMediaFormatUnitTest::NativeMediaFormatUnitTest() {
86     mInt32KeyValuePairs.insert({118, "elements in periodic table"});
87     mInt32KeyValuePairs.insert({5778, "surface temp. of sun in kelvin"});
88     mInt32KeyValuePairs.insert({8611, "k2 peak in mts"});
89     mInt32KeyValuePairs.insert({72, "heart rate in bpm"});
90     mInt64KeyValuePairs.insert({299792458L, "vel. of em wave in free space m/s"});
91     mInt64KeyValuePairs.insert({86400L, "number of seconds in a day"});
92     mInt64KeyValuePairs.insert({1520200000L, "distance of earth from the sun in km"});
93     mInt64KeyValuePairs.insert({39000000L, "forest area of the world km^2"});
94     mFloatKeyValuePairs.insert({22.0f / 7.0f, "pi"});
95     mFloatKeyValuePairs.insert({3.6f, "not great, not terrible"});
96     mFloatKeyValuePairs.insert({15.999f, "atomic weight of oxygen 8"});
97     mFloatKeyValuePairs.insert({2.7182f, "Euler's number"});
98     mDoubleKeyValuePairs.insert({44.0 / 7, "tau"});
99     mDoubleKeyValuePairs.insert({9.80665, "g on earth m/sec^2"});
100     mSizeKeyValuePairs.insert({sizeof(int64_t), "size of int64_t"});
101     mSizeKeyValuePairs.insert({sizeof(wchar_t), "size of wide char"});
102     mSizeKeyValuePairs.insert({sizeof(intptr_t), "size of pointer variable"});
103     mSizeKeyValuePairs.insert({sizeof *this, "size of class NativeMediaFormatUnitTest"});
104     mStringKeyValuePairs.insert(
105             {"Discovered radium and polonium, and made huge contribution to finding treatments "
106              "for cancer", "Marie Curie"});
107     mStringKeyValuePairs.insert({"Sun rises in the east has zero entropy", "Shannon"});
108     mWindowKeyValuePairs.insert({new Rect{12, 15, 12, 21}, "trapezoid"});
109     mWindowKeyValuePairs.insert({new Rect{12, 12, 12, 12}, "rhombus"});
110     mWindowKeyValuePairs.insert({new Rect{12, 15, 12, 15}, "rectangle"});
111     mWindowKeyValuePairs.insert({new Rect{12, 15, 18, 21}, "quadrilateral"});
112     mBufferKeyValuePairs.insert({new Buffer(), "empty buffer"});
113     size_t sz = strlen(story) + 1;
114     auto* quote = new Buffer{new char[sz], sz};
115     memcpy(quote->buffer, story, sz);
116     mBufferKeyValuePairs.insert({quote, "one line story"});
117     sz = strlen(dragon) + 1;
118     auto* chess = new Buffer(new char[sz], sz);
119     memcpy(chess->buffer, dragon, sz);
120     mBufferKeyValuePairs.insert({chess, "sicilian dragon"});
121 }
122 
~NativeMediaFormatUnitTest()123 NativeMediaFormatUnitTest::~NativeMediaFormatUnitTest() {
124     for (auto it : mWindowKeyValuePairs) {
125         delete it.first;
126     }
127     for (auto it : mBufferKeyValuePairs) {
128         delete[] it.first->buffer;
129         delete it.first;
130     }
131 }
132 
validateFormatInt32(AMediaFormat * fmt,int offset,bool isClear)133 bool NativeMediaFormatUnitTest::validateFormatInt32(AMediaFormat* fmt, int offset, bool isClear) {
134     bool status = true;
135     int32_t val;
136     const char* toString = AMediaFormat_toString(fmt);
137     for (auto it : mInt32KeyValuePairs) {
138         bool result = AMediaFormat_getInt32(fmt, it.second, &val);
139         if (isClear) {
140             if (result) {
141                 ALOGE("MediaFormat is not expected to contain Key %s", it.second);
142                 status &= false;
143             }
144         } else {
145             if (!result) {
146                 ALOGE("MediaFormat doesn't contain key %s", it.second);
147                 status &= false;
148             } else if (val != it.first + offset) {
149                 ALOGE("MediaFormat Value for Key %s is not %d but %d", it.second, it.first + offset,
150                       val);
151                 status &= false;
152             }
153             if (strstr(toString, it.second) == nullptr) {
154                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString, it.second);
155                 status &= false;
156             }
157             if (strstr(toString, std::to_string(it.first + offset).c_str()) == nullptr) {
158                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString,
159                       std::to_string(it.first + offset).c_str());
160                 status &= false;
161             }
162         }
163     }
164     if (AMediaFormat_getInt32(fmt, "hello world", &val)) {
165         ALOGE("MediaFormat has value for key 'hello world' ");
166         status &= false;
167     }
168     return status;
169 }
170 
validateFormatInt64(AMediaFormat * fmt,int offset,bool isClear)171 bool NativeMediaFormatUnitTest::validateFormatInt64(AMediaFormat* fmt, int offset, bool isClear) {
172     bool status = true;
173     int64_t val;
174     const char* toString = AMediaFormat_toString(fmt);
175     for (auto it : mInt64KeyValuePairs) {
176         bool result = AMediaFormat_getInt64(fmt, it.second, &val);
177         if (isClear) {
178             if (result) {
179                 ALOGE("MediaFormat is not expected to contain Key %s", it.second);
180                 status &= false;
181             }
182         } else {
183             if (!result) {
184                 ALOGE("MediaFormat doesn't contain key %s", it.second);
185                 status &= false;
186             } else if (val != it.first + offset) {
187                 ALOGE("MediaFormat Value for Key %s is not %" PRId64 "but %" PRId64, it.second,
188                       it.first + offset, val);
189                 status &= false;
190             }
191             if (strstr(toString, it.second) == nullptr) {
192                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString, it.second);
193                 status &= false;
194             }
195             if (strstr(toString, std::to_string(it.first + offset).c_str()) == nullptr) {
196                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString,
197                       std::to_string(it.first + offset).c_str());
198                 status &= false;
199             }
200         }
201     }
202     if (AMediaFormat_getInt64(fmt, "hello world", &val)) {
203         ALOGE("MediaFormat has value for key 'hello world' ");
204         status &= false;
205     }
206     return status;
207 }
208 
validateFormatFloat(AMediaFormat * fmt,float offset,bool isClear)209 bool NativeMediaFormatUnitTest::validateFormatFloat(AMediaFormat* fmt, float offset, bool isClear) {
210     bool status = true;
211     float val;
212     const char* toString = AMediaFormat_toString(fmt);
213     for (auto it : mFloatKeyValuePairs) {
214         bool result = AMediaFormat_getFloat(fmt, it.second, &val);
215         if (isClear) {
216             if (result) {
217                 ALOGE("MediaFormat is not expected to contain Key %s", it.second);
218                 status &= false;
219             }
220         } else {
221             if (!result) {
222                 ALOGE("MediaFormat doesn't contain key %s", it.second);
223                 status &= false;
224             } else if (val != it.first + offset) {
225                 ALOGE("MediaFormat Value for Key %s is not %f but %f", it.second, it.first + offset,
226                       val);
227                 status &= false;
228             }
229             if (strstr(toString, it.second) == nullptr) {
230                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString, it.second);
231                 status &= false;
232             }
233             if (strstr(toString, std::to_string(it.first + offset).c_str()) == nullptr) {
234                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString,
235                       std::to_string(it.first + offset).c_str());
236                 status &= false;
237             }
238         }
239     }
240     if (AMediaFormat_getFloat(fmt, "hello world", &val)) {
241         ALOGE("MediaFormat has value for key 'hello world' ");
242         status &= false;
243     }
244     return status;
245 }
246 
validateFormatDouble(AMediaFormat * fmt,double offset,bool isClear)247 bool NativeMediaFormatUnitTest::validateFormatDouble(AMediaFormat* fmt, double offset,
248                                                      bool isClear) {
249     bool status = true;
250     double val;
251     const char* toString = AMediaFormat_toString(fmt);
252     for (auto it : mDoubleKeyValuePairs) {
253         bool result = AMediaFormat_getDouble(fmt, it.second, &val);
254         if (isClear) {
255             if (result) {
256                 ALOGE("MediaFormat is not expected to contain Key %s", it.second);
257                 status &= false;
258             }
259         } else {
260             if (!result) {
261                 ALOGE("MediaFormat doesn't contain key %s", it.second);
262                 status &= false;
263             } else if (val != it.first + offset) {
264                 ALOGE("MediaFormat Value for Key %s is not %f but %f", it.second, it.first + offset,
265                       val);
266                 status &= false;
267             }
268             if (strstr(toString, it.second) == nullptr) {
269                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString, it.second);
270                 status &= false;
271             }
272             if (strstr(toString, std::to_string(it.first + offset).c_str()) == nullptr) {
273                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString,
274                       std::to_string(it.first + offset).c_str());
275                 status &= false;
276             }
277         }
278     }
279     if (AMediaFormat_getDouble(fmt, "hello world", &val)) {
280         ALOGE("MediaFormat has value for key 'hello world' ");
281         status &= false;
282     }
283     return status;
284 }
285 
validateFormatSize(AMediaFormat * fmt,size_t offset,bool isClear)286 bool NativeMediaFormatUnitTest::validateFormatSize(AMediaFormat* fmt, size_t offset, bool isClear) {
287     bool status = true;
288     size_t val;
289     const char* toString = AMediaFormat_toString(fmt);
290     for (auto it : mSizeKeyValuePairs) {
291         bool result = AMediaFormat_getSize(fmt, it.second, &val);
292         if (isClear) {
293             if (result) {
294                 ALOGE("MediaFormat is not expected to contain Key %s", it.second);
295                 status &= false;
296             }
297         } else {
298             if (!result) {
299                 ALOGE("MediaFormat doesn't contain key %s", it.second);
300                 status &= false;
301             } else if (val != it.first + offset) {
302                 ALOGE("MediaFormat Value for Key %s is not %zu but %zu", it.second,
303                       it.first + offset, val);
304                 status &= false;
305             }
306             if (strstr(toString, it.second) == nullptr) {
307                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString, it.second);
308                 status &= false;
309             }
310             if (strstr(toString, std::to_string(it.first + offset).c_str()) == nullptr) {
311                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString,
312                       std::to_string(it.first + offset).c_str());
313                 status &= false;
314             }
315         }
316     }
317     if (AMediaFormat_getSize(fmt, "hello world", &val)) {
318         ALOGE("MediaFormat has value for key 'hello world' ");
319         status &= false;
320     }
321     return status;
322 }
323 
validateFormatString(AMediaFormat * fmt,int offset,bool isClear)324 bool NativeMediaFormatUnitTest::validateFormatString(AMediaFormat* fmt, int offset, bool isClear) {
325     bool status = true;
326     const char* val;
327     const char* toString = AMediaFormat_toString(fmt);
328     for (auto it : mStringKeyValuePairs) {
329         bool result = AMediaFormat_getString(fmt, it.second, &val);
330         if (isClear) {
331             if (result) {
332                 ALOGE("MediaFormat is not expected to contain Key %s", it.second);
333                 status &= false;
334             }
335         } else {
336             std::string s = it.first + std::to_string(offset);
337             if (!result) {
338                 ALOGE("MediaFormat doesn't contain key %s", it.second);
339                 status &= false;
340             } else if (s != val) {
341                 ALOGE("MediaFormat Value for Key %s is not %s but %s", it.second, s.c_str(), val);
342                 status &= false;
343             }
344             if (strstr(toString, it.second) == nullptr) {
345                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString, it.second);
346                 status &= false;
347             }
348             if (strstr(toString, s.c_str()) == nullptr) {
349                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString, s.c_str());
350                 status &= false;
351             }
352         }
353     }
354     if (AMediaFormat_getString(fmt, "hello world", &val)) {
355         ALOGE("MediaFormat has value for key 'hello world' ");
356         status &= false;
357     }
358     return status;
359 }
360 
validateFormatRect(AMediaFormat * fmt,int offset,bool isClear)361 bool NativeMediaFormatUnitTest::validateFormatRect(AMediaFormat* fmt, int offset, bool isClear) {
362     bool status = true;
363     int left, top, right, bottom;
364     const char* toString = AMediaFormat_toString(fmt);
365     for (auto it : mWindowKeyValuePairs) {
366         bool result = AMediaFormat_getRect(fmt, it.second, &left, &top, &right, &bottom);
367         if (isClear) {
368             if (result) {
369                 ALOGE("MediaFormat is not expected to contain Key %s", it.second);
370                 status &= false;
371             }
372         } else {
373             if (!result) {
374                 ALOGE("MediaFormat doesn't contain key %s", it.second);
375                 status &= false;
376             } else if (left != it.first->left + offset || top != it.first->top + offset ||
377                        right != it.first->right + offset || bottom != it.first->bottom + offset) {
378                 ALOGE("MediaFormat Value for Key %s is not (%d, %d, %d, %d)) but (%d, %d, %d, %d)",
379                       it.second, it.first->left, it.first->top, it.first->right, it.first->bottom,
380                       left, top, right, bottom);
381                 status &= false;
382             }
383             if (strstr(toString, it.second) == nullptr) {
384                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString, it.second);
385                 status &= false;
386             }
387             if (strstr(toString, std::to_string(it.first->left + offset).c_str()) == nullptr) {
388                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString,
389                       std::to_string(it.first->left + offset).c_str());
390                 status &= false;
391             }
392             if (strstr(toString, std::to_string(it.first->top + offset).c_str()) == nullptr) {
393                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString,
394                       std::to_string(it.first->top + offset).c_str());
395                 status &= false;
396             }
397             if (strstr(toString, std::to_string(it.first->right + offset).c_str()) == nullptr) {
398                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString,
399                       std::to_string(it.first->right + offset).c_str());
400                 status &= false;
401             }
402             if (strstr(toString, std::to_string(it.first->bottom + offset).c_str()) == nullptr) {
403                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString,
404                       std::to_string(it.first->bottom + offset).c_str());
405                 status &= false;
406             }
407         }
408     }
409     if (AMediaFormat_getRect(fmt, "hello world", &left, &top, &right, &bottom)) {
410         ALOGE("MediaFormat has value for key 'hello world' ");
411         status &= false;
412     }
413     return status;
414 }
415 
validateFormatBuffer(AMediaFormat * fmt,int offset,bool isClear)416 bool NativeMediaFormatUnitTest::validateFormatBuffer(AMediaFormat* fmt, int offset, bool isClear) {
417     bool status = true;
418     void* data;
419     size_t size;
420     const char* toString = AMediaFormat_toString(fmt);
421     for (auto it : mBufferKeyValuePairs) {
422         bool result = AMediaFormat_getBuffer(fmt, it.second, &data, &size);
423         if (isClear) {
424             if (result) {
425                 ALOGE("MediaFormat is not expected to contain Key %s", it.second);
426                 status &= false;
427             }
428         } else {
429             if (!result) {
430                 ALOGE("MediaFormat doesn't contain key %s", it.second);
431                 status &= false;
432             } else if (size != (offset == 0 ? it.first->size : it.first->size / 2)) {
433                 ALOGE("MediaFormat Value for Key %s is not %zu but %zu", it.second,
434                       (offset == 0 ? it.first->size : it.first->size / 2), size);
435                 status &= false;
436             } else {
437                 if (it.first->buffer != nullptr &&
438                     memcmp(data, it.first->buffer + it.first->size - size, size) != 0) {
439                     ALOGE("MediaFormat Value for Key %s is not %s but %s {%zu}", it.second,
440                           it.first->buffer + it.first->size - size, (char*)data, size);
441                     status &= false;
442                 }
443             }
444             if (strstr(toString, it.second) == nullptr) {
445                 ALOGE("AMediaFormat_toString() of fmt %s doesn't contains %s", toString, it.second);
446                 status &= false;
447             }
448         }
449     }
450     if (AMediaFormat_getBuffer(fmt, "hello world", &data, &size)) {
451         ALOGE("MediaFormat has value for key 'hello world' ");
452         status &= false;
453     }
454     return status;
455 }
456 
validateFormat(AMediaFormat * fmt,int offset,bool isClear)457 bool NativeMediaFormatUnitTest::validateFormat(AMediaFormat* fmt, int offset, bool isClear) {
458     bool status = validateFormatInt32(fmt, offset, isClear);
459     status &= validateFormatInt64(fmt, offset, isClear);
460     status &= validateFormatFloat(fmt, offset, isClear);
461     status &= validateFormatDouble(fmt, offset, isClear);
462     status &= validateFormatSize(fmt, offset, isClear);
463     status &= validateFormatString(fmt, offset, isClear);
464     status &= validateFormatRect(fmt, offset, isClear);
465     status &= validateFormatBuffer(fmt, offset, isClear);
466     return status;
467 }
468 
configureFormatInt32(AMediaFormat * fmt,int offset)469 void NativeMediaFormatUnitTest::configureFormatInt32(AMediaFormat* fmt, int offset) {
470     for (auto it : mInt32KeyValuePairs) {
471         AMediaFormat_setInt32(fmt, it.second, it.first + offset);
472     }
473 }
474 
configureFormatInt64(AMediaFormat * fmt,int offset)475 void NativeMediaFormatUnitTest::configureFormatInt64(AMediaFormat* fmt, int offset) {
476     for (auto it : mInt64KeyValuePairs) {
477         AMediaFormat_setInt64(fmt, it.second, it.first + offset);
478     }
479 }
480 
configureFormatFloat(AMediaFormat * fmt,float offset)481 void NativeMediaFormatUnitTest::configureFormatFloat(AMediaFormat* fmt, float offset) {
482     for (auto it : mFloatKeyValuePairs) {
483         AMediaFormat_setFloat(fmt, it.second, it.first + offset);
484     }
485 }
486 
configureFormatDouble(AMediaFormat * fmt,double offset)487 void NativeMediaFormatUnitTest::configureFormatDouble(AMediaFormat* fmt, double offset) {
488     for (auto it : mDoubleKeyValuePairs) {
489         AMediaFormat_setDouble(fmt, it.second, it.first + offset);
490     }
491 }
492 
configureFormatSize(AMediaFormat * fmt,size_t offset)493 void NativeMediaFormatUnitTest::configureFormatSize(AMediaFormat* fmt, size_t offset) {
494     for (auto it : mSizeKeyValuePairs) {
495         AMediaFormat_setSize(fmt, it.second, it.first + offset);
496     }
497 }
498 
configureFormatString(AMediaFormat * fmt,int offset)499 void NativeMediaFormatUnitTest::configureFormatString(AMediaFormat* fmt, int offset) {
500     for (auto it : mStringKeyValuePairs) {
501         std::string s1 = it.first + std::to_string(offset);
502         AMediaFormat_setString(fmt, it.second, s1.c_str());
503     }
504 }
505 
configureFormatRect(AMediaFormat * fmt,int offset)506 void NativeMediaFormatUnitTest::configureFormatRect(AMediaFormat* fmt, int offset) {
507     for (auto it : mWindowKeyValuePairs) {
508         AMediaFormat_setRect(fmt, it.second, it.first->left + offset, it.first->top + offset,
509                              it.first->right + offset, it.first->bottom + offset);
510     }
511 }
512 
configureFormatBuffer(AMediaFormat * fmt,int offset)513 void NativeMediaFormatUnitTest::configureFormatBuffer(AMediaFormat* fmt, int offset) {
514     for (auto it : mBufferKeyValuePairs) {
515         int sz = offset == 0 ? it.first->size : it.first->size / 2;
516         AMediaFormat_setBuffer(fmt, it.second, it.first->buffer + it.first->size - sz, sz);
517     }
518 }
519 
configureFormat(AMediaFormat * fmt,int offset)520 void NativeMediaFormatUnitTest::configureFormat(AMediaFormat* fmt, int offset) {
521     configureFormatInt32(fmt, offset);
522     configureFormatInt64(fmt, offset);
523     configureFormatFloat(fmt, offset);
524     configureFormatDouble(fmt, offset);
525     configureFormatSize(fmt, offset);
526     configureFormatString(fmt, offset);
527     configureFormatRect(fmt, offset);
528     configureFormatBuffer(fmt, offset);
529 }
530 
531 // 1. configure format with default values and validate the same
532 // 2. copy configured format to an empty format and validate the copied format
533 // 3. overwrite copied format with default + offset values and validate the updated format
534 // 4. overwrite updated format with default values using AMediaFormat_copy API and validate the same
535 // 5. clear mediaformat and validate if keys are not present
testMediaFormatAllNative()536 static bool testMediaFormatAllNative() {
537     auto* nmf = new NativeMediaFormatUnitTest();
538     AMediaFormat* fmtOrig = AMediaFormat_new();
539     AMediaFormat* fmtDup = AMediaFormat_new();
540     const int offset = 123;
541 
542     nmf->configureFormat(fmtOrig);
543     bool status = nmf->validateFormat(fmtOrig);
544 
545     AMediaFormat_copy(fmtDup, fmtOrig);
546     status &= nmf->validateFormat(fmtDup);
547 
548     nmf->configureFormat(fmtDup, offset);
549     status &= nmf->validateFormat(fmtDup, offset);
550 
551     AMediaFormat_copy(fmtDup, fmtOrig);
552     status &= nmf->validateFormat(fmtDup);
553 
554     AMediaFormat_clear(fmtDup);
555     status &= nmf->validateFormat(fmtDup, offset, true);
556 
557     AMediaFormat_delete(fmtOrig);
558     AMediaFormat_delete(fmtDup);
559     delete nmf;
560 
561     return status;
562 }
563 
564 // 1. configure format with default values and validate the same
565 // 2. copy configured format to an empty format and validate the copied format
566 // 3. overwrite copied format with default + offset values and validate the updated format
567 // 4. overwrite updated format with default values using AMediaFormat_copy API and validate the same
568 #define testMediaFormatfuncNative(func)                            \
569     static bool testMediaFormat##func##Native() {                  \
570         auto* nmf = new NativeMediaFormatUnitTest();               \
571         AMediaFormat* fmtOrig = AMediaFormat_new();                \
572         AMediaFormat* fmtDup = AMediaFormat_new();                 \
573         const int offset = 12345;                                  \
574                                                                    \
575         nmf->configureFormat##func(fmtOrig);                       \
576         bool status = nmf->validateFormat##func(fmtOrig);          \
577                                                                    \
578         AMediaFormat_copy(fmtDup, fmtOrig);                        \
579         status &= nmf->validateFormat##func(fmtDup);               \
580                                                                    \
581         nmf->configureFormat##func(fmtDup, offset);                \
582         status &= nmf->validateFormat##func(fmtDup, offset);       \
583                                                                    \
584         AMediaFormat_copy(fmtDup, fmtOrig);                        \
585         status &= nmf->validateFormat##func(fmtDup);               \
586                                                                    \
587         AMediaFormat_clear(fmtDup);                                \
588         status &= nmf->validateFormat##func(fmtDup, offset, true); \
589         AMediaFormat_delete(fmtOrig);                              \
590         AMediaFormat_delete(fmtDup);                               \
591         delete nmf;                                                \
592         return status;                                             \
593     }
594 
595 testMediaFormatfuncNative(Int32)
596 
testMediaFormatfuncNative(Int64)597 testMediaFormatfuncNative(Int64)
598 
599 testMediaFormatfuncNative(Float)
600 
601 testMediaFormatfuncNative(Double)
602 
603 testMediaFormatfuncNative(Size)
604 
605 testMediaFormatfuncNative(String)
606 
607 testMediaFormatfuncNative(Rect)
608 
609 testMediaFormatfuncNative(Buffer)
610 
611 #define nativeTestMediaFormatfunc(func)                                \
612     static jboolean nativeTestMediaFormat##func(JNIEnv*, jobject) {    \
613         return static_cast<jboolean>(testMediaFormat##func##Native()); \
614     }
615 
616 //@ApiTest(apis = {"AMediaFormat_getInt32", "AMediaFormat_setInt32",
617 //                 "AMediaFormat_copy", "AMediaFormat_clear", "AMediaFormat_toString",
618 //                 "AMediaFormat_new", "AMediaFormat_delete"})
619 nativeTestMediaFormatfunc(Int32)
620 
621 //@ApiTest(apis = {"AMediaFormat_getInt64", "AMediaFormat_setInt64",
622 //                 "AMediaFormat_copy", "AMediaFormat_clear", "AMediaFormat_toString",
623 //                 "AMediaFormat_new", "AMediaFormat_delete"})
624 nativeTestMediaFormatfunc(Int64)
625 
626 //@ApiTest(apis = {"AMediaFormat_getFloat", "AMediaFormat_setFloat",
627 //                 "AMediaFormat_copy", "AMediaFormat_clear", "AMediaFormat_toString",
628 //                 "AMediaFormat_new", "AMediaFormat_delete"})
629 nativeTestMediaFormatfunc(Float)
630 
631 //@ApiTest(apis = {"AMediaFormat_getDouble", "AMediaFormat_setDouble",
632 //                 "AMediaFormat_copy", "AMediaFormat_clear", "AMediaFormat_toString",
633 //                 "AMediaFormat_new", "AMediaFormat_delete"})
634 nativeTestMediaFormatfunc(Double)
635 
636 //@ApiTest(apis = {"AMediaFormat_getSize", "AMediaFormat_setSize",
637 //                 "AMediaFormat_copy", "AMediaFormat_clear", "AMediaFormat_toString",
638 //                 "AMediaFormat_new", "AMediaFormat_delete"})
639 nativeTestMediaFormatfunc(Size)
640 
641 //@ApiTest(apis = {"AMediaFormat_getString", "AMediaFormat_setString",
642 //                 "AMediaFormat_copy", "AMediaFormat_clear", "AMediaFormat_toString",
643 //                 "AMediaFormat_new", "AMediaFormat_delete"})
644 nativeTestMediaFormatfunc(String)
645 
646 //@ApiTest(apis = {"AMediaFormat_getRect", "AMediaFormat_setRect",
647 //                 "AMediaFormat_copy", "AMediaFormat_clear", "AMediaFormat_toString",
648 //                 "AMediaFormat_new", "AMediaFormat_delete"})
649 nativeTestMediaFormatfunc(Rect)
650 
651 //@ApiTest(apis = {"AMediaFormat_getBuffer", "AMediaFormat_setBuffer",
652 //                 "AMediaFormat_copy", "AMediaFormat_clear", "AMediaFormat_toString",
653 //                 "AMediaFormat_new", "AMediaFormat_delete"})
654 nativeTestMediaFormatfunc(Buffer)
655 
656 //@ApiTest(apis = {"AMediaFormat_getInt32", "AMediaFormat_setInt32",
657 //                 "AMediaFormat_getInt64", "AMediaFormat_setInt64",
658 //                 "AMediaFormat_getFloat", "AMediaFormat_setFloat",
659 //                 "AMediaFormat_getDouble", "AMediaFormat_setDouble",
660 //                 "AMediaFormat_getString", "AMediaFormat_setString",
661 //                 "AMediaFormat_getSize", "AMediaFormat_setSize",
662 //                 "AMediaFormat_getRect", "AMediaFormat_setRect",
663 //                 "AMediaFormat_getBuffer", "AMediaFormat_setBuffer",
664 //                 "AMediaFormat_copy", "AMediaFormat_clear", "AMediaFormat_toString",
665 //                 "AMediaFormat_new", "AMediaFormat_delete"})
666 nativeTestMediaFormatfunc(All)
667 
668 int registerAndroidMediaV2CtsMediaFormatUnitTest(JNIEnv* env) {
669     const JNINativeMethod methodTable[] = {
670             {"nativeTestMediaFormatInt32", "()Z", (void*)nativeTestMediaFormatInt32},
671             {"nativeTestMediaFormatInt64", "()Z", (void*)nativeTestMediaFormatInt64},
672             {"nativeTestMediaFormatFloat", "()Z", (void*)nativeTestMediaFormatFloat},
673             {"nativeTestMediaFormatDouble", "()Z", (void*)nativeTestMediaFormatDouble},
674             {"nativeTestMediaFormatSize", "()Z", (void*)nativeTestMediaFormatSize},
675             {"nativeTestMediaFormatString", "()Z", (void*)nativeTestMediaFormatString},
676             {"nativeTestMediaFormatRect", "()Z", (void*)nativeTestMediaFormatRect},
677             {"nativeTestMediaFormatBuffer", "()Z", (void*)nativeTestMediaFormatBuffer},
678             {"nativeTestMediaFormatAll", "()Z", (void*)nativeTestMediaFormatAll},
679     };
680     jclass c = env->FindClass("android/mediav2/cts/MediaFormatUnitTest");
681     return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
682 }
683 
JNI_OnLoad(JavaVM * vm,void *)684 extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
685     JNIEnv* env;
686     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) return JNI_ERR;
687     if (registerAndroidMediaV2CtsMediaFormatUnitTest(env) != JNI_OK) return JNI_ERR;
688     return JNI_VERSION_1_6;
689 }
690