summaryrefslogtreecommitdiffstats
path: root/libaudio/AudioHardware.h
blob: 455da01bd3eafd2002225fd95fd68d78eee942f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
/*
** Copyright 2008, The Android Open-Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#ifndef ANDROID_AUDIO_HARDWARE_H
#define ANDROID_AUDIO_HARDWARE_H

#include <stdint.h>
#include <sys/types.h>

#include <utils/threads.h>
#include <utils/SortedVector.h>

#include <hardware_legacy/AudioHardwareBase.h>
#include <hardware/audio_effect.h>

#include "secril-client.h"

#include <audio_utils/resampler.h>
#include <audio_utils/echo_reference.h>

extern "C" {
    struct pcm;
    struct mixer;
    struct mixer_ctl;
};

namespace android_audio_legacy {
    using android::AutoMutex;
    using android::Mutex;
    using android::RefBase;
    using android::SortedVector;
    using android::sp;
    using android::String16;
    using android::Vector;

// TODO: determine actual audio DSP and hardware latency
// Additional latency introduced by audio DSP and hardware in ms
#define AUDIO_HW_OUT_LATENCY_MS 0
// Default audio output sample rate
#define AUDIO_HW_OUT_SAMPLERATE 44100
// Default audio output channel mask
#define AUDIO_HW_OUT_CHANNELS (AudioSystem::CHANNEL_OUT_STEREO)
// Default audio output sample format
#define AUDIO_HW_OUT_FORMAT (AudioSystem::PCM_16_BIT)
// Kernel pcm out buffer size in frames at 44.1kHz
#define AUDIO_HW_OUT_PERIOD_SZ 880
#define AUDIO_HW_OUT_PERIOD_CNT 2
// Default audio output buffer size in bytes
#define AUDIO_HW_OUT_PERIOD_BYTES (AUDIO_HW_OUT_PERIOD_SZ * 2 * sizeof(int16_t))

// Default audio input sample rate
#define AUDIO_HW_IN_SAMPLERATE 44100
// Default audio input channel mask
#define AUDIO_HW_IN_CHANNELS (AudioSystem::CHANNEL_IN_MONO)
// Default audio input sample format
#define AUDIO_HW_IN_FORMAT (AudioSystem::PCM_16_BIT)
// Kernel pcm in buffer size in frames at 44.1kHz (before resampling)
#define AUDIO_HW_IN_PERIOD_SZ 1024
#define AUDIO_HW_IN_PERIOD_CNT 4
// Default audio input buffer size in bytes (8kHz mono)
#define AUDIO_HW_IN_PERIOD_BYTES ((AUDIO_HW_IN_PERIOD_SZ*sizeof(int16_t))/8)


class AudioHardware : public AudioHardwareBase
{
    class AudioStreamOutALSA;
    class AudioStreamInALSA;

public:

    // input path names used to translate from input sources to driver paths
    static const char *inputPathNameDefault;
    static const char *inputPathNameCamcorder;
    static const char *inputPathNameVoiceRecognition;
    static const char *inputPathNameVoiceCommunication;

    AudioHardware();
    virtual ~AudioHardware();
    virtual status_t initCheck();

    virtual status_t setVoiceVolume(float volume);
    virtual status_t setMasterVolume(float volume);
#ifdef HAVE_FM_RADIO
    virtual status_t setFmVolume(float volume);
#endif

    virtual status_t setMode(int mode);

    virtual status_t setMicMute(bool state);
    virtual status_t getMicMute(bool* state);

    virtual status_t setParameters(const String8& keyValuePairs);
    virtual String8 getParameters(const String8& keys);

    virtual AudioStreamOut* openOutputStream(
        uint32_t devices, int *format=0, uint32_t *channels=0,
        uint32_t *sampleRate=0, status_t *status=0);

    virtual AudioStreamIn* openInputStream(
        uint32_t devices, int *format, uint32_t *channels,
        uint32_t *sampleRate, status_t *status,
        AudioSystem::audio_in_acoustics acoustics);

    virtual void closeOutputStream(AudioStreamOut* out);
    virtual void closeInputStream(AudioStreamIn* in);

    virtual size_t getInputBufferSize(
        uint32_t sampleRate, int format, int channelCount);

            int  mode() { return mMode; }
            const char *getOutputRouteFromDevice(uint32_t device);
            const char *getInputRouteFromDevice(uint32_t device);
            const char *getVoiceRouteFromDevice(uint32_t device);

            status_t setIncallPath_l(uint32_t device);

#ifdef HAVE_FM_RADIO
            void enableFMRadio();
            void disableFMRadio();
            status_t setFMRadioPath_l(uint32_t device);
#endif

            status_t setInputSource_l(audio_source source);

            void setVoiceVolume_l(float volume);

    static uint32_t    getInputSampleRate(uint32_t sampleRate);
           sp <AudioStreamInALSA> getActiveInput_l();

           Mutex& lock() { return mLock; }

           struct pcm *openPcmOut_l();
           void closePcmOut_l();

           struct mixer *openMixer_l();
           void closeMixer_l();

           sp <AudioStreamOutALSA>  output() { return mOutput; }

           struct echo_reference_itfe *getEchoReference(audio_format_t format,
                                          uint32_t channelCount,
                                          uint32_t samplingRate);
           void releaseEchoReference(struct echo_reference_itfe *reference);

protected:
    virtual status_t dump(int fd, const Vector<String16>& args);

private:

    enum tty_modes {
        TTY_MODE_OFF,
        TTY_MODE_VCO,
        TTY_MODE_HCO,
        TTY_MODE_FULL
    };

    bool            mInit;
    bool            mMicMute;
    sp <AudioStreamOutALSA>                 mOutput;
    SortedVector < sp<AudioStreamInALSA> >   mInputs;
    Mutex           mLock;
    struct pcm*     mPcm;
    struct mixer*   mMixer;
    uint32_t        mPcmOpenCnt;
    uint32_t        mMixerOpenCnt;
    bool            mInCallAudioMode;
    float           mVoiceVol;

    audio_source    mInputSource;
    bool            mBluetoothNrec;
    int             mTTYMode;

    void*           mSecRilLibHandle;
    HRilClient      mRilClient;
    bool            mActivatedCP;
    HRilClient      (*openClientRILD)  (void);
    int             (*disconnectRILD)  (HRilClient);
    int             (*closeClientRILD) (HRilClient);
    int             (*isConnectedRILD) (HRilClient);
    int             (*connectRILD)     (HRilClient);
#ifdef USES_FROYO_RILCLIENT
    int             (*invokeOemRequestHookRaw) (HRilClient, char *, size_t);
    int             (convertSoundType)    (SoundType);
    int             (convertAudioPath)    (AudioPath);
    int             (setCallVolume)       (HRilClient, SoundType, int);
    int             (setCallAudioPath)    (HRilClient, AudioPath);
    int             (setCallClockSync)    (HRilClient, SoundClockCondition);
#else
    int             (*setCallVolume)   (HRilClient, SoundType, int);
    int             (*setCallAudioPath)(HRilClient, AudioPath);
    int             (*setCallClockSync)(HRilClient, SoundClockCondition);
#endif
    void            loadRILD(void);
    status_t        connectRILDIfRequired(void);
    struct echo_reference_itfe *mEchoReference;

#ifdef HAVE_FM_RADIO
    int             mFmFd;
    float           mFmVolume;
    bool            mFmResumeAfterCall;
#endif

    //  trace driver operations for dump
    int             mDriverOp;

    static uint32_t         checkInputSampleRate(uint32_t sampleRate);

    // column index in inputConfigTable[][]
    enum {
        INPUT_CONFIG_SAMPLE_RATE,
        INPUT_CONFIG_BUFFER_RATIO,
        INPUT_CONFIG_CNT
    };

    // contains the list of valid sampling rates for input streams as well as the ratio
    // between the kernel buffer size and audio hal buffer size for each sampling rate
    static const uint32_t  inputConfigTable[][INPUT_CONFIG_CNT];

    class AudioStreamOutALSA : public AudioStreamOut, public RefBase
    {
    public:
        AudioStreamOutALSA();
        virtual ~AudioStreamOutALSA();
        status_t set(AudioHardware* mHardware,
                     uint32_t devices,
                     int *pFormat,
                     uint32_t *pChannels,
                     uint32_t *pRate);
        virtual uint32_t sampleRate()
            const { return mSampleRate; }
        virtual size_t bufferSize()
            const { return mBufferSize; }
        virtual uint32_t channels()
            const { return mChannels; }
        virtual int format()
            const { return AUDIO_HW_OUT_FORMAT; }
        virtual uint32_t latency()
            const { return (1000 * AUDIO_HW_OUT_PERIOD_CNT *
                            (bufferSize()/frameSize()))/sampleRate() +
                AUDIO_HW_OUT_LATENCY_MS; }
        virtual status_t setVolume(float left, float right)
        { return INVALID_OPERATION; }
        virtual ssize_t write(const void* buffer, size_t bytes);
        virtual status_t standby();
                bool checkStandby();

        virtual status_t dump(int fd, const Vector<String16>& args);
        virtual status_t setParameters(const String8& keyValuePairs);
        virtual String8 getParameters(const String8& keys);
        uint32_t device() { return mDevices; }
        virtual status_t getRenderPosition(uint32_t *dspFrames);

                void doStandby_l();
                void close_l();
                status_t open_l();
                int standbyCnt() { return mStandbyCnt; }

                int prepareLock();
                void lock();
                void unlock();

                void addEchoReference(struct echo_reference_itfe *reference);
                void removeEchoReference(struct echo_reference_itfe *reference);

    private:

                int computeEchoReferenceDelay(size_t frames, struct timespec *echoRefRenderTime);
                int getPlaybackDelay(size_t frames, struct echo_reference_buffer *buffer);

        Mutex mLock;
        AudioHardware* mHardware;
        struct pcm *mPcm;
        struct mixer *mMixer;
        struct mixer_ctl *mRouteCtl;
        const char *next_route;
        bool mStandby;
        uint32_t mDevices;
        uint32_t mChannels;
        uint32_t mSampleRate;
        size_t mBufferSize;
        //  trace driver operations for dump
        int mDriverOp;
        int mStandbyCnt;
        bool mSleepReq;
        struct echo_reference_itfe *mEchoReference;
    };

    class AudioStreamInALSA : public AudioStreamIn, public RefBase
    {

     public:
                    AudioStreamInALSA();
        virtual     ~AudioStreamInALSA();
        status_t    set(AudioHardware* hw,
                    uint32_t devices,
                    int *pFormat,
                    uint32_t *pChannels,
                    uint32_t *pRate,
                    AudioSystem::audio_in_acoustics acoustics);
        virtual size_t bufferSize() const { return mBufferSize; }
        virtual uint32_t channels() const { return mChannels; }
        virtual int format() const { return AUDIO_HW_IN_FORMAT; }
        virtual uint32_t sampleRate() const { return mSampleRate; }
        virtual status_t setGain(float gain) { return INVALID_OPERATION; }
        virtual ssize_t read(void* buffer, ssize_t bytes);
        virtual status_t dump(int fd, const Vector<String16>& args);
        virtual status_t standby();
                bool checkStandby();
        virtual status_t setParameters(const String8& keyValuePairs);
        virtual String8 getParameters(const String8& keys);
        virtual unsigned int getInputFramesLost() const { return 0; }
        virtual status_t    addAudioEffect(effect_handle_t effect);
        virtual status_t    removeAudioEffect(effect_handle_t effect);

                uint32_t device() { return mDevices; }
                void doStandby_l();
                void close_l();
                status_t open_l();
                int standbyCnt() { return mStandbyCnt; }

        static size_t getBufferSize(uint32_t sampleRate, int channelCount);

        // resampler_buffer_provider
        static int getNextBufferStatic(struct resampler_buffer_provider *provider,
                             struct resampler_buffer* buffer);
        static void releaseBufferStatic(struct resampler_buffer_provider *provider,
                             struct resampler_buffer* buffer);

        int prepareLock();
        void lock();
        void unlock();

     private:

        struct ResamplerBufferProvider {
            struct resampler_buffer_provider mProvider;
            AudioStreamInALSA *mInputStream;
        };

        ssize_t readFrames(void* buffer, ssize_t frames);
        ssize_t processFrames(void* buffer, ssize_t frames);
        int32_t updateEchoReference(size_t frames);
        void pushEchoReference(size_t frames);
        void updateEchoDelay(size_t frames, struct timespec *echoRefRenderTime);
        void getCaptureDelay(size_t frames, struct echo_reference_buffer *buffer);
        status_t setPreProcessorEchoDelay(effect_handle_t handle, int32_t delayUs);
        status_t setPreprocessorParam(effect_handle_t handle, effect_param_t *param);

        // BufferProvider
        status_t getNextBuffer(struct resampler_buffer* buffer);
        void releaseBuffer(struct resampler_buffer* buffer);

        Mutex mLock;
        AudioHardware* mHardware;
        struct pcm *mPcm;
        struct mixer *mMixer;
        struct mixer_ctl *mRouteCtl;
        const char *next_route;
        bool mStandby;
        uint32_t mDevices;
        uint32_t mChannels;
        uint32_t mChannelCount;
        uint32_t mSampleRate;
        size_t mBufferSize;
        struct resampler_itfe *mDownSampler;
        struct ResamplerBufferProvider mBufferProvider;
        status_t mReadStatus;
        size_t mInputFramesIn;
        int16_t *mInputBuf;
        //  trace driver operations for dump
        int mDriverOp;
        int mStandbyCnt;
        bool mSleepReq;
        SortedVector<effect_handle_t> mPreprocessors;
        int16_t *mProcBuf;
        size_t mProcBufSize;
        size_t mProcFramesIn;
        int16_t *mRefBuf;
        size_t mRefBufSize;
        size_t mRefFramesIn;
        struct echo_reference_itfe *mEchoReference;
        bool mNeedEchoReference;
    };

};

}; // namespace android

#endif