Merge "Remove some usage of IGBPs in the ICamera." into main
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 34ff367..e9b757b 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -30,10 +30,8 @@
# Only turn on clang-format check for the following subfolders.
clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
- camera/
media/libaudioclient/tests/
media/libaudiohal/tests/
media/libmediatranscoding/
services/camera/virtualcamera/
services/mediatranscoding/
- services/camera/libcameraservice/
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index db33dd7..8e53ca0 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -171,3 +171,10 @@
description: "Use the context-provided AttributionSource when checking for client permissions"
bug: "190657833"
}
+
+flag {
+ namespace: "camera_platform"
+ name: "check_full_attribution_source_chain"
+ description: "Pass the full AttributionSource chain to PermissionChecker"
+ bug: "190657833"
+}
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 6862cb1..d0df90b 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -22,6 +22,11 @@
default_applicable_licenses: ["frameworks_av_camera_license"],
}
+vintf_fragment {
+ name: "manifest_android.frameworks.cameraservice.service.xml",
+ src: "manifest_android.frameworks.cameraservice.service.xml",
+}
+
cc_binary {
name: "cameraserver",
@@ -61,7 +66,7 @@
init_rc: ["cameraserver.rc"],
- vintf_fragments: [
+ vintf_fragment_modules: [
"manifest_android.frameworks.cameraservice.service.xml",
],
}
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 7fb2d05..acc3c7c 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -573,7 +573,7 @@
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR">CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR</a>
* capability or devices where
* <a href="https://developer.android.com/reference/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>
- * lists <a href="https://developer.android.com/reference/CaptureRequest.html#SENSOR_PIXEL_MODE">ACAMERA_SENSOR_PIXEL_MODE</a>
+ * lists ACAMERA_SENSOR_PIXEL_MODE,
* ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION /
* ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION must be used as the
* coordinate system for requests where ACAMERA_SENSOR_PIXEL_MODE is set to
@@ -802,7 +802,7 @@
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR">CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR</a>
* capability or devices where
* <a href="https://developer.android.com/reference/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>
- * lists <a href="https://developer.android.com/reference/CaptureRequest.html#SENSOR_PIXEL_MODE">ACAMERA_SENSOR_PIXEL_MODE</a>,
+ * lists ACAMERA_SENSOR_PIXEL_MODE,
* ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION /
* ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION must be used as the
* coordinate system for requests where ACAMERA_SENSOR_PIXEL_MODE is set to
@@ -1008,7 +1008,7 @@
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR">CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR</a>
* capability or devices where
* <a href="https://developer.android.com/reference/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>
- * lists <a href="https://developer.android.com/reference/CaptureRequest.html#SENSOR_PIXEL_MODE">ACAMERA_SENSOR_PIXEL_MODE</a>,
+ * lists ACAMERA_SENSOR_PIXEL_MODE,
* ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION /
* ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION must be used as the
* coordinate system for requests where ACAMERA_SENSOR_PIXEL_MODE is set to
@@ -4052,8 +4052,8 @@
* <p>For camera devices with the
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR">CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR</a>
* capability or devices where <a href="https://developer.android.com/reference/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>
- * lists <a href="https://developer.android.com/reference/CaptureRequest.html#SENSOR_PIXEL_MODE">ACAMERA_SENSOR_PIXEL_MODE</a></p>
- * <p>ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION /
+ * lists ACAMERA_SENSOR_PIXEL_MODE,
+ * ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION /
* ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION must be used as the
* coordinate system for requests where ACAMERA_SENSOR_PIXEL_MODE is set to
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
@@ -5999,7 +5999,7 @@
* This key will only be present for devices which advertise the
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR">CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR</a>
* capability or devices where <a href="https://developer.android.com/reference/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>
- * lists <a href="https://developer.android.com/reference/CaptureRequest.html#SENSOR_PIXEL_MODE">ACAMERA_SENSOR_PIXEL_MODE</a></p>
+ * lists ACAMERA_SENSOR_PIXEL_MODE.</p>
* <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
*
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -6032,7 +6032,7 @@
* This key will only be present for devices which advertise the
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR">CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR</a>
* capability or devices where <a href="https://developer.android.com/reference/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>
- * lists <a href="https://developer.android.com/reference/CaptureRequest.html#SENSOR_PIXEL_MODE">ACAMERA_SENSOR_PIXEL_MODE</a></p>
+ * lists ACAMERA_SENSOR_PIXEL_MODE.</p>
*
* @see ACAMERA_SENSOR_INFO_PHYSICAL_SIZE
* @see ACAMERA_SENSOR_PIXEL_MODE
@@ -6061,7 +6061,7 @@
* This key will only be present for devices which advertise the
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR">CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR</a>
* capability or devices where <a href="https://developer.android.com/reference/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>
- * lists <a href="https://developer.android.com/reference/CaptureRequest.html#SENSOR_PIXEL_MODE">ACAMERA_SENSOR_PIXEL_MODE</a></p>
+ * lists ACAMERA_SENSOR_PIXEL_MODE.</p>
* <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
*
* @see ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
@@ -6100,7 +6100,7 @@
* <ul>
* <li>This key will be present if
* <a href="https://developer.android.com/reference/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>
- * lists <a href="https://developer.android.com/reference/CaptureRequest.html#SENSOR_PIXEL_MODE">ACAMERA_SENSOR_PIXEL_MODE</a>, since RAW
+ * lists ACAMERA_SENSOR_PIXEL_MODE, since RAW
* images may not necessarily have a regular bayer pattern when
* <a href="https://developer.android.com/reference/CaptureRequest.html#SENSOR_PIXEL_MODE">ACAMERA_SENSOR_PIXEL_MODE</a> is set to
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</li>
@@ -6470,9 +6470,19 @@
* height dimensions are given in ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE.
* This may include hot pixels that lie outside of the active array
* bounds given by ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE.</p>
+ * <p>For camera devices with the
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR">CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR</a>
+ * capability or devices where
+ * <a href="https://developer.android.com/reference/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>
+ * lists ACAMERA_SENSOR_PIXEL_MODE,
+ * ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION will be used as the
+ * pixel array size if the corresponding request sets ACAMERA_SENSOR_PIXEL_MODE to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
*
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
* @see ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE
+ * @see ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION
+ * @see ACAMERA_SENSOR_PIXEL_MODE
*/
ACAMERA_STATISTICS_HOT_PIXEL_MAP = // int32[2*n]
ACAMERA_STATISTICS_START + 15,
@@ -7622,8 +7632,8 @@
* <p>For camera devices with the
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR">CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR</a>
* capability or devices where <a href="https://developer.android.com/reference/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>
- * lists <a href="https://developer.android.com/reference/CaptureRequest.html#SENSOR_PIXEL_MODE">ACAMERA_SENSOR_PIXEL_MODE</a>
- * , the current active physical device
+ * lists ACAMERA_SENSOR_PIXEL_MODE,
+ * the current active physical device
* ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION /
* ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION must be used as the
* coordinate system for requests where ACAMERA_SENSOR_PIXEL_MODE is set to
diff --git a/cmds/stagefright/AudioPlayer.cpp b/cmds/stagefright/AudioPlayer.cpp
index 6cddf47..54885ef 100644
--- a/cmds/stagefright/AudioPlayer.cpp
+++ b/cmds/stagefright/AudioPlayer.cpp
@@ -101,6 +101,10 @@
CHECK(mFirstBuffer == NULL);
+ if (!mAudioPlayerWrapper) {
+ mAudioPlayerWrapper = sp<MediaPlayerBase::WeakWrapper<AudioPlayer>>::make(this);
+ }
+
MediaSource::ReadOptions options;
if (mSeeking) {
options.setSeekTo(mSeekTimeUs);
@@ -203,7 +207,7 @@
mSampleRate, numChannels, channelMask, audioFormat,
DEFAULT_AUDIOSINK_BUFFERCOUNT,
&AudioPlayer::AudioSinkCallback,
- this,
+ mAudioPlayerWrapper,
(audio_output_flags_t)flags,
useOffload() ? &offloadInfo : NULL);
@@ -430,10 +434,11 @@
// static
size_t AudioPlayer::AudioSinkCallback(
- MediaPlayerBase::AudioSink * /* audioSink */,
- void *buffer, size_t size, void *cookie,
+ const sp<MediaPlayerBase::AudioSink>& /* audioSink */,
+ void *buffer, size_t size, const wp<RefBase>& cookie,
MediaPlayerBase::AudioSink::cb_event_t event) {
- AudioPlayer *me = (AudioPlayer *)cookie;
+ const auto me = MediaPlayerBase::WeakWrapper<AudioPlayer>::promoteFromRefBase(cookie);
+ if (!me) return 0;
switch(event) {
case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
diff --git a/cmds/stagefright/AudioPlayer.h b/cmds/stagefright/AudioPlayer.h
index 608f54b..877ac13 100644
--- a/cmds/stagefright/AudioPlayer.h
+++ b/cmds/stagefright/AudioPlayer.h
@@ -29,7 +29,7 @@
struct AwesomePlayer;
-class AudioPlayer : AudioTrack::IAudioTrackCallback {
+class AudioPlayer : public AudioTrack::IAudioTrackCallback {
public:
enum {
REACHED_EOS,
@@ -97,14 +97,15 @@
MediaBufferBase *mFirstBuffer;
sp<MediaPlayerBase::AudioSink> mAudioSink;
+ sp<MediaPlayerBase::WeakWrapper<AudioPlayer>> mAudioPlayerWrapper;
bool mPlaying;
int64_t mStartPosUs;
const uint32_t mCreateFlags;
static size_t AudioSinkCallback(
- MediaPlayerBase::AudioSink *audioSink,
- void *data, size_t size, void *me,
+ const sp<MediaPlayerBase::AudioSink>& audioSink,
+ void *data, size_t size, const wp<RefBase>& me,
MediaPlayerBase::AudioSink::cb_event_t event);
size_t fillBuffer(void *data, size_t size);
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Android.bp b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
index 079e075..4132ba2 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
@@ -134,6 +134,7 @@
required: [
"com.android.hardware.drm.clearkey",
],
+ vendor: true,
}
cc_defaults {
diff --git a/media/aconfig/codec_fwk.aconfig b/media/aconfig/codec_fwk.aconfig
index ed1522b..84c0f48 100644
--- a/media/aconfig/codec_fwk.aconfig
+++ b/media/aconfig/codec_fwk.aconfig
@@ -103,6 +103,14 @@
}
flag {
+ name: "p210_format_support"
+ is_exported: true
+ namespace: "codec_fwk"
+ description: "Feature flag for Android support for P210 YCbCr format"
+ bug: "368395888"
+}
+
+flag {
name: "region_of_interest"
is_exported: true
namespace: "codec_fwk"
@@ -118,6 +126,13 @@
}
flag {
+ name: "rendering_depth_removal"
+ namespace: "codec_fwk"
+ description: "Feature flag for removing rendering depth"
+ bug: "275527219"
+}
+
+flag {
name: "secure_codecs_require_crypto"
namespace: "codec_fwk"
description: "Bugfix flag for requiring setting crypto for secure codecs"
diff --git a/media/audio/aconfig/Android.bp b/media/audio/aconfig/Android.bp
index a5aeff2..2da6758 100644
--- a/media/audio/aconfig/Android.bp
+++ b/media/audio/aconfig/Android.bp
@@ -116,7 +116,10 @@
package: "android.media.audio",
container: "system",
srcs: ["audio_framework.aconfig"],
- visibility: ["//frameworks/base/api"],
+ visibility: [
+ "//frameworks/base/api",
+ "//frameworks/base/core/res",
+ ],
}
aconfig_declarations {
@@ -172,6 +175,12 @@
}
cc_aconfig_library {
+ name: "android.media.audio-aconfig-cc",
+ aconfig_declarations: "android.media.audio-aconfig",
+ defaults: ["audio-aconfig-cc-defaults"],
+}
+
+cc_aconfig_library {
name: "android.media.audiopolicy-aconfig-cc",
aconfig_declarations: "android.media.audiopolicy-aconfig",
defaults: ["audio-aconfig-cc-defaults"],
diff --git a/media/audio/aconfig/audio_framework.aconfig b/media/audio/aconfig/audio_framework.aconfig
index 411996e..0b434f7 100644
--- a/media/audio/aconfig/audio_framework.aconfig
+++ b/media/audio/aconfig/audio_framework.aconfig
@@ -1,5 +1,6 @@
# Top level framework (android.media) flags
# Only add flags here which must be included in framework.jar
+# Flags used in both framework.jar and native can be added here
#
# Please add flags in alphabetical order.
@@ -22,6 +23,15 @@
bug: "302323921"
}
+flag {
+ name: "concurrent_audio_record_bypass_permission"
+ namespace: "media_audio"
+ description:
+ "New privileged permission to allow bypassing concurrent audio"
+ "capture rules."
+ bug: "374751406"
+}
+
flag{
name: "enable_ringtone_haptics_customization"
namespace: "media_audio"
@@ -144,6 +154,14 @@
is_fixed_read_only: true
}
+flag {
+ name: "routed_device_ids"
+ namespace: "media_audio"
+ description:
+ "Enable Java and native functions to get"
+ "multiple routed device ids"
+ bug: "367816690"
+}
# TODO remove
flag {
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 90996a3..cdcce08 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -1057,6 +1057,14 @@
return OK;
}
+namespace {
+ // Use '01' for LSB bits 0 and 1 as Bluetooth MAC addresses are never multicast
+ // and universaly administered
+ constexpr std::array<uint8_t, 4> BTANON_PREFIX {0xFD, 0xFF, 0xFF, 0xFF};
+ // Keep sync with ServiceUtilities.cpp mustAnonymizeBluetoothAddress
+ constexpr const char * BTANON_PREFIX_STR = "XX:XX:XX:XX:";
+}
+
::android::status_t aidl2legacy_AudioDevice_audio_device(
const AudioDevice& aidl,
audio_devices_t* legacyType, std::string* legacyAddress) {
@@ -1071,8 +1079,16 @@
case Tag::mac: {
const std::vector<uint8_t>& mac = aidl.address.get<AudioDeviceAddress::mac>();
if (mac.size() != 6) return BAD_VALUE;
- snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%02X:%02X:%02X:%02X:%02X:%02X",
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ if (std::equal(BTANON_PREFIX.begin(), BTANON_PREFIX.end(), mac.begin())) {
+ // special case for anonymized mac address:
+ // change anonymized bytes back from FD:FF:FF:FF: to XX:XX:XX:XX:
+ snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN,
+ "%s%02X:%02X", BTANON_PREFIX_STR, mac[4], mac[5]);
+ } else {
+ snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN,
+ "%02X:%02X:%02X:%02X:%02X:%02X",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ }
} break;
case Tag::ipv4: {
const std::vector<uint8_t>& ipv4 = aidl.address.get<AudioDeviceAddress::ipv4>();
@@ -1134,8 +1150,20 @@
switch (suggestDeviceAddressTag(aidl.type)) {
case Tag::mac: {
std::vector<uint8_t> mac(6);
- int status = sscanf(legacyAddress.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
- &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
+ int status;
+ // special case for anonymized mac address:
+ // change anonymized bytes so that they can be scanned as HEX bytes
+ if (legacyAddress.starts_with(BTANON_PREFIX_STR)) {
+ std::copy(BTANON_PREFIX.begin(), BTANON_PREFIX.end(), mac.begin());
+ LOG_ALWAYS_FATAL_IF(legacyAddress.length() <= strlen(BTANON_PREFIX_STR));
+ status = sscanf(legacyAddress.c_str() + strlen(BTANON_PREFIX_STR),
+ "%hhX:%hhX",
+ &mac[4], &mac[5]);
+ status += 4;
+ } else {
+ status = sscanf(legacyAddress.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
+ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
+ }
if (status != mac.size()) {
ALOGE("%s: malformed MAC address: \"%s\"", __func__, legacyAddress.c_str());
return unexpected(BAD_VALUE);
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index 5d7daa4..d55932d 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -205,6 +205,7 @@
__func__, status, policyInfos.size());
}
const auto endTime = std::chrono::steady_clock::now();
+ af->startupFinished();
using FloatMillis = std::chrono::duration<float, std::milli>;
const float timeTaken = std::chrono::duration_cast<FloatMillis>(
endTime - startTime).count();
diff --git a/media/codec2/components/aom/C2SoftAomEnc.cpp b/media/codec2/components/aom/C2SoftAomEnc.cpp
index 722b13a..93009c4 100644
--- a/media/codec2/components/aom/C2SoftAomEnc.cpp
+++ b/media/codec2/components/aom/C2SoftAomEnc.cpp
@@ -466,6 +466,7 @@
aom_codec_err_t C2SoftAomEnc::setupCodecParameters() {
aom_codec_err_t codec_return = AOM_CODEC_OK;
+ const int maxIntraBitratePct = mBitrateControlMode == AOM_CBR ? 300 : 450;
codec_return = aom_codec_control(mCodecContext, AV1E_SET_TARGET_SEQ_LEVEL_IDX, mAV1EncLevel);
if (codec_return != AOM_CODEC_OK) goto BailOut;
@@ -492,6 +493,10 @@
codec_return = aom_codec_control(mCodecContext, AV1E_SET_AQ_MODE, 3);
if (codec_return != AOM_CODEC_OK) goto BailOut;
+ codec_return = aom_codec_control(mCodecContext, AOME_SET_MAX_INTRA_BITRATE_PCT,
+ maxIntraBitratePct);
+ if (codec_return != AOM_CODEC_OK) goto BailOut;
+
codec_return = aom_codec_control(mCodecContext, AV1E_SET_COEFF_COST_UPD_FREQ, 3);
if (codec_return != AOM_CODEC_OK) goto BailOut;
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index 562dcf5..52920c2 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -743,6 +743,25 @@
}
status_t C2SoftMpeg2Dec::deleteDecoder() {
+ // API call to IV_CMD_RETRIEVE_MEMREC not only retrieves the memory records
+ // but also joins active threads and destroys conditional thread variables and
+ // mutex locks for each thread.
+ iv_retrieve_mem_rec_ip_t s_retrieve_mem_ip;
+ iv_retrieve_mem_rec_op_t s_retrieve_mem_op;
+
+ s_retrieve_mem_ip.pv_mem_rec_location = (iv_mem_rec_t *)mMemRecords;
+ s_retrieve_mem_ip.e_cmd = IV_CMD_RETRIEVE_MEMREC;
+ s_retrieve_mem_ip.u4_size = sizeof(iv_retrieve_mem_rec_ip_t);
+ s_retrieve_mem_op.u4_size = sizeof(iv_retrieve_mem_rec_op_t);
+
+ IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
+ &s_retrieve_mem_ip,
+ &s_retrieve_mem_op);
+ if (IV_SUCCESS != status) {
+ ALOGE("error in %s: 0x%x", __func__, s_retrieve_mem_op.u4_error_code);
+ return UNKNOWN_ERROR;
+ }
+
if (mMemRecords) {
iv_mem_rec_t *ps_mem_rec = mMemRecords;
diff --git a/media/codec2/hal/common/include/codec2/common/BqPoolInvalidateHelper.h b/media/codec2/hal/common/include/codec2/common/BqPoolInvalidateHelper.h
new file mode 100644
index 0000000..859f703
--- /dev/null
+++ b/media/codec2/hal/common/include/codec2/common/BqPoolInvalidateHelper.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <C2BqBufferPriv.h>
+#include <C2PlatformSupport.h>
+
+namespace android {
+
+// filter fn from component's blockpool container to bqpool conatainer
+static inline bool BqPoolFilterFn(
+ std::pair<const uint64_t, std::shared_ptr<C2BlockPool>> pool) {
+ return (pool.second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE);
+}
+
+// convert fn from component's blockpool container to bqpool container
+static inline std::shared_ptr<C2BufferQueueBlockPool> BqPoolConvertFn(
+ std::pair<const uint64_t, std::shared_ptr<C2BlockPool>> pool) {
+ return std::static_pointer_cast<C2BufferQueueBlockPool>(pool.second);
+}
+
+// This is similar to std::transform excpet there is \pred functor parameter.
+// The elements with \pred function value \true only will be transformed and
+// added to the dest container. (For portability std::ranges are not used.)
+template <class InputIt, class OutputIt, class Pred, class Fct>
+void transform_if(InputIt first, InputIt last, OutputIt dest, Pred pred, Fct transform)
+{
+ while (first != last) {
+ if (pred(*first)) {
+ *dest++ = transform(*first);
+ }
+ ++first;
+ }
+}
+
+} // namespace android
diff --git a/media/codec2/hal/hidl/1.0/utils/Component.cpp b/media/codec2/hal/hidl/1.0/utils/Component.cpp
index 62f0e25..162a80e 100644
--- a/media/codec2/hal/hidl/1.0/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/Component.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "Codec2-Component"
#include <android-base/logging.h>
+#include <codec2/common/BqPoolInvalidateHelper.h>
#include <codec2/hidl/1.0/Component.h>
#include <codec2/hidl/1.0/ComponentStore.h>
#include <codec2/hidl/1.0/InputBufferManager.h>
@@ -30,6 +31,7 @@
#include <utils/Timers.h>
#include <C2BqBufferPriv.h>
+#include <C2BqPoolInvalidator.h>
#include <C2Debug.h>
#include <C2PlatformSupport.h>
@@ -270,16 +272,17 @@
}
void Component::onDeathReceived() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mClientDied = true;
- for (auto it = mBlockPools.begin(); it != mBlockPools.end(); ++it) {
- if (it->second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
- std::shared_ptr<C2BufferQueueBlockPool> bqPool =
- std::static_pointer_cast<C2BufferQueueBlockPool>(it->second);
- bqPool->invalidate();
- }
- }
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ bqInvalidateItem->invalidate();
}
release();
}
@@ -549,7 +552,26 @@
}
Return<Status> Component::release() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ if (!mClientDied) {
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ }
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem;
+ if (!bqPools.empty()) {
+ // handling rare cases of process death just after release() called.
+ bqInvalidateItem = std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
Status status = static_cast<Status>(mComponent->release());
+ if (bqInvalidateItem) {
+ // If release is not blocked,
+ // skip invalidation and finish ASAP.
+ bqInvalidateItem->skip();
+ }
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mBlockPools.clear();
@@ -637,6 +659,18 @@
}
Component::~Component() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ LOG(ERROR) << "blockpools are not cleared yet at dtor";
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
InputBufferManager::unregisterFrameData(mListener);
mStore->reportComponentDeath(this);
}
diff --git a/media/codec2/hal/hidl/1.1/utils/Component.cpp b/media/codec2/hal/hidl/1.1/utils/Component.cpp
index 7f2c4dd..1c2a49a 100644
--- a/media/codec2/hal/hidl/1.1/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.1/utils/Component.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "Codec2-Component@1.1"
#include <android-base/logging.h>
+#include <codec2/common/BqPoolInvalidateHelper.h>
#include <codec2/hidl/1.1/Component.h>
#include <codec2/hidl/1.1/ComponentStore.h>
#include <codec2/hidl/1.1/InputBufferManager.h>
@@ -32,6 +33,7 @@
#include <codec2/common/MultiAccessUnitHelper.h>
#include <C2BqBufferPriv.h>
+#include <C2BqPoolInvalidator.h>
#include <C2Debug.h>
#include <C2PlatformSupport.h>
@@ -274,16 +276,17 @@
}
void Component::onDeathReceived() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mClientDied = true;
- for (auto it = mBlockPools.begin(); it != mBlockPools.end(); ++it) {
- if (it->second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
- std::shared_ptr<C2BufferQueueBlockPool> bqPool =
- std::static_pointer_cast<C2BufferQueueBlockPool>(it->second);
- bqPool->invalidate();
- }
- }
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ bqInvalidateItem->invalidate();
}
release();
}
@@ -555,7 +558,26 @@
}
Return<Status> Component::release() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ if (!mClientDied) {
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ }
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem;
+ if (!bqPools.empty()) {
+ // handling rare cases of process death just after release() called.
+ bqInvalidateItem = std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
Status status = static_cast<Status>(mComponent->release());
+ if (bqInvalidateItem) {
+ // If release is not blocked,
+ // skip invalidation and finish ASAP.
+ bqInvalidateItem->skip();
+ }
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mBlockPools.clear();
@@ -649,6 +671,18 @@
}
Component::~Component() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ LOG(ERROR) << "blockpools are not cleared yet at dtor";
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
InputBufferManager::unregisterFrameData(mListener);
mStore->reportComponentDeath(this);
}
diff --git a/media/codec2/hal/hidl/1.2/utils/Component.cpp b/media/codec2/hal/hidl/1.2/utils/Component.cpp
index 7b0aa9b..a15febe 100644
--- a/media/codec2/hal/hidl/1.2/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.2/utils/Component.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "Codec2-Component@1.2"
#include <android-base/logging.h>
+#include <codec2/common/BqPoolInvalidateHelper.h>
#include <codec2/hidl/1.2/Component.h>
#include <codec2/hidl/1.2/ComponentStore.h>
#include <codec2/hidl/1.2/InputBufferManager.h>
@@ -30,6 +31,7 @@
#include <utils/Timers.h>
#include <C2BqBufferPriv.h>
+#include <C2BqPoolInvalidator.h>
#include <C2Debug.h>
#include <C2PlatformSupport.h>
@@ -272,16 +274,17 @@
}
void Component::onDeathReceived() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mClientDied = true;
- for (auto it = mBlockPools.begin(); it != mBlockPools.end(); ++it) {
- if (it->second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
- std::shared_ptr<C2BufferQueueBlockPool> bqPool =
- std::static_pointer_cast<C2BufferQueueBlockPool>(it->second);
- bqPool->invalidate();
- }
- }
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ bqInvalidateItem->invalidate();
}
release();
}
@@ -551,7 +554,26 @@
}
Return<Status> Component::release() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ if (!mClientDied) {
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ }
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem;
+ if (!bqPools.empty()) {
+ // handling rare cases of process death just after release() called.
+ bqInvalidateItem = std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
Status status = static_cast<Status>(mComponent->release());
+ if (bqInvalidateItem) {
+ // If release is not blocked,
+ // skip invalidation and finish ASAP.
+ bqInvalidateItem->skip();
+ }
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mBlockPools.clear();
@@ -676,6 +698,18 @@
}
Component::~Component() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ LOG(ERROR) << "blockpools are not cleared yet at dtor";
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
InputBufferManager::unregisterFrameData(mListener);
mStore->reportComponentDeath(this);
}
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 3c8c1b7..cc5d10c 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -16,6 +16,10 @@
cc_library_shared {
name: "libsfplugin_ccodec",
+ defaults: [
+ "android.hardware.graphics.common-ndk_shared",
+ ],
+
export_include_dirs: ["include"],
srcs: [
@@ -46,6 +50,7 @@
],
static_libs: [
+ "libPlatformProperties",
"libSurfaceFlingerProperties",
"aconfig_mediacodec_flags_c_lib",
"android.media.codec-aconfig-cc",
@@ -56,7 +61,6 @@
"android.hardware.drm@1.0",
"android.hardware.media.c2@1.0",
"android.hardware.media.omx@1.0",
- "android.hardware.graphics.common-V5-ndk",
"graphicbuffersource-aidl-ndk",
"libbase",
"libbinder",
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 3ef2f84..5c46d99 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -38,6 +38,7 @@
#include <android/hardware/cas/native/1.0/IDescrambler.h>
#include <android/hardware/drm/1.0/types.h>
+#include <android/sysprop/MediaProperties.sysprop.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
@@ -207,8 +208,18 @@
Mutexed<BlockPools>::Locked pools(mBlockPools);
pools->outputPoolId = C2BlockPool::BASIC_LINEAR;
}
- std::string value = GetServerConfigurableFlag("media_native", "ccodec_rendering_depth", "3");
- android::base::ParseInt(value, &mRenderingDepth);
+ if (android::media::codec::provider_->rendering_depth_removal()) {
+ constexpr int kAndroidApi202404 = 202404;
+ int vendorVersion = ::android::base::GetIntProperty("ro.vendor.api_level", -1);
+ using ::android::sysprop::MediaProperties::codec2_remove_rendering_depth;
+ if (vendorVersion > kAndroidApi202404 || codec2_remove_rendering_depth().value_or(false)) {
+ mRenderingDepth = 0;
+ }
+ } else {
+ std::string value = GetServerConfigurableFlag(
+ "media_native", "ccodec_rendering_depth", "3");
+ android::base::ParseInt(value, &mRenderingDepth);
+ }
mOutputSurface.lock()->maxDequeueBuffers = kSmoothnessFactor + mRenderingDepth;
}
@@ -2052,6 +2063,14 @@
status_t CCodecBufferChannel::requestInitialInputBuffers(
std::map<size_t, sp<MediaCodecBuffer>> &&clientInputBuffers) {
+ std::optional<QueueGuard> guard;
+ if (android::media::codec::provider_->codec_buffer_state_cleanup()) {
+ guard.emplace(mSync);
+ if (!guard->isRunning()) {
+ ALOGD("[%s] skip requestInitialInputBuffers when not running", mName);
+ return OK;
+ }
+ }
C2StreamBufferTypeSetting::output oStreamFormat(0u);
C2PrependHeaderModeSetting prepend(PREPEND_HEADER_TO_NONE);
c2_status_t err = mComponent->query({ &oStreamFormat, &prepend }, {}, C2_DONT_BLOCK, nullptr);
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index dc06ee6..9d1cbff 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -53,7 +53,7 @@
],
defaults: [
- "aconfig_lib_cc_static_link.defaults",
+ "aconfig_lib_cc_static_link.defaults",
"libcodec2_hal_selection",
],
@@ -68,6 +68,7 @@
"C2PlatformStorePluginLoader.cpp",
"C2Store.cpp",
"platform/C2BqBuffer.cpp",
+ "platform/C2BqPoolInvalidator.cpp",
"platform/C2SurfaceSyncObj.cpp",
"platform/C2IgbaBuffer.cpp",
"types.cpp",
diff --git a/media/codec2/vndk/include/C2BqPoolInvalidator.h b/media/codec2/vndk/include/C2BqPoolInvalidator.h
new file mode 100644
index 0000000..612d023
--- /dev/null
+++ b/media/codec2/vndk/include/C2BqPoolInvalidator.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/no_destructor.h>
+#include <media/stagefright/foundation/ABase.h>
+
+#include <condition_variable>
+#include <deque>
+#include <list>
+#include <memory>
+#include <thread>
+
+class C2BufferQueueBlockPool;
+
+namespace android {
+
+/**
+ * Container class in order to invalidate C2BufferQueueBlockPool(s) and their resources
+ * when the client process is dead abruptly.
+ */
+class C2BqPoolInvalidateItem {
+public:
+
+ /**
+ * invalidate contained C2BufferQueueBlockPool(s) and their resources
+ */
+ void invalidate();
+
+ /**
+ * skip invalidate(), if it is scheduled and not yet invalidated.
+ */
+ void skip();
+
+ /**
+ * returns whether invalidate() is reuqired or not.
+ */
+ bool needsInvalidate();
+
+ C2BqPoolInvalidateItem(std::list<std::shared_ptr<C2BufferQueueBlockPool>> &&pools);
+
+ ~C2BqPoolInvalidateItem() = default;
+private:
+
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> mPools;
+ bool mNeedsInvalidate;
+ std::mutex mLock;
+
+ DISALLOW_EVIL_CONSTRUCTORS(C2BqPoolInvalidateItem);
+};
+
+/**
+ * Asynchronous C2BufferQueueBlockPool invalidator.
+ *
+ * this has C2BqPoolInvalidateItem inside. and call invalidate() from a separate
+ * thread asynchronously.
+ */
+class C2BqPoolInvalidator {
+public:
+ /**
+ * This gets the singleton instance of the class.
+ */
+ static C2BqPoolInvalidator &getInstance();
+
+ /**
+ * queue invalidation items. the item will be invalidated after certain
+ * amount of delay from a separate thread.
+ */
+ void queue(std::shared_ptr<C2BqPoolInvalidateItem> &item);
+
+ ~C2BqPoolInvalidator();
+private:
+
+ C2BqPoolInvalidator();
+
+ void run();
+
+ std::thread mThread;
+ bool mDone;
+
+ std::mutex mMutex;
+ std::condition_variable mCv;
+
+ std::deque<std::pair<int64_t, std::shared_ptr<C2BqPoolInvalidateItem>>> mItems;
+
+ friend class ::android::base::NoDestructor<C2BqPoolInvalidator>;
+
+ DISALLOW_EVIL_CONSTRUCTORS(C2BqPoolInvalidator);
+};
+
+} // namespace android
diff --git a/media/codec2/vndk/platform/C2BqPoolInvalidator.cpp b/media/codec2/vndk/platform/C2BqPoolInvalidator.cpp
new file mode 100644
index 0000000..2666cd3
--- /dev/null
+++ b/media/codec2/vndk/platform/C2BqPoolInvalidator.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "C2BqPoolInvalidator"
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+#include <C2BqBufferPriv.h>
+#include <C2BqPoolInvalidator.h>
+
+namespace android {
+
+namespace {
+ static constexpr int64_t kBqPoolInvalidateDelayMs = 1000;
+} // anonymous namespace
+
+C2BqPoolInvalidateItem::C2BqPoolInvalidateItem(
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> &&pools) : mPools(std::move(pools)) {
+ if (!mPools.empty()) {
+ mNeedsInvalidate = true;
+ } else {
+ mNeedsInvalidate = false;
+ }
+}
+
+void C2BqPoolInvalidateItem::invalidate() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> pools;
+ {
+ std::unique_lock<std::mutex> l(mLock);
+ if (!mNeedsInvalidate) {
+ return;
+ }
+ pools = std::move(mPools);
+ mNeedsInvalidate = false;
+ }
+ for(auto it = pools.begin(); it != pools.end(); ++it) {
+ (*it)->invalidate();
+ }
+}
+
+void C2BqPoolInvalidateItem::skip() {
+ std::unique_lock<std::mutex> l(mLock);
+ mNeedsInvalidate = false;
+ mPools.clear();
+}
+
+bool C2BqPoolInvalidateItem::needsInvalidate() {
+ std::unique_lock<std::mutex> l(mLock);
+ return mNeedsInvalidate;
+}
+
+C2BqPoolInvalidator &C2BqPoolInvalidator::getInstance() {
+ static android::base::NoDestructor<C2BqPoolInvalidator> sInvalidator;
+ return *sInvalidator;
+}
+
+C2BqPoolInvalidator::C2BqPoolInvalidator() : mDone(false) {
+ mThread = std::thread(&C2BqPoolInvalidator::run, this);
+}
+
+C2BqPoolInvalidator::~C2BqPoolInvalidator() {
+ {
+ std::unique_lock<std::mutex> l(mMutex);
+ mDone = true;
+ mCv.notify_one();
+ }
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+void C2BqPoolInvalidator::queue(std::shared_ptr<C2BqPoolInvalidateItem> &item) {
+ std::unique_lock<std::mutex> l(mMutex);
+ std::pair<int64_t, std::shared_ptr<C2BqPoolInvalidateItem>> p =
+ std::make_pair(::android::elapsedRealtime() + kBqPoolInvalidateDelayMs, item);
+ mItems.push_back(p);
+ mCv.notify_one();
+}
+
+void C2BqPoolInvalidator::run() {
+ while(true) {
+ int64_t nowMs = ::android::elapsedRealtime();
+ std::unique_lock<std::mutex> l(mMutex);
+ if (mDone) {
+ break;
+ }
+ std::list<std::shared_ptr<C2BqPoolInvalidateItem>> items;
+ while (!mItems.empty()) {
+ if (mItems.front().first <= nowMs) {
+ items.push_back(mItems.front().second);
+ mItems.pop_front();
+ } else {
+ break;
+ }
+ }
+ if (items.empty()) {
+ if (mItems.empty()) {
+ mCv.wait(l);
+ } else {
+ int64_t nextMs = mItems.front().first;
+ if (nextMs > nowMs) {
+ mCv.wait_for(l, std::chrono::milliseconds(nextMs - nowMs));
+ }
+ }
+ } else {
+ l.unlock();
+ int invalidated = 0;
+ for (auto it = items.begin(); it != items.end(); ++it, ++invalidated) {
+ (*it)->invalidate();
+ }
+ ALOGD("invalidated %d bqpool items", invalidated);
+ }
+ }
+}
+
+} // android
diff --git a/media/libaaudio/fuzzer/Android.bp b/media/libaaudio/fuzzer/Android.bp
index a1551f8..f4637e3 100644
--- a/media/libaaudio/fuzzer/Android.bp
+++ b/media/libaaudio/fuzzer/Android.bp
@@ -66,6 +66,7 @@
"libmedia_helper",
"libmediametrics",
"libprocessgroup",
+ "libprocessgroup_util",
"mediametricsservice-aidl-cpp",
"shared-file-region-aidl-cpp",
],
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 5b954f7..b193950 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -1159,11 +1159,10 @@
// start of lock scope
AutoMutex lock(mLock);
- uint32_t newSequence = mSequence;
// did previous obtainBuffer() fail due to media server death or voluntary invalidation?
if (status == DEAD_OBJECT) {
// re-create track, unless someone else has already done so
- if (newSequence == oldSequence) {
+ if (mSequence == oldSequence) {
if (!audio_is_linear_pcm(mFormat)) {
// If compressed capture, don't attempt to restore the track.
// Return a DEAD_OBJECT error and let the caller recreate.
@@ -1179,7 +1178,7 @@
}
}
}
- oldSequence = newSequence;
+ oldSequence = mSequence;
// Keep the extra references
proxy = mProxy;
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index ee44074..769475c 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -308,11 +308,11 @@
}
status_t AudioSystem::setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output) {
+ bool muted, audio_io_handle_t output) {
if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
const sp<IAudioFlinger> af = get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
- af->setStreamVolume(stream, value, output);
+ af->setStreamVolume(stream, value, muted, output);
return NO_ERROR;
}
@@ -325,14 +325,15 @@
}
status_t AudioSystem::setPortsVolume(
- const std::vector<audio_port_handle_t>& portIds, float volume, audio_io_handle_t output) {
+ const std::vector<audio_port_handle_t>& portIds, float volume, bool muted,
+ audio_io_handle_t output) {
const sp<IAudioFlinger> af = get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
std::vector<int32_t> portIdsAidl = VALUE_OR_RETURN_STATUS(
convertContainer<std::vector<int32_t>>(
portIds, legacy2aidl_audio_port_handle_t_int32_t));
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
- af->setPortsVolume(portIdsAidl, volume, outputAidl);
+ af->setPortsVolume(portIdsAidl, volume, muted, outputAidl);
return NO_ERROR;
}
@@ -1096,7 +1097,8 @@
std::vector<audio_io_handle_t>* secondaryOutputs,
bool *isSpatialized,
bool *isBitPerfect,
- float *volume) {
+ float *volume,
+ bool *muted) {
if (attr == nullptr) {
ALOGE("%s NULL audio attributes", __func__);
return BAD_VALUE;
@@ -1163,6 +1165,7 @@
*attr = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioAttributes_audio_attributes_t(responseAidl.attr));
*volume = responseAidl.volume;
+ *muted = responseAidl.muted;
return OK;
}
@@ -1326,6 +1329,7 @@
status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,
int index,
+ bool muted,
audio_devices_t device) {
const sp<IAudioPolicyService> aps = get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
@@ -1336,7 +1340,7 @@
AudioDeviceDescription deviceAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_devices_t_AudioDeviceDescription(device));
return statusTFromBinderStatus(
- aps->setStreamVolumeIndex(streamAidl, deviceAidl, indexAidl));
+ aps->setStreamVolumeIndex(streamAidl, deviceAidl, indexAidl, muted));
}
status_t AudioSystem::getStreamVolumeIndex(audio_stream_type_t stream,
@@ -1360,6 +1364,7 @@
status_t AudioSystem::setVolumeIndexForAttributes(const audio_attributes_t& attr,
int index,
+ bool muted,
audio_devices_t device) {
const sp<IAudioPolicyService> aps = get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
@@ -1370,7 +1375,7 @@
AudioDeviceDescription deviceAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_devices_t_AudioDeviceDescription(device));
return statusTFromBinderStatus(
- aps->setVolumeIndexForAttributes(attrAidl, deviceAidl, indexAidl));
+ aps->setVolumeIndexForAttributes(attrAidl, deviceAidl, indexAidl, muted));
}
status_t AudioSystem::getVolumeIndexForAttributes(const audio_attributes_t& attr,
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index d7c0b5b..e0c5e92 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -2221,11 +2221,10 @@
{ // start of lock scope
AutoMutex lock(mLock);
- uint32_t newSequence = mSequence;
// did previous obtainBuffer() fail due to media server death or voluntary invalidation?
if (status == DEAD_OBJECT) {
// re-create track, unless someone else has already done so
- if (newSequence == oldSequence) {
+ if (mSequence == oldSequence) {
status = restoreTrack_l("obtainBuffer");
if (status != NO_ERROR) {
buffer.mFrameCount = 0;
@@ -2235,7 +2234,7 @@
}
}
}
- oldSequence = newSequence;
+ oldSequence = mSequence;
if (status == NOT_ENOUGH_DATA) {
restartIfDisabled();
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 9241973..168b47e 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -337,11 +337,12 @@
}
status_t AudioFlingerClientAdapter::setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output) {
+ bool muted, audio_io_handle_t output) {
AudioStreamType streamAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
- return statusTFromBinderStatus(mDelegate->setStreamVolume(streamAidl, value, outputAidl));
+ return statusTFromBinderStatus(
+ mDelegate->setStreamVolume(streamAidl, value, muted, outputAidl));
}
status_t AudioFlingerClientAdapter::setStreamMute(audio_stream_type_t stream, bool muted) {
@@ -351,12 +352,14 @@
}
status_t AudioFlingerClientAdapter::setPortsVolume(
- const std::vector<audio_port_handle_t>& portIds, float volume, audio_io_handle_t output) {
+ const std::vector<audio_port_handle_t> &portIds, float volume, bool muted,
+ audio_io_handle_t output) {
std::vector<int32_t> portIdsAidl = VALUE_OR_RETURN_STATUS(
convertContainer<std::vector<int32_t>>(
portIds, legacy2aidl_audio_port_handle_t_int32_t));
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
- return statusTFromBinderStatus(mDelegate->setPortsVolume(portIdsAidl, volume, outputAidl));
+ return statusTFromBinderStatus(
+ mDelegate->setPortsVolume(portIdsAidl, volume, muted, outputAidl));
}
status_t AudioFlingerClientAdapter::setMode(audio_mode_t mode) {
@@ -1007,12 +1010,13 @@
}
Status AudioFlingerServerAdapter::setStreamVolume(AudioStreamType stream, float value,
- int32_t output) {
+ bool muted, int32_t output) {
audio_stream_type_t streamLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_AudioStreamType_audio_stream_type_t(stream));
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_int32_t_audio_io_handle_t(output));
- return Status::fromStatusT(mDelegate->setStreamVolume(streamLegacy, value, outputLegacy));
+ return Status::fromStatusT(
+ mDelegate->setStreamVolume(streamLegacy, value, muted, outputLegacy));
}
Status AudioFlingerServerAdapter::setStreamMute(AudioStreamType stream, bool muted) {
@@ -1022,13 +1026,14 @@
}
Status AudioFlingerServerAdapter::setPortsVolume(
- const std::vector<int32_t>& portIds, float volume, int32_t output) {
+ const std::vector<int32_t>& portIds, float volume, bool muted, int32_t output) {
std::vector<audio_port_handle_t> portIdsLegacy = VALUE_OR_RETURN_BINDER(
convertContainer<std::vector<audio_port_handle_t>>(
portIds, aidl2legacy_int32_t_audio_port_handle_t));
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_int32_t_audio_io_handle_t(output));
- return Status::fromStatusT(mDelegate->setPortsVolume(portIdsLegacy, volume, outputLegacy));
+ return Status::fromStatusT(
+ mDelegate->setPortsVolume(portIdsLegacy, volume, muted, outputLegacy));
}
Status AudioFlingerServerAdapter::setMode(AudioMode mode) {
diff --git a/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl b/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
index 4b26d5b..d3975c0 100644
--- a/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
+++ b/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
@@ -41,4 +41,6 @@
AudioAttributes attr;
/** initial port volume for the new audio track */
float volume;
+ /** initial port muted state for the new audio track */
+ boolean muted;
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 1c825bc..474ab11 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -96,15 +96,17 @@
/*
* Set stream type state. This will probably be used by
* the preference panel, mostly.
+ * This method is deprecated. Please use the setPortsVolume method instead.
*/
- void setStreamVolume(AudioStreamType stream, float value, int /* audio_io_handle_t */ output);
+ void setStreamVolume(AudioStreamType stream, float value, boolean muted,
+ int /* audio_io_handle_t */ output);
void setStreamMute(AudioStreamType stream, boolean muted);
/*
* Set AudioTrack port ids volume attribute. This is the new way of controlling volume from
* AudioPolicyManager to AudioFlinger.
*/
- void setPortsVolume(in int[] /* audio_port_handle_t[] */ portIds, float volume,
+ void setPortsVolume(in int[] /* audio_port_handle_t[] */ portIds, float volume, boolean muted,
int /* audio_io_handle_t */ output);
// set audio mode.
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index b4f879a..40ab938 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -126,14 +126,14 @@
void setStreamVolumeIndex(AudioStreamType stream,
in AudioDeviceDescription device,
- int index);
+ int index, boolean muted);
int getStreamVolumeIndex(AudioStreamType stream,
in AudioDeviceDescription device);
void setVolumeIndexForAttributes(in AudioAttributes attr,
in AudioDeviceDescription device,
- int index);
+ int index, boolean muted);
int getVolumeIndexForAttributes(in AudioAttributes attr,
in AudioDeviceDescription device);
diff --git a/media/libaudioclient/aidl/fuzzer/Android.bp b/media/libaudioclient/aidl/fuzzer/Android.bp
index 61d5ccd..a215c0b 100644
--- a/media/libaudioclient/aidl/fuzzer/Android.bp
+++ b/media/libaudioclient/aidl/fuzzer/Android.bp
@@ -30,6 +30,7 @@
"libjsoncpp",
"libmediametricsservice",
"libprocessgroup",
+ "libprocessgroup_util",
"shared-file-region-aidl-cpp",
],
shared_libs: [
diff --git a/media/libaudioclient/fuzzer/Android.bp b/media/libaudioclient/fuzzer/Android.bp
index a95c700..8bca8df 100644
--- a/media/libaudioclient/fuzzer/Android.bp
+++ b/media/libaudioclient/fuzzer/Android.bp
@@ -46,6 +46,7 @@
"libmediametrics",
"libmediametricsservice",
"libprocessgroup",
+ "libprocessgroup_util",
"shared-file-region-aidl-cpp",
],
shared_libs: [
diff --git a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
index 710a656..b0b7e03 100644
--- a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
+++ b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
@@ -511,11 +511,11 @@
stream = getValue(&mFdp, kStreamtypes);
AudioSystem::setStreamVolume(stream, mFdp.ConsumeFloatingPoint<float>(),
- mFdp.ConsumeIntegral<int32_t>());
+ mFdp.ConsumeBool(), mFdp.ConsumeIntegral<int32_t>());
} else {
std::vector <audio_port_handle_t> portsForVolumeChange{};
AudioSystem::setPortsVolume(portsForVolumeChange, mFdp.ConsumeFloatingPoint<float>(),
- mFdp.ConsumeIntegral<int32_t>());
+ mFdp.ConsumeBool(), mFdp.ConsumeIntegral<int32_t>());
}
audio_mode_t mode = getValue(&mFdp, kModes);
AudioSystem::setMode(mode);
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 40e5673..31e4f05 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -126,7 +126,7 @@
// set stream volume on specified output
static status_t setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output);
+ bool muted, audio_io_handle_t output);
// mute/unmute stream
static status_t setStreamMute(audio_stream_type_t stream, bool mute);
@@ -135,11 +135,12 @@
* Set volume for given AudioTrack port ids on specified output
* @param portIds to consider
* @param volume to set
+ * @param muted to set
* @param output to consider
* @return NO_ERROR if successful
*/
static status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds,
- float volume, audio_io_handle_t output);
+ float volume, bool muted, audio_io_handle_t output);
// set audio mode in audio hardware
static status_t setMode(audio_mode_t mode);
@@ -345,7 +346,8 @@
std::vector<audio_io_handle_t> *secondaryOutputs,
bool *isSpatialized,
bool *isBitPerfect,
- float *volume);
+ float *volume,
+ bool *muted);
static status_t startOutput(audio_port_handle_t portId);
static status_t stopOutput(audio_port_handle_t portId);
static void releaseOutput(audio_port_handle_t portId);
@@ -391,6 +393,7 @@
int indexMax);
static status_t setStreamVolumeIndex(audio_stream_type_t stream,
int index,
+ bool muted,
audio_devices_t device);
static status_t getStreamVolumeIndex(audio_stream_type_t stream,
int *index,
@@ -398,6 +401,7 @@
static status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
int index,
+ bool muted,
audio_devices_t device);
static status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
int &index,
diff --git a/media/libaudioclient/include/media/AudioTimestamp.h b/media/libaudioclient/include/media/AudioTimestamp.h
index e5925dd..45d5595 100644
--- a/media/libaudioclient/include/media/AudioTimestamp.h
+++ b/media/libaudioclient/include/media/AudioTimestamp.h
@@ -154,10 +154,13 @@
std::string toString() const {
std::stringstream ss;
- ss << "BOOTTIME offset " << mTimebaseOffset[TIMEBASE_BOOTTIME] << "\n";
+ ss << "BOOTTIME offset " << mTimebaseOffset[TIMEBASE_BOOTTIME] << ": ExtendedTimestamp: ";
for (int i = 0; i < LOCATION_MAX; ++i) {
- ss << "ExtendedTimestamp[" << i << "] position: "
- << mPosition[i] << " time: " << mTimeNs[i] << "\n";
+ ss << "([" << i << "] position: "
+ << mPosition[i] << " time: " << mTimeNs[i] << ")";
+ if (i != LOCATION_MAX - 1) {
+ ss << ", ";
+ }
}
return ss.str();
}
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index a5f3217..21ecb09 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -226,18 +226,19 @@
* the preference panel, mostly.
*/
virtual status_t setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output) = 0;
+ bool muted, audio_io_handle_t output) = 0;
virtual status_t setStreamMute(audio_stream_type_t stream, bool muted) = 0;
/**
* Set volume for given AudioTrack port ids on specified output
* @param portIds to consider
* @param volume to set
+ * @param muted to set
* @param output to consider
* @return NO_ERROR if successful
*/
virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
- audio_io_handle_t output) = 0;
+ bool muted, audio_io_handle_t output) = 0;
// set audio mode
virtual status_t setMode(audio_mode_t mode) = 0;
@@ -428,10 +429,10 @@
status_t setMasterBalance(float balance) override;
status_t getMasterBalance(float* balance) const override;
status_t setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output) override;
+ bool muted, audio_io_handle_t output) override;
status_t setStreamMute(audio_stream_type_t stream, bool muted) override;
status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
- audio_io_handle_t output) override;
+ bool muted, audio_io_handle_t output) override;
status_t setMode(audio_mode_t mode) override;
status_t setMicMute(bool state) override;
bool getMicMute() const override;
@@ -675,10 +676,10 @@
Status setMasterBalance(float balance) override;
Status getMasterBalance(float* _aidl_return) override;
Status setStreamVolume(media::audio::common::AudioStreamType stream,
- float value, int32_t output) override;
+ float value, bool muted, int32_t output) override;
Status setStreamMute(media::audio::common::AudioStreamType stream, bool muted) override;
- Status setPortsVolume(const std::vector<int32_t>& portIds, float volume, int32_t output)
- override;
+ Status setPortsVolume(const std::vector<int32_t>& portIds, float volume, bool muted,
+ int32_t output) override;
Status setMode(media::audio::common::AudioMode mode) override;
Status setMicMute(bool state) override;
Status getMicMute(bool* _aidl_return) override;
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 7f55e48..2076045 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -483,8 +483,27 @@
AudioDeviceAddress::make<AudioDeviceAddress::Tag::alsa>(
std::vector<int32_t>{1, 2}))));
+TEST(AnonymizedBluetoothAddressRoundTripTest, Legacy2Aidl2Legacy) {
+ const std::vector<uint8_t> sAnonymizedAidlAddress {0xFD, 0xFF, 0xFF, 0xFF, 0xAB, 0xCD};
+ const std::string sAnonymizedLegacyAddress = std::string("XX:XX:XX:XX:AB:CD");
+ auto device = legacy2aidl_audio_device_AudioDevice(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+ sAnonymizedLegacyAddress);
+ ASSERT_TRUE(device.ok());
+ ASSERT_EQ(AudioDeviceAddress::Tag::mac, device.value().address.getTag());
+ ASSERT_EQ(sAnonymizedAidlAddress, device.value().address.get<AudioDeviceAddress::mac>());
+
+ audio_devices_t legacyType;
+ std::string legacyAddress;
+ status_t status =
+ aidl2legacy_AudioDevice_audio_device(device.value(), &legacyType, &legacyAddress);
+ ASSERT_EQ(OK, status);
+ EXPECT_EQ(legacyType, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP);
+ EXPECT_EQ(sAnonymizedLegacyAddress, legacyAddress);
+}
+
class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam<AudioFormatDescription> {
};
+
TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
const auto initial = GetParam();
auto conv = aidl2legacy_AudioFormatDescription_audio_format_t(initial);
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 75e2c11..74a64bf 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -23,7 +23,6 @@
],
required: [
- "libaudiohal@5.0",
"libaudiohal@6.0",
"libaudiohal@7.0",
"libaudiohal@7.1",
diff --git a/media/libaudiohal/FactoryHal.cpp b/media/libaudiohal/FactoryHal.cpp
index 15cb297..2c30693 100644
--- a/media/libaudiohal/FactoryHal.cpp
+++ b/media/libaudiohal/FactoryHal.cpp
@@ -50,12 +50,11 @@
* This list need to keep sync with AudioHalVersionInfo.VERSIONS in
* media/java/android/media/AudioHalVersionInfo.java.
*/
-static const std::array<AudioHalVersionInfo, 5> sAudioHALVersions = {
+static const std::array<AudioHalVersionInfo, 4> sAudioHALVersions = {
AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, 1, 0),
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 1),
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 0),
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0),
- AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 5, 0),
};
static const std::map<AudioHalVersionInfo::Type, InterfaceName> sDevicesHALInterfaces = {
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 1a6b949..f5dec56 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -83,32 +83,6 @@
}
cc_library_shared {
- name: "libaudiohal@5.0",
- defaults: [
- "libaudiohal_default",
- "libaudiohal_hidl_default",
- ],
- srcs: [
- ":audio_core_hal_client_sources",
- ":audio_effect_hidl_hal_client_sources",
- "EffectsFactoryHalEntry.cpp",
- ],
- shared_libs: [
- "android.hardware.audio.common@5.0",
- "android.hardware.audio.common@5.0-util",
- "android.hardware.audio.effect@5.0",
- "android.hardware.audio.effect@5.0-util",
- "android.hardware.audio@5.0",
- "android.hardware.audio@5.0-util",
- ],
- cflags: [
- "-DMAJOR_VERSION=5",
- "-DMINOR_VERSION=0",
- "-include common/all-versions/VersionMacro.h",
- ],
-}
-
-cc_library_shared {
name: "libaudiohal@6.0",
defaults: [
"libaudiohal_default",
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index d65701a..c4e4ae8 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -443,9 +443,29 @@
if (!mStream) return NO_INIT;
if (const auto state = getState(); isInPlayOrRecordState(state)) {
- return sendCommand(
- makeHalCommand<HalCommand::Tag::pause>(), reply,
+ StreamDescriptor::Reply localReply{};
+ StreamDescriptor::Reply* innerReply = reply ?: &localReply;
+ auto status = sendCommand(
+ makeHalCommand<HalCommand::Tag::pause>(), innerReply,
true /*safeFromNonWorkerThread*/); // The workers stops its I/O activity first.
+ if (status == STATUS_INVALID_OPERATION &&
+ !isInPlayOrRecordState(innerReply->state)) {
+ /**
+ * In case of transient states like DRAINING, the HAL may change its
+ * StreamDescriptor::State on its own and may not be in synchronization with client.
+ * Thus, client can send the unexpected command and HAL returns failure. such failure is
+ * natural. The client handles it gracefully.
+ * Example where HAL change its state,
+ * 1) DRAINING -> IDLE (on empty buffer)
+ * 2) DRAINING -> IDLE (on IStreamCallback::onDrainReady)
+ **/
+ AUGMENT_LOG(D,
+ "HAL failed to handle the 'pause' command, but stream state is in one of"
+ " the PAUSED kind of states, current state: %s",
+ toString(state).c_str());
+ return OK;
+ }
+ return status;
} else {
AUGMENT_LOG(D, "already stream in one of the PAUSED kind of states, current state: %s",
toString(state).c_str());
@@ -473,13 +493,9 @@
return INVALID_OPERATION;
}
return OK;
- } else if (state == StreamDescriptor::State::PAUSED ||
- state == StreamDescriptor::State::TRANSFER_PAUSED ||
- state == StreamDescriptor::State::DRAIN_PAUSED) {
+ } else if (isInPausedState(state)) {
return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
- } else if (state == StreamDescriptor::State::ACTIVE ||
- state == StreamDescriptor::State::TRANSFERRING ||
- state == StreamDescriptor::State::DRAINING) {
+ } else if (isInPlayOrRecordState(state)) {
AUGMENT_LOG(D, "already in stream state: %s", toString(state).c_str());
return OK;
} else {
@@ -528,7 +544,14 @@
}
void StreamHalAidl::onAsyncTransferReady() {
- if (auto state = getState(); state == StreamDescriptor::State::TRANSFERRING) {
+ StreamDescriptor::State state;
+ {
+ // Use 'mCommandReplyLock' to ensure that 'sendCommand' has finished updating the state
+ // after the reply from the 'burst' command.
+ std::lock_guard l(mCommandReplyLock);
+ state = getState();
+ }
+ if (state == StreamDescriptor::State::TRANSFERRING) {
// Retrieve the current state together with position counters unconditionally
// to ensure that the state on our side gets updated.
sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(),
@@ -539,7 +562,14 @@
}
void StreamHalAidl::onAsyncDrainReady() {
- if (auto state = getState(); state == StreamDescriptor::State::DRAINING) {
+ StreamDescriptor::State state;
+ {
+ // Use 'mCommandReplyLock' to ensure that 'sendCommand' has finished updating the state
+ // after the reply from the 'drain' command.
+ std::lock_guard l(mCommandReplyLock);
+ state = getState();
+ }
+ if (state == StreamDescriptor::State::DRAINING) {
// Retrieve the current state together with position counters unconditionally
// to ensure that the state on our side gets updated.
sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), nullptr,
diff --git a/media/libmedia/xsd/vts/Android.bp b/media/libmedia/xsd/vts/Android.bp
index 83ab977..add7b51 100644
--- a/media/libmedia/xsd/vts/Android.bp
+++ b/media/libmedia/xsd/vts/Android.bp
@@ -15,6 +15,7 @@
//
package {
+ default_team: "trendy_team_android_kernel",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_av_media_libmedia_license"
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 10a1da7..b267c08 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1816,8 +1816,6 @@
const sp<AudioSystem::AudioDeviceCallback>& deviceCallback)
: mCachedPlayerIId(PLAYER_PIID_INVALID),
mCallback(NULL),
- mCallbackCookie(NULL),
- mCallbackData(NULL),
mStreamType(AUDIO_STREAM_MUSIC),
mLeftVolume(1.0),
mRightVolume(1.0),
@@ -2085,7 +2083,7 @@
status_t MediaPlayerService::AudioOutput::open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
audio_format_t format, int bufferCount,
- AudioCallback cb, void *cookie,
+ AudioCallback cb, const wp<RefBase>& cookie,
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo,
bool doNotReconnect,
@@ -2514,6 +2512,15 @@
{
Mutex::Autolock lock(mLock);
track = mTrack;
+ }
+
+ // do not hold lock while joining.
+ if (track) {
+ track->stopAndJoinCallbacks();
+ }
+
+ {
+ Mutex::Autolock lock(mLock);
close_l(); // clears mTrack
}
// destruction of the track occurs outside of mutex.
@@ -2705,7 +2712,7 @@
return 0;
}
size_t actualSize = (*me->mCallback)(
- me.get(), buffer.data(), buffer.size(), me->mCallbackCookie,
+ me, buffer.data(), buffer.size(), me->mCallbackCookie,
CB_EVENT_FILL_BUFFER);
// Log when no data is returned from the callback.
@@ -2730,7 +2737,7 @@
return;
}
ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
- (*me->mCallback)(me.get(), NULL /* buffer */, 0 /* size */,
+ (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
me->mCallbackCookie, CB_EVENT_STREAM_END);
unlock();
}
@@ -2744,7 +2751,7 @@
return;
}
ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
- (*me->mCallback)(me.get(), NULL /* buffer */, 0 /* size */,
+ (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
unlock();
}
@@ -2794,7 +2801,7 @@
struct CallbackThread : public Thread {
CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink,
MediaPlayerBase::AudioSink::AudioCallback cb,
- void *cookie);
+ const wp<RefBase>& cookie);
protected:
virtual ~CallbackThread();
@@ -2804,7 +2811,7 @@
private:
wp<MediaPlayerBase::AudioSink> mSink;
MediaPlayerBase::AudioSink::AudioCallback mCallback;
- void *mCookie;
+ wp<RefBase> mCookie;
void *mBuffer;
size_t mBufferSize;
@@ -2815,7 +2822,7 @@
CallbackThread::CallbackThread(
const wp<MediaPlayerBase::AudioSink> &sink,
MediaPlayerBase::AudioSink::AudioCallback cb,
- void *cookie)
+ const wp<RefBase>& cookie)
: mSink(sink),
mCallback(cb),
mCookie(cookie),
@@ -2842,7 +2849,7 @@
}
size_t actualSize =
- (*mCallback)(sink.get(), mBuffer, mBufferSize, mCookie,
+ (*mCallback)(sink, mBuffer, mBufferSize, mCookie,
MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER);
if (actualSize > 0) {
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index cb544bd..76b7bcf 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -104,14 +104,14 @@
virtual int64_t getBufferDurationInUs() const;
virtual audio_output_flags_t getFlags() const { return mFlags; }
- virtual status_t open(
+ status_t open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
audio_format_t format, int bufferCount,
- AudioCallback cb, void *cookie,
+ AudioCallback cb, const wp<RefBase>& cookie,
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
const audio_offload_info_t *offloadInfo = NULL,
bool doNotReconnect = false,
- uint32_t suggestedFrameCount = 0);
+ uint32_t suggestedFrameCount = 0) override;
virtual void setPlayerIId(int32_t playerIId);
@@ -164,7 +164,7 @@
sp<AudioOutput> mNextOutput;
int mCachedPlayerIId;
AudioCallback mCallback;
- void * mCallbackCookie;
+ wp<RefBase> mCallbackCookie;
sp<CallbackData> mCallbackData;
audio_stream_type_t mStreamType;
audio_attributes_t * mAttributes;
diff --git a/media/libmediaplayerservice/include/MediaPlayerInterface.h b/media/libmediaplayerservice/include/MediaPlayerInterface.h
index be1aa00..495cf00 100644
--- a/media/libmediaplayerservice/include/MediaPlayerInterface.h
+++ b/media/libmediaplayerservice/include/MediaPlayerInterface.h
@@ -76,6 +76,33 @@
virtual ~Listener() {}
};
+ // For the AudioCallback, we provide a WeakWrapper class
+ // to wrap a virtual RefBase derived object to pass into the AudioCallback.
+ // This is not used for NuPlayer::Renderer, only for legacy AudioPlayer implementation.
+ template <typename T>
+ class WeakWrapper : public RefBase {
+ public:
+ explicit WeakWrapper(const sp<T>& object)
+ : mObject(object) {}
+
+ sp<T> promote() const {
+ if (mObject == nullptr) return {};
+ return mObject.promote();
+ }
+
+ static sp<T> promoteFromRefBase(const wp<RefBase>& weakWrapper) {
+ if (weakWrapper == nullptr) return {};
+ const auto refBase = weakWrapper.promote();
+ if (!refBase) return {};
+ const auto wrapper = sp<WeakWrapper<T>>::fromExisting(
+ static_cast<WeakWrapper<T>*>(refBase.get()));
+ return wrapper->promote();
+ }
+
+ private:
+ const wp<T> mObject;
+ };
+
// AudioSink: abstraction layer for audio output
class AudioSink : public RefBase {
public:
@@ -89,8 +116,8 @@
// Callback returns the number of bytes actually written to the buffer.
typedef size_t (*AudioCallback)(
- AudioSink *audioSink, void *buffer, size_t size, void *cookie,
- cb_event_t event);
+ const sp<AudioSink>& audioSink, void *buffer, size_t size,
+ const wp<RefBase>& cookie, cb_event_t event);
virtual ~AudioSink() {}
virtual bool ready() const = 0; // audio output is open and ready
@@ -117,7 +144,7 @@
audio_format_t format=AUDIO_FORMAT_PCM_16_BIT,
int bufferCount=DEFAULT_AUDIOSINK_BUFFERCOUNT,
AudioCallback cb = NULL,
- void *cookie = NULL,
+ const wp<RefBase>& cookie = {},
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
const audio_offload_info_t *offloadInfo = NULL,
bool doNotReconnect = false,
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 899d50e..f6aff83 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -912,12 +912,15 @@
// static
size_t NuPlayer::Renderer::AudioSinkCallback(
- MediaPlayerBase::AudioSink * /* audioSink */,
+ const sp<MediaPlayerBase::AudioSink>& /* audioSink */,
void *buffer,
size_t size,
- void *cookie,
+ const wp<RefBase>& cookie,
MediaPlayerBase::AudioSink::cb_event_t event) {
- NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
+ if (cookie == nullptr) return 0;
+ const auto ref = cookie.promote();
+ if (!ref) return 0;
+ const auto me = static_cast<NuPlayer::Renderer*>(ref.get()); // we already hold a sp.
switch (event) {
case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
diff --git a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h
index 574ad3d..cfa742e 100644
--- a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h
@@ -43,8 +43,8 @@
uint32_t flags = 0);
static size_t AudioSinkCallback(
- MediaPlayerBase::AudioSink *audioSink,
- void *data, size_t size, void *me,
+ const sp<MediaPlayerBase::AudioSink>& audioSink,
+ void *data, size_t size, const wp<RefBase>& me,
MediaPlayerBase::AudioSink::cb_event_t event);
void queueBuffer(
diff --git a/media/libstagefright/xmlparser/vts/Android.bp b/media/libstagefright/xmlparser/vts/Android.bp
index 1e36c8f..527230c 100644
--- a/media/libstagefright/xmlparser/vts/Android.bp
+++ b/media/libstagefright/xmlparser/vts/Android.bp
@@ -15,6 +15,7 @@
//
package {
+ default_team: "trendy_team_android_media_codec_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index d916fd1..b5124d0 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -51,6 +51,11 @@
],
}
+vintf_fragment {
+ name: "manifest_media_c2_software.xml",
+ src: "manifest_media_c2_software.xml",
+}
+
mediaserver_cc_binary {
name: "mediaserver",
@@ -88,7 +93,7 @@
"-Wall",
],
- vintf_fragments: ["manifest_media_c2_software.xml"],
+ vintf_fragment_modules: ["manifest_media_c2_software.xml"],
soong_config_variables: {
TARGET_DYNAMIC_64_32_MEDIASERVER: {
diff --git a/media/module/aidlpersistentsurface/Android.bp b/media/module/aidlpersistentsurface/Android.bp
index 5c1a010..8b273f3 100644
--- a/media/module/aidlpersistentsurface/Android.bp
+++ b/media/module/aidlpersistentsurface/Android.bp
@@ -3,6 +3,9 @@
unstable: true,
local_include_dir: "aidl",
min_sdk_version: "29",
+ defaults: [
+ "android.hardware.graphics.common-latest"
+ ],
srcs: [
"aidl/android/media/AidlColorAspects.aidl",
"aidl/android/media/IAidlGraphicBufferSource.aidl",
@@ -12,9 +15,6 @@
headers: [
"HardwareBuffer_aidl",
],
- imports: [
- "android.hardware.graphics.common-V5",
- ],
include_dirs: [
"frameworks/native/aidl/gui",
],
@@ -41,6 +41,9 @@
cc_library_shared {
name: "libstagefright_graphicbuffersource_aidl",
min_sdk_version: "29",
+ defaults: [
+ "android.hardware.graphics.common-ndk_shared",
+ ],
srcs: [
"AidlGraphicBufferSource.cpp",
"wrapper/WAidlGraphicBufferSource.cpp",
@@ -56,7 +59,6 @@
"media_plugin_headers",
],
shared_libs: [
- "android.hardware.graphics.common-V5-ndk",
"graphicbuffersource-aidl-ndk",
"libbinder_ndk",
"libcutils",
diff --git a/media/module/codecs/amrwb/enc/Android.bp b/media/module/codecs/amrwb/enc/Android.bp
index 04f36b5..6ca3b6e 100644
--- a/media/module/codecs/amrwb/enc/Android.bp
+++ b/media/module/codecs/amrwb/enc/Android.bp
@@ -96,8 +96,6 @@
"-DARM",
"-DARMV7",
"-DASM_OPT",
- // don't actually generate neon instructions, see bug 26932980
- "-mfpu=vfpv3",
],
local_include_dirs: [
"src/asm/ARMV7",
diff --git a/media/module/extractors/extractor.aconfig b/media/module/extractors/extractor.aconfig
index c61efa4..c9bf694 100644
--- a/media/module/extractors/extractor.aconfig
+++ b/media/module/extractors/extractor.aconfig
@@ -7,6 +7,7 @@
flag {
name: "extractor_sniff_midi_optimizations"
is_exported: true
+ is_fixed_read_only: true
namespace: "media_extractor"
description: "Enable SniffMidi optimizations."
bug: "359920208"
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index 4645a75..26e5ddf 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -300,7 +300,6 @@
int count = mChildThreads.size();
for (int i = 0; i < count; i++) {
mChildThreads[i].join();
- delete &mChildThreads[i];
}
mChildThreads.clear();
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/BlockModelDecoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/BlockModelDecoder.java
new file mode 100644
index 0000000..3b3640e
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/BlockModelDecoder.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2024 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 com.android.media.benchmark.library;
+
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.os.Build;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.List;
+
+import com.android.media.benchmark.library.Decoder;
+
+public class BlockModelDecoder extends Decoder {
+ private static final String TAG = BlockModelDecoder.class.getSimpleName();
+ private final boolean DEBUG = false;
+ protected final LinearBlockWrapper mLinearInputBlock = new LinearBlockWrapper();
+
+ /**
+ * Wrapper class for {@link MediaCodec.LinearBlock}
+ */
+ public static class LinearBlockWrapper {
+ private MediaCodec.LinearBlock mBlock;
+ private ByteBuffer mBuffer;
+ private int mOffset;
+
+ public MediaCodec.LinearBlock getBlock() {
+ return mBlock;
+ }
+
+ public ByteBuffer getBuffer() {
+ return mBuffer;
+ }
+
+ public int getBufferCapacity() {
+ return mBuffer == null ? 0 : mBuffer.capacity();
+ }
+
+ public int getOffset() {
+ return mOffset;
+ }
+
+ public void setOffset(int size) {
+ mOffset = size;
+ }
+
+ public boolean allocateBlock(String codec, int size) throws RuntimeException{
+ recycle();
+ mBlock = MediaCodec.LinearBlock.obtain(size, new String[]{codec});
+ if (mBlock == null || !mBlock.isMappable()) {
+ throw new RuntimeException("Linear Block not allocated/mapped");
+ }
+ mBuffer = mBlock.map();
+ mOffset = 0;
+ return true;
+ }
+
+ public void recycle() {
+ if (mBlock != null) {
+ mBlock.recycle();
+ mBlock = null;
+ }
+ mBuffer = null;
+ mOffset = 0;
+ }
+ }
+
+ public BlockModelDecoder() {
+ // empty
+ }
+
+ public void tearDown() {
+ mLinearInputBlock.recycle();
+
+ }
+
+ /**
+ * Decodes the given input buffer,
+ * provided valid list of buffer info and format are passed as inputs.
+ *
+ * @param inputBuffer Decode the provided list of ByteBuffers
+ * @param inputBufferInfo List of buffer info corresponding to provided input buffers
+ * @param asyncMode Will run on async implementation if true
+ * @param format For creating the decoder if codec name is empty and configuring it
+ * @param codecName Will create the decoder with codecName
+ * @return DECODE_SUCCESS if decode was successful, DECODE_DECODER_ERROR for fail,
+ * DECODE_CREATE_ERROR for decoder not created
+ * @throws IOException if the codec cannot be created.
+ */
+ @Override
+ public int decode(@NonNull List<ByteBuffer> inputBuffer,
+ @NonNull List<MediaCodec.BufferInfo> inputBufferInfo, final boolean asyncMode,
+ @NonNull MediaFormat format, String codecName)
+ throws IOException, InterruptedException {
+ setExtraConfigureFlags(MediaCodec.CONFIGURE_FLAG_USE_BLOCK_MODEL);
+ return super.decode(inputBuffer, inputBufferInfo, asyncMode, format, codecName);
+ }
+
+ @Override
+ protected void onInputAvailable(int inputBufferId, MediaCodec mediaCodec) {
+ if (mNumInFramesProvided >= mNumInFramesRequired) {
+ mIndex = mInputBufferInfo.size() - 1;
+ }
+ MediaCodec.BufferInfo bufInfo = mInputBufferInfo.get(mIndex);
+ mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ if (mLinearInputBlock.getOffset() + bufInfo.size > mLinearInputBlock.getBufferCapacity()) {
+ int requestSize = 8192;
+ requestSize = Math.max(bufInfo.size, requestSize);
+ mLinearInputBlock.allocateBlock(mediaCodec.getCanonicalName(), requestSize);
+ }
+ int codecFlags = 0;
+ if ((bufInfo.flags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
+ codecFlags |= MediaCodec.BUFFER_FLAG_KEY_FRAME;
+ }
+ if ((bufInfo.flags & MediaExtractor.SAMPLE_FLAG_PARTIAL_FRAME) != 0) {
+ codecFlags |= MediaCodec.BUFFER_FLAG_PARTIAL_FRAME;
+ }
+ codecFlags |= mSawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0;
+ if (DEBUG) {
+ Log.v(TAG, "input: id: " + inputBufferId
+ + " size: " + bufInfo.size
+ + " pts: " + bufInfo.presentationTimeUs
+ + " flags: " + codecFlags);
+ }
+ mLinearInputBlock.getBuffer().put(mInputBuffer.get(mIndex).array());
+ mNumInFramesProvided++;
+ mIndex = mNumInFramesProvided % (mInputBufferInfo.size() - 1);
+ if (mSawInputEOS) {
+ Log.i(TAG, "Saw Input EOS");
+ }
+ mStats.addFrameSize(bufInfo.size);
+ MediaCodec.QueueRequest request = mCodec.getQueueRequest(inputBufferId);
+ request.setLinearBlock(mLinearInputBlock.getBlock(), mLinearInputBlock.getOffset(),
+ bufInfo.size);
+ request.setPresentationTimeUs(bufInfo.presentationTimeUs);
+ request.setFlags(codecFlags);
+ request.queue();
+ if (bufInfo.size > 0 && (codecFlags & (MediaCodec.BUFFER_FLAG_CODEC_CONFIG
+ | MediaCodec.BUFFER_FLAG_PARTIAL_FRAME)) == 0) {
+ mLinearInputBlock.setOffset(mLinearInputBlock.getOffset() + bufInfo.size);
+ }
+ }
+
+ @Override
+ protected void onOutputAvailable(
+ MediaCodec mediaCodec, int outputBufferId, MediaCodec.BufferInfo outputBufferInfo) {
+ if (mSawOutputEOS || outputBufferId < 0) {
+ return;
+ }
+ mNumOutputFrame++;
+ if (DEBUG) {
+ Log.d(TAG,
+ "In OutputBufferAvailable ,"
+ + " output frame number = " + mNumOutputFrame
+ + " timestamp = " + outputBufferInfo.presentationTimeUs
+ + " size = " + outputBufferInfo.size);
+ }
+ MediaCodec.OutputFrame outFrame = mediaCodec.getOutputFrame(outputBufferId);
+ ByteBuffer outputBuffer = null;
+ try {
+ if (outFrame.getLinearBlock() != null) {
+ outputBuffer = outFrame.getLinearBlock().map();
+ }
+ } catch(IllegalStateException e) {
+ // buffer may not be linear, this is ok
+ // as we are handling non-linear buffers below.
+ }
+ if (mOutputStream != null) {
+ try {
+ if (outputBuffer != null) {
+ byte[] bytesOutput = new byte[outputBuffer.remaining()];
+ outputBuffer.get(bytesOutput);
+ mOutputStream.write(bytesOutput);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ Log.d(TAG, "Error Dumping File: Exception " + e.toString());
+ }
+ }
+ ByteBuffer copiedBuffer = null;
+ int bytesRemaining = 0;
+ if (outputBuffer != null) {
+ bytesRemaining = outputBuffer.remaining();
+ if (mIBufferSend != null) {
+ copiedBuffer = ByteBuffer.allocate(outputBuffer.remaining());
+ copiedBuffer.put(outputBuffer);
+ }
+ outFrame.getLinearBlock().recycle();
+ outputBuffer = null;
+ }
+ if (mFrameReleaseQueue != null) {
+ if (mMime.startsWith("audio/")) {
+ try {
+ mFrameReleaseQueue.pushFrame(outputBufferId, bytesRemaining);
+ } catch (Exception e) {
+ Log.d(TAG, "Error in getting MediaCodec buffer" + e.toString());
+ }
+ } else {
+ mFrameReleaseQueue.pushFrame(mNumOutputFrame, outputBufferId,
+ outputBufferInfo.presentationTimeUs);
+ }
+
+ } else if (mIBufferSend != null) {
+ IBufferXfer.BufferXferInfo info = new IBufferXfer.BufferXferInfo();
+ // TODO: may be inefficient;
+ info.buf = copiedBuffer;
+ info.idx = outputBufferId;
+ info.obj = mediaCodec;
+ info.bytesRead = outputBufferInfo.size;
+ info.presentationTimeUs = outputBufferInfo.presentationTimeUs;
+ info.flag = outputBufferInfo.flags;
+ mIBufferSend.sendBuffer(this, info);
+ } else {
+ mediaCodec.releaseOutputBuffer(outputBufferId, mRender);
+ }
+ mSawOutputEOS = (outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ if (DEBUG && mSawOutputEOS) {
+ Log.i(TAG, "Saw output EOS");
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
index f223242..031817b 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
@@ -78,4 +78,21 @@
}
return null;
}
+ /**
+ * Returns compression ratio for a given mediaType.
+ * @param mediaType mime type for which compression ratio is to be returned.
+ */
+ public static float getCompressionRatio(String mediaType) {
+ switch (mediaType) {
+ case MediaFormat.MIMETYPE_AUDIO_FLAC:
+ return 0.7f;
+ case MediaFormat.MIMETYPE_AUDIO_G711_MLAW:
+ case MediaFormat.MIMETYPE_AUDIO_G711_ALAW:
+ case MediaFormat.MIMETYPE_AUDIO_MSGSM:
+ return 0.5f;
+ case MediaFormat.MIMETYPE_AUDIO_RAW:
+ return 1.0f;
+ }
+ return 0.1f;
+ }
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
index e9b337d..2ea0ed2 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
@@ -18,6 +18,7 @@
import android.view.Surface;
+import android.media.AudioFormat;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaFormat;
@@ -42,6 +43,7 @@
protected final Object mLock = new Object();
protected MediaCodec mCodec;
+ protected int mExtraFlags = 0;
protected Surface mSurface = null;
protected boolean mRender = false;
protected ArrayList<BufferInfo> mInputBufferInfo;
@@ -58,6 +60,8 @@
protected int mNumOutputFrame;
protected int mIndex;
+ protected boolean mUseFrameReleaseQueue = false;
+
protected ArrayList<ByteBuffer> mInputBuffer;
protected FileOutputStream mOutputStream;
protected FrameReleaseQueue mFrameReleaseQueue = null;
@@ -85,6 +89,11 @@
mIBufferSend = receiver;
return true;
}
+
+ public void setExtraConfigureFlags(int flags) {
+ this.mExtraFlags = flags;
+ }
+
/**
* Setup of decoder
*
@@ -94,17 +103,32 @@
mSignalledError = false;
mOutputStream = outputStream;
}
+
+ /*
+ * This can be used to setup audio decoding, simulating audio playback.
+ */
+ public void setupDecoder(
+ boolean render, boolean useFrameReleaseQueue, int numInFramesRequired) {
+ mRender = render;
+ mUseFrameReleaseQueue = useFrameReleaseQueue;
+ mNumInFramesRequired = numInFramesRequired;
+ mSignalledError = false;
+ setupDecoder(null);
+ }
+
public void setupDecoder(Surface surface, boolean render,
boolean useFrameReleaseQueue, int frameRate) {
setupDecoder(surface, render, useFrameReleaseQueue, frameRate, -1);
}
+
public void setupDecoder(Surface surface, boolean render,
boolean useFrameReleaseQueue, int frameRate, int numInFramesRequired) {
mSignalledError = false;
mOutputStream = null;
mSurface = surface;
mRender = render;
- if (useFrameReleaseQueue) {
+ mUseFrameReleaseQueue = useFrameReleaseQueue;
+ if (mUseFrameReleaseQueue) {
Log.i(TAG, "Using FrameReleaseQueue with frameRate " + frameRate);
mFrameReleaseQueue = new FrameReleaseQueue(mRender, frameRate);
}
@@ -166,6 +190,18 @@
public void onOutputFormatChanged(
@NonNull MediaCodec mediaCodec, @NonNull MediaFormat format) {
Log.i(TAG, "Output format changed. Format: " + format.toString());
+ if (mUseFrameReleaseQueue
+ && mFrameReleaseQueue == null && mMime.startsWith("audio/")) {
+ // start a frame release thread for this configuration.
+ int bytesPerSample = AudioFormat.getBytesPerSample(
+ format.getInteger(MediaFormat.KEY_PCM_ENCODING,
+ AudioFormat.ENCODING_PCM_16BIT));
+ int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+ int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+ mFrameReleaseQueue = new FrameReleaseQueue(
+ mRender, sampleRate, channelCount, bytesPerSample);
+ mFrameReleaseQueue.setMediaCodec(mCodec);
+ }
}
@Override
@@ -223,11 +259,10 @@
if (asyncMode) {
setCallback(mCodec);
}
- int isEncoder = 0;
if (DEBUG) {
Log.d(TAG, "Media Format : " + format.toString());
}
- mCodec.configure(format, mSurface, null, isEncoder);
+ mCodec.configure(format, mSurface, null, mExtraFlags);
mCodec.start();
Log.i(TAG, "Codec started async mode ? " + asyncMode);
@@ -395,8 +430,17 @@
}
}
if (mFrameReleaseQueue != null) {
- mFrameReleaseQueue.pushFrame(mNumOutputFrame, outputBufferId,
- outputBufferInfo.presentationTimeUs);
+ if (mMime.startsWith("audio/")) {
+ try {
+ ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferId);
+ mFrameReleaseQueue.pushFrame(outputBufferId, outputBuffer.remaining());
+ } catch (Exception e) {
+ Log.d(TAG, "Error in getting MediaCodec buffer" + e.toString());
+ }
+ } else {
+ mFrameReleaseQueue.pushFrame(mNumOutputFrame, outputBufferId,
+ outputBufferInfo.presentationTimeUs);
+ }
} else if (mIBufferSend != null) {
IBufferXfer.BufferXferInfo info = new IBufferXfer.BufferXferInfo();
info.buf = mediaCodec.getOutputBuffer(outputBufferId);
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
index 20a2573..0861c2c 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
@@ -29,45 +29,89 @@
public class FrameReleaseQueue {
private static final String TAG = "FrameReleaseQueue";
+ private static final boolean DEBUG = false;
private final String MIME_AV1 = "video/av01";
private final int AV1_SUPERFRAME_DELAY = 6;
private final int THRESHOLD_TIME = 5;
+ private final long HOUR_IN_MS = (60 * 60 * 1000L);
+ private final long MINUTE_IN_MS = (60 * 1000L);
+
private MediaCodec mCodec;
private LinkedBlockingQueue<FrameInfo> mFrameInfoQueue;
private ReleaseThread mReleaseThread;
private AtomicBoolean doFrameRelease = new AtomicBoolean(false);
- private boolean mReleaseJobStarted = false;
+ private AtomicBoolean mReleaseJobStarted = new AtomicBoolean(false);
private boolean mRender = false;
- private int mWaitTime = 40; // milliseconds per frame
+ private long mWaitTime = 40; // milliseconds per frame
private int mWaitTimeCorrection = 0;
private int mCorrectionLoopCount;
- private int firstReleaseTime = -1;
- private int mAllowedDelayTime = THRESHOLD_TIME;
+ protected long firstReleaseTime = -1;
+ private long mAllowedDelayTime = THRESHOLD_TIME;
private int mFrameDelay = 0;
private final ScheduledExecutorService mScheduler = Executors.newScheduledThreadPool(1);
+ public FrameReleaseQueue(boolean render, int frameRate) {
+ this.mFrameInfoQueue = new LinkedBlockingQueue();
+ this.mReleaseThread = new ReleaseThread();
+ this.doFrameRelease.set(true);
+ this.mRender = render;
+ this.mWaitTime = 1000 / frameRate; // wait time in milliseconds per frame
+ int waitTimeRemainder = 1000 % frameRate;
+ int gcd = gcd(frameRate, waitTimeRemainder);
+ this.mCorrectionLoopCount = frameRate / gcd;
+ this.mWaitTimeCorrection = waitTimeRemainder / gcd;
+ Log.i(TAG, "Constructed FrameReleaseQueue with wait time " + this.mWaitTime + " ms");
+ }
+
+ public FrameReleaseQueue(boolean render, int sampleRate, int nChannels, int bytesPerChannel) {
+ this.mFrameInfoQueue = new LinkedBlockingQueue();
+ this.doFrameRelease.set(true);
+ this.mRender = render;
+ this.mReleaseThread = new AudioRendererThread(sampleRate, nChannels, bytesPerChannel);
+ }
private static class FrameInfo {
private int number;
private int bufferId;
private int displayTime;
+ private int bytes;
public FrameInfo(int frameNumber, int frameBufferId, int frameDisplayTime) {
this.number = frameNumber;
this.bufferId = frameBufferId;
this.displayTime = frameDisplayTime;
}
+ public FrameInfo(int frameBufferId, int bytes) {
+ this.bufferId = frameBufferId;
+ this.bytes = bytes;
+ }
}
private class ReleaseThread extends Thread {
private int mLoopCount = 0;
- private int mNextReleaseTime = 0;
+ private long mNextReleaseTime = 0;
+
+ protected void printPlaybackTime() {
+ if (firstReleaseTime == -1) {
+ Log.d(TAG, "Playback Time not initialized");
+ return;
+ }
+ long curTime = getCurSysTime() - firstReleaseTime;
+ long hours = curTime / (HOUR_IN_MS);
+ curTime -= (hours * HOUR_IN_MS);
+ long min = curTime / MINUTE_IN_MS;
+ curTime -= (min * MINUTE_IN_MS);
+ Log.d(TAG, "Playback time: "
+ + hours + "h "
+ + min + "m "
+ + (double)(curTime / (double)1000) +"s");
+ }
@SuppressWarnings("FutureReturnValueIgnored")
public void run() {
/* Check if the release thread wakes up too late */
if (mLoopCount != 0) {
- int delta = getCurSysTime() - mNextReleaseTime;
+ long delta = getCurSysTime() - mNextReleaseTime;
if (delta >= THRESHOLD_TIME) {
Log.d(TAG, "Release thread wake up late by " + delta);
/* For accidental late wake up, we should relax the timestamp
@@ -93,8 +137,8 @@
popAndRelease(false);
} else {
mNextReleaseTime += mWaitTime;
- int curSysTime = getCurSysTime();
- int curMediaTime = curSysTime - firstReleaseTime;
+ long curSysTime = getCurSysTime();
+ long curMediaTime = curSysTime - firstReleaseTime;
while (curFrameInfo != null && curFrameInfo.displayTime > 0 &&
curFrameInfo.displayTime <= curMediaTime) {
if (!((curMediaTime - curFrameInfo.displayTime) <= mAllowedDelayTime)) {
@@ -123,21 +167,86 @@
mNextReleaseTime += mWaitTimeCorrection;
}
mLoopCount += 1;
+ } else {
+ mReleaseJobStarted.set(false);
}
}
}
- public FrameReleaseQueue(boolean render, int frameRate) {
- this.mFrameInfoQueue = new LinkedBlockingQueue();
- this.mReleaseThread = new ReleaseThread();
- this.doFrameRelease.set(true);
- this.mRender = render;
- this.mWaitTime = 1000 / frameRate; // wait time in milliseconds per frame
- int waitTimeRemainder = 1000 % frameRate;
- int gcd = gcd(frameRate, waitTimeRemainder);
- this.mCorrectionLoopCount = frameRate / gcd;
- this.mWaitTimeCorrection = waitTimeRemainder / gcd;
- Log.i(TAG, "Constructed FrameReleaseQueue with wait time " + this.mWaitTime + " ms");
+ private class AudioRendererThread extends ReleaseThread {
+ private final int WAIT_FOR_BUFFER_IN_SEC = 2;
+ private double mTimeAdjustMs = 0;
+ private double mMsForByte = 0;
+ private double mExpectedWakeUpTime = 0;
+ private FrameInfo mCurrentFrameInfo;
+
+ AudioRendererThread(int sampleRate, int nChannels, int bytesPerChannel) {
+ if (DEBUG) {
+ Log.d(TAG, "sampleRate " + sampleRate
+ + " nChannels " + nChannels
+ + " bytesPerChannel " + bytesPerChannel);
+ }
+ this.mMsForByte = 1000 / (double)(sampleRate * nChannels * bytesPerChannel);
+ }
+
+ @Override
+ @SuppressWarnings("FutureReturnValueIgnored")
+ public void run() {
+ long curTime = getCurSysTime();
+ if (DEBUG) {
+ if (firstReleaseTime == -1) {
+ firstReleaseTime = curTime;
+ }
+ printPlaybackTime();
+ }
+ if (mMsForByte == 0) {
+ Log.e(TAG, "Audio rendering not possible, no valid params");
+ return;
+ }
+ if (mCurrentFrameInfo != null) {
+ try {
+ mCodec.releaseOutputBuffer(mCurrentFrameInfo.bufferId, mRender);
+ } catch (IllegalStateException e) {
+ doFrameRelease.set(false);
+ Log.e(TAG, "Threw InterruptedException on releaseOutputBuffer");
+ } finally {
+ mCurrentFrameInfo = null;
+ }
+ }
+ boolean requestedSchedule = false;
+ try {
+ while (doFrameRelease.get() || mFrameInfoQueue.size() > 0) {
+ mCurrentFrameInfo = mFrameInfoQueue.poll(
+ WAIT_FOR_BUFFER_IN_SEC, TimeUnit.SECONDS);
+ if (mCurrentFrameInfo != null) {
+ mTimeAdjustMs = 0;
+ if (mExpectedWakeUpTime != 0) {
+ mTimeAdjustMs = mExpectedWakeUpTime - getCurSysTime();
+ }
+ double sleepTimeUs =
+ (mMsForByte * mCurrentFrameInfo.bytes + mTimeAdjustMs) * 1000;
+ mExpectedWakeUpTime = getCurSysTime() + (sleepTimeUs / 1000);
+ if (DEBUG) {
+ Log.d(TAG, " mExpectedWakeUpTime " + mExpectedWakeUpTime
+ + " Waiting for " + (long)(sleepTimeUs) + "us"
+ + " Now " + getCurSysTime()
+ + " bytes " + mCurrentFrameInfo.bytes
+ + " bufferID " + mCurrentFrameInfo.bufferId);
+ }
+ mScheduler.schedule(
+ mReleaseThread,(long)(sleepTimeUs),TimeUnit.MICROSECONDS);
+ requestedSchedule = true;
+ break;
+ }
+ }
+ } catch(InterruptedException e) {
+ Log.d(TAG, "Interrupted during poll wait");
+ doFrameRelease.set(false);
+ }
+ if (!requestedSchedule) {
+ mReleaseJobStarted.set(false);
+ }
+ }
}
private static int gcd(int a, int b) {
@@ -154,6 +263,19 @@
}
}
+ public boolean pushFrame(int frameBufferId, int bytes) {
+ FrameInfo info = new FrameInfo(frameBufferId, bytes);
+ boolean pushSuccess = mFrameInfoQueue.offer(info);
+ if (!pushSuccess) {
+ Log.e(TAG, "Failed to push frame with buffer id " + info.bufferId);
+ return false;
+ }
+ if (!mReleaseJobStarted.get()) {
+ mScheduler.execute(mReleaseThread);
+ mReleaseJobStarted.set(true);
+ }
+ return true;
+ }
public boolean pushFrame(int frameNumber, int frameBufferId, long frameDisplayTime) {
int frameDisplayTimeMs = (int)(frameDisplayTime/1000);
FrameInfo curFrameInfo = new FrameInfo(frameNumber, frameBufferId, frameDisplayTimeMs);
@@ -163,16 +285,16 @@
return false;
}
- if (!mReleaseJobStarted && frameNumber >= mFrameDelay) {
+ if (!mReleaseJobStarted.get() && frameNumber >= mFrameDelay) {
mScheduler.execute(mReleaseThread);
- mReleaseJobStarted = true;
+ mReleaseJobStarted.set(true);
Log.i(TAG, "Started frame release thread");
}
return true;
}
- private int getCurSysTime() {
- return (int)(System.nanoTime()/1000000);
+ private long getCurSysTime() {
+ return (long)(System.nanoTime() / 1000000L);
}
@SuppressWarnings("FutureReturnValueIgnored")
@@ -196,7 +318,7 @@
public void stopFrameRelease() {
doFrameRelease.set(false);
- while (mFrameInfoQueue.size() > 0) {
+ while (mReleaseJobStarted.get()) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java
index c97a35c..bbc3d48 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java
@@ -16,6 +16,8 @@
package com.android.media.benchmark.library;
import android.media.MediaCodec;
+
+import java.util.ArrayDeque;
import java.nio.ByteBuffer;
/**
* interfaces that can be used to implement
@@ -26,10 +28,11 @@
public ByteBuffer buf;
public int idx;
public Object obj;
- int flag;
- int bytesRead;
- boolean isComplete = true;
- long presentationTimeUs;
+ public ArrayDeque<MediaCodec.BufferInfo> infos;
+ public int flag;
+ public int bytesRead;
+ public boolean isComplete = true;
+ public long presentationTimeUs;
}
public interface IReceiveBuffer {
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java
index 3e6cee1..c68ac8a 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java
@@ -96,10 +96,10 @@
pBuf.info.buf.remaining() +" C:" + cBuf.info.buf.remaining());
}
}
+ cBuf.info.infos = pBuf.info.infos;
cBuf.info.bytesRead = bytesRead;
cBuf.info.presentationTimeUs = pBuf.info.presentationTimeUs;
cBuf.info.flag = pBuf.info.flag;
-
if (pBuf.rIface != null) {
pBuf.rIface.receiveBuffer(pBuf.info);
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitBlockModelDecoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitBlockModelDecoder.java
new file mode 100644
index 0000000..ed2defe
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitBlockModelDecoder.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2024 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 com.android.media.benchmark.library;
+
+import android.media.AudioFormat;
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.os.Build;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import java.util.ArrayDeque;
+import java.util.Iterator;
+import java.util.List;
+
+import com.android.media.benchmark.library.CodecUtils;
+import com.android.media.benchmark.library.BlockModelDecoder;
+
+public class MultiAccessUnitBlockModelDecoder extends BlockModelDecoder {
+ private static final String TAG = MultiAccessUnitBlockModelDecoder.class.getSimpleName();
+ private final ArrayDeque<MediaCodec.BufferInfo> mInputInfos = new ArrayDeque<>();
+ private final boolean DEBUG = false;
+ protected int mMaxInputSize = 0;
+
+ public MultiAccessUnitBlockModelDecoder() {
+ // empty
+ }
+
+ /**
+ * Decodes the given input buffer,
+ * provided valid list of buffer info and format are passed as inputs.
+ *
+ * @param inputBuffer Decode the provided list of ByteBuffers
+ * @param inputBufferInfo List of buffer info corresponding to provided input buffers
+ * @param asyncMode Will run on async implementation if true
+ * @param format For creating the decoder if codec name is empty and configuring it
+ * @param codecName Will create the decoder with codecName
+ * @return DECODE_SUCCESS if decode was successful, DECODE_DECODER_ERROR for fail,
+ * DECODE_CREATE_ERROR for decoder not created
+ * @throws IOException if the codec cannot be created.
+ */
+ @Override
+ public int decode(@NonNull List<ByteBuffer> inputBuffer,
+ @NonNull List<MediaCodec.BufferInfo> inputBufferInfo, final boolean asyncMode,
+ @NonNull MediaFormat format, String codecName)
+ throws IOException, InterruptedException {
+ setExtraConfigureFlags(MediaCodec.CONFIGURE_FLAG_USE_BLOCK_MODEL);
+ configureMaxInputSize(format);
+ return super.decode(inputBuffer, inputBufferInfo, asyncMode, format, codecName);
+ }
+
+ protected void configureMaxInputSize(MediaFormat format) {
+ final String mime = format.getString(MediaFormat.KEY_MIME);
+ final int maxOutputSize = format.getNumber(
+ MediaFormat.KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE, 0).intValue();
+ final int maxInputSizeInBytes = format.getInteger(
+ MediaFormat.KEY_MAX_INPUT_SIZE);
+ mMaxInputSize = Math.max(maxInputSizeInBytes,
+ (int) (maxOutputSize * CodecUtils.getCompressionRatio(mime)));
+ }
+
+ @Override
+ public void setCallback(MediaCodec codec) {
+ mCodec.setCallback(new MediaCodec.Callback() {
+ boolean isUsingLargeFrameMode = false;
+
+ @Override
+ public void onInputBufferAvailable(
+ @NonNull MediaCodec mediaCodec, int inputBufferId) {
+ try {
+ mStats.addInputTime();
+ if (isUsingLargeFrameMode) {
+ onInputsAvailable(inputBufferId, mediaCodec);
+ } else {
+ onInputAvailable(inputBufferId, mediaCodec);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ @Override
+ public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
+ int outputBufferId, @NonNull MediaCodec.BufferInfo bufferInfo) {
+ mStats.addOutputTime();
+ onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
+ if (mSawOutputEOS) {
+ synchronized (mLock) { mLock.notify(); }
+ }
+ }
+
+ @Override
+ public void onOutputBuffersAvailable(
+ @NonNull MediaCodec mediaCodec,
+ int outputBufferId, @NonNull ArrayDeque<MediaCodec.BufferInfo> infos) {
+ int i = 0;
+ while(i++ < infos.size()) {
+ mStats.addOutputTime();
+ }
+ onOutputsAvailable(mediaCodec, outputBufferId, infos);
+ if (mSawOutputEOS) {
+ synchronized (mLock) { mLock.notify(); }
+ }
+ }
+
+ @Override
+ public void onOutputFormatChanged(
+ @NonNull MediaCodec mediaCodec, @NonNull MediaFormat format) {
+ Log.i(TAG, "Output format changed. Format: " + format.toString());
+ final int maxOutputSize = format.getNumber(
+ MediaFormat.KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE, 0).intValue();
+ isUsingLargeFrameMode = (maxOutputSize > 0);
+ configureMaxInputSize(format);
+ if (mUseFrameReleaseQueue && mFrameReleaseQueue == null) {
+ int bytesPerSample = AudioFormat.getBytesPerSample(
+ format.getInteger(MediaFormat.KEY_PCM_ENCODING,
+ AudioFormat.ENCODING_PCM_16BIT));
+ int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+ int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+ mFrameReleaseQueue = new FrameReleaseQueue(
+ mRender, sampleRate, channelCount, bytesPerSample);
+ mFrameReleaseQueue.setMediaCodec(mCodec);
+ }
+ }
+
+ @Override
+ public void onError(
+ @NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
+ mSignalledError = true;
+ Log.e(TAG, "Codec Error: " + e.toString());
+ e.printStackTrace();
+ synchronized (mLock) { mLock.notify(); }
+ }
+ });
+
+ }
+
+ protected void onInputsAvailable(int inputBufferId, MediaCodec mediaCodec) {
+ if (inputBufferId >= 0) {
+ mLinearInputBlock.allocateBlock(mediaCodec.getCanonicalName(), mMaxInputSize);
+ MediaCodec.BufferInfo bufInfo;
+ mInputInfos.clear();
+ int offset = 0;
+ while (mNumInFramesProvided < mNumInFramesRequired) {
+ bufInfo = mInputBufferInfo.get(mIndex);
+ mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ int bufferSizeNeeded = mLinearInputBlock.getOffset() + bufInfo.size;
+ if (bufferSizeNeeded > mLinearInputBlock.getBufferCapacity()) {
+ break;
+ }
+ mLinearInputBlock.getBuffer().put(mInputBuffer.get(mIndex).array());
+ mLinearInputBlock.setOffset(mLinearInputBlock.getOffset() + bufInfo.size);
+ bufInfo.offset = offset; offset += bufInfo.size;
+ mInputInfos.add(bufInfo);
+ mNumInFramesProvided++;
+ mIndex = mNumInFramesProvided % (mInputBufferInfo.size() - 1);
+
+ }
+ if (DEBUG) {
+ Log.d(TAG, "inputsAvailable ID : " + inputBufferId
+ + " queued info size: " + mInputInfos.size()
+ + " Total queued size: " + offset);
+ }
+ if (mNumInFramesProvided >= mNumInFramesRequired) {
+ mIndex = mInputBufferInfo.size() - 1;
+ bufInfo = mInputBufferInfo.get(mIndex);
+ int bufferSizeNeeded = mLinearInputBlock.getOffset() + bufInfo.size;
+ if (bufferSizeNeeded <= mLinearInputBlock.getBufferCapacity()) {
+ if ((bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) == 0) {
+ Log.e(TAG, "Error in EOS flag for Decoder");
+ }
+ mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ mLinearInputBlock.getBuffer().put(mInputBuffer.get(mIndex).array());
+ mLinearInputBlock.setOffset(mLinearInputBlock.getOffset() + bufInfo.size);
+ bufInfo.offset = offset; offset += bufInfo.size;
+ //bufInfo.flags = codecFlags;
+ mInputInfos.add(bufInfo);
+ mNumInFramesProvided++;
+ }
+ }
+ if (mInputInfos.size() == 0) {
+ Log.d(TAG, " No inputs to queue");
+ } else {
+ mStats.addFrameSize(offset);
+ MediaCodec.QueueRequest request = mediaCodec.getQueueRequest(inputBufferId);
+ request.setMultiFrameLinearBlock(mLinearInputBlock.getBlock(), mInputInfos);
+ request.queue();
+ }
+ }
+ }
+
+ protected void onOutputsAvailable(MediaCodec mediaCodec, int outputBufferId,
+ ArrayDeque<MediaCodec.BufferInfo> infos) {
+ if (mSawOutputEOS || outputBufferId < 0) {
+ return;
+ }
+ MediaCodec.OutputFrame outFrame = mediaCodec.getOutputFrame(outputBufferId);
+ ByteBuffer outputBuffer = null;
+ try {
+ if (outFrame.getLinearBlock() != null) {
+ outputBuffer = outFrame.getLinearBlock().map();
+ }
+ } catch(IllegalStateException e) {
+ // buffer may not be linear, this is ok
+ // as we are handling non-linear buffers below.
+ }
+ if (mOutputStream != null) {
+ try {
+ if (outputBuffer != null) {
+ byte[] bytesOutput = new byte[outputBuffer.remaining()];
+ outputBuffer.get(bytesOutput);
+ mOutputStream.write(bytesOutput);
+ if (DEBUG) {
+ Log.d(TAG, "Received outputs buffer size : " + outputBuffer.remaining()
+ + " infos size " + infos.size());
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ Log.d(TAG, "Error Dumping File: Exception " + e.toString());
+ }
+ }
+ mNumOutputFrame += infos.size();
+ MediaCodec.BufferInfo last = infos.peekLast();
+ if (last != null) {
+ mSawOutputEOS |= ((last.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0);
+ }
+ int bytesRemaining = 0;
+ if (outputBuffer != null) {
+ bytesRemaining = outputBuffer.remaining();
+ outFrame.getLinearBlock().recycle();
+ outputBuffer = null;
+ }
+ if (mFrameReleaseQueue != null) {
+ mFrameReleaseQueue.pushFrame(outputBufferId, bytesRemaining);
+ } else if (mIBufferSend == null) {
+ mediaCodec.releaseOutputBuffer(outputBufferId, mRender);
+ }
+ if (mSawOutputEOS) {
+ Log.i(TAG, "Large frame - saw output EOS");
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitDecoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitDecoder.java
index cb92f06..fd8859b 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitDecoder.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitDecoder.java
@@ -18,6 +18,7 @@
import android.view.Surface;
+import android.media.AudioFormat;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaFormat;
@@ -91,8 +92,18 @@
@NonNull MediaCodec mediaCodec, @NonNull MediaFormat format) {
Log.i(TAG, "Output format changed. Format: " + format.toString());
final int maxOutputSize = format.getNumber(
- MediaFormat.KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE, 0).intValue();
+ MediaFormat.KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE, 0).intValue();
isUsingLargeFrameMode = (maxOutputSize > 0);
+ if (mUseFrameReleaseQueue && mFrameReleaseQueue == null) {
+ int bytesPerSample = AudioFormat.getBytesPerSample(
+ format.getInteger(MediaFormat.KEY_PCM_ENCODING,
+ AudioFormat.ENCODING_PCM_16BIT));
+ int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+ int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+ mFrameReleaseQueue = new FrameReleaseQueue(
+ mRender, sampleRate, channelCount, bytesPerSample);
+ mFrameReleaseQueue.setMediaCodec(mCodec);
+ }
}
@Override
@@ -177,30 +188,6 @@
if (mSawOutputEOS || outputBufferId < 0) {
return;
}
- Iterator<BufferInfo> iter = infos.iterator();
- while (iter.hasNext()) {
- BufferInfo bufferInfo = iter.next();
- mNumOutputFrame++;
- if (DEBUG) {
- Log.d(TAG,
- "In OutputBufferAvailable ,"
- + " output frame number = " + mNumOutputFrame
- + " timestamp = " + bufferInfo.presentationTimeUs
- + " size = " + bufferInfo.size);
- }
- if (mIBufferSend != null) {
- IBufferXfer.BufferXferInfo info = new IBufferXfer.BufferXferInfo();
- info.buf = mc.getOutputBuffer(outputBufferId);
- info.idx = outputBufferId;
- info.obj = mc;
- info.bytesRead = bufferInfo.size;
- info.presentationTimeUs = bufferInfo.presentationTimeUs;
- info.flag = bufferInfo.flags;
- info.isComplete = iter.hasNext() ? false : true;
- mIBufferSend.sendBuffer(this, info);
- }
- mSawOutputEOS |= (bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
- }
if (mOutputStream != null) {
try {
ByteBuffer outputBuffer = mc.getOutputBuffer(outputBufferId);
@@ -212,12 +199,27 @@
Log.d(TAG, "Error Dumping File: Exception " + e.toString());
}
}
- if (mIBufferSend == null) {
+ mNumOutputFrame += infos.size();
+ MediaCodec.BufferInfo last = infos.peekLast();
+ if (last != null) {
+ mSawOutputEOS |= ((last.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0);
+ }
+ if (mIBufferSend != null) {
+ IBufferXfer.BufferXferInfo info = new IBufferXfer.BufferXferInfo();
+ info.buf = mc.getOutputBuffer(outputBufferId);
+ info.idx = outputBufferId;
+ info.obj = mc;
+ info.infos = infos;
+ mIBufferSend.sendBuffer(this, info);
+ } else if (mFrameReleaseQueue != null) {
+ ByteBuffer outputBuffer = mc.getOutputBuffer(outputBufferId);
+ mFrameReleaseQueue.pushFrame(
+ outputBufferId, outputBuffer.remaining());
+ } else {
mc.releaseOutputBuffer(outputBufferId, mRender);
}
if (mSawOutputEOS) {
Log.i(TAG, "Large frame - saw output EOS");
}
- // we don't support frame release queue for large audio frame
}
}
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index e13f8f7..679b111 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "ServiceUtilities"
#include <audio_utils/clock.h>
+#include <android-base/properties.h>
#include <binder/AppOpsManager.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -28,9 +29,11 @@
#include <media/AidlConversionUtil.h>
#include <android/content/AttributionSourceState.h>
-#include <iterator>
#include <algorithm>
+#include <iterator>
+#include <mutex>
#include <pwd.h>
+#include <thread>
/* When performing permission checks we do not use permission cache for
* runtime permissions (protection level dangerous) as they may change at
@@ -396,6 +399,106 @@
return NO_ERROR;
}
+// TODO(b/285588444), clean this up on main, but soak it for backporting purposes for now
+namespace {
+class BluetoothPermissionCache {
+ static constexpr auto SYSPROP_NAME = "cache_key.system_server.package_info";
+ const String16 BLUETOOTH_PERM {"android.permission.BLUETOOTH_CONNECT"};
+ mutable std::mutex mLock;
+ // Cached property conditionally defined, since only avail on bionic. On host, don't inval cache
+#if defined(__BIONIC__)
+ // Unlocked, but only accessed from mListenerThread
+ base::CachedProperty mCachedProperty;
+#endif
+ // This thread is designed to never join/terminate, so no signal is fine
+ const std::thread mListenerThread;
+ GUARDED_BY(mLock)
+ std::string mPropValue;
+ GUARDED_BY(mLock)
+ std::unordered_map<uid_t, bool> mCache;
+ PermissionController mPc{};
+public:
+ BluetoothPermissionCache()
+#if defined(__BIONIC__)
+ : mCachedProperty{SYSPROP_NAME},
+ mListenerThread([this]() mutable {
+ while (true) {
+ std::string newVal = mCachedProperty.WaitForChange() ?: "";
+ std::lock_guard l{mLock};
+ if (newVal != mPropValue) {
+ ALOGV("Bluetooth permission update");
+ mPropValue = newVal;
+ mCache.clear();
+ }
+ }
+ })
+#endif
+ {}
+
+ bool checkPermission(uid_t uid, pid_t pid) {
+ std::lock_guard l{mLock};
+ auto it = mCache.find(uid);
+ if (it == mCache.end()) {
+ it = mCache.insert({uid, mPc.checkPermission(BLUETOOTH_PERM, pid, uid)}).first;
+ }
+ return it->second;
+ }
+};
+
+// Don't call this from locks, since it potentially calls up to system server!
+// Check for non-app UIDs above this method!
+bool checkBluetoothPermission(const AttributionSourceState& attr) {
+ [[clang::no_destroy]] static BluetoothPermissionCache impl{};
+ return impl.checkPermission(attr.uid, attr.pid);
+}
+} // anonymous
+
+/**
+ * Determines if the MAC address in Bluetooth device descriptors returned by APIs of
+ * a native audio service (audio flinger, audio policy) must be anonymized.
+ * MAC addresses returned to system server or apps with BLUETOOTH_CONNECT permission
+ * are not anonymized.
+ *
+ * @param attributionSource The attribution source of the calling app.
+ * @param caller string identifying the caller for logging.
+ * @return true if the MAC addresses must be anonymized, false otherwise.
+ */
+bool mustAnonymizeBluetoothAddress(
+ const AttributionSourceState& attributionSource, const String16&) {
+ uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
+ bool res;
+ switch(multiuser_get_app_id(uid)) {
+ case AID_ROOT:
+ case AID_SYSTEM:
+ case AID_RADIO:
+ case AID_BLUETOOTH:
+ case AID_MEDIA:
+ case AID_AUDIOSERVER:
+ // Don't anonymize for privileged clients
+ res = false;
+ break;
+ default:
+ res = !checkBluetoothPermission(attributionSource);
+ break;
+ }
+ ALOGV("%s uid: %d, result: %d", __func__, uid, res);
+ return res;
+}
+
+/**
+ * Modifies the passed MAC address string in place for consumption by unprivileged clients.
+ * the string is assumed to have a valid MAC address format.
+ * the anonymization must be kept in sync with toAnonymizedAddress() in BluetoothUtils.java
+ *
+ * @param address input/output the char string contining the MAC address to anonymize.
+ */
+void anonymizeBluetoothAddress(char *address) {
+ if (address == nullptr || strlen(address) != strlen("AA:BB:CC:DD:EE:FF")) {
+ return;
+ }
+ memcpy(address, "XX:XX:XX:XX", strlen("XX:XX:XX:XX"));
+}
+
sp<content::pm::IPackageManagerNative> MediaPackageManager::retrievePackageManager() {
const sp<IServiceManager> sm = defaultServiceManager();
if (sm == nullptr) {
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 2631469..461e190 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -114,6 +114,10 @@
bool bypassInterruptionPolicyAllowed(const AttributionSourceState& attributionSource);
bool callAudioInterceptionAllowed(const AttributionSourceState& attributionSource);
void purgePermissionCache();
+bool mustAnonymizeBluetoothAddress(
+ const AttributionSourceState& attributionSource, const String16& caller);
+void anonymizeBluetoothAddress(char *address);
+
int32_t getOpForSource(audio_source_t source);
AttributionSourceState getCallingAttributionSource();
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0d5d61f..a1a0634 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -629,6 +629,7 @@
bool isSpatialized;
bool isBitPerfect;
float volume;
+ bool muted;
ret = AudioSystem::getOutputForAttr(&localAttr, &io,
actualSessionId,
&streamType, adjAttributionSource,
@@ -637,7 +638,8 @@
AUDIO_OUTPUT_FLAG_DIRECT),
deviceId, &portId, &secondaryOutputs, &isSpatialized,
&isBitPerfect,
- &volume);
+ &volume,
+ &muted);
if (ret != NO_ERROR) {
config->sample_rate = fullConfig.sample_rate;
config->channel_mask = fullConfig.channel_mask;
@@ -905,6 +907,26 @@
// Unknown arg silently ignored
}
+ {
+ std::string res;
+ res.reserve(100);
+ res += "Start begin: ";
+ const auto startTimeStr = audio_utils_time_string_from_ns(mStartTime);
+ res += startTimeStr.time;
+ const auto startFinishedTime = getStartupFinishedTime();
+ if (startFinishedTime != 0) {
+ res += "\nStart end: ";
+ const auto startEndStr = audio_utils_time_string_from_ns(startFinishedTime);
+ res += startEndStr.time;
+ } else {
+ res += "\nStartup not yet finished!";
+ }
+ const auto nowTimeStr = audio_utils_time_string_from_ns(audio_utils_get_real_time_ns());
+ res += "\nNow: ";
+ res += nowTimeStr.time;
+ res += "\n";
+ writeStr(fd, res);
+ }
// get state of hardware lock
{
FallibleLockGuard l{hardwareMutex()};
@@ -1097,6 +1119,7 @@
bool isSpatialized = false;
bool isBitPerfect = false;
float volume;
+ bool muted;
audio_io_handle_t effectThreadId = AUDIO_IO_HANDLE_NONE;
std::vector<int> effectIds;
@@ -1157,7 +1180,7 @@
lStatus = AudioSystem::getOutputForAttr(&localAttr, &output.outputId, sessionId, &streamType,
adjAttributionSource, &input.config, input.flags,
&output.selectedDeviceId, &portId, &secondaryOutputs,
- &isSpatialized, &isBitPerfect, &volume);
+ &isSpatialized, &isBitPerfect, &volume, &muted);
if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
ALOGE("createTrack() getOutputForAttr() return error %d or invalid output handle", lStatus);
@@ -1214,7 +1237,7 @@
if (effectThread == nullptr) {
effectChain = getOrphanEffectChain_l(sessionId);
}
- ALOGV("createTrack() sessionId: %d volume: %f", sessionId, volume);
+ ALOGV("createTrack() sessionId: %d volume: %f muted %d", sessionId, volume, muted);
output.sampleRate = input.config.sample_rate;
output.frameCount = input.frameCount;
@@ -1229,7 +1252,7 @@
input.sharedBuffer, sessionId, &output.flags,
callingPid, adjAttributionSource, input.clientInfo.clientTid,
&lStatus, portId, input.audioTrackCallback, isSpatialized,
- isBitPerfect, &output.afTrackFlags, volume);
+ isBitPerfect, &output.afTrackFlags, volume, muted);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
// we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
@@ -1653,7 +1676,7 @@
}
status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output)
+ bool muted, audio_io_handle_t output)
{
// check calling permissions
if (!settingsAllowed()) {
@@ -1675,14 +1698,14 @@
if (volumeInterface == NULL) {
return BAD_VALUE;
}
- volumeInterface->setStreamVolume(stream, value);
+ volumeInterface->setStreamVolume(stream, value, muted);
return NO_ERROR;
}
status_t AudioFlinger::setPortsVolume(
- const std::vector<audio_port_handle_t>& ports, float volume, audio_io_handle_t output)
-{
+ const std::vector<audio_port_handle_t> &ports, float volume, bool muted,
+ audio_io_handle_t output) {
for (const auto& port : ports) {
if (port == AUDIO_PORT_HANDLE_NONE) {
return BAD_VALUE;
@@ -1697,12 +1720,12 @@
audio_utils::lock_guard lock(mutex());
IAfPlaybackThread *thread = checkPlaybackThread_l(output);
if (thread != nullptr) {
- return thread->setPortsVolume(ports, volume);
+ return thread->setPortsVolume(ports, volume, muted);
}
const sp<IAfMmapThread> mmapThread = checkMmapThread_l(output);
if (mmapThread != nullptr && mmapThread->isOutput()) {
IAfMmapPlaybackThread *mmapPlaybackThread = mmapThread->asIAfMmapPlaybackThread().get();
- return mmapPlaybackThread->setPortsVolume(ports, volume);
+ return mmapPlaybackThread->setPortsVolume(ports, volume, muted);
}
return BAD_VALUE;
}
@@ -4097,7 +4120,8 @@
0ns /* timeout */,
frameCountToBeReady,
track->getSpeed(),
- 1.f /* volume */);
+ 1.f /* volume */,
+ false /* muted */);
status = patchTrack->initCheck();
if (status != NO_ERROR) {
ALOGE("Secondary output patchTrack init failed: %d", status);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index ace74ee..042194f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -27,6 +27,7 @@
#include "IAfTrack.h"
#include "MelReporter.h"
#include "PatchCommandThread.h"
+#include "audio_utils/clock.h"
// External classes
#include <audio_utils/mutex.h>
@@ -65,6 +66,11 @@
status_t resetReferencesForTest();
+ // Called by main when startup finished -- for logging purposes only
+ void startupFinished() {
+ mStartupFinishedTime.store(audio_utils_get_real_time_ns(), std::memory_order_release);
+ }
+
private:
// ---- begin IAudioFlinger interface
@@ -93,12 +99,12 @@
status_t getMasterBalance(float* balance) const final EXCLUDES_AudioFlinger_Mutex;
status_t setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
+ bool muted, audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
status_t setStreamMute(audio_stream_type_t stream, bool muted) final
EXCLUDES_AudioFlinger_Mutex;
status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
- audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
+ bool muted, audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
status_t setMode(audio_mode_t mode) final EXCLUDES_AudioFlinger_Mutex;
@@ -420,6 +426,10 @@
sp<EffectsFactoryHalInterface> getEffectsFactory();
+ int64_t getStartupFinishedTime() {
+ return mStartupFinishedTime.load(std::memory_order_acquire);
+ }
+
public:
// TODO(b/292281786): Remove this when Oboeservice can get access to
// openMmapStream through an IAudioFlinger handle directly.
@@ -803,6 +813,10 @@
// Local interface to AudioPolicyService, late inited, but logically const
mediautils::atomic_sp<media::IAudioPolicyServiceLocal> mAudioPolicyServiceLocal;
+
+ const int64_t mStartTime = audio_utils_get_real_time_ns();
+ // Late-inited from main()
+ std::atomic<int64_t> mStartupFinishedTime {};
};
// ----------------------------------------------------------------------------
diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h
index abb8f2f..a13819c 100644
--- a/services/audioflinger/IAfThread.h
+++ b/services/audioflinger/IAfThread.h
@@ -481,7 +481,8 @@
bool isSpatialized,
bool isBitPerfect,
audio_output_flags_t* afTrackFlags,
- float volume)
+ float volume,
+ bool muted)
REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
virtual status_t addTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex()) = 0;
@@ -558,8 +559,8 @@
virtual void setTracksInternalMute(std::map<audio_port_handle_t, bool>* tracksInternalMute)
EXCLUDES_ThreadBase_Mutex = 0;
- virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
- EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t setPortsVolume(const std::vector<audio_port_handle_t> &portIds, float volume,
+ bool muted) EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfDirectOutputThread : public virtual IAfPlaybackThread {
@@ -700,8 +701,8 @@
virtual AudioStreamOut* clearOutput() EXCLUDES_ThreadBase_Mutex = 0;
- virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
- EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
+ bool muted) EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfMmapCaptureThread : public virtual IAfMmapThread {
diff --git a/services/audioflinger/IAfTrack.h b/services/audioflinger/IAfTrack.h
index 2049adc..1b10f81 100644
--- a/services/audioflinger/IAfTrack.h
+++ b/services/audioflinger/IAfTrack.h
@@ -291,14 +291,15 @@
float speed = 1.0f,
bool isSpatialized = false,
bool isBitPerfect = false,
- float volume = 0.0f);
+ float volume = 0.0f,
+ bool muted = false);
static constexpr std::string_view getLogHeader() {
using namespace std::literals;
return "Type Id Active Client(pid/uid) Session Port Id S Flags "
" Format Chn mask SRate "
"ST Usg CT "
- " G db L dB R dB VS dB PortVol dB "
+ " G db L dB R dB VS dB PortVol dB PortMuted"
" Server FrmCnt FrmRdy F Underruns Flushed BitPerfect InternalMute"
" Latency\n"sv;
}
@@ -476,12 +477,13 @@
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
- float volume = 0.0f);
+ float volume = 0.0f,
+ bool muted = false);
static constexpr std::string_view getLogHeader() {
using namespace std::literals;
return "Client(pid/uid) Session Port Id"
- " Format Chn mask SRate Flags Usg/Src PortVol dB\n"sv;
+ " Format Chn mask SRate Flags Usg/Src PortVol dB PortMuted\n"sv;
};
// protected by MMapThread::mLock
@@ -610,7 +612,8 @@
* the lowest possible latency
* even if it might glitch. */
float speed = 1.0f,
- float volume = 1.0f);
+ float volume = 1.0f,
+ bool muted = false);
};
class IAfPatchRecord : public virtual IAfRecordTrack, public virtual IAfPatchTrackBase {
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index 442dd80..30bbd5d 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -36,7 +36,8 @@
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
- float volume = 0.0f);
+ float volume = 0.0f,
+ bool muted = false);
~MmapTrack() override;
status_t initCheck() const final;
@@ -71,7 +72,11 @@
void setPortVolume(float volume) override {
mVolume = volume;
}
+ void setPortMute(bool muted) override {
+ mMuteState.muteFromPortVolume = muted;
+ }
float getPortVolume() const override { return mVolume; }
+ bool getPortMute() const override { return mMuteState.muteFromPortVolume; }
private:
DISALLOW_COPY_AND_ASSIGN(MmapTrack);
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index d0b96de..be59299 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -650,7 +650,8 @@
{} /*timeout*/,
frameCountToBeReady,
1.0f /*speed*/,
- 1.0f /*volume*/);
+ 1.0f /*volume*/,
+ false /*muted*/);
status = mPlayback.checkTrack(tempPatchTrack.get());
if (status != NO_ERROR) {
return status;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 84758a4..70bab6a 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -97,7 +97,8 @@
float speed = 1.0f,
bool isSpatialized = false,
bool isBitPerfect = false,
- float volume = 0.0f);
+ float volume = 0.0f,
+ bool muted = false);
~Track() override;
status_t initCheck() const final;
void appendDumpHeader(String8& result) const final;
@@ -226,7 +227,9 @@
// VolumePortInterface implementation
void setPortVolume(float volume) override;
+ void setPortMute(bool muted) override;
float getPortVolume() const override { return mVolume; }
+ bool getPortMute() const override { return mMuteState.load().muteFromPortVolume; }
protected:
@@ -410,9 +413,9 @@
// TODO: replace PersistableBundle with own struct
// access these two variables only when holding player thread lock.
std::unique_ptr<os::PersistableBundle> mMuteEventExtras;
- mute_state_t mMuteState;
- bool mInternalMute = false;
- std::atomic<float> mVolume = 0.0f;
+ std::atomic<mute_state_t> mMuteState;
+ bool mInternalMute = false;
+ std::atomic<float> mVolume = 0.0f;
}; // end of Track
@@ -510,7 +513,8 @@
* the lowest possible latency
* even if it might glitch. */
float speed = 1.0f,
- float volume = 1.0f);
+ float volume = 1.0f,
+ bool muted = false);
~PatchTrack() override;
size_t framesReady() const final;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index ae102fc..1c0b749 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2405,7 +2405,8 @@
bool isSpatialized,
bool isBitPerfect,
audio_output_flags_t *afTrackFlags,
- float volume)
+ float volume,
+ bool muted)
{
size_t frameCount = *pFrameCount;
size_t notificationFrameCount = *pNotificationFrameCount;
@@ -2734,7 +2735,7 @@
nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
sessionId, creatorPid, attributionSource, trackFlags,
IAfTrackBase::TYPE_DEFAULT, portId, SIZE_MAX /*frameCountToBeReady*/,
- speed, isSpatialized, isBitPerfect, volume);
+ speed, isSpatialized, isBitPerfect, volume, muted);
lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
if (lStatus != NO_ERROR) {
@@ -2842,10 +2843,14 @@
}
}
-void PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
+void PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value, bool muted)
{
+ ALOGV("%s: stream %d value %f muted %d", __func__, stream, value, muted);
audio_utils::lock_guard _l(mutex());
mStreamTypes[stream].volume = value;
+ if (com_android_media_audio_ring_my_car()) {
+ mStreamTypes[stream].mute = muted;
+ }
broadcast_l();
}
@@ -2863,13 +2868,14 @@
}
status_t PlaybackThread::setPortsVolume(
- const std::vector<audio_port_handle_t>& portIds, float volume) {
+ const std::vector<audio_port_handle_t>& portIds, float volume, bool muted) {
audio_utils::lock_guard _l(mutex());
for (const auto& portId : portIds) {
for (size_t i = 0; i < mTracks.size(); i++) {
sp<IAfTrack> track = mTracks[i].get();
if (portId == track->portId()) {
track->setPortVolume(volume);
+ track->setPortMute(muted);
break;
}
}
@@ -5859,7 +5865,7 @@
volume = masterVolume * mStreamTypes[track->streamType()].volume;
}
} else {
- if (track->isPlaybackRestricted()) {
+ if (track->isPlaybackRestricted() || track->getPortMute()) {
volume = 0.f;
} else {
volume = masterVolume * track->getPortVolume();
@@ -5883,7 +5889,8 @@
mStreamTypes[track->streamType()].mute,
track->isPlaybackRestricted(),
vlf == 0.f && vrf == 0.f,
- vh == 0.f});
+ vh == 0.f,
+ /*muteFromPortVolume=*/false});
} else {
track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
/*muteState=*/{masterVolume == 0.f,
@@ -5891,7 +5898,8 @@
/* muteFromStreamMuted= */ false,
track->isPlaybackRestricted(),
vlf == 0.f && vrf == 0.f,
- vh == 0.f});
+ vh == 0.f,
+ track->getPortMute()});
}
vlf *= volume;
vrf *= volume;
@@ -6055,7 +6063,7 @@
}
} else {
v = masterVolume * track->getPortVolume();
- if (track->isPlaybackRestricted()) {
+ if (track->isPlaybackRestricted() || track->getPortMute()) {
v = 0;
}
}
@@ -6085,7 +6093,8 @@
mStreamTypes[track->streamType()].mute,
track->isPlaybackRestricted(),
vlf == 0.f && vrf == 0.f,
- vh == 0.f});
+ vh == 0.f,
+ /*muteFromPortVolume=*/false});
} else {
track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
/*muteState=*/{masterVolume == 0.f,
@@ -6093,7 +6102,8 @@
/* muteFromStreamMuted= */ false,
track->isPlaybackRestricted(),
vlf == 0.f && vrf == 0.f,
- vh == 0.f});
+ vh == 0.f,
+ track->getPortMute()});
}
// now apply the master volume and stream type volume and shaper volume
vlf *= v * vh;
@@ -6851,7 +6861,8 @@
mStreamTypes[track->streamType()].mute,
track->isPlaybackRestricted(),
clientVolumeMute,
- shaperVolume == 0.f});
+ shaperVolume == 0.f,
+ /*muteFromPortVolume=*/false});
} else {
if (mMasterMute || track->isPlaybackRestricted()) {
left = right = 0;
@@ -6879,7 +6890,8 @@
/* muteFromStreamMuted= */ false,
track->isPlaybackRestricted(),
clientVolumeMute,
- shaperVolume == 0.f});
+ shaperVolume == 0.f,
+ track->getPortMute()});
}
if (lastTrack) {
@@ -7981,8 +7993,9 @@
return;
}
if (!audioserver_flags::portid_volume_management()) {
- thread->setStreamVolume(AUDIO_STREAM_PATCH, 1.0f);
+ thread->setStreamVolume(AUDIO_STREAM_PATCH, /*volume=*/1.0f, /*muted=*/false);
}
+
mOutputTracks.add(outputTrack);
ALOGV("addOutputTrack() track %p, on thread %p", outputTrack.get(), thread);
updateWaitTime_l();
@@ -10486,6 +10499,7 @@
const auto localSessionId = mSessionId;
auto localAttr = mAttr;
float volume = 0.0f;
+ bool muted = false;
if (isOutput()) {
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = mSampleRate;
@@ -10510,7 +10524,8 @@
&secondaryOutputs,
&isSpatialized,
&isBitPerfect,
- &volume);
+ &volume,
+ &muted);
mutex().lock();
mAttr = localAttr;
ALOGD_IF(!secondaryOutputs.empty(),
@@ -10580,7 +10595,7 @@
mChannelMask, mSessionId, isOutput(),
client.attributionSource,
IPCThreadState::self()->getCallingPid(), portId,
- volume);
+ volume, muted);
if (!isOutput()) {
track->setSilenced_l(isClientSilenced_l(portId));
}
@@ -11238,10 +11253,14 @@
}
}
-void MmapPlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
+void MmapPlaybackThread::setStreamVolume(audio_stream_type_t stream, float value, bool muted)
{
+ ALOGV("%s: stream %d value %f muted %d", __func__, stream, value, muted);
audio_utils::lock_guard _l(mutex());
mStreamTypes[stream].volume = value;
+ if (com_android_media_audio_ring_my_car()) {
+ mStreamTypes[stream].mute = muted;
+ }
if (stream == mStreamType) {
broadcast_l();
}
@@ -11263,12 +11282,13 @@
}
status_t MmapPlaybackThread::setPortsVolume(
- const std::vector<audio_port_handle_t>& portIds, float volume) {
+ const std::vector<audio_port_handle_t>& portIds, float volume, bool muted) {
audio_utils::lock_guard _l(mutex());
for (const auto& portId : portIds) {
for (const sp<IAfMmapTrack>& track : mActiveTracks) {
if (portId == track->portId()) {
track->setPortVolume(volume);
+ track->setPortMute(muted);
break;
}
}
@@ -11326,7 +11346,11 @@
// will be broadcasted to all tracks. Thus, take arbitrarily first track volume.
size_t numtracks = mActiveTracks.size();
if (numtracks) {
- volume = mMasterVolume * mActiveTracks[0]->getPortVolume();
+ if (mActiveTracks[0]->getPortMute()) {
+ volume = 0;
+ } else {
+ volume = mMasterVolume * mActiveTracks[0]->getPortVolume();
+ }
}
}
}
@@ -11370,7 +11394,8 @@
// TODO(b/241533526): adjust logic to include mute from AppOps
false /*muteFromPlaybackRestricted*/,
false /*muteFromClientVolume*/,
- false /*muteFromVolumeShaper*/});
+ false /*muteFromVolumeShaper*/,
+ false /*muteFromPortVolume*/});
} else {
track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
/*muteState=*/{mMasterMute,
@@ -11379,7 +11404,8 @@
// TODO(b/241533526): adjust logic to include mute from AppOps
false /*muteFromPlaybackRestricted*/,
false /*muteFromClientVolume*/,
- false /*muteFromVolumeShaper*/});
+ false /*muteFromVolumeShaper*/,
+ track->getPortMute()});
}
}
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index a13340d..0c5a2c3 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1020,11 +1020,12 @@
void setMasterVolume(float value) final;
void setMasterBalance(float balance) override EXCLUDES_ThreadBase_Mutex;
void setMasterMute(bool muted) final;
- void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
+ void setStreamVolume(audio_stream_type_t stream, float value, bool muted) final
+ EXCLUDES_ThreadBase_Mutex;
void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
- status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
- final EXCLUDES_ThreadBase_Mutex;
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
+ bool muted) final EXCLUDES_ThreadBase_Mutex;
void setVolumeForOutput_l(float left, float right) const final;
@@ -1051,7 +1052,8 @@
bool isSpatialized,
bool isBitPerfect,
audio_output_flags_t* afTrackFlags,
- float volume) final
+ float volume,
+ bool muted) final
REQUIRES(audio_utils::AudioFlinger_Mutex);
bool isTrackActive(const sp<IAfTrack>& track) const final {
@@ -2405,11 +2407,13 @@
// Needs implementation?
void setMasterBalance(float /* value */) final EXCLUDES_ThreadBase_Mutex {}
void setMasterMute(bool muted) final EXCLUDES_ThreadBase_Mutex;
- void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
+
+ void setStreamVolume(audio_stream_type_t stream, float value, bool muted) final
+ EXCLUDES_ThreadBase_Mutex;
void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
- status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
- final EXCLUDES_ThreadBase_Mutex;
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
+ bool muted) final EXCLUDES_ThreadBase_Mutex;
void setMasterMute_l(bool muted) REQUIRES(mutex()) { mMasterMute = muted; }
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index b08b0b7..0ddbaec 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -728,7 +728,8 @@
float speed,
bool isSpatialized,
bool isBitPerfect,
- float volume) {
+ float volume,
+ bool muted) {
return sp<Track>::make(thread,
client,
streamType,
@@ -750,7 +751,8 @@
speed,
isSpatialized,
isBitPerfect,
- volume);
+ volume,
+ muted);
}
// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
@@ -776,7 +778,8 @@
float speed,
bool isSpatialized,
bool isBitPerfect,
- float volume)
+ float volume,
+ bool muted)
: TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
@@ -861,11 +864,16 @@
populateUsageAndContentTypeFromStreamType();
+ mute_state_t newMuteState = mMuteState.load();
+ newMuteState.muteFromPortVolume = muted;
+
// Audio patch and call assistant volume are always max
if (mAttr.usage == AUDIO_USAGE_CALL_ASSISTANT
|| mAttr.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
mVolume = 1.0f;
+ newMuteState.muteFromPortVolume = false;
}
+ mMuteState.store(newMuteState);
mServerLatencySupported = checkServerLatencySupported(format, flags);
#ifdef TEE_SINK
@@ -1084,7 +1092,7 @@
result.appendFormat("%7s %7u/%7u %7u %7u %2s 0x%03X "
"%08X %08X %6u "
"%2u %3x %2x "
- "%5.2g %5.2g %5.2g %5.2g%c %11.2g "
+ "%5.2g %5.2g %5.2g %5.2g%c %11.2g %12s"
"%08X %6zu%c %6zu %c %9u%c %7u %10s %12s",
active ? "yes" : "no",
mClient ? mClient->pid() : getpid() ,
@@ -1108,6 +1116,7 @@
20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
20.0 * log10(mVolume),
+ getPortMute() ? "true" : "false",
mCblk->mServer,
bufferSizeInFrames,
@@ -1614,8 +1623,25 @@
if (mType != TYPE_PATCH) {
// Do not recursively propagate a PatchTrack setPortVolume to
// downstream PatchTracks.
- forEachTeePatchTrack_l([volume](const auto& patchTrack) {
- patchTrack->setPortVolume(volume); });
+ forEachTeePatchTrack_l([volume](const auto &patchTrack) {
+ patchTrack->setPortVolume(volume);
+ });
+ }
+}
+
+void Track::setPortMute(bool muted) {
+ mute_state_t newMuteState = mMuteState.load();
+ if (newMuteState.muteFromPortVolume == muted) {
+ return;
+ }
+ newMuteState.muteFromPortVolume = muted;
+ mMuteState.store(newMuteState);
+ if (mType != TYPE_PATCH) {
+ // Do not recursively propagate a PatchTrack setPortVolume to
+ // downstream PatchTracks.
+ forEachTeePatchTrack_l([muted](const auto &patchTrack) {
+ patchTrack->setPortMute(muted);
+ });
}
}
@@ -1720,8 +1746,8 @@
}
if (result == OK) {
- ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
- static_cast<int>(mMuteState), static_cast<int>(muteState));
+ ALOGI("%s(%d): processed mute state for port ID %d from %#x to %#x", __func__, id(),
+ mPortId, static_cast<int>(mMuteState.load()), static_cast<int>(muteState));
mMuteState = muteState;
} else {
ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
@@ -2498,7 +2524,8 @@
* the lowest possible latency
* even if it might glitch. */
float speed,
- float volume)
+ float volume,
+ bool muted)
{
return sp<PatchTrack>::make(
playbackThread,
@@ -2513,7 +2540,8 @@
timeout,
frameCountToBeReady,
speed,
- volume);
+ volume,
+ muted);
}
PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
@@ -2528,14 +2556,15 @@
const Timeout& timeout,
size_t frameCountToBeReady,
float speed,
- float volume)
+ float volume,
+ bool muted)
: Track(playbackThread, NULL, streamType,
AUDIO_ATTRIBUTES_INITIALIZER,
sampleRate, format, channelMask, frameCount,
buffer, bufferSize, nullptr /* sharedBuffer */,
AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed,
- false /*isSpatialized*/, false /*isBitPerfect*/, volume),
+ false /*isSpatialized*/, false /*isBitPerfect*/, volume, muted),
PatchTrackBase(mCblk ? new AudioTrackClientProxy(mCblk, mBuffer, frameCount, mFrameSize,
true /*clientInServer*/) : nullptr,
playbackThread, timeout)
@@ -3519,7 +3548,8 @@
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
audio_port_handle_t portId,
- float volume)
+ float volume,
+ bool muted)
{
return sp<MmapTrack>::make(
thread,
@@ -3532,7 +3562,8 @@
attributionSource,
creatorPid,
portId,
- volume);
+ volume,
+ muted);
}
MmapTrack::MmapTrack(IAfThreadBase* thread,
@@ -3545,7 +3576,8 @@
const AttributionSourceState& attributionSource,
pid_t creatorPid,
audio_port_handle_t portId,
- float volume)
+ float volume,
+ bool muted)
: TrackBase(thread, NULL, attr, sampleRate, format,
channelMask, (size_t)0 /* frameCount */,
nullptr /* buffer */, (size_t)0 /* bufferSize */,
@@ -3559,12 +3591,14 @@
mUid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid))),
mSilenced(false), mSilencedNotified(false), mVolume(volume)
{
+ mMuteState.muteFromPortVolume = muted;
// Once this item is logged by the server, the client can add properties.
mTrackMetrics.logConstructor(creatorPid, uid(), id());
if (isOut && (attr.usage == AUDIO_USAGE_CALL_ASSISTANT
|| attr.usage == AUDIO_USAGE_VIRTUAL_SOURCE)) {
// Audio patch and call assistant volume are always max
mVolume = 1.0f;
+ mMuteState.muteFromPortVolume = false;
}
}
@@ -3662,6 +3696,7 @@
if (isOut()) {
result.appendFormat("%4x %2x", mAttr.usage, mAttr.content_type);
result.appendFormat("%11.2g", 20.0 * log10(mVolume));
+ result.appendFormat("%12s", mMuteState.muteFromPortVolume ? "true" : "false");
} else {
result.appendFormat("%7x", mAttr.source);
}
diff --git a/services/audioflinger/datapath/VolumeInterface.h b/services/audioflinger/datapath/VolumeInterface.h
index 1564fe1..02b6ade 100644
--- a/services/audioflinger/datapath/VolumeInterface.h
+++ b/services/audioflinger/datapath/VolumeInterface.h
@@ -25,7 +25,7 @@
virtual void setMasterVolume(float value) = 0;
virtual void setMasterBalance(float balance) = 0;
virtual void setMasterMute(bool muted) = 0;
- virtual void setStreamVolume(audio_stream_type_t stream, float value) = 0;
+ virtual void setStreamVolume(audio_stream_type_t stream, float value, bool muted) = 0;
virtual void setStreamMute(audio_stream_type_t stream, bool muted) = 0;
// TODO(b/290699744) add "get" prefix for getter below.
virtual float streamVolume(audio_stream_type_t stream) const = 0;
diff --git a/services/audioflinger/datapath/VolumePortInterface.h b/services/audioflinger/datapath/VolumePortInterface.h
index fb1c463..fe3b782 100644
--- a/services/audioflinger/datapath/VolumePortInterface.h
+++ b/services/audioflinger/datapath/VolumePortInterface.h
@@ -23,7 +23,10 @@
class VolumePortInterface : public virtual RefBase {
public:
virtual void setPortVolume(float volume) = 0;
+ virtual void setPortMute(bool mute) = 0;
virtual float getPortVolume() const = 0;
+ /** Returns the muted state defined by the volume group which is playing on this port. */
+ virtual bool getPortMute() const = 0;
};
} // namespace android
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index edcb805..3539f00 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -148,7 +148,8 @@
output_type_t *outputType,
bool *isSpatialized,
bool *isBitPerfect,
- float *volume) = 0;
+ float *volume,
+ bool *muted) = 0;
// indicates to the audio policy manager that the output starts being used by corresponding
// stream.
virtual status_t startOutput(audio_port_handle_t portId) = 0;
@@ -197,6 +198,7 @@
// setting volume for all devices
virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
int index,
+ bool muted,
audio_devices_t device) = 0;
// retrieve current volume index for the specified stream and the
@@ -208,6 +210,7 @@
virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
int index,
+ bool muted,
audio_devices_t device) = 0;
virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
int &index,
@@ -514,7 +517,7 @@
// set a stream volume for a particular output. For the same user setting, a given stream type
// can have different volumes
// for each output (destination device) it is attached to.
- virtual status_t setStreamVolume(audio_stream_type_t stream, float volume,
+ virtual status_t setStreamVolume(audio_stream_type_t stream, float volume, bool muted,
audio_io_handle_t output, int delayMs = 0) = 0;
/**
* Set volume for given AudioTrack port ids for a particular output.
@@ -522,12 +525,13 @@
* can have different volumes for each output (destination device) it is attached to.
* @param ports to consider
* @param volume to apply
+ * @param muted to apply
* @param output to consider
* @param delayMs to use
* @return NO_ERROR if successful
*/
virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& ports, float volume,
- audio_io_handle_t output, int delayMs = 0) = 0;
+ bool muted, audio_io_handle_t output, int delayMs = 0) = 0;
// function enabling to send proprietary informations directly from audio policy manager to
// audio hardware interface.
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 4dedcd6..0e1d090 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -39,6 +39,7 @@
"android.media.audiopolicy-aconfig-cc",
"audioclient-types-aidl-cpp",
"audiopolicy-types-aidl-cpp",
+ "com.android.media.audio-aconfig-cc",
"com.android.media.audioserver-aconfig-cc",
"libaconfig_storage_read_api_cc",
"libaudioclient_aidl_conversion",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 835fad2..9bceee7 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -89,7 +89,9 @@
class VolumeActivity : public ActivityTracking
{
public:
- bool isMuted() const { return mMuteCount > 0; }
+ bool isMutedInternally() const { return mMuteCount > 0; }
+ bool isMutedByGroup() const { return mMutedByGroup > 0; }
+ void setMutedByGroup(bool mutedByGroup) { mMutedByGroup = mutedByGroup; }
int getMuteCount() const { return mMuteCount; }
int incMuteCount() { return ++mMuteCount; }
int decMuteCount() { return mMuteCount > 0 ? --mMuteCount : -1; }
@@ -107,6 +109,7 @@
private:
int mMuteCount = 0; /**< mute request counter */
+ bool mMutedByGroup = false; /**< mute from AudioService, does not add to counter */
float mCurVolumeDb = NAN; /**< current volume in dB. */
bool mIsVoice = false; /** true if this volume source is used for voice call volume */
};
@@ -209,16 +212,25 @@
return mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
mVolumeActivities.at(vs).getActivityCount() : 0;
}
- bool isMuted(VolumeSource vs) const
+ bool isMutedInternally(VolumeSource vs) const
{
return mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
- mVolumeActivities.at(vs).isMuted() : false;
+ mVolumeActivities.at(vs).isMutedInternally() : false;
}
int getMuteCount(VolumeSource vs) const
{
return mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
mVolumeActivities.at(vs).getMuteCount() : 0;
}
+ bool isMutedByGroup(VolumeSource vs)
+ {
+ return mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
+ mVolumeActivities.at(vs).isMutedByGroup() : false;
+ }
+ bool hasVolumeSource(VolumeSource vs)
+ {
+ return mVolumeActivities.find(vs) != std::end(mVolumeActivities);
+ }
int incMuteCount(VolumeSource vs)
{
return mVolumeActivities[vs].incMuteCount();
@@ -227,10 +239,11 @@
{
return mVolumeActivities[vs].decMuteCount();
}
- void setCurVolume(VolumeSource vs, float volumeDb, bool isVoiceVolSrc)
+ void setCurVolume(VolumeSource vs, float volumeDb, bool mutedByGroup, bool isVoiceVolSrc)
{
// Even if not activity for this source registered, need to create anyway
mVolumeActivities[vs].setVolume(volumeDb);
+ mVolumeActivities[vs].setMutedByGroup(mutedByGroup);
mVolumeActivities[vs].setIsVoice(isVoiceVolSrc);
}
float getCurVolume(VolumeSource vs) const
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 688772c..c2ee5f6 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -73,7 +73,8 @@
enum CompatibilityScore{
NO_MATCH = 0,
PARTIAL_MATCH = 1,
- EXACT_MATCH = 2
+ PARTIAL_MATCH_WITH_FLAG = 2,
+ EXACT_MATCH = 3
};
/**
@@ -92,7 +93,6 @@
* @param channelMask to be checked for compatibility. Must be specified
* @param updatedChannelMask if non-NULL, it is assigned the actual channel mask
* @param flags to be checked for compatibility
- * @param exactMatchRequiredForInputFlags true if exact match is required on flags
* @return how the IO profile is compatible with the given parameters.
*/
CompatibilityScore getCompatibilityScore(const DeviceVector &devices,
@@ -103,8 +103,7 @@
audio_channel_mask_t channelMask,
audio_channel_mask_t *updatedChannelMask,
// FIXME parameter type
- uint32_t flags,
- bool exactMatchRequiredForInputFlags = false) const;
+ uint32_t flags) const;
/**
* @brief areAllDevicesSupported: Checks if the given devices are supported by the IO profile.
@@ -119,11 +118,9 @@
* specified flags.
*
* @param flags to be checked for compatibility
- * @param exactMatchRequiredForInputFlags true if exact match is required on flags
* @return true if the profile is compatible, false otherwise.
*/
- bool isCompatibleProfileForFlags(uint32_t flags,
- bool exactMatchRequiredForInputFlags = false) const;
+ bool isCompatibleProfileForFlags(uint32_t flags) const;
void dump(String8 *dst, int spaces) const;
void log();
@@ -235,6 +232,7 @@
private:
void refreshMixerBehaviors();
+ CompatibilityScore getFlagsCompatibleScore(uint32_t flags) const;
DeviceVector mSupportedDevices; // supported devices: this input/output can be routed from/to
diff --git a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
index fd8b81a..ebfc597 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
@@ -41,6 +41,8 @@
virtual status_t initVolume(int indexMin, int indexMax) = 0;
virtual std::vector<audio_attributes_t> getAttributes() const = 0;
virtual std::vector<audio_stream_type_t> getStreamTypes() const = 0;
+ virtual void setIsMuted(bool isMuted) = 0;
+ virtual bool isMuted() const = 0;
virtual void dump(String8 *dst, int spaces = 0, bool curvePoints = false) const = 0;
};
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 2c41de4..c417462 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -22,6 +22,7 @@
#include <AudioPolicyInterface.h>
#include "AudioOutputDescriptor.h"
#include "AudioPolicyMix.h"
+#include <com_android_media_audio.h>
#include "IOProfile.h"
#include "Volume.h"
#include "HwModule.h"
@@ -161,7 +162,7 @@
return false;
}
-bool AudioOutputDescriptor::setVolume(float volumeDb, bool /*muted*/,
+bool AudioOutputDescriptor::setVolume(float volumeDb, bool mutedByGroup,
VolumeSource volumeSource,
const StreamTypeVector &/*streams*/,
const DeviceTypeSet& deviceTypes,
@@ -169,7 +170,6 @@
bool force,
bool isVoiceVolSrc)
{
-
if (!supportedDevices().containsDeviceAmongTypes(deviceTypes)) {
ALOGV("%s output ID %d unsupported device %s",
__func__, getId(), toString(deviceTypes).c_str());
@@ -177,10 +177,14 @@
}
// We actually change the volume if:
// - the float value returned by computeVolume() changed
+ // - the muted state changed
// - the force flag is set
- if (volumeDb != getCurVolume(volumeSource) || force) {
- ALOGV("%s for volumeSrc %d, volume %f, delay %d", __func__, volumeSource, volumeDb, delayMs);
- setCurVolume(volumeSource, volumeDb, isVoiceVolSrc);
+ const bool mutedChanged =
+ com_android_media_audio_ring_my_car() && (isMutedByGroup(volumeSource) != mutedByGroup);
+ if (volumeDb != getCurVolume(volumeSource) || mutedChanged || force) {
+ ALOGV("%s for volumeSrc %d, volume %f, mutedByGroup %d, delay %d", __func__, volumeSource,
+ volumeDb, mutedByGroup, delayMs);
+ setCurVolume(volumeSource, volumeDb, mutedByGroup, isVoiceVolSrc);
return true;
}
return false;
@@ -497,7 +501,7 @@
}
void SwAudioOutputDescriptor::setSwMute(
- bool muted, VolumeSource vs, const StreamTypeVector &streamTypes,
+ bool mutedByGroup, VolumeSource vs, const StreamTypeVector &streamTypes,
const DeviceTypeSet& deviceTypes, uint32_t delayMs) {
// volume source active and more than one volume source is active, otherwise, no-op or let
// setVolume controlling SW and/or HW Gains
@@ -506,11 +510,11 @@
for (const auto& devicePort : devices()) {
if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
devicePort->hasGainController(true /*canUseForVolume*/)) {
- float volumeAmpl = muted ? 0.0f : Volume::DbToAmpl(0);
ALOGV("%s: output: %d, vs: %d, muted: %d, active vs count: %zu", __func__,
- mIoHandle, vs, muted, getActiveVolumeSources().size());
+ mIoHandle, vs, mutedByGroup, getActiveVolumeSources().size());
for (const auto &stream : streamTypes) {
- mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ mClientInterface->setStreamVolume(stream, Volume::DbToAmpl(0), mutedByGroup,
+ mIoHandle, delayMs);
}
return;
}
@@ -521,11 +525,12 @@
for (const auto &devicePort: devices()) {
if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
devicePort->hasGainController(true /*canUseForVolume*/)) {
- float volumeAmpl = muted ? 0.0f : Volume::DbToAmpl(0);
+ float volumeAmpl = Volume::DbToAmpl(0);
ALOGV("%s: output: %d, vs: %d, muted: %d, active vs count: %zu", __func__,
- mIoHandle, vs, muted, getActiveVolumeSources().size());
+ mIoHandle, vs, mutedByGroup, getActiveVolumeSources().size());
mClientInterface->setPortsVolume(
- getPortsForVolumeSource(vs), volumeAmpl, mIoHandle, delayMs);
+ getPortsForVolumeSource(vs), Volume::DbToAmpl(0), mutedByGroup,
+ mIoHandle, delayMs);
return;
}
}
@@ -533,7 +538,7 @@
}
}
-bool SwAudioOutputDescriptor::setVolume(float volumeDb, bool muted,
+bool SwAudioOutputDescriptor::setVolume(float volumeDb, bool mutedByGroup,
VolumeSource vs, const StreamTypeVector &streamTypes,
const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
@@ -542,18 +547,22 @@
{
StreamTypeVector streams = streamTypes;
if (!AudioOutputDescriptor::setVolume(
- volumeDb, muted, vs, streamTypes, deviceTypes, delayMs, force, isVoiceVolSrc)) {
+ volumeDb, mutedByGroup, vs, streamTypes, deviceTypes, delayMs, force, isVoiceVolSrc)) {
if (hasStream(streamTypes, AUDIO_STREAM_BLUETOOTH_SCO)) {
VolumeSource callVolSrc = getVoiceSource();
- if (callVolSrc != VOLUME_SOURCE_NONE && volumeDb != getCurVolume(callVolSrc)) {
- setCurVolume(callVolSrc, volumeDb, true);
+ const bool mutedChanged =
+ com_android_media_audio_ring_my_car() && hasVolumeSource(callVolSrc) &&
+ (isMutedByGroup(callVolSrc) != mutedByGroup);
+ if (callVolSrc != VOLUME_SOURCE_NONE &&
+ (volumeDb != getCurVolume(callVolSrc) || mutedChanged)) {
+ setCurVolume(callVolSrc, volumeDb, mutedByGroup, true);
float volumeAmpl = Volume::DbToAmpl(volumeDb);
if (audioserver_flags::portid_volume_management()) {
mClientInterface->setPortsVolume(getPortsForVolumeSource(callVolSrc),
- volumeAmpl, mIoHandle, delayMs);
+ volumeAmpl, mutedByGroup, mIoHandle, delayMs);
} else {
mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL,
- volumeAmpl, mIoHandle, delayMs);
+ volumeAmpl, mutedByGroup, mIoHandle, delayMs);
}
}
}
@@ -580,18 +589,19 @@
// Allows to mute SW Gain on AudioFlinger only for volume group with explicit
// stream(s)
if (!streamTypes.empty() || (getActiveVolumeSources().size() == 1)) {
- const bool canMute = muted && (volumeDb != 0.0f) && !streamTypes.empty();
- float volumeAmpl = canMute ? 0.0f : Volume::DbToAmpl(0);
+ const bool canMute = mutedByGroup && !streamTypes.empty();
+ const float volumeAmpl = Volume::DbToAmpl(0);
for (const auto &stream: streams) {
- mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ mClientInterface->setStreamVolume(stream, volumeAmpl, canMute, mIoHandle,
+ delayMs);
}
}
} else {
- float volumeAmpl = (muted && volumeDb != 0.0f) ? 0.0f : Volume::DbToAmpl(0);
+ float volumeAmpl = Volume::DbToAmpl(0);
ALOGV("%s: output: %d, vs: %d, active vs count: %zu", __func__,
mIoHandle, vs, getActiveVolumeSources().size());
mClientInterface->setPortsVolume(
- getPortsForVolumeSource(vs), volumeAmpl, mIoHandle, delayMs);
+ getPortsForVolumeSource(vs), volumeAmpl, mutedByGroup, mIoHandle, delayMs);
}
AudioGains gains = devicePort->getGains();
int gainMinValueInMb = gains[0]->getMinValueInMb();
@@ -615,26 +625,27 @@
if (audioserver_flags::portid_volume_management()) {
if (callVolSrc != VOLUME_SOURCE_NONE) {
mClientInterface->setPortsVolume(getPortsForVolumeSource(callVolSrc), volumeAmpl,
- mIoHandle, delayMs);
+ mutedByGroup, mIoHandle, delayMs);
}
} else {
- mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mIoHandle,
- delayMs);
+ mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mutedByGroup,
+ mIoHandle, delayMs);
}
if (callVolSrc != VOLUME_SOURCE_NONE) {
- setCurVolume(callVolSrc, getCurVolume(vs), true);
+ setCurVolume(callVolSrc, getCurVolume(vs), mutedByGroup, true);
}
}
if (audioserver_flags::portid_volume_management()) {
- ALOGV("%s output %d for volumeSource %d, volume %f, delay %d active=%d", __func__,
- mIoHandle, vs, volumeDb, delayMs, isActive(vs));
- mClientInterface->setPortsVolume(getPortsForVolumeSource(vs), volumeAmpl, mIoHandle,
- delayMs);
+ ALOGV("%s output %d for volumeSource %d, volume %f, mutedByGroup %d, delay %d active=%d",
+ __func__, mIoHandle, vs, volumeDb, mutedByGroup, delayMs, isActive(vs));
+ mClientInterface->setPortsVolume(getPortsForVolumeSource(vs), volumeAmpl, mutedByGroup,
+ mIoHandle, delayMs);
} else {
for (const auto &stream : streams) {
- ALOGV("%s output %d for volumeSource %d, volume %f, delay %d stream=%s", __func__,
- mIoHandle, vs, volumeDb, delayMs, toString(stream).c_str());
- mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ ALOGV("%s output %d for volumeSource %d, volume %f, mutedByGroup %d delay %d stream=%s",
+ __func__, mIoHandle, vs, volumeDb, mutedByGroup, delayMs,
+ toString(stream).c_str());
+ mClientInterface->setStreamVolume(stream, volumeAmpl, mutedByGroup, mIoHandle, delayMs);
}
}
return true;
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 991b103..bc9eb20 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -42,15 +42,14 @@
audio_channel_mask_t channelMask,
audio_channel_mask_t *updatedChannelMask,
// FIXME type punning here
- uint32_t flags,
- bool exactMatchRequiredForInputFlags) const {
+ uint32_t flags) const {
const bool isPlaybackThread =
getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SOURCE;
const bool isRecordThread =
getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SINK;
ALOG_ASSERT(isPlaybackThread != isRecordThread);
- if (!areAllDevicesSupported(devices) ||
- !isCompatibleProfileForFlags(flags, exactMatchRequiredForInputFlags)) {
+ const auto flagsCompatibleScore = getFlagsCompatibleScore(flags);
+ if (!areAllDevicesSupported(devices) || flagsCompatibleScore == NO_MATCH) {
return NO_MATCH;
}
@@ -81,7 +80,11 @@
result = EXACT_MATCH;
} else if (checkCompatibleAudioProfile(
myUpdatedSamplingRate, myUpdatedChannelMask, myUpdatedFormat) == NO_ERROR) {
- result = PARTIAL_MATCH;
+ if (flagsCompatibleScore == EXACT_MATCH) {
+ result = PARTIAL_MATCH_WITH_FLAG;
+ } else {
+ result = PARTIAL_MATCH;
+ }
} else {
return result;
}
@@ -118,32 +121,8 @@
return mSupportedDevices.containsAllDevices(devices);
}
-bool IOProfile::isCompatibleProfileForFlags(uint32_t flags,
- bool exactMatchRequiredForInputFlags) const {
- const bool isPlaybackThread =
- getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SOURCE;
- const bool isRecordThread =
- getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SINK;
- ALOG_ASSERT(isPlaybackThread != isRecordThread);
-
- const uint32_t mustMatchOutputFlags =
- AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
- if (isPlaybackThread &&
- !audio_output_flags_is_subset((audio_output_flags_t)getFlags(),
- (audio_output_flags_t)flags,
- mustMatchOutputFlags)) {
- return false;
- }
- // The only input flag that is allowed to be different is the fast flag.
- // An existing fast stream is compatible with a normal track request.
- // An existing normal stream is compatible with a fast track request,
- // but the fast request will be denied by AudioFlinger and converted to normal track.
- if (isRecordThread && ((getFlags() ^ flags) &
- ~(exactMatchRequiredForInputFlags ? AUDIO_INPUT_FLAG_NONE : AUDIO_INPUT_FLAG_FAST))) {
- return false;
- }
-
- return true;
+bool IOProfile::isCompatibleProfileForFlags(uint32_t flags) const {
+ return getFlagsCompatibleScore(flags) != NO_MATCH;
}
bool IOProfile::containsSingleDeviceSupportingEncodedFormats(
@@ -228,6 +207,39 @@
}
}
+IOProfile::CompatibilityScore IOProfile::getFlagsCompatibleScore(uint32_t flags) const {
+ const bool isPlaybackThread =
+ getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SOURCE;
+ const bool isRecordThread =
+ getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SINK;
+ ALOG_ASSERT(isPlaybackThread != isRecordThread);
+
+ const uint32_t mustMatchOutputFlags =
+ AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ if (isPlaybackThread &&
+ !audio_output_flags_is_subset((audio_output_flags_t)getFlags(),
+ (audio_output_flags_t)flags,
+ mustMatchOutputFlags)) {
+ return NO_MATCH;
+ }
+ // The only input flag that is allowed to be different is the fast flag.
+ // An existing fast stream is compatible with a normal track request.
+ // An existing normal stream is compatible with a fast track request,
+ // but the fast request will be denied by AudioFlinger and converted to normal track.
+ if (isRecordThread) {
+ const auto unmatchedFlag = getFlags() ^ flags;
+ if (unmatchedFlag == AUDIO_INPUT_FLAG_NONE) {
+ return EXACT_MATCH;
+ } else if (unmatchedFlag == AUDIO_INPUT_FLAG_FAST) {
+ return PARTIAL_MATCH;
+ } else {
+ return NO_MATCH;
+ }
+ }
+
+ return EXACT_MATCH;
+}
+
void IOProfile::dump(String8 *dst, int spaces) const
{
String8 extraInfo;
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 8162720..9b1125d 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -92,6 +92,10 @@
bool isDefault() const;
+ bool isPatchStrategy() const {
+ return getVolumeGroupForStreamType(AUDIO_STREAM_PATCH) != VOLUME_GROUP_NONE;
+ }
+
void dump(String8 *dst, int spaces = 0) const;
private:
diff --git a/services/audiopolicy/engine/common/include/VolumeCurve.h b/services/audiopolicy/engine/common/include/VolumeCurve.h
index 2e75ff1..e5f7a41 100644
--- a/services/audiopolicy/engine/common/include/VolumeCurve.h
+++ b/services/audiopolicy/engine/common/include/VolumeCurve.h
@@ -179,6 +179,12 @@
}
StreamTypeVector getStreamTypes() const override { return mStreams; }
+ void setIsMuted(bool isMuted)
+ {
+ mIsMuted = isMuted;
+ }
+ bool isMuted() const { return mIsMuted; }
+
void dump(String8 *dst, int spaces = 0, bool curvePoints = false) const override;
private:
@@ -187,6 +193,7 @@
int mIndexMin; /**< min volume index. */
int mIndexMax; /**< max volume index. */
const bool mCanBeMuted = true; /**< true is the stream can be muted. */
+ bool mIsMuted = false; /**< true if the stream is currently muted. */
AttributesVector mAttributes;
StreamTypeVector mStreams; /**< Keep it for legacy. */
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 976791f..fb8379e 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -311,6 +311,9 @@
}
StrategyVector orderedStrategies;
for (const auto &iter : strategies) {
+ if (iter.second->isPatchStrategy()) {
+ continue;
+ }
orderedStrategies.push_back(iter.second->getId());
}
return orderedStrategies;
@@ -742,6 +745,9 @@
auto defaultDevices = DeviceVector(getApmObserver()->getDefaultOutputDevice());
for (const auto &iter : getProductStrategies()) {
const auto &strategy = iter.second;
+ if (strategy->isPatchStrategy()) {
+ continue;
+ }
mDevicesForStrategies[strategy->getId()] = defaultDevices;
setStrategyDevices(strategy, defaultDevices);
}
@@ -750,6 +756,9 @@
void EngineBase::updateDeviceSelectionCache() {
for (const auto &iter : getProductStrategies()) {
const auto& strategy = iter.second;
+ if (strategy->isPatchStrategy()) {
+ continue;
+ }
auto devices = getDevicesForProductStrategy(strategy->getId());
mDevicesForStrategies[strategy->getId()] = devices;
setStrategyDevices(strategy, devices);
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
index c9a77a4..27a290f 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
@@ -45,4 +45,7 @@
"libparameter",
"libutils",
],
+ defaults: [
+ "aconfig_lib_cc_shared_link.defaults",
+ ],
}
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index fd40c04..a5f37b0 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -266,6 +266,7 @@
bool isSpatialized;
bool isBitPerfect;
float volume;
+ bool muted;
// TODO b/182392769: use attribution source util
AttributionSourceState attributionSource;
@@ -273,7 +274,7 @@
attributionSource.token = sp<BBinder>::make();
if (mManager->getOutputForAttr(&attr, output, AUDIO_SESSION_NONE, &stream, attributionSource,
&config, &flags, selectedDeviceId, portId, {}, &outputType, &isSpatialized,
- &isBitPerfect, &volume) != OK) {
+ &isBitPerfect, &volume, &muted) != OK) {
return false;
}
if (*output == AUDIO_IO_HANDLE_NONE || *portId == AUDIO_PORT_HANDLE_NONE) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c1c4a28..0aa3dfc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1512,7 +1512,8 @@
output_type_t *outputType,
bool *isSpatialized,
bool *isBitPerfect,
- float *volume)
+ float *volume,
+ bool *muted)
{
// The supplied portId must be AUDIO_PORT_HANDLE_NONE
if (*portId != AUDIO_PORT_HANDLE_NONE) {
@@ -1569,6 +1570,7 @@
outputDesc->addClient(clientDesc);
*volume = Volume::DbToAmpl(outputDesc->getCurVolume(toVolumeSource(resultAttr)));
+ *muted = outputDesc->isMutedByGroup(toVolumeSource(resultAttr));
ALOGV("%s() returns output %d requestedPortId %d selectedDeviceId %d for port ID %d", __func__,
*output, requestedPortId, *selectedDeviceId, *portId);
@@ -2617,8 +2619,7 @@
auto &curves = getVolumeCurves(client->attributes());
if (NO_ERROR != checkAndSetVolume(curves, client->volumeSource(),
curves.getVolumeIndex(outputDesc->devices().types()),
- outputDesc,
- outputDesc->devices().types(), 0 /*delay*/,
+ outputDesc, outputDesc->devices().types(), 0 /*delay*/,
outputDesc->useHwGain() /*force*/)) {
// request AudioService to reinitialize the volume curves asynchronously
ALOGE("checkAndSetVolume failed, requesting volume range init");
@@ -3555,6 +3556,9 @@
bool enabled,
audio_stream_type_t streamToDriveAbs)
{
+ ALOGI("%s: deviceType 0x%X, enabled %d, streamToDriveAbs %d", __func__, deviceType, enabled,
+ streamToDriveAbs);
+
if (!enabled) {
mAbsoluteVolumeDrivingStreams.erase(deviceType);
return NO_ERROR;
@@ -3591,6 +3595,7 @@
status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
int index,
+ bool muted,
audio_devices_t device)
{
auto attributes = mEngine->getAttributesForStreamType(stream);
@@ -3600,7 +3605,7 @@
}
ALOGV("%s: stream %s attributes=%s, index %d , device 0x%X", __func__,
toString(stream).c_str(), toString(attributes).c_str(), index, device);
- return setVolumeIndexForAttributes(attributes, index, device);
+ return setVolumeIndexForAttributes(attributes, index, muted, device);
}
status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream,
@@ -3619,6 +3624,7 @@
status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_t &attributes,
int index,
+ bool muted,
audio_devices_t device)
{
// Get Volume group matching the Audio Attributes
@@ -3629,6 +3635,11 @@
}
ALOGV("%s: group %d matching with %s index %d",
__FUNCTION__, group, toString(attributes).c_str(), index);
+ if (mEngine->getStreamTypeForAttributes(attributes) == AUDIO_STREAM_PATCH) {
+ ALOGV("%s: cannot change volume for PATCH stream, attrs: %s",
+ __FUNCTION__, toString(attributes).c_str());
+ return NO_ERROR;
+ }
status_t status = NO_ERROR;
IVolumeCurves &curves = getVolumeCurves(attributes);
VolumeSource vs = toVolumeSource(group);
@@ -3638,7 +3649,8 @@
toVolumeSource(AUDIO_STREAM_VOICE_CALL, false) : vs;
product_strategy_t strategy = mEngine->getProductStrategyForAttributes(attributes);
- status = setVolumeCurveIndex(index, device, curves);
+
+ status = setVolumeCurveIndex(index, muted, device, curves);
if (status != NO_ERROR) {
ALOGE("%s failed to set curve index for group %d device 0x%X", __func__, group, device);
return status;
@@ -3700,8 +3712,9 @@
// HW Gain management, do not change the volume
if (desc->useHwGain()) {
applyVolume = false;
+ bool swMute = com_android_media_audio_ring_my_car() ? curves.isMuted() : (index == 0);
// If the volume source is active with higher priority source, ensure at least Sw Muted
- desc->setSwMute((index == 0), vs, curves.getStreamTypes(), curDevices, 0 /*delayMs*/);
+ desc->setSwMute(swMute, vs, curves.getStreamTypes(), curDevices, 0 /*delayMs*/);
for (const auto &productStrategy : mEngine->getOrderedProductStrategies()) {
auto activeClients = desc->clientsList(true /*activeOnly*/, productStrategy,
false /*preferredDevice*/);
@@ -3739,8 +3752,7 @@
//FIXME: workaround for truncated touch sounds
// delayed volume change for system stream to be removed when the problem is
// handled by system UI
- status_t volStatus = checkAndSetVolume(
- curves, vs, index, desc, curDevices,
+ status_t volStatus = checkAndSetVolume(curves, vs, index, desc, curDevices,
((vs == toVolumeSource(AUDIO_STREAM_SYSTEM, false))?
TOUCH_SOUND_FIXED_DELAY_MS : 0));
if (volStatus != NO_ERROR) {
@@ -3769,6 +3781,7 @@
}
status_t AudioPolicyManager::setVolumeCurveIndex(int index,
+ bool muted,
audio_devices_t device,
IVolumeCurves &volumeCurves)
{
@@ -3788,8 +3801,9 @@
// Force max volume if stream cannot be muted
if (!volumeCurves.canBeMuted()) index = volumeCurves.getVolumeIndexMax();
- ALOGV("%s device %08x, index %d", __FUNCTION__ , device, index);
+ ALOGV("%s device %08x, index %d, muted %d", __FUNCTION__ , device, index, muted);
volumeCurves.addCurrentVolumeIndex(device, index);
+ volumeCurves.setIsMuted(muted);
return NO_ERROR;
}
@@ -5011,8 +5025,7 @@
nullptr /*updatedFormat*/,
mixerAttributes->config.channel_mask,
nullptr /*updatedChannelMask*/,
- flags,
- false /*exactMatchRequiredForInputFlags*/)
+ flags)
!= IOProfile::NO_MATCH) {
profile = curProfile;
break;
@@ -7898,7 +7911,8 @@
}
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- setVolumeSourceMute(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/, DeviceTypeSet());
+ setVolumeSourceMutedInternally(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/,
+ DeviceTypeSet());
const uint32_t latency = desc->latency() * 2;
if (desc->isActive(latency * 2) && latency > maxLatency) {
maxLatency = latency;
@@ -7992,9 +8006,10 @@
for (const auto &activeVs : outputDesc->getActiveVolumeSources()) {
// make sure that we do not start the temporary mute period too early in case of
// delayed device change
- setVolumeSourceMute(activeVs, true, outputDesc, delayMs);
- setVolumeSourceMute(activeVs, false, outputDesc, delayMs + tempMuteDurationMs,
- devices.types());
+ setVolumeSourceMutedInternally(activeVs, true, outputDesc, delayMs);
+ setVolumeSourceMutedInternally(activeVs, false, outputDesc,
+ delayMs + tempMuteDurationMs,
+ devices.types());
}
}
@@ -8220,7 +8235,7 @@
const underlying_input_flag_t oriFlags = flags;
for (;;) {
- sp<IOProfile> firstInexact = nullptr;
+ sp<IOProfile> inexact = nullptr;
uint32_t inexactSamplingRate = 0;
audio_format_t inexactFormat = AUDIO_FORMAT_INVALID;
audio_channel_mask_t inexactChannelMask = AUDIO_CHANNEL_INVALID;
@@ -8231,7 +8246,7 @@
for (const auto& profile : hwModule->getInputProfiles()) {
// profile->log();
//updatedFormat = format;
- if (profile->getCompatibilityScore(
+ auto compatibleScore = profile->getCompatibilityScore(
DeviceVector(device),
samplingRate,
&updatedSamplingRate,
@@ -8240,27 +8255,16 @@
channelMask,
&updatedChannelMask,
// FIXME ugly cast
- (audio_output_flags_t) flags,
- true /*exactMatchRequiredForInputFlags*/) == IOProfile::EXACT_MATCH) {
+ (audio_output_flags_t) flags);
+ if (compatibleScore == IOProfile::EXACT_MATCH) {
samplingRate = updatedSamplingRate;
format = updatedFormat;
channelMask = updatedChannelMask;
return profile;
- }
- if (firstInexact == nullptr
- && profile->getCompatibilityScore(
- DeviceVector(device),
- samplingRate,
- &updatedSamplingRate,
- format,
- &updatedFormat,
- channelMask,
- &updatedChannelMask,
- // FIXME ugly cast
- (audio_output_flags_t) flags,
- false /*exactMatchRequiredForInputFlags*/)
- != IOProfile::NO_MATCH) {
- firstInexact = profile;
+ } else if ((flags != AUDIO_INPUT_FLAG_NONE
+ && compatibleScore == IOProfile::PARTIAL_MATCH_WITH_FLAG)
+ || (inexact == nullptr && compatibleScore != IOProfile::NO_MATCH)) {
+ inexact = profile;
inexactSamplingRate = updatedSamplingRate;
inexactFormat = updatedFormat;
inexactChannelMask = updatedChannelMask;
@@ -8268,11 +8272,11 @@
}
}
- if (firstInexact != nullptr) {
+ if (inexact != nullptr) {
samplingRate = inexactSamplingRate;
format = inexactFormat;
channelMask = inexactChannelMask;
- return firstInexact;
+ return inexact;
} else if (flags & AUDIO_INPUT_FLAG_RAW) {
flags = (audio_input_flags_t) (flags & ~AUDIO_INPUT_FLAG_RAW); // retry
} else if ((flags & mustMatchFlag) == AUDIO_INPUT_FLAG_NONE &&
@@ -8299,9 +8303,9 @@
float volumeDb = curves.volIndexToDb(deviceCategory, index);
if (com_android_media_audio_abs_volume_index_fix()) {
- if (mAbsoluteVolumeDrivingStreams.find(volumeDevice) !=
- mAbsoluteVolumeDrivingStreams.end()) {
- audio_attributes_t attributesToDriveAbs = mAbsoluteVolumeDrivingStreams[volumeDevice];
+ const auto it = mAbsoluteVolumeDrivingStreams.find(volumeDevice);
+ if (it != mAbsoluteVolumeDrivingStreams.end()) {
+ audio_attributes_t attributesToDriveAbs = it->second;
auto groupToDriveAbs = mEngine->getVolumeGroupForAttributes(attributesToDriveAbs);
if (groupToDriveAbs == VOLUME_GROUP_NONE) {
ALOGD("%s: no group matching with %s", __FUNCTION__,
@@ -8507,7 +8511,7 @@
static std::set<IVolumeCurves*> invalidCurvesReported;
// do not change actual attributes volume if the attributes is muted
- if (outputDesc->isMuted(volumeSource)) {
+ if (!com_android_media_audio_ring_my_car() && outputDesc->isMutedInternally(volumeSource)) {
ALOGVV("%s: volume source %d muted count %d active=%d", __func__, volumeSource,
outputDesc->getMuteCount(volumeSource), outputDesc->isActive(volumeSource));
return NO_ERROR;
@@ -8549,7 +8553,13 @@
|| isSingleDeviceType(deviceTypes, audio_is_ble_out_device)))) {
volumeDb = 0.0f;
}
- const bool muted = (index == 0) && (volumeDb != 0.0f);
+
+ bool muted;
+ if (!com_android_media_audio_ring_my_car()) {
+ muted = (index == 0) && (volumeDb != 0.0f);
+ } else {
+ muted = curves.isMuted();
+ }
outputDesc->setVolume(volumeDb, muted, volumeSource, curves.getStreamTypes(),
deviceTypes, delayMs, force, isVoiceVolSrc);
@@ -8564,6 +8574,11 @@
void AudioPolicyManager::setVoiceVolume(
int index, IVolumeCurves &curves, bool voiceVolumeManagedByHost, int delayMs) {
float voiceVolume;
+
+ if (com_android_media_audio_ring_my_car() && curves.isMuted()) {
+ index = 0;
+ }
+
// Force voice volume to max or mute for Bluetooth SCO/BLE as other attenuations are managed
// by the headset
if (voiceVolumeManagedByHost) {
@@ -8617,8 +8632,7 @@
ALOGVV("applyStreamVolumes() for device %s", dumpDeviceTypes(deviceTypes).c_str());
for (const auto &volumeGroup : mEngine->getVolumeGroups()) {
auto &curves = getVolumeCurves(toVolumeSource(volumeGroup));
- checkAndSetVolume(curves, toVolumeSource(volumeGroup),
- curves.getVolumeIndex(deviceTypes),
+ checkAndSetVolume(curves, toVolumeSource(volumeGroup), curves.getVolumeIndex(deviceTypes),
outputDesc, deviceTypes, delayMs, force);
}
}
@@ -8641,23 +8655,23 @@
}
}
for (auto source : sourcesToMute) {
- setVolumeSourceMute(source, on, outputDesc, delayMs, deviceTypes);
+ setVolumeSourceMutedInternally(source, on, outputDesc, delayMs, deviceTypes);
}
}
-void AudioPolicyManager::setVolumeSourceMute(VolumeSource volumeSource,
- bool on,
- const sp<AudioOutputDescriptor>& outputDesc,
- int delayMs,
- DeviceTypeSet deviceTypes)
+void AudioPolicyManager::setVolumeSourceMutedInternally(VolumeSource volumeSource,
+ bool on,
+ const sp<AudioOutputDescriptor>& outputDesc,
+ int delayMs,
+ DeviceTypeSet deviceTypes)
{
if (deviceTypes.empty()) {
deviceTypes = outputDesc->devices().types();
}
auto &curves = getVolumeCurves(volumeSource);
if (on) {
- if (!outputDesc->isMuted(volumeSource)) {
+ if (!outputDesc->isMutedInternally(volumeSource)) {
if (curves.canBeMuted() &&
(volumeSource != toVolumeSource(AUDIO_STREAM_ENFORCED_AUDIBLE, false) ||
(mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) ==
@@ -8669,7 +8683,7 @@
// ignored
outputDesc->incMuteCount(volumeSource);
} else {
- if (!outputDesc->isMuted(volumeSource)) {
+ if (!outputDesc->isMutedInternally(volumeSource)) {
ALOGV("%s unmuting non muted attributes!", __func__);
return;
}
@@ -9235,8 +9249,7 @@
: hwModule->getOutputProfiles();
for (const auto& profile : ioProfiles) {
if (!profile->areAllDevicesSupported(devices) ||
- !profile->isCompatibleProfileForFlags(
- flags, false /*exactMatchRequiredForInputFlags*/)) {
+ !profile->isCompatibleProfileForFlags(flags)) {
continue;
}
audioProfiles.addAllValidProfiles(profile->asAudioPort()->getAudioProfiles());
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 9ad2ea5..20f7b12 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -129,7 +129,8 @@
output_type_t *outputType,
bool *isSpatialized,
bool *isBitPerfect,
- float *volume) override;
+ float *volume,
+ bool *muted) override;
virtual status_t startOutput(audio_port_handle_t portId);
virtual status_t stopOutput(audio_port_handle_t portId);
virtual bool releaseOutput(audio_port_handle_t portId);
@@ -169,6 +170,7 @@
virtual void initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax);
virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
int index,
+ bool muted,
audio_devices_t device);
virtual status_t getStreamVolumeIndex(audio_stream_type_t stream,
int *index,
@@ -176,6 +178,7 @@
virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
int index,
+ bool muted,
audio_devices_t device);
virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
int &index,
@@ -185,6 +188,7 @@
virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
status_t setVolumeCurveIndex(int index,
+ bool muted,
audio_devices_t device,
IVolumeCurves &volumeCurves);
@@ -650,7 +654,8 @@
DeviceTypeSet deviceTypes = DeviceTypeSet());
/**
- * @brief setVolumeSourceMute Mute or unmute the volume source on the specified output
+ * @brief setVolumeSourceMutedInternally Mute or unmute the volume source on the specified
+ * output
* @param volumeSource to be muted/unmute (may host legacy streams or by extension set of
* audio attributes)
* @param on true to mute, false to umute
@@ -658,11 +663,11 @@
* @param delayMs
* @param device
*/
- void setVolumeSourceMute(VolumeSource volumeSource,
- bool on,
- const sp<AudioOutputDescriptor>& outputDesc,
- int delayMs = 0,
- DeviceTypeSet deviceTypes = DeviceTypeSet());
+ void setVolumeSourceMutedInternally(VolumeSource volumeSource,
+ bool on,
+ const sp<AudioOutputDescriptor>& outputDesc,
+ int delayMs = 0,
+ DeviceTypeSet deviceTypes = DeviceTypeSet());
audio_mode_t getPhoneState();
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 363dfa7..3ed247b 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -186,21 +186,19 @@
}
status_t AudioPolicyService::AudioPolicyClient::setStreamVolume(audio_stream_type_t stream,
- float volume, audio_io_handle_t output,
- int delay_ms)
+ float volume, bool muted, audio_io_handle_t output, int delay_ms)
{
- return mAudioPolicyService->setStreamVolume(stream, volume, output,
- delay_ms);
+ return mAudioPolicyService->setStreamVolume(stream, volume, muted, output, delay_ms);
}
status_t AudioPolicyService::AudioPolicyClient::setPortsVolume(
- const std::vector<audio_port_handle_t> &ports, float volume, audio_io_handle_t output,
- int delayMs)
+ const std::vector<audio_port_handle_t> &ports, float volume, bool muted,
+ audio_io_handle_t output, int delayMs)
{
if (ports.empty()) {
return NO_ERROR;
}
- return mAudioPolicyService->setPortsVolume(ports, volume, output, delayMs);
+ return mAudioPolicyService->setPortsVolume(ports, volume, muted, output, delayMs);
}
void AudioPolicyService::AudioPolicyClient::setParameters(audio_io_handle_t io_handle,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 24ab6a1..0442cae 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -430,6 +430,7 @@
bool isSpatialized = false;
bool isBitPerfect = false;
float volume;
+ bool muted;
status_t result = mAudioPolicyManager->getOutputForAttr(&attr, &output, session,
&stream,
attributionSource,
@@ -439,7 +440,8 @@
&outputType,
&isSpatialized,
&isBitPerfect,
- &volume);
+ &volume,
+ &muted);
// FIXME: Introduce a way to check for the the telephony device before opening the output
if (result == NO_ERROR) {
@@ -504,6 +506,7 @@
_aidl_return->attr = VALUE_OR_RETURN_BINDER_STATUS(
legacy2aidl_audio_attributes_t_AudioAttributes(attr));
_aidl_return->volume = volume;
+ _aidl_return->muted = muted;
} else {
_aidl_return->configBase.format = VALUE_OR_RETURN_BINDER_STATUS(
legacy2aidl_audio_format_t_AudioFormatDescription(config.format));
@@ -1118,8 +1121,15 @@
Status AudioPolicyService::setDeviceAbsoluteVolumeEnabled(const AudioDevice& deviceAidl,
bool enabled,
AudioStreamType streamToDriveAbsAidl) {
- audio_stream_type_t streamToDriveAbs = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioStreamType_audio_stream_type_t(streamToDriveAbsAidl));
+ ALOGI("%s: deviceAidl %s, enabled %d, streamToDriveAbsAidl %d", __func__,
+ deviceAidl.toString().c_str(), enabled, streamToDriveAbsAidl);
+
+ audio_stream_type_t streamToDriveAbs = AUDIO_STREAM_DEFAULT;
+ if (enabled) {
+ streamToDriveAbs = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(streamToDriveAbsAidl));
+ }
+
audio_devices_t deviceType;
std::string address;
RETURN_BINDER_STATUS_IF_ERROR(
@@ -1133,9 +1143,7 @@
: settingsAllowed())) {
return binderStatusFromStatusT(PERMISSION_DENIED);
}
- if (uint32_t(streamToDriveAbs) >= AUDIO_STREAM_PUBLIC_CNT) {
- return binderStatusFromStatusT(BAD_VALUE);
- }
+
audio_utils::lock_guard _l(mMutex);
AutoCallerClear acc;
return binderStatusFromStatusT(
@@ -1170,7 +1178,7 @@
Status AudioPolicyService::setStreamVolumeIndex(AudioStreamType streamAidl,
const AudioDeviceDescription& deviceAidl,
- int32_t indexAidl) {
+ int32_t indexAidl, bool muted) {
audio_stream_type_t stream = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioStreamType_audio_stream_type_t(streamAidl));
int index = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int>(indexAidl));
@@ -1192,6 +1200,7 @@
AutoCallerClear acc;
return binderStatusFromStatusT(mAudioPolicyManager->setStreamVolumeIndex(stream,
index,
+ muted,
device));
}
@@ -1220,7 +1229,7 @@
Status AudioPolicyService::setVolumeIndexForAttributes(
const media::audio::common::AudioAttributes& attrAidl,
- const AudioDeviceDescription& deviceAidl, int32_t indexAidl) {
+ const AudioDeviceDescription& deviceAidl, int32_t indexAidl, bool muted) {
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
int index = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int>(indexAidl));
@@ -1240,7 +1249,7 @@
audio_utils::lock_guard _l(mMutex);
AutoCallerClear acc;
return binderStatusFromStatusT(
- mAudioPolicyManager->setVolumeIndexForAttributes(attributes, index, device));
+ mAudioPolicyManager->setVolumeIndexForAttributes(attributes, index, muted, device));
}
Status AudioPolicyService::getVolumeIndexForAttributes(
@@ -1687,6 +1696,19 @@
return Status::ok();
}
+template <typename Port>
+void anonymizePortBluetoothAddress(Port& port) {
+ if (port.type != AUDIO_PORT_TYPE_DEVICE) {
+ return;
+ }
+ if (!(audio_is_a2dp_device(port.ext.device.type)
+ || audio_is_ble_device(port.ext.device.type)
+ || audio_is_bluetooth_sco_device(port.ext.device.type)
+ || audio_is_hearing_aid_out_device(port.ext.device.type))) {
+ return;
+ }
+ anonymizeBluetoothAddress(port.ext.device.address);
+}
Status AudioPolicyService::listAudioPorts(media::AudioPortRole roleAidl,
media::AudioPortType typeAidl, Int* count,
@@ -1705,14 +1727,27 @@
std::unique_ptr<audio_port_v7[]> ports(new audio_port_v7[num_ports]);
unsigned int generation;
- audio_utils::lock_guard _l(mMutex);
- if (mAudioPolicyManager == NULL) {
- return binderStatusFromStatusT(NO_INIT);
- }
+ const AttributionSourceState attributionSource = getCallingAttributionSource();
AutoCallerClear acc;
- RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
- mAudioPolicyManager->listAudioPorts(role, type, &num_ports, ports.get(), &generation)));
- numPortsReq = std::min(numPortsReq, num_ports);
+ {
+ audio_utils::lock_guard _l(mMutex);
+ if (mAudioPolicyManager == NULL) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+ // AudioPolicyManager->listAudioPorts makes a deep copy of port structs into ports
+ // so it is safe to access after releasing the mutex
+ RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
+ mAudioPolicyManager->listAudioPorts(
+ role, type, &num_ports, ports.get(), &generation)));
+ numPortsReq = std::min(numPortsReq, num_ports);
+ }
+
+ if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) {
+ for (size_t i = 0; i < numPortsReq; ++i) {
+ anonymizePortBluetoothAddress(ports[i]);
+ }
+ }
+
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
convertRange(ports.get(), ports.get() + numPortsReq, std::back_inserter(*portsAidl),
legacy2aidl_audio_port_v7_AudioPortFw)));
@@ -1735,12 +1770,24 @@
Status AudioPolicyService::getAudioPort(int portId,
media::AudioPortFw* _aidl_return) {
audio_port_v7 port{ .id = portId };
- audio_utils::lock_guard _l(mMutex);
- if (mAudioPolicyManager == NULL) {
- return binderStatusFromStatusT(NO_INIT);
- }
+
+ const AttributionSourceState attributionSource = getCallingAttributionSource();
AutoCallerClear acc;
- RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(mAudioPolicyManager->getAudioPort(&port)));
+
+ {
+ audio_utils::lock_guard _l(mMutex);
+ if (mAudioPolicyManager == NULL) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+ // AudioPolicyManager->getAudioPort makes a deep copy of the port struct into port
+ // so it is safe to access after releasing the mutex
+ RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(mAudioPolicyManager->getAudioPort(&port)));
+ }
+
+ if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) {
+ anonymizePortBluetoothAddress(port);
+ }
+
*_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_port_v7_AudioPortFw(port));
return Status::ok();
}
@@ -1802,14 +1849,32 @@
std::unique_ptr<audio_patch[]> patches(new audio_patch[num_patches]);
unsigned int generation;
- audio_utils::lock_guard _l(mMutex);
- if (mAudioPolicyManager == NULL) {
- return binderStatusFromStatusT(NO_INIT);
- }
+ const AttributionSourceState attributionSource = getCallingAttributionSource();
AutoCallerClear acc;
- RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
- mAudioPolicyManager->listAudioPatches(&num_patches, patches.get(), &generation)));
- numPatchesReq = std::min(numPatchesReq, num_patches);
+
+ {
+ audio_utils::lock_guard _l(mMutex);
+ if (mAudioPolicyManager == NULL) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+ // AudioPolicyManager->listAudioPatches makes a deep copy of patches structs into patches
+ // so it is safe to access after releasing the mutex
+ RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
+ mAudioPolicyManager->listAudioPatches(&num_patches, patches.get(), &generation)));
+ numPatchesReq = std::min(numPatchesReq, num_patches);
+ }
+
+ if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) {
+ for (size_t i = 0; i < numPatchesReq; ++i) {
+ for (size_t j = 0; j < patches[i].num_sources; ++j) {
+ anonymizePortBluetoothAddress(patches[i].sources[j]);
+ }
+ for (size_t j = 0; j < patches[i].num_sinks; ++j) {
+ anonymizePortBluetoothAddress(patches[i].sinks[j]);
+ }
+ }
+ }
+
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
convertRange(patches.get(), patches.get() + numPatchesReq,
std::back_inserter(*patchesAidl), legacy2aidl_audio_patch_AudioPatchFw)));
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 7b7275e..290a036 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1041,6 +1041,9 @@
current->attributionSource.uid == topSensitiveActive->attributionSource.uid;
bool isTopOrLatestAssistant = latestActiveAssistant == nullptr ? false :
current->attributionSource.uid == latestActiveAssistant->attributionSource.uid;
+ bool isActiveAssistant =
+ (useActiveAssistantList && mUidPolicy->isActiveAssistantUid(currentUid))
+ || mUidPolicy->isAssistantUid(currentUid);
// TODO: b/339112720
// Refine this logic when we have the correct phone state owner UID. The current issue is
@@ -1069,7 +1072,7 @@
const bool allowSensitiveCapture =
!isSensitiveActive || isTopOrLatestSensitive || current->canCaptureOutput;
bool allowCapture = false;
- if (!isAssistantOnTop) {
+ if (!isAssistantOnTop || isActiveAssistant) {
allowCapture = (isTopOrLatestActive || isTopOrLatestSensitive) &&
allowSensitiveCapture && canCaptureIfInCallOrCommunication;
} else {
@@ -1817,6 +1820,7 @@
ul.unlock();
command->mStatus = AudioSystem::setStreamVolume(data->mStream,
data->mVolume,
+ data->mIsMuted,
data->mIO);
ul.lock();
}break;
@@ -1827,6 +1831,7 @@
ul.unlock();
command->mStatus = AudioSystem::setPortsVolume(data->mPorts,
data->mVolume,
+ data->mMuted,
data->mIO);
ul.lock();
} break;
@@ -2147,6 +2152,7 @@
status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
float volume,
+ bool muted,
audio_io_handle_t output,
int delayMs)
{
@@ -2155,6 +2161,7 @@
sp<VolumeData> data = new VolumeData();
data->mStream = stream;
data->mVolume = volume;
+ data->mIsMuted = muted;
data->mIO = output;
command->mParam = data;
command->mWaitStatus = true;
@@ -2164,14 +2171,15 @@
}
status_t AudioPolicyService::AudioCommandThread::volumePortsCommand(
- const std::vector<audio_port_handle_t> &ports, float volume, audio_io_handle_t output,
- int delayMs)
+ const std::vector<audio_port_handle_t> &ports, float volume, bool muted,
+ audio_io_handle_t output, int delayMs)
{
sp<AudioCommand> command = new AudioCommand();
command->mCommand = SET_PORTS_VOLUME;
sp<VolumePortsData> data = new VolumePortsData();
data->mPorts = ports;
data->mVolume = volume;
+ data->mMuted = muted;
data->mIO = output;
command->mParam = data;
command->mWaitStatus = true;
@@ -2675,17 +2683,18 @@
int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
float volume,
+ bool muted,
audio_io_handle_t output,
int delayMs)
{
- return (int)mAudioCommandThread->volumeCommand(stream, volume,
+ return (int)mAudioCommandThread->volumeCommand(stream, volume, muted,
output, delayMs);
}
int AudioPolicyService::setPortsVolume(const std::vector<audio_port_handle_t> &ports, float volume,
- audio_io_handle_t output, int delayMs)
+ bool muted, audio_io_handle_t output, int delayMs)
{
- return (int)mAudioCommandThread->volumePortsCommand(ports, volume, output, delayMs);
+ return (int)mAudioCommandThread->volumePortsCommand(ports, volume, muted, output, delayMs);
}
int AudioPolicyService::setVoiceVolume(float volume, int delayMs)
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index c47b5e9..2ce82c0 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -136,13 +136,13 @@
int32_t indexMax) override;
binder::Status setStreamVolumeIndex(AudioStreamType stream,
const AudioDeviceDescription& device,
- int32_t index) override;
+ int32_t index, bool muted) override;
binder::Status getStreamVolumeIndex(AudioStreamType stream,
const AudioDeviceDescription& device,
int32_t* _aidl_return) override;
binder::Status setVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
const AudioDeviceDescription& device,
- int32_t index) override;
+ int32_t index, bool muted) override;
binder::Status getVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
const AudioDeviceDescription& device,
int32_t* _aidl_return) override;
@@ -353,6 +353,7 @@
virtual status_t setStreamVolume(audio_stream_type_t stream,
float volume,
+ bool muted,
audio_io_handle_t output,
int delayMs = 0);
@@ -364,12 +365,13 @@
*
* @param ports to consider
* @param volume to set
+ * @param muted to set
* @param output to consider
* @param delayMs to use
* @return NO_ERROR if successful
*/
virtual status_t setPortsVolume(const std::vector<audio_port_handle_t> &ports, float volume,
- audio_io_handle_t output, int delayMs = 0);
+ bool muted, audio_io_handle_t output, int delayMs = 0);
virtual status_t setVoiceVolume(float volume, int delayMs = 0);
void doOnNewAudioModulesAvailable();
@@ -625,10 +627,10 @@
virtual bool threadLoop();
void exit();
- status_t volumeCommand(audio_stream_type_t stream, float volume,
+ status_t volumeCommand(audio_stream_type_t stream, float volume, bool muted,
audio_io_handle_t output, int delayMs = 0);
status_t volumePortsCommand(const std::vector<audio_port_handle_t> &ports,
- float volume, audio_io_handle_t output, int delayMs = 0);
+ float volume, bool muted, audio_io_handle_t output, int delayMs = 0);
status_t parametersCommand(audio_io_handle_t ioHandle,
const char *keyValuePairs, int delayMs = 0);
status_t voiceVolumeCommand(float volume, int delayMs = 0);
@@ -700,6 +702,7 @@
public:
audio_stream_type_t mStream;
float mVolume;
+ bool mIsMuted;
audio_io_handle_t mIO;
};
@@ -707,13 +710,15 @@
public:
std::vector<audio_port_handle_t> mPorts;
float mVolume;
+ bool mMuted;
audio_io_handle_t mIO;
std::string dumpPorts() {
- return std::string("volume ") + std::to_string(mVolume) + " on IO " +
- std::to_string(mIO) + " and ports " +
- std::accumulate(std::begin(mPorts), std::end(mPorts), std::string{},
- [] (const std::string& ls, int rs) {
- return ls + std::to_string(rs) + " "; });
+ return std::string("volume ") + std::to_string(mVolume) + std::string("muted ") +
+ std::to_string(mMuted) + " on IO " + std::to_string(mIO) + " and ports " +
+ std::accumulate(std::begin(mPorts), std::end(mPorts), std::string{},
+ [](const std::string &ls, int rs) {
+ return ls + std::to_string(rs) + " ";
+ });
}
};
@@ -854,9 +859,10 @@
// misc control functions
//
- // set a stream volume for a particular output. For the same user setting, a given stream type can have different volumes
- // for each output (destination device) it is attached to.
- virtual status_t setStreamVolume(audio_stream_type_t stream, float volume, audio_io_handle_t output, int delayMs = 0);
+ // set a stream volume for a particular output. For the same user setting, a given stream
+ // type can have different volumes for each output (destination device) it is attached to.
+ virtual status_t setStreamVolume(audio_stream_type_t stream, float volume, bool muted,
+ audio_io_handle_t output, int delayMs = 0);
/**
* Set a volume on port(s) for a particular output. For the same user setting, a volume
* group (and associated given port of the client's track) can have different volumes for
@@ -864,12 +870,13 @@
*
* @param ports to consider
* @param volume to set
+ * @param muted to set
* @param output to consider
* @param delayMs to use
* @return NO_ERROR if successful
*/
status_t setPortsVolume(const std::vector<audio_port_handle_t> &ports, float volume,
- audio_io_handle_t output, int delayMs = 0) override;
+ bool muted, audio_io_handle_t output, int delayMs = 0) override;
// function enabling to send proprietary informations directly from audio policy manager to audio hardware interface.
virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs = 0);
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 154b063..182dc61 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -29,7 +29,6 @@
"libbase",
"libbinder",
"libcutils",
- "libcutils",
"libhidlbase",
"liblog",
"libmedia_helper",
@@ -41,6 +40,7 @@
static_libs: [
"android.media.audiopolicy-aconfig-cc",
"audioclient-types-aidl-cpp",
+ "com.android.media.audio-aconfig-cc",
"com.android.media.audioserver-aconfig-cc",
"libaudiopolicycomponents",
"libflagtest",
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index 9ddfd6c..5290da2 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -56,11 +56,13 @@
status_t closeInput(audio_io_handle_t /*input*/) override { return NO_INIT; }
status_t setStreamVolume(audio_stream_type_t /*stream*/,
float /*volume*/,
+ bool /*muted*/,
audio_io_handle_t /*output*/,
int /*delayMs*/) override { return NO_INIT; }
- status_t setPortsVolume(const std::vector<audio_port_handle_t>& /*ports*/, float /*volume*/,
- audio_io_handle_t /*output*/, int /*delayMs*/) override { return NO_INIT; }
+ status_t setPortsVolume(const std::vector<audio_port_handle_t> & /*ports*/, float /*volume*/,
+ bool /*muted*/, audio_io_handle_t /*output*/,
+ int /*delayMs*/) override { return NO_INIT; }
void setParameters(audio_io_handle_t /*ioHandle*/,
const String8& /*keyValuePairs*/,
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 39f9b8a..e901cfd 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -310,11 +310,13 @@
bool isSpatialized;
bool isBitPerfectInternal;
float volume;
+ bool muted;
AttributionSourceState attributionSource = createAttributionSourceState(uid);
ASSERT_EQ(OK, mManager->getOutputForAttr(
&attr, output, session, &stream, attributionSource, &config, &flags,
selectedDeviceId, portId, {}, &outputType, &isSpatialized,
- isBitPerfect == nullptr ? &isBitPerfectInternal : isBitPerfect, &volume));
+ isBitPerfect == nullptr ? &isBitPerfectInternal : isBitPerfect, &volume,
+ &muted));
ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
ASSERT_NE(AUDIO_IO_HANDLE_NONE, *output);
}
@@ -1274,6 +1276,33 @@
EXPECT_EQ(expectedChannelMask, requestedChannelMask);
}
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, MatchesMoreInputFlagsWhenPossible) {
+ const audio_format_t expectedFormat = AUDIO_FORMAT_PCM_16_BIT;
+ const uint32_t expectedSampleRate = 48000;
+ const audio_channel_mask_t expectedChannelMask = AUDIO_CHANNEL_IN_STEREO;
+ const std::string expectedIOProfile = "mixport_fast_input";
+
+ auto devices = mManager->getAvailableInputDevices();
+ sp<DeviceDescriptor> mic = nullptr;
+ for (auto device : devices) {
+ if (device->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ mic = device;
+ break;
+ }
+ }
+ EXPECT_NE(nullptr, mic);
+
+ audio_format_t requestedFormat = AUDIO_FORMAT_PCM_24_BIT_PACKED;
+ uint32_t requestedSampleRate = 48000;
+ audio_channel_mask_t requestedChannelMask = AUDIO_CHANNEL_IN_STEREO;
+ auto profile = mManager->getInputProfile(
+ mic, requestedSampleRate, requestedFormat, requestedChannelMask, AUDIO_INPUT_FLAG_FAST);
+ EXPECT_EQ(expectedIOProfile, profile->getName());
+ EXPECT_EQ(expectedFormat, requestedFormat);
+ EXPECT_EQ(expectedSampleRate, requestedSampleRate);
+ EXPECT_EQ(expectedChannelMask, requestedChannelMask);
+}
+
class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
protected:
void TearDown() override;
@@ -2107,6 +2136,7 @@
bool mIsSpatialized;
bool mIsBitPerfect;
float mVolume;
+ bool mMuted;
};
TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, MmapPlaybackStreamMatchingLoopbackDapMixFails) {
@@ -2125,7 +2155,8 @@
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
&outputFlags, &mSelectedDeviceId, &mPortId, {},
- &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume,
+ &mMuted));
}
TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting,
@@ -2144,7 +2175,8 @@
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
&outputFlags, &mSelectedDeviceId, &mPortId, {},
- &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume,
+ &mMuted));
}
TEST_F(AudioPolicyManagerTestMMapPlaybackRerouting,
@@ -2175,7 +2207,8 @@
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
&outputFlags, &mSelectedDeviceId, &mPortId, {},
- &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume,
+ &mMuted));
ASSERT_EQ(usbDevicePort.id, mSelectedDeviceId);
auto outputDesc = mManager->getOutputs().valueFor(mOutput);
ASSERT_NE(nullptr, outputDesc);
@@ -2191,7 +2224,8 @@
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
&outputFlags, &mSelectedDeviceId, &mPortId, {},
- &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume,
+ &mMuted));
ASSERT_EQ(usbDevicePort.id, mSelectedDeviceId);
outputDesc = mManager->getOutputs().valueFor(mOutput);
ASSERT_NE(nullptr, outputDesc);
@@ -2220,7 +2254,8 @@
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
&outputFlags, &mSelectedDeviceId, &mPortId, {},
- &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume,
+ &mMuted));
}
INSTANTIATE_TEST_SUITE_P(
@@ -3978,11 +4013,12 @@
bool isSpatialized;
bool isBitPerfect;
float volume;
+ bool muted;
EXPECT_EQ(expected,
mManager->getOutputForAttr(&sMediaAttr, &mBitPerfectOutput, AUDIO_SESSION_NONE,
&stream, attributionSource, &config, &flags,
&mSelectedDeviceId, &mBitPerfectPortId, {}, &outputType,
- &isSpatialized, &isBitPerfect, &volume));
+ &isSpatialized, &isBitPerfect, &volume, &muted));
}
class AudioPolicyManagerTestBitPerfect : public AudioPolicyManagerTestBitPerfectBase {
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index 3c64898..9cb3608 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -71,6 +71,11 @@
samplingRates="48000"
channelMasks="AUDIO_CHANNEL_IN_5POINT1"/>
</mixPort>
+ <mixPort name="mixport_fast_input" role="sink" flags="AUDIO_INPUT_FLAG_FAST">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
</mixPorts>
<devicePorts>
<devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
@@ -121,6 +126,8 @@
sources="USB Device In" />
<route type="mix" sink="multiple_channels_input"
sources="Built-In Mic" />
+ <route type="mix" sink="mixport_fast_input"
+ sources="Built-In Mic"/>
</routes>
</module>
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index fa5eb6f..17ec41e 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -95,6 +95,7 @@
const char* kProcessInfoServiceName = "processinfo";
const char* kVirtualDeviceBackCameraId = "0";
const char* kVirtualDeviceFrontCameraId = "1";
+ const char* kUnknownPackageName = "<unknown>";
int32_t getDeviceId(const android::CameraMetadata& cameraInfo) {
if (!cameraInfo.exists(ANDROID_INFO_DEVICE_ID)) {
@@ -1605,14 +1606,18 @@
int callingPid = getCallingPid();
logConnectionAttempt(callingPid, kServiceName, cameraIdStr, API_1);
- if (!(ret = connectHelper<ICameraClient,Client>(
- sp<ICameraClient>{nullptr}, cameraIdStr, cameraId,
- kServiceName, /*systemNativeClient*/ false, {}, uid, callingPid,
- API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0,
- /*targetSdkVersion*/ __ANDROID_API_FUTURE__,
- /*rotationOverride*/hardware::ICameraService::ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT,
- /*forceSlowJpegMode*/false, cameraIdStr, /*isNonSystemNdk*/ false, /*out*/ tmp)
- ).isOk()) {
+ AttributionSourceState clientAttribution =
+ buildAttributionSource(callingPid, uid, kServiceName, kDefaultDeviceId);
+
+ if (!(ret = connectHelper<ICameraClient, Client>(
+ sp<ICameraClient>{nullptr}, cameraIdStr, cameraId, clientAttribution,
+ /*systemNativeClient*/ false, API_1, /*shimUpdateOnly*/ true,
+ /*oomScoreOffset*/ 0,
+ /*targetSdkVersion*/ __ANDROID_API_FUTURE__,
+ /*rotationOverride*/
+ hardware::ICameraService::ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT,
+ /*forceSlowJpegMode*/ false, cameraIdStr, /*isNonSystemNdk*/ false, /*out*/ tmp))
+ .isOk()) {
ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().c_str());
}
return ret;
@@ -1681,14 +1686,11 @@
}
Status CameraService::validateConnectLocked(const std::string& cameraId,
- const std::string& clientName8, int clientUid, int clientPid) const {
-
+ const AttributionSourceState& clientAttribution) const {
#ifdef __BRILLO__
- UNUSED(clientName8);
- UNUSED(clientUid);
- UNUSED(clientPid);
+ UNUSED(clientAttribution);
#else
- Status allowed = validateClientPermissionsLocked(cameraId, clientName8, clientUid, clientPid);
+ Status allowed = validateClientPermissionsLocked(cameraId, clientAttribution);
if (!allowed.isOk()) {
return allowed;
}
@@ -1725,11 +1727,15 @@
return Status::ok();
}
-Status CameraService::validateClientPermissionsLocked(const std::string& cameraId,
- const std::string& clientName, int clientUid, int clientPid) const {
+Status CameraService::validateClientPermissionsLocked(
+ const std::string& cameraId, const AttributionSourceState& clientAttribution) const {
int callingPid = getCallingPid();
int callingUid = getCallingUid();
+ int clientPid = clientAttribution.pid;
+ int clientUid = clientAttribution.uid;
+ const std::string clientName = clientAttribution.packageName.value_or(kUnknownPackageName);
+
if (shouldRejectSystemCameraConnection(cameraId)) {
ALOGW("Attempting to connect to system-only camera id %s, connection rejected",
cameraId.c_str());
@@ -1745,12 +1751,14 @@
// Get the device id that owns this camera.
auto [deviceId, _] = mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(cameraId);
+ AttributionSourceState clientAttributionWithDeviceId = clientAttribution;
+ clientAttributionWithDeviceId.deviceId = deviceId;
// If it's not calling from cameraserver, check the permission if the
// device isn't a system only camera (shouldRejectSystemCameraConnection already checks for
// android.permission.SYSTEM_CAMERA for system only camera devices).
bool checkPermissionForCamera =
- hasPermissionsForCamera(cameraId, clientPid, clientUid, clientName, deviceId);
+ hasPermissionsForCamera(cameraId, clientAttributionWithDeviceId);
if (callingPid != getpid() &&
(deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) && !checkPermissionForCamera) {
ALOGE("Permission Denial: can't use the camera pid=%d, uid=%d", clientPid, clientUid);
@@ -2122,7 +2130,7 @@
ret = resolveAttributionSource(resolvedClientAttribution, __FUNCTION__, cameraIdStr);
if (!ret.isOk()) {
logRejected(cameraIdStr, getCallingPid(),
- clientAttribution.packageName.value_or("<unknown>"),
+ clientAttribution.packageName.value_or(kUnknownPackageName),
toStdString(ret.toString8()));
return ret;
}
@@ -2134,15 +2142,15 @@
logConnectionAttempt(clientPid, clientPackageName, cameraIdStr, API_1);
sp<Client> client = nullptr;
- ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId,
- clientPackageName, /*systemNativeClient*/ false, {},
- clientUid, clientPid, API_1,
- /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion,
- rotationOverride, forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*out*/client);
+ ret = connectHelper<ICameraClient, Client>(
+ cameraClient, cameraIdStr, api1CameraId, resolvedClientAttribution,
+ /*systemNativeClient*/ false, API_1,
+ /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion, rotationOverride,
+ forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*out*/ client);
if (!ret.isOk()) {
logRejected(cameraIdStr, getCallingPid(),
- clientAttribution.packageName.value_or("<unknown>"),
+ clientAttribution.packageName.value_or(kUnknownPackageName),
toStdString(ret.toString8()));
return ret;
}
@@ -2298,9 +2306,8 @@
}
ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks, CameraDeviceClient>(
- cameraCb, cameraId, /*api1CameraId*/ -1, clientPackageName, systemNativeClient,
- resolvedClientAttribution.attributionTag, clientUid, clientPid, API_2,
- /*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, rotationOverride,
+ cameraCb, cameraId, /*api1CameraId*/ -1, resolvedClientAttribution, systemNativeClient,
+ API_2, /*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, rotationOverride,
/*forceSlowJpegMode*/ false, unresolvedCameraId, isNonSystemNdk, /*out*/ client);
if (!ret.isOk()) {
@@ -2373,13 +2380,15 @@
static_cast<int>(effectiveApiLevel));
}
-template<class CALLBACK, class CLIENT>
+template <class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::string& cameraId,
- int api1CameraId, const std::string& clientPackageName, bool systemNativeClient,
- const std::optional<std::string>& clientFeatureId, int clientUid, int clientPid,
- apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion,
- int rotationOverride, bool forceSlowJpegMode,
- const std::string& originalCameraId, bool isNonSystemNdk, /*out*/sp<CLIENT>& device) {
+ int api1CameraId,
+ const AttributionSourceState& clientAttribution,
+ bool systemNativeClient, apiLevel effectiveApiLevel,
+ bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion,
+ int rotationOverride, bool forceSlowJpegMode,
+ const std::string& originalCameraId, bool isNonSystemNdk,
+ /*out*/ sp<CLIENT>& device) {
binder::Status ret = binder::Status::ok();
nsecs_t openTimeNs = systemTime();
@@ -2388,22 +2397,25 @@
int facing = -1;
int orientation = 0;
+ const std::string clientPackageName =
+ clientAttribution.packageName.value_or(kUnknownPackageName);
+
{
// Acquire mServiceLock and prevent other clients from connecting
std::unique_ptr<AutoConditionLock> lock =
AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);
if (lock == nullptr) {
- ALOGE("CameraService::connect (PID %d) rejected (too many other clients connecting)."
- , clientPid);
- return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
+ ALOGE("CameraService::connect (PID %d) rejected (too many other clients connecting).",
+ clientAttribution.pid);
+ return STATUS_ERROR_FMT(
+ ERROR_MAX_CAMERAS_IN_USE,
"Cannot open camera %s for \"%s\" (PID %d): Too many other clients connecting",
- cameraId.c_str(), clientPackageName.c_str(), clientPid);
+ cameraId.c_str(), clientPackageName.c_str(), clientAttribution.pid);
}
// Enforce client permissions and do basic validity checks
- if (!(ret = validateConnectLocked(cameraId, clientPackageName,
- /*inout*/clientUid, /*inout*/clientPid)).isOk()) {
+ if (!(ret = validateConnectLocked(cameraId, clientAttribution)).isOk()) {
return ret;
}
@@ -2420,9 +2432,12 @@
sp<BasicClient> clientTmp = nullptr;
std::shared_ptr<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>> partial;
- if ((err = handleEvictionsLocked(cameraId, clientPid, effectiveApiLevel,
- IInterface::asBinder(cameraCb), clientPackageName, oomScoreOffset,
- systemNativeClient, /*out*/&clientTmp, /*out*/&partial)) != NO_ERROR) {
+ if ((err = handleEvictionsLocked(
+ cameraId, clientAttribution.pid, effectiveApiLevel,
+ IInterface::asBinder(cameraCb),
+ clientAttribution.packageName.value_or(kUnknownPackageName), oomScoreOffset,
+ systemNativeClient, /*out*/ &clientTmp,
+ /*out*/ &partial)) != NO_ERROR) {
switch (err) {
case -ENODEV:
return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
@@ -2468,12 +2483,13 @@
// Only use passed in clientPid to check permission. Use calling PID as the client PID
// that's connected to camera service directly.
- if(!(ret = makeClient(this, cameraCb, clientPackageName, systemNativeClient,
- clientFeatureId, cameraId, api1CameraId, facing,
- orientation, getCallingPid(), clientUid, getpid(),
- deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass,
- rotationOverride, forceSlowJpegMode, originalCameraId,
- /*out*/&tmp)).isOk()) {
+ if (!(ret = makeClient(this, cameraCb, clientPackageName, systemNativeClient,
+ clientAttribution.attributionTag, cameraId, api1CameraId, facing,
+ orientation, getCallingPid(), clientAttribution.uid, getpid(),
+ deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass,
+ rotationOverride, forceSlowJpegMode, originalCameraId,
+ /*out*/ &tmp))
+ .isOk()) {
return ret;
}
client = static_cast<CLIENT*>(tmp.get());
@@ -2574,8 +2590,9 @@
client->setRotateAndCropOverride(rotateAndCropMode);
} else {
client->setRotateAndCropOverride(
- mCameraServiceProxyWrapper->getRotateAndCropOverride(
- clientPackageName, facing, multiuser_get_user_id(clientUid)));
+ mCameraServiceProxyWrapper->getRotateAndCropOverride(
+ clientPackageName, facing,
+ multiuser_get_user_id(clientAttribution.uid)));
}
}
@@ -2600,8 +2617,9 @@
bool isCameraPrivacyEnabled;
if (flags::camera_privacy_allowlist()) {
// Set camera muting behavior.
- isCameraPrivacyEnabled = this->isCameraPrivacyEnabled(
- toString16(client->getPackageName()), cameraId, clientPid, clientUid);
+ isCameraPrivacyEnabled =
+ this->isCameraPrivacyEnabled(toString16(client->getPackageName()), cameraId,
+ clientAttribution.pid, clientAttribution.uid);
} else {
isCameraPrivacyEnabled =
mSensorPrivacyPolicy->isCameraPrivacyEnabled();
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d0c3361..fd051db 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -927,12 +927,10 @@
void removeStates(const std::string& id);
// Check if we can connect, before we acquire the service lock.
- // If clientPid/clientUid are USE_CALLING_PID/USE_CALLING_UID, they will be overwritten with
- // the calling pid/uid.
- binder::Status validateConnectLocked(const std::string& cameraId, const std::string& clientName,
- int clientUid, int clientPid) const;
- binder::Status validateClientPermissionsLocked(const std::string& cameraId,
- const std::string& clientName, int clientUid, int clientPid) const;
+ binder::Status validateConnectLocked(const std::string& cameraId,
+ const AttributionSourceState& clientAttribution) const;
+ binder::Status validateClientPermissionsLocked(
+ const std::string& cameraId, const AttributionSourceState& clientAttribution) const;
void logConnectionAttempt(int clientPid, const std::string& clientPackageName,
const std::string& cameraId, apiLevel effectiveApiLevel) const;
@@ -974,14 +972,14 @@
void filterAPI1SystemCameraLocked(const std::vector<std::string> &normalDeviceIds);
// Single implementation shared between the various connect calls
- template<class CALLBACK, class CLIENT>
+ template <class CALLBACK, class CLIENT>
binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const std::string& cameraId,
- int api1CameraId, const std::string& clientPackageName, bool systemNativeClient,
- const std::optional<std::string>& clientFeatureId, int clientUid, int clientPid,
- apiLevel effectiveApiLevel, bool shimUpdateOnly, int scoreOffset, int targetSdkVersion,
- int rotationOverride, bool forceSlowJpegMode,
- const std::string& originalCameraId, bool isNonSystemNdk,
- /*out*/sp<CLIENT>& device);
+ int api1CameraId, const AttributionSourceState& clientAttribution,
+ bool systemNativeClient, apiLevel effectiveApiLevel,
+ bool shimUpdateOnly, int scoreOffset, int targetSdkVersion,
+ int rotationOverride, bool forceSlowJpegMode,
+ const std::string& originalCameraId, bool isNonSystemNdk,
+ /*out*/ sp<CLIENT>& device);
// Lock guarding camera service state
Mutex mServiceLock;
diff --git a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
index 37903e1..b213218 100644
--- a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
+++ b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
@@ -32,7 +32,32 @@
#include <hwbinder/IPCThreadState.h>
namespace {
+
+using android::content::AttributionSourceState;
+
static const std::string kPermissionServiceName = "permission";
+
+static std::string getAttributionString(const AttributionSourceState& attributionSource) {
+ std::ostringstream ret;
+ const AttributionSourceState* current = &attributionSource;
+ while (current != nullptr) {
+ if (current != &attributionSource) {
+ ret << ", ";
+ }
+
+ ret << "[uid " << current->uid << ", pid " << current->pid;
+ ret << ", packageName \"" << current->packageName.value_or("<unknown>");
+ ret << "\"]";
+
+ if (!current->next.empty()) {
+ current = ¤t->next[0];
+ } else {
+ current = nullptr;
+ }
+ }
+ return ret.str();
+}
+
} // namespace
namespace android {
@@ -111,13 +136,22 @@
const std::string& cameraId, const std::string& permission,
const AttributionSourceState& attributionSource, const std::string& message,
int32_t attributedOpCode) {
- if (checkAutomotivePrivilegedClient(cameraId, attributionSource)) {
+ AttributionSourceState clientAttribution = attributionSource;
+ if (!flags::check_full_attribution_source_chain() && !clientAttribution.next.empty()) {
+ clientAttribution.next.clear();
+ }
+
+ if (checkAutomotivePrivilegedClient(cameraId, clientAttribution)) {
return true;
}
- return mPermissionChecker->checkPermissionForPreflight(
- toString16(permission), attributionSource, toString16(message),
- attributedOpCode) != PermissionChecker::PERMISSION_HARD_DENIED;
+ PermissionChecker::PermissionResult result = mPermissionChecker->checkPermissionForPreflight(
+ toString16(permission), clientAttribution, toString16(message), attributedOpCode);
+ if (result == PermissionChecker::PERMISSION_HARD_DENIED) {
+ ALOGE("%s: Permission denied for client attribution %s", __FUNCTION__,
+ getAttributionString(clientAttribution).c_str());
+ }
+ return result != PermissionChecker::PERMISSION_HARD_DENIED;
}
// Can camera service trust the caller based on the calling UID?
diff --git a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
index 22abccc..9ed7fa2 100644
--- a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
+++ b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
@@ -222,8 +222,9 @@
bool hasPermissionsForCamera(int callingPid, int callingUid, const std::string& packageName,
int32_t deviceId) const {
- return hasPermissionsForCamera(std::string(), callingPid, callingUid, packageName,
- deviceId);
+ auto attributionSource =
+ buildAttributionSource(callingPid, callingUid, packageName, deviceId);
+ return hasPermissionsForCamera(std::string(), attributionSource);
}
bool hasPermissionsForCamera(const std::string& cameraId, int callingPid, int callingUid,
@@ -232,11 +233,9 @@
return mAttributionAndPermissionUtils->hasPermissionsForCamera(cameraId, attributionSource);
}
- bool hasPermissionsForCamera(const std::string& cameraId, int callingPid, int callingUid,
- const std::string& packageName, int32_t deviceId) const {
- auto attributionSource =
- buildAttributionSource(callingPid, callingUid, packageName, deviceId);
- return mAttributionAndPermissionUtils->hasPermissionsForCamera(cameraId, attributionSource);
+ bool hasPermissionsForCamera(const std::string& cameraId,
+ const AttributionSourceState& clientAttribution) const {
+ return mAttributionAndPermissionUtils->hasPermissionsForCamera(cameraId, clientAttribution);
}
bool hasPermissionsForSystemCamera(const std::string& cameraId, int callingPid, int callingUid,
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.h b/services/camera/virtualcamera/VirtualCameraRenderThread.h
index a35eea1..1fb4e84 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.h
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.h
@@ -221,8 +221,8 @@
std::mutex mLock;
std::deque<std::unique_ptr<ProcessCaptureRequestTask>> mQueue GUARDED_BY(mLock);
std::condition_variable mCondVar;
- volatile bool mTextureUpdateRequested GUARDED_BY(mLock);
- volatile bool mPendingExit GUARDED_BY(mLock);
+ volatile bool GUARDED_BY(mLock) mTextureUpdateRequested = false;
+ volatile bool GUARDED_BY(mLock) mPendingExit = false;
// Acquisition timestamp of last frame.
std::atomic<uint64_t> mLastAcquisitionTimestampNanoseconds;
diff --git a/services/tuner/TunerHelper.cpp b/services/tuner/TunerHelper.cpp
index a03386f..8357a9e 100644
--- a/services/tuner/TunerHelper.cpp
+++ b/services/tuner/TunerHelper.cpp
@@ -73,7 +73,7 @@
// TODO: update Demux, Descrambler.
void TunerHelper::updateTunerResources(const vector<TunerFrontendInfo>& feInfos,
- const vector<int32_t>& lnbHandles) {
+ const vector<int64_t>& lnbHandles) {
::ndk::SpAIBinder binder(AServiceManager_waitForService("tv_tuner_resource_mgr"));
shared_ptr<ITunerResourceManager> tunerRM = ITunerResourceManager::fromBinder(binder);
if (tunerRM == nullptr) {
@@ -85,7 +85,7 @@
}
void TunerHelper::updateTunerResources(const vector<TunerFrontendInfo>& feInfos,
const vector<TunerDemuxInfo>& demuxInfos,
- const vector<int32_t>& lnbHandles) {
+ const vector<int64_t>& lnbHandles) {
::ndk::SpAIBinder binder(AServiceManager_waitForService("tv_tuner_resource_mgr"));
shared_ptr<ITunerResourceManager> tunerRM = ITunerResourceManager::fromBinder(binder);
if (tunerRM == nullptr) {
@@ -101,13 +101,22 @@
}
// TODO: create a map between resource id and handles.
-int TunerHelper::getResourceIdFromHandle(int resourceHandle, int /*type*/) {
- return (resourceHandle & 0x00ff0000) >> 16;
+int TunerHelper::getResourceIdFromHandle(long resourceHandle, int /*type*/) {
+ return (int)((resourceHandle >> RESOURCE_ID_SHIFT) & RESOURCE_ID_MASK);
}
-int TunerHelper::getResourceHandleFromId(int id, int resourceType) {
+/**
+ * Generate resource handle for resourceType and id
+ * Resource Handle Allotment : 64 bits (long)
+ * 8 bits - resourceType
+ * 32 bits - id
+ * 24 bits - resourceRequestCount
+ */
+long TunerHelper::getResourceHandleFromId(int id, int resourceType) {
// TODO: build up randomly generated id to handle mapping
- return (resourceType & 0x000000ff) << 24 | (id << 16) | (sResourceRequestCount++ & 0xffff);
+ return static_cast<int64_t>(resourceType & RESOURCE_TYPE_MASK) << RESOURCE_TYPE_SHIFT |
+ static_cast<int64_t>(id & RESOURCE_ID_MASK) << RESOURCE_ID_SHIFT |
+ (sResourceRequestCount++ & RESOURCE_COUNT_MASK);
}
} // namespace tuner
diff --git a/services/tuner/TunerHelper.h b/services/tuner/TunerHelper.h
index 65a9b0b..74e1662 100644
--- a/services/tuner/TunerHelper.h
+++ b/services/tuner/TunerHelper.h
@@ -56,17 +56,23 @@
// TODO: update Demux, Descrambler.
static void updateTunerResources(const vector<TunerFrontendInfo>& feInfos,
- const vector<int32_t>& lnbHandles);
+ const vector<int64_t>& lnbHandles);
static void updateTunerResources(const vector<TunerFrontendInfo>& feInfos,
const vector<TunerDemuxInfo>& demuxInfos,
- const vector<int32_t>& lnbHandles);
+ const vector<int64_t>& lnbHandles);
// TODO: create a map between resource id and handles.
- static int getResourceIdFromHandle(int resourceHandle, int type);
- static int getResourceHandleFromId(int id, int resourceType);
+ static int getResourceIdFromHandle(long resourceHandle, int type);
+ static long getResourceHandleFromId(int id, int resourceType);
private:
static int32_t sResourceRequestCount;
+
+ static constexpr uint32_t RESOURCE_ID_SHIFT = 24;
+ static constexpr uint32_t RESOURCE_TYPE_SHIFT = 56;
+ static constexpr uint32_t RESOURCE_COUNT_MASK = 0xffffff;
+ static constexpr uint32_t RESOURCE_ID_MASK = 0xffffffff;
+ static constexpr uint32_t RESOURCE_TYPE_MASK = 0xff;
};
} // namespace tuner
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index 9a1e8bb..8cf84e2 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -82,7 +82,7 @@
return AServiceManager_addService(tunerService->asBinder().get(), getServiceName());
}
-::ndk::ScopedAStatus TunerService::openDemux(int32_t in_demuxHandle,
+::ndk::ScopedAStatus TunerService::openDemux(int64_t in_demuxHandle,
shared_ptr<ITunerDemux>* _aidl_return) {
ALOGV("openDemux");
shared_ptr<IDemux> demux;
@@ -116,7 +116,7 @@
}
}
-::ndk::ScopedAStatus TunerService::getDemuxInfo(int32_t in_demuxHandle, DemuxInfo* _aidl_return) {
+::ndk::ScopedAStatus TunerService::getDemuxInfo(int64_t in_demuxHandle, DemuxInfo* _aidl_return) {
if (mTunerVersion <= TUNER_HAL_VERSION_2_0) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
@@ -169,7 +169,7 @@
return mTuner->getFrontendInfo(id, _aidl_return);
}
-::ndk::ScopedAStatus TunerService::openFrontend(int32_t frontendHandle,
+::ndk::ScopedAStatus TunerService::openFrontend(int64_t frontendHandle,
shared_ptr<ITunerFrontend>* _aidl_return) {
int id = TunerHelper::getResourceIdFromHandle(frontendHandle, FRONTEND);
shared_ptr<IFrontend> frontend;
@@ -181,7 +181,7 @@
return status;
}
-::ndk::ScopedAStatus TunerService::openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) {
+::ndk::ScopedAStatus TunerService::openLnb(int64_t lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) {
shared_ptr<ILnb> lnb;
int id = TunerHelper::getResourceIdFromHandle(lnbHandle, LNB);
auto status = mTuner->openLnbById(id, &lnb);
@@ -204,7 +204,7 @@
return ::ndk::ScopedAStatus::ok();
}
-::ndk::ScopedAStatus TunerService::openDescrambler(int32_t /*descramblerHandle*/,
+::ndk::ScopedAStatus TunerService::openDescrambler(int64_t /*descramblerHandle*/,
shared_ptr<ITunerDescrambler>* _aidl_return) {
shared_ptr<IDescrambler> descrambler;
// int id = TunerHelper::getResourceIdFromHandle(descramblerHandle, DESCRAMBLER);
@@ -310,7 +310,7 @@
continue;
}
TunerFrontendInfo tunerFrontendInfo{
- .handle = TunerHelper::getResourceHandleFromId((int)ids[i], FRONTEND),
+ .handle = TunerHelper::getResourceHandleFromId(ids[i], FRONTEND),
.type = static_cast<int>(frontendInfo.type),
.exclusiveGroupId = frontendInfo.exclusiveGroupId,
};
@@ -336,18 +336,16 @@
for (int i = 0; i < ids.size(); i++) {
DemuxInfo demuxInfo;
mTuner->getDemuxInfo(ids[i], &demuxInfo);
- TunerDemuxInfo tunerDemuxInfo{
- .handle = TunerHelper::getResourceHandleFromId((int)ids[i], DEMUX),
- .filterTypes = static_cast<int>(demuxInfo.filterTypes)
- };
+ TunerDemuxInfo tunerDemuxInfo{.handle = TunerHelper::getResourceHandleFromId(ids[i], DEMUX),
+ .filterTypes = static_cast<int>(demuxInfo.filterTypes)};
infos.push_back(tunerDemuxInfo);
}
return infos;
}
-vector<int32_t> TunerService::getTRMLnbHandles() {
- vector<int32_t> lnbHandles;
+vector<int64_t> TunerService::getTRMLnbHandles() {
+ vector<int64_t> lnbHandles;
if (mTuner != nullptr) {
vector<int32_t> lnbIds;
auto res = mTuner->getLnbIds(&lnbIds);
diff --git a/services/tuner/TunerService.h b/services/tuner/TunerService.h
index 190ccd4..07b414e 100644
--- a/services/tuner/TunerService.h
+++ b/services/tuner/TunerService.h
@@ -61,20 +61,20 @@
virtual ~TunerService();
::ndk::ScopedAStatus getFrontendIds(vector<int32_t>* out_ids) override;
- ::ndk::ScopedAStatus getFrontendInfo(int32_t in_frontendHandle,
+ ::ndk::ScopedAStatus getFrontendInfo(int32_t in_frontendId,
FrontendInfo* _aidl_return) override;
- ::ndk::ScopedAStatus openFrontend(int32_t in_frontendHandle,
+ ::ndk::ScopedAStatus openFrontend(int64_t in_frontendHandle,
shared_ptr<ITunerFrontend>* _aidl_return) override;
- ::ndk::ScopedAStatus openLnb(int32_t in_lnbHandle,
+ ::ndk::ScopedAStatus openLnb(int64_t in_lnbHandle,
shared_ptr<ITunerLnb>* _aidl_return) override;
::ndk::ScopedAStatus openLnbByName(const string& in_lnbName,
shared_ptr<ITunerLnb>* _aidl_return) override;
- ::ndk::ScopedAStatus openDemux(int32_t in_demuxHandle,
+ ::ndk::ScopedAStatus openDemux(int64_t in_demuxHandle,
shared_ptr<ITunerDemux>* _aidl_return) override;
::ndk::ScopedAStatus getDemuxCaps(DemuxCapabilities* _aidl_return) override;
- ::ndk::ScopedAStatus getDemuxInfo(int32_t in_demuxHandle, DemuxInfo* _aidl_return) override;
+ ::ndk::ScopedAStatus getDemuxInfo(int64_t in_demuxHandle, DemuxInfo* _aidl_return) override;
::ndk::ScopedAStatus getDemuxInfoList(vector<DemuxInfo>* _aidl_return) override;
- ::ndk::ScopedAStatus openDescrambler(int32_t in_descramblerHandle,
+ ::ndk::ScopedAStatus openDescrambler(int64_t in_descramblerHandle,
shared_ptr<ITunerDescrambler>* _aidl_return) override;
::ndk::ScopedAStatus getTunerHalVersion(int32_t* _aidl_return) override;
::ndk::ScopedAStatus openSharedFilter(const string& in_filterToken,
@@ -94,7 +94,7 @@
void updateTunerResources();
vector<TunerFrontendInfo> getTRMFrontendInfos();
vector<TunerDemuxInfo> getTRMDemuxInfos();
- vector<int32_t> getTRMLnbHandles();
+ vector<int64_t> getTRMLnbHandles();
shared_ptr<ITuner> mTuner;
int mTunerVersion = TUNER_HAL_VERSION_UNKNOWN;
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
index 932133e..0d23817 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
@@ -54,7 +54,7 @@
* @param frontendHandle the handle of the frontend granted by TRM.
* @return the aidl interface of the frontend.
*/
- ITunerFrontend openFrontend(in int frontendHandle);
+ ITunerFrontend openFrontend(in long frontendHandle);
/**
* Open a new interface of ITunerLnb given a lnbHandle.
@@ -62,7 +62,7 @@
* @param lnbHandle the handle of the LNB granted by TRM.
* @return a newly created ITunerLnb interface.
*/
- ITunerLnb openLnb(in int lnbHandle);
+ ITunerLnb openLnb(in long lnbHandle);
/**
* Open a new interface of ITunerLnb given a LNB name.
@@ -75,7 +75,7 @@
/**
* Create a new instance of Demux.
*/
- ITunerDemux openDemux(in int demuxHandle);
+ ITunerDemux openDemux(in long demuxHandle);
/**
* Retrieve the supported filter main types
@@ -83,7 +83,7 @@
* @param demuxHandle the handle of the demux to query demux info for
* @return the demux info
*/
- DemuxInfo getDemuxInfo(in int demuxHandle);
+ DemuxInfo getDemuxInfo(in long demuxHandle);
/**
* Retrieve the list of demux info for all the demuxes on the system
@@ -104,7 +104,7 @@
* @param descramblerHandle the handle of the descrambler granted by TRM.
* @return a newly created ITunerDescrambler interface.
*/
- ITunerDescrambler openDescrambler(in int descramblerHandle);
+ ITunerDescrambler openDescrambler(in long descramblerHandle);
/**
* Get an integer that carries the Tuner HIDL version. The high 16 bits are the
diff --git a/services/tuner/hidl/TunerHidlService.cpp b/services/tuner/hidl/TunerHidlService.cpp
index 6bc36be..1b6b032 100644
--- a/services/tuner/hidl/TunerHidlService.cpp
+++ b/services/tuner/hidl/TunerHidlService.cpp
@@ -101,7 +101,7 @@
return AServiceManager_addService(tunerService->asBinder().get(), getServiceName());
}
-::ndk::ScopedAStatus TunerHidlService::openDemux(int32_t /* in_demuxHandle */,
+::ndk::ScopedAStatus TunerHidlService::openDemux(int64_t /* in_demuxHandle */,
shared_ptr<ITunerDemux>* _aidl_return) {
ALOGV("openDemux");
HidlResult res;
@@ -123,7 +123,7 @@
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
}
-::ndk::ScopedAStatus TunerHidlService::getDemuxInfo(int32_t /* in_demuxHandle */,
+::ndk::ScopedAStatus TunerHidlService::getDemuxInfo(int64_t /* in_demuxHandle */,
DemuxInfo* /* _aidl_return */) {
ALOGE("getDemuxInfo is not supported");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
@@ -195,7 +195,7 @@
return ::ndk::ScopedAStatus::ok();
}
-::ndk::ScopedAStatus TunerHidlService::openFrontend(int32_t frontendHandle,
+::ndk::ScopedAStatus TunerHidlService::openFrontend(int64_t frontendHandle,
shared_ptr<ITunerFrontend>* _aidl_return) {
HidlResult status;
sp<HidlIFrontend> frontend;
@@ -221,7 +221,8 @@
return ::ndk::ScopedAStatus::ok();
}
-::ndk::ScopedAStatus TunerHidlService::openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) {
+::ndk::ScopedAStatus TunerHidlService::openLnb(int64_t lnbHandle,
+ shared_ptr<ITunerLnb>* _aidl_return) {
HidlResult status;
sp<HidlILnb> lnb;
int id = TunerHelper::getResourceIdFromHandle(lnbHandle, LNB);
@@ -256,7 +257,7 @@
}
::ndk::ScopedAStatus TunerHidlService::openDescrambler(
- int32_t /*descramblerHandle*/, shared_ptr<ITunerDescrambler>* _aidl_return) {
+ int64_t /*descramblerHandle*/, shared_ptr<ITunerDescrambler>* _aidl_return) {
HidlResult status;
sp<HidlIDescrambler> descrambler;
//int id = TunerHelper::getResourceIdFromHandle(descramblerHandle, DESCRAMBLER);
@@ -410,8 +411,8 @@
return infos;
}
-vector<int32_t> TunerHidlService::getTRMLnbHandles() {
- vector<int32_t> lnbHandles;
+vector<int64_t> TunerHidlService::getTRMLnbHandles() {
+ vector<int64_t> lnbHandles;
if (mTuner != nullptr) {
HidlResult res;
vector<HidlLnbId> lnbIds;
diff --git a/services/tuner/hidl/TunerHidlService.h b/services/tuner/hidl/TunerHidlService.h
index 526c5e6..1973a77 100644
--- a/services/tuner/hidl/TunerHidlService.h
+++ b/services/tuner/hidl/TunerHidlService.h
@@ -73,20 +73,19 @@
virtual ~TunerHidlService();
::ndk::ScopedAStatus getFrontendIds(vector<int32_t>* out_ids) override;
- ::ndk::ScopedAStatus getFrontendInfo(int32_t in_frontendHandle,
- FrontendInfo* _aidl_return) override;
- ::ndk::ScopedAStatus openFrontend(int32_t in_frontendHandle,
+ ::ndk::ScopedAStatus getFrontendInfo(int32_t in_id, FrontendInfo* _aidl_return) override;
+ ::ndk::ScopedAStatus openFrontend(int64_t in_frontendHandle,
shared_ptr<ITunerFrontend>* _aidl_return) override;
- ::ndk::ScopedAStatus openLnb(int32_t in_lnbHandle,
+ ::ndk::ScopedAStatus openLnb(int64_t in_lnbHandle,
shared_ptr<ITunerLnb>* _aidl_return) override;
::ndk::ScopedAStatus openLnbByName(const std::string& in_lnbName,
shared_ptr<ITunerLnb>* _aidl_return) override;
- ::ndk::ScopedAStatus openDemux(int32_t in_demuxHandle,
+ ::ndk::ScopedAStatus openDemux(int64_t in_demuxHandle,
shared_ptr<ITunerDemux>* _aidl_return) override;
::ndk::ScopedAStatus getDemuxCaps(DemuxCapabilities* _aidl_return) override;
- ::ndk::ScopedAStatus getDemuxInfo(int32_t in_demuxHandle, DemuxInfo* _aidl_return) override;
+ ::ndk::ScopedAStatus getDemuxInfo(int64_t in_demuxHandle, DemuxInfo* _aidl_return) override;
::ndk::ScopedAStatus getDemuxInfoList(vector<DemuxInfo>* _aidl_return) override;
- ::ndk::ScopedAStatus openDescrambler(int32_t in_descramblerHandle,
+ ::ndk::ScopedAStatus openDescrambler(int64_t in_descramblerHandle,
shared_ptr<ITunerDescrambler>* _aidl_return) override;
::ndk::ScopedAStatus getTunerHalVersion(int32_t* _aidl_return) override;
::ndk::ScopedAStatus openSharedFilter(const string& in_filterToken,
@@ -106,7 +105,7 @@
private:
void updateTunerResources();
vector<TunerFrontendInfo> getTRMFrontendInfos();
- vector<int32_t> getTRMLnbHandles();
+ vector<int64_t> getTRMLnbHandles();
HidlResult getHidlFrontendIds(hidl_vec<HidlFrontendId>& ids);
HidlResult getHidlFrontendInfo(const int id, HidlFrontendInfo& info);
DemuxCapabilities getAidlDemuxCaps(const HidlDemuxCapabilities& caps);