1 /*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17 // test RemoteAudio with fake TCP
18
19 #include <unistd.h>
20
21 #include <utils/String8.h>
22
23 #include <gtest/gtest.h>
24
25 #include <utils/StrongPointer.h>
26
27 #include <Log.h>
28 #include <audio/AudioHardware.h>
29 #include <audio/AudioProtocol.h>
30 #include <audio/AudioSignalFactory.h>
31 #include <ClientSocket.h>
32 #include <audio/RemoteAudio.h>
33
34
35
assertTrue(bool cond)36 void assertTrue(bool cond) {
37 ASSERT_TRUE(cond);
38 }
assertData(const char * data1,const char * data2,int len)39 void assertData(const char* data1, const char* data2, int len) {
40 for (int i = 0; i < len; i++) {
41 //LOGD("0x%x vs 0x%x", data1[i], data2[i]);
42 ASSERT_TRUE(data1[i] == data2[i]);
43 }
44 }
45
46 class ClientSocketForTest: public ClientSocket {
47 public:
ClientSocketForTest()48 ClientSocketForTest()
49 : mToRead(NULL),
50 mReadLength(0) {};
51
~ClientSocketForTest()52 virtual ~ClientSocketForTest() {
53 close(mSocket);
54 close(mPipeWrFd);
55 }
init(const char * hostIp,int port,bool enableTimeout=false)56 virtual bool init(const char* hostIp, int port, bool enableTimeout = false) {
57 LOGD("ClientSocketForTest::init");
58 // use this fd to work with poll
59 int pipefd[2];
60 if (pipe(pipefd) == -1) {
61 LOGE("cannot create pipe");
62 return false;
63 }
64 LOGD("pipe %d %d", pipefd[0], pipefd[1]);
65 mSocket = pipefd[0];
66 mPipeWrFd = pipefd[1];
67 const char ipExpectation[] = "127.0.0.1";
68 assertTrue(memcmp(ipExpectation, hostIp, sizeof(ipExpectation)) == 0);
69 return true;
70 }
readData(char * data,int len,int timeoutInMs=0)71 virtual bool readData(char* data, int len, int timeoutInMs = 0) {
72 read(mSocket, data, len);
73 return true;
74 }
sendData(const char * data,int len)75 virtual bool sendData(const char* data, int len) {
76 assertTrue((len + mSendPointer) <= mSendLength);
77 assertData(data, mToSend + mSendPointer, len);
78 mSendPointer += len;
79 if ((mToRead != NULL) && (mReadLength != 0)) {
80 LOGD("fake TCP copy reply %d", mReadLength);
81 write(mPipeWrFd, mToRead, mReadLength);
82 mToRead = NULL; // prevent writing the same data again
83 }
84 return true;
85 }
86
setSendExpectation(const char * data,int len)87 void setSendExpectation(const char* data, int len) {
88 mToSend = data;
89 mSendLength = len;
90 mSendPointer = 0;
91 }
setReadExpectation(char * data,int len)92 void setReadExpectation(char* data, int len) {
93 mToRead = data;
94 mReadLength = len;
95 }
96 public:
97 int mPipeWrFd; // for writing
98 const char* mToRead;
99 int mReadLength;
100 const char* mToSend;
101 int mSendLength;
102 int mSendPointer;
103 };
104
105 class RemoteAudioFakeTcpTest : public testing::Test {
106 protected:
107 android::sp<RemoteAudio> mRemoteAudio;
108 ClientSocketForTest mTestSocket;
109
110 protected:
SetUp()111 virtual void SetUp() {
112 ASSERT_TRUE(U32_ENDIAN_SWAP(0x12345678) == 0x78563412);
113 mRemoteAudio = new RemoteAudio(mTestSocket);
114 ASSERT_TRUE(mRemoteAudio != NULL);
115 ASSERT_TRUE(mRemoteAudio->init(1234));
116 }
117
TearDown()118 virtual void TearDown() {
119 mRemoteAudio->release();
120 mRemoteAudio.clear();
121 }
122
doDownload()123 void doDownload() {
124 android::sp<Buffer> buffer = AudioSignalFactory::generateZeroSound(AudioHardware::E2BPS, 2,
125 false);
126 uint32_t prepareSend[] = {
127 U32_ENDIAN_SWAP(AudioProtocol::ECmdDownload),
128 U32_ENDIAN_SWAP(8),
129 U32_ENDIAN_SWAP(0), //id
130 U32_ENDIAN_SWAP(0)
131 };
132 uint32_t prepareReply[] = {
133 U32_ENDIAN_SWAP((AudioProtocol::ECmdDownload & 0xffff) | 0x43210000),
134 0,
135 0
136 };
137 LOGD("reply 0x%x", prepareReply[0]);
138
139 mTestSocket.setSendExpectation((char*)prepareSend, sizeof(prepareSend));
140 // this is reply, but set expectation for reply first as it is sent after send
141 mTestSocket.setReadExpectation((char*)prepareReply, sizeof(prepareReply));
142
143 int id = -1;
144 android::String8 name("1");
145 ASSERT_TRUE(mRemoteAudio->downloadData(name, buffer, id));
146 ASSERT_TRUE(id >= 0);
147 }
148 };
149
TEST_F(RemoteAudioFakeTcpTest,InitTest)150 TEST_F(RemoteAudioFakeTcpTest, InitTest) {
151 // all done in SetUp
152 }
153
TEST_F(RemoteAudioFakeTcpTest,DownloadTest)154 TEST_F(RemoteAudioFakeTcpTest, DownloadTest) {
155 doDownload();
156 }
157
TEST_F(RemoteAudioFakeTcpTest,PlayTest)158 TEST_F(RemoteAudioFakeTcpTest, PlayTest) {
159 doDownload();
160
161 bool stereo = false;
162 int id = 0;
163 int samplingF = 44100;
164 int mode = AudioHardware::EModeVoice | (stereo ? 0x80000000 : 0);
165 int volume = 0;
166 int repeat = 1;
167
168 uint32_t prepareSend[] = {
169 U32_ENDIAN_SWAP(AudioProtocol::ECmdStartPlayback),
170 U32_ENDIAN_SWAP(20),
171 U32_ENDIAN_SWAP(id), //id
172 U32_ENDIAN_SWAP(samplingF),
173 U32_ENDIAN_SWAP(mode),
174 U32_ENDIAN_SWAP(volume),
175 U32_ENDIAN_SWAP(repeat)
176 };
177 uint32_t prepareReply[] = {
178 U32_ENDIAN_SWAP((AudioProtocol::ECmdStartPlayback & 0xffff) | 0x43210000),
179 0,
180 0
181 };
182
183 mTestSocket.setSendExpectation((char*)prepareSend, sizeof(prepareSend));
184 // this is reply, but set expectation for reply first as it is sent after send
185 mTestSocket.setReadExpectation((char*)prepareReply, sizeof(prepareReply));
186
187 ASSERT_TRUE(mRemoteAudio->startPlayback(stereo, samplingF, mode, volume, id, repeat));
188 ASSERT_TRUE(mRemoteAudio->waitForPlaybackCompletion());
189 }
190
TEST_F(RemoteAudioFakeTcpTest,PlayStopTest)191 TEST_F(RemoteAudioFakeTcpTest, PlayStopTest) {
192 doDownload();
193
194 bool stereo = false;
195 int id = 0;
196 int samplingF = 44100;
197 int mode = AudioHardware::EModeVoice | (stereo ? 0x80000000 : 0);
198 int volume = 0;
199 int repeat = 1;
200
201 uint32_t startPlaybackSend[] = {
202 U32_ENDIAN_SWAP(AudioProtocol::ECmdStartPlayback),
203 U32_ENDIAN_SWAP(20),
204 U32_ENDIAN_SWAP(id),
205 U32_ENDIAN_SWAP(samplingF),
206 U32_ENDIAN_SWAP(mode),
207 U32_ENDIAN_SWAP(volume),
208 U32_ENDIAN_SWAP(repeat)
209 };
210 uint32_t startReply[] = {
211 U32_ENDIAN_SWAP((AudioProtocol::ECmdStartPlayback & 0xffff) | 0x43210000),
212 0,
213 0
214 };
215
216 uint32_t stopPlaybackSend[] = {
217 U32_ENDIAN_SWAP(AudioProtocol::ECmdStopPlayback),
218 U32_ENDIAN_SWAP(0)
219 };
220
221 uint32_t stopReply[] = {
222 U32_ENDIAN_SWAP((AudioProtocol::ECmdStopPlayback & 0xffff) | 0x43210000),
223 0,
224 0
225 };
226
227 mTestSocket.setSendExpectation((char*)startPlaybackSend, sizeof(startPlaybackSend));
228 // this is reply, but set expectation for reply first as it is sent after send
229 mTestSocket.setReadExpectation((char*)startReply, sizeof(startReply));
230
231 ASSERT_TRUE(mRemoteAudio->startPlayback(stereo, samplingF, mode, volume, id, repeat));
232 sleep(1);
233 mTestSocket.setSendExpectation((char*)stopPlaybackSend, sizeof(stopPlaybackSend));
234 // this is reply, but set expectation for reply first as it is sent after send
235 mTestSocket.setReadExpectation((char*)stopReply, sizeof(stopReply));
236 mRemoteAudio->stopPlayback();
237
238 mTestSocket.setSendExpectation((char*)startPlaybackSend, sizeof(startPlaybackSend));
239 // this is reply, but set expectation for reply first as it is sent after send
240 mTestSocket.setReadExpectation((char*)startReply, sizeof(startReply));
241 ASSERT_TRUE(mRemoteAudio->startPlayback(stereo, samplingF, mode, volume, id, repeat));
242 sleep(1);
243 mTestSocket.setSendExpectation((char*)stopPlaybackSend, sizeof(stopPlaybackSend));
244 // this is reply, but set expectation for reply first as it is sent after send
245 mTestSocket.setReadExpectation((char*)stopReply, sizeof(stopReply));
246 mRemoteAudio->stopPlayback();
247
248 mTestSocket.setSendExpectation((char*)startPlaybackSend, sizeof(startPlaybackSend));
249 // this is reply, but set expectation for reply first as it is sent after send
250 mTestSocket.setReadExpectation((char*)startReply, sizeof(startReply));
251 ASSERT_TRUE(mRemoteAudio->startPlayback(stereo, samplingF, mode, volume, id, repeat));
252 ASSERT_TRUE(mRemoteAudio->waitForPlaybackCompletion());
253 }
254
TEST_F(RemoteAudioFakeTcpTest,RecordingTest)255 TEST_F(RemoteAudioFakeTcpTest, RecordingTest) {
256 bool stereo = false;
257 int id = 0;
258 int samplingF = 44100;
259 int mode = AudioHardware::EModeVoice | (stereo ? 0x80000000 : 0);
260 int volume = 0;
261 int noSamples = 44; // 1ms worth
262
263 android::sp<Buffer> buffer(new Buffer(100, noSamples*2, false));
264
265 uint32_t startSend[] = {
266 U32_ENDIAN_SWAP(AudioProtocol::ECmdStartRecording),
267 U32_ENDIAN_SWAP(16),
268 U32_ENDIAN_SWAP(samplingF),
269 U32_ENDIAN_SWAP(mode),
270 U32_ENDIAN_SWAP(volume),
271 U32_ENDIAN_SWAP(noSamples)
272 };
273
274 // 2bytes per sample, +2 for last samples rounded off
275 uint32_t startReply[noSamples/2 + 2 + 3];
276 memset(startReply, 0, sizeof(startReply));
277 startReply[0] = U32_ENDIAN_SWAP((AudioProtocol::ECmdStartRecording & 0xffff) | 0x43210000);
278 startReply[1] = 0;
279 startReply[2] = U32_ENDIAN_SWAP(noSamples * 2);
280
281 uint32_t stopSend[] = {
282 U32_ENDIAN_SWAP(AudioProtocol::ECmdStopRecording),
283 U32_ENDIAN_SWAP(0)
284 };
285
286 uint32_t stopReply[] = {
287 U32_ENDIAN_SWAP((AudioProtocol::ECmdStopRecording & 0xffff) | 0x43210000),
288 0,
289 0
290 };
291
292
293 mTestSocket.setSendExpectation((char*)startSend, sizeof(startSend));
294 // this is reply, but set expectation for reply first as it is sent after send
295 mTestSocket.setReadExpectation((char*)startReply, 12 + noSamples*2);
296
297 ASSERT_TRUE(mRemoteAudio->startRecording(stereo, samplingF, mode, volume, buffer));
298 ASSERT_TRUE(mRemoteAudio->waitForRecordingCompletion());
299 ASSERT_TRUE(buffer->amountHandled() == (size_t)(noSamples * 2));
300 mTestSocket.setSendExpectation((char*)startSend, sizeof(startSend));
301 // this is reply, but set expectation for reply first as it is sent after send
302 mTestSocket.setReadExpectation((char*)startReply, 12 + noSamples*2);
303 ASSERT_TRUE(mRemoteAudio->startRecording(stereo, samplingF, mode, volume, buffer));
304 sleep(1);
305 mTestSocket.setSendExpectation((char*)stopSend, sizeof(stopSend));
306 // this is reply, but set expectation for reply first as it is sent after send
307 mTestSocket.setReadExpectation((char*)stopReply, sizeof(stopReply));
308 mRemoteAudio->stopRecording();
309 }
310
TEST_F(RemoteAudioFakeTcpTest,getDeviceInfoTest)311 TEST_F(RemoteAudioFakeTcpTest, getDeviceInfoTest) {
312 uint32_t prepareSend[] = {
313 U32_ENDIAN_SWAP(AudioProtocol::ECmdGetDeviceInfo),
314 U32_ENDIAN_SWAP(0)
315 };
316 uint32_t prepareReply[] = {
317 U32_ENDIAN_SWAP((AudioProtocol::ECmdGetDeviceInfo & 0xffff) | 0x43210000),
318 0,
319 U32_ENDIAN_SWAP(4),
320 U32_ENDIAN_SWAP(0x30313233)
321 };
322
323 mTestSocket.setSendExpectation((char*)prepareSend, sizeof(prepareSend));
324 // this is reply, but set expectation for reply first as it is sent after send
325 mTestSocket.setReadExpectation((char*)prepareReply, sizeof(prepareReply));
326
327 android::String8 info;
328 ASSERT_TRUE(mRemoteAudio->getDeviceInfo(info));
329 ASSERT_TRUE(info == "0123");
330 }
331