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