Merge "Fix bug in default engine setForceUse."
diff --git a/apex/manifest.json b/apex/manifest.json
index 932d28e..5b235cd 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,6 +1,10 @@
{
"name": "com.android.media",
- "version": 990090000,
+
+ // Placeholder module version to be replaced during build.
+ // Do not change!
+ "version": 0,
+
"requireNativeLibs": [
"libandroid.so",
"libbinder_ndk.so",
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
index f42f5a4..f2b8b36 100644
--- a/apex/manifest_codec.json
+++ b/apex/manifest_codec.json
@@ -1,6 +1,10 @@
{
"name": "com.android.media.swcodec",
- "version": 990090000,
+
+ // Placeholder module version to be replaced during build.
+ // Do not change!
+ "version": 0,
+
"requireNativeLibs": [
":sphal"
]
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index b6f8552..772b6ed 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -2197,7 +2197,8 @@
* flashlight brightness level via
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#turnOnTorchWithStrengthLevel">CameraManager#turnOnTorchWithStrengthLevel</a>.
* If this value is equal to 1, flashlight brightness control is not supported.
- * The value for this key will be null for devices with no flash unit.</p>
+ * The value for this key will be null for devices with no flash unit.
+ * This level must be set to a safe value to prevent any burn out issues.</p>
*/
ACAMERA_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL = // int32
ACAMERA_FLASH_INFO_START + 2,
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index 32d7723..4e82f57 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -619,6 +619,8 @@
return Void();
}
+ android_errorWriteLog(0x534e4554, "235601882");
+ Mutex::Autolock lock(mSecurityLevelLock);
std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
mSecurityLevel.find(sid);
if (itr == mSecurityLevel.end()) {
@@ -691,6 +693,8 @@
return Status::ERROR_DRM_SESSION_NOT_OPENED;
}
+ android_errorWriteLog(0x534e4554, "235601882");
+ Mutex::Autolock lock(mSecurityLevelLock);
std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
mSecurityLevel.find(sid);
if (itr != mSecurityLevel.end()) {
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
index cb5c9fe..274a89a 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
@@ -414,7 +414,6 @@
std::map<std::string, std::vector<uint8_t> > mByteArrayProperties;
std::map<std::string, std::vector<uint8_t> > mReleaseKeysMap;
std::map<std::vector<uint8_t>, std::string> mPlaybackId;
- std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel;
sp<IDrmPluginListener> mListener;
sp<IDrmPluginListener_V1_2> mListenerV1_2;
SessionLibrary *mSessionLibrary;
@@ -434,6 +433,9 @@
DeviceFiles mFileHandle;
Mutex mSecureStopLock;
+ Mutex mSecurityLevelLock;
+ std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel
+ GUARDED_BY(mSecurityLevelLock);
CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin);
};
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 9d4f049..199875d 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -190,7 +190,7 @@
// matrix conversion coefficients
// (see media/libstagefright/colorconverter/ColorConverter.cpp for more details)
struct Coeffs {
- int32_t _y, _b_u, _g_u, _g_v, _r_v, _c16;
+ int32_t _y, _r_v, _g_u, _g_v, _b_u, _c16;
};
static const struct Coeffs GetCoeffsForAspects(const C2ColorAspectsStruct &aspects) {
diff --git a/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp b/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
index da62111..6c8ce3c 100644
--- a/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
+++ b/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
@@ -417,6 +417,7 @@
}
std::unique_lock lock(mQueueMutex);
mQueue.splice(mQueue.end(), *items);
+ mQueueCondition.notify_all();
return C2_OK;
}
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index bc4053d..f272499 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -54,6 +54,10 @@
static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
} // unnamed
+static bool isAtLeastT() {
+ return android_get_device_api_level() >= __ANDROID_API_T__;
+}
+
C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
// gralloc does not support WRITE_PROTECTED
return C2MemoryUsage(
@@ -702,6 +706,14 @@
}
case static_cast<uint32_t>(PixelFormat4::YCBCR_P010): {
+ // In Android T, P010 is relaxed to allow arbitrary stride for the Y and UV planes,
+ // try locking with the gralloc4 mapper first.
+ c2_status_t status = Gralloc4Mapper_lock(
+ const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
+ if (status == C2_OK) {
+ break;
+ }
+
void *pointer = nullptr;
status_t err = GraphicBufferMapper::get().lock(
const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
@@ -760,10 +772,12 @@
default: {
// We don't know what it is, let's try to lock it with gralloc4
android_ycbcr ycbcrLayout;
- c2_status_t status = Gralloc4Mapper_lock(
- const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
- if (status == C2_OK) {
- break;
+ if (isAtLeastT()) {
+ c2_status_t status = Gralloc4Mapper_lock(
+ const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
+ if (status == C2_OK) {
+ break;
+ }
}
// fallback to lockYCbCr
diff --git a/media/libaaudio/include/aaudio/AAudioTesting.h b/media/libaaudio/include/aaudio/AAudioTesting.h
index 0f2d7a2..01d97b6 100644
--- a/media/libaaudio/include/aaudio/AAudioTesting.h
+++ b/media/libaaudio/include/aaudio/AAudioTesting.h
@@ -87,7 +87,7 @@
* @note This is only for testing. Do not use this in an application.
* It may change or be removed at any time.
*
- * @return true if the stream uses ther MMAP data path
+ * @return true if the stream uses the MMAP data path
*/
AAUDIO_API bool AAudioStream_isMMapUsed(AAudioStream* stream);
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index b0c9a0c..1521882 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -3388,4 +3388,24 @@
enumToMask_index<int32_t, media::AudioDirectMode>);
}
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl) {
+ switch (aidl) {
+ case media::LatencyMode::FREE:
+ return AUDIO_LATENCY_MODE_FREE;
+ case media::LatencyMode::LOW:
+ return AUDIO_LATENCY_MODE_LOW;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<media::LatencyMode>
+legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_LATENCY_MODE_FREE:
+ return media::LatencyMode::FREE;
+ case AUDIO_LATENCY_MODE_LOW:
+ return media::LatencyMode::LOW;
+ }
+ return unexpected(BAD_VALUE);
+}
} // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 4c27d52..79dae27 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -356,6 +356,7 @@
"aidl/android/media/AudioUniqueIdUse.aidl",
"aidl/android/media/AudioVibratorInfo.aidl",
"aidl/android/media/EffectDescriptor.aidl",
+ "aidl/android/media/LatencyMode.aidl",
"aidl/android/media/TrackSecondaryOutputInfo.aidl",
],
imports: [
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 1280577..965c40f 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -670,6 +670,30 @@
return Status::ok();
}
+Status AudioSystem::AudioFlingerClient::onSupportedLatencyModesChanged(
+ int output, const std::vector<media::LatencyMode>& latencyModes) {
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ std::vector<audio_latency_mode_t> modesLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+ convertContainer<std::vector<audio_latency_mode_t>>(
+ latencyModes, aidl2legacy_LatencyMode_audio_latency_mode_t));
+
+ std::vector<sp<SupportedLatencyModesCallback>> callbacks;
+ {
+ Mutex::Autolock _l(mLock);
+ for (auto callback : mSupportedLatencyModesCallbacks) {
+ if (auto ref = callback.promote(); ref != nullptr) {
+ callbacks.push_back(ref);
+ }
+ }
+ }
+ for (const auto& callback : callbacks) {
+ callback->onSupportedLatencyModesChanged(outputLegacy, modesLegacy);
+ }
+
+ return Status::ok();
+}
+
status_t AudioSystem::AudioFlingerClient::getInputBufferSize(
uint32_t sampleRate, audio_format_t format,
audio_channel_mask_t channelMask, size_t* buffSize) {
@@ -749,6 +773,31 @@
return NO_ERROR;
}
+status_t AudioSystem::AudioFlingerClient::addSupportedLatencyModesCallback(
+ const sp<SupportedLatencyModesCallback>& callback) {
+ Mutex::Autolock _l(mLock);
+ if (std::find(mSupportedLatencyModesCallbacks.begin(),
+ mSupportedLatencyModesCallbacks.end(),
+ callback) != mSupportedLatencyModesCallbacks.end()) {
+ return INVALID_OPERATION;
+ }
+ mSupportedLatencyModesCallbacks.push_back(callback);
+ return NO_ERROR;
+}
+
+status_t AudioSystem::AudioFlingerClient::removeSupportedLatencyModesCallback(
+ const sp<SupportedLatencyModesCallback>& callback) {
+ Mutex::Autolock _l(mLock);
+ auto it = std::find(mSupportedLatencyModesCallbacks.begin(),
+ mSupportedLatencyModesCallbacks.end(),
+ callback);
+ if (it == mSupportedLatencyModesCallbacks.end()) {
+ return INVALID_OPERATION;
+ }
+ mSupportedLatencyModesCallbacks.erase(it);
+ return NO_ERROR;
+}
+
/* static */ uintptr_t AudioSystem::addErrorCallback(audio_error_callback cb) {
Mutex::Autolock _l(gLockErrorCallbacks);
gAudioErrorCallbacks.insert(cb);
@@ -1662,6 +1711,24 @@
return afc->removeAudioDeviceCallback(callback, audioIo, portId);
}
+status_t AudioSystem::addSupportedLatencyModesCallback(
+ const sp<SupportedLatencyModesCallback>& callback) {
+ const sp<AudioFlingerClient> afc = getAudioFlingerClient();
+ if (afc == 0) {
+ return NO_INIT;
+ }
+ return afc->addSupportedLatencyModesCallback(callback);
+}
+
+status_t AudioSystem::removeSupportedLatencyModesCallback(
+ const sp<SupportedLatencyModesCallback>& callback) {
+ const sp<AudioFlingerClient> afc = getAudioFlingerClient();
+ if (afc == 0) {
+ return NO_INIT;
+ }
+ return afc->removeSupportedLatencyModesCallback(callback);
+}
+
audio_port_handle_t AudioSystem::getDeviceIdForIo(audio_io_handle_t audioIo) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
@@ -2338,6 +2405,24 @@
return NO_ERROR;
}
+status_t AudioSystem::setRequestedLatencyMode(
+ audio_io_handle_t output, audio_latency_mode_t mode) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == nullptr) {
+ return PERMISSION_DENIED;
+ }
+ return af->setRequestedLatencyMode(output, mode);
+}
+
+status_t AudioSystem::getSupportedLatencyModes(audio_io_handle_t output,
+ std::vector<audio_latency_mode_t>* modes) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == nullptr) {
+ return PERMISSION_DENIED;
+ }
+ return af->getSupportedLatencyModes(output, modes);
+}
+
class CaptureStateListenerImpl : public media::BnCaptureStateListener,
public IBinder::DeathRecipient {
public:
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index ffbb32f..7efcc6b 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -29,6 +29,7 @@
#include <audio_utils/clock.h>
#include <audio_utils/primitives.h>
#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
#include <media/AudioTrack.h>
#include <utils/Log.h>
#include <private/media/AudioTrackShared.h>
@@ -42,7 +43,9 @@
#define WAIT_PERIOD_MS 10
#define WAIT_STREAM_END_TIMEOUT_SEC 120
+
static const int kMaxLoopCountNotifications = 32;
+static constexpr char kAudioServiceName[] = "audio";
using ::android::aidl_utils::statusTFromBinderStatus;
using ::android::base::StringPrintf;
@@ -450,7 +453,7 @@
std::string errorMessage;
// Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
ALOGV("%s(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
- "flags #%x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
+ "flags %#x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
__func__,
streamType, sampleRate, format, channelMask, frameCount, flags, notificationFrames,
sessionId, transferType, attributionSource.uid, attributionSource.pid);
@@ -1945,6 +1948,9 @@
}
mPortId = output.portId;
+ // notify the upper layers about the new portId
+ triggerPortIdUpdate_l();
+
// We retain a copy of the I/O handle, but don't own the reference
mOutput = output.outputId;
mRefreshRemaining = true;
@@ -3507,12 +3513,34 @@
if (mPlayerIId == playerIId) return;
mPlayerIId = playerIId;
+ triggerPortIdUpdate_l();
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETPLAYERIID)
.set(AMEDIAMETRICS_PROP_PLAYERIID, playerIId)
.record();
}
+void AudioTrack::triggerPortIdUpdate_l() {
+ if (mAudioManager == nullptr) {
+ // use checkService() to avoid blocking if audio service is not up yet
+ sp<IBinder> binder =
+ defaultServiceManager()->checkService(String16(kAudioServiceName));
+ if (binder == nullptr) {
+ ALOGE("%s(%d): binding to audio service failed.",
+ __func__,
+ mPlayerIId);
+ return;
+ }
+
+ mAudioManager = interface_cast<IAudioManager>(binder);
+ }
+
+ // first time when the track is created we do not have a valid piid
+ if (mPlayerIId != PLAYER_PIID_INVALID) {
+ mAudioManager->playerEvent(mPlayerIId, PLAYER_UPDATE_PORT_ID, mPortId);
+ }
+}
+
status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
{
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 292d92f..6ad97d1 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -810,6 +810,33 @@
return statusTFromBinderStatus(mDelegate->setDeviceConnectedState(aidlPort, connected));
}
+status_t AudioFlingerClientAdapter::setRequestedLatencyMode(
+ audio_io_handle_t output, audio_latency_mode_t mode) {
+ int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+ media::LatencyMode modeAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_latency_mode_t_LatencyMode(mode));
+ return statusTFromBinderStatus(mDelegate->setRequestedLatencyMode(outputAidl, modeAidl));
+}
+
+status_t AudioFlingerClientAdapter::getSupportedLatencyModes(
+ audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) {
+ if (modes == nullptr) {
+ return BAD_VALUE;
+ }
+
+ int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+ std::vector<media::LatencyMode> modesAidl;
+
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->getSupportedLatencyModes(outputAidl, &modesAidl)));
+
+ *modes = VALUE_OR_RETURN_STATUS(
+ convertContainer<std::vector<audio_latency_mode_t>>(modesAidl,
+ aidl2legacy_LatencyMode_audio_latency_mode_t));
+
+ return NO_ERROR;
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// AudioFlingerServerAdapter
AudioFlingerServerAdapter::AudioFlingerServerAdapter(
@@ -1304,4 +1331,28 @@
return Status::fromStatusT(mDelegate->setDeviceConnectedState(&portLegacy, connected));
}
+Status AudioFlingerServerAdapter::setRequestedLatencyMode(
+ int32_t output, media::LatencyMode modeAidl) {
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ audio_latency_mode_t modeLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_LatencyMode_audio_latency_mode_t(modeAidl));
+ return Status::fromStatusT(mDelegate->setRequestedLatencyMode(
+ outputLegacy, modeLegacy));
+}
+
+Status AudioFlingerServerAdapter::getSupportedLatencyModes(
+ int output, std::vector<media::LatencyMode>* _aidl_return) {
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ std::vector<audio_latency_mode_t> modesLegacy;
+
+ RETURN_BINDER_IF_ERROR(mDelegate->getSupportedLatencyModes(outputLegacy, &modesLegacy));
+
+ *_aidl_return = VALUE_OR_RETURN_BINDER(
+ convertContainer<std::vector<media::LatencyMode>>(
+ modesLegacy, legacy2aidl_audio_latency_mode_t_LatencyMode));
+ return Status::ok();
+}
+
} // namespace android
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
index 421c31c..a2bb024 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
@@ -18,6 +18,7 @@
import android.media.AudioIoConfigEvent;
import android.media.AudioIoDescriptor;
+import android.media.LatencyMode;
/**
* A callback interface for AudioFlinger.
@@ -27,4 +28,10 @@
interface IAudioFlingerClient {
oneway void ioConfigChanged(AudioIoConfigEvent event,
in AudioIoDescriptor ioDesc);
+ /**
+ * Called when the latency modes supported on a given output stream change.
+ * output is the I/O handle of the output stream for which the change is signalled.
+ * latencyModes is the new list of supported latency modes (See LatencyMode.aidl).
+ */
+ oneway void onSupportedLatencyModesChanged(int output, in LatencyMode[] latencyModes);
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 10da028..9b8a843 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -35,6 +35,7 @@
import android.media.IAudioFlingerClient;
import android.media.IAudioRecord;
import android.media.IAudioTrack;
+import android.media.LatencyMode;
import android.media.MicrophoneInfoData;
import android.media.RenderPosition;
import android.media.TrackSecondaryOutputInfo;
@@ -228,6 +229,23 @@
void setDeviceConnectedState(in AudioPort devicePort, boolean connected);
+ /**
+ * Requests a given latency mode (See LatencyMode.aidl) on an output stream.
+ * This can be used when some use case on a given mixer/stream can only be enabled
+ * if a specific latency mode is selected on the audio path below the HAL.
+ * For instance spatial audio with head tracking.
+ * output is the I/O handle of the output stream for which the request is made.
+ * latencyMode is the requested latency mode.
+ */
+ void setRequestedLatencyMode(int output, LatencyMode latencyMode);
+
+ /**
+ * Queries the list of latency modes (See LatencyMode.aidl) supported by an output stream.
+ * output is the I/O handle of the output stream to which the query applies.
+ * returns the list of supported latency modes.
+ */
+ LatencyMode[] getSupportedLatencyModes(int output);
+
// When adding a new method, please review and update
// IAudioFlinger.h AudioFlingerServerAdapter::Delegate::TransactionCode
// AudioFlinger.cpp AudioFlinger::onTransactWrapper()
diff --git a/media/libaudioclient/aidl/android/media/LatencyMode.aidl b/media/libaudioclient/aidl/android/media/LatencyMode.aidl
new file mode 100644
index 0000000..0b2a72b
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/LatencyMode.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 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.
+ */
+
+package android.media;
+
+/**
+ * The latency mode currently used by the spatializer mixer.
+ * {@hide}
+ */
+@Backing(type="byte")
+enum LatencyMode {
+ /** No specific constraint on the latency */
+ FREE = 0,
+ /** A relatively low latency compatible with head tracking operation (e.g less than 100ms) */
+ LOW = 1,
+}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index e769303..1e66164 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -35,6 +35,7 @@
#include <android/media/AudioTimestampInternal.h>
#include <android/media/AudioUniqueIdUse.h>
#include <android/media/EffectDescriptor.h>
+#include <android/media/LatencyMode.h>
#include <android/media/TrackSecondaryOutputInfo.h>
#include <android/media/audio/common/AudioChannelLayout.h>
#include <android/media/audio/common/AudioConfig.h>
@@ -454,5 +455,9 @@
ConversionResult<audio_direct_mode_t> aidl2legacy_int32_t_audio_direct_mode_t_mask(int32_t aidl);
ConversionResult<int32_t> legacy2aidl_audio_direct_mode_t_int32_t_mask(audio_direct_mode_t legacy);
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl);
+ConversionResult<media::LatencyMode>
+legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy);
} // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 360b83d..9411f46 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -569,6 +569,12 @@
static status_t getDirectProfilesForAttributes(const audio_attributes_t* attr,
std::vector<audio_profile>* audioProfiles);
+ static status_t setRequestedLatencyMode(
+ audio_io_handle_t output, audio_latency_mode_t mode);
+
+ static status_t getSupportedLatencyModes(audio_io_handle_t output,
+ std::vector<audio_latency_mode_t>* modes);
+
// A listener for capture state changes.
class CaptureStateListener : public virtual RefBase {
public:
@@ -644,6 +650,22 @@
audio_io_handle_t audioIo,
audio_port_handle_t portId);
+ class SupportedLatencyModesCallback : public virtual RefBase
+ {
+ public:
+
+ SupportedLatencyModesCallback() = default;
+ virtual ~SupportedLatencyModesCallback() = default;
+
+ virtual void onSupportedLatencyModesChanged(
+ audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) = 0;
+ };
+
+ static status_t addSupportedLatencyModesCallback(
+ const sp<SupportedLatencyModesCallback>& callback);
+ static status_t removeSupportedLatencyModesCallback(
+ const sp<SupportedLatencyModesCallback>& callback);
+
static audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
static status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos);
@@ -682,6 +704,9 @@
media::AudioIoConfigEvent event,
const media::AudioIoDescriptor& ioDesc) override;
+ binder::Status onSupportedLatencyModesChanged(
+ int output, const std::vector<media::LatencyMode>& latencyModes) override;
+
status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
audio_io_handle_t audioIo,
audio_port_handle_t portId);
@@ -689,6 +714,11 @@
audio_io_handle_t audioIo,
audio_port_handle_t portId);
+ status_t addSupportedLatencyModesCallback(
+ const sp<SupportedLatencyModesCallback>& callback);
+ status_t removeSupportedLatencyModesCallback(
+ const sp<SupportedLatencyModesCallback>& callback);
+
audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
private:
@@ -697,6 +727,10 @@
std::map<audio_io_handle_t, std::map<audio_port_handle_t, wp<AudioDeviceCallback>>>
mAudioDeviceCallbacks;
+
+ std::vector<wp<SupportedLatencyModesCallback>>
+ mSupportedLatencyModesCallbacks GUARDED_BY(mLock);
+
// cached values for recording getInputBufferSize() queries
size_t mInBuffSize; // zero indicates cache is invalid
uint32_t mInSamplingRate;
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 32576c2..e873607 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_AUDIOTRACK_H
#define ANDROID_AUDIOTRACK_H
+#include <audiomanager/IAudioManager.h>
#include <binder/IMemory.h>
#include <cutils/sched_policy.h>
#include <media/AudioSystem.h>
@@ -1145,6 +1146,8 @@
void setAudioTrackCallback(const sp<media::IAudioTrackCallback>& callback) {
mAudioTrackCallback->setAudioTrackCallback(callback);
}
+ private:
+ void triggerPortIdUpdate_l();
protected:
/* copying audio tracks is not allowed */
@@ -1419,6 +1422,9 @@
*/
int mPlayerIId = -1; // AudioManager.h PLAYER_PIID_INVALID
+ /** Interface for interacting with the AudioService. */
+ sp<IAudioManager> mAudioManager;
+
/**
* mLogSessionId is a string identifying this AudioTrack for the metrics service.
* It may be unique or shared with other objects. An empty string means the
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 3c3715d..c891ae6 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -360,6 +360,13 @@
virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) = 0;
+
+ virtual status_t setRequestedLatencyMode(
+ audio_io_handle_t output, audio_latency_mode_t mode) = 0;
+
+ virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
+ std::vector<audio_latency_mode_t>* modes) = 0;
+
};
/**
@@ -462,6 +469,10 @@
int32_t getAAudioMixerBurstCount() override;
int32_t getAAudioHardwareBurstMinUsec() override;
status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) override;
+ status_t setRequestedLatencyMode(audio_io_handle_t output,
+ audio_latency_mode_t mode) override;
+ status_t getSupportedLatencyModes(
+ audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) override;
private:
const sp<media::IAudioFlingerService> mDelegate;
@@ -551,6 +562,8 @@
GET_AAUDIO_MIXER_BURST_COUNT = media::BnAudioFlingerService::TRANSACTION_getAAudioMixerBurstCount,
GET_AAUDIO_HARDWARE_BURST_MIN_USEC = media::BnAudioFlingerService::TRANSACTION_getAAudioHardwareBurstMinUsec,
SET_DEVICE_CONNECTED_STATE = media::BnAudioFlingerService::TRANSACTION_setDeviceConnectedState,
+ SET_REQUESTED_LATENCY_MODE = media::BnAudioFlingerService::TRANSACTION_setRequestedLatencyMode,
+ GET_SUPPORTED_LATENCY_MODES = media::BnAudioFlingerService::TRANSACTION_getSupportedLatencyModes,
};
protected:
@@ -672,7 +685,9 @@
Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
Status setDeviceConnectedState(const media::AudioPort& port, bool connected) override;
-
+ Status setRequestedLatencyMode(int output, media::LatencyMode mode) override;
+ Status getSupportedLatencyModes(int output,
+ std::vector<media::LatencyMode>* _aidl_return) override;
private:
const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
};
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index fdfe225..8743c04 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -93,13 +93,13 @@
}
status_t EffectHalHidl::process() {
- TIME_CHECK();
+ // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS));
}
status_t EffectHalHidl::processReverse() {
- TIME_CHECK();
+ // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE));
}
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 021ec51..76f9a60 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -441,7 +441,7 @@
#endif
status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
- TIME_CHECK();
+ // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
if (mStream == 0) return NO_INIT;
*written = 0;
@@ -587,7 +587,7 @@
}
status_t StreamOutHalHidl::getRenderPosition(uint32_t *dspFrames) {
- TIME_CHECK();
+ // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
if (mStream == 0) return NO_INIT;
Result retval;
Return<void> ret = mStream->getRenderPosition(
@@ -668,7 +668,7 @@
}
status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
- TIME_CHECK();
+ // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
if (mStream == 0) return NO_INIT;
if (mWriterClient == gettid() && mCommandMQ) {
return callWriterThread(
@@ -1012,7 +1012,7 @@
}
status_t StreamInHalHidl::read(void *buffer, size_t bytes, size_t *read) {
- TIME_CHECK();
+ // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
if (mStream == 0) return NO_INIT;
*read = 0;
@@ -1146,7 +1146,7 @@
}
status_t StreamInHalHidl::getCapturePosition(int64_t *frames, int64_t *time) {
- TIME_CHECK();
+ // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
if (mStream == 0) return NO_INIT;
if (mReaderClient == gettid() && mCommandMQ) {
ReadParameters params;
diff --git a/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp b/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp
index fa36ed9..e8ac480 100644
--- a/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp
+++ b/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp
@@ -69,18 +69,18 @@
* 0: 44100, 1: 48000, 2: 96000
* The second parameter indicates the duration in ms.
* 0: 2, 1: 5, 2: 10
- *-------------------------------------------------------------
- *Benchmark Time CPU Iterations
- *-------------------------------------------------------------
- *BM_SPATIALIZER/0/0 2108308 ns 2102841 ns 308
- *BM_SPATIALIZER/0/1 3779324 ns 3769180 ns 182
- *BM_SPATIALIZER/0/2 7283784 ns 7260581 ns 73
- *BM_SPATIALIZER/1/0 2256171 ns 2250618 ns 298
- *BM_SPATIALIZER/1/1 4085380 ns 4075370 ns 167
- *BM_SPATIALIZER/1/2 8005652 ns 7974261 ns 67
- *BM_SPATIALIZER/2/0 4294597 ns 4283184 ns 153
- *BM_SPATIALIZER/2/1 8141776 ns 8120468 ns 83
- *BM_SPATIALIZER/2/2 16450758 ns 16375285 ns 35
+ * -------------------------------------------------------------
+ * Benchmark Time CPU Iterations
+ * -------------------------------------------------------------
+ * BM_SPATIALIZER/0/0 739848 ns 738497 ns 934
+ * BM_SPATIALIZER/0/1 1250503 ns 1248337 ns 480
+ * BM_SPATIALIZER/0/2 2094092 ns 2090092 ns 310
+ * BM_SPATIALIZER/1/0 783114 ns 781626 ns 683
+ * BM_SPATIALIZER/1/1 1332951 ns 1330473 ns 452
+ * BM_SPATIALIZER/1/2 2258313 ns 2254022 ns 289
+ * BM_SPATIALIZER/2/0 1210332 ns 1207957 ns 477
+ * BM_SPATIALIZER/2/1 2356259 ns 2351764 ns 269
+ * BM_SPATIALIZER/2/2 4267814 ns 4259567 ns 155
*******************************************************************/
static void BM_SPATIALIZER(benchmark::State& state) {
diff --git a/media/libmedia/tests/codeclist/Android.bp b/media/libmedia/tests/codeclist/Android.bp
index 2ed3126..d4494f6 100644
--- a/media/libmedia/tests/codeclist/Android.bp
+++ b/media/libmedia/tests/codeclist/Android.bp
@@ -25,7 +25,7 @@
cc_test {
name: "CodecListTest",
- test_suites: ["device-tests", "mts"],
+ test_suites: ["device-tests", "mts-media"],
gtest: true,
// Support multilib variants (using different suffix per sub-architecture), which is needed on
diff --git a/media/libmediametrics/libmediametrics.map.txt b/media/libmediametrics/libmediametrics.map.txt
index c46281a..f37af64 100644
--- a/media/libmediametrics/libmediametrics.map.txt
+++ b/media/libmediametrics/libmediametrics.map.txt
@@ -1,29 +1,29 @@
LIBMEDIAMETRICS_1 {
global:
- mediametrics_addDouble; # apex
- mediametrics_addInt32; # apex
- mediametrics_addInt64; # apex
- mediametrics_addRate; # apex
- mediametrics_count; # apex
- mediametrics_create; # apex
- mediametrics_delete; # apex
- mediametrics_freeCString; # apex
- mediametrics_getAttributes; # apex
- mediametrics_getCString; # apex
- mediametrics_getDouble; # apex
- mediametrics_getInt32; # apex
- mediametrics_getInt64; # apex
- mediametrics_getKey; # apex
- mediametrics_getRate; # apex
- mediametrics_isEnabled; # apex
- mediametrics_readable; # apex
- mediametrics_selfRecord; # apex
- mediametrics_setCString; # apex
- mediametrics_setDouble; # apex
- mediametrics_setInt32; # apex
- mediametrics_setInt64; # apex
- mediametrics_setRate; # apex
- mediametrics_setUid; # apex
+ mediametrics_addDouble; # systemapi
+ mediametrics_addInt32; # systemapi
+ mediametrics_addInt64; # systemapi
+ mediametrics_addRate; # systemapi
+ mediametrics_count; # systemapi
+ mediametrics_create; # systemapi
+ mediametrics_delete; # systemapi
+ mediametrics_freeCString; # systemapi
+ mediametrics_getAttributes; # systemapi
+ mediametrics_getCString; # systemapi
+ mediametrics_getDouble; # systemapi
+ mediametrics_getInt32; # systemapi
+ mediametrics_getInt64; # systemapi
+ mediametrics_getKey; # systemapi
+ mediametrics_getRate; # systemapi
+ mediametrics_isEnabled; # systemapi
+ mediametrics_readable; # systemapi
+ mediametrics_selfRecord; # systemapi
+ mediametrics_setCString; # systemapi
+ mediametrics_setDouble; # systemapi
+ mediametrics_setInt32; # systemapi
+ mediametrics_setInt64; # systemapi
+ mediametrics_setRate; # systemapi
+ mediametrics_setUid; # systemapi
local:
*;
};
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 2828d44..45fac76 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -73,6 +73,10 @@
// is closed to allow the audio DSP to power down.
static const int64_t kOffloadPauseMaxUs = 10000000LL;
+// Additional delay after teardown before releasing the wake lock to allow time for the audio path
+// to be completely released
+static const int64_t kWakelockReleaseDelayUs = 2000000LL;
+
// Maximum allowed delay from AudioSink, 1.5 seconds.
static const int64_t kMaxAllowedAudioSinkDelayUs = 1500000LL;
@@ -793,6 +797,20 @@
}
ALOGV("Audio Offload tear down due to pause timeout.");
onAudioTearDown(kDueToTimeout);
+ sp<AMessage> newMsg = new AMessage(kWhatReleaseWakeLock, this);
+ newMsg->setInt32("drainGeneration", generation);
+ newMsg->post(kWakelockReleaseDelayUs);
+ break;
+ }
+
+ case kWhatReleaseWakeLock:
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("drainGeneration", &generation));
+ if (generation != mAudioOffloadPauseTimeoutGeneration) {
+ break;
+ }
+ ALOGV("releasing audio offload pause wakelock.");
mWakeLock->release();
break;
}
@@ -1785,6 +1803,8 @@
return;
}
+ startAudioOffloadPauseTimeout();
+
{
Mutex::Autolock autoLock(mLock);
// we do not increment audio drain generation so that we fill audio buffer during pause.
@@ -1799,7 +1819,6 @@
// Note: audio data may not have been decoded, and the AudioSink may not be opened.
mAudioSink->pause();
- startAudioOffloadPauseTimeout();
ALOGV("now paused audio queue has %zu entries, video has %zu entries",
mAudioQueue.size(), mVideoQueue.size());
@@ -1927,12 +1946,27 @@
int32_t numChannels;
CHECK(format->findInt32("channel-count", &numChannels));
- int32_t rawChannelMask;
- audio_channel_mask_t channelMask =
- format->findInt32("channel-mask", &rawChannelMask) ?
- static_cast<audio_channel_mask_t>(rawChannelMask)
- // signal to the AudioSink to derive the mask from count.
- : CHANNEL_MASK_USE_CHANNEL_ORDER;
+ // channel mask info as read from the audio format
+ int32_t channelMaskFromFormat;
+ // channel mask to use for native playback
+ audio_channel_mask_t channelMask;
+ if (format->findInt32("channel-mask", &channelMaskFromFormat)) {
+ // KEY_CHANNEL_MASK follows the android.media.AudioFormat java mask
+ // which is left-bitshifted by 2 relative to the native mask
+ if ((channelMaskFromFormat & 0b11) != 0) {
+ // received an unexpected mask (supposed to follow AudioFormat constants
+ // for output masks with the 2 least-significant bits at 0), but
+ // it may come from an extractor that uses native masks: keeping
+ // the mask as given is ok as it contains at least mono or stereo
+ // and potentially the haptic channels
+ channelMask = static_cast<audio_channel_mask_t>(channelMaskFromFormat);
+ } else {
+ channelMask = static_cast<audio_channel_mask_t>(channelMaskFromFormat >> 2);
+ }
+ } else {
+ // no mask found: the mask will be derived from the channel count
+ channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
+ }
int32_t sampleRate;
CHECK(format->findInt32("sample-rate", &sampleRate));
diff --git a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h
index 3d2b033..3640678 100644
--- a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h
@@ -100,6 +100,7 @@
kWhatMediaRenderingStart = 'mdrd',
kWhatAudioTearDown = 'adTD',
kWhatAudioOffloadPauseTimeout = 'aOPT',
+ kWhatReleaseWakeLock = 'adRL',
};
enum AudioTearDownReason {
diff --git a/media/libstagefright/renderfright/gl/ProgramCache.cpp b/media/libstagefright/renderfright/gl/ProgramCache.cpp
index 56d35a9..af55172 100644
--- a/media/libstagefright/renderfright/gl/ProgramCache.cpp
+++ b/media/libstagefright/renderfright/gl/ProgramCache.cpp
@@ -373,7 +373,11 @@
return color * slope;
} else if (nits < x1) {
// scale [x0, x1] to [y0, y1] linearly
- float slope = (y1 - y0) / (x1 - x0);
+ // Use highp since some compilers may do this
+ // operation as reciprocal multiplication with
+ // re-association that could exceed the range
+ // of mediump float.
+ highp float slope = (y1 - y0) / (x1 - x0);
nits = y0 + (nits - x0) * slope;
} else if (nits < x2) {
// scale [x1, x2] to [y1, y2] using Hermite interp
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index edddaa4..19f9549 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -26,7 +26,33 @@
],
}
-cc_binary {
+prebuilt_etc {
+ name: "mediaserver.zygote64_32.rc",
+ src: "mediaserver.zygote64_32.rc",
+ sub_dir: "init/hw",
+}
+
+prebuilt_etc {
+ name: "mediaserver.zygote64.rc",
+ src: "mediaserver.zygote64.rc",
+ sub_dir: "init/hw",
+}
+
+soong_config_module_type {
+ name: "mediaserver_cc_binary",
+ module_type: "cc_binary",
+ config_namespace: "ANDROID",
+ bool_variables: ["TARGET_DYNAMIC_64_32_MEDIASERVER"],
+ properties: [
+ "compile_multilib",
+ "init_rc",
+ "multilib.lib32.suffix",
+ "multilib.lib64.suffix",
+ "required",
+ ],
+}
+
+mediaserver_cc_binary {
name: "mediaserver",
srcs: ["main_mediaserver.cpp"],
@@ -55,12 +81,32 @@
// ****************************************************************
compile_multilib: "prefer32",
- init_rc: ["mediaserver.rc"],
-
cflags: [
"-Werror",
"-Wall",
],
vintf_fragments: ["manifest_media_c2_software.xml"],
+
+ soong_config_variables: {
+ TARGET_DYNAMIC_64_32_MEDIASERVER: {
+ compile_multilib: "both",
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
+ required: [
+ "mediaserver.zygote64_32.rc",
+ "mediaserver.zygote64.rc",
+ ],
+ init_rc: ["mediaserver_dynamic.rc"],
+ conditions_default: {
+ init_rc: ["mediaserver.rc"],
+ },
+ },
+ },
}
diff --git a/media/mediaserver/mediaserver.zygote64.rc b/media/mediaserver/mediaserver.zygote64.rc
new file mode 100644
index 0000000..8842b01
--- /dev/null
+++ b/media/mediaserver/mediaserver.zygote64.rc
@@ -0,0 +1,6 @@
+service media /system/bin/mediaserver64
+ class main
+ user media
+ group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh HighPerformance
diff --git a/media/mediaserver/mediaserver.zygote64_32.rc b/media/mediaserver/mediaserver.zygote64_32.rc
new file mode 100644
index 0000000..4039073
--- /dev/null
+++ b/media/mediaserver/mediaserver.zygote64_32.rc
@@ -0,0 +1,6 @@
+service media /system/bin/mediaserver32
+ class main
+ user media
+ group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh HighPerformance
diff --git a/media/mediaserver/mediaserver_dynamic.rc b/media/mediaserver/mediaserver_dynamic.rc
new file mode 100644
index 0000000..65d5c40
--- /dev/null
+++ b/media/mediaserver/mediaserver_dynamic.rc
@@ -0,0 +1,4 @@
+on property:init.svc.media=*
+ setprop init.svc.mediadrm ${init.svc.media}
+
+import /system/etc/init/hw/mediaserver.${ro.zygote}.rc
diff --git a/media/mtp/tests/MtpFuzzer/Android.bp b/media/mtp/tests/MtpFuzzer/Android.bp
index 5365f4b..289b3ba 100644
--- a/media/mtp/tests/MtpFuzzer/Android.bp
+++ b/media/mtp/tests/MtpFuzzer/Android.bp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
@@ -6,29 +22,20 @@
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_av_media_mtp_license"],
}
-
-cc_fuzz {
- name: "mtp_fuzzer",
- srcs: [
- "mtp_fuzzer.cpp",
- "MtpMockDatabase.cpp",
- ],
+cc_defaults {
+ name: "mtp_fuzzer_defaults",
shared_libs: [
- "libmtp",
- "libbase",
- "liblog",
- "libutils",
+ "libbase",
+ "liblog",
+ "libutils",
],
+ static_libs: ["libc++fs",],
cflags: [
"-Wall",
"-Wextra",
"-Werror",
- "-DMTP_DEVICE",
"-Wno-unused-parameter",
],
- dictionary: "mtp_fuzzer.dict",
- corpus: ["corpus/*"],
-
fuzz_config: {
cc: ["jameswei@google.com"],
@@ -38,3 +45,15 @@
],
},
}
+cc_fuzz {
+ name: "mtp_fuzzer",
+ srcs: [
+ "mtp_fuzzer.cpp",
+ "MtpMockDatabase.cpp",
+ ],
+ cflags: ["-DMTP_DEVICE",],
+ shared_libs: ["libmtp",],
+ defaults: ["mtp_fuzzer_defaults"],
+ dictionary: "mtp_fuzzer.dict",
+ corpus: ["corpus/*"],
+}
diff --git a/media/mtp/tests/MtpFuzzer/README.md b/media/mtp/tests/MtpFuzzer/README.md
new file mode 100644
index 0000000..7c6ff7a
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/README.md
@@ -0,0 +1,24 @@
+# Fuzzers for libmtp
+
+## Table of contents
++ [mtp_fuzzer](#MtpServer)
+
+# <a name="MtpServer"></a> Fuzzer for MtpServer
+
+MtpServer supports the following parameters:
+1. PacketData (parameter name: "packetData")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`packetData`| `String` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mtp_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mtp_fuzzer/mtp_fuzzer corpus/ -dict=mtp_fuzzer.dict
+```
diff --git a/media/mtp/tests/MtpFuzzer/corpus/6-mtp-open_session_send_object_info.pkt b/media/mtp/tests/MtpFuzzer/corpus/6-mtp-open_session_send_object_info.pkt
new file mode 100644
index 0000000..71f2836
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/corpus/6-mtp-open_session_send_object_info.pkt
Binary files differ
diff --git a/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp
index f578462..e886816 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp
@@ -14,12 +14,15 @@
* limitations under the License.
*/
+#include <android-base/properties.h>
#include <android-base/unique_fd.h>
+#include <fuzzer/FuzzedDataProvider.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
-
+#include <filesystem>
+#include <fstream>
#include <string>
#define LOG_TAG "MtpFuzzer"
@@ -32,38 +35,40 @@
#include "MtpStorage.h"
#include "MtpUtils.h"
-const char* storage_desc = "Fuzz Storage";
+constexpr int32_t kMinFiles = 0;
+constexpr int32_t kMaxFiles = 5;
+constexpr int32_t kMaxBytes = 128;
+constexpr float kMinDataSizeFactor = 0.8;
// prefer tmpfs for file operations to avoid wearing out flash
const char* storage_path = "/storage/fuzzer/0";
-const char* source_database = "srcdb/";
+const char* source_database = "/data/local/tmp/srcdb/";
+const std::string test_path = std::string(source_database) + "TestDir/";
+const std::string kPropertyKey = "sys.fuse.transcode_mtp";
namespace android {
class MtpMockServer {
-public:
- std::unique_ptr<MtpMockHandle> mHandle;
- std::unique_ptr<MtpStorage> mStorage;
- std::unique_ptr<MtpMockDatabase> mDatabase;
- std::unique_ptr<MtpServer> mMtp;
- int mStorageId;
-
- MtpMockServer(const char* storage_path) : mStorageId(0) {
- bool ptp = false;
- const char* manu = "Google";
- const char* model = "Pixel 3XL";
- const char* version = "1.0";
- const char* serial = "ABDEF1231";
-
+ public:
+ MtpMockServer(const uint8_t* data, size_t size) : mFdp(data, size) {
// This is unused in our harness
int controlFd = -1;
mHandle = std::make_unique<MtpMockHandle>();
- mStorage = std::make_unique<MtpStorage>(mStorageId, storage_path, storage_desc, true,
- 0x200000000L);
+ mStorage = std::make_unique<MtpStorage>(
+ mFdp.ConsumeIntegral<uint32_t>() /* storageId */, storage_path,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* descriptor */,
+ mFdp.ConsumeBool() /* removable */,
+ mFdp.ConsumeIntegral<uint64_t>() /* maxFileSize */);
mDatabase = std::make_unique<MtpMockDatabase>();
mDatabase->addStorage(mStorage.get());
- mMtp = std::make_unique<MtpServer>(mDatabase.get(), controlFd, ptp, manu, model, version,
- serial);
+ init(data, size);
+
+ mMtp = std::make_unique<MtpServer>(
+ mDatabase.get(), controlFd, mFdp.ConsumeBool() /* ptp */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* manu */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* model */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* version */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* serial */);
mMtp->addStorage(mStorage.get());
// clear the old handle first, so we don't leak memory
@@ -71,7 +76,76 @@
mMtp->mHandle = mHandle.get();
}
- void run() { mMtp->run(); }
+ void process() {
+ if (mFdp.ConsumeBool()) {
+ createDatabaseFromSourceDir(source_database, storage_path, MTP_PARENT_ROOT);
+ }
+
+ while (mFdp.remaining_bytes()) {
+ MtpStorage storage(mFdp.ConsumeIntegral<uint32_t>() /* id */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* filePath */,
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* description */,
+ mFdp.ConsumeBool() /* removable */,
+ mFdp.ConsumeIntegral<uint64_t>() /* maxFileSize */);
+
+ auto invokeMtpServerAPI = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() { mMtp->run(); },
+ [&]() { mMtp->sendObjectAdded(mFdp.ConsumeIntegral<uint32_t>()); },
+ [&]() { mMtp->sendObjectRemoved(mFdp.ConsumeIntegral<uint32_t>()); },
+ [&]() { mMtp->sendObjectInfoChanged(mFdp.ConsumeIntegral<uint32_t>()); },
+ [&]() { mMtp->sendDevicePropertyChanged(mFdp.ConsumeIntegral<uint16_t>()); },
+ [&]() { mMtp->addStorage(&storage); },
+ [&]() { mMtp->removeStorage(&storage); },
+ });
+
+ invokeMtpServerAPI();
+ }
+
+ std::filesystem::remove_all(source_database);
+ }
+
+ private:
+ void createFiles(std::string path, size_t fileCount) {
+ std::ofstream file;
+ for (size_t idx = 0; idx < fileCount; ++idx) {
+ file.open(path.append(std::to_string(idx)));
+ file.close();
+ }
+ }
+
+ void addPackets(const uint8_t* data, size_t size) {
+ size_t off = 0;
+ for (size_t i = 0; i < size; ++i) {
+ // A longer delimiter could be used, but this worked in practice
+ if (data[i] == '@') {
+ size_t pktsz = i - off;
+ if (pktsz > 0) {
+ packet_t pkt = packet_t((unsigned char*)data + off, (unsigned char*)data + i);
+ // insert into packet buffer
+ mHandle->add_packet(pkt);
+ off = i;
+ }
+ }
+ }
+ }
+
+ void init(const uint8_t* data, size_t size) {
+ std::vector<uint8_t> packetData = mFdp.ConsumeBytes<uint8_t>(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinDataSizeFactor * size, size));
+
+ // Packetize the input stream
+ addPackets(packetData.data(), packetData.size());
+
+ // Setting the property to true/false to randomly fuzz the PoC depended on it
+ base::SetProperty(kPropertyKey, mFdp.ConsumeBool() ? "true" : "false");
+
+ std::filesystem::create_directories(source_database);
+ if (mFdp.ConsumeBool()) {
+ std::filesystem::create_directories(test_path);
+ createFiles(test_path, mFdp.ConsumeIntegralInRange<size_t>(kMinFiles, kMaxFiles));
+ }
+ createFiles(source_database, mFdp.ConsumeIntegralInRange<size_t>(kMinFiles, kMaxFiles));
+ }
int createDatabaseFromSourceDir(const char* fromPath, const char* toPath,
MtpObjectHandle parentHandle) {
@@ -130,8 +204,14 @@
closedir(dir);
return ret;
}
+
+ FuzzedDataProvider mFdp;
+ std::unique_ptr<MtpMockHandle> mHandle;
+ std::unique_ptr<MtpStorage> mStorage;
+ std::unique_ptr<MtpMockDatabase> mDatabase;
+ std::unique_ptr<MtpServer> mMtp;
};
-}; // namespace android
+}; // namespace android
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) __attribute__((optnone)) {
// reset our storage (from MtpUtils.h)
@@ -140,26 +220,9 @@
android::makeFolder(storage_path);
std::unique_ptr<android::MtpMockServer> mtp =
- std::make_unique<android::MtpMockServer>(storage_path);
+ std::make_unique<android::MtpMockServer>(data, size);
+ mtp->process();
- size_t off = 0;
-
- // Packetize the input stream
- for (size_t i = 0; i < size; i++) {
- // A longer delimiter could be used, but this worked in practice
- if (data[i] == '@') {
- size_t pktsz = i - off;
- if (pktsz > 0) {
- packet_t pkt = packet_t((unsigned char*)data + off, (unsigned char*)data + i);
- // insert into packet buffer
- mtp->mHandle->add_packet(pkt);
- off = i;
- }
- }
- }
-
- mtp->createDatabaseFromSourceDir(source_database, storage_path, MTP_PARENT_ROOT);
- mtp->run();
-
+ std::filesystem::remove_all("/storage/fuzzer");
return 0;
}
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index 59c1103..f4674de 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -183,7 +183,7 @@
AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
int32_t dataSize = data.size();
const uint8_t *dataPtr = data.data();
- if (dataSize > 0) {
+ if (dataSize >= 0) {
(*mEventListener)(mObj, &asid, ndkEventType, 0, dataPtr, dataSize);
} else {
ALOGE("invalid event data size=%d", dataSize);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 5fbb4ed..7a9027c 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -226,6 +226,9 @@
BINDER_METHOD_ENTRY(getAAudioMixerBurstCount) \
BINDER_METHOD_ENTRY(getAAudioHardwareBurstMinUsec) \
BINDER_METHOD_ENTRY(setDeviceConnectedState) \
+BINDER_METHOD_ENTRY(setRequestedLatencyMode) \
+BINDER_METHOD_ENTRY(getSupportedLatencyModes) \
+
// singleton for Binder Method Statistics for IAudioFlinger
static auto& getIAudioFlingerStatistics() {
@@ -1589,6 +1592,32 @@
return NO_ERROR;
}
+status_t AudioFlinger::setRequestedLatencyMode(
+ audio_io_handle_t output, audio_latency_mode_t mode) {
+ if (output == AUDIO_IO_HANDLE_NONE) {
+ return BAD_VALUE;
+ }
+ AutoMutex lock(mLock);
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+ if (thread == nullptr) {
+ return BAD_VALUE;
+ }
+ return thread->setRequestedLatencyMode(mode);
+}
+
+status_t AudioFlinger::getSupportedLatencyModes(audio_io_handle_t output,
+ std::vector<audio_latency_mode_t>* modes) {
+ if (output == AUDIO_IO_HANDLE_NONE) {
+ return BAD_VALUE;
+ }
+ AutoMutex lock(mLock);
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+ if (thread == nullptr) {
+ return BAD_VALUE;
+ }
+ return thread->getSupportedLatencyModes(modes);
+}
+
status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
{
// check calling permissions
@@ -2088,6 +2117,21 @@
}
}
+void AudioFlinger::onSupportedLatencyModesChanged(
+ audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
+ int32_t outputAidl = VALUE_OR_FATAL(legacy2aidl_audio_io_handle_t_int32_t(output));
+ std::vector<media::LatencyMode> modesAidl = VALUE_OR_FATAL(
+ convertContainer<std::vector<media::LatencyMode>>(modes,
+ legacy2aidl_audio_latency_mode_t_LatencyMode));
+
+ Mutex::Autolock _l(mClientLock);
+ size_t size = mNotificationClients.size();
+ for (size_t i = 0; i < size; i++) {
+ mNotificationClients.valueAt(i)->audioFlingerClient()
+ ->onSupportedLatencyModesChanged(outputAidl, modesAidl);
+ }
+}
+
// removeClient_l() must be called with AudioFlinger::mClientLock held
void AudioFlinger::removeClient_l(pid_t pid)
{
@@ -4482,6 +4526,8 @@
case TransactionCode::SET_RECORD_SILENCED:
case TransactionCode::AUDIO_POLICY_READY:
case TransactionCode::SET_DEVICE_CONNECTED_STATE:
+ case TransactionCode::SET_REQUESTED_LATENCY_MODE:
+ case TransactionCode::GET_SUPPORTED_LATENCY_MODES:
ALOGW("%s: transaction %d received from PID %d",
__func__, code, IPCThreadState::self()->getCallingPid());
// return status only for non void methods
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 8e4383c..fc4c807 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -293,6 +293,12 @@
virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected);
+ virtual status_t setRequestedLatencyMode(
+ audio_io_handle_t output, audio_latency_mode_t mode);
+
+ virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
+ std::vector<audio_latency_mode_t>* modes);
+
status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
const std::function<status_t()>& delegate) override;
@@ -764,6 +770,8 @@
void ioConfigChanged(audio_io_config_event_t event,
const sp<AudioIoDescriptor>& ioDesc,
pid_t pid = 0);
+ void onSupportedLatencyModesChanged(
+ audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes);
// Allocate an audio_unique_id_t.
// Specific types are audio_io_handle_t, audio_session_t, effect ID (int),
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 7ccf5a1..e127431 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -741,6 +741,12 @@
sendConfigEvent_l(configEvent);
}
+void AudioFlinger::ThreadBase::sendHalLatencyModesChangedEvent_l()
+{
+ sp<ConfigEvent> configEvent = sp<HalLatencyModesChangedEvent>::make();
+ sendConfigEvent_l(configEvent);
+}
+
// post condition: mConfigEvents.isEmpty()
void AudioFlinger::ThreadBase::processConfigEvents_l()
{
@@ -808,6 +814,10 @@
setCheckOutputStageEffects();
} break;
+ case CFG_EVENT_HAL_LATENCY_MODES_CHANGED: {
+ onHalLatencyModesChanged_l();
+ } break;
+
default:
ALOG_ASSERT(false, "processConfigEvents_l() unknown event type %d", event->mType);
break;
@@ -3919,6 +3929,8 @@
// stop(), pause(), etc.), but the threadLoop is entitled to call audio
// data / buffer methods on tracks from activeTracks without the ThreadBase lock.
activeTracks.insert(activeTracks.end(), mActiveTracks.begin(), mActiveTracks.end());
+
+ setHalLatencyMode_l();
} // mLock scope ends
if (mBytesRemaining == 0) {
@@ -4618,6 +4630,9 @@
if (configChanged) {
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -4648,6 +4663,9 @@
} else {
status = mOutput->stream->legacyReleaseAudioPatch();
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -5018,6 +5036,7 @@
mCallbackThread->setDraining(mDrainSequence);
}
mHwPaused = false;
+ setHalLatencyMode_l();
}
void AudioFlinger::PlaybackThread::onAddNewTrack_l()
@@ -7261,6 +7280,94 @@
{
}
+void AudioFlinger::SpatializerThread::onFirstRef() {
+ PlaybackThread::onFirstRef();
+
+ Mutex::Autolock _l(mLock);
+ status_t status = mOutput->stream->setLatencyModeCallback(this);
+ if (status != INVALID_OPERATION) {
+ updateHalSupportedLatencyModes_l();
+ }
+}
+
+status_t AudioFlinger::SpatializerThread::createAudioPatch_l(const struct audio_patch *patch,
+ audio_patch_handle_t *handle)
+{
+ status_t status = MixerThread::createAudioPatch_l(patch, handle);
+ updateHalSupportedLatencyModes_l();
+ return status;
+}
+
+void AudioFlinger::SpatializerThread::updateHalSupportedLatencyModes_l() {
+ std::vector<audio_latency_mode_t> latencyModes;
+ if (mOutput->stream->getRecommendedLatencyModes(&latencyModes) != NO_ERROR) {
+ latencyModes.clear();
+ }
+ if (latencyModes != mSupportedLatencyModes) {
+ mSupportedLatencyModes.swap(latencyModes);
+ sendHalLatencyModesChangedEvent_l();
+ }
+}
+
+void AudioFlinger::SpatializerThread::onHalLatencyModesChanged_l() {
+ mAudioFlinger->onSupportedLatencyModesChanged(mId, mSupportedLatencyModes);
+}
+
+void AudioFlinger::SpatializerThread::setHalLatencyMode_l() {
+ // if mSupportedLatencyModes is empty, the HAL stream does not support
+ // latency mode control and we can exit.
+ if (mSupportedLatencyModes.empty()) {
+ return;
+ }
+ audio_latency_mode_t latencyMode = AUDIO_LATENCY_MODE_FREE;
+ if (mSupportedLatencyModes.size() == 1) {
+ // If the HAL only support one latency mode currently, confirm the choice
+ latencyMode = mSupportedLatencyModes[0];
+ } else if (mSupportedLatencyModes.size() > 1) {
+ // Request low latency if:
+ // - The low latency mode is requested by the spatializer controller
+ // (mRequestedLatencyMode = AUDIO_LATENCY_MODE_LOW)
+ // AND
+ // - At least one active track is spatialized
+ bool hasSpatializedActiveTrack = false;
+ for (const auto& track : mActiveTracks) {
+ if (track->isSpatialized()) {
+ hasSpatializedActiveTrack = true;
+ break;
+ }
+ }
+ if (hasSpatializedActiveTrack && mRequestedLatencyMode == AUDIO_LATENCY_MODE_LOW) {
+ latencyMode = AUDIO_LATENCY_MODE_LOW;
+ }
+ }
+
+ if (latencyMode != mSetLatencyMode) {
+ status_t status = mOutput->stream->setLatencyMode(latencyMode);
+ if (status == NO_ERROR) {
+ mSetLatencyMode = latencyMode;
+ }
+ }
+}
+
+status_t AudioFlinger::SpatializerThread::setRequestedLatencyMode(audio_latency_mode_t mode) {
+ if (mode != AUDIO_LATENCY_MODE_LOW && mode != AUDIO_LATENCY_MODE_FREE) {
+ return BAD_VALUE;
+ }
+ Mutex::Autolock _l(mLock);
+ mRequestedLatencyMode = mode;
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::SpatializerThread::getSupportedLatencyModes(
+ std::vector<audio_latency_mode_t>* modes) {
+ if (modes == nullptr) {
+ return BAD_VALUE;
+ }
+ Mutex::Autolock _l(mLock);
+ *modes = mSupportedLatencyModes;
+ return NO_ERROR;
+}
+
void AudioFlinger::SpatializerThread::checkOutputStageEffects()
{
bool hasVirtualizer = false;
@@ -7313,6 +7420,14 @@
}
}
+void AudioFlinger::SpatializerThread::onRecommendedLatencyModeChanged(
+ std::vector<audio_latency_mode_t> modes) {
+ Mutex::Autolock _l(mLock);
+ if (modes != mSupportedLatencyModes) {
+ mSupportedLatencyModes.swap(modes);
+ sendHalLatencyModesChangedEvent_l();
+ }
+}
// ----------------------------------------------------------------------------
// Record
@@ -9162,6 +9277,9 @@
track->logEndInterval();
track->logBeginInterval(pathSourcesAsString);
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -9178,6 +9296,9 @@
} else {
status = mInput->stream->legacyReleaseAudioPatch();
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -9474,8 +9595,10 @@
return mHalStream->getMmapPosition(position);
}
-status_t AudioFlinger::MmapThread::exitStandby()
+status_t AudioFlinger::MmapThread::exitStandby_l()
{
+ // The HAL must receive track metadata before starting the stream
+ updateMetadata_l();
status_t ret = mHalStream->start();
if (ret != NO_ERROR) {
ALOGE("%s: error mHalStream->start() = %d for first track", __FUNCTION__, ret);
@@ -9501,13 +9624,10 @@
status_t ret;
+ // For the first track, reuse portId and session allocated when the stream was opened.
if (*handle == mPortId) {
- // For the first track, reuse portId and session allocated when the stream was opened.
- ret = exitStandby();
- if (ret == NO_ERROR) {
- acquireWakeLock();
- }
- return ret;
+ acquireWakeLock();
+ return NO_ERROR;
}
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
@@ -9609,7 +9729,6 @@
}
}
-
mActiveTracks.add(track);
sp<EffectChain> chain = getEffectChain_l(mSessionId);
if (chain != 0) {
@@ -9620,11 +9739,16 @@
track->logBeginInterval(patchSinksToString(&mPatch)); // log to MediaMetrics
*handle = portId;
+
+ if (mActiveTracks.size() == 1) {
+ ret = exitStandby_l();
+ }
+
broadcast_l();
- ALOGV("%s DONE handle %d stream %p", __FUNCTION__, *handle, mHalStream.get());
+ ALOGV("%s DONE status %d handle %d stream %p", __FUNCTION__, ret, *handle, mHalStream.get());
- return NO_ERROR;
+ return ret;
}
status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle)
@@ -9636,7 +9760,6 @@
}
if (handle == mPortId) {
- mHalStream->stop();
releaseWakeLock();
return NO_ERROR;
}
@@ -9673,6 +9796,10 @@
chain->decTrackCnt();
}
+ if (mActiveTracks.isEmpty()) {
+ mHalStream->stop();
+ }
+
broadcast_l();
return NO_ERROR;
@@ -9943,6 +10070,9 @@
mPatch = *patch;
mDeviceId = deviceId;
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -9962,6 +10092,9 @@
} else {
status = mHalStream->legacyReleaseAudioPatch();
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -10359,16 +10492,15 @@
mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
}
-status_t AudioFlinger::MmapCaptureThread::exitStandby()
+status_t AudioFlinger::MmapCaptureThread::exitStandby_l()
{
{
// mInput might have been cleared by clearInput()
- Mutex::Autolock _l(mLock);
if (mInput != nullptr && mInput->stream != nullptr) {
mInput->stream->setGain(1.0f);
}
}
- return MmapThread::exitStandby();
+ return MmapThread::exitStandby_l();
}
AudioFlinger::AudioStreamIn* AudioFlinger::MmapCaptureThread::clearInput()
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 074ae8f..fc37bd2 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -55,7 +55,8 @@
CFG_EVENT_RELEASE_AUDIO_PATCH,
CFG_EVENT_UPDATE_OUT_DEVICE,
CFG_EVENT_RESIZE_BUFFER,
- CFG_EVENT_CHECK_OUTPUT_STAGE_EFFECTS
+ CFG_EVENT_CHECK_OUTPUT_STAGE_EFFECTS,
+ CFG_EVENT_HAL_LATENCY_MODES_CHANGED,
};
class ConfigEventData: public RefBase {
@@ -282,6 +283,15 @@
virtual ~CheckOutputStageEffectsEvent() {}
};
+ class HalLatencyModesChangedEvent : public ConfigEvent {
+ public:
+ HalLatencyModesChangedEvent() :
+ ConfigEvent(CFG_EVENT_HAL_LATENCY_MODES_CHANGED) {
+ }
+
+ virtual ~HalLatencyModesChangedEvent() {}
+ };
+
class PMDeathRecipient : public IBinder::DeathRecipient {
public:
@@ -353,6 +363,7 @@
void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs);
void sendCheckOutputStageEffectsEvent();
void sendCheckOutputStageEffectsEvent_l();
+ void sendHalLatencyModesChangedEvent_l();
void processConfigEvents_l();
virtual void setCheckOutputStageEffects() {}
@@ -364,7 +375,7 @@
virtual void toAudioPortConfig(struct audio_port_config *config) = 0;
virtual void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs);
-
+ virtual void onHalLatencyModesChanged_l() {}
// see note at declaration of mStandby, mOutDevice and mInDevice
@@ -786,6 +797,11 @@
*/
bool readAndClearHasChanged();
+ /** Force updating track metadata to audio HAL stream next time
+ * readAndClearHasChanged() is called.
+ */
+ void setHasChanged() { mHasChanged = true; }
+
private:
void logTrack(const char *funcName, const sp<T> &track) const;
@@ -921,6 +937,8 @@
}
virtual void checkOutputStageEffects() {}
+ virtual void setHalLatencyMode_l() {}
+
void dumpInternals_l(int fd, const Vector<String16>& args) override;
void dumpTracks_l(int fd, const Vector<String16>& args) override;
@@ -1064,6 +1082,15 @@
bool hasMixer() const {
return mType == MIXER || mType == DUPLICATING || mType == SPATIALIZER;
}
+
+ virtual status_t setRequestedLatencyMode(
+ audio_latency_mode_t mode __unused) { return INVALID_OPERATION; }
+
+ virtual status_t getSupportedLatencyModes(
+ std::vector<audio_latency_mode_t>* modes __unused) {
+ return INVALID_OPERATION;
+ }
+
protected:
// updated by readOutputParameters_l()
size_t mNormalFrameCount; // normal mixer and effects
@@ -1682,7 +1709,8 @@
}
};
-class SpatializerThread : public MixerThread {
+class SpatializerThread : public MixerThread,
+ public StreamOutHalInterfaceLatencyModeCallback {
public:
SpatializerThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamOut* output,
@@ -1693,10 +1721,35 @@
bool hasFastMixer() const override { return false; }
+ status_t createAudioPatch_l(const struct audio_patch *patch,
+ audio_patch_handle_t *handle) override;
+
+ // RefBase
+ virtual void onFirstRef();
+
+ // StreamOutHalInterfaceLatencyModeCallback
+ void onRecommendedLatencyModeChanged(std::vector<audio_latency_mode_t> modes) override;
+
+ status_t setRequestedLatencyMode(audio_latency_mode_t mode) override;
+ status_t getSupportedLatencyModes(std::vector<audio_latency_mode_t>* modes) override;
+
protected:
void checkOutputStageEffects() override;
+ void onHalLatencyModesChanged_l() override;
+ void setHalLatencyMode_l() override;
private:
+ void updateHalSupportedLatencyModes_l();
+
+ // Support low latency mode by default as unless explicitly indicated by the audio HAL
+ // we assume the audio path is compatible with the head tracking latency requirements
+ std::vector<audio_latency_mode_t> mSupportedLatencyModes = {AUDIO_LATENCY_MODE_LOW};
+ // default to invalid value to force first update to the audio HAL
+ audio_latency_mode_t mSetLatencyMode =
+ (audio_latency_mode_t)AUDIO_LATENCY_MODE_INVALID;
+ // Do not request a specific mode by default
+ audio_latency_mode_t mRequestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
+
sp<EffectHandle> mFinalDownMixer;
};
@@ -2014,7 +2067,7 @@
virtual void threadLoop_exit();
virtual void threadLoop_standby();
virtual bool shouldStandby_l() { return false; }
- virtual status_t exitStandby();
+ virtual status_t exitStandby_l() REQUIRES(mLock);
virtual status_t initCheck() const { return (mHalStream == 0) ? NO_INIT : NO_ERROR; }
virtual size_t frameCount() const { return mFrameCount; }
@@ -2165,7 +2218,7 @@
AudioStreamIn* clearInput();
- status_t exitStandby() override;
+ status_t exitStandby_l() REQUIRES(mLock) override;
void updateMetadata_l() override;
void processVolume_l() override;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index c2a20c6..bb1699e 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -70,8 +70,9 @@
* @return OK if the request is valid
* otherwise if the request is not supported
*/
- status_t getOutputForAttr(const audio_attributes_t& attributes, uid_t uid,
- audio_output_flags_t flags,
+ status_t getOutputForAttr(const audio_attributes_t& attributes,
+ const audio_config_base_t& config,
+ uid_t uid, audio_output_flags_t flags,
sp<AudioPolicyMix> &primaryMix,
std::vector<sp<AudioPolicyMix>> *secondaryMixes);
@@ -126,6 +127,7 @@
enum class MixMatchStatus { MATCH, NO_MATCH, INVALID_MIX };
MixMatchStatus mixMatch(const AudioMix* mix, size_t mixIndex,
const audio_attributes_t& attributes,
+ const audio_config_base_t& config,
uid_t uid);
};
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 546f56b..551eab6 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -151,7 +151,7 @@
}
status_t AudioPolicyMixCollection::getOutputForAttr(
- const audio_attributes_t& attributes, uid_t uid,
+ const audio_attributes_t& attributes, const audio_config_base_t& config, uid_t uid,
audio_output_flags_t flags,
sp<AudioPolicyMix> &primaryMix,
std::vector<sp<AudioPolicyMix>> *secondaryMixes)
@@ -177,7 +177,7 @@
continue; // Primary output already found
}
- switch (mixMatch(policyMix.get(), i, attributes, uid)) {
+ switch (mixMatch(policyMix.get(), i, attributes, config, uid)) {
case MixMatchStatus::INVALID_MIX:
// The mix has contradictory rules, ignore it
// TODO: reject invalid mix at registration
@@ -202,7 +202,8 @@
}
AudioPolicyMixCollection::MixMatchStatus AudioPolicyMixCollection::mixMatch(
- const AudioMix* mix, size_t mixIndex, const audio_attributes_t& attributes, uid_t uid) {
+ const AudioMix* mix, size_t mixIndex, const audio_attributes_t& attributes,
+ const audio_config_base_t& config, uid_t uid) {
if (mix->mMixType == MIX_TYPE_PLAYERS) {
// Loopback render mixes are created from a public API and thus restricted
@@ -229,6 +230,14 @@
}
}
+ // Permit match only if requested format and mix format are PCM and can be format
+ // adapted by the mixer, or are the same (compressed) format.
+ if (!((audio_is_linear_pcm(config.format) && audio_is_linear_pcm(mix->mFormat.format)) ||
+ (config.format == mix->mFormat.format)) &&
+ config.format != AUDIO_CONFIG_BASE_INITIALIZER.format) {
+ return MixMatchStatus::NO_MATCH;
+ }
+
int userId = (int) multiuser_get_user_id(uid);
// TODO if adding more player rules (currently only 2), make rule handling "generic"
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index dbfb0c0..d67e6c4 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -198,6 +198,12 @@
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, }));
}
+ // If connected to a dock, never use the device speaker for calls
+ if (!availableOutputDevices.getDevicesFromTypes({AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET})
+ .isEmpty()) {
+ availableOutputDevices.remove(
+ availableOutputDevices.getDevicesFromTypes({AUDIO_DEVICE_OUT_SPEAKER}));
+ }
} break;
case STRATEGY_ACCESSIBILITY: {
// do not route accessibility prompts to a digital output currently configured with a
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 2c5a61f..dea329a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1165,7 +1165,12 @@
// otherwise, fallback to the dynamic policies, if none match, query the engine.
// Secondary outputs are always found by dynamic policies as the engine do not support them
sp<AudioPolicyMix> primaryMix;
- status = mPolicyMixes.getOutputForAttr(*resultAttr, uid, *flags, primaryMix, secondaryMixes);
+ const audio_config_base_t clientConfig = {.sample_rate = config->sample_rate,
+ .channel_mask = config->channel_mask,
+ .format = config->format,
+ };
+ status = mPolicyMixes.getOutputForAttr(*resultAttr, clientConfig, uid, *flags, primaryMix,
+ secondaryMixes);
if (status != OK) {
return status;
}
@@ -1174,10 +1179,9 @@
bool usePrimaryOutputFromPolicyMixes = requestedDevice == nullptr && primaryMix != nullptr;
// FIXME: in case of RENDER policy, the output capabilities should be checked
- if ((usePrimaryOutputFromPolicyMixes
- || (secondaryMixes != nullptr && !secondaryMixes->empty()))
- && !audio_is_linear_pcm(config->format)) {
- ALOGD("%s: rejecting request as dynamic audio policy only support pcm", __func__);
+ if ((secondaryMixes != nullptr && !secondaryMixes->empty())
+ && !audio_is_linear_pcm(config->format)) {
+ ALOGD("%s: rejecting request as secondary mixes only support pcm", __func__);
return BAD_VALUE;
}
if (usePrimaryOutputFromPolicyMixes) {
@@ -1186,19 +1190,27 @@
primaryMix->mDeviceAddress,
AUDIO_FORMAT_DEFAULT);
sp<SwAudioOutputDescriptor> policyDesc = primaryMix->getOutput();
- if (deviceDesc != nullptr
- && (policyDesc == nullptr || (policyDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT))) {
+ bool tryDirectForFlags = policyDesc == nullptr ||
+ (policyDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT);
+ // if a direct output can be opened to deliver the track's multi-channel content to the
+ // output rather than being downmixed by the primary output, then use this direct
+ // output by by-passing the primary mix if possible, otherwise fall-through to primary
+ // mix.
+ bool tryDirectForChannelMask = policyDesc != nullptr
+ && (audio_channel_count_from_out_mask(policyDesc->getConfig().channel_mask) <
+ audio_channel_count_from_out_mask(config->channel_mask));
+ if (deviceDesc != nullptr && (tryDirectForFlags || tryDirectForChannelMask)) {
audio_io_handle_t newOutput;
status = openDirectOutput(
*stream, session, config,
(audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT),
DeviceVector(deviceDesc), &newOutput);
- if (status != NO_ERROR) {
- policyDesc = nullptr;
- } else {
+ if (status == NO_ERROR) {
policyDesc = mOutputs.valueFor(newOutput);
primaryMix->setOutput(policyDesc);
- }
+ } else if (tryDirectForFlags) {
+ policyDesc = nullptr;
+ } // otherwise use primary if available.
}
if (policyDesc != nullptr) {
policyDesc->mPolicyMix = primaryMix;
@@ -4519,7 +4531,11 @@
audio_attributes_t resultAttr;
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = sourceDesc->config().sample_rate;
- config.channel_mask = sourceDesc->config().channel_mask;
+ audio_channel_mask_t sourceMask = sourceDesc->config().channel_mask;
+ config.channel_mask =
+ (audio_channel_mask_get_representation(sourceMask)
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX) ? sourceMask
+ : audio_channel_mask_in_to_out(sourceMask);
config.format = sourceDesc->config().format;
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
@@ -6318,8 +6334,8 @@
continue;
}
sp<AudioPolicyMix> primaryMix;
- status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->uid(),
- client->flags(), primaryMix, nullptr);
+ status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->config(),
+ client->uid(), client->flags(), primaryMix, nullptr);
if (status != OK) {
continue;
}
@@ -6431,8 +6447,8 @@
for (const sp<TrackClientDescriptor>& client : outputDescriptor->getClientIterable()) {
sp<AudioPolicyMix> primaryMix;
std::vector<sp<AudioPolicyMix>> secondaryMixes;
- status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->uid(),
- client->flags(), primaryMix, &secondaryMixes);
+ status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->config(),
+ client->uid(), client->flags(), primaryMix, &secondaryMixes);
std::vector<sp<SwAudioOutputDescriptor>> secondaryDescs;
for (auto &secondaryMix : secondaryMixes) {
sp<SwAudioOutputDescriptor> outputDesc = secondaryMix->getOutput();
@@ -6690,8 +6706,8 @@
// check dynamic policies but only for primary descriptors (secondary not used for audible
// audio routing, only used for duplication for playback capture)
sp<AudioPolicyMix> policyMix;
- status_t status = mPolicyMixes.getOutputForAttr(attr, 0 /*uid unknown here*/,
- AUDIO_OUTPUT_FLAG_NONE, policyMix, nullptr /* secondaryMixes */);
+ status_t status = mPolicyMixes.getOutputForAttr(attr, AUDIO_CONFIG_BASE_INITIALIZER,
+ 0 /*uid unknown here*/, AUDIO_OUTPUT_FLAG_NONE, policyMix, nullptr);
if (status != OK) {
return status;
}
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index e7d945f..691f13c 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -516,8 +516,6 @@
void AudioPolicyService::doOnCheckSpatializer()
{
- Mutex::Autolock _l(mLock);
-
ALOGI("%s mSpatializer %p level %d", __func__, mSpatializer.get(), (int)mSpatializer->getLevel());
if (mSpatializer != nullptr) {
@@ -527,6 +525,8 @@
audio_io_handle_t newOutput;
const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
audio_config_base_t config = mSpatializer->getAudioInConfig();
+
+ Mutex::Autolock _l(mLock);
status_t status =
mAudioPolicyManager->getSpatializerOutput(&config, &attr, &newOutput);
ALOGV("%s currentOutput %d newOutput %d channel_mask %#x",
@@ -538,21 +538,19 @@
mLock.unlock();
// It is OK to call detachOutput() is none is already attached.
mSpatializer->detachOutput();
- if (status != NO_ERROR || newOutput == AUDIO_IO_HANDLE_NONE) {
- mLock.lock();
- return;
+ if (status == NO_ERROR && newOutput != AUDIO_IO_HANDLE_NONE) {
+ status = mSpatializer->attachOutput(newOutput, numActiveTracks);
}
- status = mSpatializer->attachOutput(newOutput, numActiveTracks);
mLock.lock();
if (status != NO_ERROR) {
mAudioPolicyManager->releaseSpatializerOutput(newOutput);
}
} else if (mSpatializer->getLevel() == media::SpatializationLevel::NONE
&& mSpatializer->getOutput() != AUDIO_IO_HANDLE_NONE) {
- mLock.unlock();
audio_io_handle_t output = mSpatializer->detachOutput();
- mLock.lock();
+
if (output != AUDIO_IO_HANDLE_NONE) {
+ Mutex::Autolock _l(mLock);
mAudioPolicyManager->releaseSpatializerOutput(output);
}
}
@@ -581,19 +579,16 @@
void AudioPolicyService::doOnUpdateActiveSpatializerTracks()
{
- sp<Spatializer> spatializer;
+ if (mSpatializer == nullptr) {
+ return;
+ }
+ audio_io_handle_t output = mSpatializer->getOutput();
size_t activeClients;
{
Mutex::Autolock _l(mLock);
- if (mSpatializer == nullptr) {
- return;
- }
- spatializer = mSpatializer;
- activeClients = countActiveClientsOnOutput_l(mSpatializer->getOutput());
+ activeClients = countActiveClientsOnOutput_l(output);
}
- if (spatializer != nullptr) {
- spatializer->updateActiveTracks(activeClients);
- }
+ mSpatializer->updateActiveTracks(activeClients);
}
status_t AudioPolicyService::clientCreateAudioPatch(const struct audio_patch *patch,
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 3a08cf8..a87d871 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -1060,6 +1060,7 @@
CaptureStateNotifier mCaptureStateNotifier;
+ // created in onFirstRef() and never cleared: does not need to be guarded by mLock
sp<Spatializer> mSpatializer;
void *mLibraryHandle = nullptr;
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index a98d474..20c7a5d 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -84,6 +84,7 @@
kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
+ kWhatOnLatencyModesChanged, // Spatializer::onSupportedLatencyModesChanged
};
static constexpr const char *kNumFramesKey = "numFrames";
static constexpr const char *kModeKey = "mode";
@@ -93,15 +94,27 @@
static constexpr const char *kRotation0Key = "rotation0";
static constexpr const char *kRotation1Key = "rotation1";
static constexpr const char *kRotation2Key = "rotation2";
+ static constexpr const char *kLatencyModesKey = "latencyModes";
+
+ class LatencyModes : public RefBase {
+ public:
+ LatencyModes(audio_io_handle_t output,
+ const std::vector<audio_latency_mode_t>& latencyModes)
+ : mOutput(output), mLatencyModes(latencyModes) {}
+ ~LatencyModes() = default;
+
+ audio_io_handle_t mOutput;
+ std::vector<audio_latency_mode_t> mLatencyModes;
+ };
void onMessageReceived(const sp<AMessage> &msg) override {
+ sp<Spatializer> spatializer = mSpatializer.promote();
+ if (spatializer == nullptr) {
+ ALOGW("%s: Cannot promote spatializer", __func__);
+ return;
+ }
switch (msg->what()) {
case kWhatOnFramesProcessed: {
- sp<Spatializer> spatializer = mSpatializer.promote();
- if (spatializer == nullptr) {
- ALOGW("%s: Cannot promote spatializer", __func__);
- return;
- }
int numFrames;
if (!msg->findInt32(kNumFramesKey, &numFrames)) {
ALOGE("%s: Cannot find num frames!", __func__);
@@ -112,11 +125,6 @@
}
} break;
case kWhatOnHeadToStagePose: {
- sp<Spatializer> spatializer = mSpatializer.promote();
- if (spatializer == nullptr) {
- ALOGW("%s: Cannot promote spatializer", __func__);
- return;
- }
std::vector<float> headToStage(sHeadPoseKeys.size());
for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
@@ -127,18 +135,25 @@
spatializer->onHeadToStagePoseMsg(headToStage);
} break;
case kWhatOnActualModeChange: {
- sp<Spatializer> spatializer = mSpatializer.promote();
- if (spatializer == nullptr) {
- ALOGW("%s: Cannot promote spatializer", __func__);
- return;
- }
int mode;
- if (!msg->findInt32(EngineCallbackHandler::kModeKey, &mode)) {
+ if (!msg->findInt32(kModeKey, &mode)) {
ALOGE("%s: Cannot find actualMode!", __func__);
return;
}
spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
} break;
+
+ case kWhatOnLatencyModesChanged: {
+ sp<RefBase> object;
+ if (!msg->findObject(kLatencyModesKey, &object)) {
+ ALOGE("%s: Cannot find latency modes!", __func__);
+ return;
+ }
+ sp<LatencyModes> latencyModes = static_cast<LatencyModes*>(object.get());
+ spatializer->onSupportedLatencyModesChangedMsg(
+ latencyModes->mOutput, std::move(latencyModes->mLatencyModes));
+ } break;
+
default:
LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
}
@@ -714,7 +729,9 @@
mEngine->setEnabled(false);
mEngine.clear();
mPoseController.reset();
+ AudioSystem::removeSupportedLatencyModesCallback(this);
}
+
// create FX instance on output
AttributionSourceState attributionSource = AttributionSourceState();
mEngine = new AudioEffect(attributionSource);
@@ -731,6 +748,13 @@
outputChanged = mOutput != output;
mOutput = output;
mNumActiveTracks = numActiveTracks;
+ AudioSystem::addSupportedLatencyModesCallback(this);
+
+ std::vector<audio_latency_mode_t> latencyModes;
+ status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
+ if (status == OK) {
+ mSupportedLatencyModes = latencyModes;
+ }
checkEngineState_l();
if (mSupportsHeadTracking) {
@@ -760,6 +784,7 @@
// remove FX instance
mEngine->setEnabled(false);
mEngine.clear();
+ AudioSystem::removeSupportedLatencyModesCallback(this);
output = mOutput;
mOutput = AUDIO_IO_HANDLE_NONE;
mPoseController.reset();
@@ -772,6 +797,27 @@
return output;
}
+void Spatializer::onSupportedLatencyModesChanged(
+ audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
+ ALOGV("%s output %d num modes %zu", __func__, (int)output, modes.size());
+ sp<AMessage> msg =
+ new AMessage(EngineCallbackHandler::kWhatOnLatencyModesChanged, mHandler);
+ msg->setObject(EngineCallbackHandler::kLatencyModesKey,
+ sp<EngineCallbackHandler::LatencyModes>::make(output, modes));
+ msg->post();
+}
+
+void Spatializer::onSupportedLatencyModesChangedMsg(
+ audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
+ std::lock_guard lock(mLock);
+ ALOGV("%s output %d mOutput %d num modes %zu",
+ __func__, (int)output, (int)mOutput, modes.size());
+ if (output == mOutput) {
+ mSupportedLatencyModes = std::move(modes);
+ checkSensorsState_l();
+ }
+}
+
void Spatializer::updateActiveTracks(size_t numActiveTracks) {
std::lock_guard lock(mLock);
if (mNumActiveTracks != numActiveTracks) {
@@ -782,17 +828,25 @@
}
void Spatializer::checkSensorsState_l() {
+ audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
+ bool lowLatencySupported = mSupportedLatencyModes.empty()
+ || (std::find(mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
+ AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end());
if (mSupportsHeadTracking && mPoseController != nullptr) {
- if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
+ if (lowLatencySupported && mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
&& mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
&& mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
mPoseController->setHeadSensor(mHeadSensor);
mPoseController->setScreenSensor(mScreenSensor);
+ requestedLatencyMode = AUDIO_LATENCY_MODE_LOW;
} else {
mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
}
}
+ if (mOutput != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
+ }
}
void Spatializer::checkEngineState_l() {
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index ad45fa9..bc95fe4 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -86,7 +86,8 @@
class Spatializer : public media::BnSpatializer,
public AudioEffect::IAudioEffectCallback,
public IBinder::DeathRecipient,
- private SpatializerPoseController::Listener {
+ private SpatializerPoseController::Listener,
+ public virtual AudioSystem::SupportedLatencyModesCallback {
public:
static sp<Spatializer> create(SpatializerPolicyCallback *callback);
@@ -123,6 +124,10 @@
/** IBinder::DeathRecipient. Listen to the death of the INativeSpatializerCallback. */
virtual void binderDied(const wp<IBinder>& who);
+ /** SupportedLatencyModesCallback */
+ void onSupportedLatencyModesChanged(
+ audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) override;
+
/** Registers a INativeSpatializerCallback when a client is attached to this Spatializer
* by audio policy service.
*/
@@ -163,6 +168,8 @@
void onHeadToStagePoseMsg(const std::vector<float>& headToStage);
void onActualModeChangeMsg(media::HeadTrackingMode mode);
+ void onSupportedLatencyModesChangedMsg(
+ audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes);
static constexpr int kMaxEffectParamValues = 10;
/**
@@ -355,6 +362,7 @@
sp<EngineCallbackHandler> mHandler;
size_t mNumActiveTracks GUARDED_BY(mLock) = 0;
+ std::vector<audio_latency_mode_t> mSupportedLatencyModes GUARDED_BY(mLock);
static const std::vector<const char *> sHeadPoseKeys;
};
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index e5bd9bc..bb00c48 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -148,6 +148,8 @@
std::unique_ptr<AudioPolicyManagerTestClient> mClient;
std::unique_ptr<AudioPolicyTestManager> mManager;
+
+ const uint32_t k48000SamplingRate = 48000;
};
void AudioPolicyManagerTest::SetUp() {
@@ -414,11 +416,11 @@
AudioPolicyConfig& config = mManager->getConfig();
mMsdOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_BUS);
sp<AudioProfile> pcmOutputProfile = new AudioProfile(
- AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
+ AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
sp<AudioProfile> ac3OutputProfile = new AudioProfile(
- AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000);
+ AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, k48000SamplingRate);
sp<AudioProfile> iec958OutputProfile = new AudioProfile(
- AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_OUT_STEREO, 48000);
+ AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
mMsdOutputDevice->addAudioProfile(pcmOutputProfile);
mMsdOutputDevice->addAudioProfile(ac3OutputProfile);
mMsdOutputDevice->addAudioProfile(iec958OutputProfile);
@@ -473,7 +475,7 @@
// Add a profile with another encoding to the default device to test routing
// of streams that are not supported by MSD.
sp<AudioProfile> dtsOutputProfile = new AudioProfile(
- AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000);
+ AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, k48000SamplingRate);
config.getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile("encoded");
primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile);
@@ -491,7 +493,7 @@
// Add HDMI input device with IEC60958 profile for HDMI in -> MSD patching.
mHdmiInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_HDMI);
sp<AudioProfile> iec958InputProfile = new AudioProfile(
- AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_IN_STEREO, 48000);
+ AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate);
mHdmiInputDevice->addAudioProfile(iec958InputProfile);
config.addDevice(mHdmiInputDevice);
sp<InputProfile> hdmiInputProfile = new InputProfile("hdmi input");
@@ -556,8 +558,8 @@
TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- getOutputForAttr(&selectedDeviceId,
- AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
@@ -566,7 +568,7 @@
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
- AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
+ AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
@@ -574,13 +576,13 @@
TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- getOutputForAttr(&selectedDeviceId,
- AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
- AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
+ AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
@@ -588,8 +590,8 @@
TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrUnsupportedFormatBypassesMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- getOutputForAttr(&selectedDeviceId,
- AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
@@ -600,9 +602,8 @@
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
audio_port_handle_t portId;
- getOutputForAttr(&selectedDeviceId,
- AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
- nullptr /*output*/, &portId);
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, nullptr /*output*/, &portId);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
@@ -612,9 +613,8 @@
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
audio_port_handle_t portId;
- getOutputForAttr(&selectedDeviceId,
- AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
- nullptr /*output*/, &portId);
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, nullptr /*output*/, &portId);
ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
ASSERT_EQ(-static_cast<int>(mExpectedAudioPatchCount), patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
@@ -623,8 +623,8 @@
{
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- getOutputForAttr(&selectedDeviceId,
- AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
@@ -653,8 +653,8 @@
ASSERT_EQ(AUDIO_FORMAT_IEC60958, patch->mPatch.sinks[0].format);
ASSERT_EQ(AUDIO_CHANNEL_IN_STEREO, patch->mPatch.sources[0].channel_mask);
ASSERT_EQ(AUDIO_CHANNEL_OUT_STEREO, patch->mPatch.sinks[0].channel_mask);
- ASSERT_EQ(48000, patch->mPatch.sources[0].sample_rate);
- ASSERT_EQ(48000, patch->mPatch.sinks[0].sample_rate);
+ ASSERT_EQ(k48000SamplingRate, patch->mPatch.sources[0].sample_rate);
+ ASSERT_EQ(k48000SamplingRate, patch->mPatch.sinks[0].sample_rate);
ASSERT_EQ(1, patchCount.deltaFromSnapshot());
}
@@ -1020,7 +1020,7 @@
clearPolicyMix();
audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
- audioConfig.sample_rate = 48000;
+ audioConfig.sample_rate = k48000SamplingRate;
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
std::vector<PolicyMixTuple>());
@@ -1059,7 +1059,7 @@
audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
- audioConfig.sample_rate = 48000;
+ audioConfig.sample_rate = k48000SamplingRate;
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
std::vector<PolicyMixTuple>());
@@ -1297,7 +1297,7 @@
audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
- audioConfig.sample_rate = 48000;
+ audioConfig.sample_rate = k48000SamplingRate;
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
ASSERT_EQ(INVALID_OPERATION, ret);
@@ -1331,7 +1331,7 @@
audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
- audioConfig.sample_rate = 48000;
+ audioConfig.sample_rate = k48000SamplingRate;
status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig, mUsageRules);
ASSERT_EQ(NO_ERROR, ret);
@@ -1347,7 +1347,7 @@
std::string tags = "addr=" + mMixAddress;
strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
getInputForAttr(attr, mTracker->getRiid(), &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT,
- AUDIO_CHANNEL_IN_STEREO, 48000 /*sampleRate*/, AUDIO_INPUT_FLAG_NONE, &mPortId);
+ AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate, AUDIO_INPUT_FLAG_NONE, &mPortId);
ASSERT_EQ(NO_ERROR, mManager->startInput(mPortId));
ASSERT_EQ(extractionPort.id, selectedDeviceId);
@@ -1374,8 +1374,8 @@
audio_port_handle_t playbackRoutedPortId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&playbackRoutedPortId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
- 48000 /*sampleRate*/, AUDIO_OUTPUT_FLAG_NONE,
- nullptr /*output*/, nullptr /*portId*/, attr);
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_NONE, nullptr /*output*/, nullptr /*portId*/,
+ attr);
if (std::find_if(begin(mUsageRules), end(mUsageRules), [&usage](const auto &usageRule) {
return (std::get<0>(usageRule) == usage) &&
(std::get<2>(usageRule) == RULE_MATCH_ATTRIBUTE_USAGE);}) != end(mUsageRules) ||
@@ -1517,7 +1517,7 @@
audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
audioConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
- audioConfig.sample_rate = 48000;
+ audioConfig.sample_rate = k48000SamplingRate;
status_t ret = addPolicyMix(MIX_TYPE_RECORDERS, MIX_ROUTE_FLAG_LOOP_BACK,
AUDIO_DEVICE_IN_REMOTE_SUBMIX, mMixAddress, audioConfig, mSourceRules);
ASSERT_EQ(NO_ERROR, ret);
@@ -1533,7 +1533,7 @@
std::string tags = std::string("addr=") + mMixAddress;
strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
- 48000 /*sampleRate*/, AUDIO_OUTPUT_FLAG_NONE, nullptr /*output*/, &mPortId, attr);
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_NONE, nullptr /*output*/, &mPortId, attr);
ASSERT_EQ(NO_ERROR, mManager->startOutput(mPortId));
ASSERT_EQ(injectionPort.id, getDeviceIdFromPatch(mClient->getLastAddedPatch()));
@@ -1561,7 +1561,7 @@
audio_port_handle_t captureRoutedPortId = AUDIO_PORT_HANDLE_NONE;
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
getInputForAttr(attr, mTracker->getRiid(), &captureRoutedPortId, AUDIO_FORMAT_PCM_16_BIT,
- AUDIO_CHANNEL_IN_STEREO, 48000 /*sampleRate*/, AUDIO_INPUT_FLAG_NONE, &portId);
+ AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate, AUDIO_INPUT_FLAG_NONE, &portId);
if (std::find_if(begin(mSourceRules), end(mSourceRules), [&source](const auto &sourceRule) {
return (std::get<1>(sourceRule) == source) &&
(std::get<2>(sourceRule) == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET);})
@@ -1711,11 +1711,11 @@
// Try start input or output according to the device type
if (audio_is_output_devices(type)) {
getOutputForAttr(&routedPortId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
- 48000 /*sampleRate*/, AUDIO_OUTPUT_FLAG_NONE);
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_NONE);
} else if (audio_is_input_device(type)) {
RecordingActivityTracker tracker;
getInputForAttr({}, tracker.getRiid(), &routedPortId, AUDIO_FORMAT_PCM_16_BIT,
- AUDIO_CHANNEL_IN_STEREO, 48000 /*sampleRate*/, AUDIO_INPUT_FLAG_NONE);
+ AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate, AUDIO_INPUT_FLAG_NONE);
}
ASSERT_EQ(devicePort.id, routedPortId);
@@ -1778,6 +1778,57 @@
)
);
+class AudioPolicyManagerCarTest : public AudioPolicyManagerTestDynamicPolicy {
+protected:
+ std::string getConfigFile() override { return sCarConfig; }
+
+ static const std::string sCarConfig;
+};
+
+const std::string AudioPolicyManagerCarTest::sCarConfig =
+ AudioPolicyManagerCarTest::sExecutableDir + "test_car_ap_atmos_offload_configuration.xml";
+
+TEST_F(AudioPolicyManagerCarTest, InitSuccess) {
+ // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerCarTest, Dump) {
+ dumpToLog();
+}
+
+TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrAtmosOutputAfterRegisteringPolicyMix) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ const std::string kTestBusMediaOutput = "bus0_media_out";
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, kTestBusMediaOutput, audioConfig, std::vector<PolicyMixTuple>());
+ ASSERT_EQ(NO_ERROR, ret);
+
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_E_AC3_JOC, AUDIO_CHANNEL_OUT_5POINT1,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId);
+ ASSERT_NE(AUDIO_PORT_HANDLE_NONE, selectedDeviceId);
+ sp<SwAudioOutputDescriptor> outDesc = mManager->getOutputs().valueFor(output);
+ ASSERT_NE(nullptr, outDesc.get());
+ ASSERT_EQ(AUDIO_FORMAT_E_AC3_JOC, outDesc->getFormat());
+ ASSERT_EQ(AUDIO_CHANNEL_OUT_5POINT1, outDesc->getChannelMask());
+ ASSERT_EQ(k48000SamplingRate, outDesc->getSamplingRate());
+
+ selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ output = AUDIO_IO_HANDLE_NONE;
+ portId = AUDIO_PORT_HANDLE_NONE;
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_7POINT1POINT4,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId);
+ ASSERT_NE(AUDIO_PORT_HANDLE_NONE, selectedDeviceId);
+ outDesc = mManager->getOutputs().valueFor(output);
+ ASSERT_NE(nullptr, outDesc.get());
+ ASSERT_EQ(AUDIO_FORMAT_PCM_16_BIT, outDesc->getFormat());
+ ASSERT_EQ(AUDIO_CHANNEL_OUT_7POINT1POINT4, outDesc->getChannelMask());
+ ASSERT_EQ(k48000SamplingRate, outDesc->getSamplingRate());
+}
+
class AudioPolicyManagerTVTest : public AudioPolicyManagerTestWithConfigurationFile {
protected:
std::string getConfigFile() override { return sTvConfig; }
@@ -1798,8 +1849,8 @@
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
audio_io_handle_t output;
audio_port_handle_t portId;
- getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000,
- flags, &output, &portId);
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, flags, &output, &portId);
sp<SwAudioOutputDescriptor> outDesc = mManager->getOutputs().valueFor(output);
ASSERT_NE(nullptr, outDesc.get());
audio_port_v7 port = {};
diff --git a/services/audiopolicy/tests/resources/Android.bp b/services/audiopolicy/tests/resources/Android.bp
index ff4d568..5e71210 100644
--- a/services/audiopolicy/tests/resources/Android.bp
+++ b/services/audiopolicy/tests/resources/Android.bp
@@ -12,6 +12,7 @@
srcs: [
"test_audio_policy_configuration.xml",
"test_audio_policy_primary_only_configuration.xml",
+ "test_car_ap_atmos_offload_configuration.xml",
"test_invalid_audio_policy_configuration.xml",
"test_tv_apm_configuration.xml",
"test_settop_box_surround_configuration.xml",
diff --git a/services/audiopolicy/tests/resources/test_car_ap_atmos_offload_configuration.xml b/services/audiopolicy/tests/resources/test_car_ap_atmos_offload_configuration.xml
new file mode 100644
index 0000000..d131ed8
--- /dev/null
+++ b/services/audiopolicy/tests/resources/test_car_ap_atmos_offload_configuration.xml
@@ -0,0 +1,308 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <globalConfiguration speaker_drc_enabled="true"/>
+
+ <modules>
+ <!-- Primary Audio HAL -->
+ <module name="primary" halVersion="3.0">
+ <attachedDevices>
+ <!-- One bus per context -->
+ <item>bus0_media_out</item>
+ <item>bus1_navigation_out</item>
+ <item>bus2_voice_command_out</item>
+ <item>bus3_call_ring_out</item>
+ <item>bus4_call_out</item>
+ <item>bus5_alarm_out</item>
+ <item>bus6_notification_out</item>
+ <item>bus7_system_sound_out</item>
+ <!-- names with _audio_zone_# are used for defined an emulator rear seat audio zone
+ where each number # is the zone id number -->
+ <item>bus100_audio_zone_1</item>
+ <item>bus200_audio_zone_2</item>
+ <item>Built-In Mic</item>
+ <item>Built-In Back Mic</item>
+ <item>Echo-Reference Mic</item>
+ <item>FM Tuner</item>
+ <item>Tone Generator 0</item>
+ <item>Tone Generator 1</item>
+ </attachedDevices>
+ <defaultOutputDevice>bus0_media_out</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="mixport_bus0_media_out" role="source"
+ flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bus0_media_out_atmos" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name="" format="AUDIO_FORMAT_E_AC3_JOC"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1"/>
+ </mixPort>
+ <mixPort name="mixport_bus0_media_out_atmos_pcm" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_7POINT1POINT4"/>
+ </mixPort>
+ <mixPort name="mixport_bus1_navigation_out" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bus2_voice_command_out" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bus3_call_ring_out" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bus4_call_out" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bus5_alarm_out" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bus6_notification_out" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bus7_system_sound_out" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bus100_audio_zone_1" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bus200_audio_zone_2" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="primary input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </mixPort>
+ <mixPort name="mixport_tuner0" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_input_bus_tone_zone_0" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_input_bus_tone_zone_1" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
+ address="bus0_media_out">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <profile name="" format="AUDIO_FORMAT_E_AC3_JOC"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_7POINT1POINT4"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="bus1_navigation_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
+ address="bus1_navigation_out">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="bus2_voice_command_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
+ address="bus2_voice_command_out">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="bus3_call_ring_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
+ address="bus3_call_ring_out">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="bus4_call_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
+ address="bus4_call_out">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="bus5_alarm_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
+ address="bus5_alarm_out">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="bus6_notification_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
+ address="bus6_notification_out">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="bus7_system_sound_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
+ address="bus7_system_sound_out">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="bus100_audio_zone_1" role="sink" type="AUDIO_DEVICE_OUT_BUS"
+ address="bus100_audio_zone_1">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="bus200_audio_zone_2" role="sink" type="AUDIO_DEVICE_OUT_BUS"
+ address="bus200_audio_zone_2">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC"
+ role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Echo-Reference Mic" type="AUDIO_DEVICE_IN_ECHO_REFERENCE"
+ role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="FM Tuner" type="AUDIO_DEVICE_IN_FM_TUNER" role="source"
+ address="tuner0">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="Tone Generator 0" type="AUDIO_DEVICE_IN_BUS" role="source"
+ address="input_bus_tone_zone_0">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="Tone Generator 1" type="AUDIO_DEVICE_IN_BUS" role="source"
+ address="input_bus_tone_zone_1">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ </devicePorts>
+ <!-- route declaration, i.e. list all available sources for a given sink -->
+ <routes>
+ <route type="mix" sink="bus0_media_out"
+ sources="mixport_bus0_media_out,mixport_bus0_media_out_atmos,mixport_bus0_media_out_atmos_pcm"/>
+ <route type="mix" sink="bus1_navigation_out" sources="mixport_bus1_navigation_out"/>
+ <route type="mix" sink="bus2_voice_command_out"
+ sources="mixport_bus2_voice_command_out"/>
+ <route type="mix" sink="bus3_call_ring_out" sources="mixport_bus3_call_ring_out"/>
+ <route type="mix" sink="bus4_call_out" sources="mixport_bus4_call_out"/>
+ <route type="mix" sink="bus5_alarm_out" sources="mixport_bus5_alarm_out"/>
+ <route type="mix" sink="bus6_notification_out"
+ sources="mixport_bus6_notification_out"/>
+ <route type="mix" sink="bus7_system_sound_out"
+ sources="mixport_bus7_system_sound_out"/>
+ <route type="mix" sink="bus100_audio_zone_1" sources="mixport_bus100_audio_zone_1"/>
+ <route type="mix" sink="bus200_audio_zone_2" sources="mixport_bus200_audio_zone_2"/>
+ <route type="mix" sink="primary input"
+ sources="Built-In Mic,Built-In Back Mic,Echo-Reference Mic"/>
+ <route type="mix" sink="mixport_tuner0" sources="FM Tuner"/>
+ <route type="mix" sink="mixport_input_bus_tone_zone_0" sources="Tone Generator 0"/>
+ <route type="mix" sink="mixport_input_bus_tone_zone_1" sources="Tone Generator 1"/>
+ </routes>
+ </module>
+ </modules>
+</audioPolicyConfiguration>
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index 7dde268..ed490a8 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -127,7 +127,7 @@
size_t getUHRMaxJpegBufferSize(camera3::Size uhrMaxJpegSize,
camera3::Size defaultMaxJpegSize, size_t defaultMaxJpegBufferSize) {
- return (uhrMaxJpegSize.width * uhrMaxJpegSize.height) /
+ return ((float)(uhrMaxJpegSize.width * uhrMaxJpegSize.height)) /
(defaultMaxJpegSize.width * defaultMaxJpegSize.height) * defaultMaxJpegBufferSize;
}
diff --git a/services/camera/libcameraservice/utils/TagMonitor.cpp b/services/camera/libcameraservice/utils/TagMonitor.cpp
index 461f5e9..fe87ed6 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.cpp
+++ b/services/camera/libcameraservice/utils/TagMonitor.cpp
@@ -169,6 +169,22 @@
camera_metadata_entry lastEntry = lastValues.find(tag);
+ // Monitor when the stream ids change, this helps visually see what
+ // monitored metadata values are for capture requests with different
+ // stream ids.
+ if (source == REQUEST) {
+ if (inputStreamId != mLastInputStreamId) {
+ mMonitoringEvents.emplace(source, frameNumber, timestamp, camera_metadata_ro_entry_t{},
+ cameraId, std::unordered_set<int>(), inputStreamId);
+ mLastInputStreamId = inputStreamId;
+ }
+
+ if (outputStreamIds != mLastStreamIds) {
+ mMonitoringEvents.emplace(source, frameNumber, timestamp, camera_metadata_ro_entry_t{},
+ cameraId, outputStreamIds, -1);
+ mLastStreamIds = outputStreamIds;
+ }
+ }
if (entry.count > 0) {
bool isDifferent = false;
if (lastEntry.count > 0) {
@@ -190,22 +206,14 @@
// No last entry, so always consider to be different
isDifferent = true;
}
- // Also monitor when the stream ids change, this helps visually see what
- // monitored metadata values are for capture requests with different
- // stream ids.
- if (source == REQUEST &&
- (inputStreamId != mLastInputStreamId || outputStreamIds != mLastStreamIds)) {
- mLastInputStreamId = inputStreamId;
- mLastStreamIds = outputStreamIds;
- isDifferent = true;
- }
+
if (isDifferent) {
ALOGV("%s: Tag %s changed", __FUNCTION__,
get_local_camera_metadata_tag_name_vendor_id(
tag, mVendorTagId));
lastValues.update(entry);
mMonitoringEvents.emplace(source, frameNumber, timestamp, entry, cameraId,
- outputStreamIds, inputStreamId);
+ std::unordered_set<int>(), -1);
}
} else if (lastEntry.count > 0) {
// Value has been removed
@@ -219,8 +227,8 @@
entry.count = 0;
mLastInputStreamId = inputStreamId;
mLastStreamIds = outputStreamIds;
- mMonitoringEvents.emplace(source, frameNumber, timestamp, entry, cameraId, outputStreamIds,
- inputStreamId);
+ mMonitoringEvents.emplace(source, frameNumber, timestamp, entry, cameraId,
+ std::unordered_set<int>(), -1);
}
}
@@ -261,23 +269,39 @@
for (const auto& event : mMonitoringEvents) {
int indentation = (event.source == REQUEST) ? 15 : 30;
- String8 eventString = String8::format("f%d:%" PRId64 "ns:%*s%*s%s.%s: ",
+ String8 eventString = String8::format("f%d:%" PRId64 "ns:%*s%*s",
event.frameNumber, event.timestamp,
2, event.cameraId.c_str(),
indentation,
- event.source == REQUEST ? "REQ:" : "RES:",
+ event.source == REQUEST ? "REQ:" : "RES:");
+
+ if (!event.outputStreamIds.empty()) {
+ eventString += " output stream ids:";
+ for (const auto& id : event.outputStreamIds) {
+ eventString.appendFormat(" %d", id);
+ }
+ eventString += "\n";
+ vec.emplace_back(eventString.string());
+ continue;
+ }
+
+ if (event.inputStreamId != -1) {
+ eventString.appendFormat(" input stream id: %d\n", event.inputStreamId);
+ vec.emplace_back(eventString.string());
+ continue;
+ }
+
+ eventString += String8::format(
+ "%s.%s: ",
get_local_camera_metadata_section_name_vendor_id(event.tag, mVendorTagId),
get_local_camera_metadata_tag_name_vendor_id(event.tag, mVendorTagId));
- if (event.newData.size() == 0) {
- eventString += " (Removed)";
+
+ if (event.newData.empty()) {
+ eventString += " (Removed)\n";
} else {
- eventString += getEventDataString(event.newData.data(),
- event.tag,
- event.type,
- event.newData.size() / camera_metadata_type_size[event.type],
- indentation + 18,
- event.outputStreamIds,
- event.inputStreamId);
+ eventString += getEventDataString(
+ event.newData.data(), event.tag, event.type,
+ event.newData.size() / camera_metadata_type_size[event.type], indentation + 18);
}
vec.emplace_back(eventString.string());
}
@@ -285,13 +309,8 @@
#define CAMERA_METADATA_ENUM_STRING_MAX_SIZE 29
-String8 TagMonitor::getEventDataString(const uint8_t* data_ptr,
- uint32_t tag,
- int type,
- int count,
- int indentation,
- const std::unordered_set<int32_t>& outputStreamIds,
- int32_t inputStreamId) {
+String8 TagMonitor::getEventDataString(const uint8_t* data_ptr, uint32_t tag, int type, int count,
+ int indentation) {
static int values_per_line[NUM_TYPES] = {
[TYPE_BYTE] = 16,
[TYPE_INT32] = 8,
@@ -362,17 +381,7 @@
returnStr += "??? ";
}
}
- returnStr += "] ";
- if (!outputStreamIds.empty()) {
- returnStr += "output stream ids: ";
- for (const auto &id : outputStreamIds) {
- returnStr.appendFormat(" %d ", id);
- }
- }
- if (inputStreamId != -1) {
- returnStr.appendFormat("input stream id: %d", inputStreamId);
- }
- returnStr += "\n";
+ returnStr += "]\n";
}
return returnStr;
}
@@ -385,11 +394,12 @@
source(src),
frameNumber(frameNumber),
timestamp(timestamp),
+ cameraId(cameraId),
tag(value.tag),
type(value.type),
newData(value.data.u8, value.data.u8 + camera_metadata_type_size[value.type] * value.count),
- cameraId(cameraId), outputStreamIds(outputStreamIds), inputStreamId(inputStreamId) {
-}
+ outputStreamIds(outputStreamIds),
+ inputStreamId(inputStreamId) {}
TagMonitor::MonitorEvent::~MonitorEvent() {
}
diff --git a/services/camera/libcameraservice/utils/TagMonitor.h b/services/camera/libcameraservice/utils/TagMonitor.h
index 088d6fe..9ded15d 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.h
+++ b/services/camera/libcameraservice/utils/TagMonitor.h
@@ -85,12 +85,8 @@
// function.
void dumpMonitoredTagEventsToVectorLocked(std::vector<std::string> &out);
- static String8 getEventDataString(const uint8_t *data_ptr,
- uint32_t tag, int type,
- int count,
- int indentation,
- const std::unordered_set<int32_t> &outputStreamIds,
- int32_t inputStreamId);
+ static String8 getEventDataString(const uint8_t* data_ptr, uint32_t tag, int type, int count,
+ int indentation);
void monitorSingleMetadata(TagMonitor::eventSource source, int64_t frameNumber,
nsecs_t timestamp, const std::string& cameraId, uint32_t tag,
@@ -128,12 +124,15 @@
eventSource source;
uint32_t frameNumber;
nsecs_t timestamp;
+ std::string cameraId;
uint32_t tag;
uint8_t type;
std::vector<uint8_t> newData;
- std::string cameraId;
+ // NOTE: We want to print changes to outputStreamIds and inputStreamId in their own lines.
+ // So any MonitorEvent where these fields are not the default value will have garbage
+ // values for all fields other than source, frameNumber, timestamp, and cameraId.
std::unordered_set<int32_t> outputStreamIds;
- int32_t inputStreamId = 1;
+ int32_t inputStreamId = -1;
};
// A ring buffer for tracking the last kMaxMonitorEvents metadata changes
diff --git a/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h b/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
index b7215e6..6e5a5cf 100644
--- a/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
+++ b/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
@@ -50,7 +50,7 @@
*/
std::pair<std::string, int32_t> dump(int32_t lines = INT32_MAX) const;
- // align with message AudioUsageDataReported in frameworks/base/cmds/statsd/src/atoms.proto
+ // align with message AudioPowerUsageDataReported in frameworks/proto_logging/stats/atoms.proto
enum AudioType {
UNKNOWN_TYPE = 0,
VOICE_CALL_TYPE = 1, // voice call