| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2016 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 |  | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 17 | // This file is used in both client and server processes. | 
 | 18 | // This is needed to make sense of the logs more easily. | 
 | 19 | #define LOG_TAG (mInService ? "AAudioService" : "AAudio") | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 20 | //#define LOG_NDEBUG 0 | 
 | 21 | #include <utils/Log.h> | 
 | 22 |  | 
| Phil Burk | 4485d41 | 2017-05-09 15:55:02 -0700 | [diff] [blame] | 23 | #define ATRACE_TAG ATRACE_TAG_AUDIO | 
 | 24 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 25 | #include <stdint.h> | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 26 | #include <assert.h> | 
 | 27 |  | 
 | 28 | #include <binder/IServiceManager.h> | 
 | 29 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 30 | #include <aaudio/AAudio.h> | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 31 | #include <utils/String16.h> | 
| Phil Burk | 4485d41 | 2017-05-09 15:55:02 -0700 | [diff] [blame] | 32 | #include <utils/Trace.h> | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 33 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 34 | #include "AudioClock.h" | 
 | 35 | #include "AudioEndpointParcelable.h" | 
 | 36 | #include "binding/AAudioStreamRequest.h" | 
 | 37 | #include "binding/AAudioStreamConfiguration.h" | 
 | 38 | #include "binding/IAAudioService.h" | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 39 | #include "binding/AAudioServiceMessage.h" | 
| Phil Burk | 3df348f | 2017-02-08 11:41:55 -0800 | [diff] [blame] | 40 | #include "core/AudioStreamBuilder.h" | 
| Phil Burk | e572f46 | 2017-04-20 13:03:19 -0700 | [diff] [blame] | 41 | #include "fifo/FifoBuffer.h" | 
 | 42 | #include "utility/LinearRamp.h" | 
 | 43 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 44 | #include "AudioStreamInternal.h" | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 45 |  | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 46 | using android::String16; | 
| Phil Burk | dec33ab | 2017-01-17 14:48:16 -0800 | [diff] [blame] | 47 | using android::Mutex; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 48 | using android::WrappingBuffer; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 49 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 50 | using namespace aaudio; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 51 |  | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 52 | #define MIN_TIMEOUT_NANOS        (1000 * AAUDIO_NANOS_PER_MILLISECOND) | 
 | 53 |  | 
 | 54 | // Wait at least this many times longer than the operation should take. | 
 | 55 | #define MIN_TIMEOUT_OPERATIONS    4 | 
 | 56 |  | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 57 | #define LOG_TIMESTAMPS   0 | 
 | 58 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 59 | AudioStreamInternal::AudioStreamInternal(AAudioServiceInterface  &serviceInterface, bool inService) | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 60 |         : AudioStream() | 
 | 61 |         , mClockModel() | 
 | 62 |         , mAudioEndpoint() | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 63 |         , mServiceStreamHandle(AAUDIO_HANDLE_INVALID) | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 64 |         , mFramesPerBurst(16) | 
| Eric Laurent | a2f296e | 2017-06-21 18:51:47 -0700 | [diff] [blame] | 65 |         , mStreamVolume(1.0f) | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 66 |         , mServiceInterface(serviceInterface) | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 67 |         , mInService(inService) { | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 68 | } | 
 | 69 |  | 
 | 70 | AudioStreamInternal::~AudioStreamInternal() { | 
 | 71 | } | 
 | 72 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 73 | aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) { | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 74 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 75 |     aaudio_result_t result = AAUDIO_OK; | 
 | 76 |     AAudioStreamRequest request; | 
 | 77 |     AAudioStreamConfiguration configuration; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 78 |  | 
 | 79 |     result = AudioStream::open(builder); | 
 | 80 |     if (result < 0) { | 
 | 81 |         return result; | 
 | 82 |     } | 
 | 83 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 84 |     // We have to do volume scaling. So we prefer FLOAT format. | 
| Glenn Kasten | 37a466a | 2017-05-30 15:53:14 -0700 | [diff] [blame] | 85 |     if (getFormat() == AAUDIO_FORMAT_UNSPECIFIED) { | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 86 |         setFormat(AAUDIO_FORMAT_PCM_FLOAT); | 
 | 87 |     } | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 88 |     // Request FLOAT for the shared mixer. | 
 | 89 |     request.getConfiguration().setAudioFormat(AAUDIO_FORMAT_PCM_FLOAT); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 90 |  | 
| Phil Burk | dec33ab | 2017-01-17 14:48:16 -0800 | [diff] [blame] | 91 |     // Build the request to send to the server. | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 92 |     request.setUserId(getuid()); | 
 | 93 |     request.setProcessId(getpid()); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 94 |     request.setDirection(getDirection()); | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 95 |     request.setSharingModeMatchRequired(isSharingModeMatchRequired()); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 96 |  | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 97 |     request.getConfiguration().setDeviceId(getDeviceId()); | 
 | 98 |     request.getConfiguration().setSampleRate(getSampleRate()); | 
 | 99 |     request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame()); | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 100 |     request.getConfiguration().setSharingMode(getSharingMode()); | 
 | 101 |  | 
| Phil Burk | 3df348f | 2017-02-08 11:41:55 -0800 | [diff] [blame] | 102 |     request.getConfiguration().setBufferCapacity(builder.getBufferCapacity()); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 103 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 104 |     mServiceStreamHandle = mServiceInterface.openStream(request, configuration); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 105 |     if (mServiceStreamHandle < 0) { | 
 | 106 |         result = mServiceStreamHandle; | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 107 |         ALOGE("AudioStreamInternal.open(): openStream() returned %d", result); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 108 |     } else { | 
 | 109 |         result = configuration.validate(); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 110 |         if (result != AAUDIO_OK) { | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 111 |             close(); | 
 | 112 |             return result; | 
 | 113 |         } | 
 | 114 |         // Save results of the open. | 
 | 115 |         setSampleRate(configuration.getSampleRate()); | 
 | 116 |         setSamplesPerFrame(configuration.getSamplesPerFrame()); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 117 |         setDeviceId(configuration.getDeviceId()); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 118 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 119 |         // Save device format so we can do format conversion and volume scaling together. | 
 | 120 |         mDeviceFormat = configuration.getAudioFormat(); | 
 | 121 |  | 
 | 122 |         result = mServiceInterface.getStreamDescription(mServiceStreamHandle, mEndPointParcelable); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 123 |         if (result != AAUDIO_OK) { | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 124 |             mServiceInterface.closeStream(mServiceStreamHandle); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 125 |             return result; | 
 | 126 |         } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 127 |  | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 128 |         // resolve parcelable into a descriptor | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 129 |         result = mEndPointParcelable.resolve(&mEndpointDescriptor); | 
 | 130 |         if (result != AAUDIO_OK) { | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 131 |             mServiceInterface.closeStream(mServiceStreamHandle); | 
 | 132 |             return result; | 
 | 133 |         } | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 134 |  | 
 | 135 |         // Configure endpoint based on descriptor. | 
 | 136 |         mAudioEndpoint.configure(&mEndpointDescriptor); | 
 | 137 |  | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 138 |         mFramesPerBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst; | 
 | 139 |         int32_t capacity = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames; | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 140 |  | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 141 |         // Validate result from server. | 
 | 142 |         if (mFramesPerBurst < 16 || mFramesPerBurst > 16 * 1024) { | 
 | 143 |             ALOGE("AudioStream::open(): framesPerBurst out of range = %d", mFramesPerBurst); | 
 | 144 |             return AAUDIO_ERROR_OUT_OF_RANGE; | 
 | 145 |         } | 
 | 146 |         if (capacity < mFramesPerBurst || capacity > 32 * 1024) { | 
 | 147 |             ALOGE("AudioStream::open(): bufferCapacity out of range = %d", capacity); | 
 | 148 |             return AAUDIO_ERROR_OUT_OF_RANGE; | 
 | 149 |         } | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 150 |  | 
 | 151 |         mClockModel.setSampleRate(getSampleRate()); | 
 | 152 |         mClockModel.setFramesPerBurst(mFramesPerBurst); | 
 | 153 |  | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 154 |         if (getDataCallbackProc()) { | 
 | 155 |             mCallbackFrames = builder.getFramesPerDataCallback(); | 
 | 156 |             if (mCallbackFrames > getBufferCapacity() / 2) { | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 157 |                 ALOGE("AudioStreamInternal.open(): framesPerCallback too large = %d, capacity = %d", | 
 | 158 |                       mCallbackFrames, getBufferCapacity()); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 159 |                 mServiceInterface.closeStream(mServiceStreamHandle); | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 160 |                 return AAUDIO_ERROR_OUT_OF_RANGE; | 
 | 161 |  | 
 | 162 |             } else if (mCallbackFrames < 0) { | 
 | 163 |                 ALOGE("AudioStreamInternal.open(): framesPerCallback negative"); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 164 |                 mServiceInterface.closeStream(mServiceStreamHandle); | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 165 |                 return AAUDIO_ERROR_OUT_OF_RANGE; | 
 | 166 |  | 
 | 167 |             } | 
 | 168 |             if (mCallbackFrames == AAUDIO_UNSPECIFIED) { | 
 | 169 |                 mCallbackFrames = mFramesPerBurst; | 
 | 170 |             } | 
 | 171 |  | 
 | 172 |             int32_t bytesPerFrame = getSamplesPerFrame() | 
 | 173 |                                     * AAudioConvert_formatToSizeInBytes(getFormat()); | 
 | 174 |             int32_t callbackBufferSize = mCallbackFrames * bytesPerFrame; | 
 | 175 |             mCallbackBuffer = new uint8_t[callbackBufferSize]; | 
 | 176 |         } | 
 | 177 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 178 |         setState(AAUDIO_STREAM_STATE_OPEN); | 
| Eric Laurent | a2f296e | 2017-06-21 18:51:47 -0700 | [diff] [blame] | 179 |         // only connect to AudioManager if this is a playback stream running in client process | 
 | 180 |         if (!mInService && getDirection() == AAUDIO_DIRECTION_OUTPUT) { | 
 | 181 |             init(android::PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA); | 
 | 182 |         } | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 183 |     } | 
 | 184 |     return result; | 
 | 185 | } | 
 | 186 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 187 | aaudio_result_t AudioStreamInternal::close() { | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 188 |     ALOGD("AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X", | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 189 |              mServiceStreamHandle); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 190 |     if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) { | 
| Phil Burk | 4485d41 | 2017-05-09 15:55:02 -0700 | [diff] [blame] | 191 |         // Don't close a stream while it is running. | 
 | 192 |         aaudio_stream_state_t currentState = getState(); | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 193 |         if (isActive()) { | 
| Phil Burk | 4485d41 | 2017-05-09 15:55:02 -0700 | [diff] [blame] | 194 |             requestStop(); | 
 | 195 |             aaudio_stream_state_t nextState; | 
 | 196 |             int64_t timeoutNanoseconds = MIN_TIMEOUT_NANOS; | 
 | 197 |             aaudio_result_t result = waitForStateChange(currentState, &nextState, | 
 | 198 |                                                        timeoutNanoseconds); | 
 | 199 |             if (result != AAUDIO_OK) { | 
 | 200 |                 ALOGE("AudioStreamInternal::close() waitForStateChange() returned %d %s", | 
 | 201 |                 result, AAudio_convertResultToText(result)); | 
 | 202 |             } | 
 | 203 |         } | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 204 |         aaudio_handle_t serviceStreamHandle = mServiceStreamHandle; | 
 | 205 |         mServiceStreamHandle = AAUDIO_HANDLE_INVALID; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 206 |  | 
 | 207 |         mServiceInterface.closeStream(serviceStreamHandle); | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 208 |         delete[] mCallbackBuffer; | 
| Phil Burk | 4485d41 | 2017-05-09 15:55:02 -0700 | [diff] [blame] | 209 |         mCallbackBuffer = nullptr; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 210 |         return mEndPointParcelable.close(); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 211 |     } else { | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 212 |         return AAUDIO_ERROR_INVALID_HANDLE; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 213 |     } | 
 | 214 | } | 
 | 215 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 216 |  | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 217 | static void *aaudio_callback_thread_proc(void *context) | 
 | 218 | { | 
 | 219 |     AudioStreamInternal *stream = (AudioStreamInternal *)context; | 
| Phil Burk | 677d791 | 2017-04-07 12:17:12 -0700 | [diff] [blame] | 220 |     //LOGD("AudioStreamInternal(): oboe_callback_thread, stream = %p", stream); | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 221 |     if (stream != NULL) { | 
 | 222 |         return stream->callbackLoop(); | 
 | 223 |     } else { | 
 | 224 |         return NULL; | 
 | 225 |     } | 
 | 226 | } | 
 | 227 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 228 | aaudio_result_t AudioStreamInternal::requestStart() | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 229 | { | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 230 |     int64_t startTime; | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 231 |     ALOGD("AudioStreamInternal(): start()"); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 232 |     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { | 
 | 233 |         return AAUDIO_ERROR_INVALID_STATE; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 234 |     } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 235 |  | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 236 |     startTime = AudioClock::getNanoseconds(); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 237 |     mClockModel.start(startTime); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 238 |     setState(AAUDIO_STREAM_STATE_STARTING); | 
| Eric Laurent | a2f296e | 2017-06-21 18:51:47 -0700 | [diff] [blame] | 239 |     aaudio_result_t result = AAudioConvert_androidToAAudioResult(startWithStatus()); | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 240 |  | 
 | 241 |     if (result == AAUDIO_OK && getDataCallbackProc() != nullptr) { | 
 | 242 |         // Launch the callback loop thread. | 
 | 243 |         int64_t periodNanos = mCallbackFrames | 
 | 244 |                               * AAUDIO_NANOS_PER_SECOND | 
 | 245 |                               / getSampleRate(); | 
 | 246 |         mCallbackEnabled.store(true); | 
 | 247 |         result = createThread(periodNanos, aaudio_callback_thread_proc, this); | 
 | 248 |     } | 
 | 249 |     return result; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 250 | } | 
 | 251 |  | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 252 | int64_t AudioStreamInternal::calculateReasonableTimeout(int32_t framesPerOperation) { | 
 | 253 |  | 
 | 254 |     // Wait for at least a second or some number of callbacks to join the thread. | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 255 |     int64_t timeoutNanoseconds = (MIN_TIMEOUT_OPERATIONS | 
 | 256 |                                   * framesPerOperation | 
 | 257 |                                   * AAUDIO_NANOS_PER_SECOND) | 
 | 258 |                                   / getSampleRate(); | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 259 |     if (timeoutNanoseconds < MIN_TIMEOUT_NANOS) { // arbitrary number of seconds | 
 | 260 |         timeoutNanoseconds = MIN_TIMEOUT_NANOS; | 
 | 261 |     } | 
 | 262 |     return timeoutNanoseconds; | 
 | 263 | } | 
 | 264 |  | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 265 | int64_t AudioStreamInternal::calculateReasonableTimeout() { | 
 | 266 |     return calculateReasonableTimeout(getFramesPerBurst()); | 
 | 267 | } | 
 | 268 |  | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 269 | aaudio_result_t AudioStreamInternal::stopCallback() | 
 | 270 | { | 
 | 271 |     if (isDataCallbackActive()) { | 
 | 272 |         mCallbackEnabled.store(false); | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 273 |         return joinThread(NULL); | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 274 |     } else { | 
 | 275 |         return AAUDIO_OK; | 
 | 276 |     } | 
 | 277 | } | 
 | 278 |  | 
 | 279 | aaudio_result_t AudioStreamInternal::requestPauseInternal() | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 280 | { | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 281 |     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 282 |         ALOGE("AudioStreamInternal(): requestPauseInternal() mServiceStreamHandle invalid = 0x%08X", | 
 | 283 |               mServiceStreamHandle); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 284 |         return AAUDIO_ERROR_INVALID_STATE; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 285 |     } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 286 |  | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 287 |     mClockModel.stop(AudioClock::getNanoseconds()); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 288 |     setState(AAUDIO_STREAM_STATE_PAUSING); | 
| Eric Laurent | a2f296e | 2017-06-21 18:51:47 -0700 | [diff] [blame] | 289 |     return AAudioConvert_androidToAAudioResult(pauseWithStatus()); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 290 | } | 
 | 291 |  | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 292 | aaudio_result_t AudioStreamInternal::requestPause() | 
 | 293 | { | 
 | 294 |     aaudio_result_t result = stopCallback(); | 
 | 295 |     if (result != AAUDIO_OK) { | 
 | 296 |         return result; | 
 | 297 |     } | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 298 |     result = requestPauseInternal(); | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 299 |     return result; | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 300 | } | 
 | 301 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 302 | aaudio_result_t AudioStreamInternal::requestFlush() { | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 303 |     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 304 |         ALOGE("AudioStreamInternal(): requestFlush() mServiceStreamHandle invalid = 0x%08X", | 
 | 305 |               mServiceStreamHandle); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 306 |         return AAUDIO_ERROR_INVALID_STATE; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 307 |     } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 308 |  | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 309 |     setState(AAUDIO_STREAM_STATE_FLUSHING); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 310 |     return mServiceInterface.flushStream(mServiceStreamHandle); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 311 | } | 
 | 312 |  | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 313 | // TODO for Play only | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 314 | void AudioStreamInternal::onFlushFromServer() { | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 315 |     ALOGD("AudioStreamInternal(): onFlushFromServer()"); | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 316 |     int64_t readCounter = mAudioEndpoint.getDataReadCounter(); | 
 | 317 |     int64_t writeCounter = mAudioEndpoint.getDataWriteCounter(); | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 318 |  | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 319 |     // Bump offset so caller does not see the retrograde motion in getFramesRead(). | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 320 |     int64_t framesFlushed = writeCounter - readCounter; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 321 |     mFramesOffsetFromService += framesFlushed; | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 322 |  | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 323 |     // Flush written frames by forcing writeCounter to readCounter. | 
 | 324 |     // This is because we cannot move the read counter in the hardware. | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 325 |     mAudioEndpoint.setDataWriteCounter(readCounter); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 326 | } | 
 | 327 |  | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 328 | aaudio_result_t AudioStreamInternal::requestStopInternal() | 
 | 329 | { | 
 | 330 |     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { | 
 | 331 |         ALOGE("AudioStreamInternal(): requestStopInternal() mServiceStreamHandle invalid = 0x%08X", | 
 | 332 |               mServiceStreamHandle); | 
 | 333 |         return AAUDIO_ERROR_INVALID_STATE; | 
 | 334 |     } | 
 | 335 |  | 
 | 336 |     mClockModel.stop(AudioClock::getNanoseconds()); | 
 | 337 |     setState(AAUDIO_STREAM_STATE_STOPPING); | 
| Eric Laurent | a2f296e | 2017-06-21 18:51:47 -0700 | [diff] [blame] | 338 |     return AAudioConvert_androidToAAudioResult(stopWithStatus()); | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 339 | } | 
 | 340 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 341 | aaudio_result_t AudioStreamInternal::requestStop() | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 342 | { | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 343 |     aaudio_result_t result = stopCallback(); | 
 | 344 |     if (result != AAUDIO_OK) { | 
 | 345 |         return result; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 346 |     } | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 347 |     result = requestStopInternal(); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 348 |     return result; | 
 | 349 | } | 
 | 350 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 351 | aaudio_result_t AudioStreamInternal::registerThread() { | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 352 |     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { | 
 | 353 |         return AAUDIO_ERROR_INVALID_STATE; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 354 |     } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 355 |     return mServiceInterface.registerAudioThread(mServiceStreamHandle, | 
 | 356 |                                               getpid(), | 
 | 357 |                                               gettid(), | 
 | 358 |                                               getPeriodNanoseconds()); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 359 | } | 
 | 360 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 361 | aaudio_result_t AudioStreamInternal::unregisterThread() { | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 362 |     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { | 
 | 363 |         return AAUDIO_ERROR_INVALID_STATE; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 364 |     } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 365 |     return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, getpid(), gettid()); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 366 | } | 
 | 367 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 368 | aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId, | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 369 |                            int64_t *framePosition, | 
 | 370 |                            int64_t *timeNanoseconds) { | 
| Phil Burk | 5204d31 | 2017-05-04 17:16:13 -0700 | [diff] [blame] | 371 |     // TODO Generate in server and pass to client. Return latest. | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 372 |     int64_t time = AudioClock::getNanoseconds(); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 373 |     *framePosition = mClockModel.convertTimeToPosition(time); | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 374 |     // TODO Get a more accurate timestamp from the service. This code just adds a fudge factor. | 
 | 375 |     *timeNanoseconds = time + (6 * AAUDIO_NANOS_PER_MILLISECOND); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 376 |     return AAUDIO_OK; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 377 | } | 
 | 378 |  | 
| Phil Burk | e4d7bb4 | 2017-03-28 11:32:39 -0700 | [diff] [blame] | 379 | aaudio_result_t AudioStreamInternal::updateStateWhileWaiting() { | 
 | 380 |     if (isDataCallbackActive()) { | 
 | 381 |         return AAUDIO_OK; // state is getting updated by the callback thread read/write call | 
 | 382 |     } | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 383 |     return processCommands(); | 
 | 384 | } | 
 | 385 |  | 
 | 386 | #if LOG_TIMESTAMPS | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 387 | static void AudioStreamInternal_logTimestamp(AAudioServiceMessage &command) { | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 388 |     static int64_t oldPosition = 0; | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 389 |     static int64_t oldTime = 0; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 390 |     int64_t framePosition = command.timestamp.position; | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 391 |     int64_t nanoTime = command.timestamp.timestamp; | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 392 |     ALOGD("AudioStreamInternal() timestamp says framePosition = %08lld at nanoTime %lld", | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 393 |          (long long) framePosition, | 
 | 394 |          (long long) nanoTime); | 
 | 395 |     int64_t nanosDelta = nanoTime - oldTime; | 
 | 396 |     if (nanosDelta > 0 && oldTime > 0) { | 
 | 397 |         int64_t framesDelta = framePosition - oldPosition; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 398 |         int64_t rate = (framesDelta * AAUDIO_NANOS_PER_SECOND) / nanosDelta; | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 399 |         ALOGD("AudioStreamInternal() - framesDelta = %08lld", (long long) framesDelta); | 
 | 400 |         ALOGD("AudioStreamInternal() - nanosDelta = %08lld", (long long) nanosDelta); | 
 | 401 |         ALOGD("AudioStreamInternal() - measured rate = %lld", (long long) rate); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 402 |     } | 
 | 403 |     oldPosition = framePosition; | 
 | 404 |     oldTime = nanoTime; | 
 | 405 | } | 
 | 406 | #endif | 
 | 407 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 408 | aaudio_result_t AudioStreamInternal::onTimestampFromServer(AAudioServiceMessage *message) { | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 409 | #if LOG_TIMESTAMPS | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 410 |     AudioStreamInternal_logTimestamp(*message); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 411 | #endif | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 412 |     processTimestamp(message->timestamp.position, message->timestamp.timestamp); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 413 |     return AAUDIO_OK; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 414 | } | 
 | 415 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 416 | aaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *message) { | 
 | 417 |     aaudio_result_t result = AAUDIO_OK; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 418 |     switch (message->event.event) { | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 419 |         case AAUDIO_SERVICE_EVENT_STARTED: | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 420 |             ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_STARTED"); | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 421 |             if (getState() == AAUDIO_STREAM_STATE_STARTING) { | 
 | 422 |                 setState(AAUDIO_STREAM_STATE_STARTED); | 
 | 423 |             } | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 424 |             break; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 425 |         case AAUDIO_SERVICE_EVENT_PAUSED: | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 426 |             ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_PAUSED"); | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 427 |             if (getState() == AAUDIO_STREAM_STATE_PAUSING) { | 
 | 428 |                 setState(AAUDIO_STREAM_STATE_PAUSED); | 
 | 429 |             } | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 430 |             break; | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 431 |         case AAUDIO_SERVICE_EVENT_STOPPED: | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 432 |             ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_STOPPED"); | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 433 |             if (getState() == AAUDIO_STREAM_STATE_STOPPING) { | 
 | 434 |                 setState(AAUDIO_STREAM_STATE_STOPPED); | 
 | 435 |             } | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 436 |             break; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 437 |         case AAUDIO_SERVICE_EVENT_FLUSHED: | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 438 |             ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_FLUSHED"); | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 439 |             if (getState() == AAUDIO_STREAM_STATE_FLUSHING) { | 
 | 440 |                 setState(AAUDIO_STREAM_STATE_FLUSHED); | 
 | 441 |                 onFlushFromServer(); | 
 | 442 |             } | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 443 |             break; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 444 |         case AAUDIO_SERVICE_EVENT_CLOSED: | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 445 |             ALOGD("processCommands() got AAUDIO_SERVICE_EVENT_CLOSED"); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 446 |             setState(AAUDIO_STREAM_STATE_CLOSED); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 447 |             break; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 448 |         case AAUDIO_SERVICE_EVENT_DISCONNECTED: | 
 | 449 |             result = AAUDIO_ERROR_DISCONNECTED; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 450 |             setState(AAUDIO_STREAM_STATE_DISCONNECTED); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 451 |             ALOGW("WARNING - processCommands() AAUDIO_SERVICE_EVENT_DISCONNECTED"); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 452 |             break; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 453 |         case AAUDIO_SERVICE_EVENT_VOLUME: | 
| Eric Laurent | a2f296e | 2017-06-21 18:51:47 -0700 | [diff] [blame] | 454 |             mStreamVolume = (float)message->event.dataDouble; | 
 | 455 |             doSetVolume(); | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 456 |             ALOGD("processCommands() AAUDIO_SERVICE_EVENT_VOLUME %lf", | 
| Phil Burk | e572f46 | 2017-04-20 13:03:19 -0700 | [diff] [blame] | 457 |                      message->event.dataDouble); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 458 |             break; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 459 |         default: | 
 | 460 |             ALOGW("WARNING - processCommands() Unrecognized event = %d", | 
 | 461 |                  (int) message->event.event); | 
 | 462 |             break; | 
 | 463 |     } | 
 | 464 |     return result; | 
 | 465 | } | 
 | 466 |  | 
 | 467 | // Process all the commands coming from the server. | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 468 | aaudio_result_t AudioStreamInternal::processCommands() { | 
 | 469 |     aaudio_result_t result = AAUDIO_OK; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 470 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 471 |     while (result == AAUDIO_OK) { | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 472 |         //ALOGD("AudioStreamInternal::processCommands() - looping, %d", result); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 473 |         AAudioServiceMessage message; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 474 |         if (mAudioEndpoint.readUpCommand(&message) != 1) { | 
 | 475 |             break; // no command this time, no problem | 
 | 476 |         } | 
 | 477 |         switch (message.what) { | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 478 |         case AAudioServiceMessage::code::TIMESTAMP: | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 479 |             result = onTimestampFromServer(&message); | 
 | 480 |             break; | 
 | 481 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 482 |         case AAudioServiceMessage::code::EVENT: | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 483 |             result = onEventFromServer(&message); | 
 | 484 |             break; | 
 | 485 |  | 
 | 486 |         default: | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 487 |             ALOGE("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d", | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 488 |                  (int) message.what); | 
| Phil Burk | 17fff38 | 2017-05-16 14:06:45 -0700 | [diff] [blame] | 489 |             result = AAUDIO_ERROR_INTERNAL; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 490 |             break; | 
 | 491 |         } | 
 | 492 |     } | 
 | 493 |     return result; | 
 | 494 | } | 
 | 495 |  | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 496 | // Read or write the data, block if needed and timeoutMillis > 0 | 
 | 497 | aaudio_result_t AudioStreamInternal::processData(void *buffer, int32_t numFrames, | 
 | 498 |                                                  int64_t timeoutNanoseconds) | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 499 | { | 
| Phil Burk | 4485d41 | 2017-05-09 15:55:02 -0700 | [diff] [blame] | 500 |     const char * traceName = (mInService) ? "aaWrtS" : "aaWrtC"; | 
 | 501 |     ATRACE_BEGIN(traceName); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 502 |     aaudio_result_t result = AAUDIO_OK; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 503 |     int32_t loopCount = 0; | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 504 |     uint8_t* audioData = (uint8_t*)buffer; | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 505 |     int64_t currentTimeNanos = AudioClock::getNanoseconds(); | 
 | 506 |     int64_t deadlineNanos = currentTimeNanos + timeoutNanoseconds; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 507 |     int32_t framesLeft = numFrames; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 508 |  | 
| Phil Burk | 4485d41 | 2017-05-09 15:55:02 -0700 | [diff] [blame] | 509 |     int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable(); | 
 | 510 |     if (ATRACE_ENABLED()) { | 
 | 511 |         const char * traceName = (mInService) ? "aaFullS" : "aaFullC"; | 
 | 512 |         ATRACE_INT(traceName, fullFrames); | 
 | 513 |     } | 
 | 514 |  | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 515 |     // Loop until all the data has been processed or until a timeout occurs. | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 516 |     while (framesLeft > 0) { | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 517 |         // The call to processDataNow() will not block. It will just read as much as it can. | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 518 |         int64_t wakeTimeNanos = 0; | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 519 |         aaudio_result_t framesProcessed = processDataNow(audioData, framesLeft, | 
 | 520 |                                                   currentTimeNanos, &wakeTimeNanos); | 
 | 521 |         if (framesProcessed < 0) { | 
 | 522 |             ALOGE("AudioStreamInternal::processData() loop: framesProcessed = %d", framesProcessed); | 
 | 523 |             result = framesProcessed; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 524 |             break; | 
 | 525 |         } | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 526 |         framesLeft -= (int32_t) framesProcessed; | 
 | 527 |         audioData += framesProcessed * getBytesPerFrame(); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 528 |  | 
 | 529 |         // Should we block? | 
 | 530 |         if (timeoutNanoseconds == 0) { | 
 | 531 |             break; // don't block | 
 | 532 |         } else if (framesLeft > 0) { | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 533 |             // clip the wake time to something reasonable | 
 | 534 |             if (wakeTimeNanos < currentTimeNanos) { | 
 | 535 |                 wakeTimeNanos = currentTimeNanos; | 
 | 536 |             } | 
 | 537 |             if (wakeTimeNanos > deadlineNanos) { | 
 | 538 |                 // If we time out, just return the framesWritten so far. | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 539 |                 // TODO remove after we fix the deadline bug | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 540 |                 ALOGE("AudioStreamInternal::processData(): timed out after %lld nanos", | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 541 |                       (long long) timeoutNanoseconds); | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 542 |                 ALOGE("AudioStreamInternal::processData(): wakeTime = %lld, deadline = %lld nanos", | 
 | 543 |                       (long long) wakeTimeNanos, (long long) deadlineNanos); | 
 | 544 |                 ALOGE("AudioStreamInternal::processData(): past deadline by %d micros", | 
 | 545 |                       (int)((wakeTimeNanos - deadlineNanos) / AAUDIO_NANOS_PER_MICROSECOND)); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 546 |                 break; | 
 | 547 |             } | 
 | 548 |  | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 549 |             int64_t sleepForNanos = wakeTimeNanos - currentTimeNanos; | 
 | 550 |             AudioClock::sleepForNanos(sleepForNanos); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 551 |             currentTimeNanos = AudioClock::getNanoseconds(); | 
 | 552 |         } | 
 | 553 |     } | 
 | 554 |  | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 555 |     // return error or framesProcessed | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 556 |     (void) loopCount; | 
| Phil Burk | 4485d41 | 2017-05-09 15:55:02 -0700 | [diff] [blame] | 557 |     ATRACE_END(); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 558 |     return (result < 0) ? result : numFrames - framesLeft; | 
 | 559 | } | 
 | 560 |  | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 561 | void AudioStreamInternal::processTimestamp(uint64_t position, int64_t time) { | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 562 |     mClockModel.processTimestamp(position, time); | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 563 | } | 
 | 564 |  | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 565 | aaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) { | 
 | 566 |     int32_t actualFrames = 0; | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 567 |     // Round to the next highest burst size. | 
 | 568 |     if (getFramesPerBurst() > 0) { | 
 | 569 |         int32_t numBursts = (requestedFrames + getFramesPerBurst() - 1) / getFramesPerBurst(); | 
 | 570 |         requestedFrames = numBursts * getFramesPerBurst(); | 
 | 571 |     } | 
 | 572 |  | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 573 |     aaudio_result_t result = mAudioEndpoint.setBufferSizeInFrames(requestedFrames, &actualFrames); | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 574 |     ALOGD("AudioStreamInternal::setBufferSize() req = %d => %d", requestedFrames, actualFrames); | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 575 |     if (result < 0) { | 
 | 576 |         return result; | 
 | 577 |     } else { | 
 | 578 |         return (aaudio_result_t) actualFrames; | 
 | 579 |     } | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 580 | } | 
 | 581 |  | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 582 | int32_t AudioStreamInternal::getBufferSize() const { | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 583 |     return mAudioEndpoint.getBufferSizeInFrames(); | 
 | 584 | } | 
 | 585 |  | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 586 | int32_t AudioStreamInternal::getBufferCapacity() const { | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 587 |     return mAudioEndpoint.getBufferCapacityInFrames(); | 
 | 588 | } | 
 | 589 |  | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 590 | int32_t AudioStreamInternal::getFramesPerBurst() const { | 
 | 591 |     return mEndpointDescriptor.dataQueueDescriptor.framesPerBurst; | 
| Phil Burk | 204a163 | 2017-01-03 17:23:43 -0800 | [diff] [blame] | 592 | } | 
 | 593 |  | 
| Phil Burk | 87c9f64 | 2017-05-17 07:22:39 -0700 | [diff] [blame] | 594 | aaudio_result_t AudioStreamInternal::joinThread(void** returnArg) { | 
 | 595 |     return AudioStream::joinThread(returnArg, calculateReasonableTimeout(getFramesPerBurst())); | 
| Phil Burk | 4c5129b | 2017-04-28 15:17:32 -0700 | [diff] [blame] | 596 | } | 
| Eric Laurent | a2f296e | 2017-06-21 18:51:47 -0700 | [diff] [blame] | 597 |  | 
 | 598 | void AudioStreamInternal::doSetVolume() { | 
 | 599 |     // No pan and only left volume is taken into account from IPLayer interface | 
 | 600 |     mVolumeRamp.setTarget(mStreamVolume * mVolumeMultiplierL /* * mPanMultiplierL */); | 
 | 601 | } | 
 | 602 |  | 
 | 603 |  | 
 | 604 | //------------------------------------------------------------------------------ | 
 | 605 | // Implementation of PlayerBase | 
 | 606 | status_t AudioStreamInternal::playerStart() { | 
 | 607 |     return AAudioConvert_aaudioToAndroidStatus(mServiceInterface.startStream(mServiceStreamHandle)); | 
 | 608 | } | 
 | 609 |  | 
 | 610 | status_t AudioStreamInternal::playerPause() { | 
 | 611 |     return AAudioConvert_aaudioToAndroidStatus(mServiceInterface.pauseStream(mServiceStreamHandle)); | 
 | 612 | } | 
 | 613 |  | 
 | 614 | status_t AudioStreamInternal::playerStop() { | 
 | 615 |     return AAudioConvert_aaudioToAndroidStatus(mServiceInterface.stopStream(mServiceStreamHandle)); | 
 | 616 | } | 
 | 617 |  | 
 | 618 | status_t AudioStreamInternal::playerSetVolume() { | 
 | 619 |     doSetVolume(); | 
 | 620 |     return NO_ERROR; | 
 | 621 | } | 
 | 622 |  | 
 | 623 | void AudioStreamInternal::destroy() { | 
 | 624 |     baseDestroy(); | 
 | 625 | } |