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