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 <binder/Parcel.h>
24 #include <binder/Parcelable.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 
32 #include "FakeECOServiceInfoListener.h"
33 #include "FakeECOServiceStatsProvider.h"
34 #include "eco/ECOService.h"
35 #include "eco/ECOUtils.h"
36 
37 namespace android {
38 namespace media {
39 namespace eco {
40 
41 using ::android::IBinder;
42 using android::sp;
43 using ::android::binder::Status;
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     sp<IECOService> createService() {
60         android::sp<android::IServiceManager> sm = android::defaultServiceManager();
61         assert(sm != 0);
62         android::sp<android::IBinder> binder = sm->getService(String16("media.ecoservice"));
63 
64         if (binder == 0) {
65             ALOGE("Failed to connect to ecoservice");
66             return nullptr;
67         } else {
68             ALOGD("Successfully connect to ecoservice");
69         }
70 
71         mECOService = android::interface_cast<IECOService>(binder);
72         return mECOService;
73     }
74 
~EcoServiceTest()75     ~EcoServiceTest() { ALOGD("EcoServiceTest destroyed"); }
76 
77 private:
78     sp<IECOService> mECOService = nullptr;
79 };
80 
TEST_F(EcoServiceTest,NormalObtainSessionWithInvalidWidth)81 TEST_F(EcoServiceTest, NormalObtainSessionWithInvalidWidth) {
82     sp<IECOService> service = createService();
83     EXPECT_TRUE(service != nullptr);
84 
85     // Provider obtains the session from the service.
86     sp<IECOSession> session = nullptr;
87 
88     service->obtainSession(-1 /* width */, kTestHeight, kIsCameraRecording, &session);
89     EXPECT_FALSE(session);
90 }
91 
TEST_F(EcoServiceTest,NormalObtainSessionWithInvalidHeight)92 TEST_F(EcoServiceTest, NormalObtainSessionWithInvalidHeight) {
93     sp<IECOService> service = createService();
94 
95     // Provider obtains the session from the service.
96     sp<IECOSession> session = nullptr;
97 
98     service->obtainSession(kTestWidth, -1 /* height */, kIsCameraRecording, &session);
99     EXPECT_FALSE(session);
100 }
101 
TEST_F(EcoServiceTest,NormalObtainSessionWithCameraRecordingFalse)102 TEST_F(EcoServiceTest, NormalObtainSessionWithCameraRecordingFalse) {
103     sp<IECOService> service = createService();
104 
105     // Provider obtains the session from the service.
106     sp<IECOSession> session = nullptr;
107 
108     service->obtainSession(kTestWidth, kTestHeight, false /* isCameraRecording */, &session);
109     EXPECT_TRUE(session);
110 }
111 
TEST_F(EcoServiceTest,NormalObtainSingleSession)112 TEST_F(EcoServiceTest, NormalObtainSingleSession) {
113     sp<IECOService> service = createService();
114     EXPECT_TRUE(service != nullptr);
115 
116     // Provider obtains the session from the service.
117     sp<IECOSession> session = nullptr;
118 
119     service->obtainSession(kTestWidth, kTestHeight, kIsCameraRecording, &session);
120     EXPECT_TRUE(session);
121 }
122 
TEST_F(EcoServiceTest,NormalObtainSessionTwice)123 TEST_F(EcoServiceTest, NormalObtainSessionTwice) {
124     sp<IECOService> service = createService();
125     EXPECT_TRUE(service != nullptr);
126 
127     // Provider obtains the session from the service.
128     sp<IECOSession> session1 = nullptr;
129 
130     service->obtainSession(kTestWidth, kTestHeight, kIsCameraRecording, &session1);
131     EXPECT_TRUE(session1);
132 
133     sp<IECOSession> session2 = nullptr;
134 
135     service->obtainSession(kTestWidth, kTestHeight, kIsCameraRecording, &session2);
136     EXPECT_TRUE(session2);
137 
138     // The two session instances should be the same.
139     EXPECT_TRUE(IInterface::asBinder(session1) == IInterface::asBinder(session2));
140 }
141 
TEST_F(EcoServiceTest,ObtainTwoSessions)142 TEST_F(EcoServiceTest, ObtainTwoSessions) {
143     sp<IECOService> service = createService();
144     EXPECT_TRUE(service != nullptr);
145 
146     // Provider obtains the session from the service.
147     sp<IECOSession> session1 = nullptr;
148 
149     service->obtainSession(kTestWidth, kTestHeight, kIsCameraRecording, &session1);
150     EXPECT_TRUE(session1);
151 
152     sp<IECOSession> session2 = nullptr;
153 
154     service->obtainSession(kTestWidth - 1, kTestHeight - 1, kIsCameraRecording, &session2);
155     EXPECT_TRUE(session2);
156 
157     // The two session instances must not be the same.
158     EXPECT_TRUE(IInterface::asBinder(session1) != IInterface::asBinder(session2));
159 
160     // Check the session number.
161     int32_t count = 0;
162     service->getNumOfSessions(&count);
163     EXPECT_EQ(count, 2);
164 
165     // Get the list of sessions from service.
166     std::vector<sp<IBinder>> sessionList;
167     service->getSessions(&sessionList);
168     bool foundFirstSession = false, foundSecondSession = false;
169 
170     for (std::vector<sp<IBinder>>::iterator it = sessionList.begin(); it != sessionList.end();
171          ++it) {
172         if (IInterface::asBinder(session1) == it->get()) {
173             foundFirstSession = true;
174         }
175         if (IInterface::asBinder(session2) == it->get()) {
176             foundSecondSession = true;
177         }
178     }
179 
180     // Expect found both sessions.
181     EXPECT_TRUE(foundFirstSession);
182     EXPECT_TRUE(foundSecondSession);
183 }
184 
TEST_F(EcoServiceTest,TestNormalFlowWithOneListenerAndOneProvider)185 TEST_F(EcoServiceTest, TestNormalFlowWithOneListenerAndOneProvider) {
186     sp<IECOService> service = createService();
187     EXPECT_TRUE(service != nullptr);
188 
189     // Provider obtains the session from the service.
190     sp<IECOSession> session = nullptr;
191 
192     service->obtainSession(kTestWidth, kTestHeight, kIsCameraRecording, &session);
193     EXPECT_TRUE(session);
194 
195     // Create provider and add it to the session.
196     sp<FakeECOServiceStatsProvider> fakeProvider = new FakeECOServiceStatsProvider(
197             kTestWidth, kTestHeight, kIsCameraRecording, kFrameRate);
198     fakeProvider->setECOSession(session);
199 
200     ECOData providerConfig(ECOData::DATA_TYPE_STATS_PROVIDER_CONFIG,
201                            systemTime(SYSTEM_TIME_BOOTTIME));
202     providerConfig.setString(KEY_PROVIDER_NAME, "FakeECOServiceStatsProvider");
203     providerConfig.setInt32(KEY_PROVIDER_TYPE,
204                             ECOServiceStatsProvider::STATS_PROVIDER_TYPE_VIDEO_ENCODER);
205     bool res;
206     Status status = session->addStatsProvider(fakeProvider, providerConfig, &res);
207 
208     // Create listener and add it to the session.
209     sp<FakeECOServiceInfoListener> fakeListener =
210             new FakeECOServiceInfoListener(kTestWidth, kTestHeight, kIsCameraRecording);
211     fakeListener->setECOSession(session);
212 
213     // Create the listener config.
214     ECOData listenerConfig(ECOData::DATA_TYPE_INFO_LISTENER_CONFIG,
215                            systemTime(SYSTEM_TIME_BOOTTIME));
216     listenerConfig.setString(KEY_LISTENER_NAME, "FakeECOServiceInfoListener");
217     listenerConfig.setInt32(KEY_LISTENER_TYPE, ECOServiceInfoListener::INFO_LISTENER_TYPE_CAMERA);
218 
219     // Specify the qp thresholds for receiving notification.
220     listenerConfig.setInt32(KEY_LISTENER_QP_BLOCKINESS_THRESHOLD, 40);
221     listenerConfig.setInt32(KEY_LISTENER_QP_CHANGE_THRESHOLD, 5);
222 
223     status = session->addInfoListener(fakeListener, listenerConfig, &res);
224 }
225 
226 }  // namespace eco
227 }  // namespace media
228 }  // namespace android
229