1e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk/*
2e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Copyright 2015 The Android Open Source Project
3e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
4e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Licensed under the Apache License, Version 2.0 (the "License");
5e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * you may not use this file except in compliance with the License.
6e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * You may obtain a copy of the License at
7e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
8e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *      http://www.apache.org/licenses/LICENSE-2.0
9e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
10e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Unless required by applicable law or agreed to in writing, software
11e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * distributed under the License is distributed on an "AS IS" BASIS,
12e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * See the License for the specific language governing permissions and
14e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * limitations under the License.
15e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk */
16e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
17965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk#define LOG_TAG "AAudioStream"
18e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk//#define LOG_NDEBUG 0
19e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/Log.h>
20e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
21d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk#include <atomic>
22e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <stdint.h>
235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include <aaudio/AAudio.h>
24e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
25e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include "AudioStreamBuilder.h"
26e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include "AudioStream.h"
27e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include "AudioClock.h"
28e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio;
30e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
31e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil BurkAudioStream::AudioStream()
32965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk        : mPlayerBase(new MyPlayerBase(this))
33e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk{
34d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    // mThread is a pthread_t of unknown size so we need memset.
35d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    memset(&mThread, 0, sizeof(mThread));
36d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    setPeriodNanoseconds(0);
37e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
38e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
39965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil BurkAudioStream::~AudioStream() {
40965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk    ALOGD("destroying %p, state = %s", this, AAudio_convertStreamStateToText(getState()));
41965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk    // If the stream is deleted when OPEN or in use then audio resources will leak.
42965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk    // This would indicate an internal error. So we want to find this ASAP.
43965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk    LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
44965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk                          || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED
45965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk                          || getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
46134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                        "~AudioStream() - still in use, state = %s",
47965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk                        AAudio_convertStreamStateToText(getState()));
488a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk
498a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk    mPlayerBase->clearParentReference(); // remove reference to this AudioStream
50965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk}
51965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk
52ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burkstatic const char *AudioStream_convertSharingModeToShortText(aaudio_sharing_mode_t sharingMode) {
53ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk    const char *result;
54ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk    switch (sharingMode) {
55ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk        case AAUDIO_SHARING_MODE_EXCLUSIVE:
56ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk            result = "EX";
57ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk            break;
58ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk        case AAUDIO_SHARING_MODE_SHARED:
59ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk            result = "SH";
60ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk            break;
61ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk        default:
62ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk            result = "?!";
63ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk            break;
64ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk    }
65ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk    return result;
66ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk}
67ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk
685ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
69e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
703401bcdd98c5a43a14701a0e7299a2318c6863c9Phil Burk    // Call here as well because the AAudioService will call this without calling build().
713401bcdd98c5a43a14701a0e7299a2318c6863c9Phil Burk    aaudio_result_t result = builder.validate();
723401bcdd98c5a43a14701a0e7299a2318c6863c9Phil Burk    if (result != AAUDIO_OK) {
733401bcdd98c5a43a14701a0e7299a2318c6863c9Phil Burk        return result;
743401bcdd98c5a43a14701a0e7299a2318c6863c9Phil Burk    }
753401bcdd98c5a43a14701a0e7299a2318c6863c9Phil Burk
76e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Copy parameters from the Builder because the Builder may be deleted after this call.
77d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    // TODO AudioStream should be a subclass of AudioStreamParameters
78e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mSamplesPerFrame = builder.getSamplesPerFrame();
79e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mSampleRate = builder.getSampleRate();
80e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mDeviceId = builder.getDeviceId();
81e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mFormat = builder.getFormat();
82c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    mSharingMode = builder.getSharingMode();
8371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk    mSharingModeMatchRequired = builder.isSharingModeMatchRequired();
84e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk    mPerformanceMode = builder.getPerformanceMode();
85e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk
86d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    mUsage = builder.getUsage();
87d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    if (mUsage == AAUDIO_UNSPECIFIED) {
88d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk        mUsage = AAUDIO_USAGE_MEDIA;
89d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    }
90d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    mContentType = builder.getContentType();
91d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    if (mContentType == AAUDIO_UNSPECIFIED) {
92d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk        mContentType = AAUDIO_CONTENT_TYPE_MUSIC;
93d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    }
94d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    mInputPreset = builder.getInputPreset();
95d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    if (mInputPreset == AAUDIO_UNSPECIFIED) {
96eaef9b9c7b3c6c4d4435ce5e32e9fe952a2f69fePhil Burk        mInputPreset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
97d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    }
98d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk
99e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    // callbacks
100e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    mFramesPerDataCallback = builder.getFramesPerDataCallback();
101e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    mDataCallbackProc = builder.getDataCallbackProc();
102e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    mErrorCallbackProc = builder.getErrorCallbackProc();
103e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    mDataCallbackUserData = builder.getDataCallbackUserData();
104098b883a7dc89b65b72c6d3f1d38c6afd477a0adPhil Burk    mErrorCallbackUserData = builder.getErrorCallbackUserData();
105e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
106cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    // This is very helpful for debugging in the future. Please leave it in.
10719e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk    ALOGI("open() rate   = %d, channels    = %d, format   = %d, sharing = %s, dir = %s",
108ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk          mSampleRate, mSamplesPerFrame, mFormat,
109ec89b2e2f8c84a7d3936db1a888034f4a4b0df16Phil Burk          AudioStream_convertSharingModeToShortText(mSharingMode),
110cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk          (getDirection() == AAUDIO_DIRECTION_OUTPUT) ? "OUTPUT" : "INPUT");
11119e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk    ALOGI("open() device = %d, sessionId   = %d, perfMode = %d, callback: %s with frames = %d",
1124e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk          mDeviceId,
1134e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk          mSessionId,
1144e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk          mPerformanceMode,
115134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk          (isDataCallbackSet() ? "ON" : "OFF"),
116fd34a9310659aa53e9e10d6826651577a75f6447Phil Burk          mFramesPerDataCallback);
11719e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk    ALOGI("open() usage  = %d, contentType = %d, inputPreset = %d",
118a62fb9565d73d9ec9b56da65929afc0f686c696ePhil Burk          mUsage, mContentType, mInputPreset);
119e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk
1205ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
121e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
122e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
123134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burkaaudio_result_t AudioStream::safeStart() {
124134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    std::lock_guard<std::mutex> lock(mStreamLock);
125134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    if (collidesWithCallback()) {
126134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        ALOGE("%s cannot be called from a callback!", __func__);
127134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
128134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    }
129134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    return requestStart();
130134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk}
131134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk
132134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burkaaudio_result_t AudioStream::safePause() {
1335cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk    if (!isPauseSupported()) {
1345cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        return AAUDIO_ERROR_UNIMPLEMENTED;
1355cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk    }
1365cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
137134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    std::lock_guard<std::mutex> lock(mStreamLock);
138134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    if (collidesWithCallback()) {
139134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        ALOGE("%s cannot be called from a callback!", __func__);
140134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
141134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    }
1425cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
1435cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk    switch (getState()) {
1445cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        // Proceed with pausing.
1455cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_STARTING:
1465cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_STARTED:
1475cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_DISCONNECTED:
1485cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            break;
1495cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
1505cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            // Transition from one inactive state to another.
1515cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_OPEN:
1525cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_STOPPED:
1535cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_FLUSHED:
1545cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            setState(AAUDIO_STREAM_STATE_PAUSED);
1555cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            return AAUDIO_OK;
1565cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
1575cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            // Redundant?
1585cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_PAUSING:
1595cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_PAUSED:
1605cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            return AAUDIO_OK;
1615cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
1625cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            // Don't interfere with transitional states or when closed.
1635cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_STOPPING:
1645cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_FLUSHING:
1655cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_CLOSING:
1665cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_CLOSED:
1675cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        default:
1685cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            ALOGW("safePause() stream not running, state = %s",
1695cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk                  AAudio_convertStreamStateToText(getState()));
1705cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            return AAUDIO_ERROR_INVALID_STATE;
1715cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk    }
1725cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
173134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    return requestPause();
174134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk}
175134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk
176134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burkaaudio_result_t AudioStream::safeFlush() {
1775cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk    if (!isFlushSupported()) {
1785cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        ALOGE("flush not supported for this stream");
1795cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        return AAUDIO_ERROR_UNIMPLEMENTED;
1805cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk    }
1815cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
182134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    std::lock_guard<std::mutex> lock(mStreamLock);
183134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    if (collidesWithCallback()) {
1845cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        ALOGE("stream cannot be flushed from a callback!");
185134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
186134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    }
1875cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
1885cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk    aaudio_result_t result = AAudio_isFlushAllowed(getState());
1895cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk    if (result != AAUDIO_OK) {
1905cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        return result;
1915cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk    }
1925cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
193134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    return requestFlush();
194134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk}
195134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk
196134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burkaaudio_result_t AudioStream::safeStop() {
197134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    std::lock_guard<std::mutex> lock(mStreamLock);
198134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    if (collidesWithCallback()) {
1995cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        ALOGE("stream cannot be stopped from a callback!");
200134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
201134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    }
2025cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
2035cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk    switch (getState()) {
2045cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        // Proceed with stopping.
2055cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_STARTING:
2065cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_STARTED:
2075cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_DISCONNECTED:
2085cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            break;
2095cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
2105cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        // Transition from one inactive state to another.
2115cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_OPEN:
2125cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_PAUSED:
2135cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_FLUSHED:
2145cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            setState(AAUDIO_STREAM_STATE_STOPPED);
2155cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            return AAUDIO_OK;
2165cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
2175cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        // Redundant?
2185cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_STOPPING:
2195cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_STOPPED:
2205cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            return AAUDIO_OK;
2215cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
2225cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        // Don't interfere with transitional states or when closed.
2235cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_PAUSING:
2245cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_FLUSHING:
2255cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_CLOSING:
2265cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        case AAUDIO_STREAM_STATE_CLOSED:
2275cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        default:
2285cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            ALOGW("requestStop() stream not running, state = %s",
2295cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk                  AAudio_convertStreamStateToText(getState()));
2305cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk            return AAUDIO_ERROR_INVALID_STATE;
2315cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk    }
2325cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk
233134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    return requestStop();
234134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk}
235134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk
236134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burkaaudio_result_t AudioStream::safeClose() {
237134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    std::lock_guard<std::mutex> lock(mStreamLock);
238134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    if (collidesWithCallback()) {
239134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        ALOGE("%s cannot be called from a callback!", __func__);
240134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
241134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    }
242134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    return close();
243134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk}
244e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
24519e990e480245af25ec03ff3a3f53b820b0732cdPhil Burkvoid AudioStream::setState(aaudio_stream_state_t state) {
24619e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk    ALOGV("%s(%p) from %d to %d", __func__, this, mState, state);
24719e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk    // CLOSED is a final state
24819e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk    if (mState == AAUDIO_STREAM_STATE_CLOSED) {
24919e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk        ALOGE("%s(%p) tried to set to %d but already CLOSED", __func__, this, state);
25019e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk
25119e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk    // Once DISCONNECTED, we can only move to CLOSED state.
25219e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk    } else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
25319e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk               && state != AAUDIO_STREAM_STATE_CLOSED) {
25419e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk        ALOGE("%s(%p) tried to set to %d but already DISCONNECTED", __func__, this, state);
25519e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk
25619e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk    } else {
25719e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk        mState = state;
25819e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk    }
25919e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk}
26019e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk
2615ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStream::waitForStateChange(aaudio_stream_state_t currentState,
2625ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk                                                aaudio_stream_state_t *nextState,
2633316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk                                                int64_t timeoutNanoseconds)
264e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
2650befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk    aaudio_result_t result = updateStateMachine();
266e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (result != AAUDIO_OK) {
267e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        return result;
268e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
269e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
270e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    int64_t durationNanos = 20 * AAUDIO_NANOS_PER_MILLISECOND; // arbitrary
2715ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_stream_state_t state = getState();
272e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    while (state == currentState && timeoutNanoseconds > 0) {
273e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        if (durationNanos > timeoutNanoseconds) {
274e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            durationNanos = timeoutNanoseconds;
275e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
276e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        AudioClock::sleepForNanos(durationNanos);
277e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        timeoutNanoseconds -= durationNanos;
278e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2790befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk        aaudio_result_t result = updateStateMachine();
2805ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        if (result != AAUDIO_OK) {
281e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            return result;
282e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
283e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
284e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        state = getState();
285e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
286d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (nextState != nullptr) {
287e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        *nextState = state;
288e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
2895ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return (state == currentState) ? AAUDIO_ERROR_TIMEOUT : AAUDIO_OK;
290e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
291e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
29271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk// This registers the callback thread with the server before
293d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk// passing control to the app. This gives the server an opportunity to boost
294d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk// the thread's performance characteristics.
295d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burkvoid* AudioStream::wrapUserThread() {
296d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    void* procResult = nullptr;
297d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    mThreadRegistrationResult = registerThread();
2985ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (mThreadRegistrationResult == AAUDIO_OK) {
29971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk        // Run callback loop. This may take a very long time.
300d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk        procResult = mThreadProc(mThreadArg);
301d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk        mThreadRegistrationResult = unregisterThread();
302d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    }
303d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    return procResult;
304d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk}
305d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk
306d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk// This is the entry point for the new thread created by createThread().
307d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk// It converts the 'C' function call to a C++ method call.
308d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burkstatic void* AudioStream_internalThreadProc(void* threadArg) {
309d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    AudioStream *audioStream = (AudioStream *) threadArg;
310d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    return audioStream->wrapUserThread();
311d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk}
312d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk
3135204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk// This is not exposed in the API.
3145204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk// But it is still used internally to implement callbacks for MMAP mode.
3153316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStream::createThread(int64_t periodNanoseconds,
316e2155ef0ec6742db7a3128c4ef4fb96e02828d1bPhil Burk                                     aaudio_audio_thread_proc_t threadProc,
317d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk                                     void* threadArg)
318e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
319e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (mHasThread) {
320fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk        ALOGE("createThread() - mHasThread already true");
3215ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
322e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
323d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (threadProc == nullptr) {
3245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_NULL;
325e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
326d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    // Pass input parameters to the background thread.
327d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    mThreadProc = threadProc;
328d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    mThreadArg = threadArg;
329d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    setPeriodNanoseconds(periodNanoseconds);
330d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    int err = pthread_create(&mThread, nullptr, AudioStream_internalThreadProc, this);
331e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (err != 0) {
33219e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk        android::status_t status = -errno;
33319e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk        ALOGE("createThread() - pthread_create() failed, %d", status);
33419e990e480245af25ec03ff3a3f53b820b0732cdPhil Burk        return AAudioConvert_androidToAAudioResult(status);
335e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    } else {
3365cc83c3b8acc43b760be23a4e3b96fbbb06d8e93Phil Burk        // TODO Use AAudioThread or maybe AndroidThread
337559788963268a0bc1e90e29c423ac78938c96b4aPhil Burk        // Name the thread with an increasing index, "AAudio_#", for debugging.
338559788963268a0bc1e90e29c423ac78938c96b4aPhil Burk        static std::atomic<uint32_t> nextThreadIndex{1};
339559788963268a0bc1e90e29c423ac78938c96b4aPhil Burk        char name[16]; // max length for a pthread_name
340559788963268a0bc1e90e29c423ac78938c96b4aPhil Burk        uint32_t index = nextThreadIndex++;
341559788963268a0bc1e90e29c423ac78938c96b4aPhil Burk        // Wrap the index so that we do not hit the 16 char limit
342559788963268a0bc1e90e29c423ac78938c96b4aPhil Burk        // and to avoid hard-to-read large numbers.
343559788963268a0bc1e90e29c423ac78938c96b4aPhil Burk        index = index % 100000;  // arbitrary
344559788963268a0bc1e90e29c423ac78938c96b4aPhil Burk        snprintf(name, sizeof(name), "AAudio_%u", index);
345559788963268a0bc1e90e29c423ac78938c96b4aPhil Burk        err = pthread_setname_np(mThread, name);
346559788963268a0bc1e90e29c423ac78938c96b4aPhil Burk        ALOGW_IF((err != 0), "Could not set name of AAudio thread. err = %d", err);
347559788963268a0bc1e90e29c423ac78938c96b4aPhil Burk
348e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        mHasThread = true;
3495ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_OK;
350e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
351e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
352e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3533316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanoseconds)
354e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
355e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (!mHasThread) {
356fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk        ALOGE("joinThread() - but has no thread");
3575ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
358e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
359e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#if 0
360e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO implement equivalent of pthread_timedjoin_np()
361e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    struct timespec abstime;
362e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    int err = pthread_timedjoin_np(mThread, returnArg, &abstime);
363e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#else
364e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    int err = pthread_join(mThread, returnArg);
365e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#endif
366e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mHasThread = false;
3675204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk    return err ? AAudioConvert_androidToAAudioResult(-errno) : mThreadRegistrationResult;
368e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
369e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
370134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burkaaudio_data_callback_result_t AudioStream::maybeCallDataCallback(void *audioData,
371134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                                                                 int32_t numFrames) {
372134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    aaudio_data_callback_result_t result = AAUDIO_CALLBACK_RESULT_STOP;
373134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    AAudioStream_dataCallback dataCallback = getDataCallbackProc();
374134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    if (dataCallback != nullptr) {
375134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        // Store thread ID of caller to detect stop() and close() calls from callback.
376134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        pid_t expected = CALLBACK_THREAD_NONE;
377134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        if (mDataCallbackThread.compare_exchange_strong(expected, gettid())) {
378134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk            result = (*dataCallback)(
379134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                    (AAudioStream *) this,
380134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                    getDataCallbackUserData(),
381134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                    audioData,
382134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                    numFrames);
383134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk            mDataCallbackThread.store(CALLBACK_THREAD_NONE);
384134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        } else {
385134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk            ALOGW("%s() data callback already running!", __func__);
386134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        }
387134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    }
388134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    return result;
389134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk}
390134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk
391134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burkvoid AudioStream::maybeCallErrorCallback(aaudio_result_t result) {
392134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    AAudioStream_errorCallback errorCallback = getErrorCallbackProc();
393134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    if (errorCallback != nullptr) {
394134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        // Store thread ID of caller to detect stop() and close() calls from callback.
395134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        pid_t expected = CALLBACK_THREAD_NONE;
396134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        if (mErrorCallbackThread.compare_exchange_strong(expected, gettid())) {
397134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk            (*errorCallback)(
398134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                    (AAudioStream *) this,
399134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                    getErrorCallbackUserData(),
400134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                    result);
401134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk            mErrorCallbackThread.store(CALLBACK_THREAD_NONE);
402134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        } else {
403134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk            ALOGW("%s() error callback already running!", __func__);
404134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        }
405134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    }
406134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk}
407134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk
408134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk// Is this running on the same thread as a callback?
409134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk// Note: This cannot be implemented using a thread_local because that would
410134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk// require using a thread_local variable that is shared between streams.
411134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk// So a thread_local variable would prevent stopping or closing stream A from
412134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk// a callback on stream B, which is currently legal and not so terrible.
413134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burkbool AudioStream::collidesWithCallback() const {
414134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    pid_t thisThread = gettid();
415134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    // Compare the current thread ID with the thread ID of the callback
416134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    // threads to see it they match. If so then this code is being
417134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    // called from one of the stream callback functions.
418134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    return ((mErrorCallbackThread.load() == thisThread)
419134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk            || (mDataCallbackThread.load() == thisThread));
420134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk}
421134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk
4228a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk#if AAUDIO_USE_VOLUME_SHAPER
4238a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burkandroid::media::VolumeShaper::Status AudioStream::applyVolumeShaper(
4248a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk        const android::media::VolumeShaper::Configuration& configuration __unused,
4258a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk        const android::media::VolumeShaper::Operation& operation __unused) {
4268a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk    ALOGW("applyVolumeShaper() is not supported");
4278a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk    return android::media::VolumeShaper::Status::ok();
4288a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk}
4298a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk#endif
4308a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk
43155e5eabf96af5a2964bfab1e64d81ad9be9ac975Phil Burkvoid AudioStream::setDuckAndMuteVolume(float duckAndMuteVolume) {
43255e5eabf96af5a2964bfab1e64d81ad9be9ac975Phil Burk    ALOGD("%s() to %f", __func__, duckAndMuteVolume);
43355e5eabf96af5a2964bfab1e64d81ad9be9ac975Phil Burk    mDuckAndMuteVolume = duckAndMuteVolume;
43455e5eabf96af5a2964bfab1e64d81ad9be9ac975Phil Burk    doSetVolume(); // apply this change
43555e5eabf96af5a2964bfab1e64d81ad9be9ac975Phil Burk}
43655e5eabf96af5a2964bfab1e64d81ad9be9ac975Phil Burk
4378a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil BurkAudioStream::MyPlayerBase::MyPlayerBase(AudioStream *parent) : mParent(parent) {
4388a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk}
4398a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk
4408a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil BurkAudioStream::MyPlayerBase::~MyPlayerBase() {
4418a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk    ALOGV("MyPlayerBase::~MyPlayerBase(%p) deleted", this);
4428a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk}
4438a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk
4448a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burkvoid AudioStream::MyPlayerBase::registerWithAudioManager() {
4458a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk    if (!mRegistered) {
4468a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk        init(android::PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA);
4478a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk        mRegistered = true;
4488a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk    }
4498a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk}
4508a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk
4518a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burkvoid AudioStream::MyPlayerBase::unregisterWithAudioManager() {
4528a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk    if (mRegistered) {
4538a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk        baseDestroy();
4548a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk        mRegistered = false;
4558a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk    }
4568a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk}
4578a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk
4588a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burkvoid AudioStream::MyPlayerBase::destroy() {
4598a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk    unregisterWithAudioManager();
4608a8a9e5d91c8cc110b9916982f4c5242efca33e3Phil Burk}
461