1 /*
2 * Copyright (C) 2020 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 "MetaDataUtilsTest"
19 #include <utils/Log.h>
20
21 #include <fstream>
22 #include <memory>
23 #include <string>
24
25 #include <media/esds/ESDS.h>
26 #include <media/NdkMediaFormat.h>
27 #include <media/stagefright/MediaCodecConstants.h>
28 #include <media/stagefright/MediaDefs.h>
29 #include <media/stagefright/MetaDataBase.h>
30 #include <media/stagefright/MetaDataUtils.h>
31 #include <media/stagefright/foundation/ABitReader.h>
32
33 #include "MetaDataUtilsTestEnvironment.h"
34
35 constexpr uint8_t kAdtsCsdSize = 7;
36 // from AAC specs: https://www.iso.org/standard/43345.html
37 constexpr int32_t kSamplingFreq[] = {96000, 88200, 64000, 48000, 44100, 32000,
38 24000, 22050, 16000, 12000, 11025, 8000};
39 constexpr uint8_t kMaxSamplingFreqIndex = sizeof(kSamplingFreq) / sizeof(kSamplingFreq[0]);
40
41 static MetaDataUtilsTestEnvironment *gEnv = nullptr;
42
43 using namespace android;
44
45 class MetaDataValidate {
46 public:
MetaDataValidate()47 MetaDataValidate() : mInputBuffer(nullptr) {}
48
~MetaDataValidate()49 ~MetaDataValidate() {
50 if (mInputBuffer) {
51 delete[] mInputBuffer;
52 mInputBuffer = nullptr;
53 }
54 }
55
SetUpMetaDataValidate(string fileName)56 void SetUpMetaDataValidate(string fileName) {
57 struct stat buf;
58 int8_t err = stat(fileName.c_str(), &buf);
59 ASSERT_EQ(err, 0) << "Failed to get file information for file: " << fileName;
60
61 mInputBufferSize = buf.st_size;
62 FILE *inputFilePtr = fopen(fileName.c_str(), "rb+");
63 ASSERT_NE(inputFilePtr, nullptr) << "Failed to open file: " << fileName;
64
65 mInputBuffer = new uint8_t[mInputBufferSize];
66 ASSERT_NE(mInputBuffer, nullptr)
67 << "Failed to allocate memory of size: " << mInputBufferSize;
68
69 int32_t numBytes =
70 fread((char *)mInputBuffer, sizeof(uint8_t), mInputBufferSize, inputFilePtr);
71 ASSERT_EQ(numBytes, mInputBufferSize) << numBytes << " of " << mInputBufferSize << " read";
72
73 fclose(inputFilePtr);
74 }
75
76 size_t mInputBufferSize;
77 const uint8_t *mInputBuffer;
78 };
79
80 class AvcCSDTest : public ::testing::TestWithParam<
81 tuple<string /*inputFile*/, size_t /*avcWidth*/, size_t /*avcHeight*/>> {
82 public:
AvcCSDTest()83 AvcCSDTest() : mInputBuffer(nullptr) {}
84
~AvcCSDTest()85 ~AvcCSDTest() {
86 if (mInputBuffer) {
87 delete[] mInputBuffer;
88 mInputBuffer = nullptr;
89 }
90 }
SetUp()91 virtual void SetUp() override {
92 tuple<string, size_t, size_t> params = GetParam();
93 string inputFile = gEnv->getRes() + get<0>(params);
94 mFrameWidth = get<1>(params);
95 mFrameHeight = get<2>(params);
96
97 struct stat buf;
98 int8_t err = stat(inputFile.c_str(), &buf);
99 ASSERT_EQ(err, 0) << "Failed to get information for file: " << inputFile;
100
101 mInputBufferSize = buf.st_size;
102 FILE *inputFilePtr = fopen(inputFile.c_str(), "rb+");
103 ASSERT_NE(inputFilePtr, nullptr) << "Failed to open file: " << inputFile;
104
105 mInputBuffer = new uint8_t[mInputBufferSize];
106 ASSERT_NE(mInputBuffer, nullptr)
107 << "Failed to create a buffer of size: " << mInputBufferSize;
108
109 int32_t numBytes =
110 fread((char *)mInputBuffer, sizeof(uint8_t), mInputBufferSize, inputFilePtr);
111 ASSERT_EQ(numBytes, mInputBufferSize) << numBytes << " of " << mInputBufferSize << " read";
112
113 fclose(inputFilePtr);
114 }
115
116 size_t mFrameWidth;
117 size_t mFrameHeight;
118 size_t mInputBufferSize;
119 const uint8_t *mInputBuffer;
120 };
121
122 class AvcCSDValidateTest : public MetaDataValidate,
123 public ::testing::TestWithParam<string /*inputFile*/> {
124 public:
SetUp()125 virtual void SetUp() override {
126 string inputFile = gEnv->getRes() + GetParam();
127
128 ASSERT_NO_FATAL_FAILURE(SetUpMetaDataValidate(inputFile));
129 }
130 };
131
132 class AacCSDTest
133 : public ::testing::TestWithParam<tuple<uint32_t /*profile*/, uint32_t /*samplingFreqIndex*/,
134 uint32_t /*channelConfig*/>> {
135 public:
SetUp()136 virtual void SetUp() override {
137 tuple<uint32_t, uint32_t, uint32_t> params = GetParam();
138 mAacProfile = get<0>(params);
139 mAacSamplingFreqIndex = get<1>(params);
140 mAacChannelConfig = get<2>(params);
141 }
142
143 uint32_t mAacProfile;
144 uint32_t mAacSamplingFreqIndex;
145 uint32_t mAacChannelConfig;
146 };
147
148 class AacADTSTest
149 : public ::testing::TestWithParam<
150 tuple<string /*adtsFile*/, uint32_t /*channelCount*/, uint32_t /*sampleRate*/>> {
151 public:
AacADTSTest()152 AacADTSTest() : mInputBuffer(nullptr) {}
153
SetUp()154 virtual void SetUp() override {
155 tuple<string, uint32_t, uint32_t> params = GetParam();
156 string fileName = gEnv->getRes() + get<0>(params);
157 mAacChannelCount = get<1>(params);
158 mAacSampleRate = get<2>(params);
159
160 FILE *filePtr = fopen(fileName.c_str(), "r");
161 ASSERT_NE(filePtr, nullptr) << "Failed to open file: " << fileName;
162
163 mInputBuffer = new uint8_t[kAdtsCsdSize];
164 ASSERT_NE(mInputBuffer, nullptr) << "Failed to allocate a memory of size: " << kAdtsCsdSize;
165
166 int32_t numBytes = fread((void *)mInputBuffer, sizeof(uint8_t), kAdtsCsdSize, filePtr);
167 ASSERT_EQ(numBytes, kAdtsCsdSize)
168 << "Failed to read complete file, bytes read: " << numBytes;
169
170 fclose(filePtr);
171 }
172 int32_t mAacChannelCount;
173 int32_t mAacSampleRate;
174 const uint8_t *mInputBuffer;
175 };
176
177 class AacCSDValidateTest : public MetaDataValidate,
178 public ::testing::TestWithParam<string /*inputFile*/> {
179 public:
SetUp()180 virtual void SetUp() override {
181 string inputFile = gEnv->getRes() + GetParam();
182
183 ASSERT_NO_FATAL_FAILURE(SetUpMetaDataValidate(inputFile));
184 }
185 };
186
187 class VorbisTest : public ::testing::TestWithParam<pair<string /*fileName*/, string /*infoFile*/>> {
188 public:
SetUp()189 virtual void SetUp() override {
190 pair<string, string> params = GetParam();
191 string inputMediaFile = gEnv->getRes() + params.first;
192 mInputFileStream.open(inputMediaFile, ifstream::in);
193 ASSERT_TRUE(mInputFileStream.is_open()) << "Failed to open data file: " << inputMediaFile;
194
195 string inputInfoFile = gEnv->getRes() + params.second;
196 mInfoFileStream.open(inputInfoFile, ifstream::in);
197 ASSERT_TRUE(mInputFileStream.is_open()) << "Failed to open data file: " << inputInfoFile;
198 ASSERT_FALSE(inputInfoFile.empty()) << "Empty info file: " << inputInfoFile;
199 }
200
~VorbisTest()201 ~VorbisTest() {
202 if (mInputFileStream.is_open()) mInputFileStream.close();
203 if (mInfoFileStream.is_open()) mInfoFileStream.close();
204 }
205
206 ifstream mInputFileStream;
207 ifstream mInfoFileStream;
208 };
209
TEST_P(AvcCSDTest,AvcCSDValidationTest)210 TEST_P(AvcCSDTest, AvcCSDValidationTest) {
211 AMediaFormat *csdData = AMediaFormat_new();
212 ASSERT_NE(csdData, nullptr) << "Failed to create AMedia format";
213
214 bool status = MakeAVCCodecSpecificData(csdData, mInputBuffer, mInputBufferSize);
215 ASSERT_TRUE(status) << "Failed to make AVC CSD from AMediaFormat";
216
217 int32_t avcWidth = -1;
218 status = AMediaFormat_getInt32(csdData, AMEDIAFORMAT_KEY_WIDTH, &avcWidth);
219 ASSERT_TRUE(status) << "Failed to get avc width";
220 ASSERT_EQ(avcWidth, mFrameWidth);
221
222 int32_t avcHeight = -1;
223 status = AMediaFormat_getInt32(csdData, AMEDIAFORMAT_KEY_HEIGHT, &avcHeight);
224 ASSERT_TRUE(status) << "Failed to get avc height";
225 ASSERT_EQ(avcHeight, mFrameHeight);
226
227 const char *mimeType = "";
228 status = AMediaFormat_getString(csdData, AMEDIAFORMAT_KEY_MIME, &mimeType);
229 ASSERT_TRUE(status) << "Failed to get the mime type";
230 ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_VIDEO_AVC);
231
232 std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
233 ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
234
235 status = MakeAVCCodecSpecificData(*metaData, mInputBuffer, mInputBufferSize);
236 ASSERT_TRUE(status) << "Failed to make AVC CSD from MetaDataBase";
237
238 avcWidth = -1;
239 status = metaData->findInt32(kKeyWidth, &avcWidth);
240 ASSERT_TRUE(status) << "Failed to find the width";
241 ASSERT_EQ(avcWidth, mFrameWidth);
242
243 avcHeight = -1;
244 status = metaData->findInt32(kKeyHeight, &avcHeight);
245 ASSERT_TRUE(status) << "Failed to find the height";
246 ASSERT_EQ(avcHeight, mFrameHeight);
247
248 void *csdAMediaFormatBuffer = nullptr;
249 size_t csdAMediaFormatSize;
250 status = AMediaFormat_getBuffer(csdData, AMEDIAFORMAT_KEY_CSD_AVC, &csdAMediaFormatBuffer,
251 &csdAMediaFormatSize);
252 ASSERT_TRUE(status) << "Failed to get the CSD from AMediaFormat";
253 ASSERT_NE(csdAMediaFormatBuffer, nullptr) << "Invalid CSD from AMediaFormat";
254
255 const void *csdMetaDataBaseBuffer = nullptr;
256 size_t csdMetaDataBaseSize = 0;
257 uint32_t mediaType;
258 status = metaData->findData(kKeyAVCC, &mediaType, &csdMetaDataBaseBuffer, &csdMetaDataBaseSize);
259 ASSERT_TRUE(status) << "Failed to get the CSD from MetaDataBase";
260 ASSERT_NE(csdMetaDataBaseBuffer, nullptr) << "Invalid CSD from MetaDataBase";
261 ASSERT_GT(csdMetaDataBaseSize, 0) << "CSD size must be greater than 0";
262 ASSERT_EQ(csdMetaDataBaseSize, csdAMediaFormatSize)
263 << "CSD size of MetaData type and AMediaFormat type must be same";
264
265 int32_t result = memcmp(csdAMediaFormatBuffer, csdMetaDataBaseBuffer, csdAMediaFormatSize);
266 ASSERT_EQ(result, 0) << "CSD from AMediaFormat and MetaDataBase do not match";
267
268 AMediaFormat_delete(csdData);
269 }
270
TEST_P(AvcCSDValidateTest,AvcValidateTest)271 TEST_P(AvcCSDValidateTest, AvcValidateTest) {
272 AMediaFormat *csdData = AMediaFormat_new();
273 ASSERT_NE(csdData, nullptr) << "Failed to create AMedia format";
274
275 bool status = MakeAVCCodecSpecificData(csdData, mInputBuffer, mInputBufferSize);
276 ASSERT_FALSE(status) << "MakeAVCCodecSpecificData with AMediaFormat succeeds with invalid data";
277
278 std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
279 ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
280
281 status = MakeAVCCodecSpecificData(*metaData, mInputBuffer, mInputBufferSize);
282 ASSERT_FALSE(status) << "MakeAVCCodecSpecificData with MetaDataBase succeeds with invalid data";
283 }
284
TEST_P(AacCSDTest,AacCSDValidationTest)285 TEST_P(AacCSDTest, AacCSDValidationTest) {
286 AMediaFormat *csdData = AMediaFormat_new();
287 ASSERT_NE(csdData, nullptr) << "Failed to create AMedia format";
288
289 ASSERT_GE(mAacSamplingFreqIndex, 0);
290 ASSERT_LT(mAacSamplingFreqIndex, kMaxSamplingFreqIndex);
291 bool status = MakeAACCodecSpecificData(csdData, mAacProfile, mAacSamplingFreqIndex,
292 mAacChannelConfig);
293 ASSERT_TRUE(status) << "Failed to make AAC CSD from AMediaFormat";
294
295 int32_t sampleRate = -1;
296 status = AMediaFormat_getInt32(csdData, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sampleRate);
297 ASSERT_TRUE(status) << "Failed to get sample rate";
298 ASSERT_EQ(kSamplingFreq[mAacSamplingFreqIndex], sampleRate);
299
300 int32_t channelCount = -1;
301 status = AMediaFormat_getInt32(csdData, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &channelCount);
302 ASSERT_TRUE(status) << "Failed to get channel count";
303 ASSERT_EQ(channelCount, mAacChannelConfig);
304
305 const char *mimeType = "";
306 status = AMediaFormat_getString(csdData, AMEDIAFORMAT_KEY_MIME, &mimeType);
307 ASSERT_TRUE(status) << "Failed to get the mime type";
308 ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_AUDIO_AAC);
309
310 std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
311 ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
312
313 status = MakeAACCodecSpecificData(*metaData, mAacProfile, mAacSamplingFreqIndex,
314 mAacChannelConfig);
315 ASSERT_TRUE(status) << "Failed to make AAC CSD from MetaDataBase";
316
317 sampleRate = -1;
318 status = metaData->findInt32(kKeySampleRate, &sampleRate);
319 ASSERT_TRUE(status) << "Failed to get sampling rate";
320 ASSERT_EQ(kSamplingFreq[mAacSamplingFreqIndex], sampleRate);
321
322 channelCount = -1;
323 status = metaData->findInt32(kKeyChannelCount, &channelCount);
324 ASSERT_TRUE(status) << "Failed to get channel count";
325 ASSERT_EQ(channelCount, mAacChannelConfig);
326
327 mimeType = "";
328 status = metaData->findCString(kKeyMIMEType, &mimeType);
329 ASSERT_TRUE(status) << "Failed to get mime type";
330 ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_AUDIO_AAC);
331
332 void *csdAMediaFormatBuffer = nullptr;
333 size_t csdAMediaFormatSize = 0;
334 status = AMediaFormat_getBuffer(csdData, AMEDIAFORMAT_KEY_CSD_0, &csdAMediaFormatBuffer,
335 &csdAMediaFormatSize);
336 ASSERT_TRUE(status) << "Failed to get the AMediaFormat CSD";
337 ASSERT_GT(csdAMediaFormatSize, 0) << "CSD size must be greater than 0";
338 ASSERT_NE(csdAMediaFormatBuffer, nullptr) << "Invalid CSD found";
339
340 const void *csdMetaDataBaseBuffer;
341 size_t csdMetaDataBaseSize = 0;
342 uint32_t mediaType;
343 status = metaData->findData(kKeyESDS, &mediaType, &csdMetaDataBaseBuffer, &csdMetaDataBaseSize);
344 ASSERT_TRUE(status) << "Failed to get the ESDS data from MetaDataBase";
345 ASSERT_GT(csdMetaDataBaseSize, 0) << "CSD size must be greater than 0";
346
347 ESDS esds(csdMetaDataBaseBuffer, csdMetaDataBaseSize);
348 status_t result = esds.getCodecSpecificInfo(&csdMetaDataBaseBuffer, &csdMetaDataBaseSize);
349 ASSERT_EQ(result, (status_t)OK) << "Failed to get CSD from ESDS data";
350 ASSERT_NE(csdMetaDataBaseBuffer, nullptr) << "Invalid CSD found";
351 ASSERT_EQ(csdAMediaFormatSize, csdMetaDataBaseSize)
352 << "CSD size do not match between AMediaFormat type and MetaDataBase type";
353
354 int32_t memcmpResult =
355 memcmp(csdAMediaFormatBuffer, csdMetaDataBaseBuffer, csdAMediaFormatSize);
356 ASSERT_EQ(memcmpResult, 0) << "AMediaFormat and MetaDataBase CSDs do not match";
357
358 AMediaFormat_delete(csdData);
359 }
360
TEST_P(AacADTSTest,AacADTSValidationTest)361 TEST_P(AacADTSTest, AacADTSValidationTest) {
362 std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
363 ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
364
365 bool status = MakeAACCodecSpecificData(*metaData, mInputBuffer, kAdtsCsdSize);
366 ASSERT_TRUE(status) << "Failed to make AAC CSD from MetaDataBase";
367
368 int32_t sampleRate = -1;
369 status = metaData->findInt32(kKeySampleRate, &sampleRate);
370 ASSERT_TRUE(status) << "Failed to get sampling rate";
371 ASSERT_EQ(sampleRate, mAacSampleRate);
372
373 int32_t channelCount = -1;
374 status = metaData->findInt32(kKeyChannelCount, &channelCount);
375 ASSERT_TRUE(status) << "Failed to get channel count";
376 ASSERT_EQ(channelCount, mAacChannelCount);
377
378 const char *mimeType = "";
379 status = metaData->findCString(kKeyMIMEType, &mimeType);
380 ASSERT_TRUE(status) << "Failed to get mime type";
381 ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_AUDIO_AAC);
382 }
383
TEST_P(AacCSDValidateTest,AacInvalidInputTest)384 TEST_P(AacCSDValidateTest, AacInvalidInputTest) {
385 std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
386 ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
387
388 bool status = MakeAACCodecSpecificData(*metaData, mInputBuffer, kAdtsCsdSize);
389 ASSERT_FALSE(status) << "MakeAACCodecSpecificData succeeds with invalid data";
390 }
391
TEST_P(VorbisTest,VorbisCommentTest)392 TEST_P(VorbisTest, VorbisCommentTest) {
393 string line;
394 string tag;
395 string key;
396 string value;
397 size_t commentLength;
398 bool status;
399
400 while (getline(mInfoFileStream, line)) {
401 istringstream stringLine(line);
402 stringLine >> tag >> key >> value >> commentLength;
403 ASSERT_GT(commentLength, 0) << "Vorbis comment size must be greater than 0";
404
405 string comment;
406 string dataLine;
407
408 getline(mInputFileStream, dataLine);
409 istringstream dataStringLine(dataLine);
410 dataStringLine >> comment;
411
412 std::unique_ptr<char[]> buffer(new char[commentLength]);
413 ASSERT_NE(buffer, nullptr) << "Failed to allocate buffer of size: " << commentLength;
414 strncpy(buffer.get(), comment.c_str(), commentLength);
415
416 AMediaFormat *fileMeta = AMediaFormat_new();
417 ASSERT_NE(fileMeta, nullptr) << "Failed to create AMedia format";
418
419 parseVorbisComment(fileMeta, buffer.get(), commentLength);
420
421 if (!strncasecmp(tag.c_str(), "ANDROID_HAPTIC", sizeof(tag))) {
422 int32_t numChannelExpected = stoi(value);
423 int32_t numChannelFound = -1;
424 status = AMediaFormat_getInt32(fileMeta, key.c_str(), &numChannelFound);
425 ASSERT_TRUE(status) << "Failed to get the channel count";
426 ASSERT_EQ(numChannelExpected, numChannelFound);
427 } else if (!strncasecmp(tag.c_str(), "ANDROID_LOOP", sizeof(tag))) {
428 int32_t loopExpected = !value.compare("true");
429 int32_t loopFound = -1;
430
431 status = AMediaFormat_getInt32(fileMeta, "loop", &loopFound);
432 ASSERT_TRUE(status) << "Failed to get the loop count";
433 ASSERT_EQ(loopExpected, loopFound);
434 } else {
435 const char *tagValue = "";
436 status = AMediaFormat_getString(fileMeta, key.c_str(), &tagValue);
437 ASSERT_TRUE(status) << "Failed to get the tag value";
438 ASSERT_STREQ(value.c_str(), tagValue);
439 }
440 AMediaFormat_delete(fileMeta);
441 }
442 }
443
444 INSTANTIATE_TEST_SUITE_P(MetaDataUtilsTestAll, AvcCSDTest,
445 ::testing::Values(make_tuple("sps_pps_userdata.h264", 8, 8),
446 make_tuple("sps_userdata_pps.h264", 8, 8),
447 make_tuple("sps_pps_sps_pps.h264", 8, 8)));
448
449 // TODO(b/158067691): Add invalid test vectors with incomplete PPS or no PPS
450 INSTANTIATE_TEST_SUITE_P(MetaDataUtilsTestAll, AvcCSDValidateTest,
451 ::testing::Values("sps_pps_only_startcode.h264",
452 "sps_incomplete_pps.h264",
453 // TODO(b/158067691) "sps_pps_incomplete.h264",
454 "randomdata.h264",
455 // TODO(b/158067691) "sps.h264",
456 "pps.h264"));
457
458 INSTANTIATE_TEST_SUITE_P(MetaDataUtilsTestAll, AacCSDTest,
459 ::testing::Values(make_tuple(AACObjectMain, 1, 1)));
460
461 INSTANTIATE_TEST_SUITE_P(MetaDataUtilsTestAll, AacADTSTest,
462 ::testing::Values(make_tuple("loudsoftaacadts", 1, 44100)));
463
464 INSTANTIATE_TEST_SUITE_P(MetaDataUtilsTestAll, AacCSDValidateTest,
465 ::testing::Values("loudsoftaacadts_invalidheader",
466 "loudsoftaacadts_invalidprofile",
467 "loudsoftaacadts_invalidchannelconfig"));
468
469 // TODO(b/157974508) Add test vector for vorbis thumbnail tag
470 // Info file contains TAG, Key, Value and size of the vorbis comment
471 INSTANTIATE_TEST_SUITE_P(
472 MetaDataUtilsTestAll, VorbisTest,
473 ::testing::Values(make_pair("vorbiscomment_sintel.dat", "vorbiscomment_sintel.info"),
474 make_pair("vorbiscomment_album.dat", "vorbiscomment_album.info"),
475 make_pair("vorbiscomment_loop.dat", "vorbiscomment_loop.info")));
476
main(int argc,char ** argv)477 int main(int argc, char **argv) {
478 gEnv = new MetaDataUtilsTestEnvironment();
479 ::testing::AddGlobalTestEnvironment(gEnv);
480 ::testing::InitGoogleTest(&argc, argv);
481 int status = gEnv->initFromOptions(argc, argv);
482 if (status == 0) {
483 status = RUN_ALL_TESTS();
484 ALOGV("Test result = %d\n", status);
485 }
486 return status;
487 }
488