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 // Unit Test for ECOSession.
18 
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "ECOSessionTest"
21 
22 #include <android-base/unique_fd.h>
23 #include <android/binder_auto_utils.h>
24 #include <android/binder_parcel.h>
25 #include <cutils/ashmem.h>
26 #include <gtest/gtest.h>
27 #include <math.h>
28 #include <stdlib.h>
29 #include <sys/mman.h>
30 #include <utils/Log.h>
31 #include <utils/Timers.h>
32 
33 #include "FakeECOServiceInfoListener.h"
34 #include "FakeECOServiceStatsProvider.h"
35 #include "eco/ECOSession.h"
36 #include "eco/ECOUtils.h"
37 
38 namespace android {
39 namespace media {
40 namespace eco {
41 
42 using ::ndk::ScopedAStatus;
43 
44 static constexpr uint32_t kTestWidth = 1280;
45 static constexpr uint32_t kTestHeight = 720;
46 static constexpr bool kIsCameraRecording = true;
47 static constexpr int32_t kTargetBitrateBps = 22000000;
48 static constexpr int32_t kKeyFrameIntervalFrames = 30;
49 static constexpr float kFrameRate = 30.0f;
50 
51 // A helpful class to help create ECOSession and manage ECOSession.
52 class EcoSessionTest : public ::testing::Test {
53 public:
EcoSessionTest()54     EcoSessionTest() { ALOGD("EcoSessionTest created"); }
55 
createSession(int32_t width,int32_t height,bool isCameraRecording)56     std::shared_ptr<ECOSession> createSession(int32_t width, int32_t height,
57                                               bool isCameraRecording) {
58         mSession = ECOSession::createECOSession(width, height, isCameraRecording);
59         if (mSession == nullptr) return nullptr;
60         return mSession;
61     }
62 
63 private:
64     std::shared_ptr<ECOSession> mSession = nullptr;
65 };
66 
TEST_F(EcoSessionTest,TestConstructorWithInvalidParameters)67 TEST_F(EcoSessionTest, TestConstructorWithInvalidParameters) {
68     // Expects failure as ECOService1.0 will only support up to 720P and camera recording case.
69     EXPECT_TRUE(createSession(1920 /* width */, 1080 /* height */, true /* isCameraRecording */) ==
70                 nullptr);
71 
72     // Expects failure as ECOService1.0 will only support up to 720P and camera recording case.
73     EXPECT_TRUE(createSession(1920 /* width */, 1080 /* height */, false /* isCameraRecording */) ==
74                 nullptr);
75 
76     EXPECT_TRUE(createSession(1920 /* width */, -1 /* height */, true /* isCameraRecording */) ==
77                 nullptr);
78 
79     EXPECT_TRUE(createSession(-1 /* width */, 1080 /* height */, true /* isCameraRecording */) ==
80                 nullptr);
81 }
82 
TEST_F(EcoSessionTest,TestConstructorWithValidParameters)83 TEST_F(EcoSessionTest, TestConstructorWithValidParameters) {
84     // Expects success with <= 720P and is for camera recording.
85     EXPECT_TRUE(createSession(1280 /* width */, 720 /* height */, true /* isCameraRecording */) !=
86                 nullptr);
87 
88     // Expects success with <= 720P and is for camera recording.
89     EXPECT_TRUE(createSession(640 /* width */, 480 /* height */, true /* isCameraRecording */) !=
90                 nullptr);
91 }
92 
TEST_F(EcoSessionTest,TestAddProviderWithoutSpecifyEcoDataType)93 TEST_F(EcoSessionTest, TestAddProviderWithoutSpecifyEcoDataType) {
94     std::shared_ptr<ECOSession> ecoSession =
95             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
96     EXPECT_TRUE(ecoSession);
97 
98     std::shared_ptr<FakeECOServiceStatsProvider> fakeProvider =
99             ndk::SharedRefBase::make<FakeECOServiceStatsProvider>(
100                     kTestWidth, kTestHeight, kIsCameraRecording, kFrameRate, ecoSession);
101 
102     ECOData providerConfig;
103     bool res;
104     ScopedAStatus status = ecoSession->addStatsProvider(fakeProvider, providerConfig, &res);
105     EXPECT_FALSE(status.isOk());
106 }
107 
TEST_F(EcoSessionTest,TestAddProviderWithWrongEcoDataType)108 TEST_F(EcoSessionTest, TestAddProviderWithWrongEcoDataType) {
109     std::shared_ptr<ECOSession> ecoSession =
110             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
111     EXPECT_TRUE(ecoSession);
112 
113     std::shared_ptr<FakeECOServiceStatsProvider> fakeProvider =
114             ndk::SharedRefBase::make<FakeECOServiceStatsProvider>(
115                     kTestWidth, kTestHeight, kIsCameraRecording, kFrameRate, ecoSession);
116 
117     ECOData providerConfig(ECOData::DATA_TYPE_INFO_LISTENER_CONFIG,
118                            systemTime(SYSTEM_TIME_BOOTTIME));
119     bool res;
120     ScopedAStatus status = ecoSession->addStatsProvider(fakeProvider, providerConfig, &res);
121     EXPECT_FALSE(status.isOk());
122 }
123 
TEST_F(EcoSessionTest,TestAddNormalProvider)124 TEST_F(EcoSessionTest, TestAddNormalProvider) {
125     std::shared_ptr<ECOSession> ecoSession =
126             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
127     EXPECT_TRUE(ecoSession);
128 
129     std::shared_ptr<FakeECOServiceStatsProvider> fakeProvider =
130             ndk::SharedRefBase::make<FakeECOServiceStatsProvider>(
131                     kTestWidth, kTestHeight, kIsCameraRecording, kFrameRate, ecoSession);
132 
133     ECOData providerConfig(ECOData::DATA_TYPE_STATS_PROVIDER_CONFIG,
134                            systemTime(SYSTEM_TIME_BOOTTIME));
135     bool res;
136     ScopedAStatus status = ecoSession->addStatsProvider(fakeProvider, providerConfig, &res);
137     EXPECT_TRUE(status.isOk());
138 }
139 
140 // Add two providers and expect failure as ECOService1.0 only supports one provider and one
141 // listener.
TEST_F(EcoSessionTest,TestAddTwoProvider)142 TEST_F(EcoSessionTest, TestAddTwoProvider) {
143     std::shared_ptr<ECOSession> ecoSession =
144             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
145     EXPECT_TRUE(ecoSession);
146 
147     std::shared_ptr<FakeECOServiceStatsProvider> fakeProvider1 =
148             ndk::SharedRefBase::make<FakeECOServiceStatsProvider>(
149                     kTestWidth, kTestHeight, kIsCameraRecording, kFrameRate, ecoSession);
150 
151     ECOData providerConfig(ECOData::DATA_TYPE_STATS_PROVIDER_CONFIG,
152                            systemTime(SYSTEM_TIME_BOOTTIME));
153     bool res;
154     ScopedAStatus status = ecoSession->addStatsProvider(fakeProvider1, providerConfig, &res);
155     EXPECT_TRUE(status.isOk());
156 
157     std::shared_ptr<FakeECOServiceStatsProvider> fakeProvider2 =
158             ndk::SharedRefBase::make<FakeECOServiceStatsProvider>(
159                     kTestWidth, kTestHeight, kIsCameraRecording, kFrameRate, ecoSession);
160     status = ecoSession->addStatsProvider(fakeProvider2, providerConfig, &res);
161     EXPECT_FALSE(status.isOk());
162 }
163 
TEST_F(EcoSessionTest,TestAddListenerWithDifferentHeight)164 TEST_F(EcoSessionTest, TestAddListenerWithDifferentHeight) {
165     std::shared_ptr<ECOSession> ecoSession =
166             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
167     EXPECT_TRUE(ecoSession);
168 
169     std::shared_ptr<FakeECOServiceInfoListener> fakeListener =
170             ndk::SharedRefBase::make<FakeECOServiceInfoListener>(kTestWidth - 1, kTestHeight,
171                                                                  kIsCameraRecording, ecoSession);
172 
173     ECOData ListenerConfig(ECOData::DATA_TYPE_INFO_LISTENER_CONFIG,
174                            systemTime(SYSTEM_TIME_BOOTTIME));
175     bool res;
176     ScopedAStatus status = ecoSession->addInfoListener(fakeListener, ListenerConfig, &res);
177     EXPECT_FALSE(status.isOk());
178 }
179 
TEST_F(EcoSessionTest,TestAddListenerWithDifferentWidth)180 TEST_F(EcoSessionTest, TestAddListenerWithDifferentWidth) {
181     std::shared_ptr<ECOSession> ecoSession =
182             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
183     EXPECT_TRUE(ecoSession);
184 
185     std::shared_ptr<FakeECOServiceInfoListener> fakeListener =
186             ndk::SharedRefBase::make<FakeECOServiceInfoListener>(kTestWidth, kTestHeight - 1,
187                                                                  kIsCameraRecording, ecoSession);
188 
189     ECOData ListenerConfig(ECOData::DATA_TYPE_INFO_LISTENER_CONFIG,
190                            systemTime(SYSTEM_TIME_BOOTTIME));
191     bool res;
192     ScopedAStatus status = ecoSession->addInfoListener(fakeListener, ListenerConfig, &res);
193     EXPECT_FALSE(status.isOk());
194 }
195 
TEST_F(EcoSessionTest,TestAddListenerWithCameraRecordingFalse)196 TEST_F(EcoSessionTest, TestAddListenerWithCameraRecordingFalse) {
197     std::shared_ptr<ECOSession> ecoSession =
198             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
199     EXPECT_TRUE(ecoSession);
200 
201     std::shared_ptr<FakeECOServiceInfoListener> fakeListener =
202             ndk::SharedRefBase::make<FakeECOServiceInfoListener>(kTestWidth, kTestHeight,
203                                                                  !kIsCameraRecording, ecoSession);
204 
205     ECOData ListenerConfig(ECOData::DATA_TYPE_INFO_LISTENER_CONFIG,
206                            systemTime(SYSTEM_TIME_BOOTTIME));
207     bool res;
208     ScopedAStatus status = ecoSession->addInfoListener(fakeListener, ListenerConfig, &res);
209     EXPECT_FALSE(status.isOk());
210 }
211 
212 // Test the ECOSession with FakeECOServiceStatsProvider and FakeECOServiceInfoListener. Push the
213 // stats to ECOSession through FakeECOServiceStatsProvider and check the info received in
214 // from FakeECOServiceInfoListener ECOSession.
TEST_F(EcoSessionTest,TestSessionWithProviderAndListenerSimpleTest)215 TEST_F(EcoSessionTest, TestSessionWithProviderAndListenerSimpleTest) {
216     // The time that listener needs to wait for the info from ECOService.
217     static constexpr int kServiceWaitTimeMs = 10;
218 
219     // Create the session.
220     std::shared_ptr<ECOSession> ecoSession =
221             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
222 
223     // Add provider.
224     std::shared_ptr<FakeECOServiceStatsProvider> fakeProvider =
225             ndk::SharedRefBase::make<FakeECOServiceStatsProvider>(
226                     kTestWidth, kTestHeight, kIsCameraRecording, kFrameRate, ecoSession);
227     ECOData providerConfig(ECOData::DATA_TYPE_STATS_PROVIDER_CONFIG,
228                            systemTime(SYSTEM_TIME_BOOTTIME));
229     providerConfig.setString(KEY_PROVIDER_NAME, "FakeECOServiceStatsProvider");
230     providerConfig.setInt32(KEY_PROVIDER_TYPE,
231                             ECOServiceStatsProvider::STATS_PROVIDER_TYPE_VIDEO_ENCODER);
232     bool res;
233     ScopedAStatus status = ecoSession->addStatsProvider(fakeProvider, providerConfig, &res);
234 
235     // Create listener.
236     std::shared_ptr<FakeECOServiceInfoListener> fakeListener =
237             ndk::SharedRefBase::make<FakeECOServiceInfoListener>(kTestWidth, kTestHeight,
238                                                                  kIsCameraRecording, ecoSession);
239 
240     // Create the listener config.
241     ECOData listenerConfig(ECOData::DATA_TYPE_INFO_LISTENER_CONFIG,
242                            systemTime(SYSTEM_TIME_BOOTTIME));
243     listenerConfig.setString(KEY_LISTENER_NAME, "FakeECOServiceInfoListener");
244     listenerConfig.setInt32(KEY_LISTENER_TYPE, ECOServiceInfoListener::INFO_LISTENER_TYPE_CAMERA);
245 
246     // Specify the qp thresholds for receiving notification.
247     listenerConfig.setInt32(KEY_LISTENER_QP_BLOCKINESS_THRESHOLD, 40);
248     listenerConfig.setInt32(KEY_LISTENER_QP_CHANGE_THRESHOLD, 5);
249 
250     status = ecoSession->addInfoListener(fakeListener, listenerConfig, &res);
251 
252     ECOData info;
253     bool getInfo = false;
254 
255     // Set the getInfo flag to true and copy the info from fakeListener.
256     fakeListener->setInfoAvailableCallback(
257             [&info, &getInfo](const ::android::media::eco::ECOData& newInfo) {
258                 getInfo = true;
259                 info = newInfo;
260             });
261 
262     // Inject the session stats into the ECOSession through fakeProvider.
263     SimpleEncoderConfig sessionEncoderConfig("google-avc", CodecTypeAVC, AVCProfileHigh, AVCLevel52,
264                                              kTargetBitrateBps, kKeyFrameIntervalFrames,
265                                              kFrameRate);
266     fakeProvider->injectSessionStats(sessionEncoderConfig.toEcoData(ECOData::DATA_TYPE_STATS));
267 
268     // Wait as ECOService may take some time to process.
269     std::this_thread::sleep_for(std::chrono::milliseconds(kServiceWaitTimeMs));
270     // Check the Session info matches with the session stats sent by provider.
271     EXPECT_TRUE(getInfo);
272     EXPECT_TRUE(info.getDataType() == ECOData::DATA_TYPE_INFO);
273 
274     std::string infoType;
275     EXPECT_TRUE(info.findString(KEY_INFO_TYPE, &infoType) == ECODataStatus::OK);
276     EXPECT_EQ(infoType, VALUE_INFO_TYPE_SESSION);
277 
278     // Check the session info matches the session stats provided by FakeECOServiceStatsProvider.
279     int32_t codecType;
280     EXPECT_TRUE(info.findInt32(ENCODER_TYPE, &codecType) == ECODataStatus::OK);
281     EXPECT_EQ(codecType, CodecTypeAVC);
282 
283     int32_t profile;
284     EXPECT_TRUE(info.findInt32(ENCODER_PROFILE, &profile) == ECODataStatus::OK);
285     EXPECT_EQ(profile, AVCProfileHigh);
286 
287     int32_t level;
288     EXPECT_TRUE(info.findInt32(ENCODER_LEVEL, &level) == ECODataStatus::OK);
289     EXPECT_EQ(level, AVCLevel52);
290 
291     int32_t bitrate;
292     EXPECT_TRUE(info.findInt32(ENCODER_TARGET_BITRATE_BPS, &bitrate) == ECODataStatus::OK);
293     EXPECT_EQ(bitrate, kTargetBitrateBps);
294 
295     int32_t kfi;
296     EXPECT_TRUE(info.findInt32(ENCODER_KFI_FRAMES, &kfi) == ECODataStatus::OK);
297     EXPECT_EQ(kfi, kKeyFrameIntervalFrames);
298 
299     // =======================================================================================
300     // Inject the frame stats with qp = 30. Expect receiving notification for the first frame.
301     SimpleEncodedFrameData frameStats(1 /* seq number */, FrameTypeI, 0 /* framePtsUs */,
302                                       30 /* avg-qp */, 56 /* frameSize */);
303 
304     getInfo = false;
305     fakeProvider->injectFrameStats(frameStats.toEcoData(ECOData::DATA_TYPE_STATS));
306     std::this_thread::sleep_for(std::chrono::milliseconds(kServiceWaitTimeMs));
307     // Check the Session info matches with the session stats sent by provider.
308     EXPECT_TRUE(getInfo);
309 
310     EXPECT_TRUE(info.findString(KEY_INFO_TYPE, &infoType) == ECODataStatus::OK);
311     EXPECT_EQ(infoType, VALUE_INFO_TYPE_FRAME);
312 
313     int8_t frameType;
314     EXPECT_TRUE(info.findInt8(FRAME_TYPE, &frameType) == ECODataStatus::OK);
315     EXPECT_EQ(frameType, FrameTypeI);
316 
317     int32_t frameNum;
318     EXPECT_TRUE(info.findInt32(FRAME_NUM, &frameNum) == ECODataStatus::OK);
319     EXPECT_EQ(frameNum, 1);
320 
321     int64_t framePtsUs;
322     EXPECT_TRUE(info.findInt64(FRAME_PTS_US, &framePtsUs) == ECODataStatus::OK);
323     EXPECT_EQ(framePtsUs, 0);
324 
325     int32_t frameQp;
326     EXPECT_TRUE(info.findInt32(FRAME_AVG_QP, &frameQp) == ECODataStatus::OK);
327     EXPECT_EQ(frameQp, 30);
328 
329     int32_t frameSize;
330     EXPECT_TRUE(info.findInt32(FRAME_SIZE_BYTES, &frameSize) == ECODataStatus::OK);
331     EXPECT_EQ(frameSize, 56);
332 
333     // =======================================================================================
334     // Inject the frame stats with qp = 35. Expect not receiving notification as 35 is below
335     // threshold.
336     frameStats = SimpleEncodedFrameData(2 /* seq number */, FrameTypeP, 333333 /* framePtsUs */,
337                                         35 /* avg-qp */, 56 /* frameSize */);
338     getInfo = false;
339     fakeProvider->injectFrameStats(frameStats.toEcoData(ECOData::DATA_TYPE_STATS));
340     // Wait as ECOService may take some time to process.
341     std::this_thread::sleep_for(std::chrono::milliseconds(kServiceWaitTimeMs));
342     EXPECT_FALSE(getInfo);
343 
344     // =======================================================================================
345     // Inject the frame stats with qp = 41. Expect receiving notification as 41 goes beyond
346     // threshold 40.
347     frameStats = SimpleEncodedFrameData(3 /* seq number */, FrameTypeP, 666666 /* framePtsUs */,
348                                         41 /* avg-qp */, 56 /* frameSize */);
349     getInfo = false;
350     fakeProvider->injectFrameStats(frameStats.toEcoData(ECOData::DATA_TYPE_STATS));
351     // Wait as ECOService may take some time to process.
352     std::this_thread::sleep_for(std::chrono::milliseconds(kServiceWaitTimeMs));
353 
354     // Check the frame info matches with the frame stats sent by provider.
355     EXPECT_TRUE(getInfo);
356     EXPECT_TRUE(info.findString(KEY_INFO_TYPE, &infoType) == ECODataStatus::OK);
357     EXPECT_EQ(infoType, VALUE_INFO_TYPE_FRAME);
358     EXPECT_TRUE(info.findInt8(FRAME_TYPE, &frameType) == ECODataStatus::OK);
359     EXPECT_EQ(frameType, FrameTypeP);
360     EXPECT_TRUE(info.findInt32(FRAME_NUM, &frameNum) == ECODataStatus::OK);
361     EXPECT_EQ(frameNum, 3);
362     EXPECT_TRUE(info.findInt64(FRAME_PTS_US, &framePtsUs) == ECODataStatus::OK);
363     EXPECT_EQ(framePtsUs, 666666);
364     EXPECT_TRUE(info.findInt32(FRAME_AVG_QP, &frameQp) == ECODataStatus::OK);
365     EXPECT_EQ(frameQp, 41);
366     EXPECT_TRUE(info.findInt32(FRAME_SIZE_BYTES, &frameSize) == ECODataStatus::OK);
367     EXPECT_EQ(frameSize, 56);
368 
369     // =======================================================================================
370     // Inject the frame stats with qp = 42. Expect not receiving notification as 42 goes beyond
371     // threshold 40 but delta oes not go beyond the mQpChangeThreshold threshold.
372     frameStats = SimpleEncodedFrameData(4 /* seq number */, FrameTypeP, 999999 /* framePtsUs */,
373                                         42 /* avg-qp */, 56 /* frameSize */);
374     getInfo = false;
375     fakeProvider->injectFrameStats(frameStats.toEcoData(ECOData::DATA_TYPE_STATS));
376     // Wait as ECOService may take some time to process.
377     std::this_thread::sleep_for(std::chrono::milliseconds(kServiceWaitTimeMs));
378     EXPECT_FALSE(getInfo);
379 
380     // =======================================================================================
381     // Inject the frame stats with qp = 10. Expect receiving notification as the detal from
382     // last reported QP is larger than threshold 4.
383     frameStats = SimpleEncodedFrameData(5 /* seq number */, FrameTypeB, 1333332 /* framePtsUs */,
384                                         49 /* avg-qp */, 56 /* frameSize */);
385     getInfo = false;
386     fakeProvider->injectFrameStats(frameStats.toEcoData(ECOData::DATA_TYPE_STATS));
387     // Wait as ECOService may take some time to process.
388     std::this_thread::sleep_for(std::chrono::milliseconds(kServiceWaitTimeMs));
389 
390     // Check the frame info matches with the frame stats sent by provider.
391     EXPECT_TRUE(getInfo);
392     EXPECT_TRUE(info.findString(KEY_INFO_TYPE, &infoType) == ECODataStatus::OK);
393     EXPECT_EQ(infoType, VALUE_INFO_TYPE_FRAME);
394     EXPECT_TRUE(info.findInt8(FRAME_TYPE, &frameType) == ECODataStatus::OK);
395     EXPECT_EQ(frameType, FrameTypeB);
396     EXPECT_TRUE(info.findInt32(FRAME_NUM, &frameNum) == ECODataStatus::OK);
397     EXPECT_EQ(frameNum, 5);
398     EXPECT_TRUE(info.findInt64(FRAME_PTS_US, &framePtsUs) == ECODataStatus::OK);
399     EXPECT_EQ(framePtsUs, 1333332);
400     EXPECT_TRUE(info.findInt32(FRAME_AVG_QP, &frameQp) == ECODataStatus::OK);
401     EXPECT_EQ(frameQp, 49);
402     EXPECT_TRUE(info.findInt32(FRAME_SIZE_BYTES, &frameSize) == ECODataStatus::OK);
403     EXPECT_EQ(frameSize, 56);
404 
405     // =======================================================================================
406     // Inject the frame stats with qp = 41. Expect receiving notification as the detal from
407     // last reported QP is larger than threshold 4.
408     frameStats = SimpleEncodedFrameData(6 /* seq number */, FrameTypeB, 1666665 /* framePtsUs */,
409                                         41 /* avg-qp */, 56 /* frameSize */);
410     getInfo = false;
411     fakeProvider->injectFrameStats(frameStats.toEcoData(ECOData::DATA_TYPE_STATS));
412     std::this_thread::sleep_for(std::chrono::milliseconds(kServiceWaitTimeMs));
413 
414     // Check the frame info matches with the frame stats sent by provider.
415     EXPECT_TRUE(getInfo);
416     EXPECT_TRUE(info.findString(KEY_INFO_TYPE, &infoType) == ECODataStatus::OK);
417     EXPECT_EQ(infoType, VALUE_INFO_TYPE_FRAME);
418     EXPECT_TRUE(info.findInt8(FRAME_TYPE, &frameType) == ECODataStatus::OK);
419     EXPECT_EQ(frameType, FrameTypeB);
420     EXPECT_TRUE(info.findInt32(FRAME_NUM, &frameNum) == ECODataStatus::OK);
421     EXPECT_EQ(frameNum, 6);
422     EXPECT_TRUE(info.findInt64(FRAME_PTS_US, &framePtsUs) == ECODataStatus::OK);
423     EXPECT_EQ(framePtsUs, 1666665);
424     EXPECT_TRUE(info.findInt32(FRAME_AVG_QP, &frameQp) == ECODataStatus::OK);
425     EXPECT_EQ(frameQp, 41);
426     EXPECT_TRUE(info.findInt32(FRAME_SIZE_BYTES, &frameSize) == ECODataStatus::OK);
427     EXPECT_EQ(frameSize, 56);
428 }
429 
TEST_F(EcoSessionTest,TestRemoveMatchProvider)430 TEST_F(EcoSessionTest, TestRemoveMatchProvider) {
431     std::shared_ptr<ECOSession> ecoSession =
432             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
433     EXPECT_TRUE(ecoSession);
434 
435     std::shared_ptr<FakeECOServiceStatsProvider> fakeProvider1 =
436             ndk::SharedRefBase::make<FakeECOServiceStatsProvider>(
437                     kTestWidth, kTestHeight, kIsCameraRecording, kFrameRate, ecoSession);
438 
439     ECOData providerConfig(ECOData::DATA_TYPE_STATS_PROVIDER_CONFIG,
440                            systemTime(SYSTEM_TIME_BOOTTIME));
441     bool res;
442     ScopedAStatus status = ecoSession->addStatsProvider(fakeProvider1, providerConfig, &res);
443     EXPECT_TRUE(res);
444     EXPECT_TRUE(status.isOk());
445 
446     status = ecoSession->removeStatsProvider(fakeProvider1, &res);
447     EXPECT_TRUE(res);
448     EXPECT_TRUE(status.isOk());
449 }
450 
TEST_F(EcoSessionTest,TestRemoveMisMatchProvider)451 TEST_F(EcoSessionTest, TestRemoveMisMatchProvider) {
452     std::shared_ptr<ECOSession> ecoSession =
453             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
454     EXPECT_TRUE(ecoSession);
455 
456     std::shared_ptr<FakeECOServiceStatsProvider> fakeProvider1 =
457             ndk::SharedRefBase::make<FakeECOServiceStatsProvider>(
458                     kTestWidth, kTestHeight, kIsCameraRecording, kFrameRate, ecoSession);
459 
460     ECOData providerConfig(ECOData::DATA_TYPE_STATS_PROVIDER_CONFIG,
461                            systemTime(SYSTEM_TIME_BOOTTIME));
462     bool res;
463     ScopedAStatus status = ecoSession->addStatsProvider(fakeProvider1, providerConfig, &res);
464     EXPECT_TRUE(res);
465     EXPECT_TRUE(status.isOk());
466 
467     std::shared_ptr<FakeECOServiceStatsProvider> fakeProvider2 =
468             ndk::SharedRefBase::make<FakeECOServiceStatsProvider>(
469                     kTestWidth, kTestHeight, kIsCameraRecording, kFrameRate, ecoSession);
470 
471     status = ecoSession->removeStatsProvider(fakeProvider2, &res);
472     EXPECT_FALSE(res);
473     EXPECT_FALSE(status.isOk());
474 }
475 
TEST_F(EcoSessionTest,TestRemoveMatchListener)476 TEST_F(EcoSessionTest, TestRemoveMatchListener) {
477     std::shared_ptr<ECOSession> ecoSession =
478             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
479     EXPECT_TRUE(ecoSession);
480 
481     // Create listener.
482     std::shared_ptr<FakeECOServiceInfoListener> fakeListener =
483             ndk::SharedRefBase::make<FakeECOServiceInfoListener>(kTestWidth, kTestHeight,
484                                                                  kIsCameraRecording, ecoSession);
485 
486     // Create the listener config.
487     ECOData listenerConfig(ECOData::DATA_TYPE_INFO_LISTENER_CONFIG,
488                            systemTime(SYSTEM_TIME_BOOTTIME));
489     listenerConfig.setString(KEY_LISTENER_NAME, "FakeECOServiceInfoListener");
490     listenerConfig.setInt32(KEY_LISTENER_TYPE, ECOServiceInfoListener::INFO_LISTENER_TYPE_CAMERA);
491 
492     // Specify the qp thresholds for receiving notification.
493     listenerConfig.setInt32(KEY_LISTENER_QP_BLOCKINESS_THRESHOLD, 40);
494     listenerConfig.setInt32(KEY_LISTENER_QP_CHANGE_THRESHOLD, 5);
495 
496     bool res;
497     ScopedAStatus status = ecoSession->addInfoListener(fakeListener, listenerConfig, &res);
498 
499     status = ecoSession->removeInfoListener(fakeListener, &res);
500     EXPECT_TRUE(res);
501     EXPECT_TRUE(status.isOk());
502 }
503 
TEST_F(EcoSessionTest,TestRemoveMisMatchListener)504 TEST_F(EcoSessionTest, TestRemoveMisMatchListener) {
505     std::shared_ptr<ECOSession> ecoSession =
506             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
507     EXPECT_TRUE(ecoSession);
508 
509     // Create listener.
510     std::shared_ptr<FakeECOServiceInfoListener> fakeListener =
511             ndk::SharedRefBase::make<FakeECOServiceInfoListener>(kTestWidth, kTestHeight,
512                                                                  kIsCameraRecording, ecoSession);
513 
514     // Create the listener config.
515     ECOData listenerConfig(ECOData::DATA_TYPE_INFO_LISTENER_CONFIG,
516                            systemTime(SYSTEM_TIME_BOOTTIME));
517     listenerConfig.setString(KEY_LISTENER_NAME, "FakeECOServiceInfoListener");
518     listenerConfig.setInt32(KEY_LISTENER_TYPE, ECOServiceInfoListener::INFO_LISTENER_TYPE_CAMERA);
519 
520     // Specify the qp thresholds for receiving notification.
521     listenerConfig.setInt32(KEY_LISTENER_QP_BLOCKINESS_THRESHOLD, 40);
522     listenerConfig.setInt32(KEY_LISTENER_QP_CHANGE_THRESHOLD, 5);
523 
524     bool res;
525     ScopedAStatus status = ecoSession->addInfoListener(fakeListener, listenerConfig, &res);
526 
527     // Create listener.
528     std::shared_ptr<FakeECOServiceInfoListener> fakeListener2 =
529             ndk::SharedRefBase::make<FakeECOServiceInfoListener>(kTestWidth, kTestHeight,
530                                                                  kIsCameraRecording, ecoSession);
531 
532     status = ecoSession->removeInfoListener(fakeListener2, &res);
533     EXPECT_FALSE(res);
534     EXPECT_FALSE(status.isOk());
535 }
536 
537 // Test the listener connects to the ECOSession after provider sends the session info. Listener
538 // should recieve the session info right after adding itself to the ECOSession.
TEST_F(EcoSessionTest,TestAddListenerAferProviderStarts)539 TEST_F(EcoSessionTest, TestAddListenerAferProviderStarts) {
540     // The time that listener needs to wait for the info from ECOService.
541     static constexpr int kServiceWaitTimeMs = 10;
542 
543     // Create the session.
544     std::shared_ptr<ECOSession> ecoSession =
545             createSession(kTestWidth, kTestHeight, kIsCameraRecording);
546 
547     // Add provider.
548     std::shared_ptr<FakeECOServiceStatsProvider> fakeProvider =
549             ndk::SharedRefBase::make<FakeECOServiceStatsProvider>(
550                     kTestWidth, kTestHeight, kIsCameraRecording, kFrameRate, ecoSession);
551     ECOData providerConfig(ECOData::DATA_TYPE_STATS_PROVIDER_CONFIG,
552                            systemTime(SYSTEM_TIME_BOOTTIME));
553     providerConfig.setString(KEY_PROVIDER_NAME, "FakeECOServiceStatsProvider");
554     providerConfig.setInt32(KEY_PROVIDER_TYPE,
555                             ECOServiceStatsProvider::STATS_PROVIDER_TYPE_VIDEO_ENCODER);
556     bool res;
557     ScopedAStatus status = ecoSession->addStatsProvider(fakeProvider, providerConfig, &res);
558 
559     // Inject the session stats into the ECOSession through fakeProvider.
560     SimpleEncoderConfig sessionEncoderConfig("google-avc", CodecTypeAVC, AVCProfileHigh, AVCLevel52,
561                                              kTargetBitrateBps, kKeyFrameIntervalFrames,
562                                              kFrameRate);
563     fakeProvider->injectSessionStats(sessionEncoderConfig.toEcoData(ECOData::DATA_TYPE_STATS));
564 
565     // Wait as ECOService may take some time to process.
566     std::this_thread::sleep_for(std::chrono::milliseconds(kServiceWaitTimeMs));
567 
568     // =======================================================================================
569     // Inject the frame stats with qp = 30. Expect receiving notification for the first frame.
570     SimpleEncodedFrameData frameStats(1 /* seq number */, FrameTypeI, 0 /* framePtsUs */,
571                                       30 /* avg-qp */, 56 /* frameSize */);
572 
573     fakeProvider->injectFrameStats(frameStats.toEcoData(ECOData::DATA_TYPE_STATS));
574     std::this_thread::sleep_for(std::chrono::milliseconds(kServiceWaitTimeMs));
575 
576     // =======================================================================================
577     // Create and add the listener to the ECOSession. Expect to receive the session infor right
578     // after addInfoListener.
579     std::shared_ptr<FakeECOServiceInfoListener> fakeListener =
580             ndk::SharedRefBase::make<FakeECOServiceInfoListener>(kTestWidth, kTestHeight,
581                                                                  kIsCameraRecording, ecoSession);
582 
583     // Create the listener config.
584     ECOData listenerConfig(ECOData::DATA_TYPE_INFO_LISTENER_CONFIG,
585                            systemTime(SYSTEM_TIME_BOOTTIME));
586     listenerConfig.setString(KEY_LISTENER_NAME, "FakeECOServiceInfoListener");
587     listenerConfig.setInt32(KEY_LISTENER_TYPE, ECOServiceInfoListener::INFO_LISTENER_TYPE_CAMERA);
588 
589     // Specify the qp thresholds for receiving notification.
590     listenerConfig.setInt32(KEY_LISTENER_QP_BLOCKINESS_THRESHOLD, 40);
591     listenerConfig.setInt32(KEY_LISTENER_QP_CHANGE_THRESHOLD, 5);
592 
593     ECOData info;
594     bool getInfo = false;
595 
596     // Set the getInfo flag to true and copy the info from fakeListener.
597     fakeListener->setInfoAvailableCallback(
598             [&info, &getInfo](const ::android::media::eco::ECOData& newInfo) {
599                 getInfo = true;
600                 info = newInfo;
601             });
602 
603     status = ecoSession->addInfoListener(fakeListener, listenerConfig, &res);
604 
605     // Wait as ECOService may take some time to process.
606     std::this_thread::sleep_for(std::chrono::milliseconds(kServiceWaitTimeMs));
607 
608     // Check the Session info matches with the session stats sent by provider.
609     EXPECT_TRUE(getInfo);
610     EXPECT_TRUE(info.getDataType() == ECOData::DATA_TYPE_INFO);
611 
612     std::string infoType;
613     EXPECT_TRUE(info.findString(KEY_INFO_TYPE, &infoType) == ECODataStatus::OK);
614     EXPECT_EQ(infoType, VALUE_INFO_TYPE_SESSION);
615 
616     // Check the session info matches the session stats provided by FakeECOServiceStatsProvider.
617     int32_t codecType;
618     EXPECT_TRUE(info.findInt32(ENCODER_TYPE, &codecType) == ECODataStatus::OK);
619     EXPECT_EQ(codecType, CodecTypeAVC);
620 
621     int32_t profile;
622     EXPECT_TRUE(info.findInt32(ENCODER_PROFILE, &profile) == ECODataStatus::OK);
623     EXPECT_EQ(profile, AVCProfileHigh);
624 
625     int32_t level;
626     EXPECT_TRUE(info.findInt32(ENCODER_LEVEL, &level) == ECODataStatus::OK);
627     EXPECT_EQ(level, AVCLevel52);
628 
629     int32_t bitrate;
630     EXPECT_TRUE(info.findInt32(ENCODER_TARGET_BITRATE_BPS, &bitrate) == ECODataStatus::OK);
631     EXPECT_EQ(bitrate, kTargetBitrateBps);
632 
633     int32_t kfi;
634     EXPECT_TRUE(info.findInt32(ENCODER_KFI_FRAMES, &kfi) == ECODataStatus::OK);
635     EXPECT_EQ(kfi, kKeyFrameIntervalFrames);
636 }
637 
638 }  // namespace eco
639 }  // namespace media
640 }  // namespace android
641