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 ECOService.
18 
19 #define LOG_NDEBUG 0
20 #define LOG_TAG "ECOServiceTest"
21 
22 #include <android-base/unique_fd.h>
23 #include <android/binder_auto_utils.h>
24 #include <android/binder_manager.h>
25 #include <android/binder_parcel.h>
26 #include <cutils/ashmem.h>
27 #include <gtest/gtest.h>
28 #include <math.h>
29 #include <stdlib.h>
30 #include <sys/mman.h>
31 #include <utils/Log.h>
32 #include <utils/Timers.h>
33 
34 #include "FakeECOServiceInfoListener.h"
35 #include "FakeECOServiceStatsProvider.h"
36 #include "eco/ECOService.h"
37 #include "eco/ECOUtils.h"
38 
39 namespace android {
40 namespace media {
41 namespace eco {
42 
43 using ::ndk::ScopedAStatus;
44 
45 namespace {
46 
47 static constexpr uint32_t kTestWidth = 1280;
48 static constexpr uint32_t kTestHeight = 720;
49 static constexpr bool kIsCameraRecording = true;
50 static constexpr float kFrameRate = 30.0f;
51 
52 }  // namespace
53 
54 // A helper class to help create ECOService and manage ECOService.
55 class EcoServiceTest : public ::testing::Test {
56 public:
EcoServiceTest()57     EcoServiceTest() { ALOGD("EcoServiceTest created"); }
58 
createService()59     std::shared_ptr<IECOService> createService() {
60         mECOService = IECOService::fromBinder(
61                 ndk::SpAIBinder(AServiceManager_waitForService("media.ecoservice")));
62         if (mECOService == nullptr) {
63             ALOGE("Failed to connect to ecoservice");
64             return nullptr;
65         }
66 
67         return mECOService;
68     }
69 
~EcoServiceTest()70     ~EcoServiceTest() { ALOGD("EcoServiceTest destroyed"); }
71 
72 private:
73     std::shared_ptr<IECOService> mECOService = nullptr;
74 };
75 
TEST_F(EcoServiceTest,NormalObtainSessionWithInvalidWidth)76 TEST_F(EcoServiceTest, NormalObtainSessionWithInvalidWidth) {
77     std::shared_ptr<IECOService> service = createService();
78     EXPECT_TRUE(service != nullptr);
79 
80     // Provider obtains the session from the service.
81     std::shared_ptr<IECOSession> session = nullptr;
82 
83     service->obtainSession(-1 /* width */, kTestHeight, kIsCameraRecording, &session);
84     EXPECT_FALSE(session);
85 }
86 
TEST_F(EcoServiceTest,NormalObtainSessionWithInvalidHeight)87 TEST_F(EcoServiceTest, NormalObtainSessionWithInvalidHeight) {
88     std::shared_ptr<IECOService> service = createService();
89 
90     // Provider obtains the session from the service.
91     std::shared_ptr<IECOSession> session = nullptr;
92 
93     service->obtainSession(kTestWidth, -1 /* height */, kIsCameraRecording, &session);
94     EXPECT_FALSE(session);
95 }
96 
TEST_F(EcoServiceTest,NormalObtainSessionWithCameraRecordingFalse)97 TEST_F(EcoServiceTest, NormalObtainSessionWithCameraRecordingFalse) {
98     std::shared_ptr<IECOService> service = createService();
99 
100     // Provider obtains the session from the service.
101     std::shared_ptr<IECOSession> session = nullptr;
102 
103     service->obtainSession(kTestWidth, kTestHeight, false /* isCameraRecording */, &session);
104     EXPECT_TRUE(session);
105 }
106 
TEST_F(EcoServiceTest,NormalObtainSingleSession)107 TEST_F(EcoServiceTest, NormalObtainSingleSession) {
108     std::shared_ptr<IECOService> service = createService();
109     EXPECT_TRUE(service != nullptr);
110 
111     // Provider obtains the session from the service.
112     std::shared_ptr<IECOSession> session = nullptr;
113 
114     service->obtainSession(kTestWidth, kTestHeight, kIsCameraRecording, &session);
115     EXPECT_TRUE(session);
116 }
117 
TEST_F(EcoServiceTest,NormalObtainSessionTwice)118 TEST_F(EcoServiceTest, NormalObtainSessionTwice) {
119     std::shared_ptr<IECOService> service = createService();
120     EXPECT_TRUE(service != nullptr);
121 
122     // Provider obtains the session from the service.
123     std::shared_ptr<IECOSession> session1 = nullptr;
124 
125     service->obtainSession(kTestWidth, kTestHeight, kIsCameraRecording, &session1);
126     EXPECT_TRUE(session1);
127 
128     std::shared_ptr<IECOSession> session2 = nullptr;
129 
130     service->obtainSession(kTestWidth, kTestHeight, kIsCameraRecording, &session2);
131     EXPECT_TRUE(session2);
132 
133     // The two session instances should be the same.
134     EXPECT_TRUE(session1->asBinder() == session2->asBinder());
135 }
136 
TEST_F(EcoServiceTest,ObtainTwoSessions)137 TEST_F(EcoServiceTest, ObtainTwoSessions) {
138     std::shared_ptr<IECOService> service = createService();
139     EXPECT_TRUE(service != nullptr);
140 
141     // Provider obtains the session from the service.
142     std::shared_ptr<IECOSession> session1 = nullptr;
143 
144     service->obtainSession(kTestWidth, kTestHeight, kIsCameraRecording, &session1);
145     EXPECT_TRUE(session1);
146 
147     std::shared_ptr<IECOSession> session2 = nullptr;
148 
149     service->obtainSession(kTestWidth - 1, kTestHeight - 1, kIsCameraRecording, &session2);
150     EXPECT_TRUE(session2);
151 
152     // The two session instances must not be the same.
153     EXPECT_TRUE(session1->asBinder() != session2->asBinder());
154 
155     // Check the session number.
156     int32_t count = 0;
157     service->getNumOfSessions(&count);
158     EXPECT_EQ(count, 2);
159 
160     // Get the list of sessions from service.
161     std::vector<::ndk::SpAIBinder> sessionList;
162     service->getSessions(&sessionList);
163     bool foundFirstSession = false, foundSecondSession = false;
164 
165     for (std::vector<::ndk::SpAIBinder>::iterator it = sessionList.begin(); it != sessionList.end();
166          ++it) {
167         if (session1->asBinder() == it->get()) {
168             foundFirstSession = true;
169         }
170         if (session2->asBinder() == it->get()) {
171             foundSecondSession = true;
172         }
173     }
174 
175     // Expect found both sessions.
176     EXPECT_TRUE(foundFirstSession);
177     EXPECT_TRUE(foundSecondSession);
178 }
179 
TEST_F(EcoServiceTest,TestNormalFlowWithOneListenerAndOneProvider)180 TEST_F(EcoServiceTest, TestNormalFlowWithOneListenerAndOneProvider) {
181     std::shared_ptr<IECOService> service = createService();
182     EXPECT_TRUE(service != nullptr);
183 
184     // Provider obtains the session from the service.
185     std::shared_ptr<IECOSession> session = nullptr;
186 
187     service->obtainSession(kTestWidth, kTestHeight, kIsCameraRecording, &session);
188     EXPECT_TRUE(session);
189 
190     // Create provider and add it to the session.
191     std::shared_ptr<FakeECOServiceStatsProvider> fakeProvider =
192             ndk::SharedRefBase::make<FakeECOServiceStatsProvider>(kTestWidth, kTestHeight,
193                                                                   kIsCameraRecording, kFrameRate);
194     fakeProvider->setECOSession(session);
195 
196     ECOData providerConfig(ECOData::DATA_TYPE_STATS_PROVIDER_CONFIG,
197                            systemTime(SYSTEM_TIME_BOOTTIME));
198     providerConfig.setString(KEY_PROVIDER_NAME, "FakeECOServiceStatsProvider");
199     providerConfig.setInt32(KEY_PROVIDER_TYPE,
200                             ECOServiceStatsProvider::STATS_PROVIDER_TYPE_VIDEO_ENCODER);
201     bool res;
202     ScopedAStatus status = session->addStatsProvider(fakeProvider, providerConfig, &res);
203 
204     // Create listener and add it to the session.
205     std::shared_ptr<FakeECOServiceInfoListener> fakeListener =
206             ndk::SharedRefBase::make<FakeECOServiceInfoListener>(kTestWidth, kTestHeight,
207                                                                  kIsCameraRecording);
208     fakeListener->setECOSession(session);
209 
210     // Create the listener config.
211     ECOData listenerConfig(ECOData::DATA_TYPE_INFO_LISTENER_CONFIG,
212                            systemTime(SYSTEM_TIME_BOOTTIME));
213     listenerConfig.setString(KEY_LISTENER_NAME, "FakeECOServiceInfoListener");
214     listenerConfig.setInt32(KEY_LISTENER_TYPE, ECOServiceInfoListener::INFO_LISTENER_TYPE_CAMERA);
215 
216     // Specify the qp thresholds for receiving notification.
217     listenerConfig.setInt32(KEY_LISTENER_QP_BLOCKINESS_THRESHOLD, 40);
218     listenerConfig.setInt32(KEY_LISTENER_QP_CHANGE_THRESHOLD, 5);
219 
220     status = session->addInfoListener(fakeListener, listenerConfig, &res);
221 }
222 
223 }  // namespace eco
224 }  // namespace media
225 }  // namespace android
226