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