1e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk/*
2e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * Copyright 2017 The Android Open Source Project
3e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk *
4e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * Licensed under the Apache License, Version 2.0 (the "License");
5e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * you may not use this file except in compliance with the License.
6e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * You may obtain a copy of the License at
7e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk *
8e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk *      http://www.apache.org/licenses/LICENSE-2.0
9e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk *
10e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * Unless required by applicable law or agreed to in writing, software
11e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * distributed under the License is distributed on an "AS IS" BASIS,
12e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * See the License for the specific language governing permissions and
14e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * limitations under the License.
15e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk */
16e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
17e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#define LOG_TAG "AudioStreamLegacy"
18e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk//#define LOG_NDEBUG 0
19e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <utils/Log.h>
20e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
21e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <stdint.h>
223d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
233d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk#include <aaudio/AAudio.h>
243d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk#include <audio_utils/primitives.h>
25e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <media/AudioTrack.h>
267328a80ffc83729cc6252c79e0851a31af59c653Phil Burk#include <media/AudioTimestamp.h>
273d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk#include <utils/String16.h>
28e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
29e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "core/AudioStream.h"
30e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamLegacy.h"
31e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
32e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkusing namespace android;
33e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkusing namespace aaudio;
34e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
35e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil BurkAudioStreamLegacy::AudioStreamLegacy()
362d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        : AudioStream()
372d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        , mDeviceCallback(new StreamDeviceCallback(this)) {
38e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk}
39e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
40e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil BurkAudioStreamLegacy::~AudioStreamLegacy() {
41e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk}
42e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
43e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk// Called from AudioTrack.cpp or AudioRecord.cpp
44e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkstatic void AudioStreamLegacy_callback(int event, void* userData, void *info) {
45e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    AudioStreamLegacy *streamLegacy = (AudioStreamLegacy *) userData;
46e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    streamLegacy->processCallback(event, info);
47e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk}
48e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
49e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_legacy_callback_t AudioStreamLegacy::getLegacyCallback() {
50e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    return AudioStreamLegacy_callback;
51e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk}
52e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
533d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burkaaudio_data_callback_result_t AudioStreamLegacy::callDataCallbackFrames(uint8_t *buffer,
543d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                                                                        int32_t numFrames) {
553d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    void *finalAudioData = buffer;
567328a80ffc83729cc6252c79e0851a31af59c653Phil Burk    if (getDirection() == AAUDIO_DIRECTION_INPUT) {
577328a80ffc83729cc6252c79e0851a31af59c653Phil Burk        // Increment before because we already got the data from the device.
587328a80ffc83729cc6252c79e0851a31af59c653Phil Burk        incrementFramesRead(numFrames);
593d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        finalAudioData = (void *) maybeConvertDeviceData(buffer, numFrames);
607328a80ffc83729cc6252c79e0851a31af59c653Phil Burk    }
617328a80ffc83729cc6252c79e0851a31af59c653Phil Burk
62e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    // Call using the AAudio callback interface.
633d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    aaudio_data_callback_result_t callbackResult = maybeCallDataCallback(finalAudioData, numFrames);
647328a80ffc83729cc6252c79e0851a31af59c653Phil Burk
657328a80ffc83729cc6252c79e0851a31af59c653Phil Burk    if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE
667328a80ffc83729cc6252c79e0851a31af59c653Phil Burk            && getDirection() == AAUDIO_DIRECTION_OUTPUT) {
677328a80ffc83729cc6252c79e0851a31af59c653Phil Burk        // Increment after because we are going to write the data to the device.
687328a80ffc83729cc6252c79e0851a31af59c653Phil Burk        incrementFramesWritten(numFrames);
697328a80ffc83729cc6252c79e0851a31af59c653Phil Burk    }
707328a80ffc83729cc6252c79e0851a31af59c653Phil Burk    return callbackResult;
717328a80ffc83729cc6252c79e0851a31af59c653Phil Burk}
727328a80ffc83729cc6252c79e0851a31af59c653Phil Burk
737328a80ffc83729cc6252c79e0851a31af59c653Phil Burk// Implement FixedBlockProcessor
747328a80ffc83729cc6252c79e0851a31af59c653Phil Burkint32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
753d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    int32_t numFrames = numBytes / getBytesPerDeviceFrame();
76134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    return (int32_t) callDataCallbackFrames(buffer, numFrames);
77e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk}
78e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
79e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkvoid AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {
80e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    aaudio_data_callback_result_t callbackResult;
813d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // This illegal size can be used to tell AudioFlinger to stop calling us.
82134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    // This takes advantage of AudioFlinger killing the stream.
833d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // TODO add to API in AudioRecord and AudioTrack
84134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    const size_t SIZE_STOP_CALLBACKS = SIZE_MAX;
85fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent
86e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    switch (opcode) {
87e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        case AAUDIO_CALLBACK_OPERATION_PROCESS_DATA: {
88134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk            (void) checkForDisconnectRequest(true);
892d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk
902d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            // Note that this code assumes an AudioTrack::Buffer is the same as
912d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            // AudioRecord::Buffer
922d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            // TODO define our own AudioBuffer and pass it from the subclasses.
932d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
949e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk            if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
959e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk                ALOGW("processCallbackCommon() data, stream disconnected");
969e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk                audioBuffer->size = SIZE_STOP_CALLBACKS;
979e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk            } else if (!mCallbackEnabled.load()) {
989e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk                ALOGW("processCallbackCommon() stopping because callback disabled");
99134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                audioBuffer->size = SIZE_STOP_CALLBACKS;
1002d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            } else {
1012d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk                if (audioBuffer->frameCount == 0) {
1029e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk                    ALOGW("processCallbackCommon() data, frameCount is zero");
1032d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk                    return;
1042d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk                }
105fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent
106fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent                // If the caller specified an exact size then use a block size adapter.
107fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent                if (mBlockAdapter != nullptr) {
1083d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                    int32_t byteCount = audioBuffer->frameCount * getBytesPerDeviceFrame();
109fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent                    callbackResult = mBlockAdapter->processVariableBlock(
110fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent                            (uint8_t *) audioBuffer->raw, byteCount);
111fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent                } else {
112fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent                    // Call using the AAudio callback interface.
1137328a80ffc83729cc6252c79e0851a31af59c653Phil Burk                    callbackResult = callDataCallbackFrames((uint8_t *)audioBuffer->raw,
1147328a80ffc83729cc6252c79e0851a31af59c653Phil Burk                                                            audioBuffer->frameCount);
115fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent                }
116fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent                if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
1173d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                    audioBuffer->size = audioBuffer->frameCount * getBytesPerDeviceFrame();
118134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                } else { // STOP or invalid result
1199e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk                    ALOGW("%s() callback requested stop, fake an error", __func__);
120134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                    audioBuffer->size = SIZE_STOP_CALLBACKS;
121134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                    // Disable the callback just in case AudioFlinger keeps trying to call us.
122134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk                    mCallbackEnabled.store(false);
123fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent                }
1240befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk
1252d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk                if (updateStateMachine() != AAUDIO_OK) {
1262d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk                    forceDisconnect();
1272d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk                    mCallbackEnabled.store(false);
1280befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk                }
129e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            }
130e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        }
1312d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            break;
132e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
1330befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk        // Stream got rerouted so we disconnect.
1342d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        case AAUDIO_CALLBACK_OPERATION_DISCONNECTED:
135fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            ALOGD("processCallbackCommon() stream disconnected");
1362d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            forceDisconnect();
137e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            mCallbackEnabled.store(false);
138e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
139e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
140e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        default:
141e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
142e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
143e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk}
1445204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk
145134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burkaaudio_result_t AudioStreamLegacy::checkForDisconnectRequest(bool errorCallbackEnabled) {
1462d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk    if (mRequestDisconnect.isRequested()) {
1472d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        ALOGD("checkForDisconnectRequest() mRequestDisconnect acknowledged");
148134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        forceDisconnect(errorCallbackEnabled);
1492d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        mRequestDisconnect.acknowledge();
1502d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        mCallbackEnabled.store(false);
151134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        return AAUDIO_ERROR_DISCONNECTED;
152134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    } else {
153134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        return AAUDIO_OK;
1542d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk    }
1552d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk}
1562d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk
157134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burkvoid AudioStreamLegacy::forceDisconnect(bool errorCallbackEnabled) {
1582d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk    if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
1592d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        setState(AAUDIO_STREAM_STATE_DISCONNECTED);
160134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk        if (errorCallbackEnabled) {
161134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk            maybeCallErrorCallback(AAUDIO_ERROR_DISCONNECTED);
1622d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        }
1632d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk    }
1642d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk}
1652d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk
1665204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burkaaudio_result_t AudioStreamLegacy::getBestTimestamp(clockid_t clockId,
1675204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk                                                   int64_t *framePosition,
1685204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk                                                   int64_t *timeNanoseconds,
1695204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk                                                   ExtendedTimestamp *extendedTimestamp) {
1705204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk    int timebase;
1715204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk    switch (clockId) {
1725204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk        case CLOCK_BOOTTIME:
1735204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk            timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
1745204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk            break;
1755204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk        case CLOCK_MONOTONIC:
1765204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk            timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
1775204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk            break;
1785204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk        default:
1795204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk            ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
18017fff38dd9d467bc5fb6cd5b9a6b183951c7750dPhil Burk            return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
1815204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk            break;
1825204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk    }
1837328a80ffc83729cc6252c79e0851a31af59c653Phil Burk    ExtendedTimestamp::Location location = ExtendedTimestamp::Location::LOCATION_INVALID;
1847328a80ffc83729cc6252c79e0851a31af59c653Phil Burk    int64_t localPosition;
1857328a80ffc83729cc6252c79e0851a31af59c653Phil Burk    status_t status = extendedTimestamp->getBestTimestamp(&localPosition, timeNanoseconds,
1867328a80ffc83729cc6252c79e0851a31af59c653Phil Burk                                                          timebase, &location);
187c0959648b4a3d73212cd16c1f03289eadcbacae0Phil Burk    if (status == OK) {
188c0959648b4a3d73212cd16c1f03289eadcbacae0Phil Burk        // use MonotonicCounter to prevent retrograde motion.
189c0959648b4a3d73212cd16c1f03289eadcbacae0Phil Burk        mTimestampPosition.update32((int32_t) localPosition);
190c0959648b4a3d73212cd16c1f03289eadcbacae0Phil Burk        *framePosition = mTimestampPosition.get();
191c0959648b4a3d73212cd16c1f03289eadcbacae0Phil Burk    }
1927328a80ffc83729cc6252c79e0851a31af59c653Phil Burk
1937328a80ffc83729cc6252c79e0851a31af59c653Phil Burk//    ALOGD("getBestTimestamp() fposition: server = %6lld, kernel = %6lld, location = %d",
1947328a80ffc83729cc6252c79e0851a31af59c653Phil Burk//          (long long) extendedTimestamp->mPosition[ExtendedTimestamp::Location::LOCATION_SERVER],
1957328a80ffc83729cc6252c79e0851a31af59c653Phil Burk//          (long long) extendedTimestamp->mPosition[ExtendedTimestamp::Location::LOCATION_KERNEL],
1967328a80ffc83729cc6252c79e0851a31af59c653Phil Burk//          (int)location);
197c0959648b4a3d73212cd16c1f03289eadcbacae0Phil Burk    return AAudioConvert_androidToAAudioResult(status);
1985204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk}
199fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent
200fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurentvoid AudioStreamLegacy::onAudioDeviceUpdate(audio_port_handle_t deviceId)
201fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent{
202fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    ALOGD("onAudioDeviceUpdate() deviceId %d", (int)deviceId);
203fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
204fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
2052d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        // Note that isDataCallbackActive() is affected by state so call it before DISCONNECTING.
2062d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        // If we have a data callback and the stream is active, then ask the data callback
2072d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        // to DISCONNECT and call the error callback.
2082d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        if (isDataCallbackActive()) {
2092d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            ALOGD("onAudioDeviceUpdate() request DISCONNECT in data callback due to device change");
2102d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            // If the stream is stopped before the data callback has a chance to handle the
2112d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            // request then the requestStop() and requestPause() methods will handle it after
2122d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            // the callback has stopped.
2132d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            mRequestDisconnect.request();
2142d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk        } else {
2152d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            ALOGD("onAudioDeviceUpdate() DISCONNECT the stream now");
2162d5ba532cc80b3408b9eb5d47d3144bf93ece8cdPhil Burk            forceDisconnect();
217fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        }
218fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    }
219fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    setDeviceId(deviceId);
220fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent}
221