1 /*
2  * Copyright 2017 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 #define LOG_TAG "AudioStreamLegacy"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <stdint.h>
22 #include <utils/String16.h>
23 #include <media/AudioTrack.h>
24 #include <aaudio/AAudio.h>
25 
26 #include "core/AudioStream.h"
27 #include "legacy/AudioStreamLegacy.h"
28 
29 using namespace android;
30 using namespace aaudio;
31 
AudioStreamLegacy()32 AudioStreamLegacy::AudioStreamLegacy()
33         : AudioStream(), mDeviceCallback(new StreamDeviceCallback(this)) {
34 }
35 
~AudioStreamLegacy()36 AudioStreamLegacy::~AudioStreamLegacy() {
37 }
38 
39 // Called from AudioTrack.cpp or AudioRecord.cpp
AudioStreamLegacy_callback(int event,void * userData,void * info)40 static void AudioStreamLegacy_callback(int event, void* userData, void *info) {
41     AudioStreamLegacy *streamLegacy = (AudioStreamLegacy *) userData;
42     streamLegacy->processCallback(event, info);
43 }
44 
getLegacyCallback()45 aaudio_legacy_callback_t AudioStreamLegacy::getLegacyCallback() {
46     return AudioStreamLegacy_callback;
47 }
48 
49 // Implement FixedBlockProcessor
onProcessFixedBlock(uint8_t * buffer,int32_t numBytes)50 int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
51     int32_t frameCount = numBytes / getBytesPerFrame();
52     // Call using the AAudio callback interface.
53     AAudioStream_dataCallback appCallback = getDataCallbackProc();
54     return (*appCallback)(
55             (AAudioStream *) this,
56             getDataCallbackUserData(),
57             buffer,
58             frameCount);
59 }
60 
processCallbackCommon(aaudio_callback_operation_t opcode,void * info)61 void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {
62     aaudio_data_callback_result_t callbackResult;
63 
64     if (!mCallbackEnabled.load()) {
65         return;
66     }
67 
68     switch (opcode) {
69         case AAUDIO_CALLBACK_OPERATION_PROCESS_DATA: {
70             if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
71                 // Note that this code assumes an AudioTrack::Buffer is the same as
72                 // AudioRecord::Buffer
73                 // TODO define our own AudioBuffer and pass it from the subclasses.
74                 AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
75                 if (audioBuffer->frameCount == 0) return;
76 
77                 // If the caller specified an exact size then use a block size adapter.
78                 if (mBlockAdapter != nullptr) {
79                     int32_t byteCount = audioBuffer->frameCount * getBytesPerFrame();
80                     callbackResult = mBlockAdapter->processVariableBlock(
81                             (uint8_t *) audioBuffer->raw, byteCount);
82                 } else {
83                     // Call using the AAudio callback interface.
84                     callbackResult = (*getDataCallbackProc())(
85                             (AAudioStream *) this,
86                             getDataCallbackUserData(),
87                             audioBuffer->raw,
88                             audioBuffer->frameCount
89                             );
90                 }
91                 if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
92                     audioBuffer->size = audioBuffer->frameCount * getBytesPerFrame();
93                     incrementClientFrameCounter(audioBuffer->frameCount);
94                 } else {
95                     audioBuffer->size = 0;
96                 }
97                 break;
98             }
99         }
100         /// FALL THROUGH
101 
102             // Stream got rerouted so we disconnect.
103         case AAUDIO_CALLBACK_OPERATION_DISCONNECTED: {
104             setState(AAUDIO_STREAM_STATE_DISCONNECTED);
105             ALOGD("processCallbackCommon() stream disconnected");
106             if (getErrorCallbackProc() != nullptr) {
107                 (*getErrorCallbackProc())(
108                         (AAudioStream *) this,
109                         getErrorCallbackUserData(),
110                         AAUDIO_ERROR_DISCONNECTED
111                         );
112             }
113             mCallbackEnabled.store(false);
114         }
115             break;
116 
117         default:
118             break;
119     }
120 }
121 
getBestTimestamp(clockid_t clockId,int64_t * framePosition,int64_t * timeNanoseconds,ExtendedTimestamp * extendedTimestamp)122 aaudio_result_t AudioStreamLegacy::getBestTimestamp(clockid_t clockId,
123                                                    int64_t *framePosition,
124                                                    int64_t *timeNanoseconds,
125                                                    ExtendedTimestamp *extendedTimestamp) {
126     int timebase;
127     switch (clockId) {
128         case CLOCK_BOOTTIME:
129             timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
130             break;
131         case CLOCK_MONOTONIC:
132             timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
133             break;
134         default:
135             ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
136             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
137             break;
138     }
139     status_t status = extendedTimestamp->getBestTimestamp(framePosition, timeNanoseconds, timebase);
140     return AAudioConvert_androidToAAudioResult(status);
141 }
142 
onAudioDeviceUpdate(audio_port_handle_t deviceId)143 void AudioStreamLegacy::onAudioDeviceUpdate(audio_port_handle_t deviceId)
144 {
145     ALOGD("onAudioDeviceUpdate() deviceId %d", (int)deviceId);
146     if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
147             getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
148         setState(AAUDIO_STREAM_STATE_DISCONNECTED);
149         // if we have a data callback and the stream is active, send the error callback from
150         // data callback thread when it sees the DISCONNECTED state
151         if (!isDataCallbackActive() && getErrorCallbackProc() != nullptr) {
152             (*getErrorCallbackProc())(
153                     (AAudioStream *) this,
154                     getErrorCallbackUserData(),
155                     AAUDIO_ERROR_DISCONNECTED
156                     );
157         }
158     }
159     setDeviceId(deviceId);
160 }
161