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 
18 #ifndef CTSAUDIO_REMOTEAUDIO_H
19 #define CTSAUDIO_REMOTEAUDIO_H
20 
21 #include <map>
22 
23 #include <utils/Looper.h>
24 #include <utils/String8.h>
25 #include <utils/StrongPointer.h>
26 #include <utils/threads.h>
27 
28 #include "audio/Buffer.h"
29 #include "AudioProtocol.h"
30 #include "ClientSocket.h"
31 #include "Semaphore.h"
32 
33 class CommandHandler;
34 /**
35  * Tcp communication runs in a separate thread,
36  * and client can communicate using public APIs
37  * Assumption: only one command at a time. No other command can come
38  * while a command is pending.
39  */
40 class RemoteAudio: public android::Thread {
41 public:
42 
43     RemoteAudio(ClientSocket& socket);
44     virtual ~RemoteAudio();
45 
46     /** launch a thread, and connect to host */
47     bool init(int port);
48     bool downloadData(const android::String8 name, android::sp<Buffer>& buffer, int& id);
49     // <0 : not found
50     int getDataId(const android::String8& name);
51     bool startPlayback(bool stereo, int samplingF, int mode, int volume,
52             int id, int numberRepetition);
53     void stopPlayback();
54     bool waitForPlaybackCompletion();
55     // buffer.getSize() determines number of samples
56     bool startRecording(bool stereo, int samplingF, int mode, int volume,
57             android::sp<Buffer>& buffer);
58     bool waitForRecordingCompletion();
59     void stopRecording();
60 
61     bool getDeviceInfo(android::String8& data);
62     /** should be called before RemoteAudio is destroyed */
63     void release();
64 
65 private:
66     RemoteAudio(const RemoteAudio&);
67 
68     bool threadLoop();
69     void wakeClient(bool result);
70     void cleanup(bool notifyClient);
71 
72     bool handlePacket();
73     static int socketRxCallback(int fd, int events, void* data);
74 
75     class CommandHandler;
76     void sendCommand(android::sp<android::MessageHandler>& command);
77 
78     // this is just semaphore wait without any addition
79     bool waitForCompletion(android::sp<android::MessageHandler>& command, int timeInMSec);
80     // common code for waitForXXXCompletion
81     bool waitForPlaybackOrRecordingCompletion(
82             android::sp<android::MessageHandler>& commandHandler);
83     // common code for stopXXX
84     void doStop(android::sp<android::MessageHandler>& commandHandler, AudioProtocol::CommandId id);
85 
toCommandHandler(android::sp<android::MessageHandler> & command)86     CommandHandler* toCommandHandler(android::sp<android::MessageHandler>& command) {
87         return reinterpret_cast<CommandHandler*>(command.get());
88     };
89 
90 private:
91     bool mExitRequested;
92     bool mInitResult;
93     // used only for notifying successful init
94     Semaphore mInitWait;
95 
96 
97     enum EventId {
98         EIdSocket = 1,
99     };
100     static const int CLIENT_WAIT_TIMEOUT_MSEC = 2000;
101     int mPort;
102     ClientSocket& mSocket;
103 
104 
105     android::sp<android::Looper> mLooper;
106 
107     friend class CommandHandler;
108 
109     class CommandHandler: public android::MessageHandler {
110     public:
111         enum ClientCommands {
112             EExit = 1,
113         };
CommandHandler(RemoteAudio & thread,int command)114         CommandHandler(RemoteAudio& thread, int command)
115             : mThread(thread),
116               mMessage(command),
117               mNotifyOnReply(false),
118               mActive(false) {};
~CommandHandler()119         virtual ~CommandHandler() {};
120         void handleMessage(const android::Message& message);
timedWait(int timeInMSec)121         bool timedWait(int timeInMSec) {
122             return mClientWait.timedWait(timeInMSec);
123         };
getParam()124         AudioParam& getParam() {
125             return mParam;
126         };
getMessage()127         android::Message& getMessage() {
128             return mMessage;
129         };
130 
131     private:
132         RemoteAudio& mThread;
133         AudioParam mParam;
134         Semaphore mClientWait;
135         android::Mutex mStateLock;
136         android::Message mMessage;
137         bool mResult;
138         bool mNotifyOnReply;
139         bool mActive;
140         friend class RemoteAudio;
141     };
142     android::sp<android::MessageHandler> mDownloadHandler;
143     android::sp<android::MessageHandler> mPlaybackHandler;
144     android::sp<android::MessageHandler> mRecordingHandler;
145     android::sp<android::MessageHandler> mDeviceInfoHandler;
146 
147     AudioProtocol* mCmds[AudioProtocol::ECmdLast - AudioProtocol::ECmdStart];
148     int mDownloadId;
149     std::map<int, android::sp<Buffer> > mBufferList;
150     std::map<android::String8, int> mIdMap;
151 };
152 
153 
154 
155 #endif // CTSAUDIO_REMOTEAUDIO_H
156