1 /*
2  * Copyright (C) 2023 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 #include <aidl/android/hardware/radio/ims/media/MediaDirection.h>
18 #include <android/binder_auto_utils.h>
19 #include <android/binder_manager.h>
20 #include <sys/socket.h>
21 
22 #include "radio_imsmedia_utils.h"
23 
24 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
25 
SetUp()26 void RadioImsMediaTest::SetUp() {
27     RadioServiceTest::SetUp();
28     std::string serviceName = GetParam();
29 
30     radio_imsmedia = IImsMedia::fromBinder(
31             ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
32     ASSERT_NE(nullptr, radio_imsmedia.get());
33 
34     radio_imsmedialistener = ndk::SharedRefBase::make<ImsMediaListener>(*this);
35     ASSERT_NE(nullptr, radio_imsmedialistener.get());
36 
37     radio_imsmediasessionlistener = ndk::SharedRefBase::make<ImsMediaSessionListener>(*this);
38     ASSERT_NE(nullptr, radio_imsmediasessionlistener.get());
39 }
40 
TEST_P(RadioImsMediaTest,MOCallSuccess)41 TEST_P(RadioImsMediaTest, MOCallSuccess) {
42     int32_t sessionId = 1;
43     RtpConfig modifyRtpConfig;
44 
45     modifyRtpConfig.direction = static_cast<int32_t>(MediaDirection::RTP_TX) |
46                                 static_cast<int32_t>(MediaDirection::RTP_RX) |
47                                 static_cast<int32_t>(MediaDirection::RTCP_TX) |
48                                 static_cast<int32_t>(MediaDirection::RTCP_RX);
49     modifyRtpConfig.remoteAddress.ipAddress = "122.22.22.33";
50     modifyRtpConfig.remoteAddress.portNumber = 1234;
51 
52     if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
53         ALOGI("Skipping setListener because ims is not supported in device");
54         return;
55     } else {
56         ALOGI("Running setListener because ims is supported in device");
57     }
58 
59     ndk::ScopedAStatus res = radio_imsmedia->setListener(radio_imsmedialistener);
60     ASSERT_OK(res);
61 
62     serial = SERIAL_OPEN_SESSION;
63     res = triggerOpenSession(sessionId);
64     ASSERT_OK(res);
65     EXPECT_EQ(std::cv_status::no_timeout, wait());
66     EXPECT_EQ(sessionId, radio_imsmedialistener->mSessionId);
67     ASSERT_NE(nullptr, radio_imsmedialistener->mSession);
68 
69     radio_imsmediasession = radio_imsmedialistener->mSession;
70     radio_imsmediasession->setListener(radio_imsmediasessionlistener);
71     ASSERT_OK(res);
72 
73     serial = SERIAL_MODIFY_SESSION;
74     res = radio_imsmediasession->modifySession(modifyRtpConfig);
75     ASSERT_OK(res);
76     EXPECT_EQ(std::cv_status::no_timeout, wait());
77     EXPECT_EQ(modifyRtpConfig, radio_imsmediasessionlistener->mConfig);
78     verifyError(radio_imsmediasessionlistener->mError);
79 
80     serial = SERIAL_CLOSE_SESSION;
81     res = radio_imsmedia->closeSession(sessionId);
82     ASSERT_OK(res);
83     EXPECT_EQ(std::cv_status::no_timeout, wait());
84     EXPECT_EQ(sessionId, radio_imsmedialistener->mSessionId);
85 }
86 
TEST_P(RadioImsMediaTest,testDtmfOperation)87 TEST_P(RadioImsMediaTest, testDtmfOperation) {
88     int32_t sessionId = 1;
89     char16_t dtmfDight = 'a';
90     int32_t duration = 200;
91     RtpConfig modifyRtpConfig;
92 
93     modifyRtpConfig.direction = static_cast<int32_t>(MediaDirection::RTP_TX) |
94                                 static_cast<int32_t>(MediaDirection::RTP_RX) |
95                                 static_cast<int32_t>(MediaDirection::RTCP_TX) |
96                                 static_cast<int32_t>(MediaDirection::RTCP_RX);
97     modifyRtpConfig.remoteAddress.ipAddress = "122.22.22.33";
98     modifyRtpConfig.remoteAddress.portNumber = 1234;
99 
100     if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
101         ALOGI("Skipping setListener because ims is not supported in device");
102         return;
103     } else {
104         ALOGI("Running setListener because ims is supported in device");
105     }
106 
107     ndk::ScopedAStatus res = radio_imsmedia->setListener(radio_imsmedialistener);
108     ASSERT_OK(res);
109 
110     serial = SERIAL_OPEN_SESSION;
111     res = triggerOpenSession(sessionId);
112     ASSERT_OK(res);
113     EXPECT_EQ(std::cv_status::no_timeout, wait());
114     EXPECT_EQ(sessionId, radio_imsmedialistener->mSessionId);
115     ASSERT_NE(nullptr, radio_imsmedialistener->mSession);
116 
117     radio_imsmediasession = radio_imsmedialistener->mSession;
118     radio_imsmediasession->setListener(radio_imsmediasessionlistener);
119     ASSERT_OK(res);
120 
121     serial = SERIAL_MODIFY_SESSION;
122     res = radio_imsmediasession->modifySession(modifyRtpConfig);
123     ASSERT_OK(res);
124     EXPECT_EQ(std::cv_status::no_timeout, wait());
125     EXPECT_EQ(modifyRtpConfig, radio_imsmediasessionlistener->mConfig);
126     verifyError(radio_imsmediasessionlistener->mError);
127 
128     res = radio_imsmediasession->sendDtmf(dtmfDight, duration);
129     ASSERT_OK(res);
130 
131     res = radio_imsmediasession->startDtmf(dtmfDight);
132     ASSERT_OK(res);
133 
134     res = radio_imsmediasession->stopDtmf();
135     ASSERT_OK(res);
136 
137     serial = SERIAL_CLOSE_SESSION;
138     res = radio_imsmedia->closeSession(sessionId);
139     ASSERT_OK(res);
140     EXPECT_EQ(std::cv_status::no_timeout, wait());
141 }
142 
TEST_P(RadioImsMediaTest,sendHeaderExtension)143 TEST_P(RadioImsMediaTest, sendHeaderExtension) {
144     int32_t sessionId = 1;
145     std::vector<RtpHeaderExtension> extensions;
146     RtpConfig modifyRtpConfig;
147 
148     modifyRtpConfig.direction = static_cast<int32_t>(MediaDirection::RTP_TX) |
149                                 static_cast<int32_t>(MediaDirection::RTP_RX) |
150                                 static_cast<int32_t>(MediaDirection::RTCP_TX) |
151                                 static_cast<int32_t>(MediaDirection::RTCP_RX);
152     modifyRtpConfig.remoteAddress.ipAddress = "122.22.22.33";
153     modifyRtpConfig.remoteAddress.portNumber = 1234;
154 
155     if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
156         ALOGI("Skipping setListener because ims is not supported in device");
157         return;
158     } else {
159         ALOGI("Running setListener because ims is supported in device");
160     }
161 
162     ndk::ScopedAStatus res = radio_imsmedia->setListener(radio_imsmedialistener);
163     ASSERT_OK(res);
164 
165     serial = SERIAL_OPEN_SESSION;
166     res = triggerOpenSession(sessionId);
167     ASSERT_OK(res);
168     EXPECT_EQ(std::cv_status::no_timeout, wait());
169     EXPECT_EQ(sessionId, radio_imsmedialistener->mSessionId);
170     ASSERT_NE(nullptr, radio_imsmedialistener->mSession);
171 
172     radio_imsmediasession = radio_imsmedialistener->mSession;
173     radio_imsmediasession->setListener(radio_imsmediasessionlistener);
174     ASSERT_OK(res);
175 
176     serial = SERIAL_MODIFY_SESSION;
177     res = radio_imsmediasession->modifySession(modifyRtpConfig);
178     ASSERT_OK(res);
179     EXPECT_EQ(std::cv_status::no_timeout, wait());
180     EXPECT_EQ(modifyRtpConfig, radio_imsmediasessionlistener->mConfig);
181     verifyError(radio_imsmediasessionlistener->mError);
182 
183     res = radio_imsmediasession->sendHeaderExtension(extensions);
184     ASSERT_OK(res);
185 
186     serial = SERIAL_CLOSE_SESSION;
187     res = radio_imsmedia->closeSession(sessionId);
188     ASSERT_OK(res);
189     EXPECT_EQ(std::cv_status::no_timeout, wait());
190 }
191 
TEST_P(RadioImsMediaTest,setMediaQualityThreshold)192 TEST_P(RadioImsMediaTest, setMediaQualityThreshold) {
193     int32_t sessionId = 1;
194     MediaQualityThreshold threshold;
195     RtpConfig modifyRtpConfig;
196 
197     modifyRtpConfig.direction = static_cast<int32_t>(MediaDirection::RTP_TX) |
198                                 static_cast<int32_t>(MediaDirection::RTP_RX) |
199                                 static_cast<int32_t>(MediaDirection::RTCP_TX) |
200                                 static_cast<int32_t>(MediaDirection::RTCP_RX);
201     modifyRtpConfig.remoteAddress.ipAddress = "122.22.22.33";
202     modifyRtpConfig.remoteAddress.portNumber = 1234;
203 
204     if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
205         ALOGI("Skipping setListener because ims is not supported in device");
206         return;
207     } else {
208         ALOGI("Running setListener because ims is supported in device");
209     }
210 
211     ndk::ScopedAStatus res = radio_imsmedia->setListener(radio_imsmedialistener);
212     ASSERT_OK(res);
213 
214     serial = SERIAL_OPEN_SESSION;
215     res = triggerOpenSession(sessionId);
216     ASSERT_OK(res);
217     EXPECT_EQ(std::cv_status::no_timeout, wait());
218     EXPECT_EQ(sessionId, radio_imsmedialistener->mSessionId);
219     ASSERT_NE(nullptr, radio_imsmedialistener->mSession);
220 
221     radio_imsmediasession = radio_imsmedialistener->mSession;
222     radio_imsmediasession->setListener(radio_imsmediasessionlistener);
223     ASSERT_OK(res);
224 
225     serial = SERIAL_MODIFY_SESSION;
226     res = radio_imsmediasession->modifySession(modifyRtpConfig);
227     ASSERT_OK(res);
228     EXPECT_EQ(std::cv_status::no_timeout, wait());
229     EXPECT_EQ(modifyRtpConfig, radio_imsmediasessionlistener->mConfig);
230     verifyError(radio_imsmediasessionlistener->mError);
231 
232     res = radio_imsmediasession->setMediaQualityThreshold(threshold);
233     ASSERT_OK(res);
234 
235     serial = SERIAL_CLOSE_SESSION;
236     res = radio_imsmedia->closeSession(sessionId);
237     ASSERT_OK(res);
238     EXPECT_EQ(std::cv_status::no_timeout, wait());
239 }
240 
triggerOpenSession(int32_t sessionId)241 ndk::ScopedAStatus RadioImsMediaTest::triggerOpenSession(int32_t sessionId) {
242     LocalEndPoint localEndPoint;
243     RtpConfig rtpConfig;
244     ndk::ScopedAStatus result;
245 
246     int mSocketFd = ::socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
247     int mRtcpSocketFd = ::socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
248     localEndPoint.rtpFd = ndk::ScopedFileDescriptor(mSocketFd);
249     localEndPoint.rtcpFd = ndk::ScopedFileDescriptor(mRtcpSocketFd);
250     localEndPoint.modemId = 1;
251 
252     rtpConfig.direction = static_cast<int32_t>(MediaDirection::RTP_TX) |
253                           static_cast<int32_t>(MediaDirection::RTP_RX) |
254                           static_cast<int32_t>(MediaDirection::RTCP_TX) |
255                           static_cast<int32_t>(MediaDirection::RTCP_RX);
256     rtpConfig.remoteAddress.ipAddress = "122.22.22.22";
257     rtpConfig.remoteAddress.portNumber = 2222;
258 
259     result = radio_imsmedia->openSession(sessionId, localEndPoint, rtpConfig);
260     return result;
261 }
262 
TEST_P(RadioImsMediaTest,testAvSyncOperation)263 TEST_P(RadioImsMediaTest, testAvSyncOperation) {
264     int32_t sessionId = 1;
265     RtpConfig modifyRtpConfig;
266     int32_t receptionInterval = 1000;
267     int32_t delay = 200;
268 
269     modifyRtpConfig.direction = static_cast<int32_t>(MediaDirection::RTP_TX) |
270                                 static_cast<int32_t>(MediaDirection::RTP_RX) |
271                                 static_cast<int32_t>(MediaDirection::RTCP_TX) |
272                                 static_cast<int32_t>(MediaDirection::RTCP_RX);
273     modifyRtpConfig.remoteAddress.ipAddress = "122.22.22.33";
274     modifyRtpConfig.remoteAddress.portNumber = 1234;
275 
276     if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
277         ALOGI("Skipping setListener because ims is not supported in device");
278         return;
279     } else {
280         ALOGI("Running setListener because ims is supported in device");
281     }
282 
283     ndk::ScopedAStatus res = radio_imsmedia->setListener(radio_imsmedialistener);
284     ASSERT_OK(res);
285 
286     serial = SERIAL_OPEN_SESSION;
287     res = triggerOpenSession(sessionId);
288     ASSERT_OK(res);
289     EXPECT_EQ(std::cv_status::no_timeout, wait());
290     EXPECT_EQ(sessionId, radio_imsmedialistener->mSessionId);
291     ASSERT_NE(nullptr, radio_imsmedialistener->mSession);
292 
293     radio_imsmediasession = radio_imsmedialistener->mSession;
294     radio_imsmediasession->setListener(radio_imsmediasessionlistener);
295     ASSERT_OK(res);
296 
297     serial = SERIAL_MODIFY_SESSION;
298     res = radio_imsmediasession->modifySession(modifyRtpConfig);
299     ASSERT_OK(res);
300     EXPECT_EQ(std::cv_status::no_timeout, wait());
301     EXPECT_EQ(modifyRtpConfig, radio_imsmediasessionlistener->mConfig);
302     verifyError(radio_imsmediasessionlistener->mError);
303 
304     res = radio_imsmediasession->requestRtpReceptionStats(receptionInterval);
305     ASSERT_OK(res);
306 
307     res = radio_imsmediasession->adjustDelay(delay);
308     ASSERT_OK(res);
309 
310     serial = SERIAL_CLOSE_SESSION;
311     res = radio_imsmedia->closeSession(sessionId);
312     ASSERT_OK(res);
313     EXPECT_EQ(std::cv_status::no_timeout, wait());
314 }
315 
verifyError(RtpError error)316 void RadioImsMediaTest::verifyError(RtpError error) {
317     switch (error) {
318         case RtpError::NONE:
319         case RtpError::INVALID_PARAM:
320         case RtpError::NOT_READY:
321         case RtpError::NO_MEMORY:
322         case RtpError::NO_RESOURCES:
323         case RtpError::PORT_UNAVAILABLE:
324         case RtpError::NOT_SUPPORTED:
325             SUCCEED();
326             break;
327         default:
328             FAIL();
329             break;
330     }
331 }
332