| Phil Burk | 2355edb | 2016-12-26 13:54:02 -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 |  | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 17 | #define LOG_TAG "AAudioServiceStreamBase" | 
| Phil Burk | 2355edb | 2016-12-26 13:54:02 -0800 | [diff] [blame] | 18 | //#define LOG_NDEBUG 0 | 
 | 19 | #include <utils/Log.h> | 
 | 20 |  | 
| Phil Burk | a5222e2 | 2017-07-28 13:31:14 -0700 | [diff] [blame] | 21 | #include <iomanip> | 
 | 22 | #include <iostream> | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 23 | #include <mutex> | 
| Phil Burk | 2355edb | 2016-12-26 13:54:02 -0800 | [diff] [blame] | 24 |  | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 25 | #include <media/MediaMetricsItem.h> | 
 | 26 | #include <media/TypeConverter.h> | 
 | 27 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 28 | #include "binding/IAAudioService.h" | 
 | 29 | #include "binding/AAudioServiceMessage.h" | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 30 | #include "core/AudioGlobal.h" | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 31 | #include "utility/AudioClock.h" | 
 | 32 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 33 | #include "AAudioEndpointManager.h" | 
 | 34 | #include "AAudioService.h" | 
 | 35 | #include "AAudioServiceEndpoint.h" | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 36 | #include "AAudioServiceStreamBase.h" | 
 | 37 | #include "TimestampScheduler.h" | 
 | 38 |  | 
 | 39 | using namespace android;  // TODO just import names needed | 
 | 40 | using namespace aaudio;   // TODO just import names needed | 
| Phil Burk | 2355edb | 2016-12-26 13:54:02 -0800 | [diff] [blame] | 41 |  | 
 | 42 | /** | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 43 |  * Base class for streams in the service. | 
 | 44 |  * @return | 
| Phil Burk | 2355edb | 2016-12-26 13:54:02 -0800 | [diff] [blame] | 45 |  */ | 
 | 46 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 47 | AAudioServiceStreamBase::AAudioServiceStreamBase(AAudioService &audioService) | 
| Phil Burk | 2355edb | 2016-12-26 13:54:02 -0800 | [diff] [blame] | 48 |         : mUpMessageQueue(nullptr) | 
| Phil Burk | 5597889 | 2018-01-11 14:56:09 -0800 | [diff] [blame] | 49 |         , mTimestampThread("AATime") | 
| Phil Burk | a53ffa6 | 2018-10-10 16:21:37 -0700 | [diff] [blame] | 50 |         , mAtomicStreamTimestamp() | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 51 |         , mAudioService(audioService) { | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 52 |     mMmapClient.clientUid = -1; | 
 | 53 |     mMmapClient.clientPid = -1; | 
 | 54 |     mMmapClient.packageName = String16(""); | 
| Phil Burk | 2355edb | 2016-12-26 13:54:02 -0800 | [diff] [blame] | 55 | } | 
 | 56 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 57 | AAudioServiceStreamBase::~AAudioServiceStreamBase() { | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 58 |     // May not be set if open failed. | 
 | 59 |     if (mMetricsId.size() > 0) { | 
 | 60 |         mediametrics::LogItem(mMetricsId) | 
 | 61 |                 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR) | 
 | 62 |                 .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState())) | 
 | 63 |                 .record(); | 
 | 64 |     } | 
 | 65 |  | 
| Phil Burk | 5a26e66 | 2017-07-07 12:44:48 -0700 | [diff] [blame] | 66 |     // If the stream is deleted when OPEN or in use then audio resources will leak. | 
 | 67 |     // This would indicate an internal error. So we want to find this ASAP. | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 68 |     LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED | 
 | 69 |                         || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED | 
 | 70 |                         || getState() == AAUDIO_STREAM_STATE_DISCONNECTED), | 
| Phil Burk | 8b4e05e | 2019-12-17 12:12:09 -0800 | [diff] [blame] | 71 |                         "service stream %p still open, state = %d", | 
 | 72 |                         this, getState()); | 
| Phil Burk | 2355edb | 2016-12-26 13:54:02 -0800 | [diff] [blame] | 73 | } | 
 | 74 |  | 
| Phil Burk | a5222e2 | 2017-07-28 13:31:14 -0700 | [diff] [blame] | 75 | std::string AAudioServiceStreamBase::dumpHeader() { | 
| Phil Burk | bbd5286 | 2018-04-13 11:37:42 -0700 | [diff] [blame] | 76 |     return std::string("    T   Handle   UId   Port Run State Format Burst Chan Capacity"); | 
| Phil Burk | a5222e2 | 2017-07-28 13:31:14 -0700 | [diff] [blame] | 77 | } | 
 | 78 |  | 
| Phil Burk | 4501b35 | 2017-06-29 18:12:36 -0700 | [diff] [blame] | 79 | std::string AAudioServiceStreamBase::dump() const { | 
 | 80 |     std::stringstream result; | 
 | 81 |  | 
| Phil Burk | a5222e2 | 2017-07-28 13:31:14 -0700 | [diff] [blame] | 82 |     result << "    0x" << std::setfill('0') << std::setw(8) << std::hex << mHandle | 
 | 83 |            << std::dec << std::setfill(' ') ; | 
 | 84 |     result << std::setw(6) << mMmapClient.clientUid; | 
| Phil Burk | bbd5286 | 2018-04-13 11:37:42 -0700 | [diff] [blame] | 85 |     result << std::setw(7) << mClientHandle; | 
| Phil Burk | a5222e2 | 2017-07-28 13:31:14 -0700 | [diff] [blame] | 86 |     result << std::setw(4) << (isRunning() ? "yes" : " no"); | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 87 |     result << std::setw(6) << getState(); | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 88 |     result << std::setw(7) << getFormat(); | 
| Phil Burk | a5222e2 | 2017-07-28 13:31:14 -0700 | [diff] [blame] | 89 |     result << std::setw(6) << mFramesPerBurst; | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 90 |     result << std::setw(5) << getSamplesPerFrame(); | 
 | 91 |     result << std::setw(9) << getBufferCapacity(); | 
| Phil Burk | 4501b35 | 2017-06-29 18:12:36 -0700 | [diff] [blame] | 92 |  | 
 | 93 |     return result.str(); | 
 | 94 | } | 
 | 95 |  | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 96 | void AAudioServiceStreamBase::logOpen(aaudio_handle_t streamHandle) { | 
 | 97 |     // This is the first log sent from the AAudio Service for a stream. | 
 | 98 |     mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM) | 
 | 99 |             + std::to_string(streamHandle); | 
 | 100 |  | 
 | 101 |     audio_attributes_t attributes = AAudioServiceEndpoint::getAudioAttributesFrom(this); | 
 | 102 |  | 
 | 103 |     // Once this item is logged by the server, the client with the same PID, UID | 
 | 104 |     // can also log properties. | 
 | 105 |     mediametrics::LogItem(mMetricsId) | 
 | 106 |         .setPid(getOwnerProcessId()) | 
 | 107 |         .setUid(getOwnerUserId()) | 
 | 108 |         .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_OPEN) | 
 | 109 |         // the following are immutable | 
 | 110 |         .set(AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, (int32_t)getBufferCapacity()) | 
 | 111 |         .set(AMEDIAMETRICS_PROP_BURSTFRAMES, (int32_t)getFramesPerBurst()) | 
 | 112 |         .set(AMEDIAMETRICS_PROP_CHANNELCOUNT, (int32_t)getSamplesPerFrame()) | 
 | 113 |         .set(AMEDIAMETRICS_PROP_CONTENTTYPE, toString(attributes.content_type).c_str()) | 
 | 114 |         .set(AMEDIAMETRICS_PROP_DIRECTION, | 
 | 115 |                 AudioGlobal_convertDirectionToText(getDirection())) | 
 | 116 |         .set(AMEDIAMETRICS_PROP_ENCODING, toString(getFormat()).c_str()) | 
 | 117 |         .set(AMEDIAMETRICS_PROP_ROUTEDDEVICEID, (int32_t)getDeviceId()) | 
 | 118 |         .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)getSampleRate()) | 
 | 119 |         .set(AMEDIAMETRICS_PROP_SESSIONID, (int32_t)getSessionId()) | 
 | 120 |         .set(AMEDIAMETRICS_PROP_SOURCE, toString(attributes.source).c_str()) | 
 | 121 |         .set(AMEDIAMETRICS_PROP_USAGE, toString(attributes.usage).c_str()) | 
 | 122 |         .record(); | 
 | 123 | } | 
 | 124 |  | 
| Phil Burk | 15f97c9 | 2018-09-04 14:06:27 -0700 | [diff] [blame] | 125 | aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request) { | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 126 |     AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance(); | 
 | 127 |     aaudio_result_t result = AAUDIO_OK; | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 128 |  | 
 | 129 |     mMmapClient.clientUid = request.getUserId(); | 
 | 130 |     mMmapClient.clientPid = request.getProcessId(); | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 131 |     mMmapClient.packageName.setTo(String16("")); // TODO What should we do here? | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 132 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 133 |     // Limit scope of lock to avoid recursive lock in close(). | 
 | 134 |     { | 
 | 135 |         std::lock_guard<std::mutex> lock(mUpMessageQueueLock); | 
 | 136 |         if (mUpMessageQueue != nullptr) { | 
| Phil Burk | 19e990e | 2018-03-22 13:59:34 -0700 | [diff] [blame] | 137 |             ALOGE("%s() called twice", __func__); | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 138 |             return AAUDIO_ERROR_INVALID_STATE; | 
 | 139 |         } | 
 | 140 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 141 |         mUpMessageQueue = new SharedRingBuffer(); | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 142 |         result = mUpMessageQueue->allocate(sizeof(AAudioServiceMessage), | 
 | 143 |                                            QUEUE_UP_CAPACITY_COMMANDS); | 
 | 144 |         if (result != AAUDIO_OK) { | 
 | 145 |             goto error; | 
 | 146 |         } | 
 | 147 |  | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 148 |         // This is not protected by a lock because the stream cannot be | 
 | 149 |         // referenced until the service returns a handle to the client. | 
 | 150 |         // So only one thread can open a stream. | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 151 |         mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService, | 
| Phil Burk | 15f97c9 | 2018-09-04 14:06:27 -0700 | [diff] [blame] | 152 |                                                          request); | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 153 |         if (mServiceEndpoint == nullptr) { | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 154 |             result = AAUDIO_ERROR_UNAVAILABLE; | 
 | 155 |             goto error; | 
 | 156 |         } | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 157 |         // Save a weak pointer that we will use to access the endpoint. | 
 | 158 |         mServiceEndpointWeak = mServiceEndpoint; | 
 | 159 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 160 |         mFramesPerBurst = mServiceEndpoint->getFramesPerBurst(); | 
 | 161 |         copyFrom(*mServiceEndpoint); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 162 |     } | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 163 |     return result; | 
 | 164 |  | 
 | 165 | error: | 
 | 166 |     close(); | 
 | 167 |     return result; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 168 | } | 
| Phil Burk | dec33ab | 2017-01-17 14:48:16 -0800 | [diff] [blame] | 169 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 170 | aaudio_result_t AAudioServiceStreamBase::close() { | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 171 |     if (getState() == AAUDIO_STREAM_STATE_CLOSED) { | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 172 |         return AAUDIO_OK; | 
 | 173 |     } | 
 | 174 |  | 
 | 175 |     stop(); | 
 | 176 |  | 
| Phil Burk | 8b4e05e | 2019-12-17 12:12:09 -0800 | [diff] [blame] | 177 |     aaudio_result_t result = AAUDIO_OK; | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 178 |     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote(); | 
 | 179 |     if (endpoint == nullptr) { | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 180 |         result = AAUDIO_ERROR_INVALID_STATE; | 
 | 181 |     } else { | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 182 |         endpoint->unregisterStream(this); | 
 | 183 |         AAudioEndpointManager &endpointManager = AAudioEndpointManager::getInstance(); | 
 | 184 |         endpointManager.closeEndpoint(endpoint); | 
 | 185 |  | 
 | 186 |         // AAudioService::closeStream() prevents two threads from closing at the same time. | 
 | 187 |         mServiceEndpoint.clear(); // endpoint will hold the pointer until this method returns. | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 188 |     } | 
 | 189 |  | 
 | 190 |     { | 
 | 191 |         std::lock_guard<std::mutex> lock(mUpMessageQueueLock); | 
| Phil Burk | 98d6d92 | 2017-07-06 11:52:45 -0700 | [diff] [blame] | 192 |         stopTimestampThread(); | 
| Phil Burk | 98d6d92 | 2017-07-06 11:52:45 -0700 | [diff] [blame] | 193 |         delete mUpMessageQueue; | 
 | 194 |         mUpMessageQueue = nullptr; | 
| Phil Burk | 98d6d92 | 2017-07-06 11:52:45 -0700 | [diff] [blame] | 195 |     } | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 196 |  | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 197 |     setState(AAUDIO_STREAM_STATE_CLOSED); | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 198 |  | 
 | 199 |     mediametrics::LogItem(mMetricsId) | 
 | 200 |         .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CLOSE) | 
 | 201 |         .record(); | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 202 |     return result; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 203 | } | 
 | 204 |  | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 205 | aaudio_result_t AAudioServiceStreamBase::startDevice() { | 
 | 206 |     mClientHandle = AUDIO_PORT_HANDLE_NONE; | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 207 |     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote(); | 
 | 208 |     if (endpoint == nullptr) { | 
 | 209 |         ALOGE("%s() has no endpoint", __func__); | 
 | 210 |         return AAUDIO_ERROR_INVALID_STATE; | 
 | 211 |     } | 
 | 212 |     return endpoint->startStream(this, &mClientHandle); | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 213 | } | 
 | 214 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 215 | /** | 
 | 216 |  * Start the flow of audio data. | 
 | 217 |  * | 
 | 218 |  * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete. | 
 | 219 |  */ | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 220 | aaudio_result_t AAudioServiceStreamBase::start() { | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 221 |     const int64_t beginNs = AudioClock::getNanoseconds(); | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 222 |     aaudio_result_t result = AAUDIO_OK; | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 223 |  | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 224 |     mediametrics::Defer defer([&] { | 
 | 225 |         mediametrics::LogItem(mMetricsId) | 
 | 226 |             .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START) | 
 | 227 |             .set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(AudioClock::getNanoseconds() - beginNs)) | 
 | 228 |             .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState())) | 
 | 229 |             .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result) | 
 | 230 |             .record(); }); | 
 | 231 |  | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 232 |     if (isRunning()) { | 
 | 233 |         return AAUDIO_OK; | 
 | 234 |     } | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 235 |  | 
| Phil Burk | 2329638 | 2017-11-20 15:45:11 -0800 | [diff] [blame] | 236 |     setFlowing(false); | 
| Phil Burk | 762365c | 2018-12-10 16:02:16 -0800 | [diff] [blame] | 237 |     setSuspended(false); | 
| Phil Burk | 2329638 | 2017-11-20 15:45:11 -0800 | [diff] [blame] | 238 |  | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 239 |     // Start with fresh presentation timestamps. | 
| Phil Burk | a53ffa6 | 2018-10-10 16:21:37 -0700 | [diff] [blame] | 240 |     mAtomicStreamTimestamp.clear(); | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 241 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 242 |     mClientHandle = AUDIO_PORT_HANDLE_NONE; | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 243 |     result = startDevice(); | 
 | 244 |     if (result != AAUDIO_OK) goto error; | 
 | 245 |  | 
 | 246 |     // This should happen at the end of the start. | 
 | 247 |     sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED); | 
 | 248 |     setState(AAUDIO_STREAM_STATE_STARTED); | 
 | 249 |     mThreadEnabled.store(true); | 
 | 250 |     result = mTimestampThread.start(this); | 
 | 251 |     if (result != AAUDIO_OK) goto error; | 
 | 252 |  | 
 | 253 |     return result; | 
 | 254 |  | 
 | 255 | error: | 
 | 256 |     disconnect(); | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 257 |     return result; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 258 | } | 
 | 259 |  | 
 | 260 | aaudio_result_t AAudioServiceStreamBase::pause() { | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 261 |     const int64_t beginNs = AudioClock::getNanoseconds(); | 
| Phil Burk | 11e8d33 | 2017-05-24 09:59:02 -0700 | [diff] [blame] | 262 |     aaudio_result_t result = AAUDIO_OK; | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 263 |     if (!isRunning()) { | 
 | 264 |         return result; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 265 |     } | 
| Phil Burk | 73af62a | 2017-10-26 12:11:47 -0700 | [diff] [blame] | 266 |  | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 267 |     mediametrics::Defer defer([&] { | 
 | 268 |         mediametrics::LogItem(mMetricsId) | 
 | 269 |             .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_PAUSE) | 
 | 270 |             .set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(AudioClock::getNanoseconds() - beginNs)) | 
 | 271 |             .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState())) | 
 | 272 |             .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result) | 
 | 273 |             .record(); }); | 
 | 274 |  | 
| Phil Burk | 73af62a | 2017-10-26 12:11:47 -0700 | [diff] [blame] | 275 |     // Send it now because the timestamp gets rounded up when stopStream() is called below. | 
 | 276 |     // Also we don't need the timestamps while we are shutting down. | 
 | 277 |     sendCurrentTimestamp(); | 
 | 278 |  | 
 | 279 |     result = stopTimestampThread(); | 
 | 280 |     if (result != AAUDIO_OK) { | 
 | 281 |         disconnect(); | 
 | 282 |         return result; | 
 | 283 |     } | 
 | 284 |  | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 285 |     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote(); | 
 | 286 |     if (endpoint == nullptr) { | 
 | 287 |         ALOGE("%s() has no endpoint", __func__); | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 288 |         result =  AAUDIO_ERROR_INVALID_STATE; // for MediaMetric tracking | 
 | 289 |         return result; | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 290 |     } | 
 | 291 |     result = endpoint->stopStream(this, mClientHandle); | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 292 |     if (result != AAUDIO_OK) { | 
| Phil Burk | 19e990e | 2018-03-22 13:59:34 -0700 | [diff] [blame] | 293 |         ALOGE("%s() mServiceEndpoint returned %d, %s", __func__, result, getTypeText()); | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 294 |         disconnect(); // TODO should we return or pause Base first? | 
 | 295 |     } | 
 | 296 |  | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 297 |     sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED); | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 298 |     setState(AAUDIO_STREAM_STATE_PAUSED); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 299 |     return result; | 
 | 300 | } | 
 | 301 |  | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 302 | aaudio_result_t AAudioServiceStreamBase::stop() { | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 303 |     const int64_t beginNs = AudioClock::getNanoseconds(); | 
| Phil Burk | 11e8d33 | 2017-05-24 09:59:02 -0700 | [diff] [blame] | 304 |     aaudio_result_t result = AAUDIO_OK; | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 305 |     if (!isRunning()) { | 
 | 306 |         return result; | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 307 |     } | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 308 |  | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 309 |     mediametrics::Defer defer([&] { | 
 | 310 |         mediametrics::LogItem(mMetricsId) | 
 | 311 |             .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP) | 
 | 312 |             .set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(AudioClock::getNanoseconds() - beginNs)) | 
 | 313 |             .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState())) | 
 | 314 |             .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result) | 
 | 315 |             .record(); }); | 
 | 316 |  | 
| Phil Burk | 83fb844 | 2017-10-05 16:55:17 -0700 | [diff] [blame] | 317 |     setState(AAUDIO_STREAM_STATE_STOPPING); | 
 | 318 |  | 
| Phil Burk | 73af62a | 2017-10-26 12:11:47 -0700 | [diff] [blame] | 319 |     // Send it now because the timestamp gets rounded up when stopStream() is called below. | 
 | 320 |     // Also we don't need the timestamps while we are shutting down. | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 321 |     sendCurrentTimestamp(); // warning - this calls a virtual function | 
 | 322 |     result = stopTimestampThread(); | 
 | 323 |     if (result != AAUDIO_OK) { | 
 | 324 |         disconnect(); | 
 | 325 |         return result; | 
 | 326 |     } | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 327 |  | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 328 |     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote(); | 
 | 329 |     if (endpoint == nullptr) { | 
 | 330 |         ALOGE("%s() has no endpoint", __func__); | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 331 |         result =  AAUDIO_ERROR_INVALID_STATE; // for MediaMetric tracking | 
 | 332 |         return result; | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 333 |     } | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 334 |     // TODO wait for data to be played out | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 335 |     result = endpoint->stopStream(this, mClientHandle); | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 336 |     if (result != AAUDIO_OK) { | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 337 |         ALOGE("%s() stopStream returned %d, %s", __func__, result, getTypeText()); | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 338 |         disconnect(); | 
 | 339 |         // TODO what to do with result here? | 
 | 340 |     } | 
 | 341 |  | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 342 |     sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED); | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 343 |     setState(AAUDIO_STREAM_STATE_STOPPED); | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 344 |     return result; | 
 | 345 | } | 
 | 346 |  | 
| Phil Burk | 98d6d92 | 2017-07-06 11:52:45 -0700 | [diff] [blame] | 347 | aaudio_result_t AAudioServiceStreamBase::stopTimestampThread() { | 
 | 348 |     aaudio_result_t result = AAUDIO_OK; | 
 | 349 |     // clear flag that tells thread to loop | 
 | 350 |     if (mThreadEnabled.exchange(false)) { | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 351 |         result = mTimestampThread.stop(); | 
| Phil Burk | 98d6d92 | 2017-07-06 11:52:45 -0700 | [diff] [blame] | 352 |     } | 
 | 353 |     return result; | 
 | 354 | } | 
 | 355 |  | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 356 | aaudio_result_t AAudioServiceStreamBase::flush() { | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 357 |     const int64_t beginNs = AudioClock::getNanoseconds(); | 
| Phil Burk | 5cc83c3 | 2017-11-28 15:43:18 -0800 | [diff] [blame] | 358 |     aaudio_result_t result = AAudio_isFlushAllowed(getState()); | 
 | 359 |     if (result != AAUDIO_OK) { | 
 | 360 |         return result; | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 361 |     } | 
| Phil Burk | 5cc83c3 | 2017-11-28 15:43:18 -0800 | [diff] [blame] | 362 |  | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 363 |     mediametrics::Defer defer([&] { | 
 | 364 |         mediametrics::LogItem(mMetricsId) | 
 | 365 |             .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_FLUSH) | 
 | 366 |             .set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(AudioClock::getNanoseconds() - beginNs)) | 
 | 367 |             .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState())) | 
 | 368 |             .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result) | 
 | 369 |             .record(); }); | 
 | 370 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 371 |     // Data will get flushed when the client receives the FLUSHED event. | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 372 |     sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED); | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 373 |     setState(AAUDIO_STREAM_STATE_FLUSHED); | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 374 |     return AAUDIO_OK; | 
 | 375 | } | 
 | 376 |  | 
| Phil Burk | cf5f6d2 | 2017-05-26 12:35:07 -0700 | [diff] [blame] | 377 | // implement Runnable, periodically send timestamps to client | 
| Phil Burk | a53ffa6 | 2018-10-10 16:21:37 -0700 | [diff] [blame] | 378 | __attribute__((no_sanitize("integer"))) | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 379 | void AAudioServiceStreamBase::run() { | 
| Phil Burk | 19e990e | 2018-03-22 13:59:34 -0700 | [diff] [blame] | 380 |     ALOGD("%s() %s entering >>>>>>>>>>>>>> TIMESTAMPS", __func__, getTypeText()); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 381 |     TimestampScheduler timestampScheduler; | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 382 |     timestampScheduler.setBurstPeriod(mFramesPerBurst, getSampleRate()); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 383 |     timestampScheduler.start(AudioClock::getNanoseconds()); | 
 | 384 |     int64_t nextTime = timestampScheduler.nextAbsoluteTime(); | 
| Phil Burk | a53ffa6 | 2018-10-10 16:21:37 -0700 | [diff] [blame] | 385 |     int32_t loopCount = 0; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 386 |     while(mThreadEnabled.load()) { | 
| Phil Burk | a53ffa6 | 2018-10-10 16:21:37 -0700 | [diff] [blame] | 387 |         loopCount++; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 388 |         if (AudioClock::getNanoseconds() >= nextTime) { | 
 | 389 |             aaudio_result_t result = sendCurrentTimestamp(); | 
 | 390 |             if (result != AAUDIO_OK) { | 
| Phil Burk | a53ffa6 | 2018-10-10 16:21:37 -0700 | [diff] [blame] | 391 |                 ALOGE("%s() timestamp thread got result = %d", __func__, result); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 392 |                 break; | 
 | 393 |             } | 
 | 394 |             nextTime = timestampScheduler.nextAbsoluteTime(); | 
 | 395 |         } else  { | 
 | 396 |             // Sleep until it is time to send the next timestamp. | 
| Phil Burk | 98d6d92 | 2017-07-06 11:52:45 -0700 | [diff] [blame] | 397 |             // TODO Wait for a signal with a timeout so that we can stop more quickly. | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 398 |             AudioClock::sleepUntilNanoTime(nextTime); | 
 | 399 |         } | 
 | 400 |     } | 
| Phil Burk | a53ffa6 | 2018-10-10 16:21:37 -0700 | [diff] [blame] | 401 |     ALOGD("%s() %s exiting after %d loops <<<<<<<<<<<<<< TIMESTAMPS", | 
 | 402 |           __func__, getTypeText(), loopCount); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 403 | } | 
 | 404 |  | 
| Phil Burk | 5ef003b | 2017-06-30 11:43:37 -0700 | [diff] [blame] | 405 | void AAudioServiceStreamBase::disconnect() { | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 406 |     if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) { | 
| Phil Burk | a987670 | 2020-04-20 18:16:15 -0700 | [diff] [blame] | 407 |         mediametrics::LogItem(mMetricsId) | 
 | 408 |             .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT) | 
 | 409 |             .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState())) | 
 | 410 |             .record(); | 
| Phil Burk | 5ef003b | 2017-06-30 11:43:37 -0700 | [diff] [blame] | 411 |         sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED); | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 412 |         setState(AAUDIO_STREAM_STATE_DISCONNECTED); | 
| Phil Burk | 5ef003b | 2017-06-30 11:43:37 -0700 | [diff] [blame] | 413 |     } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 414 | } | 
 | 415 |  | 
 | 416 | aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event, | 
| Phil Burk | 2329638 | 2017-11-20 15:45:11 -0800 | [diff] [blame] | 417 |                                                           double  dataDouble) { | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 418 |     AAudioServiceMessage command; | 
 | 419 |     command.what = AAudioServiceMessage::code::EVENT; | 
| Phil Burk | 2355edb | 2016-12-26 13:54:02 -0800 | [diff] [blame] | 420 |     command.event.event = event; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 421 |     command.event.dataDouble = dataDouble; | 
| Phil Burk | 2329638 | 2017-11-20 15:45:11 -0800 | [diff] [blame] | 422 |     return writeUpMessageQueue(&command); | 
 | 423 | } | 
 | 424 |  | 
 | 425 | aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event, | 
 | 426 |                                                           int64_t dataLong) { | 
 | 427 |     AAudioServiceMessage command; | 
 | 428 |     command.what = AAudioServiceMessage::code::EVENT; | 
 | 429 |     command.event.event = event; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 430 |     command.event.dataLong = dataLong; | 
 | 431 |     return writeUpMessageQueue(&command); | 
 | 432 | } | 
 | 433 |  | 
| Phil Burk | f878a8d | 2019-03-29 17:23:00 -0700 | [diff] [blame] | 434 | bool AAudioServiceStreamBase::isUpMessageQueueBusy() { | 
 | 435 |     std::lock_guard<std::mutex> lock(mUpMessageQueueLock); | 
 | 436 |     if (mUpMessageQueue == nullptr) { | 
 | 437 |         ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__); | 
 | 438 |         return true; | 
 | 439 |     } | 
 | 440 |     int32_t framesAvailable = mUpMessageQueue->getFifoBuffer() | 
 | 441 |         ->getFullFramesAvailable(); | 
 | 442 |     int32_t capacity = mUpMessageQueue->getFifoBuffer() | 
 | 443 |         ->getBufferCapacityInFrames(); | 
 | 444 |     // Is it half full or more | 
 | 445 |     return framesAvailable >= (capacity / 2); | 
 | 446 | } | 
 | 447 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 448 | aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) { | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 449 |     std::lock_guard<std::mutex> lock(mUpMessageQueueLock); | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 450 |     if (mUpMessageQueue == nullptr) { | 
| Phil Burk | 19e990e | 2018-03-22 13:59:34 -0700 | [diff] [blame] | 451 |         ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__); | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 452 |         return AAUDIO_ERROR_NULL; | 
 | 453 |     } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 454 |     int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1); | 
 | 455 |     if (count != 1) { | 
| Phil Burk | 762365c | 2018-12-10 16:02:16 -0800 | [diff] [blame] | 456 |         ALOGW("%s(): Queue full. Did client stop? Suspending stream. what = %u, %s", | 
 | 457 |               __func__, command->what, getTypeText()); | 
 | 458 |         setSuspended(true); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 459 |         return AAUDIO_ERROR_WOULD_BLOCK; | 
 | 460 |     } else { | 
 | 461 |         return AAUDIO_OK; | 
 | 462 |     } | 
 | 463 | } | 
 | 464 |  | 
| Phil Burk | 2329638 | 2017-11-20 15:45:11 -0800 | [diff] [blame] | 465 | aaudio_result_t AAudioServiceStreamBase::sendXRunCount(int32_t xRunCount) { | 
 | 466 |     return sendServiceEvent(AAUDIO_SERVICE_EVENT_XRUN, (int64_t) xRunCount); | 
 | 467 | } | 
 | 468 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 469 | aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() { | 
 | 470 |     AAudioServiceMessage command; | 
| Phil Burk | f878a8d | 2019-03-29 17:23:00 -0700 | [diff] [blame] | 471 |     // It is not worth filling up the queue with timestamps. | 
 | 472 |     // That can cause the stream to get suspended. | 
 | 473 |     // So just drop the timestamp if the queue is getting full. | 
 | 474 |     if (isUpMessageQueueBusy()) { | 
 | 475 |         return AAUDIO_OK; | 
 | 476 |     } | 
 | 477 |  | 
| Phil Burk | 97350f9 | 2017-07-21 15:59:44 -0700 | [diff] [blame] | 478 |     // Send a timestamp for the clock model. | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 479 |     aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position, | 
 | 480 |                                                     &command.timestamp.timestamp); | 
 | 481 |     if (result == AAUDIO_OK) { | 
| Phil Burk | 19e990e | 2018-03-22 13:59:34 -0700 | [diff] [blame] | 482 |         ALOGV("%s() SERVICE  %8lld at %lld", __func__, | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 483 |               (long long) command.timestamp.position, | 
 | 484 |               (long long) command.timestamp.timestamp); | 
| Phil Burk | 97350f9 | 2017-07-21 15:59:44 -0700 | [diff] [blame] | 485 |         command.what = AAudioServiceMessage::code::TIMESTAMP_SERVICE; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 486 |         result = writeUpMessageQueue(&command); | 
| Phil Burk | 97350f9 | 2017-07-21 15:59:44 -0700 | [diff] [blame] | 487 |  | 
 | 488 |         if (result == AAUDIO_OK) { | 
 | 489 |             // Send a hardware timestamp for presentation time. | 
 | 490 |             result = getHardwareTimestamp(&command.timestamp.position, | 
 | 491 |                                           &command.timestamp.timestamp); | 
 | 492 |             if (result == AAUDIO_OK) { | 
| Phil Burk | 19e990e | 2018-03-22 13:59:34 -0700 | [diff] [blame] | 493 |                 ALOGV("%s() HARDWARE %8lld at %lld", __func__, | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 494 |                       (long long) command.timestamp.position, | 
 | 495 |                       (long long) command.timestamp.timestamp); | 
| Phil Burk | 97350f9 | 2017-07-21 15:59:44 -0700 | [diff] [blame] | 496 |                 command.what = AAudioServiceMessage::code::TIMESTAMP_HARDWARE; | 
 | 497 |                 result = writeUpMessageQueue(&command); | 
 | 498 |             } | 
 | 499 |         } | 
 | 500 |     } | 
 | 501 |  | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 502 |     if (result == AAUDIO_ERROR_UNAVAILABLE) { // TODO review best error code | 
| Phil Burk | 940083c | 2017-07-17 17:00:02 -0700 | [diff] [blame] | 503 |         result = AAUDIO_OK; // just not available yet, try again later | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 504 |     } | 
 | 505 |     return result; | 
| Phil Burk | 2355edb | 2016-12-26 13:54:02 -0800 | [diff] [blame] | 506 | } | 
 | 507 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 508 | /** | 
 | 509 |  * Get an immutable description of the in-memory queues | 
 | 510 |  * used to communicate with the underlying HAL or Service. | 
 | 511 |  */ | 
 | 512 | aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) { | 
| Phil Burk | 523b304 | 2017-09-13 13:03:08 -0700 | [diff] [blame] | 513 |     { | 
 | 514 |         std::lock_guard<std::mutex> lock(mUpMessageQueueLock); | 
 | 515 |         if (mUpMessageQueue == nullptr) { | 
| Phil Burk | 19e990e | 2018-03-22 13:59:34 -0700 | [diff] [blame] | 516 |             ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__); | 
| Phil Burk | 523b304 | 2017-09-13 13:03:08 -0700 | [diff] [blame] | 517 |             return AAUDIO_ERROR_NULL; | 
 | 518 |         } | 
 | 519 |         // Gather information on the message queue. | 
 | 520 |         mUpMessageQueue->fillParcelable(parcelable, | 
 | 521 |                                         parcelable.mUpMessageQueueParcelable); | 
 | 522 |     } | 
 | 523 |     return getAudioDataDescription(parcelable); | 
| Phil Burk | 11e8d33 | 2017-05-24 09:59:02 -0700 | [diff] [blame] | 524 | } | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 525 |  | 
 | 526 | void AAudioServiceStreamBase::onVolumeChanged(float volume) { | 
 | 527 |     sendServiceEvent(AAUDIO_SERVICE_EVENT_VOLUME, volume); | 
 | 528 | } | 
| Phil Burk | 9486252 | 2017-09-13 21:31:36 -0700 | [diff] [blame] | 529 |  | 
| Phil Burk | 2fe718b | 2018-05-14 12:28:32 -0700 | [diff] [blame] | 530 | int32_t AAudioServiceStreamBase::incrementServiceReferenceCount_l() { | 
| Phil Burk | 9486252 | 2017-09-13 21:31:36 -0700 | [diff] [blame] | 531 |     return ++mCallingCount; | 
 | 532 | } | 
 | 533 |  | 
| Phil Burk | 2fe718b | 2018-05-14 12:28:32 -0700 | [diff] [blame] | 534 | int32_t AAudioServiceStreamBase::decrementServiceReferenceCount_l() { | 
 | 535 |     int32_t count = --mCallingCount; | 
 | 536 |     // Each call to increment should be balanced with one call to decrement. | 
 | 537 |     assert(count >= 0); | 
 | 538 |     return count; | 
| Phil Burk | 9486252 | 2017-09-13 21:31:36 -0700 | [diff] [blame] | 539 | } |