此文来自一个小白(Android 8.1)
首先根据log我们可以找到log的打印位置 hardware/interfaces/audiodefault/Stream.cpp
其代码如下
Result Stream::analyzeStatus(const char* funcName, int status,
const std::vector<int>& ignoreErrors) {
if (status != 0 && (ignoreErrors.empty() || !element_in(-status, ignoreErrors))) {
ALOGW("Error from HAL stream in function %s: %s", funcName, strerror(-status));
}
switch (status) {
case 0: return Result::OK;
case -EINVAL: return Result::INVALID_ARGUMENTS;
case -ENODATA: return Result::INVALID_STATE;
case -ENODEV: return Result::NOT_INITIALIZED;
case -ENOSYS: return Result::NOT_SUPPORTED;
default: return Result::INVALID_STATE;
}
}
然后我们继续找,是谁调用了他 StreamOut.cpp
Result StreamOut::getPresentationPositionImpl(audio_stream_out_t* stream,
uint64_t* frames,
TimeSpec* timeStamp) {
// Don't logspam on EINVAL--it's normal for get_presentation_position
// to return it sometimes. EAGAIN may be returned by A2DP audio HAL
// implementation. ENODATA can also be reported while the writer is
// continuously querying it, but the stream has been stopped.
static const std::vector<int> ignoredErrors{EINVAL, EAGAIN, ENODATA};
Result retval(Result::NOT_SUPPORTED);
if (stream->get_presentation_position == NULL) return retval;
struct timespec halTimeStamp;
retval = Stream::analyzeStatus("get_presentation_position",
stream->get_presentation_position(stream, frames, &halTimeStamp),
ignoredErrors);
if (retval == Result::OK) {
timeStamp->tvSec = halTimeStamp.tv_sec;
timeStamp->tvNSec = halTimeStamp.tv_nsec;
}
return retval;
}
在 Stream::analyzeStatus 中传入的 status 便是stream->get_presentation_position(stream, frames, &halTimeStamp)
那 stream->get_presentation_position 这个方法又是在什么地方
继续寻找 你会发现在不同的时候这个方法指向的方法也不同,然额,触发这个log的方法也必然在其中
之后我们会在发现audio_hal.c中有这麽一句话out->stream.get_presentation_position = out_get_presentation_position;
(hardware/libhardware/modules/usbaudio/audio_hal.c)
那,这美滋滋 那之前到status就是 out_get_presentation_position 这个函数的返回值了 其后继续看函数
static int out_get_presentation_position(const struct audio_stream_out *stream,
uint64_t *frames, struct timespec *timestamp)
{
struct stream_out *out = (struct stream_out *)stream; // discard const qualifier
stream_lock(&out->lock);
const alsa_device_proxy *proxy = &out->proxy;
const int ret = proxy_get_presentation_position(proxy, frames, timestamp);
stream_unlock(&out->lock);
return ret;
}
哦 原来是你 proxy_get_presentation_position 继续找
system/media/alsa_utils/alsa_device_proxy.c
int proxy_get_presentation_position(const alsa_device_proxy * proxy,
uint64_t *frames, struct timespec *timestamp)
{
int ret = -EPERM; // -1
unsigned int avail;
if (proxy->pcm != NULL
&& pcm_get_htimestamp(proxy->pcm, &avail, timestamp) == 0) {
const size_t kernel_buffer_size =
proxy->alsa_config.period_size * proxy->alsa_config.period_count;
if (avail > kernel_buffer_size) {
ALOGE("stream available frames(%u) > buffer size(%zu)", avail, kernel_buffer_size);
} else {
int64_t signed_frames = proxy->transferred - kernel_buffer_size + avail;
// It is possible to compensate for additional driver and device delay
// by changing signed_frames. Example:
// signed_frames -= 20 * proxy->alsa_config.rate / 1000;
if (signed_frames >= 0) {
*frames = signed_frames;
ret = 0;
}
}
}
return ret;
}
最终方法找到了 but 我是个小白,而身为大佬的你,一定可以 完美解决