summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-07-21 23:18:36 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-07-21 23:18:36 +0000
commit023eecfd282996acf5e80d301e7f774099f4bd19 (patch)
tree83a24dbe99f2c56b0df8df7e5e33644782488edd
parent60b8eb03a8a3f1581e07469704406def013ea5ca (diff)
parentdd91871ac120b17874af7a24b1e7e7d825c48175 (diff)
downloaddevice_generic_goldfish-023eecfd282996acf5e80d301e7f774099f4bd19.tar.gz
device_generic_goldfish-023eecfd282996acf5e80d301e7f774099f4bd19.tar.bz2
device_generic_goldfish-023eecfd282996acf5e80d301e7f774099f4bd19.zip
Snap for 6698269 from dd91871ac120b17874af7a24b1e7e7d825c48175 to mainline-releaseandroid-mainline-11.0.0_r2
Change-Id: I56c0fa8d7deb11dc15eb3918a3df7f599b29cbe5
-rw-r--r--audio/Android.bp18
-rw-r--r--audio/android.hardware.audio.service.ranchu.rc9
-rw-r--r--audio/debug.h30
-rw-r--r--audio/device_factory.cpp42
-rw-r--r--audio/device_factory.h14
-rw-r--r--audio/device_port_sink.cpp158
-rw-r--r--audio/device_port_sink.h46
-rw-r--r--audio/device_port_source.cpp281
-rw-r--r--audio/device_port_source.h46
-rw-r--r--audio/entry.cpp35
-rw-r--r--audio/io_thread.cpp11
-rw-r--r--audio/policy/audio_policy_configuration.xml3
-rw-r--r--audio/policy/primary_audio_policy_configuration.xml32
-rw-r--r--audio/primary_device.cpp132
-rw-r--r--audio/primary_device.h14
-rw-r--r--audio/stream_common.cpp9
-rw-r--r--audio/stream_in.cpp104
-rw-r--r--audio/stream_in.h11
-rw-r--r--audio/stream_out.cpp164
-rw-r--r--audio/stream_out.h16
-rw-r--r--audio/talsa.cpp5
-rw-r--r--audio/util.cpp40
-rw-r--r--audio/util.h10
-rw-r--r--camera/media_codecs.xml10
-rw-r--r--camera/media_codecs_google_video_default.xml113
-rw-r--r--data/etc/advancedFeatures.ini1
-rw-r--r--data/etc/config.ini.xl4
-rw-r--r--data/etc/google/user/advancedFeatures.ini1
-rw-r--r--data/etc/google/userdebug/advancedFeatures.ini1
-rw-r--r--emulator-info.txt2
-rw-r--r--init.ranchu.rc3
-rw-r--r--sepolicy/common/file_contexts1
-rw-r--r--vendor.mk28
33 files changed, 1031 insertions, 363 deletions
diff --git a/audio/Android.bp b/audio/Android.bp
index 4905fe57..27dfbf8e 100644
--- a/audio/Android.bp
+++ b/audio/Android.bp
@@ -13,9 +13,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library_shared {
- name: "android.hardware.audio@6.0-impl.ranchu",
+cc_binary {
+ name: "android.hardware.audio.service.ranchu",
vendor: true,
+ init_rc: ["android.hardware.audio.service.ranchu.rc"],
vintf_fragments: ["android.hardware.audio@6.0-impl.ranchu.xml"],
relative_install_path: "hw",
defaults: ["hidl_defaults"],
@@ -27,6 +28,8 @@ cc_library_shared {
"stream_in.cpp",
"stream_out.cpp",
"io_thread.cpp",
+ "device_port_source.cpp",
+ "device_port_sink.cpp",
"talsa.cpp",
"util.cpp",
],
@@ -34,7 +37,9 @@ cc_library_shared {
"android.hardware.audio@6.0",
"android.hardware.audio.common@6.0",
"android.hardware.audio.common@6.0-util",
+ "libaudioutils",
"libbase",
+ "libbinder",
"libcutils",
"libhidlbase",
"liblog",
@@ -47,6 +52,13 @@ cc_library_shared {
"libaudio_system_headers",
],
cflags: [
- "-DLOG_TAG=\"android.hardware.audio@6.0-impl.ranchu\"",
+ "-DLOG_TAG=\"android.hardware.audio.service.ranchu\"",
+ ],
+ // android.hardware.audio.service.ranchu loads android.hardware.audio@6.0-impl
+ // which loads audio.r_submix.default which provides the r_submix device,
+ // see b/161485545. Should be retired once a better r_submix is available.
+ required: [
+ "android.hardware.audio@6.0-impl",
+ "audio.r_submix.default",
],
}
diff --git a/audio/android.hardware.audio.service.ranchu.rc b/audio/android.hardware.audio.service.ranchu.rc
new file mode 100644
index 00000000..777c2297
--- /dev/null
+++ b/audio/android.hardware.audio.service.ranchu.rc
@@ -0,0 +1,9 @@
+service vendor.audio-hal /vendor/bin/hw/android.hardware.audio.service.ranchu
+ class hal
+ user audioserver
+ # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
+ group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
+ capabilities BLOCK_SUSPEND
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh HighPerformance
+ onrestart restart audioserver
diff --git a/audio/debug.h b/audio/debug.h
new file mode 100644
index 00000000..60d884ae
--- /dev/null
+++ b/audio/debug.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#if 1
+
+#include <log/log.h>
+
+#define FAILURE(x) \
+ (ALOGE("%s:%s:%d failure: %s", __FILE__, __func__, __LINE__, #x), x)
+
+#else
+
+#define FAILURE(x) x
+
+#endif
diff --git a/audio/device_factory.cpp b/audio/device_factory.cpp
index e0bbf1f5..32a9a04a 100644
--- a/audio/device_factory.cpp
+++ b/audio/device_factory.cpp
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#include "device_factory.h"
-#include "primary_device.h"
#include <system/audio.h>
#include <log/log.h>
+#include "device_factory.h"
+#include "primary_device.h"
+#include "debug.h"
namespace android {
namespace hardware {
@@ -27,23 +28,34 @@ namespace implementation {
using ::android::hardware::Void;
-Return<void> DevicesFactory::openDevice(const hidl_string& device,
- openDevice_cb _hidl_cb) {
- Result result = Result::OK;
- std::unique_ptr<IDevice> dev;
+#ifdef __LP64__
+#define LIB_PATH_PREFIX "vendor/lib64/hw/"
+#else
+#define LIB_PATH_PREFIX "vendor/lib/hw/"
+#endif
- if (device == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
- dev = std::make_unique<PrimaryDevice>();
- } else {
- result = Result::INVALID_ARGUMENTS;
- }
+DevicesFactory::DevicesFactory() {
+ mLegacyLib.reset(dlopen(
+ LIB_PATH_PREFIX "android.hardware.audio@6.0-impl.so", RTLD_NOW));
+ LOG_ALWAYS_FATAL_IF(!mLegacyLib);
+
+ typedef IDevicesFactory *(*Func)(const char *);
+ const auto func = reinterpret_cast<Func>(
+ dlsym(mLegacyLib.get(), "HIDL_FETCH_IDevicesFactory"));
+ LOG_ALWAYS_FATAL_IF(!func);
+
+ mLegacyFactory.reset((*func)("default"));
+ LOG_ALWAYS_FATAL_IF(!mLegacyFactory);
+}
- if (!dev) {
- ALOGE("DevicesFactory::%s:%d: failed, device='%s' result='%s'",
- __func__, __LINE__, device.c_str(), toString(result).c_str());
+Return<void> DevicesFactory::openDevice(const hidl_string& device,
+ openDevice_cb _hidl_cb) {
+ if (device == AUDIO_HARDWARE_MODULE_ID_PRIMARY)
+ _hidl_cb(Result::OK, new PrimaryDevice);
+ else {
+ mLegacyFactory->openDevice(device, _hidl_cb);
}
- _hidl_cb(result, dev.release());
return Void();
}
diff --git a/audio/device_factory.h b/audio/device_factory.h
index ac653d0d..cc33be5a 100644
--- a/audio/device_factory.h
+++ b/audio/device_factory.h
@@ -15,7 +15,9 @@
*/
#pragma once
+#include <memory>
#include <android/hardware/audio/6.0/IDevicesFactory.h>
+#include <dlfcn.h>
namespace android {
namespace hardware {
@@ -29,8 +31,20 @@ using ::android::hardware::Return;
using namespace ::android::hardware::audio::V6_0;
struct DevicesFactory : public IDevicesFactory {
+ DevicesFactory();
+
Return<void> openDevice(const hidl_string& device, openDevice_cb _hidl_cb) override;
Return<void> openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override;
+
+private:
+ struct DLDeleter {
+ void operator()(void* dl) const {
+ ::dlclose(dl);
+ }
+ };
+
+ std::unique_ptr<void, DLDeleter> mLegacyLib;
+ std::unique_ptr<IDevicesFactory> mLegacyFactory;
};
} // namespace implementation
diff --git a/audio/device_port_sink.cpp b/audio/device_port_sink.cpp
new file mode 100644
index 00000000..0a34eb21
--- /dev/null
+++ b/audio/device_port_sink.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <log/log.h>
+#include <utils/Timers.h>
+#include "device_port_sink.h"
+#include "talsa.h"
+#include "util.h"
+#include "debug.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V6_0 {
+namespace implementation {
+
+namespace {
+
+struct TinyalsaSink : public DevicePortSink {
+ TinyalsaSink(unsigned pcmCard, unsigned pcmDevice,
+ const AudioConfig &cfg, uint64_t &frames)
+ : mFrames(frames)
+ , mPcm(talsa::pcmOpen(pcmCard, pcmDevice,
+ util::countChannels(cfg.channelMask),
+ cfg.sampleRateHz,
+ cfg.frameCount,
+ true /* isOut */)) {}
+
+ Result getPresentationPosition(uint64_t &frames, TimeSpec &ts) override {
+ frames = mFrames;
+ ts = util::nsecs2TimeSpec(systemTime(SYSTEM_TIME_MONOTONIC));
+ return Result::OK;
+ }
+
+ int write(const void *data, size_t nBytes) override {
+ const int res = ::pcm_write(mPcm.get(), data, nBytes);
+ if (res < 0) {
+ return FAILURE(res);
+ } else if (res == 0) {
+ mFrames += ::pcm_bytes_to_frames(mPcm.get(), nBytes);
+ return nBytes;
+ } else {
+ mFrames += ::pcm_bytes_to_frames(mPcm.get(), res);
+ return res;
+ }
+ }
+
+ static std::unique_ptr<TinyalsaSink> create(unsigned pcmCard,
+ unsigned pcmDevice,
+ const AudioConfig &cfg,
+ uint64_t &frames) {
+ auto src = std::make_unique<TinyalsaSink>(pcmCard, pcmDevice, cfg, frames);
+ if (src->mPcm) {
+ return src;
+ } else {
+ return FAILURE(nullptr);
+ }
+ }
+
+private:
+ uint64_t &mFrames;
+ talsa::PcmPtr mPcm;
+};
+
+struct NullSink : public DevicePortSink {
+ NullSink(const AudioConfig &cfg, uint64_t &frames)
+ : mFrames(frames)
+ , mSampleRateHz(cfg.sampleRateHz)
+ , mNChannels(util::countChannels(cfg.channelMask))
+ , mTimestamp(systemTime(SYSTEM_TIME_MONOTONIC)) {}
+
+ Result getPresentationPosition(uint64_t &frames, TimeSpec &ts) override {
+ simulatePresentationPosition();
+ frames = mFrames;
+ ts = util::nsecs2TimeSpec(mTimestamp);
+ return Result::OK;
+ }
+
+ int write(const void *, size_t nBytes) override {
+ simulatePresentationPosition();
+ mAvailableFrames += nBytes / mNChannels / sizeof(int16_t);
+ return nBytes;
+ }
+
+ void simulatePresentationPosition() {
+ const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+ const nsecs_t deltaNs = nowNs - mTimestamp;
+ const uint64_t deltaFrames = uint64_t(mSampleRateHz) * ns2ms(deltaNs) / 1000;
+ const uint64_t f = std::min(deltaFrames, mAvailableFrames);
+
+ mFrames += f;
+ mAvailableFrames -= f;
+ if (mAvailableFrames) {
+ mTimestamp += us2ns(f * 1000000 / mSampleRateHz);
+ } else {
+ mTimestamp = nowNs;
+ }
+ }
+
+ static std::unique_ptr<NullSink> create(const AudioConfig &cfg,
+ uint64_t &frames) {
+ return std::make_unique<NullSink>(cfg, frames);
+ }
+
+private:
+ uint64_t &mFrames;
+ const unsigned mSampleRateHz;
+ const unsigned mNChannels;
+ uint64_t mAvailableFrames = 0;
+ nsecs_t mTimestamp;
+};
+
+} // namespace
+
+std::unique_ptr<DevicePortSink>
+DevicePortSink::create(const DeviceAddress &address,
+ const AudioConfig &cfg,
+ const hidl_bitfield<AudioOutputFlag> &flags,
+ uint64_t &frames) {
+ (void)flags;
+
+ if (cfg.format != AudioFormat::PCM_16_BIT) {
+ ALOGE("%s:%d Only PCM_16_BIT is supported", __func__, __LINE__);
+ return FAILURE(nullptr);
+ }
+
+ switch (address.device) {
+ case AudioDevice::OUT_SPEAKER:
+ return TinyalsaSink::create(talsa::kPcmCard, talsa::kPcmDevice,
+ cfg, frames);
+
+ case AudioDevice::OUT_TELEPHONY_TX:
+ return NullSink::create(cfg, frames);
+
+ default:
+ ALOGE("%s:%d unsupported device: %x", __func__, __LINE__, address.device);
+ return FAILURE(nullptr);
+ }
+}
+
+} // namespace implementation
+} // namespace V6_0
+} // namespace audio
+} // namespace hardware
+} // namespace android
diff --git a/audio/device_port_sink.h b/audio/device_port_sink.h
new file mode 100644
index 00000000..5714cd06
--- /dev/null
+++ b/audio/device_port_sink.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <memory>
+#include <android/hardware/audio/common/6.0/types.h>
+#include <android/hardware/audio/6.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V6_0 {
+namespace implementation {
+
+using namespace ::android::hardware::audio::common::V6_0;
+using namespace ::android::hardware::audio::V6_0;
+
+struct DevicePortSink {
+ virtual ~DevicePortSink() {}
+ virtual Result getPresentationPosition(uint64_t &frames, TimeSpec &ts) = 0;
+ virtual int write(const void *data, size_t nBytes) = 0;
+
+ static std::unique_ptr<DevicePortSink> create(const DeviceAddress &,
+ const AudioConfig &,
+ const hidl_bitfield<AudioOutputFlag> &,
+ uint64_t &frames);
+};
+
+} // namespace implementation
+} // namespace V6_0
+} // namespace audio
+} // namespace hardware
+} // namespace android
diff --git a/audio/device_port_source.cpp b/audio/device_port_source.cpp
new file mode 100644
index 00000000..a82d281f
--- /dev/null
+++ b/audio/device_port_source.cpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cmath>
+#include <chrono>
+#include <thread>
+#include <audio_utils/channels.h>
+#include <audio_utils/format.h>
+#include <log/log.h>
+#include <utils/Timers.h>
+#include "device_port_source.h"
+#include "talsa.h"
+#include "util.h"
+#include "debug.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V6_0 {
+namespace implementation {
+
+namespace {
+
+struct TinyalsaSource : public DevicePortSource {
+ TinyalsaSource(unsigned pcmCard, unsigned pcmDevice,
+ const AudioConfig &cfg, uint64_t &frames)
+ : mFrames(frames)
+ , mPcm(talsa::pcmOpen(pcmCard, pcmDevice,
+ util::countChannels(cfg.channelMask),
+ cfg.sampleRateHz,
+ cfg.frameCount,
+ false /* isOut */)) {}
+
+ Result getCapturePosition(uint64_t &frames, uint64_t &time) override {
+ frames = mFrames;
+ time = systemTime(SYSTEM_TIME_MONOTONIC);
+ return Result::OK;
+ }
+
+ int read(void *data, size_t toReadBytes) override {
+ const int res = ::pcm_read(mPcm.get(), data, toReadBytes);
+ if (res < 0) {
+ return FAILURE(res);
+ } else if (res == 0) {
+ mFrames += ::pcm_bytes_to_frames(mPcm.get(), toReadBytes);
+ return toReadBytes;
+ } else {
+ mFrames += ::pcm_bytes_to_frames(mPcm.get(), res);
+ return res;
+ }
+ }
+
+ static std::unique_ptr<TinyalsaSource> create(unsigned pcmCard,
+ unsigned pcmDevice,
+ const AudioConfig &cfg,
+ uint64_t &frames) {
+ auto src = std::make_unique<TinyalsaSource>(pcmCard, pcmDevice, cfg, frames);
+ if (src->mPcm) {
+ return src;
+ } else {
+ return FAILURE(nullptr);
+ }
+ }
+
+private:
+ uint64_t &mFrames;
+ talsa::PcmPtr mPcm;
+};
+
+template <class G> struct GeneratedSource : public DevicePortSource {
+ GeneratedSource(const AudioConfig &cfg, uint64_t &frames, G generator)
+ : mFrames(frames)
+ , mStartNs(systemTime(SYSTEM_TIME_MONOTONIC))
+ , mSampleRateHz(cfg.sampleRateHz)
+ , mNChannels(util::countChannels(cfg.channelMask))
+ , mGenerator(std::move(generator)) {}
+
+ Result getCapturePosition(uint64_t &frames, uint64_t &time) override {
+ const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+ const uint64_t nowFrames = getNowFrames(nowNs);
+ mFrames += (nowFrames - mPreviousFrames);
+ mPreviousFrames = nowFrames;
+ frames = mFrames;
+ time = nowNs;
+ return Result::OK;
+ }
+
+ uint64_t getNowFrames(const nsecs_t nowNs) const {
+ return uint64_t(mSampleRateHz) * ns2ms(nowNs - mStartNs) / 1000;
+ }
+
+ int read(void *data, size_t toReadBytes) override {
+ int16_t *samples = static_cast<int16_t *>(data);
+ const unsigned nChannels = mNChannels;
+ const unsigned requestedFrames = toReadBytes / nChannels / sizeof(*samples);
+
+ unsigned availableFrames;
+ while (true) {
+ const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+ availableFrames = getNowFrames(nowNs) - mSentFrames;
+ if (availableFrames < requestedFrames / 2) {
+ const unsigned neededMoreFrames = requestedFrames / 2 - availableFrames;
+
+ using namespace std::chrono_literals;
+ std::this_thread::sleep_for(1s * neededMoreFrames / mSampleRateHz);
+ } else {
+ break;
+ }
+ }
+
+ const unsigned nFrames = std::min(requestedFrames, availableFrames);
+ mGenerator(samples, nFrames);
+ const size_t sizeBytes = nFrames * nChannels * sizeof(*samples);
+ if (nChannels > 1) {
+ adjust_channels(samples, 1, samples, nChannels,
+ sizeof(*samples), sizeBytes);
+ }
+
+ mSentFrames += nFrames;
+ return sizeBytes;
+ }
+
+private:
+ uint64_t &mFrames;
+ const nsecs_t mStartNs;
+ const unsigned mSampleRateHz;
+ const unsigned mNChannels;
+ uint64_t mPreviousFrames = 0;
+ uint64_t mSentFrames = 0;
+ G mGenerator;
+};
+
+std::vector<int16_t> convertFloatsToInt16(const std::vector<float> &pcmFloat) {
+ std::vector<int16_t> pcmI16(pcmFloat.size());
+
+ memcpy_by_audio_format(pcmI16.data(), AUDIO_FORMAT_PCM_16_BIT,
+ pcmFloat.data(), AUDIO_FORMAT_PCM_FLOAT,
+ pcmFloat.size());
+
+ return pcmI16;
+}
+
+// https://en.wikipedia.org/wiki/Busy_signal
+struct BusySignalGenerator {
+ explicit BusySignalGenerator(const uint32_t sampleRateHz) : mSampleRateHz(sampleRateHz) {
+ // 24/480 = 31/620, mValues must contain 50ms of audio samples
+ const size_t sz = sampleRateHz / 20;
+ std::vector<float> pcm(sz);
+ for (unsigned i = 0; i < sz; ++i) {
+ const double a = double(i) * M_PI * 2 / sampleRateHz;
+ pcm[i] = .5 * (sin(480 * a) + sin(620 * a));
+ }
+ mValues = convertFloatsToInt16(pcm);
+ }
+
+ void operator()(int16_t* s, size_t n) {
+ const unsigned rate = mSampleRateHz;
+ const unsigned rateHalf = rate / 2;
+ const int16_t *const vals = mValues.data();
+ const size_t valsSz = mValues.size();
+ size_t i = mI;
+
+ while (n > 0) {
+ size_t len;
+ if (i < rateHalf) {
+ const size_t valsOff = i % valsSz;
+ len = std::min(n, std::min(rateHalf - i, valsSz - valsOff));
+ memcpy(s, vals + valsOff, len * sizeof(*s));
+ } else {
+ len = std::min(n, rate - i);
+ memset(s, 0, len * sizeof(*s));
+ }
+ s += len;
+ i = (i + len) % rate;
+ n -= len;
+ }
+
+ mI = i;
+ }
+
+private:
+ const unsigned mSampleRateHz;
+ std::vector<int16_t> mValues;
+ size_t mI = 0;
+};
+
+struct RepeatGenerator {
+ explicit RepeatGenerator(const std::vector<float> &pcm)
+ : mValues(convertFloatsToInt16(pcm)) {}
+
+ void operator()(int16_t* s, size_t n) {
+ const int16_t *const vals = mValues.data();
+ const size_t valsSz = mValues.size();
+ size_t i = mI;
+
+ while (n > 0) {
+ const size_t len = std::min(n, valsSz - i);
+ memcpy(s, vals + i, len * sizeof(*s));
+ s += len;
+ i = (i + len) % valsSz;
+ n -= len;
+ }
+
+ mI = i;
+ }
+
+private:
+ const std::vector<int16_t> mValues;
+ size_t mI = 0;
+};
+
+std::vector<float> generateSinePattern(uint32_t sampleRateHz,
+ double freq,
+ double amp) {
+ std::vector<float> result(3 * sampleRateHz / freq + .5);
+
+ for (size_t i = 0; i < result.size(); ++i) {
+ const double a = double(i) * M_PI * 2 / sampleRateHz;
+ result[i] = amp * sin(a * freq);
+ }
+
+ return result;
+}
+
+template <class G> std::unique_ptr<GeneratedSource<G>>
+createGeneratedSource(const AudioConfig &cfg, uint64_t &frames, G generator) {
+ return std::make_unique<GeneratedSource<G>>(cfg, frames, std::move(generator));
+}
+
+} // namespace
+
+std::unique_ptr<DevicePortSource>
+DevicePortSource::create(const DeviceAddress &address,
+ const AudioConfig &cfg,
+ const hidl_bitfield<AudioOutputFlag> &flags,
+ uint64_t &frames) {
+ (void)flags;
+
+ if (cfg.format != AudioFormat::PCM_16_BIT) {
+ ALOGE("%s:%d Only PCM_16_BIT is supported", __func__, __LINE__);
+ return FAILURE(nullptr);
+ }
+
+ switch (address.device) {
+ case AudioDevice::IN_BUILTIN_MIC:
+ return TinyalsaSource::create(talsa::kPcmCard, talsa::kPcmDevice,
+ cfg, frames);
+
+ case AudioDevice::IN_TELEPHONY_RX:
+ return createGeneratedSource(cfg, frames,
+ BusySignalGenerator(cfg.sampleRateHz));
+
+ case AudioDevice::IN_FM_TUNER:
+ return createGeneratedSource(
+ cfg, frames,
+ RepeatGenerator(generateSinePattern(cfg.sampleRateHz, 440.0, 1.0)));
+
+ default:
+ ALOGE("%s:%d unsupported device: %x", __func__, __LINE__, address.device);
+ return FAILURE(nullptr);
+ }
+}
+
+} // namespace implementation
+} // namespace V6_0
+} // namespace audio
+} // namespace hardware
+} // namespace android
diff --git a/audio/device_port_source.h b/audio/device_port_source.h
new file mode 100644
index 00000000..3cc39ffe
--- /dev/null
+++ b/audio/device_port_source.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <memory>
+#include <android/hardware/audio/common/6.0/types.h>
+#include <android/hardware/audio/6.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V6_0 {
+namespace implementation {
+
+using namespace ::android::hardware::audio::common::V6_0;
+using namespace ::android::hardware::audio::V6_0;
+
+struct DevicePortSource {
+ virtual ~DevicePortSource() {}
+ virtual Result getCapturePosition(uint64_t &frames, uint64_t &time) = 0;
+ virtual int read(void *data, size_t nBytes) = 0;
+
+ static std::unique_ptr<DevicePortSource> create(const DeviceAddress &,
+ const AudioConfig &,
+ const hidl_bitfield<AudioOutputFlag> &,
+ uint64_t &frames);
+};
+
+} // namespace implementation
+} // namespace V6_0
+} // namespace audio
+} // namespace hardware
+} // namespace android
diff --git a/audio/entry.cpp b/audio/entry.cpp
index 1d48f432..7cbeb6d1 100644
--- a/audio/entry.cpp
+++ b/audio/entry.cpp
@@ -14,12 +14,37 @@
* limitations under the License.
*/
+#include <binder/ProcessState.h>
+#include <hwbinder/ProcessState.h>
+#include <hidl/LegacySupport.h>
#include "device_factory.h"
-using android::hardware::audio::V6_0::IDevicesFactory;
-using android::hardware::audio::V6_0::implementation::DevicesFactory;
+int main(int, char**) {
+ using ::android::sp;
+ using ::android::OK;
+ using ::android::hardware::audio::V6_0::IDevicesFactory;
+ using ::android::hardware::audio::V6_0::implementation::DevicesFactory;
+ using ::android::hardware::registerPassthroughServiceImplementation;
-extern "C" IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name) {
- (void)name;
- return new DevicesFactory();
+ ::android::ProcessState::initWithDriver("/dev/vndbinder");
+ ::android::ProcessState::self()->startThreadPool();
+ ::android::hardware::configureRpcThreadpool(16, true /* callerWillJoin */);
+
+ sp<IDevicesFactory> factory(new DevicesFactory());
+ if (factory->registerAsService() != ::android::NO_ERROR) {
+ return -EINVAL;
+ }
+
+ if (registerPassthroughServiceImplementation(
+ "android.hardware.audio.effect@6.0::IEffectsFactory") != OK) {
+ return -EINVAL;
+ }
+
+ if (registerPassthroughServiceImplementation(
+ "android.hardware.soundtrigger@2.2::ISoundTriggerHw") != OK) {
+ return -EINVAL;
+ }
+
+ ::android::hardware::joinRpcThreadpool();
+ return 0;
}
diff --git a/audio/io_thread.cpp b/audio/io_thread.cpp
index 81982b36..b87c5e4c 100644
--- a/audio/io_thread.cpp
+++ b/audio/io_thread.cpp
@@ -15,6 +15,7 @@
*/
#include "io_thread.h"
+#include "debug.h"
namespace android {
namespace hardware {
@@ -24,7 +25,15 @@ namespace implementation {
bool IOThread::notify(const uint32_t mask) {
EventFlag *evf = getEventFlag();
- return evf ? (NO_ERROR == evf->wake(mask)) : false;
+ if (evf) {
+ if (NO_ERROR == evf->wake(mask)) {
+ return true;
+ } else {
+ return FAILURE(false);
+ }
+ } else {
+ return FAILURE(false);
+ }
}
bool IOThread::standby() {
diff --git a/audio/policy/audio_policy_configuration.xml b/audio/policy/audio_policy_configuration.xml
index f631bb0d..34e8aff5 100644
--- a/audio/policy/audio_policy_configuration.xml
+++ b/audio/policy/audio_policy_configuration.xml
@@ -24,6 +24,9 @@
<!-- Primary Audio HAL -->
<xi:include href="primary_audio_policy_configuration.xml"/>
+ <!-- Remote Submix Audio HAL -->
+ <xi:include href="r_submix_audio_policy_configuration.xml"/>
+
</modules>
<!-- End of Modules section -->
diff --git a/audio/policy/primary_audio_policy_configuration.xml b/audio/policy/primary_audio_policy_configuration.xml
index f9ac2c3c..33a47d7f 100644
--- a/audio/policy/primary_audio_policy_configuration.xml
+++ b/audio/policy/primary_audio_policy_configuration.xml
@@ -4,6 +4,9 @@
<attachedDevices>
<item>Speaker</item>
<item>Built-In Mic</item>
+ <item>Telephony Tx</item>
+ <item>Telephony Rx</item>
+ <item>FM Tuner</item>
</attachedDevices>
<defaultOutputDevice>Speaker</defaultOutputDevice>
<mixPorts>
@@ -15,18 +18,47 @@
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="44100" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
</mixPort>
+
+ <mixPort name="telephony_tx" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="telephony_rx" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+
+ <mixPort name="fm_tuner" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
</mixPorts>
<devicePorts>
<devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
</devicePort>
+ <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">
+ </devicePort>
<devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
</devicePort>
+ <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">
+ </devicePort>
+
+ <devicePort tagName="FM Tuner" type="AUDIO_DEVICE_IN_FM_TUNER" role="source">
+ </devicePort>
</devicePorts>
<routes>
<route type="mix" sink="Speaker"
sources="primary output"/>
<route type="mix" sink="primary input"
sources="Built-In Mic"/>
+
+ <route type="mix" sink="telephony_rx"
+ sources="Telephony Rx"/>
+ <route type="mix" sink="Telephony Tx"
+ sources="telephony_tx"/>
+
+ <route type="mix" sink="fm_tuner"
+ sources="FM Tuner"/>
</routes>
</module>
diff --git a/audio/primary_device.cpp b/audio/primary_device.cpp
index 838a1557..9f39d088 100644
--- a/audio/primary_device.cpp
+++ b/audio/primary_device.cpp
@@ -20,6 +20,7 @@
#include "stream_in.h"
#include "stream_out.h"
#include "util.h"
+#include "debug.h"
namespace android {
namespace hardware {
@@ -28,7 +29,7 @@ namespace V6_0 {
namespace implementation {
constexpr size_t kInBufferDurationMs = 15;
-constexpr size_t kOutBufferDurationMs = 15;
+constexpr size_t kOutBufferDurationMs = 22;
using ::android::hardware::Void;
@@ -48,28 +49,28 @@ PrimaryDevice::PrimaryDevice()
}
Return<Result> PrimaryDevice::initCheck() {
- return mMixer ? Result::OK : Result::NOT_INITIALIZED;
+ return mMixer ? Result::OK : FAILURE(Result::NOT_INITIALIZED);
}
Return<Result> PrimaryDevice::setMasterVolume(float volume) {
- if (volume < 0 || volume > 1.0) {
- return Result::INVALID_ARGUMENTS;
+ if (isnan(volume) || volume < 0 || volume > 1.0) {
+ return FAILURE(Result::INVALID_ARGUMENTS);
}
if (!mMixerMasterVolumeCtl) {
- return Result::INVALID_STATE;
+ return FAILURE(Result::INVALID_STATE);
}
talsa::mixerSetPercentAll(mMixerMasterVolumeCtl, int(100 * volume));
+ mMasterVolume = volume;
return Result::OK;
}
Return<void> PrimaryDevice::getMasterVolume(getMasterVolume_cb _hidl_cb) {
if (mMixerMasterVolumeCtl) {
- _hidl_cb(Result::OK,
- mixer_ctl_get_percent(mMixerMasterVolumeCtl, 0) / 100.0);
+ _hidl_cb(Result::OK, mMasterVolume);
} else {
- _hidl_cb(Result::INVALID_STATE, 0);
+ _hidl_cb(FAILURE(Result::INVALID_STATE), 0);
}
return Void();
@@ -80,7 +81,7 @@ Return<Result> PrimaryDevice::PrimaryDevice::setMicMute(bool mute) {
talsa::mixerSetValueAll(mMixerCaptureSwitchCtl, mute ? 0 : 1);
return Result::OK;
} else {
- return Result::INVALID_STATE;
+ return FAILURE(Result::INVALID_STATE);
}
}
@@ -89,7 +90,7 @@ Return<void> PrimaryDevice::getMicMute(getMicMute_cb _hidl_cb) {
const int value = mixer_ctl_get_value(mMixerCaptureSwitchCtl, 0);
_hidl_cb(Result::OK, value == 0);
} else {
- _hidl_cb(Result::INVALID_STATE, 0);
+ _hidl_cb(FAILURE(Result::INVALID_STATE), 0);
}
return Void();
}
@@ -99,7 +100,7 @@ Return<Result> PrimaryDevice::setMasterMute(bool mute) {
talsa::mixerSetValueAll(mMixerMasterPaybackSwitchCtl, mute ? 0 : 1);
return Result::OK;
} else {
- return Result::INVALID_STATE;
+ return FAILURE(Result::INVALID_STATE);
}
}
@@ -108,7 +109,7 @@ Return<void> PrimaryDevice::getMasterMute(getMasterMute_cb _hidl_cb) {
const int value = mixer_ctl_get_value(mMixerMasterPaybackSwitchCtl, 0);
_hidl_cb(Result::OK, value == 0);
} else {
- _hidl_cb(Result::NOT_SUPPORTED, 0);
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), 0);
}
return Void();
@@ -126,7 +127,7 @@ Return<void> PrimaryDevice::getInputBufferSize(const AudioConfig& config,
_hidl_cb(Result::OK, sz);
} else {
ALOGE("PrimaryDevice::%s:%d failed", __func__, __LINE__);
- _hidl_cb(Result::INVALID_ARGUMENTS, 0);
+ _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), 0);
}
return Void();
@@ -147,7 +148,7 @@ Return<void> PrimaryDevice::openOutputStream(int32_t ioHandle,
config);
} else {
ALOGE("PrimaryDevice::%s:%d failed", __func__, __LINE__);
- _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, suggestedConfig);
+ _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), nullptr, suggestedConfig);
}
return Void();
@@ -168,49 +169,76 @@ Return<void> PrimaryDevice::openInputStream(int32_t ioHandle,
config);
} else {
ALOGE("PrimaryDevice::%s:%d failed", __func__, __LINE__);
- _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, suggestedConfig);
+ _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), nullptr, suggestedConfig);
}
return Void();
}
Return<bool> PrimaryDevice::supportsAudioPatches() {
- return false;
+ return true;
}
Return<void> PrimaryDevice::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
createAudioPatch_cb _hidl_cb) {
- (void)sources;
- (void)sinks;
- _hidl_cb(Result::NOT_SUPPORTED, 0);
+ if (sources.size() == 1 && sinks.size() == 1) {
+ AudioPatch patch;
+ patch.source = sources[0];
+ patch.sink = sinks[0];
+
+ AudioPatchHandle handle;
+ while (true) {
+ handle = mNextAudioPatchHandle;
+ mNextAudioPatchHandle = std::max(handle + 1, 0);
+ if (mAudioPatches.insert({handle, patch}).second) {
+ break;
+ }
+ }
+
+ _hidl_cb(Result::OK, handle);
+ } else {
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), 0);
+ }
+
return Void();
}
-Return<void> PrimaryDevice::updateAudioPatch(int32_t previousPatch,
+Return<void> PrimaryDevice::updateAudioPatch(AudioPatchHandle previousPatchHandle,
const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
updateAudioPatch_cb _hidl_cb) {
- (void)previousPatch;
- (void)sources;
- (void)sinks;
- _hidl_cb(Result::NOT_SUPPORTED, 0);
+ const auto i = mAudioPatches.find(previousPatchHandle);
+ if (i == mAudioPatches.end()) {
+ _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), previousPatchHandle);
+ } else {
+ if (sources.size() == 1 && sinks.size() == 1) {
+ AudioPatch patch;
+ patch.source = sources[0];
+ patch.sink = sinks[0];
+ i->second = patch;
+
+ _hidl_cb(Result::OK, previousPatchHandle);
+ } else {
+ _hidl_cb(Result::NOT_SUPPORTED, previousPatchHandle);
+ }
+ }
+
return Void();
}
-Return<Result> PrimaryDevice::releaseAudioPatch(int32_t patch) {
- (void)patch;
- return Result::NOT_SUPPORTED;
+Return<Result> PrimaryDevice::releaseAudioPatch(AudioPatchHandle patchHandle) {
+ return (mAudioPatches.erase(patchHandle) == 1) ? Result::OK : FAILURE(Result::INVALID_ARGUMENTS);
}
Return<void> PrimaryDevice::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, port);
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), port);
return Void();
}
Return<Result> PrimaryDevice::setAudioPortConfig(const AudioPortConfig& config) {
(void)config;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> PrimaryDevice::setScreenState(bool turnedOn) {
@@ -219,7 +247,7 @@ Return<Result> PrimaryDevice::setScreenState(bool turnedOn) {
}
Return<void> PrimaryDevice::getHwAvSync(getHwAvSync_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, {});
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
return Void();
}
@@ -230,7 +258,7 @@ Return<void> PrimaryDevice::getParameters(const hidl_vec<ParameterValue>& contex
if (keys.size() == 0) {
_hidl_cb(Result::OK, {});
} else {
- _hidl_cb(Result::NOT_SUPPORTED, {});
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
}
return Void();
}
@@ -250,12 +278,12 @@ Return<void> PrimaryDevice::getMicrophones(getMicrophones_cb _hidl_cb) {
Return<Result> PrimaryDevice::setConnectedState(const DeviceAddress& dev_addr, bool connected) {
(void)dev_addr;
(void)connected;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> PrimaryDevice::close() {
if (mNStreams > 0) {
- return Result::INVALID_STATE;
+ return FAILURE(Result::INVALID_STATE);
} else if (mMixer) {
mMixerMasterVolumeCtl = nullptr;
mMixerCaptureVolumeCtl = nullptr;
@@ -264,24 +292,24 @@ Return<Result> PrimaryDevice::close() {
mMixer.reset();
return Result::OK;
} else {
- return Result::INVALID_STATE;
+ return FAILURE(Result::INVALID_STATE);
}
}
Return<Result> PrimaryDevice::addDeviceEffect(AudioPortHandle device, uint64_t effectId) {
(void)device;
(void)effectId;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> PrimaryDevice::removeDeviceEffect(AudioPortHandle device, uint64_t effectId) {
(void)device;
(void)effectId;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
- return (volume >= 0 && volume <= 1.0) ? Result::OK : Result::INVALID_ARGUMENTS;
+ return (volume >= 0 && volume <= 1.0) ? Result::OK : FAILURE(Result::INVALID_ARGUMENTS);
}
Return<Result> PrimaryDevice::setMode(AudioMode mode) {
@@ -293,78 +321,78 @@ Return<Result> PrimaryDevice::setMode(AudioMode mode) {
return Result::OK;
default:
- return Result::INVALID_ARGUMENTS;
+ return FAILURE(Result::INVALID_ARGUMENTS);
}
}
Return<Result> PrimaryDevice::setBtScoHeadsetDebugName(const hidl_string& name) {
(void)name;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> PrimaryDevice::getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, false);
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
return Void();
}
Return<Result> PrimaryDevice::setBtScoNrecEnabled(bool enabled) {
(void)enabled;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> PrimaryDevice::getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, false);
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
return Void();
}
Return<Result> PrimaryDevice::setBtScoWidebandEnabled(bool enabled) {
(void)enabled;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> PrimaryDevice::getTtyMode(getTtyMode_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, TtyMode::OFF);
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), TtyMode::OFF);
return Void();
}
Return<Result> PrimaryDevice::setTtyMode(IPrimaryDevice::TtyMode mode) {
(void)mode;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> PrimaryDevice::getHacEnabled(getHacEnabled_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, false);
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
return Void();
}
Return<Result> PrimaryDevice::setHacEnabled(bool enabled) {
(void)enabled;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> PrimaryDevice::getBtHfpEnabled(getBtHfpEnabled_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, false);
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
return Void();
}
Return<Result> PrimaryDevice::setBtHfpEnabled(bool enabled) {
(void)enabled;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> PrimaryDevice::setBtHfpSampleRate(uint32_t sampleRateHz) {
(void)sampleRateHz;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> PrimaryDevice::setBtHfpVolume(float volume) {
(void)volume;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> PrimaryDevice::updateRotation(IPrimaryDevice::Rotation rotation) {
(void)rotation;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
void PrimaryDevice::unrefDevice(IDevice *dev) {
diff --git a/audio/primary_device.h b/audio/primary_device.h
index 72b5c756..05964f3e 100644
--- a/audio/primary_device.h
+++ b/audio/primary_device.h
@@ -17,6 +17,7 @@
#pragma once
#include <android/hardware/audio/6.0/IPrimaryDevice.h>
#include <atomic>
+#include <unordered_map>
#include "talsa.h"
namespace android {
@@ -62,11 +63,11 @@ struct PrimaryDevice : public IPrimaryDevice {
Return<void> createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
createAudioPatch_cb _hidl_cb) override;
- Return<void> updateAudioPatch(int32_t previousPatch,
+ Return<void> updateAudioPatch(AudioPatchHandle previousPatch,
const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
updateAudioPatch_cb _hidl_cb) override;
- Return<Result> releaseAudioPatch(int32_t patch) override;
+ Return<Result> releaseAudioPatch(AudioPatchHandle patch) override;
Return<void> getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) override;
Return<Result> setAudioPortConfig(const AudioPortConfig& config) override;
Return<Result> setScreenState(bool turnedOn) override;
@@ -107,7 +108,16 @@ private:
talsa::mixer_ctl_t *mMixerCaptureVolumeCtl = nullptr;
talsa::mixer_ctl_t *mMixerMasterPaybackSwitchCtl = nullptr;
talsa::mixer_ctl_t *mMixerCaptureSwitchCtl = nullptr;
+ float mMasterVolume = 1.0f;
std::atomic<int> mNStreams = 0;
+
+ struct AudioPatch {
+ AudioPortConfig source;
+ AudioPortConfig sink;
+ };
+
+ AudioPatchHandle mNextAudioPatchHandle = 0;
+ std::unordered_map<AudioPatchHandle, AudioPatch> mAudioPatches;
};
} // namespace implementation
diff --git a/audio/stream_common.cpp b/audio/stream_common.cpp
index 3ac4da8b..6235f9a8 100644
--- a/audio/stream_common.cpp
+++ b/audio/stream_common.cpp
@@ -17,6 +17,7 @@
#include <log/log.h>
#include "stream_common.h"
#include "util.h"
+#include "debug.h"
namespace android {
namespace hardware {
@@ -64,7 +65,7 @@ void StreamCommon::getSupportedSampleRates(AudioFormat format,
Result StreamCommon::setSampleRate(uint32_t sampleRateHz) const {
(void)sampleRateHz;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
hidl_bitfield<AudioChannelMask> StreamCommon::getChannelMask() const {
@@ -82,7 +83,7 @@ void StreamCommon::getSupportedChannelMasks(AudioFormat format,
Result StreamCommon::setChannelMask(hidl_bitfield<AudioChannelMask> mask) const {
(void)mask;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
AudioFormat StreamCommon::getFormat() const {
@@ -95,7 +96,7 @@ void StreamCommon::getSupportedFormats(IStream::getSupportedFormats_cb _hidl_cb)
Result StreamCommon::setFormat(AudioFormat format) const {
(void)format;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
void StreamCommon::getAudioProperties(IStream::getAudioProperties_cb _hidl_cb) const {
@@ -108,7 +109,7 @@ void StreamCommon::getDevices(IStream::getDevices_cb _hidl_cb) const {
Result StreamCommon::setDevices(const hidl_vec<DeviceAddress>& devices) const {
(void)devices;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
} // namespace implementation
diff --git a/audio/stream_in.cpp b/audio/stream_in.cpp
index 89ca7e60..c3ef62f2 100644
--- a/audio/stream_in.cpp
+++ b/audio/stream_in.cpp
@@ -20,9 +20,10 @@
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include "stream_in.h"
+#include "device_port_source.h"
#include "deleters.h"
-#include "talsa.h"
#include "util.h"
+#include "debug.h"
#include <sys/resource.h>
#include <pthread.h>
#include <cutils/sched_policy.h>
@@ -45,15 +46,8 @@ struct ReadThread : public IOThread {
typedef MessageQueue<IStreamIn::ReadStatus, kSynchronizedReadWrite> StatusMQ;
typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
- ReadThread(StreamIn *stream,
- const unsigned nChannels,
- const size_t sampleRateHz,
- const size_t frameCount,
- const size_t bufferSize)
+ ReadThread(StreamIn *stream, const size_t bufferSize)
: mStream(stream)
- , mNChannels(nChannels)
- , mSampleRateHz(sampleRateHz)
- , mFrameCount(frameCount)
, mCommandMQ(1)
, mStatusMQ(1)
, mDataMQ(bufferSize, true /* EventFlag */) {
@@ -117,22 +111,20 @@ struct ReadThread : public IOThread {
}
if (efState & STAND_BY_REQUEST) {
- mPcm.reset();
+ mSource.reset();
mBuffer.reset();
}
if (efState & (MessageQueueFlagBits::NOT_FULL | 0)) {
- if (!mPcm) {
+ if (!mSource) {
mBuffer.reset(new uint8_t[mDataMQ.getQuantumCount()]);
LOG_ALWAYS_FATAL_IF(!mBuffer);
- mPcm = talsa::pcmOpen(
- talsa::kPcmCard, talsa::kPcmDevice,
- mNChannels, mSampleRateHz, mFrameCount,
- false /* isOut */);
- LOG_ALWAYS_FATAL_IF(!mPcm);
-
- mPos.reset();
+ mSource = DevicePortSource::create(mStream->getDeviceAddress(),
+ mStream->getAudioConfig(),
+ mStream->getAudioOutputFlags(),
+ mStream->getFrameCounter());
+ LOG_ALWAYS_FATAL_IF(!mSource);
}
processCommand();
@@ -160,7 +152,7 @@ struct ReadThread : public IOThread {
default:
ALOGE("ReadThread::%s:%d: Unknown read thread command code %d",
__func__, __LINE__, rParameters.command);
- rStatus.retval = Result::NOT_SUPPORTED;
+ rStatus.retval = FAILURE(Result::NOT_SUPPORTED);
break;
}
@@ -184,8 +176,6 @@ struct ReadThread : public IOThread {
if (!mDataMQ.write(&mBuffer[0], read)) {
ALOGE("ReadThread::%s:%d: mDataMQ.write failed", __func__, __LINE__);
}
-
- mPos.addFrames(pcm_bytes_to_frames(mPcm.get(), read));
status.reply.read = read;
}
@@ -193,15 +183,12 @@ struct ReadThread : public IOThread {
}
Result doReadImpl(uint8_t *const data, const size_t toRead, size_t &read) {
- const int res = pcm_read(mPcm.get(), data, toRead);
+ const int res = mSource->read(data, toRead);
if (res < 0) {
memset(data, 0, toRead);
read = toRead;
-
- ALOGE("ReadThread::%s:%d pcm_read failed with %s",
+ ALOGE("StreamInReadThread::%s:%d pcm_read failed with %s",
__func__, __LINE__, strerror(-res));
- } else if (res == 0) {
- read = toRead;
} else {
read = res;
}
@@ -212,25 +199,20 @@ struct ReadThread : public IOThread {
IStreamIn::ReadStatus doGetCapturePosition() {
IStreamIn::ReadStatus status;
- status.retval = Result::OK;
- nsecs_t t = 0;
- mPos.now(mSampleRateHz, status.reply.capturePosition.frames, t);
- status.reply.capturePosition.time = t;
+ status.retval = mSource->getCapturePosition(
+ status.reply.capturePosition.frames,
+ status.reply.capturePosition.time);
return status;
}
StreamIn *const mStream;
- const unsigned mNChannels;
- const size_t mSampleRateHz;
- const size_t mFrameCount;
CommandMQ mCommandMQ;
StatusMQ mStatusMQ;
DataMQ mDataMQ;
std::unique_ptr<EventFlag, deleters::forEventFlag> mEfGroup;
std::unique_ptr<uint8_t[]> mBuffer;
- talsa::PcmPtr mPcm;
- util::StreamPosition mPos;
+ std::unique_ptr<DevicePortSource> mSource;
std::thread mThread;
std::promise<pthread_t> mTid;
};
@@ -251,7 +233,7 @@ StreamIn::StreamIn(sp<IDevice> dev,
}
StreamIn::~StreamIn() {
- close();
+ closeImpl(true);
}
Return<uint64_t> StreamIn::getFrameSize() {
@@ -314,12 +296,12 @@ Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) {
Return<Result> StreamIn::addEffect(uint64_t effectId) {
(void)effectId;
- return Result::INVALID_ARGUMENTS;
+ return FAILURE(Result::INVALID_ARGUMENTS);
}
Return<Result> StreamIn::removeEffect(uint64_t effectId) {
(void)effectId;
- return Result::INVALID_ARGUMENTS;
+ return FAILURE(Result::INVALID_ARGUMENTS);
}
Return<Result> StreamIn::standby() {
@@ -343,7 +325,7 @@ Return<void> StreamIn::getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) {
(void)context;
- _hidl_cb((keys.size() > 0) ? Result::NOT_SUPPORTED : Result::OK, {});
+ _hidl_cb((keys.size() > 0) ? FAILURE(Result::NOT_SUPPORTED) : Result::OK, {});
return Void();
}
@@ -356,48 +338,56 @@ Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& context,
Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) {
(void)hwAvSync;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> StreamIn::start() {
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> StreamIn::stop() {
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames,
createMmapBuffer_cb _hidl_cb) {
(void)minSizeFrames;
- _hidl_cb(Result::NOT_SUPPORTED, {});
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
return Void();
}
Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, {});
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
return Void();
}
-Return<Result> StreamIn::close() {
+Result StreamIn::closeImpl(const bool fromDctor) {
if (mDev) {
mReadThread.reset();
mUnrefDevice(mDev.get());
mDev = nullptr;
return Result::OK;
+ } else if (fromDctor) {
+ // closeImpl is always called from the dctor, it is ok if mDev is null,
+ // we don't want to log the error in this case.
+ return Result::OK;
} else {
- return Result::INVALID_STATE;
+ return FAILURE(Result::INVALID_STATE);
}
}
+Return<Result> StreamIn::close() {
+ return closeImpl(false);
+}
+
Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, {});
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
return Void();
}
Return<Result> StreamIn::setGain(float gain) {
(void)gain;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
@@ -409,20 +399,16 @@ Return<void> StreamIn::prepareForReading(uint32_t frameSize,
uint32_t framesCount,
prepareForReading_cb _hidl_cb) {
if (!frameSize || !framesCount || frameSize > 256 || framesCount > (1u << 20)) {
- _hidl_cb(Result::INVALID_ARGUMENTS, {}, {}, {}, {});
+ _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), {}, {}, {}, {});
return Void();
}
if (mReadThread) { // INVALID_STATE if the method was already called.
- _hidl_cb(Result::INVALID_STATE, {}, {}, {}, {});
+ _hidl_cb(FAILURE(Result::INVALID_STATE), {}, {}, {}, {});
return Void();
}
- auto t = std::make_unique<ReadThread>(this,
- util::countChannels(mCommon.getChannelMask()),
- mCommon.getSampleRate(),
- mCommon.getFrameCount(),
- frameSize * framesCount);
+ auto t = std::make_unique<ReadThread>(this, frameSize * framesCount);
if (t->isRunning()) {
_hidl_cb(Result::OK,
@@ -433,7 +419,7 @@ Return<void> StreamIn::prepareForReading(uint32_t frameSize,
mReadThread = std::move(t);
} else {
- _hidl_cb(Result::INVALID_ARGUMENTS, {}, {}, {}, {});
+ _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), {}, {}, {}, {});
}
return Void();
@@ -444,7 +430,7 @@ Return<uint32_t> StreamIn::getInputFramesLost() {
}
Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, 0, 0); // see ReadThread::doGetCapturePosition
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), 0, 0); // see ReadThread::doGetCapturePosition
return Void();
}
@@ -455,12 +441,12 @@ Return<void> StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) {
Return<Result> StreamIn::setMicrophoneDirection(MicrophoneDirection direction) {
(void)direction;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> StreamIn::setMicrophoneFieldDimension(float zoom) {
(void)zoom;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
} // namespace implementation
diff --git a/audio/stream_in.h b/audio/stream_in.h
index 13b28d81..2a769814 100644
--- a/audio/stream_in.h
+++ b/audio/stream_in.h
@@ -87,12 +87,23 @@ struct StreamIn : public IStreamIn {
Return<Result> setMicrophoneDirection(MicrophoneDirection direction) override;
Return<Result> setMicrophoneFieldDimension(float zoom) override;
+ const DeviceAddress &getDeviceAddress() const { return mCommon.m_device; }
+ const AudioConfig &getAudioConfig() const { return mCommon.m_config; }
+ const hidl_bitfield<AudioOutputFlag> &getAudioOutputFlags() const { return mCommon.m_flags; }
+
+ uint64_t &getFrameCounter() { return mFrames; }
+
private:
+ Result closeImpl(bool fromDctor);
+
sp<IDevice> mDev;
void (* const mUnrefDevice)(IDevice*);
const StreamCommon mCommon;
const SinkMetadata mSinkMetadata;
std::unique_ptr<IOThread> mReadThread;
+
+ // The count is not reset to zero when output enters standby.
+ uint64_t mFrames = 0;
};
} // namespace implementation
diff --git a/audio/stream_out.cpp b/audio/stream_out.cpp
index 8de19638..72b826fe 100644
--- a/audio/stream_out.cpp
+++ b/audio/stream_out.cpp
@@ -21,9 +21,10 @@
#include <hidl/Status.h>
#include <math.h>
#include "stream_out.h"
-#include "talsa.h"
+#include "device_port_sink.h"
#include "deleters.h"
#include "util.h"
+#include "debug.h"
#include <sys/resource.h>
#include <pthread.h>
#include <cutils/sched_policy.h>
@@ -48,15 +49,8 @@ struct WriteThread : public IOThread {
typedef MessageQueue<IStreamOut::WriteStatus, kSynchronizedReadWrite> StatusMQ;
typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
- WriteThread(StreamOut *stream,
- const unsigned nChannels,
- const size_t sampleRateHz,
- const size_t frameCount,
- const size_t mqBufferSize)
+ WriteThread(StreamOut *stream, const size_t mqBufferSize)
: mStream(stream)
- , mNChannels(nChannels)
- , mSampleRateHz(sampleRateHz)
- , mFrameCount(frameCount)
, mCommandMQ(1)
, mStatusMQ(1)
, mDataMQ(mqBufferSize, true /* EventFlag */) {
@@ -120,22 +114,19 @@ struct WriteThread : public IOThread {
}
if (efState & STAND_BY_REQUEST) {
- mPcm.reset();
- mBuffer.reset();
+ mSink.reset();
}
if (efState & (MessageQueueFlagBits::NOT_EMPTY | 0)) {
- if (!mPcm) {
+ if (!mSink) {
mBuffer.reset(new uint8_t[mDataMQ.getQuantumCount()]);
LOG_ALWAYS_FATAL_IF(!mBuffer);
- mPcm = talsa::pcmOpen(
- talsa::kPcmCard, talsa::kPcmDevice,
- mNChannels, mSampleRateHz, mFrameCount,
- true /* isOut */);
- LOG_ALWAYS_FATAL_IF(!mPcm);
-
- mPos.reset();
+ mSink = DevicePortSink::create(mStream->getDeviceAddress(),
+ mStream->getAudioConfig(),
+ mStream->getAudioOutputFlags(),
+ mStream->getFrameCounter());
+ LOG_ALWAYS_FATAL_IF(!mSink);
}
processCommand();
@@ -167,7 +158,7 @@ struct WriteThread : public IOThread {
default:
ALOGE("WriteThread::%s:%d: Unknown write thread command code %d",
__func__, __LINE__, wCommand);
- wStatus.retval = Result::NOT_SUPPORTED;
+ wStatus.retval = FAILURE(Result::NOT_SUPPORTED);
break;
}
@@ -186,9 +177,8 @@ struct WriteThread : public IOThread {
const size_t availToRead = mDataMQ.availableToRead();
size_t written = 0;
if (mDataMQ.read(&mBuffer[0], availToRead)) {
+ applyVolume(&mBuffer[0], availToRead, mStream->getVolumeNumerator());
status.retval = doWriteImpl(&mBuffer[0], availToRead, written);
-
- mPos.addFrames(pcm_bytes_to_frames(mPcm.get(), written));
status.reply.written = written;
} else {
ALOGE("WriteThread::%s:%d: mDataMQ.read failed", __func__, __LINE__);
@@ -198,10 +188,25 @@ struct WriteThread : public IOThread {
return status;
}
+ static void applyVolume(void *buf, const size_t szBytes, const int32_t numerator) {
+ constexpr int32_t kDenominator = StreamOut::kVolumeDenominator;
+
+ if (numerator == kDenominator) {
+ return;
+ }
+
+ int16_t *samples = static_cast<int16_t *>(buf);
+ std::for_each(samples,
+ samples + szBytes / sizeof(*samples),
+ [numerator](int16_t &x) {
+ x = (x * numerator + kDenominator / 2) / kDenominator;
+ });
+ }
+
IStreamOut::WriteStatus doGetPresentationPosition() {
IStreamOut::WriteStatus status;
- status.retval = doGetPresentationPositionImpl(
+ status.retval = mSink->getPresentationPosition(
status.reply.presentationPosition.frames,
status.reply.presentationPosition.timeStamp);
@@ -220,35 +225,25 @@ struct WriteThread : public IOThread {
Result doWriteImpl(const uint8_t *const data,
const size_t toWrite,
size_t &written) {
- const int res = pcm_write(mPcm.get(), data, toWrite);
- if (res) {
- ALOGE("WriteThread::%s:%d: pcm_write failed with %s",
+ const int res = mSink->write(data, toWrite);
+ if (res < 0) {
+ ALOGE("WriteThread::%s:%d: DevicePortSink::write failed with %s",
__func__, __LINE__, strerror(-res));
+ written = toWrite;
+ } else {
+ written = res;
}
- written = toWrite;
- return Result::OK;
- }
-
- Result doGetPresentationPositionImpl(uint64_t &frames, TimeSpec &ts) {
- nsecs_t t = 0;
- mPos.now(mSampleRateHz, frames, t);
- ts.tvSec = ns2s(t);
- ts.tvNSec = t - s2ns(ts.tvSec);
return Result::OK;
}
StreamOut *const mStream;
- const unsigned mNChannels;
- const size_t mSampleRateHz;
- const size_t mFrameCount;
CommandMQ mCommandMQ;
StatusMQ mStatusMQ;
DataMQ mDataMQ;
std::unique_ptr<EventFlag, deleters::forEventFlag> mEfGroup;
std::unique_ptr<uint8_t[]> mBuffer;
- talsa::PcmPtr mPcm;
- util::StreamPosition mPos;
+ std::unique_ptr<DevicePortSink> mSink;
std::thread mThread;
std::promise<pthread_t> mTid;
};
@@ -265,11 +260,10 @@ StreamOut::StreamOut(sp<IDevice> dev,
: mDev(std::move(dev))
, mUnrefDevice(unrefDevice)
, mCommon(ioHandle, device, config, flags)
- , mSourceMetadata(sourceMetadata) {
-}
+ , mSourceMetadata(sourceMetadata) {}
StreamOut::~StreamOut() {
- close();
+ closeImpl(true);
}
Return<uint64_t> StreamOut::getFrameSize() {
@@ -332,12 +326,12 @@ Return<void> StreamOut::getAudioProperties(getAudioProperties_cb _hidl_cb) {
Return<Result> StreamOut::addEffect(uint64_t effectId) {
(void)effectId;
- return Result::INVALID_ARGUMENTS;
+ return FAILURE(Result::INVALID_ARGUMENTS);
}
Return<Result> StreamOut::removeEffect(uint64_t effectId) {
(void)effectId;
- return Result::INVALID_ARGUMENTS;
+ return FAILURE(Result::INVALID_ARGUMENTS);
}
Return<Result> StreamOut::standby() {
@@ -361,7 +355,7 @@ Return<void> StreamOut::getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) {
(void)context;
- _hidl_cb((keys.size() > 0) ? Result::NOT_SUPPORTED : Result::OK, {});
+ _hidl_cb((keys.size() > 0) ? FAILURE(Result::NOT_SUPPORTED) : Result::OK, {});
return Void();
}
@@ -374,37 +368,45 @@ Return<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& context,
Return<Result> StreamOut::setHwAvSync(uint32_t hwAvSync) {
(void)hwAvSync;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
-Return<Result> StreamOut::close() {
+Result StreamOut::closeImpl(const bool fromDctor) {
if (mDev) {
mWriteThread.reset();
mUnrefDevice(mDev.get());
mDev = nullptr;
return Result::OK;
+ } else if (fromDctor) {
+ // closeImpl is always called from the dctor, it is ok if mDev is null,
+ // we don't want to log the error in this case.
+ return Result::OK;
} else {
- return Result::INVALID_STATE;
+ return FAILURE(Result::INVALID_STATE);
}
}
+Return<Result> StreamOut::close() {
+ return closeImpl(false);
+}
+
Return<Result> StreamOut::start() {
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> StreamOut::stop() {
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> StreamOut::createMmapBuffer(int32_t minSizeFrames,
createMmapBuffer_cb _hidl_cb) {
(void)minSizeFrames;
- _hidl_cb(Result::NOT_SUPPORTED, {});
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
return Void();
}
Return<void> StreamOut::getMmapPosition(getMmapPosition_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, {});
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
return Void();
}
@@ -413,9 +415,13 @@ Return<uint32_t> StreamOut::getLatency() {
}
Return<Result> StreamOut::setVolume(float left, float right) {
- (void)left;
- (void)right;
- return Result::NOT_SUPPORTED;
+ if (isnan(left) || left < 0.0f || left > 1.0f
+ || right < 0.0f || right > 1.0f || isnan(right)) {
+ return FAILURE(Result::INVALID_ARGUMENTS);
+ }
+
+ mVolumeNumerator = int16_t((left + right) * kVolumeDenominator / 2);
+ return Result::OK;
}
Return<void> StreamOut::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
@@ -427,20 +433,16 @@ Return<void> StreamOut::prepareForWriting(uint32_t frameSize,
uint32_t framesCount,
prepareForWriting_cb _hidl_cb) {
if (!frameSize || !framesCount || frameSize > 256 || framesCount > (1u << 20)) {
- _hidl_cb(Result::INVALID_ARGUMENTS, {}, {}, {}, {});
+ _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), {}, {}, {}, {});
return Void();
}
if (mWriteThread) { // INVALID_STATE if the method was already called.
- _hidl_cb(Result::INVALID_STATE, {}, {}, {}, {});
+ _hidl_cb(FAILURE(Result::INVALID_STATE), {}, {}, {}, {});
return Void();
}
- auto t = std::make_unique<WriteThread>(this,
- util::countChannels(mCommon.getChannelMask()),
- mCommon.getSampleRate(),
- mCommon.getFrameCount(),
- frameSize * framesCount);
+ auto t = std::make_unique<WriteThread>(this, frameSize * framesCount);
if (t->isRunning()) {
_hidl_cb(Result::OK,
@@ -451,34 +453,34 @@ Return<void> StreamOut::prepareForWriting(uint32_t frameSize,
mWriteThread = std::move(t);
} else {
- _hidl_cb(Result::INVALID_ARGUMENTS, {}, {}, {}, {});
+ _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), {}, {}, {}, {});
}
return Void();
}
Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, 0);
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), 0);
return Void();
}
Return<void> StreamOut::getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, 0);
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), 0);
return Void();
}
Return<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback) {
(void)callback;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> StreamOut::clearCallback() {
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> StreamOut::setEventCallback(const sp<IStreamOutEventCallback>& callback) {
(void)callback;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> StreamOut::supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb) {
@@ -487,11 +489,11 @@ Return<void> StreamOut::supportsPauseAndResume(supportsPauseAndResume_cb _hidl_c
}
Return<Result> StreamOut::pause() {
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> StreamOut::resume() {
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<bool> StreamOut::supportsDrain() {
@@ -500,15 +502,15 @@ Return<bool> StreamOut::supportsDrain() {
Return<Result> StreamOut::drain(AudioDrain type) {
(void)type;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> StreamOut::flush() {
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> StreamOut::getPresentationPosition(getPresentationPosition_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, {}, {}); // see WriteThread::doGetPresentationPosition
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {}, {}); // see WriteThread::doGetPresentationPosition
return Void();
}
@@ -516,37 +518,37 @@ Return<Result> StreamOut::selectPresentation(int32_t presentationId,
int32_t programId) {
(void)presentationId;
(void)programId;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> StreamOut::getDualMonoMode(getDualMonoMode_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, {});
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
return Void();
}
Return<Result> StreamOut::setDualMonoMode(DualMonoMode mode) {
(void)mode;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> StreamOut::getAudioDescriptionMixLevel(getAudioDescriptionMixLevel_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, 0);
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), 0);
return Void();
}
Return<Result> StreamOut::setAudioDescriptionMixLevel(float leveldB) {
(void)leveldB;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> StreamOut::getPlaybackRateParameters(getPlaybackRateParameters_cb _hidl_cb) {
- _hidl_cb(Result::NOT_SUPPORTED, {});
+ _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
return Void();
}
Return<Result> StreamOut::setPlaybackRateParameters(const PlaybackRate &playbackRate) {
(void)playbackRate;
- return Result::NOT_SUPPORTED;
+ return FAILURE(Result::NOT_SUPPORTED);
}
} // namespace implementation
diff --git a/audio/stream_out.h b/audio/stream_out.h
index c55ad8ce..79adef34 100644
--- a/audio/stream_out.h
+++ b/audio/stream_out.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <atomic>
#include <android/hardware/audio/6.0/IStreamOut.h>
#include <android/hardware/audio/6.0/IDevice.h>
#include "stream_common.h"
@@ -44,6 +45,8 @@ struct StreamOut : public IStreamOut {
const SourceMetadata& sourceMetadata);
~StreamOut();
+ static constexpr int16_t kVolumeDenominator = 1 << 14;
+
// IStream
Return<uint64_t> getFrameSize() override;
Return<uint64_t> getFrameCount() override;
@@ -101,12 +104,25 @@ struct StreamOut : public IStreamOut {
Return<void> getPlaybackRateParameters(getPlaybackRateParameters_cb _hidl_cb) override;
Return<Result> setPlaybackRateParameters(const PlaybackRate &playbackRate) override;
+ int16_t getVolumeNumerator() const { return mVolumeNumerator; };
+ const DeviceAddress &getDeviceAddress() const { return mCommon.m_device; }
+ const AudioConfig &getAudioConfig() const { return mCommon.m_config; }
+ const hidl_bitfield<AudioOutputFlag> &getAudioOutputFlags() const { return mCommon.m_flags; }
+
+ uint64_t &getFrameCounter() { return mFrames; }
+
private:
+ Result closeImpl(bool fromDctor);
+
sp<IDevice> mDev;
void (* const mUnrefDevice)(IDevice*);
const StreamCommon mCommon;
const SourceMetadata mSourceMetadata;
std::unique_ptr<IOThread> mWriteThread;
+ std::atomic<int16_t> mVolumeNumerator = kVolumeDenominator;
+
+ // The count is not reset to zero when output enters standby.
+ uint64_t mFrames = 0;
};
} // namespace implementation
diff --git a/audio/talsa.cpp b/audio/talsa.cpp
index 61ea1409..12c22b0a 100644
--- a/audio/talsa.cpp
+++ b/audio/talsa.cpp
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-#include "talsa.h"
#include <log/log.h>
+#include "talsa.h"
+#include "debug.h"
namespace android {
namespace hardware {
@@ -60,7 +61,7 @@ std::unique_ptr<pcm_t, PcmDeleter> pcmOpen(const unsigned int dev,
"frameCount=%zu isOut=%d with %s", __func__, __LINE__,
nChannels, sampleRateHz, frameCount, isOut,
pcm_get_error(pcm.get()));
- return nullptr;
+ return FAILURE(nullptr);
}
}
diff --git a/audio/util.cpp b/audio/util.cpp
index 746e37de..dbe620ba 100644
--- a/audio/util.cpp
+++ b/audio/util.cpp
@@ -18,6 +18,7 @@
#include <cutils/bitops.h>
#include <system/audio.h>
#include "util.h"
+#include "debug.h"
namespace android {
namespace hardware {
@@ -59,11 +60,16 @@ bool checkSampleRateHz(uint32_t value, uint32_t &suggest) {
}
suggest = kSupportedRatesHz.back();
- return false;
+ return FAILURE(false);
+}
+
+size_t align(size_t v, size_t a) {
+ return (v + a - 1) / a * a;
}
size_t getBufferSizeFrames(size_t duration_ms, uint32_t sample_rate) {
- return sample_rate * duration_ms / 1000;
+ // AudioFlinger requires the buffer to be aligned by 16 frames
+ return align(sample_rate * duration_ms / 1000, 16);
}
} // namespace
@@ -107,7 +113,7 @@ bool checkAudioConfig(bool isOut,
kSupportedOutChannelMask.end(),
cfg.channelMask) == kSupportedOutChannelMask.end()) {
suggested.channelMask = AudioChannelMask::OUT_STEREO | 0;
- valid = false;
+ valid = FAILURE(false);
} else {
suggested.channelMask = cfg.channelMask;
}
@@ -116,7 +122,7 @@ bool checkAudioConfig(bool isOut,
kSupportedInChannelMask.end(),
cfg.channelMask) == kSupportedInChannelMask.end()) {
suggested.channelMask = AudioChannelMask::IN_STEREO | 0;
- valid = false;
+ valid = FAILURE(false);
} else {
suggested.channelMask = cfg.channelMask;
}
@@ -126,7 +132,7 @@ bool checkAudioConfig(bool isOut,
kSupportedAudioFormats.end(),
cfg.format) == kSupportedAudioFormats.end()) {
suggested.format = AudioFormat::PCM_16_BIT;
- valid = false;
+ valid = FAILURE(false);
} else {
suggested.format = cfg.format;
}
@@ -140,25 +146,11 @@ bool checkAudioConfig(bool isOut,
return valid;
}
-StreamPosition::StreamPosition() : mTimestamp(systemTime(SYSTEM_TIME_MONOTONIC)) {}
-
-void StreamPosition::addFrames(uint64_t n) {
- mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
- mFrames += n;
-}
-
-void StreamPosition::now(const size_t sampleRateHz,
- uint64_t &frames,
- nsecs_t &timestamp) const {
- const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- const uint64_t deltaUs = ns2us(now - mTimestamp);
-
- frames = mFrames + sampleRateHz * deltaUs / 1000000;
- timestamp = now;
-}
-
-void StreamPosition::reset() {
- *this = StreamPosition();
+TimeSpec nsecs2TimeSpec(nsecs_t ns) {
+ TimeSpec ts;
+ ts.tvSec = ns2s(ns);
+ ts.tvNSec = ns - s2ns(ts.tvSec);
+ return ts;
}
} // namespace util
diff --git a/audio/util.h b/audio/util.h
index bfac69a5..aae8f535 100644
--- a/audio/util.h
+++ b/audio/util.h
@@ -43,15 +43,7 @@ bool checkAudioConfig(bool isOut,
const AudioConfig &cfg,
AudioConfig &suggested);
-struct StreamPosition {
- StreamPosition();
- void addFrames(uint64_t n);
- void now(size_t sampleRateHz, uint64_t &frames, nsecs_t &timestamp) const;
- void reset();
-
- uint64_t mFrames = 0;
- nsecs_t mTimestamp;
-};
+TimeSpec nsecs2TimeSpec(nsecs_t);
} // namespace util
} // namespace implementation
diff --git a/camera/media_codecs.xml b/camera/media_codecs.xml
index edead34f..81cffc93 100644
--- a/camera/media_codecs.xml
+++ b/camera/media_codecs.xml
@@ -82,6 +82,16 @@ Only the three quirks included above are recognized at this point:
<Setting name="max-video-encoder-input-buffers" value="12" />
</Settings>
+ <MediaCodec name="OMX.android.goldfish.h264.decoder" type="video/avc" >
+ <Limit name="concurrent-instances" max="4" />
+ </MediaCodec>
+ <MediaCodec name="OMX.android.goldfish.vp8.decoder" type="video/x-vnd.on2.vp8" >
+ <Limit name="concurrent-instances" max="4" />
+ </MediaCodec>
+ <MediaCodec name="OMX.android.goldfish.vp9.decoder" type="video/x-vnd.on2.vp9" >
+ <Limit name="concurrent-instances" max="4" />
+ </MediaCodec>
+
<Include href="media_codecs_google_audio.xml" />
<Include href="media_codecs_google_telephony.xml" />
<Include href="media_codecs_google_video.xml" />
diff --git a/camera/media_codecs_google_video_default.xml b/camera/media_codecs_google_video_default.xml
index 3d955487..588ead52 100644
--- a/camera/media_codecs_google_video_default.xml
+++ b/camera/media_codecs_google_video_default.xml
@@ -36,37 +36,18 @@
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.android.goldfish.h264.decoder" type="video/avc">
- <Limit name="size" min="96x96" max="2560x2560" />
+ <Limit name="size" min="96x96" max="3840x2160" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="24-2073600" />
<Limit name="bitrate" range="1-120000000" />
<Limit name="frame-rate" range="1-480" />
- <Limit name="performance-point-2560x1440" value="80" />
- <Limit name="performance-point-1920x1080" value="160" />
- <Limit name="performance-point-1280x720" value="480" />
- <Limit name="measured-frame-rate-320x240" range="183-183" />
- <Limit name="measured-frame-rate-720x480" range="181-181" />
- <Limit name="measured-frame-rate-1280x720" range="182-184" />
- <Limit name="measured-frame-rate-1920x1080" range="30-50" />
- <Limit name="measured-frame-rate-2560x1440" range="30-40" />
- <Feature name="adaptive-playback" />
- </MediaCodec>
- <MediaCodec name="OMX.google.goldfish.h264.decoder" type="video/avc">
- <Limit name="size" min="96x96" max="2560x2560" />
- <Limit name="alignment" value="2x2" />
- <Limit name="block-size" value="16x16" />
- <Limit name="blocks-per-second" range="24-2073600" />
- <Limit name="bitrate" range="1-120000000" />
- <Limit name="frame-rate" range="1-480" />
- <Limit name="performance-point-2560x1440" value="80" />
- <Limit name="performance-point-1920x1080" value="160" />
- <Limit name="performance-point-1280x720" value="480" />
- <Limit name="measured-frame-rate-320x240" range="183-183" />
- <Limit name="measured-frame-rate-720x480" range="181-181" />
- <Limit name="measured-frame-rate-1280x720" range="182-184" />
- <Limit name="measured-frame-rate-1920x1080" range="30-50" />
- <Limit name="measured-frame-rate-2560x1440" range="30-40" />
+ <Limit name="performance-point-3840x2160" value="60" />
+ <Limit name="measured-frame-rate-320x240" range="257-266" />
+ <Limit name="measured-frame-rate-720x480" range="262-264" />
+ <Limit name="measured-frame-rate-1280x720" range="227-251" />
+ <Limit name="measured-frame-rate-1920x1080" range="235-247" />
+ <Limit name="measured-frame-rate-3840x2160" range="235-247" />
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.google.h264.decoder" type="video/avc">
@@ -77,9 +58,7 @@
<Limit name="bitrate" range="1-120000000" />
<Limit name="frame-rate" range="1-480" />
<Limit name="concurrent-instances" max="16" />
- <Limit name="performance-point-720x480" range="180" />
- <Limit name="performance-point-1280x720" value="480" />
- <Limit name="performance-point-1920x1080" value="30" />
+ <Limit name="performance-point-1920x1088" value="30" />
<Limit name="measured-frame-rate-320x240" range="183-183" />
<Limit name="measured-frame-rate-720x480" range="181-181" />
<Limit name="measured-frame-rate-1280x720" range="182-184" />
@@ -98,71 +77,33 @@
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.android.goldfish.vp9.decoder" type="video/x-vnd.on2.vp9">
- <Limit name="size" min="96x96" max="3840x2150" />
+ <Limit name="size" min="96x96" max="3840x2160" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" min="24" max="2073600" />
<Limit name="bitrate" range="1-120000000" />
<Limit name="frame-rate" range="1-480" />
- <Limit name="performance-point-2560x1440" value="80" />
- <Limit name="performance-point-1920x1080" value="160" />
- <Limit name="performance-point-1280x720" value="480" />
- <Limit name="measured-frame-rate-320x240" range="183-183" />
- <Limit name="measured-frame-rate-720x480" range="181-181" />
- <Limit name="measured-frame-rate-1280x720" range="182-184" />
- <Limit name="measured-frame-rate-1920x1088" range="30-50" />
- <Limit name="measured-frame-rate-2560x1440" range="30-40" />
+ <Limit name="performance-point-3840x2160" value="60" />
+ <Limit name="measured-frame-rate-320x180" range="237-258" />
+ <Limit name="measured-frame-rate-640x360" range="237-258" />
+ <Limit name="measured-frame-rate-1280x720" range="237-258" />
+ <Limit name="measured-frame-rate-1920x1080" range="293-302" />
+ <Limit name="measured-frame-rate-3840x2160" range="150-150" />
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.android.goldfish.vp8.decoder" type="video/x-vnd.on2.vp8">
- <Limit name="size" min="96x96" max="3840x2150" />
+ <Limit name="size" min="96x96" max="3840x2160" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" min="24" max="2073600" />
<Limit name="bitrate" range="1-120000000" />
<Limit name="frame-rate" range="1-480" />
- <Limit name="performance-point-2560x1440" value="80" />
- <Limit name="performance-point-1920x1080" value="160" />
- <Limit name="performance-point-1280x720" value="480" />
- <Limit name="measured-frame-rate-320x240" range="183-183" />
- <Limit name="measured-frame-rate-720x480" range="181-181" />
- <Limit name="measured-frame-rate-1280x720" range="182-184" />
- <Limit name="measured-frame-rate-1920x1088" range="30-50" />
- <Limit name="measured-frame-rate-2560x1440" range="30-40" />
- <Feature name="adaptive-playback" />
- </MediaCodec>
- <MediaCodec name="OMX.google.goldfish.vp8.decoder" type="video/x-vnd.on2.vp8">
- <Limit name="size" min="2x2" max="2560x2560" />
- <Limit name="alignment" value="2x2" />
- <Limit name="block-size" value="16x16" />
- <Limit name="blocks-per-second" min="24" max="2073600" />
- <Limit name="bitrate" range="1-120000000" />
- <Limit name="frame-rate" range="1-480" />
- <Limit name="performance-point-2560x1440" value="80" />
- <Limit name="performance-point-1920x1080" value="160" />
- <Limit name="performance-point-1280x720" value="480" />
- <Limit name="measured-frame-rate-320x240" range="183-183" />
- <Limit name="measured-frame-rate-720x480" range="181-181" />
- <Limit name="measured-frame-rate-1280x720" range="182-184" />
- <Limit name="measured-frame-rate-1920x1088" range="30-50" />
- <Limit name="measured-frame-rate-2560x1440" range="30-40" />
- <Feature name="adaptive-playback" />
- </MediaCodec>
- <MediaCodec name="OMX.google.goldfish.vp9.decoder" type="video/x-vnd.on2.vp9">
- <Limit name="size" min="2x2" max="2560x2560" />
- <Limit name="alignment" value="2x2" />
- <Limit name="block-size" value="16x16" />
- <Limit name="blocks-per-second" min="24" max="2073600" />
- <Limit name="bitrate" range="1-120000000" />
- <Limit name="frame-rate" range="1-480" />
- <Limit name="performance-point-2560x1440" value="80" />
- <Limit name="performance-point-1920x1080" value="160" />
- <Limit name="performance-point-1280x720" value="480" />
- <Limit name="measured-frame-rate-320x240" range="183-183" />
- <Limit name="measured-frame-rate-720x480" range="181-181" />
- <Limit name="measured-frame-rate-1280x720" range="182-184" />
- <Limit name="measured-frame-rate-1920x1088" range="30-50" />
- <Limit name="measured-frame-rate-2560x1440" range="30-40" />
+ <Limit name="performance-point-3840x2160" value="60" />
+ <Limit name="measured-frame-rate-320x180" range="743-817" />
+ <Limit name="measured-frame-rate-640x360" range="237-258" />
+ <Limit name="measured-frame-rate-1280x720" range="237-258" />
+ <Limit name="measured-frame-rate-1920x1080" range="30-160" />
+ <Limit name="measured-frame-rate-3840x2160" range="30-90" />
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="OMX.google.vp8.decoder" type="video/x-vnd.on2.vp8">
@@ -172,9 +113,7 @@
<Limit name="blocks-per-second" min="24" max="2073600" />
<Limit name="bitrate" range="1-120000000" />
<Limit name="frame-rate" range="1-480" />
- <Limit name="performance-point-2560x1440" value="80" />
- <Limit name="performance-point-1920x1080" value="160" />
- <Limit name="performance-point-1280x720" value="480" />
+ <Limit name="performance-point-1920x1088" value="60" />
<Limit name="measured-frame-rate-320x240" range="183-183" />
<Limit name="measured-frame-rate-720x480" range="181-181" />
<Limit name="measured-frame-rate-1280x720" range="182-184" />
@@ -189,12 +128,10 @@
<Limit name="blocks-per-second" min="24" max="2073600" />
<Limit name="bitrate" range="1-120000000" />
<Limit name="frame-rate" range="1-480" />
- <Limit name="performance-point-2560x1440" value="80" />
- <Limit name="performance-point-1920x1080" value="160" />
- <Limit name="performance-point-1280x720" value="480" />
+ <Limit name="performance-point-1920x1088" value="60" />
<Limit name="measured-frame-rate-320x240" range="183-183" />
<Limit name="measured-frame-rate-720x480" range="181-181" />
- <Limit name="measured-frame-rate-1280x720" range="182-184" />
+ <Limit name="measured-frame-rate-1280x720" range="121-125" />
<Limit name="measured-frame-rate-1920x1088" range="30-50" />
<Limit name="measured-frame-rate-2560x1440" range="30-40" />
<Feature name="adaptive-playback" />
diff --git a/data/etc/advancedFeatures.ini b/data/etc/advancedFeatures.ini
index 92c37748..73a8fc25 100644
--- a/data/etc/advancedFeatures.ini
+++ b/data/etc/advancedFeatures.ini
@@ -10,6 +10,7 @@ HostComposition = on
RefCountPipe = on
VirtioInput = on
DynamicPartition = on
+HardwareDecoder = on
YUVCache = on
GLDirectMem = on
Vulkan = on
diff --git a/data/etc/config.ini.xl b/data/etc/config.ini.xl
index 40ec7cca..32d26659 100644
--- a/data/etc/config.ini.xl
+++ b/data/etc/config.ini.xl
@@ -16,5 +16,5 @@ hw.sensors.proximity=yes
image.sysdir.1=x86/
skin.dynamic=no
hw.lcd.density=560
-skin.name=1440x2560
-skin.path=1440x2560
+skin.name=1440x2960
+skin.path=1440x2960
diff --git a/data/etc/google/user/advancedFeatures.ini b/data/etc/google/user/advancedFeatures.ini
index 4b7cb339..85b5c3ab 100644
--- a/data/etc/google/user/advancedFeatures.ini
+++ b/data/etc/google/user/advancedFeatures.ini
@@ -11,6 +11,7 @@ HostComposition = on
RefCountPipe = on
VirtioInput = on
DynamicPartition = on
+HardwareDecoder = on
MultiDisplay = on
YUVCache = on
GLDirectMem = on
diff --git a/data/etc/google/userdebug/advancedFeatures.ini b/data/etc/google/userdebug/advancedFeatures.ini
index 4b7cb339..85b5c3ab 100644
--- a/data/etc/google/userdebug/advancedFeatures.ini
+++ b/data/etc/google/userdebug/advancedFeatures.ini
@@ -11,6 +11,7 @@ HostComposition = on
RefCountPipe = on
VirtioInput = on
DynamicPartition = on
+HardwareDecoder = on
MultiDisplay = on
YUVCache = on
GLDirectMem = on
diff --git a/emulator-info.txt b/emulator-info.txt
index 1ae560d8..fb45a7e0 100644
--- a/emulator-info.txt
+++ b/emulator-info.txt
@@ -1,2 +1,2 @@
# Emulator (stable) version
-require version-emulator=6278574
+require version-emulator=6629878
diff --git a/init.ranchu.rc b/init.ranchu.rc
index 9be9885b..d2e5bded 100644
--- a/init.ranchu.rc
+++ b/init.ranchu.rc
@@ -62,7 +62,8 @@ on boot
setprop ro.opengles.version ${ro.kernel.qemu.opengles.version}
setprop ro.zygote.disable_gl_preload 1
- setprop debug.stagefright.ccodec 0
+ # 0: omx; 4: c2 default now
+ setprop debug.stagefright.ccodec 4
setprop debug.stagefright.ccodec ${ro.kernel.qemu.media.ccodec}
setprop dalvik.vm.heapsize 192m
diff --git a/sepolicy/common/file_contexts b/sepolicy/common/file_contexts
index 421952f4..f009b7cd 100644
--- a/sepolicy/common/file_contexts
+++ b/sepolicy/common/file_contexts
@@ -45,6 +45,7 @@
/vendor/bin/hw/android\.hardware\.power\.stats@1\.0-service\.mock u:object_r:hal_power_stats_default_exec:s0
/vendor/bin/hw/android\.hardware\.gnss@2\.0-service\.ranchu u:object_r:hal_gnss_default_exec:s0
/vendor/bin/hw/android\.hardware\.neuralnetworks@1\.3-service-sample-.* u:object_r:hal_neuralnetworks_sample_exec:s0
+/vendor/bin/hw/android\.hardware\.audio\.service.ranchu u:object_r:hal_audio_default_exec:s0
/vendor/lib(64)?/hw/vulkan\.ranchu\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/libEGL_emulation\.so u:object_r:same_process_hal_file:s0
diff --git a/vendor.mk b/vendor.mk
index b65a9bb9..a17f8731 100644
--- a/vendor.mk
+++ b/vendor.mk
@@ -18,6 +18,9 @@
#
$(call inherit-product-if-exists, frameworks/native/build/phone-xhdpi-2048-dalvik-heap.mk)
+# Enable Scoped Storage related
+$(call inherit-product, $(SRC_TARGET_DIR)/product/emulated_storage.mk)
+
PRODUCT_SOONG_NAMESPACES += \
device/generic/goldfish \
device/generic/goldfish-opengl
@@ -73,11 +76,6 @@ PRODUCT_PACKAGES += \
endif
PRODUCT_PACKAGES += \
- audio.r_submix.default \
- android.hardware.audio.service \
- android.hardware.audio.effect@6.0-impl:32
-
-PRODUCT_PACKAGES += \
android.hardware.bluetooth@1.1-service.sim \
android.hardware.bluetooth.audio@2.0-impl
PRODUCT_PROPERTY_OVERRIDES += bt.rootcanal_test_console=off
@@ -151,15 +149,20 @@ PRODUCT_PACKAGES += \
DEVICE_MANIFEST_FILE += device/generic/goldfish/manifest.camera.xml
endif
-ifneq ($(EMULATOR_VENDOR_NO_SOUND_TRIGGER),true)
-PRODUCT_PACKAGES += android.hardware.soundtrigger@2.2-impl.ranchu
-endif
-
ifneq ($(EMULATOR_VENDOR_NO_SOUND),true)
-PRODUCT_PACKAGES += android.hardware.audio@6.0-impl.ranchu
+PRODUCT_PACKAGES += \
+ android.hardware.audio.service.ranchu \
+ android.hardware.soundtrigger@2.2-impl.ranchu \
+ android.hardware.audio.effect@6.0-impl \
+
PRODUCT_COPY_FILES += \
device/generic/goldfish/audio/policy/audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_configuration.xml \
- device/generic/goldfish/audio/policy/primary_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/primary_audio_policy_configuration.xml
+ device/generic/goldfish/audio/policy/primary_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/primary_audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/r_submix_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/r_submix_audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_volumes.xml \
+ frameworks/av/services/audiopolicy/config/default_volume_tables.xml:$(TARGET_COPY_OUT_VENDOR)/etc/default_volume_tables.xml \
+ frameworks/av/media/libeffects/data/audio_effects.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.xml \
+
endif
PRODUCT_PACKAGES += \
@@ -290,9 +293,6 @@ PRODUCT_COPY_FILES += \
device/generic/goldfish/data/etc/android.software.vulkan.deqp.level-2019-03-01.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.vulkan.deqp.level-2019-03-01.xml \
frameworks/native/data/etc/android.software.autofill.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.autofill.xml \
frameworks/native/data/etc/android.software.verified_boot.xml:${TARGET_COPY_OUT_PRODUCT}/etc/permissions/android.software.verified_boot.xml \
- frameworks/av/media/libeffects/data/audio_effects.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.xml \
- frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_volumes.xml \
- frameworks/av/services/audiopolicy/config/default_volume_tables.xml:$(TARGET_COPY_OUT_VENDOR)/etc/default_volume_tables.xml \
device/generic/goldfish/data/etc/permissions/privapp-permissions-goldfish.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/permissions/privapp-permissions-goldfish.xml \
hardware/google/camera/devices/EmulatedCamera/hwl/configs/emu_camera_back.json:$(TARGET_COPY_OUT_VENDOR)/etc/config/emu_camera_back.json \
hardware/google/camera/devices/EmulatedCamera/hwl/configs/emu_camera_front.json:$(TARGET_COPY_OUT_VENDOR)/etc/config/emu_camera_front.json \