summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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/EmulatedFakeCamera3.cpp4
-rw-r--r--camera/JpegCompressor.cpp2
-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--rro_overlays/TetheringOverlay/Android.bp22
-rw-r--r--rro_overlays/TetheringOverlay/AndroidManifest.xml11
-rw-r--r--rro_overlays/TetheringOverlay/res/values/config.xml28
-rw-r--r--sensors/multihal_sensors.cpp187
-rw-r--r--sensors/multihal_sensors.h42
-rw-r--r--sensors/multihal_sensors_epoll.cpp4
-rw-r--r--sensors/multihal_sensors_qemu.cpp15
-rw-r--r--sensors/sensor_list.cpp28
-rw-r--r--sepolicy/common/file_contexts1
-rw-r--r--vendor.mk34
-rw-r--r--wifi/wifi_hal/Android.bp1
-rw-r--r--wifi/wifi_hal/interface.cpp24
-rw-r--r--wifi/wifi_hal/netlinkmessage.cpp37
-rw-r--r--wifi/wifi_hal/netlinkmessage.h3
46 files changed, 1321 insertions, 484 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/EmulatedFakeCamera3.cpp b/camera/EmulatedFakeCamera3.cpp
index 2009a33b..2da2c4da 100644
--- a/camera/EmulatedFakeCamera3.cpp
+++ b/camera/EmulatedFakeCamera3.cpp
@@ -1109,7 +1109,7 @@ status_t EmulatedFakeCamera3::getCameraCapabilities() {
mCapabilities.add(FULL_LEVEL);
// "RAW" causes several CTS failures: b/68723953, disable it so far.
// TODO: add "RAW" back when all failures are resolved.
- //mCapabilities.add(RAW);
+ mCapabilities.add(RAW);
mCapabilities.add(MOTION_TRACKING);
}
@@ -1330,7 +1330,7 @@ status_t EmulatedFakeCamera3::constructStaticInfo() {
// android.flash
- static const uint8_t flashAvailable = 0;
+ static const uint8_t flashAvailable = 1;
ADD_STATIC_ENTRY(ANDROID_FLASH_INFO_AVAILABLE, &flashAvailable, 1);
// android.hotPixel
diff --git a/camera/JpegCompressor.cpp b/camera/JpegCompressor.cpp
index 3a5b15e1..168b98a0 100644
--- a/camera/JpegCompressor.cpp
+++ b/camera/JpegCompressor.cpp
@@ -46,7 +46,7 @@ typedef size_t (*GetCompressedSizeFunc)(JpegStub* stub);
NV21JpegCompressor::NV21JpegCompressor()
{
- const char dlName[] = "/vendor/lib/hw/camera.goldfish.jpeg.so";
+ const char dlName[] = "/vendor/lib/hw/camera.ranchu.jpeg.so";
if (mDl == NULL) {
mDl = dlopen(dlName, RTLD_NOW);
}
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/rro_overlays/TetheringOverlay/Android.bp b/rro_overlays/TetheringOverlay/Android.bp
new file mode 100644
index 00000000..31b0c570
--- /dev/null
+++ b/rro_overlays/TetheringOverlay/Android.bp
@@ -0,0 +1,22 @@
+//
+// 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.
+//
+
+runtime_resource_overlay {
+ name: "EmulatorTetheringConfigOverlay",
+ resource_dirs: ["res"],
+ product_specific: true,
+ sdk_version: "current",
+}
diff --git a/rro_overlays/TetheringOverlay/AndroidManifest.xml b/rro_overlays/TetheringOverlay/AndroidManifest.xml
new file mode 100644
index 00000000..fc8c8bd0
--- /dev/null
+++ b/rro_overlays/TetheringOverlay/AndroidManifest.xml
@@ -0,0 +1,11 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.networkstack.tethering.emulator"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application android:hasCode="false" />
+ <overlay
+ android:targetPackage="com.android.networkstack.tethering"
+ android:targetName="TetheringConfig"
+ android:isStatic="true"
+ android:priority="0"/>
+</manifest>
diff --git a/rro_overlays/TetheringOverlay/res/values/config.xml b/rro_overlays/TetheringOverlay/res/values/config.xml
new file mode 100644
index 00000000..8cb8b405
--- /dev/null
+++ b/rro_overlays/TetheringOverlay/res/values/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Allow testing SoftAP using the simulated interfaces on the emulator. -->
+ <string-array name="config_tether_wifi_regexs">
+ <item>"wlan\\d"</item>
+ </string-array>
+ <string-array name="config_tether_wifi_p2p_regexs">
+ <item>"p2p-wlan\\d-.*"</item>
+ </string-array>
+</resources>
diff --git a/sensors/multihal_sensors.cpp b/sensors/multihal_sensors.cpp
index 3502add9..104ff7f6 100644
--- a/sensors/multihal_sensors.cpp
+++ b/sensors/multihal_sensors.cpp
@@ -26,7 +26,9 @@ using ahs21::SensorType;
using ahs10::SensorFlagBits;
using ahs10::MetaDataEventType;
-MultihalSensors::MultihalSensors() : m_qemuSensorsFd(qemud_channel_open("sensors")) {
+MultihalSensors::MultihalSensors()
+ : m_qemuSensorsFd(qemud_channel_open("sensors"))
+ , m_batchInfo(getSensorNumber()) {
if (!m_qemuSensorsFd.ok()) {
ALOGE("%s:%d: m_qemuSensorsFd is not opened", __func__, __LINE__);
::abort();
@@ -56,13 +58,16 @@ MultihalSensors::MultihalSensors() : m_qemuSensorsFd(qemud_channel_open("sensors
::abort();
}
buffer[len] = 0;
- uint32_t availableSensorsMask = 0;
- if (sscanf(buffer, "%u", &availableSensorsMask) != 1) {
+ uint32_t hostSensorsMask = 0;
+ if (sscanf(buffer, "%u", &hostSensorsMask) != 1) {
ALOGE("%s:%d: Can't parse qemud response", __func__, __LINE__);
::abort();
}
m_availableSensorsMask =
- availableSensorsMask & ((1u << getSensorNumber()) - 1);
+ hostSensorsMask & ((1u << getSensorNumber()) - 1);
+
+ ALOGI("%s:%d: host sensors mask=%x, available sensors mask=%x",
+ __func__, __LINE__, hostSensorsMask, m_availableSensorsMask);
if (!::android::base::Socketpair(AF_LOCAL, SOCK_STREAM, 0,
&m_callersFd, &m_sensorThreadFd)) {
@@ -70,11 +75,17 @@ MultihalSensors::MultihalSensors() : m_qemuSensorsFd(qemud_channel_open("sensors
::abort();
}
- m_sensorThread = std::thread(qemuSensorListenerThreadStart, this);
+ m_sensorThread = std::thread(&MultihalSensors::qemuSensorListenerThread, this);
+ m_batchThread = std::thread(&MultihalSensors::batchThread, this);
}
MultihalSensors::~MultihalSensors() {
- disableAllSensors();
+ setAllQemuSensors(false);
+
+ m_batchRunning = false;
+ m_batchUpdated.notify_one();
+ m_batchThread.join();
+
qemuSensorThreadSendCommand(kCMD_QUIT);
m_sensorThread.join();
}
@@ -104,7 +115,7 @@ Return<void> MultihalSensors::getSensorsList_2_1(getSensorsList_2_1_cb _hidl_cb)
}
Return<Result> MultihalSensors::setOperationMode(const OperationMode mode) {
- std::unique_lock<std::mutex> lock(m_apiMtx);
+ std::unique_lock<std::mutex> lock(m_mtx);
if (m_activeSensorsMask) {
return Result::INVALID_OPERATION;
@@ -120,25 +131,31 @@ Return<Result> MultihalSensors::activate(const int32_t sensorHandle,
return Result::BAD_VALUE;
}
- std::unique_lock<std::mutex> lock(m_apiMtx);
+ std::unique_lock<std::mutex> lock(m_mtx);
+ BatchInfo& batchInfo = m_batchInfo[sensorHandle];
- uint32_t newActiveMask;
if (enabled) {
- newActiveMask = m_activeSensorsMask | (1u << sensorHandle);
- } else {
- newActiveMask = m_activeSensorsMask & ~(1u << sensorHandle);
- }
- if (m_activeSensorsMask == newActiveMask) {
- return Result::OK;
- }
-
- if (m_opMode == OperationMode::NORMAL) {
- if (!activateQemuSensorImpl(m_qemuSensorsFd.get(), sensorHandle, enabled)) {
- return Result::INVALID_OPERATION;
+ const SensorInfo* sensor = getSensorInfoByHandle(sensorHandle);
+ LOG_ALWAYS_FATAL_IF(!sensor);
+ if (!(sensor->flags & static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE))) {
+ if (batchInfo.samplingPeriodNs <= 0) {
+ return Result::BAD_VALUE;
+ }
+
+ BatchEventRef batchEventRef;
+ batchEventRef.timestamp =
+ ::android::elapsedRealtimeNano() + batchInfo.samplingPeriodNs;
+ batchEventRef.sensorHandle = sensorHandle;
+ batchEventRef.generation = ++batchInfo.generation;
+
+ m_batchQueue.push(batchEventRef);
+ m_batchUpdated.notify_one();
}
- }
- m_activeSensorsMask = newActiveMask;
+ m_activeSensorsMask = m_activeSensorsMask | (1u << sensorHandle);
+ } else {
+ m_activeSensorsMask = m_activeSensorsMask & ~(1u << sensorHandle);
+ }
return Result::OK;
}
@@ -147,26 +164,35 @@ Return<Result> MultihalSensors::batch(const int32_t sensorHandle,
const int64_t maxReportLatencyNs) {
(void)maxReportLatencyNs;
+ if (!isSensorHandleValid(sensorHandle)) {
+ return Result::BAD_VALUE;
+ }
+
const SensorInfo* sensor = getSensorInfoByHandle(sensorHandle);
- if (sensor) {
- if (samplingPeriodNs >= sensor->minDelay) {
- return Result::OK;
- } else {
- return Result::BAD_VALUE;
- }
- } else {
+ LOG_ALWAYS_FATAL_IF(!sensor);
+
+ if (samplingPeriodNs < sensor->minDelay) {
return Result::BAD_VALUE;
}
+
+ std::unique_lock<std::mutex> lock(m_mtx);
+ if (m_opMode == OperationMode::NORMAL) {
+ m_batchInfo[sensorHandle].samplingPeriodNs = samplingPeriodNs;
+ }
+
+ return Result::OK;
}
Return<Result> MultihalSensors::flush(const int32_t sensorHandle) {
- const SensorInfo* sensor = getSensorInfoByHandle(sensorHandle);
- if (!sensor) {
+ if (!isSensorHandleValid(sensorHandle)) {
return Result::BAD_VALUE;
}
- std::unique_lock<std::mutex> lock(m_apiMtx);
- if (!(m_activeSensorsMask & (1u << sensorHandle))) {
+ const SensorInfo* sensor = getSensorInfoByHandle(sensorHandle);
+ LOG_ALWAYS_FATAL_IF(!sensor);
+
+ std::unique_lock<std::mutex> lock(m_mtx);
+ if (!isSensorActive(sensorHandle)) {
return Result::BAD_VALUE;
}
@@ -175,48 +201,58 @@ Return<Result> MultihalSensors::flush(const int32_t sensorHandle) {
event.sensorType = SensorType::META_DATA;
event.u.meta.what = MetaDataEventType::META_DATA_FLUSH_COMPLETE;
- postSensorEventLocked(event);
+ doPostSensorEventLocked(*sensor, event);
return Result::OK;
}
Return<Result> MultihalSensors::injectSensorData_2_1(const Event& event) {
+ if (!isSensorHandleValid(event.sensorHandle)) {
+ return Result::BAD_VALUE;
+ }
if (event.sensorType == SensorType::ADDITIONAL_INFO) {
return Result::OK;
}
- std::unique_lock<std::mutex> lock(m_apiMtx);
+ std::unique_lock<std::mutex> lock(m_mtx);
if (m_opMode != OperationMode::DATA_INJECTION) {
return Result::INVALID_OPERATION;
}
const SensorInfo* sensor = getSensorInfoByHandle(event.sensorHandle);
- if (!sensor) {
- return Result::BAD_VALUE;
- }
+ LOG_ALWAYS_FATAL_IF(!sensor);
if (sensor->type != event.sensorType) {
return Result::BAD_VALUE;
}
- postSensorEventLocked(event);
+ doPostSensorEventLocked(*sensor, event);
return Result::OK;
}
Return<Result> MultihalSensors::initialize(const sp<IHalProxyCallback>& halProxyCallback) {
- std::unique_lock<std::mutex> lock(m_apiMtx);
- disableAllSensors();
+ std::unique_lock<std::mutex> lock(m_mtx);
+ setAllQemuSensors(true); // we need to start sampling sensors for batching
m_opMode = OperationMode::NORMAL;
m_halProxyCallback = halProxyCallback;
return Result::OK;
}
void MultihalSensors::postSensorEvent(const Event& event) {
- std::unique_lock<std::mutex> lock(m_apiMtx);
- postSensorEventLocked(event);
+ const SensorInfo* sensor = getSensorInfoByHandle(event.sensorHandle);
+ LOG_ALWAYS_FATAL_IF(!sensor);
+
+ std::unique_lock<std::mutex> lock(m_mtx);
+ if (sensor->flags & static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE)) {
+ if (isSensorActive(event.sensorHandle)) {
+ doPostSensorEventLocked(*sensor, event);
+ }
+ } else { // CONTINUOUS_MODE
+ m_batchInfo[event.sensorHandle].event = event;
+ }
}
-void MultihalSensors::postSensorEventLocked(const Event& event) {
+void MultihalSensors::doPostSensorEventLocked(const SensorInfo& sensor,
+ const Event& event) {
const bool isWakeupEvent =
- getSensorInfoByHandle(event.sensorHandle)->flags &
- static_cast<uint32_t>(SensorFlagBits::WAKE_UP);
+ sensor.flags & static_cast<uint32_t>(SensorFlagBits::WAKE_UP);
m_halProxyCallback->postEvents(
{event},
@@ -227,6 +263,65 @@ bool MultihalSensors::qemuSensorThreadSendCommand(const char cmd) const {
return TEMP_FAILURE_RETRY(write(m_callersFd.get(), &cmd, 1)) == 1;
}
+bool MultihalSensors::isSensorHandleValid(int sensorHandle) const {
+ if (!goldfish::isSensorHandleValid(sensorHandle)) {
+ return false;
+ }
+
+ if (!(m_availableSensorsMask & (1u << sensorHandle))) {
+ return false;
+ }
+
+ return true;
+}
+
+void MultihalSensors::batchThread() {
+ using high_resolution_clock = std::chrono::high_resolution_clock;
+
+ while (m_batchRunning) {
+ std::unique_lock<std::mutex> lock(m_mtx);
+ if (m_batchQueue.empty()) {
+ m_batchUpdated.wait(lock);
+ } else {
+ const int64_t t = m_batchQueue.top().timestamp;
+ const auto d = std::chrono::nanoseconds(t);
+ high_resolution_clock::time_point waitUntil(d);
+ m_batchUpdated.wait_until(lock, waitUntil);
+ }
+
+ const int64_t nowNs = ::android::elapsedRealtimeNano();
+ while (!m_batchQueue.empty() && (nowNs >= m_batchQueue.top().timestamp)) {
+ BatchEventRef evRef = m_batchQueue.top();
+ m_batchQueue.pop();
+
+ const int sensorHandle = evRef.sensorHandle;
+ LOG_ALWAYS_FATAL_IF(!goldfish::isSensorHandleValid(sensorHandle));
+ if (!isSensorActive(sensorHandle)) {
+ continue;
+ }
+
+ BatchInfo &batchInfo = m_batchInfo[sensorHandle];
+ if (batchInfo.event.sensorType == SensorType::META_DATA) {
+ ALOGW("%s:%d the host has not provided value yet for sensorHandle=%d",
+ __func__, __LINE__, sensorHandle);
+ } else {
+ batchInfo.event.timestamp = evRef.timestamp;
+ const SensorInfo* sensor = getSensorInfoByHandle(sensorHandle);
+ LOG_ALWAYS_FATAL_IF(!sensor);
+ doPostSensorEventLocked(*sensor, batchInfo.event);
+ }
+
+ if (evRef.generation == batchInfo.generation) {
+ const int64_t samplingPeriodNs = batchInfo.samplingPeriodNs;
+ LOG_ALWAYS_FATAL_IF(samplingPeriodNs <= 0);
+
+ evRef.timestamp += samplingPeriodNs;
+ m_batchQueue.push(evRef);
+ }
+ }
+ }
+}
+
/// not supported //////////////////////////////////////////////////////////////
Return<void> MultihalSensors::registerDirectChannel(const SharedMemInfo& mem,
registerDirectChannel_cb _hidl_cb) {
diff --git a/sensors/multihal_sensors.h b/sensors/multihal_sensors.h
index 80ed6a3b..382af7f7 100644
--- a/sensors/multihal_sensors.h
+++ b/sensors/multihal_sensors.h
@@ -17,8 +17,12 @@
#pragma once
#include <android-base/unique_fd.h>
#include <V2_1/SubHal.h>
+#include <atomic>
+#include <condition_variable>
#include <cstdint>
+#include <queue>
#include <thread>
+#include <vector>
namespace goldfish {
namespace ahs = ::android::hardware::sensors;
@@ -26,6 +30,7 @@ namespace ahs21 = ahs::V2_1;
namespace ahs10 = ahs::V1_0;
using ahs21::implementation::IHalProxyCallback;
+using ahs21::SensorInfo;
using ahs21::Event;
using ahs10::OperationMode;
using ahs10::RateLevel;
@@ -81,14 +86,18 @@ private:
float lastHingeAngle2Value = kSensorNoValue;
};
+ bool isSensorHandleValid(int sensorHandle) const;
+ bool isSensorActive(int sensorHandle) const {
+ return m_activeSensorsMask & (1u << sensorHandle); // m_mtx required
+ }
static bool activateQemuSensorImpl(int pipe, int sensorHandle, bool enabled);
- bool disableAllSensors();
+ bool setAllQemuSensors(bool enabled);
void parseQemuSensorEvent(const int pipe, QemuSensorsProtocolState* state);
void postSensorEvent(const Event& event);
- void postSensorEventLocked(const Event& event);
+ void doPostSensorEventLocked(const SensorInfo& sensor, const Event& event);
void qemuSensorListenerThread();
- static void qemuSensorListenerThreadStart(MultihalSensors* that);
+ void batchThread();
static constexpr char kCMD_QUIT = 'q';
bool qemuSensorThreadSendCommand(char cmd) const;
@@ -105,7 +114,32 @@ private:
uint32_t m_activeSensorsMask = 0;
OperationMode m_opMode = OperationMode::NORMAL;
sp<IHalProxyCallback> m_halProxyCallback;
- mutable std::mutex m_apiMtx;
+
+ // batching
+ struct BatchEventRef {
+ int64_t timestamp = -1;
+ int sensorHandle = -1;
+ int generation = 0;
+
+ bool operator<(const BatchEventRef &rhs) const {
+ // not a typo, we want m_batchQueue.top() to be the smallest timestamp
+ return timestamp > rhs.timestamp;
+ }
+ };
+
+ struct BatchInfo {
+ Event event;
+ int64_t samplingPeriodNs = 0;
+ int generation = 0;
+ };
+
+ std::priority_queue<BatchEventRef> m_batchQueue;
+ std::vector<BatchInfo> m_batchInfo;
+ std::condition_variable m_batchUpdated;
+ std::thread m_batchThread;
+ std::atomic<bool> m_batchRunning = true;
+
+ mutable std::mutex m_mtx;
};
} // namespace goldfish
diff --git a/sensors/multihal_sensors_epoll.cpp b/sensors/multihal_sensors_epoll.cpp
index 0be12245..cf2ae56b 100644
--- a/sensors/multihal_sensors_epoll.cpp
+++ b/sensors/multihal_sensors_epoll.cpp
@@ -38,10 +38,6 @@ int qemuSensortThreadRcvCommand(const int fd) {
}
} // namespace
-void MultihalSensors::qemuSensorListenerThreadStart(MultihalSensors* that) {
- that->qemuSensorListenerThread();
-}
-
void MultihalSensors::qemuSensorListenerThread() {
const unique_fd epollFd(epoll_create1(0));
if (!epollFd.ok()) {
diff --git a/sensors/multihal_sensors_qemu.cpp b/sensors/multihal_sensors_qemu.cpp
index a07d569b..f5da3a15 100644
--- a/sensors/multihal_sensors_qemu.cpp
+++ b/sensors/multihal_sensors_qemu.cpp
@@ -69,19 +69,16 @@ bool MultihalSensors::activateQemuSensorImpl(const int pipe,
}
}
-bool MultihalSensors::disableAllSensors() {
- if (m_opMode == OperationMode::NORMAL) {
- uint32_t mask = m_activeSensorsMask;
- for (int i = 0; mask; ++i, mask >>= 1) {
- if (mask & 1) {
- if (!activateQemuSensorImpl(m_qemuSensorsFd.get(), i, false)) {
- return false;
- }
+bool MultihalSensors::setAllQemuSensors(const bool enabled) {
+ uint32_t mask = m_availableSensorsMask;
+ for (int i = 0; mask; ++i, mask >>= 1) {
+ if (mask & 1) {
+ if (!activateQemuSensorImpl(m_qemuSensorsFd.get(), i, enabled)) {
+ return false;
}
}
}
- m_activeSensorsMask = 0;
return true;
}
diff --git a/sensors/sensor_list.cpp b/sensors/sensor_list.cpp
index 245379fa..d228ba62 100644
--- a/sensors/sensor_list.cpp
+++ b/sensors/sensor_list.cpp
@@ -122,11 +122,11 @@ const SensorInfo kAllSensors[] = {
.maxRange = 80.0,
.resolution = 1.0,
.power = 0.0,
- .minDelay = 10000,
+ .minDelay = 0,
.fifoReservedEventCount = 0,
.fifoMaxEventCount = 0,
.requiredPermission = "",
- .maxDelay = 500000,
+ .maxDelay = 0,
.flags = SensorFlagBits::DATA_INJECTION |
SensorFlagBits::ON_CHANGE_MODE
},
@@ -140,11 +140,11 @@ const SensorInfo kAllSensors[] = {
.maxRange = 1.0,
.resolution = 1.0,
.power = 20.0,
- .minDelay = 10000,
+ .minDelay = 0,
.fifoReservedEventCount = 0,
.fifoMaxEventCount = 0,
.requiredPermission = "",
- .maxDelay = 500000,
+ .maxDelay = 0,
.flags = SensorFlagBits::DATA_INJECTION |
SensorFlagBits::ON_CHANGE_MODE |
SensorFlagBits::WAKE_UP
@@ -159,11 +159,11 @@ const SensorInfo kAllSensors[] = {
.maxRange = 40000.0,
.resolution = 1.0,
.power = 20.0,
- .minDelay = 10000,
+ .minDelay = 0,
.fifoReservedEventCount = 0,
.fifoMaxEventCount = 0,
.requiredPermission = "",
- .maxDelay = 500000,
+ .maxDelay = 0,
.flags = SensorFlagBits::DATA_INJECTION |
SensorFlagBits::ON_CHANGE_MODE
},
@@ -195,11 +195,11 @@ const SensorInfo kAllSensors[] = {
.maxRange = 100.0,
.resolution = 1.0,
.power = 20.0,
- .minDelay = 10000,
+ .minDelay = 0,
.fifoReservedEventCount = 0,
.fifoMaxEventCount = 0,
.requiredPermission = "",
- .maxDelay = 500000,
+ .maxDelay = 0,
.flags = SensorFlagBits::DATA_INJECTION |
SensorFlagBits::ON_CHANGE_MODE
},
@@ -248,11 +248,11 @@ const SensorInfo kAllSensors[] = {
.maxRange = 360,
.resolution = 1.0,
.power = 3.0,
- .minDelay = 10000,
+ .minDelay = 0,
.fifoReservedEventCount = 0,
.fifoMaxEventCount = 0,
.requiredPermission = "",
- .maxDelay = 500000,
+ .maxDelay = 0,
.flags = SensorFlagBits::DATA_INJECTION |
SensorFlagBits::ON_CHANGE_MODE |
SensorFlagBits::WAKE_UP
@@ -267,11 +267,11 @@ const SensorInfo kAllSensors[] = {
.maxRange = 360,
.resolution = 1.0,
.power = 3.0,
- .minDelay = 10000,
+ .minDelay = 0,
.fifoReservedEventCount = 0,
.fifoMaxEventCount = 0,
.requiredPermission = "",
- .maxDelay = 500000,
+ .maxDelay = 0,
.flags = SensorFlagBits::DATA_INJECTION |
SensorFlagBits::ON_CHANGE_MODE |
SensorFlagBits::WAKE_UP
@@ -286,11 +286,11 @@ const SensorInfo kAllSensors[] = {
.maxRange = 360,
.resolution = 1.0,
.power = 3.0,
- .minDelay = 10000,
+ .minDelay = 0,
.fifoReservedEventCount = 0,
.fifoMaxEventCount = 0,
.requiredPermission = "",
- .maxDelay = 500000,
+ .maxDelay = 0,
.flags = SensorFlagBits::DATA_INJECTION |
SensorFlagBits::ON_CHANGE_MODE |
SensorFlagBits::WAKE_UP
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..4a588726 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
@@ -56,6 +59,7 @@ PRODUCT_PACKAGES += \
local_time.default \
SdkSetup \
EmulatorRadioConfig \
+ EmulatorTetheringConfigOverlay \
libstagefrighthw \
libstagefright_goldfish_vpxdec \
libstagefright_goldfish_avcdec \
@@ -73,11 +77,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 +150,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 += \
@@ -270,6 +274,7 @@ PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.bluetooth.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.bluetooth.xml \
system/bt/vendor_libs/test_vendor_lib/data/controller_properties.json:vendor/etc/bluetooth/controller_properties.json \
frameworks/native/data/etc/android.hardware.wifi.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.wifi.xml \
+ frameworks/native/data/etc/android.hardware.wifi.passpoint.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.wifi.passpoint.xml \
frameworks/native/data/etc/android.hardware.wifi.direct.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.wifi.direct.xml \
device/generic/goldfish/data/etc/handheld_core_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/handheld_core_hardware.xml \
device/generic/goldfish/camera/media_profiles.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_profiles_V1_0.xml \
@@ -280,9 +285,11 @@ PRODUCT_COPY_FILES += \
device/generic/goldfish/camera/media_codecs_performance.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_performance.xml \
frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \
frameworks/native/data/etc/android.hardware.camera.ar.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.ar.xml \
- frameworks/native/data/etc/android.hardware.camera.autofocus.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.autofocus.xml \
+ frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.flash-autofocus.xml \
+ frameworks/native/data/etc/android.hardware.camera.concurrent.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.concurrent.xml \
frameworks/native/data/etc/android.hardware.camera.front.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.front.xml \
frameworks/native/data/etc/android.hardware.camera.full.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.full.xml \
+ frameworks/native/data/etc/android.hardware.camera.raw.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.raw.xml \
frameworks/native/data/etc/android.hardware.fingerprint.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.fingerprint.xml \
frameworks/native/data/etc/android.hardware.vulkan.level-1.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.level.xml \
frameworks/native/data/etc/android.hardware.vulkan.compute-0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.compute.xml \
@@ -290,9 +297,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 \
diff --git a/wifi/wifi_hal/Android.bp b/wifi/wifi_hal/Android.bp
index 88c1e30d..64310034 100644
--- a/wifi/wifi_hal/Android.bp
+++ b/wifi/wifi_hal/Android.bp
@@ -28,6 +28,7 @@ cc_library_static {
"wifi_hal.cpp",
],
shared_libs: [
+ "libnl",
"liblog",
"libcutils",
"libhardware_legacy",
diff --git a/wifi/wifi_hal/interface.cpp b/wifi/wifi_hal/interface.cpp
index 7c683e52..47d81543 100644
--- a/wifi/wifi_hal/interface.cpp
+++ b/wifi/wifi_hal/interface.cpp
@@ -86,6 +86,9 @@ wifi_error Interface::getName(char* name, size_t size) {
return WIFI_SUCCESS;
}
+// Wifi legacy HAL implicitly assumes getLinkStats is blocking and
+// handler will be set to nullptr immediately after invocation.
+// Therefore, this function will wait until onLinkStatsReply is called.
wifi_error Interface::getLinkStats(wifi_request_id requestId,
wifi_stats_result_handler handler) {
NetlinkMessage message(RTM_GETLINK, mNetlink.getSequenceNumber());
@@ -97,12 +100,21 @@ wifi_error Interface::getLinkStats(wifi_request_id requestId,
info->ifi_flags = 0;
info->ifi_change = 0xFFFFFFFF;
- bool success = mNetlink.sendMessage(message,
- std::bind(&Interface::onLinkStatsReply,
- this,
- requestId,
- handler,
- std::placeholders::_1));
+ std::condition_variable condition;
+ std::mutex mutex;
+ std::unique_lock<std::mutex> lock(mutex);
+ bool stopped = false;
+ auto callback = [this, requestId, &handler,
+ &mutex, &condition, &stopped] (const NetlinkMessage& message) {
+ stopped = true;
+ std::unique_lock<std::mutex> lock(mutex);
+ onLinkStatsReply(requestId, handler, message);
+ condition.notify_all();
+ };
+ bool success = mNetlink.sendMessage(message, callback);
+ while (!stopped) {
+ condition.wait(lock);
+ }
return success ? WIFI_SUCCESS : WIFI_ERROR_UNKNOWN;
}
diff --git a/wifi/wifi_hal/netlinkmessage.cpp b/wifi/wifi_hal/netlinkmessage.cpp
index baf5800d..06bb7438 100644
--- a/wifi/wifi_hal/netlinkmessage.cpp
+++ b/wifi/wifi_hal/netlinkmessage.cpp
@@ -22,6 +22,7 @@
#include <linux/rtnetlink.h>
#include <sys/types.h>
#include <unistd.h>
+#include <netlink/msg.h>
size_t getSpaceForMessageType(uint16_t type) {
switch (type) {
@@ -51,13 +52,12 @@ NetlinkMessage::NetlinkMessage(const char* data, size_t size)
bool NetlinkMessage::getAttribute(int attributeId, void* data, size_t size) const {
const void* value = nullptr;
- uint16_t attrSize = 0;
- if (!findAttribute(attributeId, &value, &attrSize)) {
- return false;
- }
- if (size > attrSize) {
+ const auto attr = nlmsg_find_attr((struct nlmsghdr*)mData.data(), sizeof(ifinfomsg), attributeId);
+ if (!attr) {
return false;
}
+ value = (const uint8_t*) attr + NLA_HDRLEN;
+ size = attr->nla_len;
memcpy(data, value, size);
return true;
}
@@ -71,30 +71,3 @@ uint32_t NetlinkMessage::sequence() const {
auto header = reinterpret_cast<const nlmsghdr*>(mData.data());
return header->nlmsg_seq;
}
-
-bool NetlinkMessage::findAttribute(int attributeId,
- const void** value,
- uint16_t* size) const {
- const uint8_t* end = mData.data() + mData.size();
- size_t attrOffset = getSpaceForMessageType(type());
- if (attrOffset == 0) {
- return false;
- }
- const uint8_t* attribute = mData.data() + attrOffset;
- while (attribute < end) {
- auto header = reinterpret_cast<const nlattr*>(attribute);
- if (header->nla_len == 0) {
- // The length should include the header so the length should always
- // be greater than zero. If it doesn't we're going to end up looping
- // forever so ignore this.
- return false;
- }
- if (header->nla_type == attributeId) {
- *value = attribute + NLA_HDRLEN;
- *size = header->nla_len;
- return true;
- }
- attribute += header->nla_len;
- }
- return false;
-}
diff --git a/wifi/wifi_hal/netlinkmessage.h b/wifi/wifi_hal/netlinkmessage.h
index 45fd7cdb..5e1a3b80 100644
--- a/wifi/wifi_hal/netlinkmessage.h
+++ b/wifi/wifi_hal/netlinkmessage.h
@@ -60,9 +60,6 @@ private:
NetlinkMessage& operator=(const NetlinkMessage&) = delete;
bool getAttribute(int attributeId, void* data, size_t size) const;
- bool findAttribute(int attributeId,
- const void** value,
- uint16_t* size) const;
std::vector<uint8_t> mData;
};